| #!/usr/bin/env python |
| ## |
| ## Copyright (c) 2021, Alliance for Open Media. All rights reserved |
| ## |
| ## This source code is subject to the terms of the BSD 3-Clause Clear License and the |
| ## Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear License was |
| ## not distributed with this source code in the LICENSE file, you can obtain it |
| ## at aomedia.org/license/software-license/bsd-3-c-c/. If the Alliance for Open Media Patent |
| ## License 1.0 was not distributed with this source code in the PATENTS file, you |
| ## can obtain it at aomedia.org/license/patent-license/. |
| ## |
| """Calculates the "intersection" of two unified diffs. |
| |
| Given two diffs, A and B, it finds all hunks in B that had non-context lines |
| in A and prints them to stdout. This is useful to determine the hunks in B that |
| are relevant to A. The resulting file can be applied with patch(1) on top of A. |
| """ |
| |
| __author__ = "jkoleszar@google.com" |
| |
| import sys |
| |
| import diff |
| |
| |
| def FormatDiffHunks(hunks): |
| """Re-serialize a list of DiffHunks.""" |
| r = [] |
| last_header = None |
| for hunk in hunks: |
| this_header = hunk.header[0:2] |
| if last_header != this_header: |
| r.extend(hunk.header) |
| last_header = this_header |
| else: |
| r.extend(hunk.header[2]) |
| r.extend(hunk.lines) |
| r.append("\n") |
| return "".join(r) |
| |
| |
| def ZipHunks(rhs_hunks, lhs_hunks): |
| """Join two hunk lists on filename.""" |
| for rhs_hunk in rhs_hunks: |
| rhs_file = rhs_hunk.right.filename.split("/")[1:] |
| |
| for lhs_hunk in lhs_hunks: |
| lhs_file = lhs_hunk.left.filename.split("/")[1:] |
| if lhs_file != rhs_file: |
| continue |
| yield (rhs_hunk, lhs_hunk) |
| |
| |
| def main(): |
| old_hunks = [x for x in diff.ParseDiffHunks(open(sys.argv[1], "r"))] |
| new_hunks = [x for x in diff.ParseDiffHunks(open(sys.argv[2], "r"))] |
| out_hunks = [] |
| |
| # Join the right hand side of the older diff with the left hand side of the |
| # newer diff. |
| for old_hunk, new_hunk in ZipHunks(old_hunks, new_hunks): |
| if new_hunk in out_hunks: |
| continue |
| old_lines = old_hunk.right |
| new_lines = new_hunk.left |
| |
| # Determine if this hunk overlaps any non-context line from the other |
| for i in old_lines.delta_line_nums: |
| if i in new_lines: |
| out_hunks.append(new_hunk) |
| break |
| |
| if out_hunks: |
| print FormatDiffHunks(out_hunks) |
| sys.exit(1) |
| |
| if __name__ == "__main__": |
| main() |