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
This commit is contained in:
Brian Harring
2012-09-28 20:21:57 -07:00
parent 34acdd2534
commit 14a6674e32
3 changed files with 55 additions and 17 deletions

View File

@ -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):