mirror of
https://github.com/nivekuil/rip
synced 2025-02-16 20:18:25 +00:00
Factor out fn to delete line from record
This commit is contained in:
parent
cfc4ac81ba
commit
4a228e0e59
1 changed files with 45 additions and 49 deletions
94
src/main.rs
94
src/main.rs
|
@ -93,8 +93,9 @@ Send files to the graveyard (/tmp/.graveyard) instead of unlinking them.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut s) = matches.values_of("resurrect") {
|
if let Some(mut s) = matches.values_of("resurrect") {
|
||||||
// Vector to hold the grave path of resurrected items
|
// Vector to hold the grave path of resurrected items that we want
|
||||||
let mut skip: Vec<String> = Vec::new();
|
// to remove from the record following the resurrect
|
||||||
|
let mut graves_to_exhume: Vec<String> = Vec::new();
|
||||||
// Handle any arguments were passed to --resurrect
|
// Handle any arguments were passed to --resurrect
|
||||||
while let Some(grave) = s.next() {
|
while let Some(grave) = s.next() {
|
||||||
let dest = grave.trim_left_matches(
|
let dest = grave.trim_left_matches(
|
||||||
|
@ -104,12 +105,12 @@ Send files to the graveyard (/tmp/.graveyard) instead of unlinking them.")
|
||||||
} else {
|
} else {
|
||||||
println!("Returned {} to {}", grave, dest);
|
println!("Returned {} to {}", grave, dest);
|
||||||
}
|
}
|
||||||
skip.push(grave.to_string());
|
graves_to_exhume.push(grave.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, return the last deleted file
|
// Otherwise, return the last deleted file
|
||||||
if skip.len() == 0 {
|
if graves_to_exhume.len() == 0 {
|
||||||
if let Ok(s) = get_last_bury(record, graveyard) {
|
if let Ok(s) = get_last_bury(record) {
|
||||||
let (orig, grave) = {
|
let (orig, grave) = {
|
||||||
let record_line = record_line(s.as_str());
|
let record_line = record_line(s.as_str());
|
||||||
(record_line.orig, record_line.dest)
|
(record_line.orig, record_line.dest)
|
||||||
|
@ -126,32 +127,13 @@ Send files to the graveyard (/tmp/.graveyard) instead of unlinking them.")
|
||||||
} else {
|
} else {
|
||||||
println!("Returned {} to {}", grave, dest.display());
|
println!("Returned {} to {}", grave, dest.display());
|
||||||
}
|
}
|
||||||
skip.push(grave.to_string());
|
graves_to_exhume.push(grave.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the lines to write back
|
if let Err(e) = delete_line_from_record(record, graves_to_exhume) {
|
||||||
let lines: Vec<String> = {
|
println!("Failed to delete resurrects from grave record: {}", e)
|
||||||
if let Ok(f) = fs::File::open(record) {
|
|
||||||
BufReader::new(f)
|
|
||||||
.lines()
|
|
||||||
.filter_map(|l| l.ok())
|
|
||||||
.filter(|l| skip.clone().into_iter()
|
|
||||||
.any(|y| y != record_line(l.as_str()).dest))
|
|
||||||
.collect()
|
|
||||||
} else {
|
|
||||||
println!("Failed to read record.");
|
|
||||||
return
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if let Ok(mut f) = fs::File::create(record) {
|
|
||||||
for line in lines {
|
|
||||||
// println!("WRITING {}", line);
|
|
||||||
writeln!(f, "{}", line).unwrap();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println!("Failed to write record.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -343,39 +325,28 @@ fn copy_file<S, D>(source: S, dest: D) -> io::Result<()>
|
||||||
|
|
||||||
/// Return the line in record corresponding to the last buried file still in
|
/// Return the line in record corresponding to the last buried file still in
|
||||||
/// the graveyard
|
/// the graveyard
|
||||||
fn get_last_bury<R, G>(record: R, graveyard: G) -> io::Result<String>
|
fn get_last_bury<R: AsRef<Path>>(record: R) -> io::Result<String> {
|
||||||
where R: AsRef<Path>, G: AsRef<Path> {
|
let record = record.as_ref();
|
||||||
match fs::File::open(record) {
|
match fs::File::open(record) {
|
||||||
Ok(mut f) => {
|
Ok(mut f) => {
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
f.read_to_string(&mut contents)?;
|
f.read_to_string(&mut contents)?;
|
||||||
let mut stack: Vec<&str> = Vec::new();
|
|
||||||
|
|
||||||
for line in contents.lines().rev() {
|
for line in contents.lines().rev() {
|
||||||
let (user, orig, grave) = {
|
let (user, grave) = {
|
||||||
let record_line = record_line(line);
|
let record_line = record_line(line);
|
||||||
(record_line.user, record_line.orig, record_line.dest)
|
(record_line.user, record_line.dest)
|
||||||
};
|
};
|
||||||
// Only resurrect files buried by the same user
|
// Only resurrect files buried by the same user
|
||||||
if user != get_user() { continue }
|
if user != get_user() { continue }
|
||||||
// Check if this is a resurrect. If it is, then add the orig
|
|
||||||
// file onto the stack to match with the last buried
|
|
||||||
if Path::new(orig).starts_with(&graveyard) {
|
|
||||||
stack.push(orig);
|
|
||||||
} else {
|
|
||||||
if let Some(p) = stack.pop() {
|
|
||||||
if p == grave { continue }
|
|
||||||
}
|
|
||||||
// If the top of the resurrect stack does not match the
|
|
||||||
// buried item, then this might be the file to bring back.
|
|
||||||
// Check that the file is still in the graveyard.
|
|
||||||
// If it is, return the corresponding line.
|
|
||||||
if symlink_exists(grave) {
|
|
||||||
return Ok(String::from(line))
|
|
||||||
} else {
|
|
||||||
// File was moved, remove the line from record
|
|
||||||
|
|
||||||
}
|
// Check that the file is still in the graveyard.
|
||||||
|
// If it is, return the corresponding line.
|
||||||
|
if symlink_exists(grave) {
|
||||||
|
return Ok(String::from(line))
|
||||||
|
} else {
|
||||||
|
// File was moved, remove the line from record
|
||||||
|
delete_line_from_record(record, vec![String::from(line)])?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "But nobody came"))
|
Err(io::Error::new(io::ErrorKind::Other, "But nobody came"))
|
||||||
|
@ -384,6 +355,7 @@ fn get_last_bury<R, G>(record: R, graveyard: G) -> io::Result<String>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a line in the record into a RecordItem
|
||||||
fn record_line(line: &str) -> RecordItem {
|
fn record_line(line: &str) -> RecordItem {
|
||||||
let mut tokens = line.split("\t");
|
let mut tokens = line.split("\t");
|
||||||
let user: &str = tokens.next().expect("Bad format: column A");
|
let user: &str = tokens.next().expect("Bad format: column A");
|
||||||
|
@ -391,3 +363,27 @@ fn record_line(line: &str) -> RecordItem {
|
||||||
let dest: &str = tokens.next().expect("Bad format: column C");
|
let dest: &str = tokens.next().expect("Bad format: column C");
|
||||||
RecordItem { user: user, orig: orig, dest: dest }
|
RecordItem { user: user, orig: orig, dest: dest }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn delete_line_from_record<R>(record: R, graves_to_exhume: Vec<String>)
|
||||||
|
-> io::Result<()> where R: AsRef<Path> {
|
||||||
|
let record = record.as_ref();
|
||||||
|
// Get the lines to write back to record
|
||||||
|
let lines: Vec<String> = {
|
||||||
|
match fs::File::open(record) {
|
||||||
|
Ok(f) => BufReader::new(f)
|
||||||
|
.lines()
|
||||||
|
.filter_map(|l| l.ok())
|
||||||
|
.filter(|l| graves_to_exhume.clone().into_iter()
|
||||||
|
.any(|y| y != record_line(l.as_str()).dest))
|
||||||
|
.collect(),
|
||||||
|
Err(e) => return Err(e)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match fs::File::create(record) {
|
||||||
|
Ok(mut f) => for line in lines {
|
||||||
|
writeln!(f, "{}", line).unwrap();
|
||||||
|
},
|
||||||
|
Err(e) => return Err(e)
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue