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
This commit is contained in:
Anatol Pomazau 2011-08-25 17:21:47 -07:00 committed by Shawn O. Pearce
parent 9d8f914fe8
commit 53d6f4d17e
2 changed files with 46 additions and 21 deletions

View File

@ -36,7 +36,7 @@ except ImportError:
from color import Coloring from color import Coloring
from git_command import GitCommand 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 DownloadError
from error import GitError, HookError, ImportError, UploadError from error import GitError, HookError, ImportError, UploadError
from error import ManifestInvalidRevisionError from error import ManifestInvalidRevisionError
@ -900,7 +900,7 @@ class Project(object):
## Sync ## ## 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. """Perform only the network IO portion of the sync process.
Local working directory/branch state is not affected. 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): if alt_dir is None and self._ApplyCloneBundle(initial=is_new, quiet=quiet):
is_new = False 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 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: if self.worktree:
self._InitMRef() self._InitMRef()
else: else:
@ -1335,10 +1324,30 @@ class Project(object):
## Direct Git Commands ## ## Direct Git Commands ##
def _RemoteFetch(self, name=None, tag=None, def _RemoteFetch(self, name=None,
current_branch_only=False,
initial=False, initial=False,
quiet=False, quiet=False,
alt_dir=None): 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: if not name:
name = self.remote.name name = self.remote.name
@ -1401,9 +1410,19 @@ class Project(object):
if not self.worktree: if not self.worktree:
cmd.append('--update-head-ok') cmd.append('--update-head-ok')
cmd.append(name) 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) 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 ok = False
for i in range(2): for i in range(2):

View File

@ -131,6 +131,9 @@ later is required to fix a server side protocol bug.
p.add_option('-d','--detach', p.add_option('-d','--detach',
dest='detach_head', action='store_true', dest='detach_head', action='store_true',
help='detach projects back to manifest revision') 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', p.add_option('-q','--quiet',
dest='quiet', action='store_true', dest='quiet', action='store_true',
help='be more quiet') 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. # - We always make sure we unlock the lock if we locked it.
try: try:
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 # Lock around all the rest of the code, since printing, updating a set
# and Progress.update() are not thread safe. # 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: if self.jobs == 1:
for project in projects: for project in projects:
pm.update() 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) fetched.add(project.gitdir)
else: else:
print >>sys.stderr, 'error: Cannot fetch %s' % project.name print >>sys.stderr, 'error: Cannot fetch %s' % project.name
@ -388,7 +393,8 @@ uncommitted changes are present' % project.relpath
_PostRepoUpgrade(self.manifest) _PostRepoUpgrade(self.manifest)
if not opt.local_only: 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: if mp.HasChanges:
syncbuf = SyncBuffer(mp.config) syncbuf = SyncBuffer(mp.config)