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