From 53d6f4d17e0cb4eabcd604d584a1132a51cc8bf3 Mon Sep 17 00:00:00 2001 From: Anatol Pomazau Date: Thu, 25 Aug 2011 17:21:47 -0700 Subject: [PATCH] Add a sync flag that fetches only current branch There is also shortcuts in case if the "current branch" is a persistent revision such as tag or sha1. We check if the persistent revision is present locally and if it does - do no fetch anything from the server. This greately reduces sync time and size of the on-disk repo Change-Id: I23c6d95185474ed6e1a03c836a47f489953b99be --- project.py | 55 +++++++++++++++++++++++++++++++++---------------- subcmds/sync.py | 12 ++++++++--- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/project.py b/project.py index b61bcacb..a69407da 100644 --- a/project.py +++ b/project.py @@ -36,7 +36,7 @@ except ImportError: from color import Coloring from git_command import GitCommand -from git_config import GitConfig, IsId, GetSchemeFromUrl +from git_config import GitConfig, IsId, GetSchemeFromUrl, ID_RE from error import DownloadError from error import GitError, HookError, ImportError, UploadError from error import ManifestInvalidRevisionError @@ -900,7 +900,7 @@ class Project(object): ## Sync ## - def Sync_NetworkHalf(self, quiet=False, is_new=None): + def Sync_NetworkHalf(self, quiet=False, is_new=None, current_branch_only=False): """Perform only the network IO portion of the sync process. Local working directory/branch state is not affected. """ @@ -926,21 +926,10 @@ class Project(object): if alt_dir is None and self._ApplyCloneBundle(initial=is_new, quiet=quiet): is_new = False - if not self._RemoteFetch(initial=is_new, quiet=quiet, alt_dir=alt_dir): + if not self._RemoteFetch(initial=is_new, quiet=quiet, alt_dir=alt_dir, + current_branch_only=current_branch_only): return False - #Check that the requested ref was found after fetch - # - try: - self.GetRevisionId() - except ManifestInvalidRevisionError: - # if the ref is a tag. We can try fetching - # the tag manually as a last resort - # - rev = self.revisionExpr - if rev.startswith(R_TAGS): - self._RemoteFetch(None, rev[len(R_TAGS):], quiet=quiet) - if self.worktree: self._InitMRef() else: @@ -1335,10 +1324,30 @@ class Project(object): ## Direct Git Commands ## - def _RemoteFetch(self, name=None, tag=None, + def _RemoteFetch(self, name=None, + current_branch_only=False, initial=False, quiet=False, alt_dir=None): + + is_sha1 = False + tag_name = None + + if current_branch_only: + if ID_RE.match(self.revisionExpr) is not None: + is_sha1 = True + elif self.revisionExpr.startswith(R_TAGS): + # this is a tag and its sha1 value should never change + tag_name = self.revisionExpr[len(R_TAGS):] + + if is_sha1 or tag_name is not None: + try: + self.GetRevisionId() + return True + except ManifestInvalidRevisionError: + # There is no such persistent revision. We have to fetch it. + pass + if not name: name = self.remote.name @@ -1401,9 +1410,19 @@ class Project(object): if not self.worktree: cmd.append('--update-head-ok') cmd.append(name) - if tag is not None: + + if not current_branch_only or is_sha1: + # Fetch whole repo + cmd.append('--tags') + cmd.append((u'+refs/heads/*:') + remote.ToLocal('refs/heads/*')) + elif tag_name is not None: cmd.append('tag') - cmd.append(tag) + cmd.append(tag_name) + else: + branch = self.revisionExpr + 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): diff --git a/subcmds/sync.py b/subcmds/sync.py index a3d06922..c5955a38 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py @@ -131,6 +131,9 @@ later is required to fix a server side protocol bug. p.add_option('-d','--detach', dest='detach_head', action='store_true', help='detach projects back to manifest revision') + p.add_option('-c','--current-branch', + dest='current_branch_only', action='store_true', + help='fetch only current branch from server') p.add_option('-q','--quiet', dest='quiet', action='store_true', help='be more quiet') @@ -179,7 +182,8 @@ later is required to fix a server side protocol bug. # - We always make sure we unlock the lock if we locked it. try: try: - success = project.Sync_NetworkHalf(quiet=opt.quiet) + success = project.Sync_NetworkHalf(quiet=opt.quiet, + current_branch_only=opt.current_branch_only) # Lock around all the rest of the code, since printing, updating a set # and Progress.update() are not thread safe. @@ -212,7 +216,8 @@ later is required to fix a server side protocol bug. if self.jobs == 1: for project in projects: pm.update() - if project.Sync_NetworkHalf(quiet=opt.quiet): + if project.Sync_NetworkHalf(quiet=opt.quiet, + current_branch_only=opt.current_branch_only): fetched.add(project.gitdir) else: print >>sys.stderr, 'error: Cannot fetch %s' % project.name @@ -388,7 +393,8 @@ uncommitted changes are present' % project.relpath _PostRepoUpgrade(self.manifest) if not opt.local_only: - mp.Sync_NetworkHalf(quiet=opt.quiet) + mp.Sync_NetworkHalf(quiet=opt.quiet, + current_branch_only=opt.current_branch_only) if mp.HasChanges: syncbuf = SyncBuffer(mp.config)