mirror of
https://github.com/uutils/diffutils.git
synced 2026-06-10 15:48:59 -07:00
Implement -s/--report-identical-files option (fixes #23)
This commit is contained in:
committed by
Sylvestre Ledru
parent
a89f30afa0
commit
c68d386170
Generated
+41
@@ -81,6 +81,7 @@ dependencies = [
|
||||
"diff",
|
||||
"predicates",
|
||||
"pretty_assertions",
|
||||
"same-file",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
@@ -248,6 +249,15 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
@@ -312,6 +322,37 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
|
||||
@@ -16,6 +16,7 @@ path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
diff = "0.1.10"
|
||||
same-file = "1.0.6"
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "1"
|
||||
|
||||
+16
@@ -28,10 +28,25 @@ fn main() -> ExitCode {
|
||||
to,
|
||||
context_count,
|
||||
format,
|
||||
report_identical_files,
|
||||
} = parse_params(opts).unwrap_or_else(|error| {
|
||||
eprintln!("{error}");
|
||||
exit(2);
|
||||
});
|
||||
// if from and to are the same file, no need to perform any comparison
|
||||
let maybe_report_identical_files = || {
|
||||
if report_identical_files {
|
||||
println!(
|
||||
"Files {} and {} are identical",
|
||||
from.to_string_lossy(),
|
||||
to.to_string_lossy(),
|
||||
)
|
||||
}
|
||||
};
|
||||
if same_file::is_same_file(&from, &to).unwrap_or(false) {
|
||||
maybe_report_identical_files();
|
||||
return ExitCode::SUCCESS;
|
||||
}
|
||||
// read files
|
||||
let from_content = match fs::read(&from) {
|
||||
Ok(from_content) => from_content,
|
||||
@@ -71,6 +86,7 @@ fn main() -> ExitCode {
|
||||
};
|
||||
io::stdout().write_all(&result).unwrap();
|
||||
if result.is_empty() {
|
||||
maybe_report_identical_files();
|
||||
ExitCode::SUCCESS
|
||||
} else {
|
||||
ExitCode::from(1)
|
||||
|
||||
@@ -25,6 +25,7 @@ pub struct Params {
|
||||
pub to: OsString,
|
||||
pub format: Format,
|
||||
pub context_count: usize,
|
||||
pub report_identical_files: bool,
|
||||
}
|
||||
|
||||
pub fn parse_params<I: IntoIterator<Item = OsString>>(opts: I) -> Result<Params, String> {
|
||||
@@ -38,6 +39,7 @@ pub fn parse_params<I: IntoIterator<Item = OsString>>(opts: I) -> Result<Params,
|
||||
let mut to = None;
|
||||
let mut format = None;
|
||||
let mut context_count = 3;
|
||||
let mut report_identical_files = false;
|
||||
while let Some(param) = opts.next() {
|
||||
if param == "--" {
|
||||
break;
|
||||
@@ -52,6 +54,10 @@ pub fn parse_params<I: IntoIterator<Item = OsString>>(opts: I) -> Result<Params,
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if param == "-s" || param == "--report-identical-files" {
|
||||
report_identical_files = true;
|
||||
continue;
|
||||
}
|
||||
let p = osstr_bytes(¶m);
|
||||
if p.first() == Some(&b'-') && p.get(1) != Some(&b'-') {
|
||||
let mut bit = p[1..].iter().copied().peekable();
|
||||
@@ -133,6 +139,7 @@ pub fn parse_params<I: IntoIterator<Item = OsString>>(opts: I) -> Result<Params,
|
||||
to,
|
||||
format,
|
||||
context_count,
|
||||
report_identical_files,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -150,6 +157,7 @@ mod tests {
|
||||
to: os("bar"),
|
||||
format: Format::Normal,
|
||||
context_count: 3,
|
||||
report_identical_files: false,
|
||||
}),
|
||||
parse_params([os("diff"), os("foo"), os("bar")].iter().cloned())
|
||||
);
|
||||
@@ -162,6 +170,7 @@ mod tests {
|
||||
to: os("bar"),
|
||||
format: Format::Ed,
|
||||
context_count: 3,
|
||||
report_identical_files: false,
|
||||
}),
|
||||
parse_params([os("diff"), os("-e"), os("foo"), os("bar")].iter().cloned())
|
||||
);
|
||||
@@ -174,6 +183,7 @@ mod tests {
|
||||
to: os("bar"),
|
||||
format: Format::Unified,
|
||||
context_count: 54,
|
||||
report_identical_files: false,
|
||||
}),
|
||||
parse_params(
|
||||
[os("diff"), os("-u54"), os("foo"), os("bar")]
|
||||
@@ -187,6 +197,7 @@ mod tests {
|
||||
to: os("bar"),
|
||||
format: Format::Unified,
|
||||
context_count: 54,
|
||||
report_identical_files: false,
|
||||
}),
|
||||
parse_params(
|
||||
[os("diff"), os("-U54"), os("foo"), os("bar")]
|
||||
@@ -200,6 +211,7 @@ mod tests {
|
||||
to: os("bar"),
|
||||
format: Format::Unified,
|
||||
context_count: 54,
|
||||
report_identical_files: false,
|
||||
}),
|
||||
parse_params(
|
||||
[os("diff"), os("-U"), os("54"), os("foo"), os("bar")]
|
||||
@@ -213,6 +225,7 @@ mod tests {
|
||||
to: os("bar"),
|
||||
format: Format::Context,
|
||||
context_count: 54,
|
||||
report_identical_files: false,
|
||||
}),
|
||||
parse_params(
|
||||
[os("diff"), os("-c54"), os("foo"), os("bar")]
|
||||
@@ -222,6 +235,48 @@ mod tests {
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn report_identical_files() {
|
||||
assert_eq!(
|
||||
Ok(Params {
|
||||
from: os("foo"),
|
||||
to: os("bar"),
|
||||
format: Format::Normal,
|
||||
context_count: 3,
|
||||
report_identical_files: false,
|
||||
}),
|
||||
parse_params([os("diff"), os("foo"), os("bar")].iter().cloned())
|
||||
);
|
||||
assert_eq!(
|
||||
Ok(Params {
|
||||
from: os("foo"),
|
||||
to: os("bar"),
|
||||
format: Format::Normal,
|
||||
context_count: 3,
|
||||
report_identical_files: true,
|
||||
}),
|
||||
parse_params([os("diff"), os("-s"), os("foo"), os("bar")].iter().cloned())
|
||||
);
|
||||
assert_eq!(
|
||||
Ok(Params {
|
||||
from: os("foo"),
|
||||
to: os("bar"),
|
||||
format: Format::Normal,
|
||||
context_count: 3,
|
||||
report_identical_files: true,
|
||||
}),
|
||||
parse_params(
|
||||
[
|
||||
os("diff"),
|
||||
os("--report-identical-files"),
|
||||
os("foo"),
|
||||
os("bar"),
|
||||
]
|
||||
.iter()
|
||||
.cloned()
|
||||
)
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn double_dash() {
|
||||
assert_eq!(
|
||||
Ok(Params {
|
||||
@@ -229,6 +284,7 @@ mod tests {
|
||||
to: os("-h"),
|
||||
format: Format::Normal,
|
||||
context_count: 3,
|
||||
report_identical_files: false,
|
||||
}),
|
||||
parse_params([os("diff"), os("--"), os("-g"), os("-h")].iter().cloned())
|
||||
);
|
||||
|
||||
@@ -62,6 +62,47 @@ fn no_differences() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_differences_report_identical_files() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// same file
|
||||
let mut file1 = NamedTempFile::new()?;
|
||||
file1.write_all("foo\n".as_bytes())?;
|
||||
for option in ["", "-u", "-c", "-e"] {
|
||||
let mut cmd = Command::cargo_bin("diffutils")?;
|
||||
if !option.is_empty() {
|
||||
cmd.arg(option);
|
||||
}
|
||||
cmd.arg("-s").arg(file1.path()).arg(file1.path());
|
||||
cmd.assert()
|
||||
.code(predicate::eq(0))
|
||||
.success()
|
||||
.stdout(predicate::eq(format!(
|
||||
"Files {} and {} are identical\n",
|
||||
file1.path().to_string_lossy(),
|
||||
file1.path().to_string_lossy(),
|
||||
)));
|
||||
}
|
||||
// two files with the same content
|
||||
let mut file2 = NamedTempFile::new()?;
|
||||
file2.write_all("foo\n".as_bytes())?;
|
||||
for option in ["", "-u", "-c", "-e"] {
|
||||
let mut cmd = Command::cargo_bin("diffutils")?;
|
||||
if !option.is_empty() {
|
||||
cmd.arg(option);
|
||||
}
|
||||
cmd.arg("-s").arg(file1.path()).arg(file2.path());
|
||||
cmd.assert()
|
||||
.code(predicate::eq(0))
|
||||
.success()
|
||||
.stdout(predicate::eq(format!(
|
||||
"Files {} and {} are identical\n",
|
||||
file1.path().to_string_lossy(),
|
||||
file2.path().to_string_lossy(),
|
||||
)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn differences() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut file1 = NamedTempFile::new()?;
|
||||
|
||||
Reference in New Issue
Block a user