-
-
Notifications
You must be signed in to change notification settings - Fork 78
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
extract library #314
extract library #314
Conversation
/// Latest version published to the cargo registry. | ||
#[default] | ||
LatestVersion, | ||
} |
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 tried to group conflicting cli arguments together in enums.
src/lib.rs
Outdated
/// It can be a workspace or a single package. | ||
Manifest(PathBuf), | ||
/// The rustdoc json of the current version of the project. | ||
RustDoc(PathBuf), |
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 saw that this rustdoc also requires the Baseline rustdoc.
At the moment this is not captured by the type system.
- How would you deal with this?
- Should we move it outside of this enum?
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.
All of these allow the baseline rustdoc to be specified explicitly, while only one option requires it. This makes the decision tricky. It feels like this enum isn't at the right level of abstraction.
The baseline and the current rustdoc can be one of three things:
- already generated, just load it from an existing file
- generate it based on code at some path, optionally first checking out a gitrev (maybe better split into two cases? what do you think?)
- generate it based on a registry version (in the current CLI, only the baseline can do this, but @tonowak has a lib use case where it would be useful for the current rustdoc as well)
Perhaps a pub enum RustdocSource
like that might be better? Then the CLI can have its own structs and behaviors around "current directory" etc. For testability reasons, it might be best if the library is ignorant of the current directory and always expects explicit paths to be fed to it.
Not set on it, just wanted to suggest an idea to look at.
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 we want to create a RustdocSource struct that can be used both by the Baseline and Current rustdoc?
already generated, just load it from an existing file
enum RustdocSource {
RustDoc(PathBuf)
}
generate it based on code at some path, optionally first checking out a gitrev (maybe better split into two cases? what do you think?)
enum RustdocSource {
RustDoc(PathBuf),
Root(PathBuf),
// (path to root, rev)
Revision(PathBuf, String)
}
generate it based on a registry version
enum RustdocSource {
RustDoc(PathBuf),
Root(PathBuf),
// (path to root, rev)
Revision(PathBuf, String),
Version(Option<String>),
}
This looks similar to the current Baseline enum. Is it valid for Current
, too?
If I didn't get it, can you give me the structure of the enum you were thinking about?
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 it looks reasonable. It currently isn't valid for Current
in the CLI, but I think it should be in the lib. Not much reason not to: that would make the types more complex while providing less functionality.
Small nit: let's call the variant Rustdoc
instead, since the underlying tool doesn't capitalize the D
either.
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.
It currently isn't valid for Current in the CLI, but I think it should be in the lib.
FYI @MarcoIeni, the recent merged chain of PRs (which ended with #351) made it so that the current
crate's rustdoc is generated in the same way as the baseline
's rustdoc, so now it's possible to create the current
rustdoc from registry and from git revision -- your RustdocSource
now is also fully valid for the current
crates.
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 also, this chain of PRs renamed quite a lot of things in the source code, so there might be a big merge conflict, sorry :( I can try to merge main into this branch when I'll have some free time.
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.
If you could help with the merge, that would be great @tonowak. Probably the highest impact next thing you can do right now, TBH.
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.
Ok, I'll do it in max few days.
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.
Done.
pub fn with_manifest(&mut self, path: PathBuf) -> &mut Self { | ||
self.current = Current::Manifest(path); | ||
self | ||
} |
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 used a builder pattern that matches the cli args.
style of builder pattern: https://rust-lang.github.io/api-guidelines/type-safety.html#non-consuming-builders-preferred
src/lib.rs
Outdated
Current::Manifest(path) => path.clone(), | ||
Current::RustDoc(_) => { | ||
anyhow::bail!("error: RustDoc is not supported with these arguments.") | ||
} |
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'm not sure about 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.
Agreed, it doesn't seem great. Perhaps the rustdoc-source restructuring might help?
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.
Very excited about this, thanks for putting it together!
src/lib.rs
Outdated
/// It can be a workspace or a single package. | ||
Manifest(PathBuf), | ||
/// The rustdoc json of the current version of the project. | ||
RustDoc(PathBuf), |
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.
All of these allow the baseline rustdoc to be specified explicitly, while only one option requires it. This makes the decision tricky. It feels like this enum isn't at the right level of abstraction.
The baseline and the current rustdoc can be one of three things:
- already generated, just load it from an existing file
- generate it based on code at some path, optionally first checking out a gitrev (maybe better split into two cases? what do you think?)
- generate it based on a registry version (in the current CLI, only the baseline can do this, but @tonowak has a lib use case where it would be useful for the current rustdoc as well)
Perhaps a pub enum RustdocSource
like that might be better? Then the CLI can have its own structs and behaviors around "current directory" etc. For testability reasons, it might be best if the library is ignorant of the current directory and always expects explicit paths to be fed to it.
Not set on it, just wanted to suggest an idea to look at.
src/lib.rs
Outdated
Current::Manifest(path) => path.clone(), | ||
Current::RustDoc(_) => { | ||
anyhow::bail!("error: RustDoc is not supported with these arguments.") | ||
} |
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.
Agreed, it doesn't seem great. Perhaps the rustdoc-source restructuring might help?
src/lib.rs
Outdated
#[derive(Default)] | ||
struct Scope { | ||
selection: ScopeSelection, | ||
excluded_packages: Vec<String>, | ||
} | ||
|
||
/// Which packages to analyze. | ||
#[derive(Default, PartialEq, Eq)] | ||
enum ScopeSelection { | ||
/// Package to process (see `cargo help pkgid`) | ||
Packages(Vec<String>), |
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.
Can we define explicitly what happens if ScopeSelection::Packages
contains a package that's also in excluded_packages
? I'm not sure what should happen, or what cargo does assuming the same thing can happen in cargo. But our lib docs should state the expected behavior in any case.
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.
In 1190770 I have made it impossible for this to happen
Co-authored-by: Predrag Gruevski <[email protected]>
Hi @MarcoIeni! It turns out that to complete #207 I need exactly what you're doing in this PR -- allowing the tool to be usable as a library. Thus, if you think it would be helpful, I would be happy to help you with this PR. What do you think? Is there anything in particular I could help you with, or are you progressing nicely and don't need any help? |
Hey @tonowak, if I'm blocking you, feel free to contribute to this pr, yes 👍 I was thinking that with the type system, we could avoid the possibility of specifying |
Thanks for helping Tomasz 😄 |
src/lib.rs
Outdated
/// If `None`, uses the largest-numbered non-yanked non-prerelease version | ||
/// published to the cargo registry. If no such version, uses | ||
/// the largest-numbered version including yanked and prerelease versions. | ||
Version(Option<String>), |
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.
Maybe it would be better to call it Registry
instead of Version
? It would make it more clear that it requires internet access to use it and from where this specific version is being taken from.
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 about RegistryVersion
? 😄
The user when seeing Registry
with a string might think about Registry("crates.io")
for example
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.
Yeah, that might be better 👍 .
... but going with this logic, the user might think that in RegistryVersion
one has to pass the version of the registry to use, not the version of the crate to compare with.
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.
Naming is hard 😁
VersionFromRegistry
is more verbose, but more clear maybe. 🤔
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'm fine with either RegistryVersion
or VersionFromRegistry
. I'm not that worried about people thinking that they need to pass a version of a registry, but I'm willing to accept I may be overly optimistic if you think the other option is better.
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 do you both think about 8485cc5?
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 it's fine :)
I would not try to make the library perfect in this PR. Otherwise we will have to deal with too many merge conflicts.
I guess (and hope) that the library will be extracted in a separate crate, so we can still change the library API in future PRs.
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.
This PR is on my to-do list to review today. Sorry for the delay! Trustfall ended up in the spotlight (it was GitHub's #1 most-starred project a couple of days ago) and I've been super busy over there for the last couple of days.
I know I probably just merged another PR that causes another merge conflict, and I'm happy to fix the mess of my own making 😅
src/lib.rs
Outdated
RustdocSource::Rustdoc(_) | ||
| RustdocSource::Revision(_, _) | ||
| RustdocSource::VersionFromRegistry(_) => { | ||
let name = "<unknown>"; |
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.
While developing #207 I've found a bug: when both crates are generated from registry, this code tries to find a package named <unknown>
in registry. From how the interface looked, I was convinced that it is enough to pass .with_packages(vec![name])
to Check
, but now when I look at the lib.rs
, I don't think it's what it's supposed to accept. So, in the scenario "from registry & from registry", there is no way to pass the name of the crate to check.
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.
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.
In 7ecf587 it seems like there's still an unknown
branch. That looks like it could work if current
is given by gitrev, but won't work with a registry version nor with a premade rustdoc file.
Can we add an explicit panic!()
in the cases we know for sure won't work, instead of setting a bogus value and then breaking in a confusing way?
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.
Done in 7516ab0.
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.
This looks in pretty good shape. Let's target merging tomorrow or Monday morning if possible, so I can include this in the next release (also planned for Monday at the moment).
src/lib.rs
Outdated
RustdocSource::Rustdoc(_) | ||
| RustdocSource::Revision(_, _) | ||
| RustdocSource::VersionFromRegistry(_) => { | ||
let name = "<unknown>"; |
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.
In 7ecf587 it seems like there's still an unknown
branch. That looks like it could work if current
is given by gitrev, but won't work with a registry version nor with a premade rustdoc file.
Can we add an explicit panic!()
in the cases we know for sure won't work, instead of setting a bogus value and then breaking in a confusing way?
src/lib.rs
Outdated
} else if let Some(path) = get_target_dir_from_project_root(&self.baseline.source)? { | ||
path | ||
} else { | ||
get_xdg_cache_dir() |
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 suspect this won't work on Windows, unfortunately. Let's instead use the directories
crate which is the known-working cross-platform way to do this:
if let Some(proj_dirs) = ProjectDirs::from("cargo-semver-checks") {
proj_dirs.config_dir();
// probable dirs (still need to be created! the library won't make them for us)
// Lin: /home/alice/.config/cargo-semver-checks
// Win: C:\Users\Alice\AppData\Roaming\cargo-semver-checks\config
// Mac: /Users/Alice/Library/Application Support/cargo-semver-checks
}
I took care of the merge, it wasn't that bad because I reviewed the code that caused a conflict. Lmk what you think about the Really looking forward to merging this soon! 🚀🎉 |
Is this question for me? If yes, what's the panic!() branch? |
The two remaining items needed to merge this are:
I unfortunately have had to shift my primary focus to Trustfall for a bit, given the recent massive uptick in interest in the project. I think the remaining items aren't much work and I trust both of you to do a good job on them. |
I replaced |
Thanks :) I'll probably do the other fix in the next 48h. |
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.
This looks polished enough to release, let's not block @MarcoIeni's release-plz
work any longer. We will certainly keep improving the library APIs over time, we don't have to get to "perfect" on day 1.
Thanks, everyone!
Thanks! Some naming ideas:
Please, reserve in crates.io the one you prefer :) |
I grabbed both, just to be extra safe. My 2 cents: splitting the library into a separate crate would definitely be nice, but it doesn't seem that critical to me. The community impact of having semver-checking made automatic via Of course, |
Maybe it would be reasonable to have the |
This would prevent us to ship breaking changes independently for the cli and for the library. For example, if we change a command line argument, should it be a breaking change? Having two separate crates allows us to ship breaking changes for cli and the lib independenlty |
A step towards #67
To keep things easier I just created a new lib.rs
In the future, we could extract this lib.rs file into a
core
crate, that doesn't depend on clap.