diff options
author | Mike Frysinger <vapier@google.com> | 2020-02-19 19:19:18 -0500 |
---|---|---|
committer | Mike Frysinger <vapier@google.com> | 2020-02-20 00:51:42 +0000 |
commit | c0d1866b35d3e8d0bee3760a9f52574fa2ab8491 (patch) | |
tree | c6be761e1dbf5e93dfe499e8f53d90386a2d6769 /subcmds/sync.py | |
parent | f81c72ed7727ca408d1859a86c56b532a8de8d59 (diff) | |
download | git-repo-c0d1866b35d3e8d0bee3760a9f52574fa2ab8491.tar.gz |
project/sync: move DeleteProject helper to Project
Since deleting a source checkout involves a good bit of internal
knowledge of .repo/, move the DeleteProject helper out of the sync
code and into the Project class itself. This allows us to add git
worktree support to it so we can unlock/unlink project checkouts.
Change-Id: If9af8bd4a9c7e29743827d8166bc3db81547ca50
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/256072
Reviewed-by: Jonathan Nieder <jrn@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Diffstat (limited to 'subcmds/sync.py')
-rw-r--r-- | subcmds/sync.py | 85 |
1 files changed, 4 insertions, 81 deletions
diff --git a/subcmds/sync.py b/subcmds/sync.py index eada76a7..f2af0ec3 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
@@ -16,7 +16,6 @@ | |||
16 | 16 | ||
17 | from __future__ import print_function | 17 | from __future__ import print_function |
18 | 18 | ||
19 | import errno | ||
20 | import json | 19 | import json |
21 | import netrc | 20 | import netrc |
22 | from optparse import SUPPRESS_HELP | 21 | from optparse import SUPPRESS_HELP |
@@ -633,74 +632,6 @@ later is required to fix a server side protocol bug. | |||
633 | else: | 632 | else: |
634 | self.manifest._Unload() | 633 | self.manifest._Unload() |
635 | 634 | ||
636 | def _DeleteProject(self, path): | ||
637 | print('Deleting obsolete path %s' % path, file=sys.stderr) | ||
638 | |||
639 | # Delete the .git directory first, so we're less likely to have a partially | ||
640 | # working git repository around. There shouldn't be any git projects here, | ||
641 | # so rmtree works. | ||
642 | dotgit = os.path.join(path, '.git') | ||
643 | # Try to remove plain files first in case of git worktrees. If this fails | ||
644 | # for any reason, we'll fall back to rmtree, and that'll display errors if | ||
645 | # it can't remove things either. | ||
646 | try: | ||
647 | platform_utils.remove(dotgit) | ||
648 | except OSError: | ||
649 | pass | ||
650 | try: | ||
651 | platform_utils.rmtree(dotgit) | ||
652 | except OSError as e: | ||
653 | if e.errno != errno.ENOENT: | ||
654 | print('error: %s: %s' % (dotgit, str(e)), file=sys.stderr) | ||
655 | print('error: %s: Failed to delete obsolete path; remove manually, then ' | ||
656 | 'run sync again' % (path,), file=sys.stderr) | ||
657 | return 1 | ||
658 | |||
659 | # Delete everything under the worktree, except for directories that contain | ||
660 | # another git project | ||
661 | dirs_to_remove = [] | ||
662 | failed = False | ||
663 | for root, dirs, files in platform_utils.walk(path): | ||
664 | for f in files: | ||
665 | try: | ||
666 | platform_utils.remove(os.path.join(root, f)) | ||
667 | except OSError as e: | ||
668 | print('Failed to remove %s (%s)' % (os.path.join(root, f), str(e)), file=sys.stderr) | ||
669 | failed = True | ||
670 | dirs[:] = [d for d in dirs | ||
671 | if not os.path.lexists(os.path.join(root, d, '.git'))] | ||
672 | dirs_to_remove += [os.path.join(root, d) for d in dirs | ||
673 | if os.path.join(root, d) not in dirs_to_remove] | ||
674 | for d in reversed(dirs_to_remove): | ||
675 | if platform_utils.islink(d): | ||
676 | try: | ||
677 | platform_utils.remove(d) | ||
678 | except OSError as e: | ||
679 | print('Failed to remove %s (%s)' % (os.path.join(root, d), str(e)), file=sys.stderr) | ||
680 | failed = True | ||
681 | elif len(platform_utils.listdir(d)) == 0: | ||
682 | try: | ||
683 | platform_utils.rmdir(d) | ||
684 | except OSError as e: | ||
685 | print('Failed to remove %s (%s)' % (os.path.join(root, d), str(e)), file=sys.stderr) | ||
686 | failed = True | ||
687 | continue | ||
688 | if failed: | ||
689 | print('error: Failed to delete obsolete path %s' % path, file=sys.stderr) | ||
690 | print(' remove manually, then run sync again', file=sys.stderr) | ||
691 | return 1 | ||
692 | |||
693 | # Try deleting parent dirs if they are empty | ||
694 | project_dir = path | ||
695 | while project_dir != self.manifest.topdir: | ||
696 | if len(platform_utils.listdir(project_dir)) == 0: | ||
697 | platform_utils.rmdir(project_dir) | ||
698 | else: | ||
699 | break | ||
700 | project_dir = os.path.dirname(project_dir) | ||
701 | |||
702 | return 0 | ||
703 | |||
704 | def UpdateProjectList(self, opt): | 635 | def UpdateProjectList(self, opt): |
705 | new_project_paths = [] | 636 | new_project_paths = [] |
706 | for project in self.GetProjects(None, missing_ok=True): | 637 | for project in self.GetProjects(None, missing_ok=True): |
@@ -727,23 +658,15 @@ later is required to fix a server side protocol bug. | |||
727 | remote=RemoteSpec('origin'), | 658 | remote=RemoteSpec('origin'), |
728 | gitdir=gitdir, | 659 | gitdir=gitdir, |
729 | objdir=gitdir, | 660 | objdir=gitdir, |
661 | use_git_worktrees=os.path.isfile(gitdir), | ||
730 | worktree=os.path.join(self.manifest.topdir, path), | 662 | worktree=os.path.join(self.manifest.topdir, path), |
731 | relpath=path, | 663 | relpath=path, |
732 | revisionExpr='HEAD', | 664 | revisionExpr='HEAD', |
733 | revisionId=None, | 665 | revisionId=None, |
734 | groups=None) | 666 | groups=None) |
735 | 667 | if not project.DeleteWorktree( | |
736 | if project.IsDirty() and opt.force_remove_dirty: | 668 | quiet=opt.quiet, |
737 | print('WARNING: Removing dirty project "%s": uncommitted changes ' | 669 | force=opt.force_remove_dirty): |
738 | 'erased' % project.relpath, file=sys.stderr) | ||
739 | self._DeleteProject(project.worktree) | ||
740 | elif project.IsDirty(): | ||
741 | print('error: Cannot remove project "%s": uncommitted changes ' | ||
742 | 'are present' % project.relpath, file=sys.stderr) | ||
743 | print(' commit changes, then run sync again', | ||
744 | file=sys.stderr) | ||
745 | return 1 | ||
746 | elif self._DeleteProject(project.worktree): | ||
747 | return 1 | 670 | return 1 |
748 | 671 | ||
749 | new_project_paths.sort() | 672 | new_project_paths.sort() |