Skip to content

Commit b8001cc

Browse files
stdin: Handle directory input
When handling stdin, GNU diff now behaves as follows: * If a file is input, it displays the current time as m_time * If a directory is input, it appends the other file_name to the canonicalized path of directory and reads and displays the m_time of that file
1 parent d922313 commit b8001cc

File tree

4 files changed

+50
-10
lines changed

4 files changed

+50
-10
lines changed

src/context_diff.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,16 @@ fn make_diff(
268268

269269
#[must_use]
270270
pub fn diff(expected: &[u8], actual: &[u8], params: &Params) -> Vec<u8> {
271-
let from_modified_time = get_modification_time(&params.from.to_string_lossy());
272-
let to_modified_time = get_modification_time(&params.to.to_string_lossy());
271+
let from_modified_time =
272+
match !params.stdin_path.is_empty() && params.from.to_string_lossy().starts_with("-") {
273+
true => get_modification_time(&params.stdin_path.to_string_lossy()),
274+
false => get_modification_time(&params.from.to_string_lossy()),
275+
};
276+
let to_modified_time =
277+
match !params.stdin_path.is_empty() && params.to.to_string_lossy().starts_with("-") {
278+
true => get_modification_time(&params.stdin_path.to_string_lossy()),
279+
false => get_modification_time(&params.to.to_string_lossy()),
280+
};
273281
let mut output = format!(
274282
"*** {0}\t{1}\n--- {2}\t{3}\n",
275283
params.from.to_string_lossy(),

src/main.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,24 @@ fn main() -> ExitCode {
4646
return ExitCode::SUCCESS;
4747
}
4848
// read files
49-
fn read_file_contents(filepath: &OsString) -> io::Result<Vec<u8>> {
50-
if filepath == "-" {
49+
fn read_file_contents(filepath: &OsString, stdin_path: &OsString) -> io::Result<Vec<u8>> {
50+
if filepath.to_string_lossy().starts_with("-") && !stdin_path.is_empty() {
51+
fs::read(stdin_path)
52+
} else if filepath == "-" {
5153
let mut content = Vec::new();
5254
io::stdin().read_to_end(&mut content).and(Ok(content))
5355
} else {
5456
fs::read(filepath)
5557
}
5658
}
57-
let from_content = match read_file_contents(&params.from) {
59+
let from_content = match read_file_contents(&params.from, &params.stdin_path) {
5860
Ok(from_content) => from_content,
5961
Err(e) => {
6062
eprintln!("Failed to read from-file: {e}");
6163
return ExitCode::from(2);
6264
}
6365
};
64-
let to_content = match read_file_contents(&params.to) {
66+
let to_content = match read_file_contents(&params.to, &params.stdin_path) {
6567
Ok(to_content) => to_content,
6668
Err(e) => {
6769
eprintln!("Failed to read to-file: {e}");

src/params.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
use std::ffi::OsString;
2+
use std::fs;
23
use std::path::PathBuf;
34

5+
use std::fs::File;
6+
use std::io::stdin;
7+
use std::os::fd::AsFd;
8+
49
use regex::Regex;
510

611
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
@@ -16,6 +21,7 @@ pub enum Format {
1621
pub struct Params {
1722
pub from: OsString,
1823
pub to: OsString,
24+
pub stdin_path: OsString,
1925
pub format: Format,
2026
pub context_count: usize,
2127
pub report_identical_files: bool,
@@ -29,6 +35,7 @@ impl Default for Params {
2935
Self {
3036
from: OsString::default(),
3137
to: OsString::default(),
38+
stdin_path: OsString::default(),
3239
format: Format::default(),
3340
context_count: 3,
3441
report_identical_files: false,
@@ -178,10 +185,25 @@ pub fn parse_params<I: IntoIterator<Item = OsString>>(opts: I) -> Result<Params,
178185
let mut from_path: PathBuf = PathBuf::from(&params.from);
179186
let mut to_path: PathBuf = PathBuf::from(&params.to);
180187

181-
if from_path.is_dir() && to_path.is_file() {
188+
// check if stdin is a directory
189+
let fd = stdin().as_fd().try_clone_to_owned().unwrap();
190+
let file = File::from(fd);
191+
let meta = file.metadata().unwrap();
192+
if meta.is_dir() {
193+
let stdin = fs::canonicalize("/dev/stdin").unwrap();
194+
let mut stdin_path: PathBuf = PathBuf::from(stdin);
195+
if params.from == "-" {
196+
stdin_path.push(&to_path.file_name().unwrap());
197+
} else {
198+
stdin_path.push(&from_path.file_name().unwrap());
199+
}
200+
params.stdin_path = stdin_path.into();
201+
}
202+
203+
if (from_path.is_dir() || !params.stdin_path.is_empty()) && to_path.is_file() {
182204
from_path.push(to_path.file_name().unwrap());
183205
params.from = from_path.into_os_string();
184-
} else if from_path.is_file() && to_path.is_dir() {
206+
} else if from_path.is_file() && (to_path.is_dir() || !params.stdin_path.is_empty()) {
185207
to_path.push(from_path.file_name().unwrap());
186208
params.to = to_path.into_os_string();
187209
}

src/unified_diff.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,16 @@ fn make_diff(
239239

240240
#[must_use]
241241
pub fn diff(expected: &[u8], actual: &[u8], params: &Params) -> Vec<u8> {
242-
let from_modified_time = get_modification_time(&params.from.to_string_lossy());
243-
let to_modified_time = get_modification_time(&params.to.to_string_lossy());
242+
let from_modified_time =
243+
match !params.stdin_path.is_empty() && params.from.to_string_lossy().starts_with("-") {
244+
true => get_modification_time(&params.stdin_path.to_string_lossy()),
245+
false => get_modification_time(&params.from.to_string_lossy()),
246+
};
247+
let to_modified_time =
248+
match !params.stdin_path.is_empty() && params.to.to_string_lossy().starts_with("-") {
249+
true => get_modification_time(&params.stdin_path.to_string_lossy()),
250+
false => get_modification_time(&params.to.to_string_lossy()),
251+
};
244252
let mut output = format!(
245253
"--- {0}\t{1}\n+++ {2}\t{3}\n",
246254
params.from.to_string_lossy(),

0 commit comments

Comments
 (0)