Mercurial > hg
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 |
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, ®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 } |