From 6d8115d009a9f58c7447eabe209aeb6d396d0245 Mon Sep 17 00:00:00 2001 From: "szager@chromium.org" Date: Wed, 23 Apr 2014 20:59:23 +0000 Subject: [PATCH] Eliminate all interactive terminal prompts from git. BUG= Review URL: https://codereview.chromium.org/247493002 git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@265735 0039d316-1c4b-4281-b951-d872f2087c98 --- gclient_scm.py | 18 ++++-------------- scm.py | 21 ++++++++++++++++++--- tests/gclient_scm_test.py | 16 ++++++++-------- tests/scm_unittest.py | 1 + 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/gclient_scm.py b/gclient_scm.py index e76ba9282f..491345e856 100644 --- a/gclient_scm.py +++ b/gclient_scm.py @@ -962,7 +962,8 @@ class GitWrapper(SCMWrapper): def _Capture(self, args, **kwargs): kwargs.setdefault('cwd', self.checkout_path) kwargs.setdefault('stderr', subprocess2.PIPE) - return subprocess2.check_output(['git'] + args, **kwargs).strip() + env = scm.GIT.ApplyEnvVars(kwargs) + return subprocess2.check_output(['git'] + args, env=env, **kwargs).strip() def _UpdateBranchHeads(self, options, fetch=False): """Adds, and optionally fetches, "branch-heads" refspecs if requested.""" @@ -983,22 +984,11 @@ class GitWrapper(SCMWrapper): kwargs.setdefault('stdout', self.out_fh) kwargs['filter_fn'] = self.filter kwargs.setdefault('print_stdout', False) - # Don't prompt for passwords; just fail quickly and noisily. - # By default, git will use an interactive terminal prompt when a username/ - # password is needed. That shouldn't happen in the chromium workflow, - # and if it does, then gclient may hide the prompt in the midst of a flood - # of terminal spew. The only indication that something has gone wrong - # will be when gclient hangs unresponsively. Instead, we disable the - # password prompt and simply allow git to fail noisily. The error - # message produced by git will be copied to gclient's output. - env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy()) - env.setdefault('GIT_ASKPASS', 'true') - env.setdefault('SSH_ASKPASS', 'true') - + env = scm.GIT.ApplyEnvVars(kwargs) cmd = ['git'] + args header = "running '%s' in '%s'" % (' '.join(cmd), cwd) self.filter(header) - return gclient_utils.CheckCallAndFilter(cmd, **kwargs) + return gclient_utils.CheckCallAndFilter(cmd, env=env, **kwargs) class SVNWrapper(SCMWrapper): diff --git a/scm.py b/scm.py index 4703e61b30..eb5c52403c 100644 --- a/scm.py +++ b/scm.py @@ -97,10 +97,25 @@ class GIT(object): current_version = None @staticmethod - def Capture(args, cwd, strip_out=True, **kwargs): - env = os.environ.copy() + def ApplyEnvVars(kwargs): + env = kwargs.pop('env', None) or os.environ.copy() + # Don't prompt for passwords; just fail quickly and noisily. + # By default, git will use an interactive terminal prompt when a username/ + # password is needed. That shouldn't happen in the chromium workflow, + # and if it does, then gclient may hide the prompt in the midst of a flood + # of terminal spew. The only indication that something has gone wrong + # will be when gclient hangs unresponsively. Instead, we disable the + # password prompt and simply allow git to fail noisily. The error + # message produced by git will be copied to gclient's output. + env.setdefault('GIT_ASKPASS', 'true') + env.setdefault('SSH_ASKPASS', 'true') # 'cat' is a magical git string that disables pagers on all platforms. - env['GIT_PAGER'] = 'cat' + env.setdefault('GIT_PAGER', 'cat') + return env + + @staticmethod + def Capture(args, cwd, strip_out=True, **kwargs): + env = GIT.ApplyEnvVars(kwargs) output = subprocess2.check_output( ['git'] + args, cwd=cwd, stderr=subprocess2.PIPE, env=env, **kwargs) diff --git a/tests/gclient_scm_test.py b/tests/gclient_scm_test.py index dbd94f0a7d..370e75f39e 100755 --- a/tests/gclient_scm_test.py +++ b/tests/gclient_scm_test.py @@ -1308,13 +1308,13 @@ class ManagedGitWrapperTestCaseMox(BaseTestCase): gclient_scm.GitWrapper._Clone('refs/remotes/origin/master', self.url, options) self.mox.StubOutWithMock(gclient_scm.subprocess2, 'check_output', True) - gclient_scm.subprocess2.check_output(['git', 'ls-files'], - cwd=self.base_path, - stderr=-1, - ).AndReturn('') + gclient_scm.subprocess2.check_output( + ['git', 'ls-files'], cwd=self.base_path, + env=gclient_scm.scm.GIT.ApplyEnvVars({}), stderr=-1,).AndReturn('') gclient_scm.subprocess2.check_output( ['git', 'rev-parse', '--verify', 'HEAD'], cwd=self.base_path, + env=gclient_scm.scm.GIT.ApplyEnvVars({}), stderr=-1, ).AndReturn('') @@ -1342,13 +1342,13 @@ class ManagedGitWrapperTestCaseMox(BaseTestCase): options) # pylint: disable=E1120 self.mox.StubOutWithMock(gclient_scm.subprocess2, 'check_output', True) - gclient_scm.subprocess2.check_output(['git', 'ls-files'], - cwd=self.base_path, - stderr=-1, - ).AndReturn('') + gclient_scm.subprocess2.check_output( + ['git', 'ls-files'], cwd=self.base_path, + env=gclient_scm.scm.GIT.ApplyEnvVars({}), stderr=-1,).AndReturn('') gclient_scm.subprocess2.check_output( ['git', 'rev-parse', '--verify', 'HEAD'], cwd=self.base_path, + env=gclient_scm.scm.GIT.ApplyEnvVars({}), stderr=-1, ).AndReturn('') diff --git a/tests/scm_unittest.py b/tests/scm_unittest.py index 3282e6aeb0..4e97c73eeb 100755 --- a/tests/scm_unittest.py +++ b/tests/scm_unittest.py @@ -73,6 +73,7 @@ class RootTestCase(BaseSCMTestCase): class GitWrapperTestCase(BaseSCMTestCase): def testMembersChanged(self): members = [ + 'ApplyEnvVars', 'AssertVersion', 'Capture', 'CaptureStatus',