mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
Merge pull request #2136 from jaggededgedjustice/allow-truncate-size-and-reference
Allow truncate to take --size and --reference
This commit is contained in:
commit
33139817a2
2 changed files with 52 additions and 22 deletions
|
@ -16,6 +16,7 @@ use std::path::Path;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq)]
|
#[derive(Eq, PartialEq)]
|
||||||
enum TruncateMode {
|
enum TruncateMode {
|
||||||
|
Absolute,
|
||||||
Reference,
|
Reference,
|
||||||
Extend,
|
Extend,
|
||||||
Reduce,
|
Reduce,
|
||||||
|
@ -131,18 +132,30 @@ fn truncate(
|
||||||
size: Option<String>,
|
size: Option<String>,
|
||||||
filenames: Vec<String>,
|
filenames: Vec<String>,
|
||||||
) {
|
) {
|
||||||
let (refsize, mode) = match reference {
|
let (modsize, mode) = match size {
|
||||||
Some(rfilename) => {
|
Some(size_string) => parse_size(&size_string),
|
||||||
let _ = match File::open(Path::new(&rfilename)) {
|
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,
|
Ok(m) => m,
|
||||||
Err(f) => crash!(1, "{}", f.to_string()),
|
Err(f) => crash!(1, "{}", f.to_string()),
|
||||||
};
|
};
|
||||||
match metadata(rfilename) {
|
match metadata(rfilename) {
|
||||||
Ok(meta) => (meta.len(), TruncateMode::Reference),
|
Ok(meta) => meta.len(),
|
||||||
Err(f) => crash!(1, "{}", f.to_string()),
|
Err(f) => crash!(1, "{}", f.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => parse_size(size.unwrap().as_ref()),
|
None => 0,
|
||||||
};
|
};
|
||||||
for filename in &filenames {
|
for filename in &filenames {
|
||||||
let path = Path::new(filename);
|
let path = Path::new(filename);
|
||||||
|
@ -153,33 +166,37 @@ fn truncate(
|
||||||
.open(path)
|
.open(path)
|
||||||
{
|
{
|
||||||
Ok(file) => {
|
Ok(file) => {
|
||||||
let fsize = match metadata(filename) {
|
let fsize = match reference {
|
||||||
Ok(meta) => meta.len(),
|
Some(_) => refsize,
|
||||||
Err(f) => {
|
None => match metadata(filename) {
|
||||||
show_warning!("{}", f.to_string());
|
Ok(meta) => meta.len(),
|
||||||
continue;
|
Err(f) => {
|
||||||
}
|
show_warning!("{}", f.to_string());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let tsize: u64 = match mode {
|
let tsize: u64 = match mode {
|
||||||
TruncateMode::Reference => refsize,
|
TruncateMode::Absolute => modsize,
|
||||||
TruncateMode::Extend => fsize + refsize,
|
TruncateMode::Reference => fsize,
|
||||||
TruncateMode::Reduce => fsize - refsize,
|
TruncateMode::Extend => fsize + modsize,
|
||||||
|
TruncateMode::Reduce => fsize - modsize,
|
||||||
TruncateMode::AtMost => {
|
TruncateMode::AtMost => {
|
||||||
if fsize > refsize {
|
if fsize > modsize {
|
||||||
refsize
|
modsize
|
||||||
} else {
|
} else {
|
||||||
fsize
|
fsize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TruncateMode::AtLeast => {
|
TruncateMode::AtLeast => {
|
||||||
if fsize < refsize {
|
if fsize < modsize {
|
||||||
refsize
|
modsize
|
||||||
} else {
|
} else {
|
||||||
fsize
|
fsize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TruncateMode::RoundDown => fsize - fsize % refsize,
|
TruncateMode::RoundDown => fsize - fsize % modsize,
|
||||||
TruncateMode::RoundUp => fsize + fsize % refsize,
|
TruncateMode::RoundUp => fsize + fsize % modsize,
|
||||||
};
|
};
|
||||||
match file.set_len(tsize) {
|
match file.set_len(tsize) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
|
@ -200,10 +217,10 @@ fn parse_size(size: &str) -> (u64, TruncateMode) {
|
||||||
'>' => TruncateMode::AtLeast,
|
'>' => TruncateMode::AtLeast,
|
||||||
'/' => TruncateMode::RoundDown,
|
'/' => TruncateMode::RoundDown,
|
||||||
'*' => TruncateMode::RoundUp,
|
'*' => 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 bytes = {
|
||||||
let mut slice = if mode == TruncateMode::Reference {
|
let mut slice = if mode == TruncateMode::Absolute {
|
||||||
&clean_size
|
&clean_size
|
||||||
} else {
|
} else {
|
||||||
&clean_size[1..]
|
&clean_size[1..]
|
||||||
|
|
|
@ -216,3 +216,16 @@ fn test_round_up() {
|
||||||
actual
|
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