diff options
author | Mike Frysinger <vapier@google.com> | 2020-02-11 23:06:29 -0500 |
---|---|---|
committer | Mike Frysinger <vapier@google.com> | 2020-02-12 04:48:36 +0000 |
commit | ed4f2113d22e7cc8ccc13c15ad6d5b18926d95d7 (patch) | |
tree | 6800ef22b91cf7507c79f4bc082989a33e115415 /project.py | |
parent | 719675bcec58c60c8c9e29071c3942c343af6235 (diff) | |
download | git-repo-ed4f2113d22e7cc8ccc13c15ad6d5b18926d95d7.tar.gz |
project: make syncing a little more self-healing
We have a few files that we optionally symlink from the work tree
.git/ to the .repo/projects/ path. If they don't exist when we
first initialize, then we skip creating symlinks. If the files
are created later on under the work tree .git/, repo gets upset.
This can happen with the packed-refs file: if we don't have any
packed refs initially, we don't symlink it. But if git tries to
pack refs later on and creates the file, the project gets wedged.
We could create an empty file initially and then symlink it, but
for some files, it's not clear we want to always do that (e.g.
the .git/shallow setting). Instead, lets make handling of these
paths more dynamic. If they show up later on in the work tree
.git/ only, we'll take care of relocating & symlinking. This
also makes repo a little more robust and autorecovers incase a
path goes missing in one of the dirs.
Ideally we wouldn't monkey around at all here, but considering
the only option we give to users currently is to blow things
away with --force-sync, this seems a bit better.
Bug: https://crbug.com/gerrit/12324
Change-Id: Ia6960f1896ac6d890c762d7d053684a1c6ab2c87
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/254632
Reviewed-by: David Pursehouse <dpursehouse@collab.net>
Tested-by: Mike Frysinger <vapier@google.com>
Diffstat (limited to 'project.py')
-rw-r--r-- | project.py | 26 |
1 files changed, 24 insertions, 2 deletions
@@ -2760,9 +2760,31 @@ class Project(object): | |||
2760 | symlink_dirs += self.working_tree_dirs | 2760 | symlink_dirs += self.working_tree_dirs |
2761 | to_symlink = symlink_files + symlink_dirs | 2761 | to_symlink = symlink_files + symlink_dirs |
2762 | for name in set(to_symlink): | 2762 | for name in set(to_symlink): |
2763 | dst = platform_utils.realpath(os.path.join(destdir, name)) | 2763 | # Try to self-heal a bit in simple cases. |
2764 | dst_path = os.path.join(destdir, name) | ||
2765 | src_path = os.path.join(srcdir, name) | ||
2766 | |||
2767 | if name in self.working_tree_dirs: | ||
2768 | # If the dir is missing under .repo/projects/, create it. | ||
2769 | if not os.path.exists(src_path): | ||
2770 | os.makedirs(src_path) | ||
2771 | |||
2772 | elif name in self.working_tree_files: | ||
2773 | # If it's a file under the checkout .git/ and the .repo/projects/ has | ||
2774 | # nothing, move the file under the .repo/projects/ tree. | ||
2775 | if not os.path.exists(src_path) and os.path.isfile(dst_path): | ||
2776 | platform_utils.rename(dst_path, src_path) | ||
2777 | |||
2778 | # If the path exists under the .repo/projects/ and there's no symlink | ||
2779 | # under the checkout .git/, recreate the symlink. | ||
2780 | if name in self.working_tree_dirs or name in self.working_tree_files: | ||
2781 | if os.path.exists(src_path) and not os.path.exists(dst_path): | ||
2782 | platform_utils.symlink( | ||
2783 | os.path.relpath(src_path, os.path.dirname(dst_path)), dst_path) | ||
2784 | |||
2785 | dst = platform_utils.realpath(dst_path) | ||
2764 | if os.path.lexists(dst): | 2786 | if os.path.lexists(dst): |
2765 | src = platform_utils.realpath(os.path.join(srcdir, name)) | 2787 | src = platform_utils.realpath(src_path) |
2766 | # Fail if the links are pointing to the wrong place | 2788 | # Fail if the links are pointing to the wrong place |
2767 | if src != dst: | 2789 | if src != dst: |
2768 | _error('%s is different in %s vs %s', name, destdir, srcdir) | 2790 | _error('%s is different in %s vs %s', name, destdir, srcdir) |