Support diffing directories where files are only in one side

This was broken in 1e9f43768. Add test.

Fixes #500
pull/502/head
Wilfred Hughes 2023-03-24 23:57:49 +07:00
parent 4753c3fc16
commit 713220613e
3 changed files with 28 additions and 2 deletions

@ -3,6 +3,7 @@
use std::io::Read; use std::io::Read;
use std::{ use std::{
fs, fs,
io::ErrorKind::*,
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
@ -12,7 +13,11 @@ use walkdir::WalkDir;
use crate::exit_codes::EXIT_BAD_ARGUMENTS; use crate::exit_codes::EXIT_BAD_ARGUMENTS;
use crate::options::FileArgument; use crate::options::FileArgument;
pub fn read_files_or_die(lhs_path: &FileArgument, rhs_path: &FileArgument) -> (Vec<u8>, Vec<u8>) { pub fn read_files_or_die(
lhs_path: &FileArgument,
rhs_path: &FileArgument,
missing_as_empty: bool,
) -> (Vec<u8>, Vec<u8>) {
let lhs_res = read_file_arg(lhs_path); let lhs_res = read_file_arg(lhs_path);
let rhs_res = read_file_arg(rhs_path); let rhs_res = read_file_arg(rhs_path);
@ -20,6 +25,12 @@ pub fn read_files_or_die(lhs_path: &FileArgument, rhs_path: &FileArgument) -> (V
// Both files exist, the happy case. // Both files exist, the happy case.
(Ok(lhs_src), Ok(rhs_src)) => (lhs_src, rhs_src), (Ok(lhs_src), Ok(rhs_src)) => (lhs_src, rhs_src),
// Proceed if we've been given two paths and only one
// exists. This is important for mercurial diffs when a file
// has been removed.
(Ok(lhs_src), Err(e)) if missing_as_empty && e.kind() == NotFound => (lhs_src, vec![]),
(Err(e), Ok(rhs_src)) if missing_as_empty && e.kind() == NotFound => (vec![], rhs_src),
(lhs_res, rhs_res) => { (lhs_res, rhs_res) => {
// Something else went wrong. Print both errors // Something else went wrong. Print both errors
// encountered. // encountered.

@ -237,6 +237,7 @@ fn main() {
&rhs_path, &rhs_path,
&display_options, &display_options,
&diff_options, &diff_options,
false,
language_override, language_override,
); );
print_diff_result(&display_options, &diff_result); print_diff_result(&display_options, &diff_result);
@ -280,9 +281,10 @@ fn diff_file(
rhs_path: &FileArgument, rhs_path: &FileArgument,
display_options: &DisplayOptions, display_options: &DisplayOptions,
diff_options: &DiffOptions, diff_options: &DiffOptions,
missing_as_empty: bool,
language_override: Option<parse::guess_language::Language>, language_override: Option<parse::guess_language::Language>,
) -> DiffResult { ) -> DiffResult {
let (lhs_bytes, rhs_bytes) = read_files_or_die(lhs_path, rhs_path); let (lhs_bytes, rhs_bytes) = read_files_or_die(lhs_path, rhs_path, missing_as_empty);
diff_file_content( diff_file_content(
lhs_display_path, lhs_display_path,
rhs_display_path, rhs_display_path,
@ -618,6 +620,7 @@ fn diff_directories<'a>(
&FileArgument::NamedPath(rhs_path), &FileArgument::NamedPath(rhs_path),
&display_options, &display_options,
&diff_options, &diff_options,
true,
language_override, language_override,
) )
}) })

@ -131,3 +131,15 @@ fn slightly_invalid_utf8() {
let predicate_fn = predicate::str::contains("using"); let predicate_fn = predicate::str::contains("using");
cmd.assert().stdout(predicate_fn); cmd.assert().stdout(predicate_fn);
} }
#[test]
fn directory_arguments() {
let mut cmd = Command::cargo_bin("difft").unwrap();
cmd.arg("sample_files/dir_before")
.arg("sample_files/dir_after");
let predicate_fn = predicate::str::contains("only_in_before.c")
.and(predicate::str::contains("only_in_after_dir.rs"));
cmd.assert().stdout(predicate_fn);
}