Make git auto-svn fail if git svn fetch fails.

R=agable@chromium.org
BUG=437397

Review URL: https://codereview.chromium.org/1150353003

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@295630 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/git_auto_svn.py b/git_auto_svn.py
index 722029c..88d970b 100755
--- a/git_auto_svn.py
+++ b/git_auto_svn.py
@@ -21,7 +21,7 @@
 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 @@
   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 a01f8e5..2df4936 100644
--- a/git_common.py
+++ b/git_common.py
@@ -565,6 +565,28 @@
   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 5c6febe..ff5348c 100755
--- a/tests/git_common_test.py
+++ b/tests/git_common_test.py
@@ -221,6 +221,24 @@
 
     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('..')