def git(self, cmd, extra_args=(), capture_stdout=False, capture_stderr=False, check=True, cwd=None): '''Helper for running a git command using metadata from a Project instance. :param cmd: git command as a string (or list of strings); all strings are formatted using self.format() before use. :param extra_args: sequence of additional arguments to pass to the git command (useful mostly if cmd is a string). :param capture_stdout: True if stdout should be captured into the returned object instead of being printed. :param capture_stderr: Like capture_stdout, but for stderr. Use with caution as it prevents error messages from being shown to the user. :param check: True if a subprocess.CalledProcessError should be raised if the git command finishes with a non-zero return code. :param cwd: directory to run command in (default: self.abspath) Returns a CompletedProcess (which is back-ported for Python 3.4).''' _warn_once_if_no_git() if isinstance(cmd, str): cmd_list = shlex.split(cmd) else: cmd_list = list(cmd) extra_args = list(extra_args) if cwd is None: cwd = self.abspath args = ['git'] + [self.format(arg) for arg in cmd_list] + extra_args cmd_str = util.quote_sh_list(args) log.dbg("running '{}'".format(cmd_str), 'in', cwd, level=log.VERBOSE_VERY) popen = subprocess.Popen( args, cwd=cwd, stdout=subprocess.PIPE if capture_stdout else None, stderr=subprocess.PIPE if capture_stderr else None) stdout, stderr = popen.communicate() dbg_msg = "'{}' in {} finished with exit status {}".format( cmd_str, cwd, popen.returncode) if capture_stdout: dbg_msg += " and wrote {} to stdout".format(stdout) if capture_stderr: dbg_msg += " and wrote {} to stderr".format(stderr) log.dbg(dbg_msg, level=log.VERBOSE_VERY) if check and popen.returncode: raise subprocess.CalledProcessError(popen.returncode, cmd_list, output=stdout, stderr=stderr) else: return CompletedProcess(popen.args, popen.returncode, stdout, stderr)