contrib/merge-lists/src/main.rs
changeset 49011 b999edb15f8c
parent 49010 681b25ea579e
equal deleted inserted replaced
49010:681b25ea579e 49011:b999edb15f8c
     1 use clap::Parser;
     1 use clap::{ArgGroup, Parser};
     2 use itertools::Itertools;
     2 use itertools::Itertools;
     3 use regex::bytes::Regex;
     3 use regex::bytes::Regex;
     4 use similar::ChangeTag;
     4 use similar::ChangeTag;
     5 use std::cmp::{max, min, Ordering};
     5 use std::cmp::{max, min, Ordering};
     6 use std::collections::HashSet;
     6 use std::collections::HashSet;
   148 /// A tool that performs a 3-way merge, resolving conflicts in sorted lists and
   148 /// A tool that performs a 3-way merge, resolving conflicts in sorted lists and
   149 /// leaving other conflicts unchanged. This is useful with Mercurial's support
   149 /// leaving other conflicts unchanged. This is useful with Mercurial's support
   150 /// for partial merge tools (configured in `[partial-merge-tools]`).
   150 /// for partial merge tools (configured in `[partial-merge-tools]`).
   151 #[derive(Parser, Debug)]
   151 #[derive(Parser, Debug)]
   152 #[clap(version, about, long_about = None)]
   152 #[clap(version, about, long_about = None)]
       
   153 #[clap(group(ArgGroup::new("match").required(true).args(&["pattern", "python-imports"])))]
   153 struct Args {
   154 struct Args {
   154     /// Path to the file's content in the "local" side
   155     /// Path to the file's content in the "local" side
   155     local: OsString,
   156     local: OsString,
   156 
   157 
   157     /// Path to the file's content in the base
   158     /// Path to the file's content in the base
   158     base: OsString,
   159     base: OsString,
   159 
   160 
   160     /// Path to the file's content in the "other" side
   161     /// Path to the file's content in the "other" side
   161     other: OsString,
   162     other: OsString,
       
   163 
       
   164     /// Regular expression to use
       
   165     #[clap(long, short)]
       
   166     pattern: Option<String>,
       
   167 
       
   168     /// Use built-in regular expression for Python imports
       
   169     #[clap(long)]
       
   170     python_imports: bool,
       
   171 }
       
   172 
       
   173 fn get_regex(args: &Args) -> Regex {
       
   174     let pattern = if args.python_imports {
       
   175         r"import \w+(\.\w+)*( +#.*)?\n|from (\w+(\.\w+)* import \w+( as \w+)?(, \w+( as \w+)?)*( +#.*)?)"
       
   176     } else if let Some(pattern) = &args.pattern {
       
   177         pattern
       
   178     } else {
       
   179         ".*"
       
   180     };
       
   181     let pattern = format!(r"{}\r?\n?", pattern);
       
   182     regex::bytes::Regex::new(&pattern).unwrap()
   162 }
   183 }
   163 
   184 
   164 fn main() {
   185 fn main() {
   165     let args: Args = Args::parse();
   186     let args: Args = Args::parse();
   166 
   187 
   170 
   191 
   171     let base_bytes = std::fs::read(&base_path).unwrap();
   192     let base_bytes = std::fs::read(&base_path).unwrap();
   172     let local_bytes = std::fs::read(&local_path).unwrap();
   193     let local_bytes = std::fs::read(&local_path).unwrap();
   173     let other_bytes = std::fs::read(&other_path).unwrap();
   194     let other_bytes = std::fs::read(&other_path).unwrap();
   174 
   195 
   175     let regex =
   196     let regex = get_regex(&args);
   176         regex::bytes::Regex::new(r"import \w+(\.\w+)*( +#.*)?\n|from (\w+(\.\w+)* import \w+( as \w+)?(, \w+( as \w+)?)*( +#.*)?)\r?\n?").unwrap();
       
   177     let (new_base_bytes, new_local_bytes, new_other_bytes) =
   197     let (new_base_bytes, new_local_bytes, new_other_bytes) =
   178         resolve(&base_bytes, &local_bytes, &other_bytes, &regex);
   198         resolve(&base_bytes, &local_bytes, &other_bytes, &regex);
   179 
   199 
   180     // Write out the result if anything changed
   200     // Write out the result if anything changed
   181     if new_base_bytes != base_bytes {
   201     if new_base_bytes != base_bytes {