-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
backup_control: Fix backup mode determination #2467
backup_control: Fix backup mode determination #2467
Conversation
Hello dear maintainers! This merge isn't complete yet. I have so far only implemented the new interface to the If you find that the change is ok, I will modify the other utils that implement |
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.
From my perspective this looks good!
I just have some minor suggestions.
It would be great if you could add some tests as well to make sure everything works (and keeps working) correctly :)
Thanks for the feedback! I tried to incorporate the tests into a |
6dcb0fb
to
aa96595
Compare
The tests are not run because this repo is structured as a workspace of multiple crates. If you run EDIT: I just noticed you can also run |
aa96595
to
e3c797e
Compare
Thanks a lot! 2 Issues remain with the tests:
|
I think that's because clap isn't a dependency of
I don't know of any of that. A way to test this would be to extract the logic of determining the backup mode into a private function that takes the environment variable as an argument. You can then test that function. To test with an actual environment variable you could add integration tests for the utilities that use |
I think I fixed it now. I did some research on this type of issue and found this discussion: rust-lang/rust#47506 I mostly went for rusty-fork as I wasn't aware when implementing the Mutex that one can import single macros in Rust 2018 -- because rust would refuse to compile my code when I included If you'd like me to change this I can try that. I'm actually not sure about the cross-platform support that rusty-fork offers... |
I have now got a solution that works with a global Mutex (scoped for the test submodule only) instead. Both work fine it seems, so i'll leave the final choice up to you. It feels to me like the Mutex-solution is more cross-platform compatible, but that's just a guess. |
The previous help string for the backup subroutines didn't comply with the formatting found in the `--help` output of e.g. `mv` or `ln`. Use the exact help string from these utilities instead.
Add a function that takes a user-supplied backup option and checks if it matches any of the valid backup options. This is because GNU allows to abbreviate backup options, as long as they are valid and unambiguous. In case a backup option is either invalid or ambiguous, an error type is returned that contains a formatted error string for output to the user.
Refactor the function that determines which backup mode to select based on user input. It now complies with what the [GNU manual][1] specifies. [1]: https://www.gnu.org/software/coreutils/manual/html_node/Backup-options.html
Adds a tests submodule that performs tests on the `determine_backup_mode` function to ensure it handles backup options like specified by [GNU][1]. [1]: https://www.gnu.org/software/coreutils/manual/html_node/Backup-options.html
c03c0f7
to
89d8028
Compare
Rebased onto master. I have noticed that the I have now implemented the Mutex-based approach as it's more cross-platform compatible. This requires me to lock the mutex in a few tests, so I went ahead and lock it in all tests just to make sure I don't miss one. As a consequence these tests are now run in series instead of parallel, but due to their low cost it's hardly noticable. I have also adapted the |
89d8028
to
25857c0
Compare
Build/Makefile failed a test in cp, this isn't related to this PR. |
@miDeb Do you have some more thoughts on the current implementation? |
Sorry, I didn't see your last comment. I will take a look now |
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.
LGTM, sorry for the delay. Thanks for working on this!
let backup_mode = backup_control::determine_backup_mode( | ||
matches.is_present(OPT_BACKUP_NO_ARG), | ||
matches.is_present(OPT_BACKUP), | ||
matches.value_of(OPT_BACKUP), | ||
); |
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.
What would you think about making determine_backup_mode
take the wholematches
instead of three arguments? (I think this version is fine though, too)
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 already thought about it and that'd be cool, but in that case I'd have to streamline the naming of the various arguments involved across the utilities... I'll try to find the time tomorrow.
Example:
- install calls the arguments: "backup", "backup2", "suffix"
- cp calls the arguments: "backup", "b", "suffix"
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.
You know I gave this some more thought. I'd go even one step further with this: All utils that implement backup
s functionality have exactly the same options for that. So I'd propose that instead of defining the options in each of the applications separately, I may just as well define the backup-related options in the backup_control
as "finished" clap-Arguments (with all the texts and flags etc.) and then add these to the App in each of the applications. Then I can pass in all matches
to determine_backup_mode
, throw errors if the flags weren't present and continue as before if all is well and defined properly.
I think that I'd like to that in a separate PR though, as this is already somewhat big and I'm afraid I may lose myself in the changes... Would that be okay for you or should I attempt to do it in this PR?
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.
Agree, doing this in a new PR is fine
src/uu/cp/src/cp.rs
Outdated
let backup_mode = match backup_mode { | ||
Err(err) => { | ||
return Err(Error::Backup(err)); | ||
// show_usage_error!("{}", err); |
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.
That's not something you have to address now, but it would be interesting to integrate this with our new error handling mechanism at a later point when all utilities support it, instead of having to repeat the error handling in all utilities.
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.
Yes, definitely! I think I'll add it as a UCommonError
, as it is consistent across utilities.
Make all tests lock a mutex to ensure that they're run in series rather than parallel. We must take this precaution due to the fact that all tests are run in parallel as threads of one parent process. As all threads in a process share e.g. environment variables, we use the Mutex to ensure they're run one after another. This way we can guarantee that tests that rely on environment variables to have specific values will see these variables, too. An alternative implementation could have used the [rusty fork][1] crate to run all tests that need env variables in separate processes rather than threads. However, rusty fork likely wouldn't run on all platforms that the utilities are supposed to run on.
25857c0
to
e07b4e9
Compare
Okay, I'll start working on a new PR to:
Unless you have other suggestions to this PR it can be merged now. :) |
Fixes determination of the backup mode, as specified in the GNU manual.
Previously the backup mode determination wouldn't allow abbreviations to the backup mode, and didn't allow to differ between the short
-b
option (which automatically defaults to the"existing"
backup style) and the long--backup
option (which has more special handling).Also, handling of the
--backup
option has been revamped such that it can now be passed without an argument to it (in which case theVERSION_CONTROL
env variable is read, and if that doesn't exist it defaults to"existing"
). To achieve this the separator between this option and a following argument, if present, must be an equals-sign ("="). This is required in order to supply--backup
without arguments (i.e. as a flag).Due to this, previously it was impossible to use the option as a flag, as it expected arguments to be space-delimited. I.e. a syntax like
... --backup foo bar
, where foo and bar are meant as arguments to the utility (i.e. file arguments to mv) would have consumed foo as backup style, which isn't meant by the user nor valid.Also modifies the backup-specific help-texts and adds error outputs for invalid or ambiguous backup modes.