[gclient] Reduce number of git operations during sync

This version is 1.08 ± 0.04 times faster based on hyperfine results.

Bug: 40942309
Change-Id: If67e53bb778b88b0cb7c44ad86ba7438ab843ce3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/5480171
Commit-Queue: Josip Sokcevic <sokcevic@chromium.org>
Reviewed-by: Gavin Mak <gavinmak@google.com>
changes/71/5480171/4
Josip Sokcevic 1 year ago committed by LUCI CQ
parent 14cccc4b9a
commit 5a0631fd9d

@ -638,6 +638,7 @@ class GitWrapper(SCMWrapper):
raise gclient_utils.Error("Unsupported argument(s): %s" % raise gclient_utils.Error("Unsupported argument(s): %s" %
",".join(args)) ",".join(args))
current_revision = None
url, deps_revision = gclient_utils.SplitUrlRevision(self.url) url, deps_revision = gclient_utils.SplitUrlRevision(self.url)
revision = deps_revision revision = deps_revision
managed = True managed = True
@ -713,11 +714,11 @@ class GitWrapper(SCMWrapper):
self._UpdateMirrorIfNotContains(mirror, options, rev_type, self._UpdateMirrorIfNotContains(mirror, options, rev_type,
revision) revision)
try: try:
self._Clone(revision, url, options) current_revision = self._Clone(revision, url, options)
except subprocess2.CalledProcessError as e: except subprocess2.CalledProcessError as e:
logging.warning('Clone failed due to: %s', e) logging.warning('Clone failed due to: %s', e)
self._DeleteOrMove(options.force) self._DeleteOrMove(options.force)
self._Clone(revision, url, options) current_revision = self._Clone(revision, url, options)
if file_list is not None: if file_list is not None:
files = self._Capture( files = self._Capture(
['-c', 'core.quotePath=false', 'ls-files']).splitlines() ['-c', 'core.quotePath=false', 'ls-files']).splitlines()
@ -790,15 +791,18 @@ class GitWrapper(SCMWrapper):
os.path.join(self.checkout_path, '.git', 'objects', os.path.join(self.checkout_path, '.git', 'objects',
'info', 'alternates'), 'a') as fh: 'info', 'alternates'), 'a') as fh:
fh.write("\n" + os.path.join(url, 'objects')) fh.write("\n" + os.path.join(url, 'objects'))
self._EnsureValidHeadObjectOrCheckout(revision, options, url) current_revision = self._EnsureValidHeadObjectOrCheckout(
revision, options, url)
self._FetchAndReset(revision, file_list, options) self._FetchAndReset(revision, file_list, options)
return_early = True return_early = True
else: else:
self._EnsureValidHeadObjectOrCheckout(revision, options, url) current_revision = self._EnsureValidHeadObjectOrCheckout(
revision, options, url)
if return_early: if return_early:
return self._Capture(['rev-parse', '--verify', 'HEAD']) return current_revision or self._Capture(
['rev-parse', '--verify', 'HEAD'])
cur_branch = self._GetCurrentBranch() cur_branch = self._GetCurrentBranch()
@ -878,7 +882,11 @@ class GitWrapper(SCMWrapper):
if not (options.force or options.reset): if not (options.force or options.reset):
self._CheckClean(revision) self._CheckClean(revision)
self._CheckDetachedHead(revision, options) self._CheckDetachedHead(revision, options)
if self._Capture(['rev-list', '-n', '1', 'HEAD']) == revision:
if not current_revision:
current_revision = self._Capture(
['rev-list', '-n', '1', 'HEAD'])
if current_revision == revision:
self.Print('Up-to-date; skipping checkout.') self.Print('Up-to-date; skipping checkout.')
else: else:
# 'git checkout' may need to overwrite existing untracked files. # 'git checkout' may need to overwrite existing untracked files.
@ -1061,10 +1069,12 @@ class GitWrapper(SCMWrapper):
self.Print('_____ removing unversioned directory %s' % path) self.Print('_____ removing unversioned directory %s' % path)
gclient_utils.rmtree(full_path) gclient_utils.rmtree(full_path)
rev_hash = self._Capture(['rev-parse', '--verify', 'HEAD']) if not current_revision:
current_revision = self._Capture(['rev-parse', '--verify', 'HEAD'])
if verbose: if verbose:
self.Print(f'Checked out revision {rev_hash}', timestamp=False) self.Print(f'Checked out revision {current_revision}',
return rev_hash timestamp=False)
return current_revision
def revert(self, options, _args, file_list): def revert(self, options, _args, file_list):
"""Reverts local modifications. """Reverts local modifications.
@ -1288,6 +1298,7 @@ class GitWrapper(SCMWrapper):
'in this repo, you should use \'git checkout <branch>\' to switch \n' 'in this repo, you should use \'git checkout <branch>\' to switch \n'
'to an existing branch or use \'git checkout %s -b <branch>\' to\n' 'to an existing branch or use \'git checkout %s -b <branch>\' to\n'
'create a new branch for your work.') % (revision, self.remote)) 'create a new branch for your work.') % (revision, self.remote))
return revision
def _AskForData(self, prompt, options): def _AskForData(self, prompt, options):
if options.jobs > 1: if options.jobs > 1:
@ -1397,7 +1408,7 @@ class GitWrapper(SCMWrapper):
# on most git operations. Since git cache is used, just deleted the .git # on most git operations. Since git cache is used, just deleted the .git
# folder, and re-create it by cloning. # folder, and re-create it by cloning.
try: try:
self._Capture(['rev-list', '-n', '1', 'HEAD']) return self._Capture(['rev-list', '-n', '1', 'HEAD'])
except subprocess2.CalledProcessError as e: except subprocess2.CalledProcessError as e:
if (b'fatal: bad object HEAD' in e.stderr and self.cache_dir if (b'fatal: bad object HEAD' in e.stderr and self.cache_dir
and self.cache_dir in url): and self.cache_dir in url):
@ -1406,9 +1417,8 @@ class GitWrapper(SCMWrapper):
'the current commit points to no longer existing object.\n' 'the current commit points to no longer existing object.\n'
'%s' % e)) '%s' % e))
self._DeleteOrMove(options.force) self._DeleteOrMove(options.force)
self._Clone(revision, url, options) return self._Clone(revision, url, options)
else: raise
raise
def _IsRebasing(self): def _IsRebasing(self):
# Check for any of REBASE-i/REBASE-m/REBASE/AM. Unfortunately git # Check for any of REBASE-i/REBASE-m/REBASE/AM. Unfortunately git

Loading…
Cancel
Save