summaryrefslogtreecommitdiffstats
path: root/project.py
diff options
context:
space:
mode:
authorMike Frysinger <vapier@google.com>2019-11-11 04:34:16 -0500
committerMike Frysinger <vapier@google.com>2019-11-12 03:44:33 +0000
commitf4545126197781beb03bb0fd47e7f24ce5af6ca8 (patch)
treec648d5a0a508281c146d1db1f21960f8107342d4 /project.py
parentb466854bed4348a210fec5870023c1a44cd830b5 (diff)
downloadgit-repo-f4545126197781beb03bb0fd47e7f24ce5af6ca8.tar.gz
sync: make .git init more robust
Hitting Ctrl-C in the middle of this func will leave the .git in a bad state that requires manual recovery. The code tries to catch all exceptions and recover by deleting the incomplete .git dir, but it omits KeyboardInterrupt which Exception misses. We could add that to the recovery path, but we can make this more robust with a different approach: set up everything in .git.tmp/ and only move it to .git/ once we've fully initialized it. Change-Id: I0f5b97f2e19fc39cffc3e5e23993a2da7220f4e3 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/244733 Reviewed-by: David Pursehouse <dpursehouse@collab.net> Tested-by: Mike Frysinger <vapier@google.com>
Diffstat (limited to 'project.py')
-rwxr-xr-xproject.py64
1 files changed, 34 insertions, 30 deletions
diff --git a/project.py b/project.py
index 51160a94..a2a3adc8 100755
--- a/project.py
+++ b/project.py
@@ -2706,41 +2706,45 @@ class Project(object):
2706 raise 2706 raise
2707 2707
2708 def _InitWorkTree(self, force_sync=False, submodules=False): 2708 def _InitWorkTree(self, force_sync=False, submodules=False):
2709 dotgit = os.path.join(self.worktree, '.git') 2709 realdotgit = os.path.join(self.worktree, '.git')
2710 init_dotgit = not os.path.exists(dotgit) 2710 tmpdotgit = realdotgit + '.tmp'
2711 init_dotgit = not os.path.exists(realdotgit)
2712 if init_dotgit:
2713 dotgit = tmpdotgit
2714 platform_utils.rmtree(tmpdotgit, ignore_errors=True)
2715 os.makedirs(tmpdotgit)
2716 self._ReferenceGitDir(self.gitdir, tmpdotgit, share_refs=True,
2717 copy_all=False)
2718 else:
2719 dotgit = realdotgit
2720
2711 try: 2721 try:
2712 if init_dotgit: 2722 self._CheckDirReference(self.gitdir, dotgit, share_refs=True)
2713 os.makedirs(dotgit) 2723 except GitError as e:
2714 self._ReferenceGitDir(self.gitdir, dotgit, share_refs=True, 2724 if force_sync and not init_dotgit:
2715 copy_all=False) 2725 try:
2726 platform_utils.rmtree(dotgit)
2727 return self._InitWorkTree(force_sync=False, submodules=submodules)
2728 except:
2729 raise e
2730 raise e
2716 2731
2717 try: 2732 if init_dotgit:
2718 self._CheckDirReference(self.gitdir, dotgit, share_refs=True) 2733 _lwrite(os.path.join(tmpdotgit, HEAD), '%s\n' % self.GetRevisionId())
2719 except GitError as e:
2720 if force_sync:
2721 try:
2722 platform_utils.rmtree(dotgit)
2723 return self._InitWorkTree(force_sync=False, submodules=submodules)
2724 except:
2725 raise e
2726 raise e
2727 2734
2728 if init_dotgit: 2735 # Now that the .git dir is fully set up, move it to its final home.
2729 _lwrite(os.path.join(dotgit, HEAD), '%s\n' % self.GetRevisionId()) 2736 platform_utils.rename(tmpdotgit, realdotgit)
2730 2737
2731 cmd = ['read-tree', '--reset', '-u'] 2738 # Finish checking out the worktree.
2732 cmd.append('-v') 2739 cmd = ['read-tree', '--reset', '-u']
2733 cmd.append(HEAD) 2740 cmd.append('-v')
2734 if GitCommand(self, cmd).Wait() != 0: 2741 cmd.append(HEAD)
2735 raise GitError("cannot initialize work tree for " + self.name) 2742 if GitCommand(self, cmd).Wait() != 0:
2743 raise GitError('Cannot initialize work tree for ' + self.name)
2736 2744
2737 if submodules: 2745 if submodules:
2738 self._SyncSubmodules(quiet=True) 2746 self._SyncSubmodules(quiet=True)
2739 self._CopyAndLinkFiles() 2747 self._CopyAndLinkFiles()
2740 except Exception:
2741 if init_dotgit:
2742 platform_utils.rmtree(dotgit)
2743 raise
2744 2748
2745 def _get_symlink_error_message(self): 2749 def _get_symlink_error_message(self):
2746 if platform_utils.isWindows(): 2750 if platform_utils.isWindows():