annotate contrib/merge-lists/src/main.rs @ 49011:b999edb15f8c

merge-lists: make it possible to specify pattern to match The `merge-lists` tool doesn't know anything about Python other than its regex that attempts to match import lines. Let's make it possible to pass in a custom regex so it's easy to use the tool for e.g. C/C++ `#include` lines or Rust `use` lines (given the limited). Differential Revision: https://phab.mercurial-scm.org/D12392
author Martin von Zweigbergk <martinvonz@google.com>
date Fri, 18 Mar 2022 12:23:47 -0700
parents 681b25ea579e
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
49011
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
1 use clap::{ArgGroup, Parser};
49010
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
2 use itertools::Itertools;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
3 use regex::bytes::Regex;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
4 use similar::ChangeTag;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
5 use std::cmp::{max, min, Ordering};
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
6 use std::collections::HashSet;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
7 use std::ffi::OsString;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
8 use std::ops::Range;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
9 use std::path::PathBuf;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
10
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
11 fn find_unchanged_ranges(
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
12 old_bytes: &[u8],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
13 new_bytes: &[u8],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
14 ) -> Vec<(Range<usize>, Range<usize>)> {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
15 let diff = similar::TextDiff::configure()
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
16 .algorithm(similar::Algorithm::Patience)
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
17 .diff_lines(old_bytes, new_bytes);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
18 let mut new_unchanged_ranges = vec![];
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
19 let mut old_index = 0;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
20 let mut new_index = 0;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
21 for diff in diff.iter_all_changes() {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
22 match diff.tag() {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
23 ChangeTag::Equal => {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
24 new_unchanged_ranges.push((
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
25 old_index..old_index + diff.value().len(),
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
26 new_index..new_index + diff.value().len(),
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
27 ));
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
28 old_index += diff.value().len();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
29 new_index += diff.value().len();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
30 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
31 ChangeTag::Delete => {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
32 old_index += diff.value().len();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
33 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
34 ChangeTag::Insert => {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
35 new_index += diff.value().len();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
36 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
37 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
38 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
39 new_unchanged_ranges
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
40 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
41
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
42 /// Returns a list of all the lines in the input (including trailing newlines),
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
43 /// but only if they all match the regex and they are sorted.
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
44 fn get_lines<'input>(
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
45 input: &'input [u8],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
46 regex: &Regex,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
47 ) -> Option<Vec<&'input [u8]>> {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
48 let lines = input.split_inclusive(|x| *x == b'\n').collect_vec();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
49 let mut previous_line = "".as_bytes();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
50 for line in &lines {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
51 if *line < previous_line {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
52 return None;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
53 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
54 if !regex.is_match(line) {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
55 return None;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
56 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
57 previous_line = line;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
58 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
59 Some(lines)
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
60 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
61
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
62 fn resolve_conflict(
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
63 base_slice: &[u8],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
64 local_slice: &[u8],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
65 other_slice: &[u8],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
66 regex: &Regex,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
67 ) -> Option<Vec<u8>> {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
68 let base_lines = get_lines(base_slice, regex)?;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
69 let local_lines = get_lines(local_slice, regex)?;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
70 let other_lines = get_lines(other_slice, regex)?;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
71 let base_lines_set: HashSet<_> = base_lines.iter().copied().collect();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
72 let local_lines_set: HashSet<_> = local_lines.iter().copied().collect();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
73 let other_lines_set: HashSet<_> = other_lines.iter().copied().collect();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
74 let mut result = local_lines_set;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
75 for to_add in other_lines_set.difference(&base_lines_set) {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
76 result.insert(to_add);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
77 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
78 for to_remove in base_lines_set.difference(&other_lines_set) {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
79 result.remove(to_remove);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
80 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
81 Some(result.into_iter().sorted().collect_vec().concat())
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
82 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
83
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
84 fn resolve(
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
85 base_bytes: &[u8],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
86 local_bytes: &[u8],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
87 other_bytes: &[u8],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
88 regex: &Regex,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
89 ) -> (Vec<u8>, Vec<u8>, Vec<u8>) {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
90 // Find unchanged ranges between the base and the two sides. We do that by
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
91 // initially considering the whole base unchanged. Then we compare each
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
92 // side with the base and intersect the unchanged ranges we find with
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
93 // what we had before.
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
94 let unchanged_ranges = vec![UnchangedRange {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
95 base_range: 0..base_bytes.len(),
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
96 offsets: vec![],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
97 }];
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
98 let unchanged_ranges = intersect_regions(
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
99 unchanged_ranges,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
100 &find_unchanged_ranges(base_bytes, local_bytes),
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
101 );
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
102 let mut unchanged_ranges = intersect_regions(
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
103 unchanged_ranges,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
104 &find_unchanged_ranges(base_bytes, other_bytes),
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
105 );
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
106 // Add an empty UnchangedRange at the end to make it easier to find change
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
107 // ranges. That way there's a changed range before each UnchangedRange.
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
108 unchanged_ranges.push(UnchangedRange {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
109 base_range: base_bytes.len()..base_bytes.len(),
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
110 offsets: vec![
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
111 local_bytes.len().wrapping_sub(base_bytes.len()) as isize,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
112 other_bytes.len().wrapping_sub(base_bytes.len()) as isize,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
113 ],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
114 });
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
115
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
116 let mut new_base_bytes: Vec<u8> = vec![];
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
117 let mut new_local_bytes: Vec<u8> = vec![];
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
118 let mut new_other_bytes: Vec<u8> = vec![];
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
119 let mut previous = UnchangedRange {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
120 base_range: 0..0,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
121 offsets: vec![0, 0],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
122 };
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
123 for current in unchanged_ranges {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
124 let base_slice =
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
125 &base_bytes[previous.base_range.end..current.base_range.start];
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
126 let local_slice = &local_bytes[previous.end(0)..current.start(0)];
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
127 let other_slice = &other_bytes[previous.end(1)..current.start(1)];
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
128 if let Some(resolution) =
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
129 resolve_conflict(base_slice, local_slice, other_slice, regex)
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
130 {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
131 new_base_bytes.extend(&resolution);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
132 new_local_bytes.extend(&resolution);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
133 new_other_bytes.extend(&resolution);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
134 } else {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
135 new_base_bytes.extend(base_slice);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
136 new_local_bytes.extend(local_slice);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
137 new_other_bytes.extend(other_slice);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
138 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
139 new_base_bytes.extend(&base_bytes[current.base_range.clone()]);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
140 new_local_bytes.extend(&local_bytes[current.start(0)..current.end(0)]);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
141 new_other_bytes.extend(&other_bytes[current.start(1)..current.end(1)]);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
142 previous = current;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
143 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
144
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
145 (new_base_bytes, new_local_bytes, new_other_bytes)
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
146 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
147
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
148 /// A tool that performs a 3-way merge, resolving conflicts in sorted lists and
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
149 /// leaving other conflicts unchanged. This is useful with Mercurial's support
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
150 /// for partial merge tools (configured in `[partial-merge-tools]`).
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
151 #[derive(Parser, Debug)]
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
152 #[clap(version, about, long_about = None)]
49011
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
153 #[clap(group(ArgGroup::new("match").required(true).args(&["pattern", "python-imports"])))]
49010
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
154 struct Args {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
155 /// Path to the file's content in the "local" side
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
156 local: OsString,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
157
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
158 /// Path to the file's content in the base
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
159 base: OsString,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
160
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
161 /// Path to the file's content in the "other" side
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
162 other: OsString,
49011
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
163
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
164 /// Regular expression to use
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
165 #[clap(long, short)]
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
166 pattern: Option<String>,
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
167
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
168 /// Use built-in regular expression for Python imports
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
169 #[clap(long)]
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
170 python_imports: bool,
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
171 }
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
172
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
173 fn get_regex(args: &Args) -> Regex {
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
174 let pattern = if args.python_imports {
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
175 r"import \w+(\.\w+)*( +#.*)?\n|from (\w+(\.\w+)* import \w+( as \w+)?(, \w+( as \w+)?)*( +#.*)?)"
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
176 } else if let Some(pattern) = &args.pattern {
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
177 pattern
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
178 } else {
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
179 ".*"
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
180 };
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
181 let pattern = format!(r"{}\r?\n?", pattern);
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
182 regex::bytes::Regex::new(&pattern).unwrap()
49010
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
183 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
184
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
185 fn main() {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
186 let args: Args = Args::parse();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
187
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
188 let base_path = PathBuf::from(&args.base);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
189 let local_path = PathBuf::from(&args.local);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
190 let other_path = PathBuf::from(&args.other);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
191
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
192 let base_bytes = std::fs::read(&base_path).unwrap();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
193 let local_bytes = std::fs::read(&local_path).unwrap();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
194 let other_bytes = std::fs::read(&other_path).unwrap();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
195
49011
b999edb15f8c merge-lists: make it possible to specify pattern to match
Martin von Zweigbergk <martinvonz@google.com>
parents: 49010
diff changeset
196 let regex = get_regex(&args);
49010
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
197 let (new_base_bytes, new_local_bytes, new_other_bytes) =
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
198 resolve(&base_bytes, &local_bytes, &other_bytes, &regex);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
199
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
200 // Write out the result if anything changed
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
201 if new_base_bytes != base_bytes {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
202 std::fs::write(&base_path, new_base_bytes).unwrap();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
203 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
204 if new_local_bytes != local_bytes {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
205 std::fs::write(&local_path, new_local_bytes).unwrap();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
206 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
207 if new_other_bytes != other_bytes {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
208 std::fs::write(&other_path, new_other_bytes).unwrap();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
209 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
210 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
211
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
212 fn checked_add(base: usize, offset: isize) -> usize {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
213 if offset < 0 {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
214 base.checked_sub(offset.checked_abs().unwrap() as usize)
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
215 .unwrap()
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
216 } else {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
217 base.checked_add(offset as usize).unwrap()
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
218 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
219 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
220
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
221 // The remainder of the file is copied from
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
222 // https://github.com/martinvonz/jj/blob/main/lib/src/diff.rs
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
223
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
224 #[derive(Clone, PartialEq, Eq, Debug)]
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
225 struct UnchangedRange {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
226 base_range: Range<usize>,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
227 offsets: Vec<isize>,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
228 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
229
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
230 impl UnchangedRange {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
231 fn start(&self, side: usize) -> usize {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
232 checked_add(self.base_range.start, self.offsets[side])
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
233 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
234
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
235 fn end(&self, side: usize) -> usize {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
236 checked_add(self.base_range.end, self.offsets[side])
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
237 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
238 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
239
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
240 impl PartialOrd for UnchangedRange {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
241 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
242 Some(self.cmp(other))
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
243 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
244 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
245
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
246 impl Ord for UnchangedRange {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
247 fn cmp(&self, other: &Self) -> Ordering {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
248 self.base_range
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
249 .start
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
250 .cmp(&other.base_range.start)
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
251 .then_with(|| self.base_range.end.cmp(&other.base_range.end))
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
252 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
253 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
254
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
255 /// Takes the current regions and intersects it with the new unchanged ranges
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
256 /// from a 2-way diff. The result is a map of unchanged regions with one more
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
257 /// offset in the map's values.
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
258 fn intersect_regions(
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
259 current_ranges: Vec<UnchangedRange>,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
260 new_unchanged_ranges: &[(Range<usize>, Range<usize>)],
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
261 ) -> Vec<UnchangedRange> {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
262 let mut result = vec![];
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
263 let mut current_ranges_iter = current_ranges.into_iter().peekable();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
264 for (new_base_range, other_range) in new_unchanged_ranges.iter() {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
265 assert_eq!(new_base_range.len(), other_range.len());
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
266 while let Some(UnchangedRange {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
267 base_range,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
268 offsets,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
269 }) = current_ranges_iter.peek()
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
270 {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
271 // No need to look further if we're past the new range.
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
272 if base_range.start >= new_base_range.end {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
273 break;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
274 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
275 // Discard any current unchanged regions that don't match between
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
276 // the base and the new input.
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
277 if base_range.end <= new_base_range.start {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
278 current_ranges_iter.next();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
279 continue;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
280 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
281 let new_start = max(base_range.start, new_base_range.start);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
282 let new_end = min(base_range.end, new_base_range.end);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
283 let mut new_offsets = offsets.clone();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
284 new_offsets
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
285 .push(other_range.start.wrapping_sub(new_base_range.start)
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
286 as isize);
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
287 result.push(UnchangedRange {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
288 base_range: new_start..new_end,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
289 offsets: new_offsets,
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
290 });
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
291 if base_range.end >= new_base_range.end {
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
292 // Break without consuming the item; there may be other new
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
293 // ranges that overlap with it.
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
294 break;
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
295 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
296 current_ranges_iter.next();
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
297 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
298 }
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
299 result
681b25ea579e contrib: add a partial-merge tool for sorted lists (such as Python imports)
Martin von Zweigbergk <martinvonz@google.com>
parents:
diff changeset
300 }