mirror of
https://gerrit.googlesource.com/git-repo
synced 2024-12-21 07:16:21 +00:00
On project cleanup, don't remove nested projects
When there are nested projects in a manifest, like on AOSP right now: <project path="build" name="platform/build" /> <project path="build/blueprint" name="platform/build/blueprint" /> <project path="build/kati" name="platform/build/kati" /> <project path="build/soong" name="platform/build/soong" /> And the top "build" project is removed (or renamed to remove the nesting), repo just wipes away everything under build/ and re-creates the projects that are still there. But it only checks to see if the build/ project is dirty, so if there are dirty files in a nested project, they'll just be blown away, and a fresh worktree checked out. Instead, behave similarly to how `git clean -dxf` behaves and preserve any subdirectories that have git repositories in them. This isn't as strict as git -- it does not check to see if the '.git' entry is a readable gitdir, just whether an entry named '.git' exists. If it encounters any errors removing files, we'll print them all out to stderr and tell the user that we were unable to clean up the obsolete project, that they should clean it up manually, then sync again. Change-Id: I2f6a7dd205a8e0b7590ca5369e9b0ba21d5a6f77
This commit is contained in:
parent
628456833a
commit
4350791e0d
@ -457,6 +457,59 @@ later is required to fix a server side protocol bug.
|
||||
else:
|
||||
self.manifest._Unload()
|
||||
|
||||
def _DeleteProject(self, path):
|
||||
print('Deleting obsolete path %s' % path, file=sys.stderr)
|
||||
|
||||
# Delete the .git directory first, so we're less likely to have a partially
|
||||
# working git repository around. There shouldn't be any git projects here,
|
||||
# so rmtree works.
|
||||
try:
|
||||
shutil.rmtree(os.path.join(path, '.git'))
|
||||
except OSError:
|
||||
print('Failed to remove %s' % os.path.join(path, '.git'), file=sys.stderr)
|
||||
print('error: Failed to delete obsolete path %s' % path, file=sys.stderr)
|
||||
print(' remove manually, then run sync again', file=sys.stderr)
|
||||
return -1
|
||||
|
||||
# Delete everything under the worktree, except for directories that contain
|
||||
# another git project
|
||||
dirs_to_remove = []
|
||||
failed = False
|
||||
for root, dirs, files in os.walk(path):
|
||||
for f in files:
|
||||
try:
|
||||
os.remove(os.path.join(root, f))
|
||||
except OSError:
|
||||
print('Failed to remove %s' % os.path.join(root, f), file=sys.stderr)
|
||||
failed = True
|
||||
dirs[:] = [d for d in dirs
|
||||
if not os.path.lexists(os.path.join(root, d, '.git'))]
|
||||
dirs_to_remove += [os.path.join(root, d) for d in dirs
|
||||
if os.path.join(root, d) not in dirs_to_remove]
|
||||
for d in reversed(dirs_to_remove):
|
||||
if len(os.listdir(d)) == 0:
|
||||
try:
|
||||
os.rmdir(d)
|
||||
except OSError:
|
||||
print('Failed to remove %s' % os.path.join(root, d), file=sys.stderr)
|
||||
failed = True
|
||||
continue
|
||||
if failed:
|
||||
print('error: Failed to delete obsolete path %s' % path, file=sys.stderr)
|
||||
print(' remove manually, then run sync again', file=sys.stderr)
|
||||
return -1
|
||||
|
||||
# Try deleting parent dirs if they are empty
|
||||
project_dir = path
|
||||
while project_dir != self.manifest.topdir:
|
||||
if len(os.listdir(project_dir)) == 0:
|
||||
os.rmdir(project_dir)
|
||||
else:
|
||||
break
|
||||
project_dir = os.path.dirname(project_dir)
|
||||
|
||||
return 0
|
||||
|
||||
def UpdateProjectList(self):
|
||||
new_project_paths = []
|
||||
for project in self.GetProjects(None, missing_ok=True):
|
||||
@ -477,8 +530,8 @@ later is required to fix a server side protocol bug.
|
||||
continue
|
||||
if path not in new_project_paths:
|
||||
# If the path has already been deleted, we don't need to do it
|
||||
if os.path.exists(self.manifest.topdir + '/' + path):
|
||||
gitdir = os.path.join(self.manifest.topdir, path, '.git')
|
||||
gitdir = os.path.join(self.manifest.topdir, path, '.git')
|
||||
if os.path.exists(gitdir):
|
||||
project = Project(
|
||||
manifest = self.manifest,
|
||||
name = path,
|
||||
@ -497,18 +550,8 @@ later is required to fix a server side protocol bug.
|
||||
print(' commit changes, then run sync again',
|
||||
file=sys.stderr)
|
||||
return -1
|
||||
else:
|
||||
print('Deleting obsolete path %s' % project.worktree,
|
||||
file=sys.stderr)
|
||||
shutil.rmtree(project.worktree)
|
||||
# Try deleting parent subdirs if they are empty
|
||||
project_dir = os.path.dirname(project.worktree)
|
||||
while project_dir != self.manifest.topdir:
|
||||
try:
|
||||
os.rmdir(project_dir)
|
||||
except OSError:
|
||||
break
|
||||
project_dir = os.path.dirname(project_dir)
|
||||
elif self._DeleteProject(project.worktree):
|
||||
return -1
|
||||
|
||||
new_project_paths.sort()
|
||||
fd = open(file_path, 'w')
|
||||
|
Loading…
Reference in New Issue
Block a user