mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
Allow truncate to take --size and --reference
This commit is contained in:
parent
7dcc8c2960
commit
a7037b1ca9
2 changed files with 52 additions and 22 deletions
|
@ -16,6 +16,7 @@ use std::path::Path;
|
|||
|
||||
#[derive(Eq, PartialEq)]
|
||||
enum TruncateMode {
|
||||
Absolute,
|
||||
Reference,
|
||||
Extend,
|
||||
Reduce,
|
||||
|
@ -131,18 +132,30 @@ fn truncate(
|
|||
size: Option<String>,
|
||||
filenames: Vec<String>,
|
||||
) {
|
||||
let (refsize, mode) = match reference {
|
||||
Some(rfilename) => {
|
||||
let _ = match File::open(Path::new(&rfilename)) {
|
||||
let (modsize, mode) = match size {
|
||||
Some(size_string) => parse_size(&size_string),
|
||||
None => (0, TruncateMode::Reference),
|
||||
};
|
||||
|
||||
let refsize = match reference {
|
||||
Some(ref rfilename) => {
|
||||
match mode {
|
||||
// Only Some modes work with a reference
|
||||
TruncateMode::Reference => (), //No --size was given
|
||||
TruncateMode::Extend => (),
|
||||
TruncateMode::Reduce => (),
|
||||
_ => crash!(1, "you must specify a relative ‘--size’ with ‘--reference’"),
|
||||
};
|
||||
let _ = match File::open(Path::new(rfilename)) {
|
||||
Ok(m) => m,
|
||||
Err(f) => crash!(1, "{}", f.to_string()),
|
||||
};
|
||||
match metadata(rfilename) {
|
||||
Ok(meta) => (meta.len(), TruncateMode::Reference),
|
||||
Ok(meta) => meta.len(),
|
||||
Err(f) => crash!(1, "{}", f.to_string()),
|
||||
}
|
||||
}
|
||||
None => parse_size(size.unwrap().as_ref()),
|
||||
None => 0,
|
||||
};
|
||||
for filename in &filenames {
|
||||
let path = Path::new(filename);
|
||||
|
@ -153,33 +166,37 @@ fn truncate(
|
|||
.open(path)
|
||||
{
|
||||
Ok(file) => {
|
||||
let fsize = match metadata(filename) {
|
||||
let fsize = match reference {
|
||||
Some(_) => refsize,
|
||||
None => match metadata(filename) {
|
||||
Ok(meta) => meta.len(),
|
||||
Err(f) => {
|
||||
show_warning!("{}", f.to_string());
|
||||
continue;
|
||||
}
|
||||
},
|
||||
};
|
||||
let tsize: u64 = match mode {
|
||||
TruncateMode::Reference => refsize,
|
||||
TruncateMode::Extend => fsize + refsize,
|
||||
TruncateMode::Reduce => fsize - refsize,
|
||||
TruncateMode::Absolute => modsize,
|
||||
TruncateMode::Reference => fsize,
|
||||
TruncateMode::Extend => fsize + modsize,
|
||||
TruncateMode::Reduce => fsize - modsize,
|
||||
TruncateMode::AtMost => {
|
||||
if fsize > refsize {
|
||||
refsize
|
||||
if fsize > modsize {
|
||||
modsize
|
||||
} else {
|
||||
fsize
|
||||
}
|
||||
}
|
||||
TruncateMode::AtLeast => {
|
||||
if fsize < refsize {
|
||||
refsize
|
||||
if fsize < modsize {
|
||||
modsize
|
||||
} else {
|
||||
fsize
|
||||
}
|
||||
}
|
||||
TruncateMode::RoundDown => fsize - fsize % refsize,
|
||||
TruncateMode::RoundUp => fsize + fsize % refsize,
|
||||
TruncateMode::RoundDown => fsize - fsize % modsize,
|
||||
TruncateMode::RoundUp => fsize + fsize % modsize,
|
||||
};
|
||||
match file.set_len(tsize) {
|
||||
Ok(_) => {}
|
||||
|
@ -200,10 +217,10 @@ fn parse_size(size: &str) -> (u64, TruncateMode) {
|
|||
'>' => TruncateMode::AtLeast,
|
||||
'/' => TruncateMode::RoundDown,
|
||||
'*' => TruncateMode::RoundUp,
|
||||
_ => TruncateMode::Reference, /* assume that the size is just a number */
|
||||
_ => TruncateMode::Absolute, /* assume that the size is just a number */
|
||||
};
|
||||
let bytes = {
|
||||
let mut slice = if mode == TruncateMode::Reference {
|
||||
let mut slice = if mode == TruncateMode::Absolute {
|
||||
&clean_size
|
||||
} else {
|
||||
&clean_size[1..]
|
||||
|
|
|
@ -161,3 +161,16 @@ fn test_round_up() {
|
|||
let actual = file.seek(SeekFrom::Current(0)).unwrap();
|
||||
assert!(expected == actual, "expected '{}' got '{}'", expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_size_and_reference() {
|
||||
let expected = 15;
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let mut file1 = at.make_file(TFILE1);
|
||||
let mut file2 = at.make_file(TFILE2);
|
||||
file1.write_all(b"1234567890").unwrap();
|
||||
ucmd.args(&["--reference", TFILE1, "--size", "+5", TFILE2]).succeeds();
|
||||
file2.seek(SeekFrom::End(0)).unwrap();
|
||||
let actual = file2.seek(SeekFrom::Current(0)).unwrap();
|
||||
assert!(expected == actual, "expected '{}' got '{}'", expected, actual);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue