From 231f5eab452736872441a33024d484d207b20fbb Mon Sep 17 00:00:00 2001 From: Edward Lemur Date: Wed, 31 Jan 2018 19:02:36 +0100 Subject: [PATCH] Print git output when cloning a repo. This will allow us to show the progress when cloning a new repo when running commands like gclient sync. R=agable@chromium.org Bug: 722686 Change-Id: I268cba343ea4c3c024292c9341d5009aa112b184 Reviewed-on: https://chromium-review.googlesource.com/890524 Commit-Queue: Edward Lesmes Reviewed-by: Aaron Gable --- gclient.py | 9 +++++++-- gclient_scm.py | 12 ++++++++++-- gclient_utils.py | 16 ++++++++++++++++ tests/gclient_smoketest.py | 15 +++++++++------ 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/gclient.py b/gclient.py index 96c2ab3df5..814bf59922 100755 --- a/gclient.py +++ b/gclient.py @@ -356,7 +356,7 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): def __init__(self, parent, name, raw_url, url, managed, custom_deps, custom_vars, custom_hooks, deps_file, should_process, - relative, condition, condition_value): + relative, condition, condition_value, print_outbuf=False): gclient_utils.WorkItem.__init__(self, name) DependencySettings.__init__( self, parent, raw_url, url, managed, custom_deps, custom_vars, @@ -420,6 +420,10 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): # or just https://blah. The @123 portion is irrelevant. self.resources.append(url.split('@')[0]) + # Controls whether we want to print git's output when we first clone the + # dependency + self.print_outbuf = print_outbuf + if not self.name and self.parent: raise gclient_utils.Error('Dependency without name') @@ -1046,7 +1050,7 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): scm_class = SCM_MAP[scm_name] if not scm_class.BinaryExists(): raise gclient_utils.Error('%s command not found' % scm_name) - return scm_class(url, root_dir, relpath, out_fh, out_cb) + return scm_class(url, root_dir, relpath, out_fh, out_cb, self.print_outbuf) def HasGNArgsFile(self): return self._gn_args_file is not None @@ -1433,6 +1437,7 @@ it or fix the checkout. True, None, None, + True, True)) except KeyError: raise gclient_utils.Error('Invalid .gclient file. Solution is ' diff --git a/gclient_scm.py b/gclient_scm.py index 50cfd79776..80470ad57b 100644 --- a/gclient_scm.py +++ b/gclient_scm.py @@ -94,7 +94,7 @@ class SCMWrapper(object): """ def __init__(self, url=None, root_dir=None, relpath=None, out_fh=None, - out_cb=None): + out_cb=None, print_outbuf=False): self.url = url self._root_dir = root_dir if self._root_dir: @@ -108,6 +108,7 @@ class SCMWrapper(object): out_fh = sys.stdout self.out_fh = out_fh self.out_cb = out_cb + self.print_outbuf = print_outbuf def Print(self, *args, **kwargs): kwargs.setdefault('file', self.out_fh) @@ -896,7 +897,14 @@ class GitWrapper(SCMWrapper): dir=parent_dir) try: clone_cmd.append(tmp_dir) - self._Run(clone_cmd, options, cwd=self._root_dir, retry=True) + if self.print_outbuf: + print_stdout = True + stdout = gclient_utils.WriteToStdout(self.out_fh) + else: + print_stdout = False + stdout = self.out_fh + self._Run(clone_cmd, options, cwd=self._root_dir, retry=True, + print_stdout=print_stdout, stdout=stdout) gclient_utils.safe_makedirs(self.checkout_path) gclient_utils.safe_rename(os.path.join(tmp_dir, '.git'), os.path.join(self.checkout_path, '.git')) diff --git a/gclient_utils.py b/gclient_utils.py index 23b9dd7d66..b679169350 100644 --- a/gclient_utils.py +++ b/gclient_utils.py @@ -325,6 +325,22 @@ class Wrapper(object): return getattr(self._wrapped, name) +class WriteToStdout(Wrapper): + """Creates a file object clone to also print to sys.stdout.""" + def __init__(self, wrapped): + super(WriteToStdout, self).__init__(wrapped) + if not hasattr(self, 'lock'): + self.lock = threading.Lock() + + def write(self, out, *args, **kwargs): + self._wrapped.write(out, *args, **kwargs) + self.lock.acquire() + try: + sys.stdout.write(out, *args, **kwargs) + finally: + self.lock.release() + + class AutoFlush(Wrapper): """Creates a file object clone to automatically flush after N seconds.""" def __init__(self, wrapped, delay): diff --git a/tests/gclient_smoketest.py b/tests/gclient_smoketest.py index 40efe0244d..ebfbb4f689 100755 --- a/tests/gclient_smoketest.py +++ b/tests/gclient_smoketest.py @@ -318,7 +318,7 @@ class GClientSmokeGIT(GClientSmokeBase): # Test unversioned checkout. self.parseGclient( ['sync', '--deps', 'mac', '--jobs', '1'], - ['running', 'running']) + ['running', 'running', 'running']) # TODO(maruel): http://crosbug.com/3582 hooks run even if not matching, must # add sync parsing to get the list of updated files. tree = self.mangle_git_tree(('repo_1@2', 'src'), @@ -383,7 +383,7 @@ class GClientSmokeGIT(GClientSmokeBase): self.parseGclient( ['sync', '--deps', 'mac', '--jobs', '1', '--revision', 'invalid@' + self.githash('repo_1', 1)], - ['running', 'running'], + ['running', 'running', 'running'], 'Please fix your script, having invalid --revision flags ' 'will soon considered an error.\n') tree = self.mangle_git_tree(('repo_1@2', 'src'), @@ -401,7 +401,7 @@ class GClientSmokeGIT(GClientSmokeBase): self.parseGclient( ['sync', '--deps', 'mac', '--jobs', '1', '--revision', self.githash('repo_1', 1)], - []) + ['running']) tree = self.mangle_git_tree(('repo_1@1', 'src'), ('repo_2@2', 'src/repo2'), ('repo_3@1', 'src/repo2/repo3'), @@ -424,7 +424,7 @@ class GClientSmokeGIT(GClientSmokeBase): # Test unversioned checkout. self.parseGclient( ['sync', '--deps', 'mac', '--jobs', '8'], - ['running', 'running'], + ['running', 'running', 'running'], untangle=True) # TODO(maruel): http://crosbug.com/3582 hooks run even if not matching, must # add sync parsing to get the list of updated files. @@ -554,13 +554,15 @@ class GClientSmokeGIT(GClientSmokeBase): return self.gclient(['config', self.git_base + 'repo_5', '--name', 'src']) expectation = [ + ('running', self.root_dir), # git clone ('running', self.root_dir), # pre-deps hook ] out = self.parseGclient(['sync', '--deps', 'mac', '--jobs=1', '--revision', 'src@' + self.githash('repo_5', 2)], expectation) - self.assertEquals(2, len(out[0])) - self.assertEquals('pre-deps hook', out[0][1]) + self.assertEquals('Cloning into ', out[0][1][:13]) + self.assertEquals(2, len(out[1])) + self.assertEquals('pre-deps hook', out[1][1]) tree = self.mangle_git_tree(('repo_5@2', 'src'), ('repo_1@2', 'src/repo1'), ('repo_2@1', 'src/repo2') @@ -604,6 +606,7 @@ class GClientSmokeGIT(GClientSmokeBase): return self.gclient(['config', self.git_base + 'repo_5', '--name', 'src']) expectated_stdout = [ + ('running', self.root_dir), # git clone ('running', self.root_dir), # pre-deps hook ('running', self.root_dir), # pre-deps hook (fails) ]