Skip to content
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

Implement intersection for two VersionReq #170

Open
Laegluin opened this issue Feb 17, 2018 · 4 comments
Open

Implement intersection for two VersionReq #170

Laegluin opened this issue Feb 17, 2018 · 4 comments

Comments

@Laegluin
Copy link

It would be useful to be able to merge to VersionReq into one that only matches Versions that both individual requirements match.

Something like this:

fn intersect_with(self, other: VersionReq) -> VersionReq

along with a version that takes an Iterator of VersionReq.

Considering that a VersionReq is only a Vec anyway, this should be fairly easy to implement. Unless somebody else wants it, I can do it.

@jonhoo
Copy link

jonhoo commented Nov 26, 2020

@Laegluin Did you ever end up looking at this? It would come in super handy for rust-lang/cargo#8890.

jonhoo pushed a commit to jonhoo/cargo that referenced this issue Nov 26, 2020
Note that this could be a decent amount nicer with
dtolnay/semver#170

This currently ends up in some kind of loop for cargo-like deps:

    yielding already-fetched rustversion
    yielding already-fetched futures
    yielding already-fetched thiserror
    yielding already-fetched anyhow
    yielding already-fetched rustversion
    yielding already-fetched futures
    yielding already-fetched thiserror

Everything _up_ to that point terminates pretty quickly.
@Laegluin
Copy link
Author

@Laegluin Did you ever end up looking at this? It would come in super handy for rust-lang/cargo#8890.

For what I needed I simply hacked it together by parsing the all requirements again:

fn intersect(reqs: impl IntoIterator<Item = VersionReq>) -> VersionReq {
    let reqs: Vec<_> = reqs
        .into_iter()
        .filter_map(|req| {
            if req == VersionReq::any() {
                None
            } else {
                Some(req.to_string())
            }
        })
        .collect();

    if reqs.is_empty() {
        VersionReq::any()
    } else {
        reqs.join(", ").parse().unwrap()
    }
}

That's really ugly and probably not too fast but it works.

Implementing this properly would probably just require merging the two vecs in the range:
https://github.com/steveklabnik/semver/blob/051c39c50d565c597be65c4496597c7d16a514d9/src/version_req.rs#L34-L37).

I'm not quite sure how the Compat field affects this, I think that's a new addition that didn't exist when I opened the issue.

@jonhoo
Copy link

jonhoo commented Nov 29, 2020

I feel like if we wanted "proper" support for this, we'd also look at the individual ranges and figure out where they overlap. That might produce significantly smaller requirements lists.

Separately, I've also really wanted the ability to take the union of requirements. I think the process for that will also be very similar...

@Laegluin
Copy link
Author

I feel like if we wanted "proper" support for this, we'd also look at the individual ranges and figure out where they overlap. That might produce significantly smaller requirements lists.

Yeah, that would make a lot of sense, even though it's probably only worth it for the simple cases. In general all these types of features just come down to manipulating the list of ranges. I have to admit I am not particularly motivated to work on this at the moment, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants