1""" 2Git SCM backend for Digress. 3""" 4 5from subprocess import Popen, PIPE, STDOUT 6import re 7 8from digress.errors import SCMError 9 10GIT_BRANCH_EXPR = re.compile("[*] (.*)") 11 12def checkout(revision): 13 """ 14 Checkout a revision from git. 15 """ 16 proc = Popen([ 17 "git", 18 "checkout", 19 "-f", 20 revision 21 ], stdout=PIPE, stderr=STDOUT) 22 23 output = proc.communicate()[0].strip() 24 if proc.returncode != 0: 25 raise SCMError("checkout error: %s" % output) 26 27def rev_parse(ref): 28 proc = Popen([ 29 "git", 30 "rev-parse", 31 ref 32 ], stdout=PIPE, stderr=STDOUT) 33 34 output = proc.communicate()[0].strip() 35 if proc.returncode != 0: 36 raise SCMError("rev-parse error: %s" % output) 37 return output 38 39def current_rev(): 40 """ 41 Get the current revision. 42 """ 43 return rev_parse("HEAD") 44 45def current_branch(): 46 """ 47 Get the current branch. 48 """ 49 proc = Popen([ 50 "git", 51 "branch", 52 "--no-color" 53 ], stdout=PIPE, stderr=STDOUT) 54 55 output = proc.communicate()[0].strip() 56 if proc.returncode != 0: 57 raise SCMError("branch error: %s" % output) 58 branch_name = GIT_BRANCH_EXPR.findall(output)[0] 59 return branch_name != "(no branch)" and branch_name or None 60 61def revisions(rev_a, rev_b): 62 """ 63 Get a list of revisions from one to another. 64 """ 65 proc = Popen([ 66 "git", 67 "log", 68 "--format=%H", ("%s...%s" % (rev_a, rev_b)) 69 ], stdout=PIPE, stderr=STDOUT) 70 71 output = proc.communicate()[0].strip() 72 if proc.returncode != 0: 73 raise SCMError("log error: %s" % output) 74 return output.split("\n") 75 76def stash(): 77 """ 78 Stash the repository. 79 """ 80 proc = Popen([ 81 "git", 82 "stash", 83 "save", 84 "--keep-index" 85 ], stdout=PIPE, stderr=STDOUT) 86 87 output = proc.communicate()[0].strip() 88 if proc.returncode != 0: 89 raise SCMError("stash error: %s" % output) 90 91def unstash(): 92 """ 93 Unstash the repository. 94 """ 95 proc = Popen(["git", "stash", "pop"], stdout=PIPE, stderr=STDOUT) 96 proc.communicate() 97 98def bisect(*args): 99 """ 100 Perform a bisection. 101 """ 102 proc = Popen((["git", "bisect"] + list(args)), stdout=PIPE, stderr=STDOUT) 103 output = proc.communicate()[0] 104 if proc.returncode != 0: 105 raise SCMError("bisect error: %s" % output) 106 return output 107 108def dirty(): 109 """ 110 Check if the working tree is dirty. 111 """ 112 proc = Popen(["git", "status"], stdout=PIPE, stderr=STDOUT) 113 output = proc.communicate()[0].strip() 114 if proc.returncode != 0: 115 raise SCMError("status error: %s" % output) 116 if "modified:" in output: 117 return True 118 else: 119 return False 120