-
-
Notifications
You must be signed in to change notification settings - Fork 31
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
feat: remove features when removing dependencies #113
base: main
Are you sure you want to change the base?
Conversation
@bnjbvr Pending review |
Hi, as I'm working on my spare time on this project, I might not be very reactive for reviews and all of that. That being said: how does this work? How can you guess the feature's name? (are you assuming the feature's named after the dependency?) Not sure how prevalent that usage is, so unclear whether we should do that automatically... |
@bnjbvr I added a test case so you can see what it does. You can also add more autofix tests using the same setup. |
In short, for a Cargo.toml with the unused
It sees the
|
@bnjbvr Have you had a chance to take a look at this? |
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.
Thanks, took the time to review.
Bonus points if you switch to cargo-insta
for the snapshot tests :) (but not mandatory, of course!).
src/main.rs
Outdated
if let Some(deps) = deps.as_array_mut() { | ||
deps.retain(|dep| { | ||
if let Some(dep) = dep.as_str() { | ||
!dependencies_list.iter().any(|d| dep.contains(d)) |
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 think contains
is a bit too vague here: a dependency flagged for removal called log
would cause removal of a feature enabling something (a feature or another dependency) called flog
.
Can you handle that better, and add a test that checks that too, please?
Getting back to this: any idea why the CI doesn't even show up? There's no job and no way for me to approve the run or not 🤔 |
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 don't know why the CI job fails, but when I tried to run the tests locally by repeating the commands, they failed. Could you take another look please?
Will check later today |
hi @njelich, happy new year! Do you plan to work on this anytime soon, or should I close this PR for the time being? |
I could take a short look |
CI/CD passed on my copy of the repo. @bnjbvr Please retry running it. |
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.
Thanks! The test doesn't pass on my machine. Instead of using diff
to compare the result, would you be open to rewrite all these tests as unit tests of remove_dependencies
? It should be possible to pass a full string representing a valid manifest, and the expected final manifest. This would be simpler to test, notably it would become Just™ a Rust unit test, and it would not require a new CI step. Does it make sense to you?
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
log = "0.4.14" |
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 think log
should be removed in this expected
test result, since it's unused in the src directory?
|
||
[features] | ||
default = ["std"] | ||
std = ["log/std", "other"] |
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.
and log/std
here too
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
log = "0.4.14" |
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.
and same in this file
!dependencies_list.iter().any(|d| { | ||
let prefix = d.to_string() + "/"; | ||
dep.contains(&prefix) | ||
}) |
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.
So, scanning https://doc.rust-lang.org/cargo/reference/features.html, I think the whole set of rules is the following:
- you can remove the dependency name, if there's no other feature named like it. e.g. if you depend on
log
, and in the[features]
array there's onlymyfeat = ["log"]
, then it can be removed automatically. But it can't be removed if such a feature exists with the same name, because in that case it's referring to that feature with the same name (as far as I can tell). - there's another way to precise, starting from Rust 1.60, a dependency name over a feature name:
dep:{dependency_name}
, so it should be handled here too. - we can remove anything that starts with
{dependency_name}/
, as you're doing here 👍 . - we can remove anything that starts with
{dependency_name}?
, for optional dependencies
It would be super sweet to address those four cases completely, or someone could do this as a followup. Do you have a preference?
When removing dependencies using the
--fix
flag, the features for those dependencies are not removed. This adds support for that.I tested it manually, but tests should probably be written to make sure it works generally. From what I can see there are currently no tests for the
--fix
functionality anyway.