123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- #!/usr/bin/env python
- # -*- coding: UTF-8 -*-
- """This module defines a Print function to use with python 2.x or 3.x., so we can use the prompt with older versions of
- Python too
- It's interface is that of python 3.0's print. See
- http://docs.python.org/3.0/library/functions.html?highlight=print#print
- Shamelessly ripped from
- http://www.daniweb.com/software-development/python/code/217214/a-print-function-for-different-versions-of-python
- """
- # change those symbols to whatever you prefer
- symbols = {'ahead of': '↑·', 'behind': '↓·', 'prehash': ':'}
- import sys
- import re
- from subprocess import Popen, PIPE
- __all__ = ["Print"]
- try:
- Print = eval("print") # python 3.0 case
- python_version = 3
- to_str = str
- except SyntaxError as e:
- python_version = 2
- to_str = unicode
- D = dict()
- try:
- exec ("from __future__ import print_function\np=print", D)
- Print = D["p"] # 2.6 case
- except SyntaxError:
- def Print(*args, **kwd): # 2.4, 2.5, define our own Print function
- fout = kwd.get("file", sys.stdout)
- w = fout.write
- if args:
- w(str(args[0]))
- sep = kwd.get("sep", " ")
- for a in args[1:]:
- w(sep)
- w(str(a))
- w(kwd.get("end", "\n"))
- finally:
- del D
- def get_tag_or_hash():
- cmd = Popen(['git', 'describe', '--exact-match'], stdout=PIPE, stderr=PIPE)
- so, se = cmd.communicate()
- tag = '%s' % so.decode('utf-8').strip()
- if tag:
- return tag
- else:
- cmd = Popen(['git', 'rev-parse', '--short', 'HEAD'], stdout=PIPE, stderr=PIPE)
- so, se = cmd.communicate()
- hash_name = '%s' % so.decode('utf-8').strip()
- return ''.join([symbols['prehash'], hash_name])
- def get_stash():
- cmd = Popen(['git', 'rev-parse', '--git-dir'], stdout=PIPE, stderr=PIPE)
- so, se = cmd.communicate()
- stash_file = '%s%s' % (so.decode('utf-8').rstrip(), '/logs/refs/stash')
- try:
- with open(stash_file) as f:
- return sum(1 for _ in f)
- except IOError:
- return 0
- # `git status --porcelain --branch` can collect all information
- # branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind
- po = Popen(['git', 'status', '--porcelain', '--branch'], env={'LC_ALL': 'C'}, stdout=PIPE, stderr=PIPE)
- stdout, stderr = po.communicate()
- if po.returncode != 0:
- sys.exit(0) # Not a git repository
- # collect git status information
- untracked, staged, changed, conflicts = [], [], [], []
- num_ahead, num_behind = 0, 0
- ahead, behind = '', ''
- branch = ''
- remote = ''
- 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]):
- branch = st[2].split(' ')[-1]
- elif re.search('No commits yet on', st[2]):
- branch = st[2].split(' ')[-1]
- elif re.search('no branch', st[2]): # detached status
- branch = get_tag_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:
- num_ahead = int(div[len('ahead '):].strip())
- ahead = '%s%s' % (symbols['ahead of'], num_ahead)
- elif 'behind' in div:
- num_behind = int(div[len('behind '):].strip())
- behind = '%s%s' % (symbols['behind'], num_behind)
- remote = ''.join([behind, ahead])
- 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)
- stashed = get_stash()
- if not changed and not staged and not conflicts and not untracked and not stashed:
- clean = 1
- else:
- clean = 0
- if remote == "":
- remote = '.'
- if python_version == 2:
- remote = remote.decode('utf-8')
- out = '\n'.join([
- branch,
- remote,
- to_str(len(staged)),
- to_str(len(conflicts)),
- to_str(len(changed)),
- to_str(len(untracked)),
- to_str(stashed),
- to_str(clean),
- to_str(python_version),
- ])
- if python_version == 2:
- Print(out.encode('utf-8'))
- else:
- Print(out)
|