|
4 | 4 | # change this symbol to whatever you prefer
|
5 | 5 | prehash = ':'
|
6 | 6 |
|
7 |
| -import subprocess |
8 |
| -from subprocess import Popen, PIPE |
9 |
| - |
10 | 7 | import sys
|
11 |
| -gitsym = Popen(['git', 'symbolic-ref', 'HEAD'], stdout=PIPE, stderr=PIPE) |
12 |
| -branch, error = gitsym.communicate() |
13 |
| - |
14 |
| -error_string = error.decode('utf-8') |
| 8 | +from subprocess import Popen, PIPE |
15 | 9 |
|
16 |
| -if 'fatal: Not a git repository' in error_string: |
17 |
| - sys.exit(0) |
18 | 10 |
|
19 |
| -branch = branch.decode("utf-8").strip()[11:] |
| 11 | +# `git status --porcelain -b` can collect all information |
| 12 | +# branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind |
| 13 | +po = Popen(['git', 'status', '--porcelain', '-b'], stdout=PIPE, stderr=PIPE) |
| 14 | +stdout, sterr = po.communicate() |
| 15 | +if po.returncode != 0: |
| 16 | + sys.exit(0) # Not a git repository |
20 | 17 |
|
21 |
| -# Get git status (staged, change, conflicts and untracked) |
22 |
| -try: |
23 |
| - res = subprocess.check_output(['git', 'status', '--porcelain']) |
24 |
| -except subprocess.CalledProcessError: |
25 |
| - sys.exit(0) |
26 |
| -status = [(st[0], st[1], st[2:]) for st in res.splitlines()] |
| 18 | +# collect git status information |
27 | 19 | untracked, staged, changed, conflicts = [], [], [], []
|
| 20 | +ahead, behind = 0, 0 |
| 21 | +status = [(line[0], line[1], line[2:]) for line in stdout.splitlines()] |
28 | 22 | for st in status:
|
29 |
| - if st[0] == '?' and st[1] == '?': |
| 23 | + if st[0] == '#' and st[1] == '#': |
| 24 | + if len(st[2].strip().split('...')) == 1: |
| 25 | + branch = st[2].strip() |
| 26 | + else: |
| 27 | + # current and remote branch info |
| 28 | + branch, rest = st[2].strip().split('...') |
| 29 | + if len(rest.split(' ')) == 1: |
| 30 | + # remote_branch = rest.split(' ')[0] |
| 31 | + pass |
| 32 | + else: |
| 33 | + # ahead or behind |
| 34 | + divergence = ' '.join(rest.split(' ')[1:]) |
| 35 | + divergence = divergence.lstrip('[').rstrip(']') |
| 36 | + for div in divergence.split(', '): |
| 37 | + if 'ahead' in div: |
| 38 | + ahead = int(div[len('ahead '):].strip()) |
| 39 | + elif 'behind' in div: |
| 40 | + behind = int(div[len('behind '):].strip()) |
| 41 | + elif st[0] == '?' and st[1] == '?': |
30 | 42 | untracked.append(st)
|
31 | 43 | else:
|
32 | 44 | if st[1] == 'M':
|
|
36 | 48 | elif st[0] != ' ':
|
37 | 49 | staged.append(st)
|
38 | 50 |
|
39 |
| -ahead, behind = 0,0 |
40 |
| - |
41 |
| -if not branch: # not on any branch |
42 |
| - branch = prehash + Popen(['git','rev-parse','--short','HEAD'], stdout=PIPE).communicate()[0].decode("utf-8")[:-1] |
43 |
| -else: |
44 |
| - remote_name = Popen(['git','config','branch.%s.remote' % branch], stdout=PIPE).communicate()[0].decode("utf-8").strip() |
45 |
| - if remote_name: |
46 |
| - merge_name = Popen(['git','config','branch.%s.merge' % branch], stdout=PIPE).communicate()[0].decode("utf-8").strip() |
47 |
| - if remote_name == '.': # local |
48 |
| - remote_ref = merge_name |
49 |
| - else: |
50 |
| - remote_ref = 'refs/remotes/%s/%s' % (remote_name, merge_name[11:]) |
51 |
| - revgit = Popen(['git', 'rev-list', '--left-right', '%s...HEAD' % remote_ref],stdout=PIPE, stderr=PIPE) |
52 |
| - revlist = revgit.communicate()[0] |
53 |
| - if revgit.poll(): # fallback to local |
54 |
| - revlist = Popen(['git', 'rev-list', '--left-right', '%s...HEAD' % merge_name],stdout=PIPE, stderr=PIPE).communicate()[0] |
55 |
| - behead = revlist.decode("utf-8").splitlines() |
56 |
| - ahead = len([x for x in behead if x[0]=='>']) |
57 |
| - behind = len(behead) - ahead |
58 |
| - |
59 | 51 | out = ' '.join([
|
60 | 52 | branch,
|
61 | 53 | str(ahead),
|
|
64 | 56 | str(len(conflicts)),
|
65 | 57 | str(len(changed)),
|
66 | 58 | str(len(untracked)),
|
67 |
| - ]) |
| 59 | +]) |
68 | 60 | print(out, end='')
|
69 | 61 |
|
0 commit comments