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

Floating version patterns like '1.* are treated as ranges without a max, 1.*` is [1.*, ) #5097

Open
anangaur opened this issue Apr 20, 2017 · 9 comments
Labels
Functionality:Restore Priority:3 Issues under consideration. With enough upvotes, will be reconsidered to be added to the backlog. Resolution:ByDesign This issue appears to be ByDesign Status:Excluded from icebox cleanup Status:Inactive Icebox issues not updated for a specific long time Type:DCR Design Change Request

Comments

@anangaur
Copy link
Member

anangaur commented Apr 20, 2017

  1. Create a NETCore/NETStandard project (PackageReference).
  2. Have it depend on a package (say NuGetPlayLib) that has versions 1.1.0,1.2.0,1.3.0,2.0.0
  3. Now edit the csproj file to make the dependency on "1.*"
    <ItemGroup> <PackageReference Include="NuGetPlayLib" Version="1.*" /> </ItemGroup>
  4. Remove the versions 1.* from the feeds
  5. Restore package dependencies for the project

Expected: It should throw an error as it would have if the dependency was specified as:
<ItemGroup> <PackageReference Include="NuGetPlayLib" Version="[1.0.0, 2.0.0)" /> </ItemGroup>
Actual: It resolves to version 2.0.0

@anangaur
Copy link
Member Author

anangaur commented Apr 20, 2017

For reference look at the documentation:
http://blog.nuget.org/20170316/NuGet-now-fully-integrated-into-MSBuild.html

@emgarten
Copy link
Member

Users can specify [1.*, 2.0.0) to enforce an upper bound.

@emgarten
Copy link
Member

A floating range is treated as two ranges currently.

  1. The allowed bounds
  2. A preferred version within those bounds

In the case of 1.* the preferred range is 1.MAXINT, the nearest version to that will be used. Versions below the bounds of [1.0.0, ) will be considered errors.

@anangaur
Copy link
Member Author

I find this non-intuitive. The 1.* seems like it should match to just 1.MAXINT. Was there a requirement to match to the nearest version if the pattern match doesn't happen? I find the usecase a bit weird.

@lodejard
Copy link

The wildcard is matched to what's highest the feed first, and then acts like a normal range afterwards. So if the feed has 1.1.0,1.2.0,1.3.0,2.0.0 and you look for 1.* Then it's effectively turned to 1.3 without a maximum.

Like @emgarten mentioned then - if you have [1.*, 2.0) then it's effectively turned to [1.3, 2.0) which gives you the clamped range you were looking for.

However there is a problem if a wildcard automatically adds a maximum.

Let's say you have project Q that uses library A and B, and A and B use package X. If A says X 1.4 is ideal, and B says X 2.2 is ideal, then Q gets X 2.2 which is the lowest matching package in the intersection of ranges.

But if a wildcard also implies a maximum and A says X 1.* is ideal, and B says X 2.* is ideal, then Q will get a restore error because the ranges [1.3, 2.0) and [2.0, 3.0) have no intersection.

The major version might not seem so bad, but you'd have the same problem with any non-identical wildcard... 1.5.* and 1.6.* will exclude each other, but 1.5.4 and 1.6.1 will happily select 1.6.1 for you.

@lodejard
Copy link

That said - I do think this is a case where you should get the "under-versioning" warning. Just like if I say 1.3 is ideal and restore ends up handing me 2.0 I'll get a warning, if I say 1.* is ideal and restore ends up with 2.0 I should get that same warning.

@anangaur
Copy link
Member Author

@lodejard I see 2 issues with the current behavior using wild card:

  1. The semantic is non intuitive. The range using braces already works right now. So if somebody wants a particular behavior like no upper bound, then they can go with no upper bound. E.g [1.0.0,]
    What will 1.* regular expression mean? Can it ever mean 2.x?
    Also since [1.0.0, 2.0.0) will never match to 2.0.0 even if there are no packages with version 1.x.x, we should have similar behavior for the *

  2. If we limit 1.* to mean less than 2 equivalent to [1.0.0,2.0.0), then this also enables one to constrain the dependency range to the same major version.
    E.g
    1.* = [1.0.0,2)
    1.3.* = [1.3.0, 1.4.0)

@mishra14 mishra14 added this to the Backlog milestone Oct 17, 2017
@ivan-danilov
Copy link

ivan-danilov commented Sep 17, 2019

Wow... that's completely awkward. Docs say:

A floating or wildcard dependency version is specified with the * wildcard, as with 6.0.. This version specification says "use the latest 6.0.x version"; 4. means "use the latest 4.x version."

In reality, 4.* means [4.*, ). That's a bummer as if package sources don't have any versions with Major=4 at all - NuGet will happily resolve 5.0.0 or whatever is available there next.

But even [4.0.0, 4.1.0) (assuming it resolves to the highest applicable version) does not solve the issue: 4.1.0-prerelease.label matches that range as well. Therefore, taking the explanations in this thread into account, the correct range to specify what is expected from 4.* by most people would be [4.0.0, 4.1.0-0).

How many people would write it correctly from the first time? And what is the point in having 4.* implemented as it is now, namely [4.*, )? To be honest, I struggle to find a real case when I'd like version 5.0.0 to match reference 4.* silently.

@ivan-danilov
Copy link

In fact, even the last one is not right because of #912 as it won't consider pre-release versions if there is at least one version without pre-release label (i.e. 4.0.1-rc won't be considered if there is 4.0.0 present in the feed). Complete bummer, seems not possible to do at all. [4.0.0-*, 4.1.0-0) does not work either.

@nkolev92 nkolev92 changed the title Pattern - "*" is not properly validated in restore while mentioning the dependency version Floating version patterns like '1.* are treated as ranges without a max, 1.*` is [1.*, ) Feb 7, 2020
@nkolev92 nkolev92 removed this from the Backlog milestone Apr 9, 2020
@nkolev92 nkolev92 added the Resolution:ByDesign This issue appears to be ByDesign label Apr 9, 2020
@aortiz-msft aortiz-msft removed their assignment Apr 15, 2020
@ghost ghost added the Status:Inactive Icebox issues not updated for a specific long time label Sep 1, 2022
@jeffkl jeffkl added Priority:3 Issues under consideration. With enough upvotes, will be reconsidered to be added to the backlog. and removed Pipeline:Icebox labels Apr 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Functionality:Restore Priority:3 Issues under consideration. With enough upvotes, will be reconsidered to be added to the backlog. Resolution:ByDesign This issue appears to be ByDesign Status:Excluded from icebox cleanup Status:Inactive Icebox issues not updated for a specific long time Type:DCR Design Change Request
Projects
None yet
Development

No branches or pull requests

9 participants