4 # Read through a set of patches and see how many of them are fixes
7 # git log --decorate master..stable | stablefixes
9 # As with most gitdm stuff, this has been developed to the point where it
10 # solved the immediate task and no further. I hope it's useful, but can
13 # Copyright 2016 Eklektix, Inc.
14 # Copyright 2016 Jonathan Corbet <corbet@lwn.net>
16 # Redistributable under GPLv2
19 import sys, re, subprocess
30 # Track version tags as we go.
37 def AddVersion(commit, version):
38 PatchVersions[canonID(commit)] = version
39 def GetVersion(commit):
41 return PatchVersions[canonID(commit)]
46 # Patterns to snarf the info we're after.
47 # The {6,} in p_fixes is entirely to defend us against 8b9c6b28312cc,
48 # which reads "Fixes: 2.3.43".
50 p_fixes = re.compile(r'^\s+Fixes:\s+(commit\s+)?([0-9a-f]{6,}).*$')
51 p_revert = re.compile(r'This reverts commit ([0-9a-f]+)( +which is)?')
52 p_upstream = re.compile(r'commit ([0-9a-f]+) upstream', re.I)
53 p_upstream2 = re.compile(r'upstream commit ([0-9a-f]+)', re.I)
55 # Snarf the references to other patches.
57 def SaveFix(fixer, fixee):
58 if fixer not in Fixes:
61 if fixee not in FixMap[fixer]:
62 FixMap[fixer].append(fixee)
64 FixMap[fixer] = [ fixee ]
66 def FindRefs(commit, patch):
68 # Look for a straightforward Fixes: line.
70 for line in patch.taglines:
71 m = p_fixes.match(line)
73 SaveFix(commit, canonID(m.group(2)))
75 # Or perhaps this commit is a revert?
78 m = p_revert.search(patch.changelog)
80 SaveFix(commit, canonID(m.group(1)))
81 Reverts.append(commit)
84 # In any case keep track of upstream patch corresponding to this one. But be
85 # careful about "this reverts ... which is ... upstream"
88 m = p_upstream.search(patch.changelog) or p_upstream2.search(patch.changelog)
90 Ids.add(canonID(m.group(1)))
91 UpstreamMap[canonID(m.group(1))] = commit
93 UpstreamMissing.append(commit)
95 # What's the URL of a patch in the stable tree?
97 SBase = 'https://git.kernel.org/cgit/linux/kernel/git/stable/' + \
98 'linux-stable.git/commit?id='
106 # Go through the patch stream.
109 input = open(0, 'rb')
110 patch = gitlog.grabpatch(input)
115 commit = canonID(patch.commit)
117 AddVersion(commit, release)
118 FindRefs(commit, patch)
119 patch = gitlog.grabpatch(input)
121 TableHdr = '''<tr><th rowspan=2>Type</th>
122 <th colspan=2>Introduced</th>
123 <th colspan=2>Fixed</th></tr>
124 <tr><th>Release</th><th>Commit</th><th>Release</th><th>Commit</th></tr>
128 # Now see how many fixes have been seen before.
130 out = open('stable-fixes.html', 'w')
131 out.write('<!-- Found %d patches, %d fixes, %d reverts -->\n' % (Npatches, len(Fixes), len(Reverts)))
132 out.write('<!-- %d had no upstream reference -->\n' % (len(UpstreamMissing)))
133 out.write('<table class="OddEven">\n')
135 fixed_in_same = nfound = 0
137 # Go through all of the commit IDs we've seen (both stable and upstream)
138 # in reverse-time order.
140 def StablePatch(commit):
143 return UpstreamMap[commit]
150 buggy_different = set()
151 for i in range(0, len(Fixes)):
153 print('Checking %d/%d, found %d ' % (i, len(Fixes), nfound), end = '\r')
157 # We know we have a fix, but does it fix something that showed up in stable?
159 for fixed in FixMap[fix]:
160 fixed = StablePatch(fixed)
164 v_id = GetVersion(fixed)
165 v_fixer = GetVersion(fix)
169 out.write('<tr><td>%s</td><td>%s</td>\n'
170 '<td><a href="%s"><tt>%s</tt></a></td>\n'
172 '<td><a href="%s"><tt>%s</tt></a></td></tr>\n'
173 % (type, v_id, StableURL(fixed), trim(fixed),
174 v_fixer, StableURL(fix), trim(fix)))
178 buggy_different.add(fixed)
180 out.write('</table>')
181 out.write('<!-- Found %d/%d/%d refixes, %d in same release -->\n' % (nfound, len(buggy),
182 len(buggy_different),