diff options
author | Justin Wernick <justin@worthe-it.co.za> | 2023-07-03 21:54:21 +0200 |
---|---|---|
committer | Justin Wernick <justin@worthe-it.co.za> | 2023-07-03 21:54:21 +0200 |
commit | e18a928db5916fce43c35dff585072dace0da7e0 (patch) | |
tree | d33c8d6c08a779b0f28ddff83ce540b3821160e4 /src | |
parent | ff05e4ab91b3b84ffb04b3d8089052112e7bd51c (diff) |
Added a new "--verbose" option to the list command
Diffstat (limited to 'src')
-rw-r--r-- | src/git.rs | 40 | ||||
-rw-r--r-- | src/lib.rs | 23 | ||||
-rw-r--r-- | src/parser.rs | 9 |
3 files changed, 66 insertions, 6 deletions
@@ -109,6 +109,33 @@ pub struct RepoMetadata { pub description: String, } +pub struct VerboseRepoMetadata { + pub path: PathBuf, + pub description: String, + pub size: u64, +} + +fn get_size(path: impl AsRef<Path>) -> Result<u64, ShackleError> { + let path_metadata = path.as_ref().symlink_metadata()?; + + if path_metadata.is_dir() { + let mut size_in_bytes = path_metadata.len(); + for entry in path.as_ref().read_dir()? { + let entry = entry?; + let entry_metadata = entry.metadata()?; + + if entry_metadata.is_dir() { + size_in_bytes += get_size(entry.path())?; + } else { + size_in_bytes += entry_metadata.len(); + } + } + Ok(size_in_bytes) + } else { + Ok(path_metadata.len()) + } +} + pub fn list() -> Result<Vec<RepoMetadata>, ShackleError> { fn add_from_dir( collection_dir: &Path, @@ -163,6 +190,19 @@ pub fn list() -> Result<Vec<RepoMetadata>, ShackleError> { Ok(results) } +pub fn list_verbose() -> Result<Vec<VerboseRepoMetadata>, ShackleError> { + list()? + .into_iter() + .map(|meta| { + get_size(&meta.path).map(|size| VerboseRepoMetadata { + path: meta.path, + description: meta.description, + size, + }) + }) + .collect() +} + pub fn set_description(directory: &Path, description: &str) -> Result<(), ShackleError> { if !is_valid_git_repo_path(directory)? { return Err(ShackleError::InvalidDirectory); @@ -3,6 +3,7 @@ mod parser; pub mod user_info; use comfy_table::Table; +use humansize::{format_size, BINARY}; use parser::*; use rustyline::error::ReadlineError; use std::{io, ops::ControlFlow}; @@ -16,12 +17,24 @@ pub fn run_command(user_input: &str) -> Result<ControlFlow<(), ()>, ShackleError Ok(ShackleCommand::Exit) => { return Ok(ControlFlow::Break(())); } - Ok(ShackleCommand::List) => { + Ok(ShackleCommand::List(ListArgs { verbose })) => { let mut table = Table::new(); - table.set_header(vec!["path", "description"]); - let listing = git::list()?; - for meta in listing { - table.add_row(vec![meta.path.display().to_string(), meta.description]); + if !verbose { + table.set_header(vec!["path", "description"]); + let listing = git::list()?; + for meta in listing { + table.add_row(vec![meta.path.display().to_string(), meta.description]); + } + } else { + table.set_header(vec!["path", "description", "size"]); + let listing = git::list_verbose()?; + for meta in listing { + table.add_row(vec![ + meta.path.display().to_string(), + meta.description, + format_size(meta.size, BINARY), + ]); + } } println!("{table}"); diff --git a/src/parser.rs b/src/parser.rs index 30eb1e0..b429572 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -11,7 +11,7 @@ pub enum ShackleCommand { /// Create a new repository Init(InitArgs), /// List all repositories available - List, + List(ListArgs), /// Sets the description of a repository, as shown in the CLI listing and web interfaces SetDescription(SetDescriptionArgs), /// Sets the main branch of the repository @@ -42,6 +42,13 @@ pub struct InitArgs { } #[derive(Parser, Clone, Debug, PartialEq, Eq)] +pub struct ListArgs { + /// List extra metadata, like the repo's size on disk + #[arg(short, long)] + pub verbose: bool, +} + +#[derive(Parser, Clone, Debug, PartialEq, Eq)] pub struct SetDescriptionArgs { /// The full relative path of the repository, for example git/shuckie/repo.git #[arg(value_parser = RelativePathParser)] |