def get_diff_sections(self): yield "Complete Diff", None, ''.join(self.patch) # allow_dirty was added to parse_patches in bzrlib 2.2b1 if 'allow_dirty' in inspect.getargspec(parse_patches).args: patches = parse_patches(self.patch, allow_dirty=self.allow_dirty) else: patches = parse_patches(self.patch) for patch in patches: oldname = patch.oldname.split('\t')[0] newname = patch.newname.split('\t')[0] yield oldname, newname, str(patch)
def test_parse_patches_leading_noise(self): # https://bugs.launchpad.net/bzr/+bug/502076 # https://code.launchpad.net/~toshio/bzr/allow-dirty-patches/+merge/18854 lines = ["diff -pruN commands.py", "--- orig/commands.py", "+++ mod/dommands.py"] bits = parse_patches(iter(lines), allow_dirty=True)
def testParsePatches(self): """Make sure file names can be extracted from tricky unified diffs""" patchtext = \ """--- orig-7 +++ mod-7 @@ -1,10 +1,10 @@ -- a --- b +++ c xx d xx e ++ f -++ g +-- h xx i xx j -- k --- l +++ m --- orig-8 +++ mod-8 @@ -1 +1 @@ --- A +++ B @@ -1 +1 @@ --- C +++ D """ filenames = [('orig-7', 'mod-7'), ('orig-8', 'mod-8')] patches = parse_patches(patchtext.splitlines(True)) patch_files = [] for patch in patches: patch_files.append((patch.oldname, patch.newname)) self.assertEqual(patch_files, filenames)
def test_parse_patches_leading_noise(self): # https://bugs.launchpad.net/bzr/+bug/502076 # https://code.launchpad.net/~toshio/bzr/allow-dirty-patches/+merge/18854 lines = [ "diff -pruN commands.py", "--- orig/commands.py", "+++ mod/dommands.py" ] bits = parse_patches(iter(lines), allow_dirty=True)
def test_parse_binary_after_normal(self): patches = parse_patches(self.data_lines("binary-after-normal.patch")) self.assertIs(BinaryPatch, patches[1].__class__) self.assertIs(Patch, patches[0].__class__) self.assertContainsRe(patches[1].oldname, '^bar\t') self.assertContainsRe(patches[1].newname, '^qux\t') self.assertContainsRe(str(patches[1]), 'Binary files bar\t.* and qux\t.* differ\n')
def main(): patches = parse_patches(sys.stdin) comments = get_comments_from_diff(patches) tags = ('XXX', 'TODO') number = -1 for number, todo in enumerate(todos_from_comments(comments, tags)): print todo print "Things to do: %s" % (number + 1)
def test_parse_binary(self): """Test parsing a whole patch""" patches = parse_patches(self.data_lines("binary.patch")) self.assertIs(BinaryPatch, patches[0].__class__) self.assertIs(Patch, patches[1].__class__) self.assertContainsRe(patches[0].oldname, '^bar\t') self.assertContainsRe(patches[0].newname, '^qux\t') self.assertContainsRe(str(patches[0]), 'Binary files bar\t.* and qux\t.* differ\n')
def diff_changes(diff_bytes): inserted = [] removed = [] for patch in parse_patches(diff_bytes.splitlines(True)): for hunk in patch.hunks: for line in hunk.lines: if isinstance(line, InsertLine): inserted.append(line.contents) if isinstance(line, RemoveLine): removed.append(line.contents) return inserted, removed
def generateDiffstat(diff_bytes): """Generate statistics about the provided diff. :param diff_bytes: A unified diff, as bytes. :return: A map of {filename: (added_line_count, removed_line_count)} """ file_stats = {} # Set allow_dirty, so we don't raise exceptions for dirty patches. patches = parse_patches(diff_bytes.splitlines(True), allow_dirty=True) for patch in patches: if not isinstance(patch, Patch): continue path = patch.newname.split('\t')[0] file_stats[path] = tuple(patch.stats_values()[:2]) return file_stats
def run(self): revision = _parse_revision_str('submit:') diff_data = get_trees_and_branches_to_diff_locked( None, revision, None, None, self.add_cleanup, apply_view=True) (old_tree, new_tree, old_branch, new_branch, specific_files, extra_trees) = diff_data stream = StringIO() show_diff_trees( old_tree, new_tree, stream, old_label='', new_label='', extra_trees=extra_trees) stream.seek(0) patches = parse_patches(stream) comments = get_comments_from_diff(patches) tags = ('XXX', 'TODO') number = -1 for number, todo in enumerate(todos_from_comments(comments, tags)): print todo print "Things to do: %s" % (number + 1)
def generateDiffstat(diff_bytes, strip_prefix_segments=0): """Generate statistics about the provided diff. :param diff_bytes: A unified diff, as bytes. :param strip_prefix_segments: Strip the smallest prefix containing this many leading slashes from each file name found in the patch file, as with "patch -p". :return: A map of {filename: (added_line_count, removed_line_count)} """ file_stats = {} # Set allow_dirty, so we don't raise exceptions for dirty patches. patches = parse_patches(diff_bytes.splitlines(True), allow_dirty=True) for patch in patches: if not isinstance(patch, Patch): continue path = patch.newname.split('\t')[0] if strip_prefix_segments: path = path.split('/', strip_prefix_segments)[-1] file_stats[path] = tuple(patch.stats_values()[:2]) return file_stats
def test_preserve_dirty_head(self): """Parse a patch containing a dirty header, and preserve lines""" lines = ["=== added directory 'foo/bar'\n", "=== modified file 'orig/commands.py'\n", "--- orig/commands.py\n", "+++ mod/dommands.py\n", "=== modified file 'orig/another.py'\n", "--- orig/another.py\n", "+++ mod/another.py\n"] patches = parse_patches( lines.__iter__(), allow_dirty=True, keep_dirty=True) self.assertLength(2, patches) self.assertEqual(patches[0]['dirty_head'], ["=== added directory 'foo/bar'\n", "=== modified file 'orig/commands.py'\n"]) self.assertEqual(patches[0]['patch'].get_header().splitlines(True), ["--- orig/commands.py\n", "+++ mod/dommands.py\n"]) self.assertEqual(patches[1]['dirty_head'], ["=== modified file 'orig/another.py'\n"]) self.assertEqual(patches[1]['patch'].get_header().splitlines(True), ["--- orig/another.py\n", "+++ mod/another.py\n"])
def test_preserve_dirty_head(self): """Parse a patch containing a dirty header, and preserve lines""" lines = [ "=== added directory 'foo/bar'\n", "=== modified file 'orig/commands.py'\n", "--- orig/commands.py\n", "+++ mod/dommands.py\n", "=== modified file 'orig/another.py'\n", "--- orig/another.py\n", "+++ mod/another.py\n" ] patches = parse_patches(lines.__iter__(), allow_dirty=True, keep_dirty=True) self.assertLength(2, patches) self.assertEqual(patches[0]['dirty_head'], [ "=== added directory 'foo/bar'\n", "=== modified file 'orig/commands.py'\n" ]) self.assertEqual(patches[0]['patch'].get_header().splitlines(True), ["--- orig/commands.py\n", "+++ mod/dommands.py\n"]) self.assertEqual(patches[1]['dirty_head'], ["=== modified file 'orig/another.py'\n"]) self.assertEqual(patches[1]['patch'].get_header().splitlines(True), ["--- orig/another.py\n", "+++ mod/another.py\n"])
def test_roundtrip_binary(self): patchtext = ''.join(self.data_lines("binary.patch")) patches = parse_patches(patchtext.splitlines(True)) self.assertEqual(patchtext, ''.join(str(p) for p in patches))
def readpatches(self): return patches.parse_patches(self.readlines())
def main(): phile = sys.stdin for comment in get_comments_from_diff(patches.parse_patches(phile)): print str(comment)