def execute_git(state, repo_git, args, capture=False, capture_stderr=False):
"""Executes a Git command in the given repository, with args being a list
of arguments (not including git itself). capture and capture_stderr
arguments causes it to return stdout or stdout+stderr as a string.
state can be None, but if so, then repo_git needs to be an absolute path.
The function automatically takes into account Git commands with side effects
and applies push simulation and dry run if those are enabled."""
is_push = (args[0] == "push")
is_change = (is_push
or (args[0] == "tag" and len(args) > 1)
or (args[0] == "branch" and len(args) > 1)
or (args[0] == "config" and args[1] != "-l")
or (args[0] == "checkout")
or (args[0] == "commit")
or (args[0] == "fetch")
or (args[0] == "init")
or (args[0] == "reset"))
if os.path.isabs(repo_git):
git_dir = repo_git
else:
git_dir = os.path.join(state['repo_dir'], repo_git)
if (not PUSH and is_push) or (DRY_RUN and is_change):
print("Would have executed: cd %s && git %s"
% (git_dir, " ".join(args)))
return None
fd = os.open(".", flags=os.O_RDONLY)
os.chdir(git_dir)
if capture_stderr:
stderr = subprocess.STDOUT
else:
stderr = None
try:
if capture:
output = subprocess.check_output(["git"] + args, stderr=stderr).decode().strip()
else:
output = None
subprocess.check_call(["git"] + args, stderr=stderr)
finally:
os.fchdir(fd)
os.close(fd)
return output