Index: infra/libs/git2/util.py |
diff --git a/infra/libs/git2/util.py b/infra/libs/git2/util.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a756c3a7e45d02a3cde748bad94aaa7f7cd72d94 |
--- /dev/null |
+++ b/infra/libs/git2/util.py |
@@ -0,0 +1,59 @@ |
+# Copyright 2014 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+from cStringIO import StringIO |
+ |
+ |
+class _Invalid(object): |
+ def __call__(self, *_args, **_kwargs): |
+ return self |
+ |
+ def __getattr__(self, _key): |
+ return self |
+ |
+ def __eq__(self, _other): |
+ return False |
+ |
+ def __ne__(self, _other): # pylint: disable=R0201 |
+ return True |
+ |
+INVALID = _Invalid() |
+ |
+ |
+class CalledProcessError(Exception): |
+ """Almost like subprocess.CalledProcessError, but also captures stderr, |
+ and gives prettier error messages. |
+ """ |
+ def __init__(self, returncode, cmd, stdout, stderr): |
+ super(CalledProcessError, self).__init__() |
+ self.returncode = returncode |
+ self.cmd = cmd |
+ self.stdout = stdout |
+ self.stderr = stderr |
+ |
+ def __str__(self): |
+ msg = StringIO() |
+ |
+ suffix = ':' if self.stderr or self.stdout else '.' |
+ print >> msg, ( |
+ "Command %r returned non-zero exit status %d%s" |
+ % (self.cmd, self.returncode, suffix) |
+ ) |
+ |
+ def indent_data(banner, data): |
+ print >> msg, banner, '=' * 40 |
+ msg.writelines(' ' + l for l in data.splitlines(True)) |
+ |
+ if self.stdout: |
+ indent_data('STDOUT', self.stdout) |
+ |
+ if self.stderr: |
+ if self.stdout: |
+ print >> msg |
+ indent_data('STDERR', self.stderr) |
+ |
+ r = msg.getvalue() |
+ if r[-1] != '\n': |
+ r += '\n' |
+ return r |
+ |