Commit 396e1a6d authored by iannucci@chromium.org's avatar iannucci@chromium.org

If we're running in nohooks mode, don't bother to accumulate file_list in gclient.

This enables significant time savings, especially since file_list only exists to
enable file-specific hooks (which, AFAIK, nothing actually uses). On a z620
(linux) using the cached git repos, a first-time `gclient sync --nohooks` takes:
  * (with)    131.06s user 14.10s  system 117% cpu 2:03.89 total
  * (without) 482.13s user 189.35s system 144% cpu 7:45.63 total

This change makes nohooks cause file_list to be None if we don't need to
accumulate it, and updates GitWrapper and SvnWrapper appropriately.

R=szager@chromium.org
BUG=

Review URL: https://chromiumcodereview.appspot.com/18541006

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@210026 0039d316-1c4b-4281-b951-d872f2087c98
parent 53456aa2
...@@ -591,7 +591,7 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): ...@@ -591,7 +591,7 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
# copy state, so skip the SCM status check. # copy state, so skip the SCM status check.
run_scm = command not in ('runhooks', 'recurse', None) run_scm = command not in ('runhooks', 'recurse', None)
parsed_url = self.LateOverride(self.url) parsed_url = self.LateOverride(self.url)
file_list = [] file_list = [] if not options.nohooks else None
if run_scm and parsed_url: if run_scm and parsed_url:
if isinstance(parsed_url, self.FileImpl): if isinstance(parsed_url, self.FileImpl):
# Special support for single-file checkout. # Special support for single-file checkout.
...@@ -612,11 +612,12 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): ...@@ -612,11 +612,12 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
self._used_scm = gclient_scm.CreateSCM( self._used_scm = gclient_scm.CreateSCM(
parsed_url, self.root.root_dir, self.name) parsed_url, self.root.root_dir, self.name)
self._used_scm.RunCommand(command, options, args, file_list) self._used_scm.RunCommand(command, options, args, file_list)
file_list = [os.path.join(self.name, f.strip()) for f in file_list] if file_list:
file_list = [os.path.join(self.name, f.strip()) for f in file_list]
# TODO(phajdan.jr): We should know exactly when the paths are absolute. # TODO(phajdan.jr): We should know exactly when the paths are absolute.
# Convert all absolute paths to relative. # Convert all absolute paths to relative.
for i in range(len(file_list)): for i in range(len(file_list or [])):
# It depends on the command being executed (like runhooks vs sync). # It depends on the command being executed (like runhooks vs sync).
if not os.path.isabs(file_list[i]): if not os.path.isabs(file_list[i]):
continue continue
...@@ -630,7 +631,7 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): ...@@ -630,7 +631,7 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
# Always parse the DEPS file. # Always parse the DEPS file.
self.ParseDepsFile() self.ParseDepsFile()
self._run_is_done(file_list, parsed_url) self._run_is_done(file_list or [], parsed_url)
if self.recursion_limit: if self.recursion_limit:
# Parse the dependencies of this dependency. # Parse the dependencies of this dependency.
......
...@@ -137,10 +137,6 @@ class SCMWrapper(object): ...@@ -137,10 +137,6 @@ class SCMWrapper(object):
self.checkout_path = os.path.join(self._root_dir, self.relpath) self.checkout_path = os.path.join(self._root_dir, self.relpath)
def RunCommand(self, command, options, args, file_list=None): def RunCommand(self, command, options, args, file_list=None):
# file_list will have all files that are modified appended to it.
if file_list is None:
file_list = []
commands = ['cleanup', 'update', 'updatesingle', 'revert', commands = ['cleanup', 'update', 'updatesingle', 'revert',
'revinfo', 'status', 'diff', 'pack', 'runhooks'] 'revinfo', 'status', 'diff', 'pack', 'runhooks']
...@@ -220,7 +216,7 @@ class GitWrapper(SCMWrapper): ...@@ -220,7 +216,7 @@ class GitWrapper(SCMWrapper):
def GetCheckoutRoot(self): def GetCheckoutRoot(self):
return scm.GIT.GetCheckoutRoot(self.checkout_path) return scm.GIT.GetCheckoutRoot(self.checkout_path)
def GetRevisionDate(self, revision): def GetRevisionDate(self, _revision):
"""Returns the given revision's date in ISO-8601 format (which contains the """Returns the given revision's date in ISO-8601 format (which contains the
time zone).""" time zone)."""
# TODO(floitsch): get the time-stamp of the given revision and not just the # TODO(floitsch): get the time-stamp of the given revision and not just the
...@@ -234,11 +230,11 @@ class GitWrapper(SCMWrapper): ...@@ -234,11 +230,11 @@ class GitWrapper(SCMWrapper):
There's no real git equivalent for the svn cleanup command, do a no-op. There's no real git equivalent for the svn cleanup command, do a no-op.
""" """
def diff(self, options, args, file_list): def diff(self, options, _args, _file_list):
merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) merge_base = self._Capture(['merge-base', 'HEAD', 'origin'])
self._Run(['diff', merge_base], options) self._Run(['diff', merge_base], options)
def pack(self, options, args, file_list): def pack(self, _options, _args, _file_list):
"""Generates a patch file which can be applied to the root of the """Generates a patch file which can be applied to the root of the
repository. repository.
...@@ -293,8 +289,9 @@ class GitWrapper(SCMWrapper): ...@@ -293,8 +289,9 @@ class GitWrapper(SCMWrapper):
self._Run(fetch_cmd + quiet, options) self._Run(fetch_cmd + quiet, options)
self._Run(['reset', '--hard', revision] + quiet, options) self._Run(['reset', '--hard', revision] + quiet, options)
self.UpdateSubmoduleConfig() self.UpdateSubmoduleConfig()
files = self._Capture(['ls-files']).splitlines() if file_list is not None:
file_list.extend([os.path.join(self.checkout_path, f) for f in files]) files = self._Capture(['ls-files']).splitlines()
file_list.extend([os.path.join(self.checkout_path, f) for f in files])
def update(self, options, args, file_list): def update(self, options, args, file_list):
"""Runs git to update or transparently checkout the working copy. """Runs git to update or transparently checkout the working copy.
...@@ -332,7 +329,7 @@ class GitWrapper(SCMWrapper): ...@@ -332,7 +329,7 @@ class GitWrapper(SCMWrapper):
revision = default_rev revision = default_rev
rev_str = ' at %s' % revision rev_str = ' at %s' % revision
files = [] files = [] if file_list is not None else None
printed_path = False printed_path = False
verbose = [] verbose = []
...@@ -359,8 +356,9 @@ class GitWrapper(SCMWrapper): ...@@ -359,8 +356,9 @@ class GitWrapper(SCMWrapper):
gclient_utils.safe_makedirs(os.path.dirname(self.checkout_path)) gclient_utils.safe_makedirs(os.path.dirname(self.checkout_path))
self._Clone(revision, url, options) self._Clone(revision, url, options)
self.UpdateSubmoduleConfig() self.UpdateSubmoduleConfig()
files = self._Capture(['ls-files']).splitlines() if file_list is not None:
file_list.extend([os.path.join(self.checkout_path, f) for f in files]) files = self._Capture(['ls-files']).splitlines()
file_list.extend([os.path.join(self.checkout_path, f) for f in files])
if not verbose: if not verbose:
# Make the output a little prettier. It's nice to have some whitespace # Make the output a little prettier. It's nice to have some whitespace
# between projects when cloning. # between projects when cloning.
...@@ -510,7 +508,8 @@ class GitWrapper(SCMWrapper): ...@@ -510,7 +508,8 @@ class GitWrapper(SCMWrapper):
raise gclient_utils.Error(switch_error) raise gclient_utils.Error(switch_error)
else: else:
# case 3 - the default case # case 3 - the default case
files = self._Capture(['diff', upstream_branch, '--name-only']).split() if files is not None:
files = self._Capture(['diff', upstream_branch, '--name-only']).split()
if verbose: if verbose:
print('Trying fast-forward merge to branch : %s' % upstream_branch) print('Trying fast-forward merge to branch : %s' % upstream_branch)
try: try:
...@@ -572,7 +571,8 @@ class GitWrapper(SCMWrapper): ...@@ -572,7 +571,8 @@ class GitWrapper(SCMWrapper):
print('') print('')
self.UpdateSubmoduleConfig() self.UpdateSubmoduleConfig()
file_list.extend([os.path.join(self.checkout_path, f) for f in files]) if file_list is not None:
file_list.extend([os.path.join(self.checkout_path, f) for f in files])
# If the rebase generated a conflict, abort and ask user to fix # If the rebase generated a conflict, abort and ask user to fix
if self._IsRebasing(): if self._IsRebasing():
...@@ -601,7 +601,7 @@ class GitWrapper(SCMWrapper): ...@@ -601,7 +601,7 @@ class GitWrapper(SCMWrapper):
gclient_utils.rmtree(full_path) gclient_utils.rmtree(full_path)
def revert(self, options, args, file_list): def revert(self, options, _args, file_list):
"""Reverts local modifications. """Reverts local modifications.
All reverted files will be appended to file_list. All reverted files will be appended to file_list.
...@@ -624,19 +624,23 @@ class GitWrapper(SCMWrapper): ...@@ -624,19 +624,23 @@ class GitWrapper(SCMWrapper):
if deps_revision.startswith('refs/heads/'): if deps_revision.startswith('refs/heads/'):
deps_revision = deps_revision.replace('refs/heads/', 'origin/') deps_revision = deps_revision.replace('refs/heads/', 'origin/')
files = self._Capture(['diff', deps_revision, '--name-only']).split() if file_list is not None:
files = self._Capture(['diff', deps_revision, '--name-only']).split()
self._Run(['reset', '--hard', deps_revision], options) self._Run(['reset', '--hard', deps_revision], options)
self._Run(['clean', '-f', '-d'], options) self._Run(['clean', '-f', '-d'], options)
file_list.extend([os.path.join(self.checkout_path, f) for f in files])
def revinfo(self, options, args, file_list): if file_list is not None:
file_list.extend([os.path.join(self.checkout_path, f) for f in files])
def revinfo(self, _options, _args, _file_list):
"""Returns revision""" """Returns revision"""
return self._Capture(['rev-parse', 'HEAD']) return self._Capture(['rev-parse', 'HEAD'])
def runhooks(self, options, args, file_list): def runhooks(self, options, args, file_list):
self.status(options, args, file_list) self.status(options, args, file_list)
def status(self, options, args, file_list): def status(self, options, _args, file_list):
"""Display status information.""" """Display status information."""
if not os.path.isdir(self.checkout_path): if not os.path.isdir(self.checkout_path):
print(('\n________ couldn\'t run status in %s:\n' print(('\n________ couldn\'t run status in %s:\n'
...@@ -644,8 +648,9 @@ class GitWrapper(SCMWrapper): ...@@ -644,8 +648,9 @@ class GitWrapper(SCMWrapper):
else: else:
merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) merge_base = self._Capture(['merge-base', 'HEAD', 'origin'])
self._Run(['diff', '--name-status', merge_base], options) self._Run(['diff', '--name-status', merge_base], options)
files = self._Capture(['diff', '--name-only', merge_base]).split() if file_list is not None:
file_list.extend([os.path.join(self.checkout_path, f) for f in files]) files = self._Capture(['diff', '--name-only', merge_base]).split()
file_list.extend([os.path.join(self.checkout_path, f) for f in files])
def GetUsableRev(self, rev, options): def GetUsableRev(self, rev, options):
"""Finds a useful revision for this repository. """Finds a useful revision for this repository.
...@@ -830,7 +835,8 @@ class GitWrapper(SCMWrapper): ...@@ -830,7 +835,8 @@ class GitWrapper(SCMWrapper):
def _AttemptRebase(self, upstream, files, options, newbase=None, def _AttemptRebase(self, upstream, files, options, newbase=None,
branch=None, printed_path=False): branch=None, printed_path=False):
"""Attempt to rebase onto either upstream or, if specified, newbase.""" """Attempt to rebase onto either upstream or, if specified, newbase."""
files.extend(self._Capture(['diff', upstream, '--name-only']).split()) if files is not None:
files.extend(self._Capture(['diff', upstream, '--name-only']).split())
revision = upstream revision = upstream
if newbase: if newbase:
revision = newbase revision = newbase
...@@ -955,7 +961,7 @@ class GitWrapper(SCMWrapper): ...@@ -955,7 +961,7 @@ class GitWrapper(SCMWrapper):
'\tPlease commit, stash, or reset.\n' '\tPlease commit, stash, or reset.\n'
% (self.relpath, rev_str)) % (self.relpath, rev_str))
def _CheckDetachedHead(self, rev_str, options): def _CheckDetachedHead(self, rev_str, _options):
# HEAD is detached. Make sure it is safe to move away from (i.e., it is # HEAD is detached. Make sure it is safe to move away from (i.e., it is
# reference by a commit). If not, error out -- most likely a rebase is # reference by a commit). If not, error out -- most likely a rebase is
# in progress, try to detect so we can give a better error. # in progress, try to detect so we can give a better error.
...@@ -1057,18 +1063,18 @@ class SVNWrapper(SCMWrapper): ...@@ -1057,18 +1063,18 @@ class SVNWrapper(SCMWrapper):
os.path.join(self.checkout_path, '.')) os.path.join(self.checkout_path, '.'))
return date.strip() return date.strip()
def cleanup(self, options, args, file_list): def cleanup(self, options, args, _file_list):
"""Cleanup working copy.""" """Cleanup working copy."""
self._Run(['cleanup'] + args, options) self._Run(['cleanup'] + args, options)
def diff(self, options, args, file_list): def diff(self, options, args, _file_list):
# NOTE: This function does not currently modify file_list. # NOTE: This function does not currently modify file_list.
if not os.path.isdir(self.checkout_path): if not os.path.isdir(self.checkout_path):
raise gclient_utils.Error('Directory %s is not present.' % raise gclient_utils.Error('Directory %s is not present.' %
self.checkout_path) self.checkout_path)
self._Run(['diff'] + args, options) self._Run(['diff'] + args, options)
def pack(self, options, args, file_list): def pack(self, _options, args, _file_list):
"""Generates a patch file which can be applied to the root of the """Generates a patch file which can be applied to the root of the
repository.""" repository."""
if not os.path.isdir(self.checkout_path): if not os.path.isdir(self.checkout_path):
...@@ -1286,7 +1292,7 @@ class SVNWrapper(SCMWrapper): ...@@ -1286,7 +1292,7 @@ class SVNWrapper(SCMWrapper):
options.revision) options.revision)
self._Run(command, options, cwd=self._root_dir) self._Run(command, options, cwd=self._root_dir)
def revert(self, options, args, file_list): def revert(self, options, _args, file_list):
"""Reverts local modifications. Subversion specific. """Reverts local modifications. Subversion specific.
All reverted files will be appended to file_list, even if Subversion All reverted files will be appended to file_list, even if Subversion
...@@ -1318,7 +1324,8 @@ class SVNWrapper(SCMWrapper): ...@@ -1318,7 +1324,8 @@ class SVNWrapper(SCMWrapper):
return self.update(options, [], file_list) return self.update(options, [], file_list)
def printcb(file_status): def printcb(file_status):
file_list.append(file_status[1]) if file_list is not None:
file_list.append(file_status[1])
if logging.getLogger().isEnabledFor(logging.INFO): if logging.getLogger().isEnabledFor(logging.INFO):
logging.info('%s%s' % (file_status[0], file_status[1])) logging.info('%s%s' % (file_status[0], file_status[1]))
else: else:
...@@ -1340,7 +1347,7 @@ class SVNWrapper(SCMWrapper): ...@@ -1340,7 +1347,7 @@ class SVNWrapper(SCMWrapper):
# Maybe the directory disapeared meanwhile. Do not throw an exception. # Maybe the directory disapeared meanwhile. Do not throw an exception.
logging.error('Failed to update:\n%s' % str(e)) logging.error('Failed to update:\n%s' % str(e))
def revinfo(self, options, args, file_list): def revinfo(self, _options, _args, _file_list):
"""Display revision""" """Display revision"""
try: try:
return scm.SVN.CaptureRevision(self.checkout_path) return scm.SVN.CaptureRevision(self.checkout_path)
...@@ -1362,7 +1369,7 @@ class SVNWrapper(SCMWrapper): ...@@ -1362,7 +1369,7 @@ class SVNWrapper(SCMWrapper):
else: else:
self._RunAndGetFileList(command, options, file_list) self._RunAndGetFileList(command, options, file_list)
def GetUsableRev(self, rev, options): def GetUsableRev(self, rev, _options):
"""Verifies the validity of the revision for this repository.""" """Verifies the validity of the revision for this repository."""
if not scm.SVN.IsValidRevision(url='%s@%s' % (self.url, rev)): if not scm.SVN.IsValidRevision(url='%s@%s' % (self.url, rev)):
raise gclient_utils.Error( raise gclient_utils.Error(
......
...@@ -512,6 +512,9 @@ class SVN(object): ...@@ -512,6 +512,9 @@ class SVN(object):
Error: An error occurred while running the svn command. Error: An error occurred while running the svn command.
""" """
stdout = stdout or sys.stdout stdout = stdout or sys.stdout
if file_list is None:
# Even if our caller doesn't care about file_list, we use it internally.
file_list = []
# svn update and svn checkout use the same pattern: the first three columns # svn update and svn checkout use the same pattern: the first three columns
# are for file status, property status, and lock status. This is followed # are for file status, property status, and lock status. This is followed
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment