From ec37c5bef1f43cf8dfaacf07e2946d490c690a1b Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Sun, 26 Sep 2021 21:23:22 -0700 Subject: [PATCH] Add full Mercurial extdiff support --- CHANGELOG.md | 6 ++++++ Cargo.lock | 1 + Cargo.toml | 1 + manual/src/getting_started.md | 3 +-- src/bin/difftastic.rs | 31 ++++++++++++++++++++++++++++++- 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a54b32cc..22933e54d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ Improved handling of paired delimiters, particularly in C, C++ and C#. +### Integration + +Added support for Mercuial, see [this section in the +manual](http://difftastic.wilfred.me.uk/getting_started.html#mercurial-external-diffs) +for instructions. + ### Build Fix compilation for systems where the C++ compiler defaulted to a diff --git a/Cargo.lock b/Cargo.lock index 01ca5dc72..02541367b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -257,6 +257,7 @@ dependencies = [ "term_size", "tree-sitter", "typed-arena", + "walkdir", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 13e1cf63a..f05e2837e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ log = "0.4.14" pretty_env_logger = "0.4.0" mimalloc = { version = "0.1.26", default-features = false } radix-heap = "0.3.8" +walkdir = "2.3.2" [dev-dependencies] pretty_assertions = "0.6.1" diff --git a/manual/src/getting_started.md b/manual/src/getting_started.md index eaf1a1284..88c0b0d28 100644 --- a/manual/src/getting_started.md +++ b/manual/src/getting_started.md @@ -89,8 +89,7 @@ extdiff = ``` You can then run `hg extdiff -p difftastic` (assumes difftastic is on -your `$PATH`). **This currently only supports diffs where a single file -is modified.** +your `$PATH`). You can also define an alias to run difftastic with hg. Add the following to your `.hgrc` to run difftastic with `hg dft`. diff --git a/src/bin/difftastic.rs b/src/bin/difftastic.rs index 158477e47..3a925f69b 100644 --- a/src/bin/difftastic.rs +++ b/src/bin/difftastic.rs @@ -7,6 +7,7 @@ use atty::Stream; use clap::{crate_version, App, AppSettings, Arg}; use std::{env, ffi::OsStr, path::Path}; use typed_arena::Arena; +use walkdir::WalkDir; use difftastic::*; use difftastic::{ @@ -191,9 +192,14 @@ fn main() { } => (display_path, lhs_path, rhs_path), }; - diff_file(&display_path, &lhs_path, &rhs_path); + if Path::new(&lhs_path).is_dir() && Path::new(&rhs_path).is_dir() { + diff_directories(&lhs_path, &rhs_path); + } else { + diff_file(&display_path, &lhs_path, &rhs_path); + } } +// TODO: prefer PathBuf to &str for paths. fn diff_file(display_path: &str, lhs_path: &str, rhs_path: &str) { let lhs_bytes = read_or_die(lhs_path); let rhs_bytes = read_or_die(rhs_path); @@ -276,3 +282,26 @@ fn diff_file(display_path: &str, lhs_path: &str, rhs_path: &str) { } println!(); } + +/// Given two directories that contain the files, compare them +/// pairwise. +/// +/// This is how the hg extdiff extension calls a diff tool when there +/// is more than one changed file. +fn diff_directories(lhs_dir: &str, rhs_dir: &str) { + for entry in WalkDir::new(lhs_dir).into_iter().filter_map(Result::ok) { + let lhs_path = entry.path(); + if lhs_path.is_dir() { + continue; + } + + let rel_path = lhs_path.strip_prefix(lhs_dir).unwrap(); + let rhs_path = Path::new(rhs_dir).join(rel_path); + + diff_file( + &rel_path.to_string_lossy(), + &lhs_path.to_string_lossy(), + &rhs_path.to_string_lossy(), + ); + } +}