Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 131 lines (109 sloc) 3.475 kB
660d0f0 @dustin Added my git tree convergence script.
dustin authored
1 #!/usr/bin/env python
2 """
3 Figure out where trees converge in branches when there may be no similar
4 ancestry.
5
6 Copyright (c) 2008 Dustin Sallings <dustin@spy.net>
7 """
8
9 from __future__ import with_statement
10
11 import sys
12 import difflib
13 import subprocess
14 import collections
15
16 trees={}
17 commit_map={}
18 commits={}
19
20 def load_list(branch):
21 t=[]
22 trees[branch] = t
23 cm = collections.defaultdict(list)
24 commit_map[branch] = cm
25
26 args = ['git', 'log', '--pretty=format:%T %h', branch]
27
28 sub=subprocess.Popen(args, stdout=subprocess.PIPE, close_fds=True)
29
30 for l in sub.stdout:
31 a=l.strip().split()
32 commit = a[-1]
33 treeHash = a[0]
34 t.append(treeHash)
35 cm[treeHash].append(commit)
36
37 def load_commits():
38 args = ['git', 'log', '--all',
39 '--pretty=format:%h%x00%an%x00%ae%x00%cn%x00%ce%x00%s']
40 sub=subprocess.Popen(args, stdout=subprocess.PIPE, close_fds=True)
41
42 for l in sub.stdout:
43 hash, an, ae, cn, ce, desc=l.strip().split("\0")
44 commits[hash] = (an, ae, cn, ce, desc)
45
46 def commit_info(h):
47 branch_a, ae, cn, ce, desc = commits[h]
48 if branch_a == cn:
49 ai = branch_a
50 else:
51 ai = "%s (committed by %s)" % (branch_a, cn)
52 cl = ('<a href="http://github.com/dustin/memcached/commit/%s">%s</a>'
53 % (h, h))
54 return "<div>%s: %s<br/>%s</div>" % (cl, ai, desc)
55
56 def htmlify_col_list(col):
57 if col:
58 return "\n".join((commit_info(c) for c in col))
59 else:
60 return "&nbsp;"
61
62 def mk_row(cls, l, r):
63 return ("<tr class='%s'><td class='left'>%s</td><td class='right'>%s</td></tr>" % (cls, l, r))
64
65 def emit_differing_lists(op, left_col, right_col):
66 print mk_row(op, htmlify_col_list(left_col), htmlify_col_list(right_col))
67
68 def emit_identical_lists(op, left_col, right_col):
69 for l,r in zip(left_col, right_col):
70 print mk_row(op, commit_info(l), commit_info(r))
71
72 if __name__ == '__main__':
73 branch_a, branch_b = sys.argv[1:]
74
75 load_commits()
76 load_list(branch_a)
77 load_list(branch_b)
78
79 print """<html>
80 <head>
81 <title>Tree Comparison from %(branch_a)s to %(branch_b)s</title>
82 <style type="text/css">
83 html {
84 font-family: verdana;
85 }
86 table tr, table td {
87 border: solid 1px;
88 vertical-align: top
89 }
90 .delete .left, .replace .left {
91 background: #faa;
92 color black;
93 }
94 .insert .right, .replace .right {
95 background: #afa;
96 color black;
97 }
98 table tr td div {
99 border: solid 1px;
100 padding: 0;
101 margin: 0;
102 }
103 </style>
104 </head>
105 <body>
106 <table>
107 <thead>
108 <tr>
109 <th>%(branch_a)s</th>
110 <th>%(branch_b)s</th>
111 </tr>
112 </thead>
113 <tbody>
114 """ % {'branch_a': branch_a, 'branch_b': branch_b}
115 a=trees[branch_a]
116 b=trees[branch_b]
117 sm = difflib.SequenceMatcher(a=a, b=b)
118 for op, i1, i2, j1, j2 in sm.get_opcodes():
119 left=a[i1:i2]
120 right=b[j1:j2]
121
122 left_col=[commit_map[branch_a][tree].pop() for tree in left]
123 right_col=[commit_map[branch_b][tree].pop() for tree in right]
124
125 if op == 'equal':
126 emit_identical_lists(op, left_col, right_col)
127 else:
128 emit_differing_lists(op, left_col, right_col)
129
130 print "</tbody></table></body></html>"
Something went wrong with that request. Please try again.