Skip to content

Commit 6f140bf

Browse files
diff: implement -s
Also: fix a couple small bugs
1 parent f957698 commit 6f140bf

File tree

8 files changed

+202
-152
lines changed

8 files changed

+202
-152
lines changed

text/diff.rs

+25-17
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,16 @@
1414

1515
mod diff_util;
1616

17-
use std::{fs, io, path::PathBuf};
18-
1917
use clap::Parser;
2018
use diff_util::{
2119
common::{FormatOptions, OutputFormat},
2220
diff_exit_status::DiffExitStatus,
2321
dir_diff::DirDiff,
2422
file_diff::FileDiff,
25-
functions::check_existance,
23+
functions::check_existence,
2624
};
2725
use gettextrs::{bind_textdomain_codeset, setlocale, textdomain, LocaleCategory};
26+
use std::{fs, io, path::PathBuf};
2827

2928
/// diff - compare two files
3029
#[derive(Parser, Clone)]
@@ -54,6 +53,10 @@ struct Args {
5453
#[arg(short, long)]
5554
recurse: bool,
5655

56+
/// Print a message even when there are no differences between files
57+
#[arg(short = 's', long = "report-identical-files")]
58+
report_identical_files: bool,
59+
5760
/// Output 3 lines of unified context
5861
#[arg(short)]
5962
unified3: bool,
@@ -103,17 +106,16 @@ impl From<&Args> for OutputFormat {
103106
}
104107

105108
fn check_difference(args: Args) -> io::Result<DiffExitStatus> {
106-
let path1 = PathBuf::from(&args.file1);
107-
let path2 = PathBuf::from(&args.file2);
109+
let path1 = PathBuf::from(args.file1.as_str());
110+
let path2 = PathBuf::from(args.file2.as_str());
108111

109-
let path1_exists = check_existance(&path1)?;
110-
let path2_exists = check_existance(&path2)?;
112+
let path1_path = path1.as_path();
113+
let path2_path = path2.as_path();
111114

112-
if !path1_exists || !path2_exists {
113-
return Ok(DiffExitStatus::Trouble);
114-
}
115+
let path1_exists = check_existence(path1_path);
116+
let path2_exists = check_existence(path2_path);
115117

116-
if path1 == path2 {
118+
if !path1_exists || !path2_exists {
117119
return Ok(DiffExitStatus::Trouble);
118120
}
119121

@@ -124,18 +126,24 @@ fn check_difference(args: Args) -> io::Result<DiffExitStatus> {
124126
output_format,
125127
args.label,
126128
args.label2,
129+
args.report_identical_files,
127130
);
131+
128132
let format_options = format_options.unwrap();
129133

130-
let path1_is_file = fs::metadata(&path1)?.is_file();
131-
let path2_is_file = fs::metadata(&path2)?.is_file();
134+
let path1_is_file = fs::metadata(path1_path)?.is_file();
135+
let path2_is_file = fs::metadata(path2_path)?.is_file();
132136

133137
if path1_is_file && path2_is_file {
134-
FileDiff::file_diff(path1, path2, &format_options, None)
138+
FileDiff::file_diff(path1_path, path2_path, &format_options, None)
135139
} else if !path1_is_file && !path2_is_file {
136-
DirDiff::dir_diff(path1, path2, &format_options, args.recurse)
140+
DirDiff::dir_diff(path1_path, path2_path, &format_options, args.recurse)
137141
} else {
138-
FileDiff::file_dir_diff(path1, path2, &format_options)
142+
Ok(FileDiff::file_dir_diff(
143+
path1_path,
144+
path2_path,
145+
&format_options,
146+
)?)
139147
}
140148
}
141149

@@ -151,7 +159,7 @@ fn main() -> DiffExitStatus {
151159
match result {
152160
Ok(diff_exit_status) => diff_exit_status,
153161
Err(error) => {
154-
eprintln!("diff: {}", error);
162+
eprintln!("diff: {error}");
155163

156164
DiffExitStatus::Trouble
157165
}

text/diff_util/common.rs

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pub struct FormatOptions {
33
pub output_format: OutputFormat,
44
label1: Option<String>,
55
label2: Option<String>,
6+
pub report_identical_files: bool,
67
}
78

89
impl FormatOptions {
@@ -11,6 +12,7 @@ impl FormatOptions {
1112
output_format: OutputFormat,
1213
label1: Option<String>,
1314
label2: Option<String>,
15+
report_identical_files: bool,
1416
) -> Result<Self, &'static str> {
1517
if label1.is_none() && label2.is_some() {
1618
return Err("label1 can not be NONE when label2 is available");
@@ -21,6 +23,7 @@ impl FormatOptions {
2123
output_format,
2224
label1,
2325
label2,
26+
report_identical_files,
2427
})
2528
}
2629

text/diff_util/dir_data.rs

+10-12
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,19 @@ use std::{
33
ffi::OsString,
44
fs::{self, DirEntry},
55
io,
6-
path::PathBuf,
6+
path::{Display, Path},
77
};
88

9-
use super::constants::*;
10-
11-
pub struct DirData {
12-
path: PathBuf,
9+
pub struct DirData<'a> {
10+
path: &'a Path,
1311
files: HashMap<OsString, DirEntry>,
1412
}
1513

16-
impl DirData {
17-
pub fn load(path: PathBuf) -> io::Result<Self> {
14+
impl<'a> DirData<'a> {
15+
pub fn load(path: &'a Path) -> io::Result<Self> {
1816
let mut files: HashMap<OsString, DirEntry> = Default::default();
1917

20-
let entries = fs::read_dir(&path)?;
18+
let entries = fs::read_dir(path)?;
2119

2220
for entry in entries {
2321
let entry = entry?;
@@ -31,11 +29,11 @@ impl DirData {
3129
&self.files
3230
}
3331

34-
pub fn path(&self) -> &PathBuf {
35-
&self.path
32+
pub fn path(&'a self) -> &'a Path {
33+
self.path
3634
}
3735

38-
pub fn path_str(&self) -> &str {
39-
self.path.to_str().unwrap_or(COULD_NOT_UNWRAP_FILENAME)
36+
pub fn path_str(&self) -> Display {
37+
self.path.display()
4038
}
4139
}

text/diff_util/dir_diff.rs

+16-38
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{collections::HashSet, ffi::OsString, io, path::PathBuf};
1+
use std::{collections::HashSet, ffi::OsString, io, path::Path};
22

33
use crate::diff_util::{
44
constants::COULD_NOT_UNWRAP_FILENAME, diff_exit_status::DiffExitStatus, file_diff::FileDiff,
@@ -7,16 +7,16 @@ use crate::diff_util::{
77
use super::{common::FormatOptions, dir_data::DirData};
88

99
pub struct DirDiff<'a> {
10-
dir1: &'a mut DirData,
11-
dir2: &'a mut DirData,
10+
dir1: &'a mut DirData<'a>,
11+
dir2: &'a mut DirData<'a>,
1212
format_options: &'a FormatOptions,
1313
recursive: bool,
1414
}
1515

1616
impl<'a> DirDiff<'a> {
1717
fn new(
18-
dir1: &'a mut DirData,
19-
dir2: &'a mut DirData,
18+
dir1: &'a mut DirData<'a>,
19+
dir2: &'a mut DirData<'a>,
2020
format_options: &'a FormatOptions,
2121
recursive: bool,
2222
) -> Self {
@@ -29,8 +29,8 @@ impl<'a> DirDiff<'a> {
2929
}
3030

3131
pub fn dir_diff(
32-
path1: PathBuf,
33-
path2: PathBuf,
32+
path1: &Path,
33+
path2: &Path,
3434
format_options: &FormatOptions,
3535
recursive: bool,
3636
) -> io::Result<DiffExitStatus> {
@@ -48,15 +48,7 @@ impl<'a> DirDiff<'a> {
4848
let is_file = dir_data
4949
.files()
5050
.get_key_value(file_name)
51-
.unwrap_or_else(|| {
52-
panic!(
53-
"Could not find file in {}",
54-
dir_data
55-
.path()
56-
.to_str()
57-
.unwrap_or(COULD_NOT_UNWRAP_FILENAME)
58-
)
59-
})
51+
.unwrap_or_else(|| panic!("Could not find file in {}", dir_data.path().display()))
6052
.1
6153
.file_type()?
6254
.is_file();
@@ -141,8 +133,8 @@ impl<'a> DirDiff<'a> {
141133
}
142134

143135
let inner_exit_status = FileDiff::file_diff(
144-
path1,
145-
path2,
136+
path1.as_path(),
137+
path2.as_path(),
146138
self.format_options,
147139
Some(show_if_different),
148140
)?;
@@ -153,37 +145,23 @@ impl<'a> DirDiff<'a> {
153145
} else if !in_dir1_is_file && !in_dir2_is_file {
154146
if self.recursive {
155147
Self::dir_diff(
156-
self.dir1.path().join(file_name),
157-
self.dir2.path().join(file_name),
148+
self.dir1.path().join(file_name).as_path(),
149+
self.dir2.path().join(file_name).as_path(),
158150
self.format_options,
159151
self.recursive,
160152
)?;
161153
} else {
162154
println!(
163155
"Common subdirectories: \"{}\" and \"{}\"",
164-
self.dir1
165-
.path()
166-
.join(file_name)
167-
.to_str()
168-
.unwrap_or(COULD_NOT_UNWRAP_FILENAME),
169-
self.dir2
170-
.path()
171-
.join(file_name)
172-
.to_str()
173-
.unwrap_or(COULD_NOT_UNWRAP_FILENAME)
156+
self.dir1.path().join(file_name).display(),
157+
self.dir2.path().join(file_name).display()
174158
);
175159
}
176160
} else {
177161
let (file, dir) = if in_dir1_is_file && !in_dir2_is_file {
178-
(
179-
path1.to_str().unwrap_or(COULD_NOT_UNWRAP_FILENAME),
180-
path2.to_str().unwrap_or(COULD_NOT_UNWRAP_FILENAME),
181-
)
162+
(path1.display(), path2.display())
182163
} else {
183-
(
184-
path2.to_str().unwrap_or(COULD_NOT_UNWRAP_FILENAME),
185-
path1.to_str().unwrap_or(COULD_NOT_UNWRAP_FILENAME),
186-
)
164+
(path2.display(), path1.display())
187165
};
188166

189167
println!(

text/diff_util/file_data.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1-
use std::{fs::File, io, mem::take, path::PathBuf, str::from_utf8, time::SystemTime};
1+
use std::{
2+
fs::File,
3+
io,
4+
mem::take,
5+
path::{Display, Path},
6+
str::from_utf8,
7+
time::SystemTime,
8+
};
29

310
use super::constants::COULD_NOT_UNWRAP_FILENAME;
411

512
#[derive(Debug)]
613
pub struct FileData<'a> {
7-
path: PathBuf,
14+
path: &'a Path,
815
lines: Vec<&'a str>,
916
modified: SystemTime,
1017
ends_with_newline: bool,
@@ -16,11 +23,11 @@ impl<'a> FileData<'a> {
1623
}
1724

1825
pub fn get_file(
19-
path: PathBuf,
26+
path: &'a Path,
2027
lines: Vec<&'a str>,
2128
ends_with_newline: bool,
2229
) -> io::Result<Self> {
23-
let file = File::open(&path)?;
30+
let file = File::open(path)?;
2431
let modified = file.metadata()?.modified()?;
2532

2633
Ok(Self {
@@ -53,8 +60,8 @@ impl<'a> FileData<'a> {
5360
COULD_NOT_UNWRAP_FILENAME
5461
}
5562

56-
pub fn path(&self) -> &str {
57-
self.path.to_str().unwrap_or(COULD_NOT_UNWRAP_FILENAME)
63+
pub fn path(&self) -> Display {
64+
self.path.display()
5865
}
5966
}
6067

0 commit comments

Comments
 (0)