diff --git a/git_auto_svn.py b/git_auto_svn.py index 722029c9d..88d970b36 100755 --- a/git_auto_svn.py +++ b/git_auto_svn.py @@ -21,7 +21,7 @@ import urlparse import subprocess2 from git_common import run as run_git -from git_common import run_stream as run_git_stream +from git_common import run_stream_with_retcode as run_git_stream_with_retcode from git_common import set_config, root, ROOT from git_footers import get_footer_svn_id @@ -90,8 +90,9 @@ def main(argv): set_config('svn-remote.svn.fetch', '%s:refs/remotes/%s' % (svn_path, upstream)) print 'Configured metadata, running "git svn fetch". This may take some time.' - for line in run_git_stream('svn', 'fetch').xreadlines(): - print line.strip() + with run_git_stream_with_retcode('svn', 'fetch') as stdout: + for line in stdout.xreadlines(): + print line.strip() return 0 diff --git a/git_common.py b/git_common.py index a01f8e569..2df493663 100644 --- a/git_common.py +++ b/git_common.py @@ -565,6 +565,28 @@ def run_stream(*cmd, **kwargs): return proc.stdout +@contextlib.contextmanager +def run_stream_with_retcode(*cmd, **kwargs): + """Runs a git command as context manager yielding stdout as a PIPE. + + stderr is dropped to avoid races if the process outputs to both stdout and + stderr. + + Raises subprocess2.CalledProcessError on nonzero return code. + """ + kwargs.setdefault('stderr', subprocess2.VOID) + kwargs.setdefault('stdout', subprocess2.PIPE) + cmd = (GIT_EXE, '-c', 'color.ui=never') + cmd + try: + proc = subprocess2.Popen(cmd, **kwargs) + yield proc.stdout + finally: + retcode = proc.wait() + if retcode != 0: + raise subprocess2.CalledProcessError(retcode, cmd, os.getcwd(), + None, None) + + def run_with_stderr(*cmd, **kwargs): """Runs a git command. diff --git a/tests/git_common_test.py b/tests/git_common_test.py index 5c6febe0d..ff5348c19 100755 --- a/tests/git_common_test.py +++ b/tests/git_common_test.py @@ -221,6 +221,24 @@ class GitReadOnlyFunctionsTest(git_test_utils.GitRepoReadOnlyTestBase, self.repo.run(testfn) + def testStreamWithRetcode(self): + items = set(self.repo.commit_map.itervalues()) + + def testfn(): + with self.gc.run_stream_with_retcode('log', '--format=%H') as stdout: + for line in stdout.xreadlines(): + line = line.strip() + self.assertIn(line, items) + items.remove(line) + + self.repo.run(testfn) + + def testStreamWithRetcodeException(self): + import subprocess2 + with self.assertRaises(subprocess2.CalledProcessError): + with self.gc.run_stream_with_retcode('checkout', 'unknown-branch'): + pass + def testCurrentBranch(self): def cur_branch_out_of_git(): os.chdir('..')