Patchwork D12392: merge-lists: make it possible to specify pattern to match

login
register
mail settings
Submitter phabricator
Date March 22, 2022, 4:58 a.m.
Message ID <differential-rev-PHID-DREV-33yy7rxg43rnbb64u3bo-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/50736/
State New
Headers show

Comments

phabricator - March 22, 2022, 4:58 a.m.
martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  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).

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D12392

AFFECTED FILES
  contrib/merge-lists/src/main.rs
  contrib/merge-lists/tests/test-merge-lists.rs

CHANGE DETAILS




To: martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

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
+    "###);
+}
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, &regex);
     // Write out the result if anything changed