1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- #!/usr/bin/env python
- from __future__ import print_function
- import os
- import sys
- import re
- from subprocess import Popen, PIPE, check_output
- def get_tagname_or_hash():
- """return tagname if exists else hash"""
- # get hash
- hash_cmd = ['git', 'rev-parse', '--short', 'HEAD']
- hash_ = check_output(hash_cmd).strip()
- # get tagname
- tags_cmd = ['git', 'for-each-ref', '--points-at=HEAD', '--count=2', '--sort=-version:refname', '--format=%(refname:short)', 'refs/tags']
- tags = check_output(tags_cmd).split()
- if tags:
- return tags[0] + ('+' if len(tags) > 1 else '')
- elif hash_:
- return hash_
- return None
- # `git status --porcelain --branch` can collect all information
- # branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind
- po = Popen(['git', 'status', '--porcelain', '--branch'], env=dict(os.environ, LANG="C"), stdout=PIPE, stderr=PIPE)
- stdout, sterr = po.communicate()
- if po.returncode != 0:
- sys.exit(0) # Not a git repository
- # collect git status information
- untracked, staged, changed, conflicts = [], [], [], []
- ahead, behind = 0, 0
- status = [(line[0], line[1], line[2:]) for line in stdout.decode('utf-8').splitlines()]
- for st in status:
- if st[0] == '#' and st[1] == '#':
- if re.search('Initial commit on', st[2]) or re.search('No commits yet on', st[2]):
- branch = st[2].split(' ')[-1]
- elif re.search('no branch', st[2]): # detached status
- branch = get_tagname_or_hash()
- elif len(st[2].strip().split('...')) == 1:
- branch = st[2].strip()
- else:
- # current and remote branch info
- branch, rest = st[2].strip().split('...')
- if len(rest.split(' ')) == 1:
- # remote_branch = rest.split(' ')[0]
- pass
- else:
- # ahead or behind
- divergence = ' '.join(rest.split(' ')[1:])
- divergence = divergence.lstrip('[').rstrip(']')
- for div in divergence.split(', '):
- if 'ahead' in div:
- ahead = int(div[len('ahead '):].strip())
- elif 'behind' in div:
- behind = int(div[len('behind '):].strip())
- elif st[0] == '?' and st[1] == '?':
- untracked.append(st)
- else:
- if st[1] == 'M':
- changed.append(st)
- if st[0] == 'U':
- conflicts.append(st)
- elif st[0] != ' ':
- staged.append(st)
- out = ' '.join([
- branch,
- str(ahead),
- str(behind),
- str(len(staged)),
- str(len(conflicts)),
- str(len(changed)),
- str(len(untracked)),
- ])
- print(out, end='')
|