blob: f514e63846c501f3ba0a7d38ef831e7d5d1095b2 [file] [log] [blame]
#!/usr/bin/env python
import argparse
import subprocess
import sys
def call_process(*args, **kwargs):
_result = subprocess.check_output(*args, **kwargs)
return _result.decode("utf-8") if sys.version_info.major > 2 else _result
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("--git-dir", default="/srv/salt/reclass")
parser.add_argument("--remote", default="")
parser.add_argument("--branch")
return parser.parse_args()
CHANGES_FORMAT = '''reclass_staged_changes,directory={dir} value={staged}
reclass_unstaged_changes,directory={dir} value={unstaged}'''
if __name__ == "__main__":
args = parse_args()
git_dir = args.git_dir.strip()
staged, unstaged = [], []
for file_status in call_process(
str.split('git status --porcelain'), cwd=git_dir
).splitlines():
if file_status[0] not in (' ', '?'):
staged.append(file_status[3:].strip())
if file_status[1] != ' ':
unstaged.append(file_status[3:].strip())
print(CHANGES_FORMAT.format(
dir=git_dir, staged=len(staged), unstaged=len(unstaged)
))
# if no branch provided, default to current local branch
if not args.branch:
args.branch = call_process(str.split(
'git rev-parse --abbrev-ref HEAD'
), cwd=git_dir).strip().lstrip('heads/') # branch and tag share name
if args.branch == 'HEAD': # detached head, any assumption is bad
args.branch = 'master'
local_branch = args.branch.strip()
# remote handling
remotes = call_process(str.split('git remote show'), cwd=git_dir).splitlines()
remote_ref = '{}/{}'.format(args.remote.strip() or 'origin', local_branch)
# if no remote provided, try figuring out upstream tracking branch
if not args.remote:
upstream_ref = call_process(str.split(
'git for-each-ref --format=%(upstream:short) refs/heads/{}'.format(local_branch)
), cwd=git_dir).strip()
if upstream_ref and upstream_ref.split('/')[0] in remotes:
args.remote = upstream_ref.split('/')[0] # breaks on remotes with slashes
remote_ref = upstream_ref
else:
args.remote = 'origin'
if args.remote.strip() in remotes:
known_refs = call_process(str.split(
'git for-each-ref --format=%(refname:short)'
), cwd=git_dir).splitlines()
if all([ # check whether we have the local and remote branch with the same name
local_branch in known_refs,
remote_ref in known_refs
]):
# 0 if local branch is synced with remote, 1 otherwise
print('reclass_remote_desync,directory={dir} value={val}'.format(
dir=git_dir, val=int(bool(call_process(
str.split("git diff {local_ref}..{remote_ref}".format(
local_ref=local_branch, remote_ref=remote_ref
)), cwd=git_dir
)))
))