Skip to content

Commit

Permalink
Allow --maxsize to accept byte-unit sizes
Browse files Browse the repository at this point in the history
  • Loading branch information
marcospb19 committed Sep 18, 2023
1 parent fd4dc9e commit 63a4134
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ cargo_metadata = "0.9"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
human-size = "0.4.3"

[dev-dependencies]
assert_cmd = "2.0.4"
fs_extra = "1.2.0"
human-size = "0.4.2"
predicates = "2.1.1"
tempfile = "3.3.0"
which = { version = "4.3.0", default-features = false }
Expand Down
63 changes: 53 additions & 10 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use anyhow::anyhow;
use clap::{ArgGroup, Parser};
use std::path::PathBuf;

const MEGABYTE: u64 = 1024 * 1024;

pub fn parse() -> Args {
SweepArgs::parse().into_args()
}
Expand Down Expand Up @@ -59,12 +62,11 @@ pub struct Args {
#[arg(short, long)]
installed: bool,

/// Remove oldest artifacts until the target directory is below the specified size in MB
/// Remove oldest artifacts from the target folder until it's smaller than MAXSIZE
///
/// TODO: consider parsing units like GB, KB
/// https://github.com/holmgr/cargo-sweep/issues/82
#[arg(short, long, value_name = "MAXSIZE_MB")]
maxsize: Option<u64>,
/// Unit defaults to MB, examples: --maxsize 500, --maxsize 10GB
#[arg(short, long, value_name = "MAXSIZE")]
maxsize: Option<String>,

/// Apply on all projects below the given path
#[arg(short, long)]
Expand All @@ -88,8 +90,9 @@ pub struct Args {
}

impl Args {
pub fn criterion(&self) -> Criterion {
match &self {
// Might fail in case parsing size units fails.
pub fn criterion(&self) -> anyhow::Result<Criterion> {
Ok(match &self {
_ if self.stamp => Criterion::Stamp,
_ if self.file => Criterion::File,
_ if self.installed => Criterion::Installed,
Expand All @@ -100,13 +103,24 @@ impl Args {
Self {
maxsize: Some(size),
..
} => Criterion::MaxSize(*size),
} => {
// Try parsing as `human_size::Size` to accept "MB" and "GB" as units
// If it fails, fall back to `u64` and use "MB" as the default unit

let size = size
.parse::<human_size::Size>()
.map(human_size::Size::to_bytes)
.or_else(|_| size.parse::<u64>().map(|size| size * MEGABYTE))
.map_err(|_| anyhow!(format!("Failed to parse size '{size}'")))?;

Criterion::MaxSize(size)
}
_ => unreachable!("guaranteed by clap ArgGroup"),
}
})
}
}

#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub enum Criterion {
Stamp,
File,
Expand Down Expand Up @@ -160,4 +174,33 @@ mod tests {
};
assert_eq!(args, parse("cargo sweep --toolchains 1,2,3").unwrap());
}

#[test]
fn test_maxsize_argument_parsing() {
let test_data = [
("3", 3 * 1024 * 1024),
("3MB", 3 * 1000 * 1000),
("100", 100 * 1024 * 1024),
("100MB", 100 * 1000 * 1000),
("100MiB", 100 * 1024 * 1024),
("100GB", 100 * 1000 * 1000 * 1000),
("100GiB", 100 * 1024 * 1024 * 1024),
("700TB", 700 * 1000 * 1000 * 1000 * 1000),
("700TiB", 700 * 1024 * 1024 * 1024 * 1024),
];

for (input, expected_size) in test_data {
let input = format!("cargo-sweep sweep --maxsize {input}");
let result = parse(&input).unwrap().criterion().unwrap();

if result != Criterion::MaxSize(expected_size) {
panic!(
"Test failed.\n\
Input: {input}\n\
Expected Size: {expected_size}\n\
Got this instead: {result:?}"
);
}
}
}
}
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ fn metadata(path: &Path) -> Result<Metadata, Error> {
fn main() -> anyhow::Result<()> {
let args = cli::parse();

let criterion = args.criterion();
let criterion = args.criterion()?;
let dry_run = args.dry_run;
setup_logging(args.verbose);

Expand Down

0 comments on commit 63a4134

Please sign in to comment.