@ -1,26 +1,32 @@
#!/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
""" 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
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 ' : ' : ' }
__all__ = [ " Print " ]
import sys
import re
from subprocess import Popen , PIPE
__all__ = [ " Print " ]
try :
Print = eval ( " print " ) # python 3.0 case
except SyntaxError :
try :
D = dict ( )
try :
exec ( " from __future__ import print_function \n p=print " , D )
Print = D [ " p " ] # 2.6 case
del D
except SyntaxError :
del D
def Print ( * args , * * kwd ) : # 2.4, 2.5, define our own Print function
fout = kwd . get ( " file " , sys . stdout )
w = fout . write
@ -31,94 +37,103 @@ except SyntaxError:
w ( sep )
w ( str ( a ) )
w ( kwd . get ( " end " , " \n " ) )
finally :
del D
# change those symbols to whatever you prefer
symbols = { ' ahead of ' : ' ↑· ' , ' behind ' : ' ↓· ' , ' prehash ' : ' : ' }
from subprocess import Popen , PIPE
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 ( )
import sys
gitsym = Popen ( [ ' git ' , ' symbolic-ref ' , ' HEAD ' ] , stdout = PIPE , stderr = PIPE )
branch , error = gitsym . communicate ( )
error_string = error . decode ( ' utf-8 ' )
if ' fatal: Not a git repository ' in error_string :
sys . exit ( 0 )
branch = branch . decode ( ' utf-8 ' ) . strip ( ) [ 11 : ]
res , err = Popen ( [ ' git ' , ' diff ' , ' --name-status ' ] , stdout = PIPE , stderr = PIPE ) . communicate ( )
err_string = err . decode ( ' utf-8 ' )
if ' fatal ' in err_string :
sys . exit ( 0 )
changed_files = [ namestat [ 0 ] for namestat in res . splitlines ( ) ]
staged_files = [ namestat [ 0 ] for namestat in Popen ( [ ' git ' , ' diff ' , ' --staged ' , ' --name-status ' ] , stdout = PIPE ) . communicate ( ) [ 0 ] . splitlines ( ) ]
nb_changed = len ( changed_files ) - changed_files . count ( ' U ' )
nb_U = staged_files . count ( ' U ' )
nb_staged = len ( staged_files ) - nb_U
staged = str ( nb_staged )
conflicts = str ( nb_U )
changed = str ( nb_changed )
status_lines = Popen ( [ ' git ' , ' status ' , ' -s ' , ' -uall ' ] , stdout = PIPE ) . communicate ( ) [ 0 ] . splitlines ( )
untracked_lines = [ a for a in map ( lambda s : s . decode ( ' utf-8 ' ) , status_lines ) if a . startswith ( " ?? " ) ]
nb_untracked = len ( untracked_lines )
untracked = str ( nb_untracked )
stashes = Popen ( [ ' git ' , ' stash ' , ' list ' ] , stdout = PIPE ) . communicate ( ) [ 0 ] . splitlines ( )
nb_stashed = len ( stashes )
stashed = str ( nb_stashed )
if not nb_changed and not nb_staged and not nb_U and not nb_untracked and not nb_stashed :
clean = ' 1 '
if tag :
return tag
else :
clean = ' 0 '
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 ] )
remote = ' '
tag , tag_error = Popen ( [ ' git ' , ' describe ' , ' --exact-match ' ] , stdout = PIPE , stderr = PIPE ) . communicate ( )
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 ' )
if not branch : # not on any branch
if tag : # if we are on a tag, print the tag's name
branch = tag
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 branch ' , st [ 2 ] ) : # detached status
branch = get_tag_or_hash ( )
elif len ( st [ 2 ] . strip ( ) . split ( ' ... ' ) ) == 1 :
branch = st [ 2 ] . strip ( )
else :
branch = symbols [ ' prehash ' ] + Popen ( [ ' git ' , ' rev-parse ' , ' --short ' , ' HEAD ' ] , stdout = PIPE ) . communicate ( ) [ 0 ] . decode ( ' utf-8 ' ) [ : - 1 ]
# current and remote branch info
branch , rest = st [ 2 ] . strip ( ) . split ( ' ... ' )
if len ( rest . split ( ' ' ) ) == 1 :
# remote_branch = rest.split(' ')[0]
pass
else :
remote_name = Popen ( [ ' git ' , ' config ' , ' branch. %s .remote ' % branch ] , stdout = PIPE ) . communicate ( ) [ 0 ] . strip ( )
if remote_name :
merge_name = Popen ( [ ' git ' , ' config ' , ' branch. %s .merge ' % branch ] , stdout = PIPE ) . communicate ( ) [ 0 ] . strip ( )
# 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 :
remote_name = " origin "
merge_name = " refs/heads/ %s " % branch
if remote_name == ' . ' : # local
remote_ref = merge_name
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 :
remote_ref = ' refs/remotes/ %s / %s ' % ( remote_name , merge_name [ 11 : ] )
revgit = Popen ( [ ' git ' , ' rev-list ' , ' --left-right ' , ' %s ...HEAD ' % remote_ref ] , stdout = PIPE , stderr = PIPE )
revlist = revgit . communicate ( ) [ 0 ]
if revgit . poll ( ) : # fallback to local
revlist = Popen ( [ ' git ' , ' rev-list ' , ' --left-right ' , ' %s ...HEAD ' % merge_name ] , stdout = PIPE , stderr = PIPE ) . communicate ( ) [ 0 ]
behead = revlist . splitlines ( )
ahead = len ( [ x for x in behead if x [ 0 ] == ' > ' ] )
behind = len ( behead ) - ahead
if behind :
remote + = ' %s %s ' % ( symbols [ ' behind ' ] , behind )
if ahead :
remote + = ' %s %s ' % ( symbols [ ' ahead of ' ] , ahead )
clean = 0
if remote == " " :
remote = ' . '
out = ' \n ' . join ( [
str ( branch ) ,
str ( remote ) ,
staged ,
conflicts ,
changed ,
untracked ,
stashed ,
clean ] )
branch ,
remote . decode ( ' utf-8 ' ) ,
str ( len ( staged ) ) ,
str ( len ( conflicts ) ) ,
str ( len ( changed ) ) ,
str ( len ( untracked ) ) ,
str ( stashed ) ,
str ( clean )
] )
Print ( out )