2 from __future__ import print_function
7 from subprocess import Popen, PIPE, check_output
10 def get_tagname_or_hash():
11 """return tagname if exists else hash"""
13 hash_cmd = ['git', 'rev-parse', '--short', 'HEAD']
14 hash_ = check_output(hash_cmd).decode('utf-8').strip()
17 tags_cmd = ['git', 'for-each-ref', '--points-at=HEAD', '--count=2', '--sort=-version:refname', '--format=%(refname:short)', 'refs/tags']
18 tags = check_output(tags_cmd).decode('utf-8').split()
21 return tags[0] + ('+' if len(tags) > 1 else '')
26 # Re-use method from https://github.com/magicmonty/bash-git-prompt to get stashs count
28 cmd = Popen(['git', 'rev-parse', '--git-dir'], stdout=PIPE, stderr=PIPE)
29 so, se = cmd.communicate()
30 stash_file = '%s%s' % (so.decode('utf-8').rstrip(), '/logs/refs/stash')
33 with open(stash_file) as f:
34 return sum(1 for _ in f)
39 # `git status --porcelain --branch` can collect all information
40 # branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind
41 po = Popen(['git', 'status', '--porcelain', '--branch'], env=dict(os.environ, LANG="C"), stdout=PIPE, stderr=PIPE)
42 stdout, sterr = po.communicate()
43 if po.returncode != 0:
44 sys.exit(0) # Not a git repository
46 # collect git status information
47 untracked, staged, changed, conflicts = [], [], [], []
49 status = [(line[0], line[1], line[2:]) for line in stdout.decode('utf-8').splitlines()]
51 if st[0] == '#' and st[1] == '#':
52 if re.search('Initial commit on', st[2]) or re.search('No commits yet on', st[2]):
53 branch = st[2].split(' ')[-1]
54 elif re.search('no branch', st[2]): # detached status
55 branch = get_tagname_or_hash()
56 elif len(st[2].strip().split('...')) == 1:
57 branch = st[2].strip()
59 # current and remote branch info
60 branch, rest = st[2].strip().split('...')
61 if len(rest.split(' ')) == 1:
62 # remote_branch = rest.split(' ')[0]
66 divergence = ' '.join(rest.split(' ')[1:])
67 divergence = divergence.lstrip('[').rstrip(']')
68 for div in divergence.split(', '):
70 ahead = int(div[len('ahead '):].strip())
72 behind = int(div[len('behind '):].strip())
73 elif st[0] == '?' and st[1] == '?':
84 if not changed and not staged and not conflicts and not untracked: