summaryrefslogtreecommitdiffstats
path: root/project.py
diff options
context:
space:
mode:
authorMike Frysinger <vapier@google.com>2020-02-11 23:06:29 -0500
committerMike Frysinger <vapier@google.com>2020-02-12 04:48:36 +0000
commited4f2113d22e7cc8ccc13c15ad6d5b18926d95d7 (patch)
tree6800ef22b91cf7507c79f4bc082989a33e115415 /project.py
parent719675bcec58c60c8c9e29071c3942c343af6235 (diff)
downloadgit-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.py26
1 files changed, 24 insertions, 2 deletions
diff --git a/project.py b/project.py
index 3643762e..382650fb 100644
--- a/project.py
+++ b/project.py
@@ -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)