summaryrefslogtreecommitdiffstats
path: root/subcmds/sync.py
diff options
context:
space:
mode:
authorMike Frysinger <vapier@google.com>2020-02-19 19:19:18 -0500
committerMike Frysinger <vapier@google.com>2020-02-20 00:51:42 +0000
commitc0d1866b35d3e8d0bee3760a9f52574fa2ab8491 (patch)
treec6be761e1dbf5e93dfe499e8f53d90386a2d6769 /subcmds/sync.py
parentf81c72ed7727ca408d1859a86c56b532a8de8d59 (diff)
downloadgit-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.py85
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
17from __future__ import print_function 17from __future__ import print_function
18 18
19import errno
20import json 19import json
21import netrc 20import netrc
22from optparse import SUPPRESS_HELP 21from 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()