From abaa7f312f1b6c8d11d7c757fe909900ce5788b5 Mon Sep 17 00:00:00 2001 From: Kevin Degi Date: Wed, 12 Nov 2014 11:27:45 -0700 Subject: Add option to correct gitdir when syncing In some cases, a user may wish to continue with a sync even though it would require overwriting an existing git directory. This behavior is not safe as a default because it could result in the loss of some user data, but as an optional flag it allows the user more flexibility. To support this, add a --force-sync flag to the sync command that will attempt to overwrite the existing git dir if it is specified and the existing git dir points to the wrong obj dir. Change-Id: Ieddda8ad54e264a1eb4a9d54881dd6ebc8a03833 --- project.py | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) (limited to 'project.py') diff --git a/project.py b/project.py index 9e8ee868..868425ce 100644 --- a/project.py +++ b/project.py @@ -32,7 +32,7 @@ import traceback from color import Coloring from git_command import GitCommand, git_require from git_config import GitConfig, IsId, GetSchemeFromUrl, ID_RE -from error import GitError, HookError, UploadError +from error import GitError, HookError, UploadError, DownloadError from error import ManifestInvalidRevisionError from error import NoManifestException from trace import IsTrace, Trace @@ -1101,6 +1101,7 @@ class Project(object): quiet=False, is_new=None, current_branch_only=False, + force_sync=False, clone_bundle=True, no_tags=False, archive=False, @@ -1140,7 +1141,7 @@ class Project(object): if is_new is None: is_new = not self.Exists if is_new: - self._InitGitDir() + self._InitGitDir(force_sync=force_sync) else: self._UpdateHooks() self._InitRemote() @@ -1233,11 +1234,11 @@ class Project(object): 'revision %s in %s not found' % (self.revisionExpr, self.name)) - def Sync_LocalHalf(self, syncbuf): + def Sync_LocalHalf(self, syncbuf, force_sync=False): """Perform only the local IO portion of the sync process. Network access is not required. """ - self._InitWorkTree() + self._InitWorkTree(force_sync=force_sync) all_refs = self.bare_ref.all self.CleanPublishedCache(all_refs) revid = self.GetRevisionId(all_refs) @@ -2164,7 +2165,7 @@ class Project(object): if GitCommand(self, cmd).Wait() != 0: raise GitError('%s merge %s ' % (self.name, head)) - def _InitGitDir(self, mirror_git=None): + def _InitGitDir(self, mirror_git=None, force_sync=False): init_git_dir = not os.path.exists(self.gitdir) init_obj_dir = not os.path.exists(self.objdir) try: @@ -2181,7 +2182,20 @@ class Project(object): if init_obj_dir or init_git_dir: self._ReferenceGitDir(self.objdir, self.gitdir, share_refs=False, copy_all=True) - self._CheckDirReference(self.objdir, self.gitdir, share_refs=False) + try: + self._CheckDirReference(self.objdir, self.gitdir, share_refs=False) + except GitError as e: + print("Retrying clone after deleting %s" % force_sync, file=sys.stderr) + if force_sync: + try: + shutil.rmtree(os.path.realpath(self.gitdir)) + if self.worktree and os.path.exists( + os.path.realpath(self.worktree)): + shutil.rmtree(os.path.realpath(self.worktree)) + return self._InitGitDir(mirror_git=mirror_git, force_sync=False) + except: + raise e + raise e if init_git_dir: mp = self.manifest.manifestProject @@ -2308,7 +2322,8 @@ class Project(object): src = os.path.realpath(os.path.join(srcdir, name)) # Fail if the links are pointing to the wrong place if src != dst: - raise GitError('cannot overwrite a local work tree') + raise GitError('--force-sync not enabled; cannot overwrite a local ' + 'work tree') def _ReferenceGitDir(self, gitdir, dotgit, share_refs, copy_all): """Update |dotgit| to reference |gitdir|, using symlinks where possible. @@ -2361,11 +2376,11 @@ class Project(object): shutil.copy(src, dst) except OSError as e: if e.errno == errno.EPERM: - raise GitError('filesystem must support symlinks') + raise DownloadError('filesystem must support symlinks') else: raise - def _InitWorkTree(self): + def _InitWorkTree(self, force_sync=False): dotgit = os.path.join(self.worktree, '.git') init_dotgit = not os.path.exists(dotgit) try: @@ -2374,7 +2389,16 @@ class Project(object): self._ReferenceGitDir(self.gitdir, dotgit, share_refs=True, copy_all=False) - self._CheckDirReference(self.gitdir, dotgit, share_refs=True) + try: + self._CheckDirReference(self.gitdir, dotgit, share_refs=True) + except GitError as e: + if force_sync: + try: + shutil.rmtree(dotgit) + return self._InitWorkTree(force_sync=False) + except: + raise e + raise e if init_dotgit: _lwrite(os.path.join(dotgit, HEAD), '%s\n' % self.GetRevisionId()) -- cgit v1.2.3-54-g00ecf