diff --git a/contrib/merge-lists/src/main.rs b/contrib/merge-lists/src/main.rs --- a/contrib/merge-lists/src/main.rs +++ b/contrib/merge-lists/src/main.rs @@ -1,3 +1,4 @@ +use clap::ArgMatches; use itertools::Itertools; use regex::bytes::Regex; use similar::ChangeTag; @@ -143,11 +144,34 @@ (new_base_bytes, new_local_bytes, new_other_bytes) } +fn get_regex(matches: &ArgMatches) -> Regex { + let pattern = if matches.is_present("python") { + r"import \w+(\.\w+)*( +#.*)?\n|from (\w+(\.\w+)* import \w+( as \w+)?(, \w+( as \w+)?)*( +#.*)?)" + } else if let Some(pattern) = matches.value_of("pattern") { + pattern + } else { + ".*" + }; + let pattern = format!(r"{}\r?\n?", pattern); + regex::bytes::Regex::new(&pattern).unwrap() +} + fn main() { let app = clap::Command::new("merge-lists") .arg(clap::Arg::new("local").index(1).required(true)) .arg(clap::Arg::new("base").index(2).required(true)) - .arg(clap::Arg::new("other").index(3).required(true)); + .arg(clap::Arg::new("other").index(3).required(true)) + .arg( + clap::Arg::new("pattern") + .long("pattern") + .short('p') + .takes_value(true), + ) + .arg( + clap::Arg::new("python") + .long("python-imports") + .conflicts_with("pattern"), + ); let matches = app.get_matches(); let base_path = PathBuf::from(matches.value_of("base").unwrap()); @@ -158,8 +182,7 @@ let local_bytes = std::fs::read(&local_path).unwrap(); let other_bytes = std::fs::read(&other_path).unwrap(); - let regex = - regex::bytes::Regex::new(r"import \w+(\.\w+)*( +#.*)?\n|from (\w+(\.\w+)* import \w+( as \w+)?(, \w+( as \w+)?)*( +#.*)?)\r?\n?").unwrap(); + let regex = get_regex(&matches); let (new_base_bytes, new_local_bytes, new_other_bytes) = resolve(&base_bytes, &local_bytes, &other_bytes, ®ex); // Write out the result if anything changed diff --git a/contrib/merge-lists/tests/test-merge-lists.rs b/contrib/merge-lists/tests/test-merge-lists.rs --- a/contrib/merge-lists/tests/test-merge-lists.rs +++ b/contrib/merge-lists/tests/test-merge-lists.rs @@ -1,7 +1,8 @@ use similar::DiffableStr; +use std::ffi::OsStr; use tempdir::TempDir; -fn run_test(input: &str) -> String { +fn run_test(arg: &str, input: &str) -> String { let mut cmd = assert_cmd::Command::cargo_bin("merge-lists").unwrap(); let temp_dir = TempDir::new("test").unwrap(); let base_path = temp_dir.path().join("base"); @@ -16,6 +17,7 @@ std::fs::write(&local_path, split.next().unwrap()).unwrap(); std::fs::write(&other_path, split.next().unwrap()).unwrap(); cmd.args(&[ + OsStr::new(arg), local_path.as_os_str(), base_path.as_os_str(), other_path.as_os_str(), @@ -38,6 +40,7 @@ #[test] fn test_merge_lists_basic() { let output = run_test( + "--python-imports", r" base: import lib1 @@ -72,6 +75,7 @@ // Test some "from x import y" statements and some non-import conflicts // (unresolvable) let output = run_test( + "--python-imports", r" base: from . import x @@ -116,6 +120,7 @@ // Test that nothing is done if the elements in the conflicting hunks are // not sorted let output = run_test( + "--python-imports", r" base: import x @@ -154,3 +159,46 @@ 3+3 "###); } + +#[test] +fn test_custom_regex() { + // Test merging of all lines (by matching anything) + let output = run_test( + "--pattern=.*", + r" +base: +aardvark +baboon +camel + +local: +aardvark +camel +eagle + +other: +aardvark +camel +deer +", + ); + insta::assert_snapshot!(output, @r###" + base: + aardvark + camel + deer + eagle + + local: + aardvark + camel + deer + eagle + + other: + aardvark + camel + deer + eagle + "###); +}