From 14a6674e32b3000dbe8b7c96b0d1bb4fb0021720 Mon Sep 17 00:00:00 2001 From: Brian Harring Date: Fri, 28 Sep 2012 20:21:57 -0700 Subject: manifest: record the original revision when in -r mode. Currently when doing a sync against a revision locked manifest, sync has no option but to fall back to sync'ing the entire refs space; it doesn't know which ref to ask for that contains the sha1 it wants. This sucks if we're in -c mode; thus when we generate a revision locked manifest, record the originating branch- and try syncing that branch first. If the sha1 is found within that branch, this saves us having to pull down the rest of the repo- a potentially heavy saving. If that branch doesn't have the desired sha1, we fallback to sync'ing everything. Change-Id: I99a5e44fa1d792dfcada76956a2363187df94cf1 --- project.py | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) (limited to 'project.py') diff --git a/project.py b/project.py index 4621013c..04c43bb7 100644 --- a/project.py +++ b/project.py @@ -484,7 +484,8 @@ class Project(object): revisionId, rebase = True, groups = None, - sync_c = False): + sync_c = False, + upstream = None): self.manifest = manifest self.name = name self.remote = remote @@ -506,6 +507,7 @@ class Project(object): self.rebase = rebase self.groups = groups self.sync_c = sync_c + self.upstream = upstream self.snapshots = {} self.copyfiles = [] @@ -1373,6 +1375,16 @@ class Project(object): is_sha1 = False tag_name = None + def CheckForSha1(): + try: + # if revision (sha or tag) is not present then following function + # throws an error. + self.bare_git.rev_parse('--verify', '%s^0' % self.revisionExpr) + return True + except GitError: + # There is no such persistent revision. We have to fetch it. + return False + if current_branch_only: if ID_RE.match(self.revisionExpr) is not None: is_sha1 = True @@ -1381,14 +1393,10 @@ class Project(object): tag_name = self.revisionExpr[len(R_TAGS):] if is_sha1 or tag_name is not None: - try: - # if revision (sha or tag) is not present then following function - # throws an error. - self.bare_git.rev_parse('--verify', '%s^0' % self.revisionExpr) + if CheckForSha1(): return True - except GitError: - # There is no such persistent revision. We have to fetch it. - pass + if is_sha1 and (not self.upstream or ID_RE.match(self.upstream)): + current_branch_only = False if not name: name = self.remote.name @@ -1453,7 +1461,7 @@ class Project(object): cmd.append('--update-head-ok') cmd.append(name) - if not current_branch_only or is_sha1: + if not current_branch_only: # Fetch whole repo cmd.append('--tags') cmd.append((u'+refs/heads/*:') + remote.ToLocal('refs/heads/*')) @@ -1462,15 +1470,23 @@ class Project(object): cmd.append(tag_name) else: branch = self.revisionExpr + if is_sha1: + branch = self.upstream if branch.startswith(R_HEADS): branch = branch[len(R_HEADS):] cmd.append((u'+refs/heads/%s:' % branch) + remote.ToLocal('refs/heads/%s' % branch)) ok = False for i in range(2): - if GitCommand(self, cmd, bare=True, ssh_proxy=ssh_proxy).Wait() == 0: + ret = GitCommand(self, cmd, bare=True, ssh_proxy=ssh_proxy).Wait() + if ret == 0: ok = True break + elif current_branch_only and is_sha1 and ret == 128: + # Exit code 128 means "couldn't find the ref you asked for"; if we're in sha1 + # mode, we just tried sync'ing from the upstream field; it doesn't exist, thus + # abort the optimization attempt and do a full sync. + break time.sleep(random.randint(30, 45)) if initial: @@ -1480,6 +1496,15 @@ class Project(object): else: os.remove(packed_refs) self.bare_git.pack_refs('--all', '--prune') + + if is_sha1 and current_branch_only and self.upstream: + # We just synced the upstream given branch; verify we + # got what we wanted, else trigger a second run of all + # refs. + if not CheckForSha1(): + return self._RemoteFetch(name=name, current_branch_only=False, + initial=False, quiet=quiet, alt_dir=alt_dir) + return ok def _ApplyCloneBundle(self, initial=False, quiet=False): -- cgit v1.2.3-54-g00ecf