Mercurial > hg > gut
annotate gut/main.py @ 10:6884a771ed54
merge the master
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Wed, 21 Jul 2010 17:30:31 -0700 |
parents | b344537797de |
children | 67b04f3c5032 |
rev | line source |
---|---|
0
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
1 #!/usr/bin/env python |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
2 """ |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
3 a workflow for git |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
4 """ |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
5 |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
6 import os |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
7 import subprocess |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
8 import sys |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
9 |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
10 from command import CommandParser |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
11 |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
12 def call(command, **kw): |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
13 if isinstance(command, basestring): |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
14 kw['shell'] = True |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
15 output = kw.pop('output', True) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
16 if output or kw.pop('pipe', False): |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
17 kw['stdout'] = subprocess.PIPE |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
18 kw['stderr'] = subprocess.PIPE |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
19 check = kw.pop('check', True) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
20 process = subprocess.Popen(command, **kw) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
21 stdout, stderr = process.communicate() |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
22 code = process.poll() |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
23 if check and code: |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
24 if isinstance(command, basestring): |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
25 cmdstr = command |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
26 else: |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
27 cmdstr = ' '.join(command) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
28 raise SystemExit("Command `%s` exited with code %d" % (cmdstr, code)) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
29 if output: |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
30 print stdout |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
31 print stderr |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
32 return dict(stdout=stdout, stderr=stderr, code=code) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
33 |
2 | 34 def fake_call(command, **kw): |
35 if isinstance(command, basestring): | |
36 print command | |
37 else: | |
38 print ' '.join(command) | |
39 | |
0
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
40 class gut(object): |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
41 """ |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
42 a workflow for git |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
43 """ |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
44 |
6 | 45 def __init__(self, remote=None, simulate=False, branches=('master',)): |
2 | 46 """ |
47 - remote: name of the remote repository in .git/config | |
48 - simulate: print what calls will be used but don't run them | |
6 | 49 - branches: branches to apply to |
2 | 50 """ |
6 | 51 |
8 | 52 self.simulate = simulate |
53 | |
6 | 54 # sanity check |
7 | 55 try: |
56 self.root() | |
57 except SystemExit: | |
58 print "Not in a git repository" | |
59 sys.exit(1) | |
6 | 60 |
2 | 61 self.remote = remote |
6 | 62 self.branches = branches |
2 | 63 if simulate: |
64 globals()['call'] = fake_call | |
0
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
65 |
6 | 66 |
0
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
67 def update(self): |
6 | 68 """update the master""" |
69 branch = self.branch() | |
70 if self.simulate: | |
71 branch = '<branch>' | |
0
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
72 call(['git', 'checkout', 'master']) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
73 call(['git', 'pull', 'origin', 'master']) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
74 if self.remote: |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
75 call(['git', 'pull', self.remote, 'master']) |
6 | 76 call(['git', 'checkout', branch]) |
10 | 77 call(['git', 'merge', 'master']) |
0
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
78 |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
79 def feature(self, name): |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
80 """make a new feature branch""" |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
81 call(['git', 'checkout', 'master']) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
82 call(['git', 'checkout', '-b', name]) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
83 call(['git', 'push', 'origin', name]) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
84 |
6 | 85 def patch(self, output=None, logfile=None): |
86 """ | |
87 generate a patch for review | |
88 - output: name of patch | |
89 - logfile: name of file to output the log to [DEFAULT: stdout] | |
90 """ | |
91 self.update() | |
2 | 92 diff = call(['git', 'diff', 'master'], pipe=True, output=False) |
93 log = call(['git', 'log', 'master..'], pipe=True, output=False) | |
94 if self.simulate: | |
95 return | |
0
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
96 if not output: |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
97 output = self.branch() + '.diff' |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
98 diff = diff['stdout'] |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
99 log = log['stdout'] |
4
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
100 |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
101 # format the log |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
102 lines = [] |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
103 oldline = None |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
104 for line in log.splitlines(): |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
105 if not line: |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
106 continue |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
107 if line[0].strip(): |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
108 if oldline: |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
109 lines.append(oldline) |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
110 oldline = None |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
111 incomment = False |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
112 continue |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
113 line = line.strip() |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
114 if line.startswith('*'): |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
115 if oldline: |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
116 lines.append(oldline) |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
117 oldline = None |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
118 lines.append(line[1:].strip()) |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
119 continue |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
120 if oldline: |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
121 oldline = oldline + ' ' + line |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
122 else: |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
123 oldline = line |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
124 else: |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
125 if oldline: |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
126 lines.append(oldline) |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
127 log = '\n\n'.join(['* %s' % line for line in lines]) |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
128 |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
129 f = file(output, 'w') # write the output to a patch file |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
130 print >> f, diff |
190ce22e7e83
scour the log and format it like a civilized human being
Jeff Hammel <jhammel@mozilla.com>
parents:
3
diff
changeset
|
131 f.close() |
6 | 132 |
133 # output the log | |
134 if logfile: | |
135 f = file(logfile, 'w') # write the log to a file | |
136 print >> f, log | |
137 else: | |
138 return log | |
139 | |
140 def apply(self): | |
141 """ | |
142 apply the existing feature branch to master as a patch | |
143 """ | |
144 | |
145 # sanity check | |
146 branch = self.branch() | |
8 | 147 if self.simulate: |
148 branch = '<branch>' | |
6 | 149 assert branch != 'master', "Can't apply master to itself!" |
150 assert self.branches, "No branches defined!" | |
151 | |
152 # get the patch | |
153 self.patch(branch + '.diff', branch + '.log') | |
154 diff = os.path.abspath(branch + '.diff') | |
155 log = os.path.abspath(branch + '.log') | |
156 | |
157 # apply the patch | |
8 | 158 if not self.simulate: |
159 cwd = os.getcwd() | |
160 os.chdir(self.root()) | |
6 | 161 for b in self.branches: |
162 call(['git', 'checkout', b]) | |
9
b344537797de
when passing a string, should not be in a list
Jeff Hammel <jhammel@mozilla.com>
parents:
8
diff
changeset
|
163 call('patch -p1 < %s' % diff) |
6 | 164 call(['git', 'commit', '-a', '-F', log]) |
165 call(['git', 'push', 'origin', b]) | |
166 if self.remote: | |
167 call(['git', 'push', self.remote, b]) | |
168 | |
169 # cleanup | |
170 call(['git', 'checkout', branch]) | |
8 | 171 if not self.simulate: |
172 os.chdir(cwd) | |
0
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
173 |
7 | 174 def delete(self): |
175 """delete the current feature branch""" | |
176 # sanity check | |
177 branch = self.branch() | |
178 assert branch != 'master', "You can't delete the master!" | |
179 call(['git', 'checkout', 'master']) | |
180 call(['git', '-D', branch]) | |
181 | |
0
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
182 def branch(self): |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
183 """print what branch you're on""" |
3 | 184 output = call(['git', 'branch'], output=False, pipe=True) |
2 | 185 if self.simulate: |
6 | 186 return |
0
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
187 for line in output['stdout'].splitlines(): |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
188 if line.startswith('*'): |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
189 return line[1:].strip() |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
190 |
6 | 191 def root(self): |
192 """return (relative) root location of repository""" | |
8 | 193 |
194 if self.simulate: | |
195 return '<root>' | |
6 | 196 output = call(['git', 'rev-parse', '--show-cdup'], output=False, pipe=True) |
197 location = output['stdout'].strip() | |
198 if not location: | |
199 return '.' | |
200 return location | |
201 | |
0
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
202 def main(args=sys.argv[1:]): |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
203 parser = CommandParser(gut) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
204 parser.invoke(args) |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
205 |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
206 if __name__ == '__main__': |
9688c72a93c3
initial commit of gut, probably doesnt actually work
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
207 main() |