mirror of
https://github.com/nivekuil/rip
synced 2024-11-10 06:04:17 +00:00
Canonicalize non-symlink paths
This commit is contained in:
parent
f987ff53cc
commit
144fb35dba
2 changed files with 47 additions and 45 deletions
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "rm-improved"
|
name = "rm-improved"
|
||||||
version = "0.11.0"
|
version = "0.11.1"
|
||||||
authors = ["mail@nivekuil.com"]
|
authors = ["mail@nivekuil.com"]
|
||||||
description = "rip: a safe and ergonomic alternative to rm"
|
description = "rip: a safe and ergonomic alternative to rm"
|
||||||
repository = "https://github.com/nivekuil/rip"
|
repository = "https://github.com/nivekuil/rip"
|
||||||
|
|
90
src/main.rs
90
src/main.rs
|
@ -153,22 +153,26 @@ Send files to the graveyard (/tmp/graveyard-$USER by default) instead of unlinki
|
||||||
|
|
||||||
if let Some(targets) = matches.values_of("TARGET") {
|
if let Some(targets) = matches.values_of("TARGET") {
|
||||||
for target in targets {
|
for target in targets {
|
||||||
let source: &Path = &cwd.join(Path::new(target));
|
|
||||||
|
|
||||||
// Check if source exists
|
// Check if source exists
|
||||||
if let Ok(metadata) = source.symlink_metadata() {
|
if let Ok(metadata) = fs::symlink_metadata(target) {
|
||||||
|
// Canonicalize the path unless it's a symlink
|
||||||
|
let source = &if !metadata.file_type().is_symlink() {
|
||||||
|
cwd.join(target).canonicalize().expect("Failed to canonicalize")
|
||||||
|
} else {
|
||||||
|
cwd.join(target)
|
||||||
|
};
|
||||||
|
|
||||||
if matches.is_present("inspect") {
|
if matches.is_present("inspect") {
|
||||||
if metadata.is_dir() {
|
if metadata.is_dir() {
|
||||||
// Get the size of the directory and all its contents
|
// Get the size of the directory and all its contents
|
||||||
println!("{}: directory, {} including:", target,
|
println!("{}: directory, {} including:", target,
|
||||||
humanize_bytes(
|
humanize_bytes(
|
||||||
WalkDir::new(source)
|
WalkDir::new(source)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|x| x.ok())
|
.filter_map(|x| x.ok())
|
||||||
.filter_map(|x| x.metadata().ok())
|
.filter_map(|x| x.metadata().ok())
|
||||||
.map(|x| x.len())
|
.map(|x| x.len())
|
||||||
.sum::<u64>()));
|
.sum::<u64>()));
|
||||||
|
|
||||||
// Print the first few top-level files in the directory
|
// Print the first few top-level files in the directory
|
||||||
for entry in WalkDir::new(source)
|
for entry in WalkDir::new(source)
|
||||||
|
@ -197,41 +201,39 @@ Send files to the graveyard (/tmp/graveyard-$USER by default) instead of unlinki
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If rip is called on a file already in the graveyard, prompt
|
||||||
|
// to permanently delete it instead.
|
||||||
|
if source.starts_with(graveyard) {
|
||||||
|
println!("{} is already in the graveyard.", source.display());
|
||||||
|
if prompt_yes("Permanently unlink it?") {
|
||||||
|
if fs::remove_dir_all(source).is_err() {
|
||||||
|
if let Err(e) = fs::remove_file(source) {
|
||||||
|
println!("Couldn't unlink {}:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dest: &Path = &{
|
||||||
|
let dest = join_absolute(graveyard, source);
|
||||||
|
// Resolve a name conflict if necessary
|
||||||
|
if symlink_exists(&dest) {
|
||||||
|
rename_grave(dest)
|
||||||
|
} else {
|
||||||
|
dest
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = bury(source, dest) {
|
||||||
|
println!("ERROR: {}: {}", e, target);
|
||||||
|
// Clean up any partial buries due to permission error
|
||||||
|
fs::remove_dir_all(dest).is_ok();
|
||||||
|
} else if let Err(e) = write_log(source, dest, record) {
|
||||||
|
println!("Error adding {} to record: {}", target, e);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
println!("Cannot remove {}: no such file or directory", target);
|
println!("Cannot remove {}: no such file or directory", target);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If rip is called on a file already in the graveyard, prompt
|
|
||||||
// to permanently delete it instead.
|
|
||||||
if source.starts_with(graveyard) {
|
|
||||||
println!("{} is already in the graveyard.", source.display());
|
|
||||||
if prompt_yes("Permanently unlink it?") {
|
|
||||||
if fs::remove_dir_all(source).is_err() {
|
|
||||||
if let Err(e) = fs::remove_file(source) {
|
|
||||||
println!("Couldn't unlink {}:", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let dest: &Path = &{
|
|
||||||
let dest = join_absolute(graveyard, source);
|
|
||||||
// Resolve a name conflict if necessary
|
|
||||||
if symlink_exists(&dest) {
|
|
||||||
rename_grave(dest)
|
|
||||||
} else {
|
|
||||||
dest
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(e) = bury(source, dest) {
|
|
||||||
println!("ERROR: {}: {}", e, target);
|
|
||||||
// Clean up any partial buries due to permission error
|
|
||||||
fs::remove_dir_all(dest).is_ok();
|
|
||||||
} else if let Err(e) = write_log(source, dest, record) {
|
|
||||||
println!("Error adding {} to record: {}", target, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -262,7 +264,7 @@ fn bury<S: AsRef<Path>, D: AsRef<Path>>(source: S, dest: D) -> io::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If that didn't work, then copy and rm.
|
// If that didn't work, then copy and rm.
|
||||||
let parent = dest.parent().ok_or(io::Error::last_os_error())?;
|
let parent = dest.parent().ok_or_else(|| io::Error::from(io::ErrorKind::NotFound))?;
|
||||||
fs::create_dir_all(parent)?;
|
fs::create_dir_all(parent)?;
|
||||||
|
|
||||||
if fs::symlink_metadata(source)?.is_dir() {
|
if fs::symlink_metadata(source)?.is_dir() {
|
||||||
|
|
Loading…
Reference in a new issue