Skip to content

Commit 1734430

Browse files
committed
version 1
1 parent 7e6dd20 commit 1734430

File tree

2 files changed

+87
-44
lines changed

2 files changed

+87
-44
lines changed

src/file_util.rs

Lines changed: 70 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ use blake3::Hash;
66
use color_eyre::{
77
Result,
88
eyre::{
9+
Context,
910
OptionExt,
1011
eyre,
1112
},
1213
};
1314
use log::{
15+
debug,
1416
info,
1517
warn,
1618
};
@@ -68,15 +70,15 @@ impl From<&File> for FileWithMetadata {
6870
}
6971
impl FileWithMetadata {
7072
pub fn activate(&mut self, clobber_by_default: bool, prefix: &str) -> Result<()> {
71-
if self.missing_source() {
73+
if self.check_source() {
7274
return Ok(());
7375
}
7476

7577
self.set_metadata()?;
7678

7779
let clobber = self.clobber.unwrap_or(clobber_by_default);
7880

79-
if clobber && self.metadata.is_some() && self.atomic_activate()? {
81+
if clobber && self.metadata.is_some() && self.atomic_activate().wrap_err("(atomic)")? {
8082
return Ok(());
8183
};
8284

@@ -110,7 +112,7 @@ impl FileWithMetadata {
110112

111113
match self.kind {
112114
FileKind::Directory => self.directory(),
113-
FileKind::File => self.copy(),
115+
FileKind::Copy => self.copy(),
114116
FileKind::Symlink => self.symlink(),
115117
FileKind::Modify => self.chmod_chown(),
116118
FileKind::Delete => delete(&self.target, self.metadata.as_ref().unwrap()),
@@ -119,14 +121,14 @@ impl FileWithMetadata {
119121

120122
pub fn atomic_activate(&mut self) -> Result<bool> {
121123
match self.kind {
122-
FileKind::Symlink | FileKind::File => {
124+
FileKind::Symlink | FileKind::Copy => {
123125
let target_is_dir = self.metadata.as_ref().unwrap().is_dir();
124-
let target_is_empty = self.source.as_ref().unwrap().read_dir()?.next().is_none();
125-
126126
let source_is_dir = fs::symlink_metadata(self.source.as_ref().unwrap())?.is_dir();
127127

128128
if target_is_dir != source_is_dir
129-
|| target_is_dir && source_is_dir && !target_is_empty
129+
|| target_is_dir
130+
&& source_is_dir
131+
&& self.source.as_ref().unwrap().read_dir()?.next().is_some()
130132
{
131133
return Ok(false);
132134
};
@@ -136,7 +138,7 @@ impl FileWithMetadata {
136138
self.target.set_extension("smfh-temp");
137139
match self.kind {
138140
FileKind::Symlink => self.symlink(),
139-
FileKind::File => self.copy(),
141+
FileKind::Copy => self.copy(),
140142
_ => panic!("This should never happen"),
141143
}?;
142144
info!(
@@ -172,9 +174,17 @@ impl FileWithMetadata {
172174
// no-op on deactivation
173175
FileKind::Delete | FileKind::Modify => Ok(()),
174176
// delete only if directory is empty
175-
FileKind::Directory => rmdir(&self.target),
177+
FileKind::Directory => match self.metadata.as_ref() {
178+
Some(x) if x.is_dir() => {
179+
fs::remove_dir(&self.target)?;
180+
info!("Deleting directory '{}'", self.target.display());
181+
Ok(())
182+
}
183+
Some(_) => Err(eyre!("File is not directory")),
184+
None => Err(eyre!("Cannot access file")),
185+
},
176186
// delete only if types match
177-
FileKind::Symlink | FileKind::File => {
187+
FileKind::Symlink | FileKind::Copy => {
178188
delete(&self.target, self.metadata.as_ref().unwrap())
179189
}
180190
}
@@ -197,12 +207,12 @@ impl FileWithMetadata {
197207
// function is ever called
198208
FileWithMetadata {
199209
source: None,
200-
kind: FileKind::Symlink | FileKind::File,
210+
kind: FileKind::Symlink | FileKind::Copy,
201211
ref target,
202212
..
203213
} => Err(eyre!("File '{}' missing_source", target.display())),
204214
FileWithMetadata {
205-
kind: FileKind::File | FileKind::Directory | FileKind::Modify,
215+
kind: FileKind::Copy | FileKind::Directory | FileKind::Modify,
206216
permissions: Some(perms),
207217
metadata: Some(ref metadata),
208218
..
@@ -237,12 +247,12 @@ impl FileWithMetadata {
237247
..
238248
} => Ok(metadata.is_dir()),
239249
FileWithMetadata {
240-
kind: FileKind::File,
241-
metadata: Some(ref metadata),
250+
kind: FileKind::Copy,
251+
metadata: Some(ref metadata),
242252
..
243253
} if !metadata.is_file() => Ok(false),
244254
FileWithMetadata {
245-
kind: FileKind::File,
255+
kind: FileKind::Copy,
246256
ref target,
247257
source: Some(ref source),
248258
..
@@ -264,29 +274,61 @@ impl FileWithMetadata {
264274
}
265275

266276
pub fn set_metadata(&mut self) -> Result<()> {
267-
let metadata = fs::symlink_metadata(&self.target);
268-
if let Err(ref e) = metadata {
269-
if e.kind() == std::io::ErrorKind::NotFound {
277+
match fs::symlink_metadata(&self.target) {
278+
Ok(x) => {
279+
self.metadata = Some(x);
280+
Ok(())
281+
}
282+
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
270283
self.metadata = None;
271-
return Ok(());
272-
};
284+
Ok(())
285+
}
286+
Err(e) => Err(e).wrap_err("while setting metadata"),
273287
}
274-
self.metadata = Some(metadata?);
275-
Ok(())
276288
}
277-
pub fn missing_source(&self) -> bool {
289+
pub fn check_source(&self) -> bool {
278290
match *self {
291+
FileWithMetadata {
292+
source: Some(ref s),
293+
kind: FileKind::Copy | FileKind::Symlink,
294+
..
295+
} if fs::symlink_metadata(s)
296+
.is_err_and(|e| e.kind() == std::io::ErrorKind::NotFound) =>
297+
{
298+
warn!(
299+
"{} with target '{}' source '{}' does not exist",
300+
self.kind,
301+
self.target.display(),
302+
s.display()
303+
);
304+
true
305+
}
279306
FileWithMetadata {
280307
source: None,
281-
kind: FileKind::File | FileKind::Symlink,
308+
kind: FileKind::Copy | FileKind::Symlink,
282309
..
283310
} => {
284311
warn!(
285-
"File '{}' missing source, skipping...",
312+
"{} with target '{}' missing source, skipping...",
313+
self.kind,
286314
self.target.display()
287315
);
288316
true
289317
}
318+
FileWithMetadata {
319+
source: Some(ref s),
320+
kind: FileKind::Copy,
321+
..
322+
} if fs::symlink_metadata(s).is_ok_and(|x| !x.is_file()) => {
323+
warn!(
324+
"{} with target '{}' source '{}' is a directory, only files are permitted. Skipping...",
325+
self.kind,
326+
self.target.display(),
327+
s.display()
328+
);
329+
true
330+
}
331+
290332
_ => false,
291333
}
292334
}
@@ -397,7 +439,7 @@ pub fn mkdir(path: &Path) -> Result<()> {
397439
if !x.is_dir() {
398440
return Err(eyre!("File in way of '{}'", path.display()));
399441
};
400-
info!("Directory '{}' already exists", path.display());
442+
debug!("Directory '{}' already exists", path.display());
401443
}
402444
};
403445
Ok(())
@@ -421,27 +463,15 @@ pub fn prefix_move(path: &Path, prefix: &str) -> Result<()> {
421463
.ok_or_eyre(format!("Failed to get parent of file '{}'", path.display()))?
422464
.join(PathBuf::from(appended_path));
423465

424-
if fs::symlink_metadata(&new_path).is_ok() {
425-
prefix_move(&new_path, prefix)?;
466+
if let Ok(metadata) = fs::symlink_metadata(&new_path) {
467+
delete(&new_path, &metadata)?;
426468
};
427469

428470
fs::rename(canon_path, &new_path)?;
429471
info!("Renaming '{}' -> '{}'", path.display(), new_path.display());
430472
Ok(())
431473
}
432474

433-
pub fn rmdir(path: &Path) -> Result<()> {
434-
let Ok(metadata) = fs::symlink_metadata(path) else {
435-
return Ok(());
436-
};
437-
if !metadata.is_dir() {
438-
return Err(eyre!("Path '{}' is not a directory", path.display()));
439-
}
440-
fs::remove_dir(path)?;
441-
info!("Deleting directory '{}'", path.display());
442-
Ok(())
443-
}
444-
445475
pub fn hash_file(filepath: &Path) -> Option<Hash> {
446476
let mut hasher = blake3::Hasher::new();
447477

src/manifest.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use serde::{
2424
};
2525
use std::{
2626
cmp::Ordering,
27+
fmt,
2728
fs::{
2829
self,
2930
},
@@ -69,18 +70,30 @@ pub struct File {
6970
#[serde(rename_all = "camelCase")]
7071
pub enum FileKind {
7172
Directory,
72-
File,
73+
Copy,
7374
Symlink,
7475
Modify,
7576
Delete,
7677
}
78+
impl fmt::Display for FileKind {
79+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80+
let name = match self {
81+
FileKind::Directory => "directory",
82+
FileKind::Copy => "copy",
83+
FileKind::Symlink => "symlink",
84+
FileKind::Modify => "modify",
85+
FileKind::Delete => "delete",
86+
};
87+
write!(f, "{name}")
88+
}
89+
}
7790

7891
impl Ord for FileKind {
7992
fn cmp(&self, other: &Self) -> Ordering {
8093
fn value(kind: FileKind) -> u8 {
8194
match kind {
8295
FileKind::Directory => 1,
83-
FileKind::File => 2,
96+
FileKind::Copy => 2,
8497
FileKind::Symlink => 3,
8598
FileKind::Modify => 4,
8699
FileKind::Delete => 5,
@@ -157,7 +170,7 @@ impl Manifest {
157170
keep = !keep;
158171
} else if let Some(index) = self.files.iter().position(|inner| {
159172
matches!(inner, File {
160-
kind: FileKind::Symlink | FileKind::File,
173+
kind: FileKind::Symlink | FileKind::Copy,
161174
target,
162175
..
163176
} if target == &f.target)
@@ -205,7 +218,7 @@ impl Manifest {
205218
.atomic_activate()
206219
.inspect_err(|e| {
207220
error!(
208-
"Failed to activate file: '{}'\n Reason: '{}'",
221+
"Failed to (atomic) activate file: '{}'\n Reason: '{}'",
209222
new.target.display(),
210223
e
211224
);

0 commit comments

Comments
 (0)