#!/usr/bin/env python # Attempt to show why a patch was rejected. # Adam Sampson import re, os def read(fn): f = open(fn) ls = f.readlines() f.close() return ls def write(fn, ls): f = open(fn, "w") f.write("".join(ls)) f.close() def parse_rej(rls): chunks = [] n = 0 while n != len(rls): if rls[n] != "***************\n": print "No stars line at", n return 1 n += 1 m = re.match(r'^\*\*\* (\d+),(\d+) \*\*\*.$', rls[n]) if m is None: print "No from line at", n return 1 fromstart = int(m.group(1)) fromend = int(m.group(2)) n += 1 count = (fromend - fromstart) + 1 fromlines = rls[n:n + count] n += count m = re.match(r'^--- (\d+),(\d+) ---.$', rls[n]) if m is None: print "No to line at", n, rls[n] return 1 tostart = int(m.group(1)) toend = int(m.group(2)) n += 1 count = (toend - tostart) + 1 tolines = rls[n:n + count] n += count chunks.append((fromstart, fromlines, tostart, tolines)) return chunks def num_matches(aas, bbs): if len(aas) != len(bbs): raise "num_matches needs two lists of the same length" count = 0 for i in range(len(aas)): if aas[i] == bbs[i]: count += 1 return count def main(argv): if len(argv) not in [2, 3]: print "Usage: whyrej []" return 1 fn = argv[1] if len(argv) == 3: rejn = argv[2] else: rejn = fn + ".rej" try: fls = read(fn) rls = read(rejn) except IOError: print "Error reading files", fn, "and", rejn return 1 for (fromstart, fromlines, tostart, tolines) in parse_rej(rls): origlines = [l[2:] for l in fromlines] n = len(origlines) best = 0 bestv = -1 for pos in range(len(fls) - n): nm = num_matches(origlines, fls[pos:pos + n]) if nm > bestv: (best, bestv) = (pos, nm) print "Chunk at", fromstart, "best fit at", best write("a.chunk", origlines) write("b.chunk", fls[best:best + n]) os.system("diff -u a.chunk b.chunk") os.unlink("a.chunk") os.unlink("b.chunk") if __name__ == "__main__": import sys sys.exit(main(sys.argv))