author | Pierre-Yves DAVID <pierre-yves.david@octobus.net> |
Sun, 05 Jun 2022 07:16:29 +0200 | |
changeset 49463 | 5acbc550d987 |
parent 49011 | b999edb15f8c |
permissions | -rw-r--r-- |
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, ®ex); |
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 |
} |