Improve repo sync performance by avoid git forks

By resolving the current HEAD and the manifest revision using pure
Python, we can in the common case of "no changes" avoid a lot of
git operations and directly jump out of the local sync method.

This reduces the no-op `repo sync -l` time for Android's 114 projects
from more than 6s to under 0.8s.

Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce 2009-04-17 20:58:02 -07:00
parent d237b69865
commit fbcde472ca
2 changed files with 60 additions and 15 deletions

View File

@ -41,6 +41,17 @@ class GitRefs(object):
except KeyError: except KeyError:
return '' return ''
def deleted(self, name):
if self._phyref is not None:
if name in self._phyref:
del self._phyref[name]
if name in self._symref:
del self._symref[name]
if name in self._mtime:
del self._mtime[name]
def _NeedUpdate(self): def _NeedUpdate(self):
for name, mtime in self._mtime.iteritems(): for name, mtime in self._mtime.iteritems():
try: try:

View File

@ -416,22 +416,31 @@ class Project(object):
## Publish / Upload ## ## Publish / Upload ##
def WasPublished(self, branch): def WasPublished(self, branch, all=None):
"""Was the branch published (uploaded) for code review? """Was the branch published (uploaded) for code review?
If so, returns the SHA-1 hash of the last published If so, returns the SHA-1 hash of the last published
state for the branch. state for the branch.
""" """
key = R_PUB + branch
if all is None:
try: try:
return self.bare_git.rev_parse(R_PUB + branch) return self.bare_git.rev_parse(key)
except GitError: except GitError:
return None return None
else:
try:
return all[key]
except KeyError:
return None
def CleanPublishedCache(self): def CleanPublishedCache(self, all=None):
"""Prunes any stale published refs. """Prunes any stale published refs.
""" """
if all is None:
all = self._allrefs
heads = set() heads = set()
canrm = {} canrm = {}
for name, id in self._allrefs.iteritems(): for name, id in all.iteritems():
if name.startswith(R_HEADS): if name.startswith(R_HEADS):
heads.add(name) heads.add(name)
elif name.startswith(R_PUB): elif name.startswith(R_PUB):
@ -567,17 +576,31 @@ class Project(object):
Network access is not required. Network access is not required.
""" """
self._InitWorkTree() self._InitWorkTree()
self.CleanPublishedCache() all = self.bare_ref.all
self.CleanPublishedCache(all)
rem = self.GetRemote(self.remote.name) rem = self.GetRemote(self.remote.name)
rev = rem.ToLocal(self.revision) rev = rem.ToLocal(self.revision)
if rev in all:
revid = all[rev]
elif IsId(rev):
revid = rev
else:
try: try:
self.bare_git.rev_parse('--verify', '%s^0' % rev) revid = self.bare_git.rev_parse('--verify', '%s^0' % rev)
except GitError: except GitError:
raise ManifestInvalidRevisionError( raise ManifestInvalidRevisionError(
'revision %s in %s not found' % (self.revision, self.name)) 'revision %s in %s not found' % (self.revision, self.name))
branch = self.CurrentBranch head = self.work_git.GetHead()
if head.startswith(R_HEADS):
branch = head[len(R_HEADS):]
try:
head = all[head]
except KeyError:
head = None
else:
branch = None
if branch is None or syncbuf.detach_head: if branch is None or syncbuf.detach_head:
# Currently on a detached HEAD. The user is assumed to # Currently on a detached HEAD. The user is assumed to
@ -588,6 +611,11 @@ class Project(object):
syncbuf.fail(self, _PriorSyncFailedError()) syncbuf.fail(self, _PriorSyncFailedError())
return return
if head == revid:
# No changes; don't do anything further.
#
return
lost = self._revlist(not_rev(rev), HEAD) lost = self._revlist(not_rev(rev), HEAD)
if lost: if lost:
syncbuf.info(self, "discarding %d commits", len(lost)) syncbuf.info(self, "discarding %d commits", len(lost))
@ -599,6 +627,11 @@ class Project(object):
self._CopyFiles() self._CopyFiles()
return return
if head == revid:
# No changes; don't do anything further.
#
return
branch = self.GetBranch(branch) branch = self.GetBranch(branch)
merge = branch.LocalMerge merge = branch.LocalMerge
@ -618,7 +651,7 @@ class Project(object):
return return
upstream_gain = self._revlist(not_rev(HEAD), rev) upstream_gain = self._revlist(not_rev(HEAD), rev)
pub = self.WasPublished(branch.name) pub = self.WasPublished(branch.name, all)
if pub: if pub:
not_merged = self._revlist(not_rev(rev), pub) not_merged = self._revlist(not_rev(rev), pub)
if not_merged: if not_merged:
@ -1142,6 +1175,7 @@ class Project(object):
if not old: if not old:
old = self.rev_parse(name) old = self.rev_parse(name)
self.update_ref('-d', name, old) self.update_ref('-d', name, old)
self._project.bare_ref.deleted(name)
def rev_list(self, *args): def rev_list(self, *args):
cmdv = ['rev-list'] cmdv = ['rev-list']