-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Du size_format flag override #10743
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Du size_format flag override #10743
Changes from 3 commits
2fba27b
43d9dd8
edf51cc
1f5f612
e06d1fe
7ede99a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -963,7 +963,7 @@ fn read_files_from(file_name: &OsStr) -> Result<Vec<PathBuf>, std::io::Error> { | |
| Ok(paths) | ||
| } | ||
|
|
||
| fn get_block_size_arg_index_if_present(matches: &ArgMatches, flag: &str) -> Option<usize> { | ||
| fn get_size_format_flag_arg_index_if_present(matches: &ArgMatches, flag: &str) -> Option<usize> { | ||
| if matches.get_flag(flag) { | ||
| // Indices of returns index even if flag is not present, thats why we need to if guard it | ||
| matches | ||
|
|
@@ -974,27 +974,64 @@ fn get_block_size_arg_index_if_present(matches: &ArgMatches, flag: &str) -> Opti | |
| } | ||
| } | ||
|
|
||
| fn handle_block_size_arg_override(matches: &ArgMatches) -> Option<SizeFormat> { | ||
| fn get_size_format_string_arg_index_if_present(matches: &ArgMatches, flag: &str) -> Option<usize> { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you can also combine these two sections by using the value_source since it will work for both string and flag
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I'm giving a bunch of suggestions, not to say that there's a right way to do that, feel free to not use any of them I just think its getting a bit verbose and hard to read so I'm just going to throw a bunch of ideas and feel free to try any that you think would make it easier to read?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wasn't experienced enough with the clap api to know about value_source(). This is ofc a massive improvement in code reusability and conciseness. Thanks! |
||
| if matches.get_one::<String>(flag).is_some() { | ||
| // Indices of returns index even if flag is not present, thats why we need to if guard it | ||
| matches | ||
| .indices_of(flag) | ||
| .and_then(|mut indices| indices.next_back()) | ||
| } else { | ||
| None | ||
| } | ||
| } | ||
|
|
||
| fn handle_block_size_arg_override(matches: &ArgMatches) -> UResult<SizeFormat> { | ||
| let candidates = [ | ||
| ( | ||
| SizeFormat::BlockSize(1), | ||
| get_block_size_arg_index_if_present(matches, options::BYTES), | ||
| Some(SizeFormat::BlockSize(1)), | ||
| get_size_format_flag_arg_index_if_present(matches, options::BYTES), | ||
| ), | ||
| ( | ||
| Some(SizeFormat::BlockSize(1024)), | ||
| get_size_format_flag_arg_index_if_present(matches, options::BLOCK_SIZE_1K), | ||
| ), | ||
| ( | ||
| Some(SizeFormat::BlockSize(1024 * 1024)), | ||
| get_size_format_flag_arg_index_if_present(matches, options::BLOCK_SIZE_1M), | ||
| ), | ||
| ( | ||
| Some(SizeFormat::HumanBinary), | ||
| get_size_format_flag_arg_index_if_present(matches, options::HUMAN_READABLE), | ||
| ), | ||
| ( | ||
| SizeFormat::BlockSize(1024), | ||
| get_block_size_arg_index_if_present(matches, options::BLOCK_SIZE_1K), | ||
| Some(SizeFormat::HumanDecimal), | ||
| get_size_format_flag_arg_index_if_present(matches, options::SI), | ||
| ), | ||
| // for block size we want to handle this not in closure but in else block later | ||
| ( | ||
| SizeFormat::BlockSize(1024 * 1024), | ||
| get_block_size_arg_index_if_present(matches, options::BLOCK_SIZE_1M), | ||
| None, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about you call the function to read the block size here and then you don't need to have the call into it later?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I called it even before to only use it once and then use the return value for unwrap_or(). Otherwise i didn't see a way to only call it once with the candidates as i feel like there was no sensible way to ensure it being the fallback in case no arg was present and we needed the fallback value from that call. Obv we could rewrite the read_block_size func to not be the fallback either... maybe this would be a cleaner approach. |
||
| get_size_format_string_arg_index_if_present(matches, options::BLOCK_SIZE), | ||
| ), | ||
| ]; | ||
|
|
||
| candidates | ||
| let ret = candidates | ||
| .into_iter() | ||
| .filter(|(_, idx)| idx.is_some()) | ||
| .max_by_key(|&(_, idx)| idx.unwrap_or(0)) | ||
| .map(|(size_format, _)| size_format) | ||
| .map(|(size_format, _)| size_format); | ||
|
|
||
| if let Some(Some(size_format)) = ret { | ||
| Ok(size_format) | ||
| } else { | ||
| // we handle block_size option here manually | ||
| let block_size_str = matches.get_one::<String>(options::BLOCK_SIZE); | ||
| let block_size = read_block_size(block_size_str.map(AsRef::as_ref))?; | ||
| if block_size == 0 { | ||
| return Err(std::io::Error::other(translate!("du-error-invalid-block-size-argument", "option" => options::BLOCK_SIZE, "value" => block_size_str.map_or("???BUG", |v| v).quote())) | ||
| .into()); | ||
| } | ||
| Ok(SizeFormat::BlockSize(block_size)) | ||
| } | ||
| } | ||
|
|
||
| #[uucore::main] | ||
|
|
@@ -1048,21 +1085,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { | |
| .map_or(MetadataTimeField::Modification, |s| s.as_str().into()) | ||
| }); | ||
|
|
||
| let size_format = if matches.get_flag(options::HUMAN_READABLE) { | ||
| SizeFormat::HumanBinary | ||
| } else if matches.get_flag(options::SI) { | ||
| SizeFormat::HumanDecimal | ||
| } else if let Some(size_format) = handle_block_size_arg_override(&matches) { | ||
| size_format | ||
| } else { | ||
| let block_size_str = matches.get_one::<String>(options::BLOCK_SIZE); | ||
| let block_size = read_block_size(block_size_str.map(AsRef::as_ref))?; | ||
| if block_size == 0 { | ||
| return Err(std::io::Error::other(translate!("du-error-invalid-block-size-argument", "option" => options::BLOCK_SIZE, "value" => block_size_str.map_or("???BUG", |v| v).quote())) | ||
| .into()); | ||
| } | ||
| SizeFormat::BlockSize(block_size) | ||
| }; | ||
| let size_format = handle_block_size_arg_override(&matches)?; | ||
|
|
||
| let traversal_options = TraversalOptions { | ||
| all: matches.get_flag(options::ALL), | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test cases are great and testing around locally it seems great to me, I think we can make it a bit cleaner though. Do you think we could seperate into a helper function the parsing of the explicit block size argument?
Then it can make that section below smaller
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found yet another bug ... gnu always errors if the value for block-size is erroneous while upstream main (1 commit before #10664) does not because it only looks at block-size if no other option is present.
I will incorporate a more concise version and look at your suggestions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cannot use map on the get_one because in read_block_size() a fallback value is define in case the parameter is None. If we use this in .map() we would never get that fallback value.