NuGet / Home

Repo for NuGet Client issues
Other
1.5k stars 252 forks source link

[Bug]: NuGet pack should warn when floating versions are specified in the nuspec #11629

Open tapika opened 2 years ago

tapika commented 2 years ago

NuGet Product Used

NuGet.exe

Product Version

6.0

Worked before?

Never worked, I guess

Impact

It's more difficult to complete my work

Repro Steps & Context

Using nuget pack ... <csproj path>

it's possible to build nuget package.

Next to project I'm using also .nuspec file to specify nuget package dependencies.

So I have following files:

  1. project.csproj
  2. project.nuspec

In 2nd file, I'm additionally specifying nuget package dependencies.

<?xml version="1.0" encoding="utf-8"?>
<package>
  <metadata>
    <!-- 
      This file is merged with outcome from .csproj, but here we can list additional nuget package dependencies.
      Rest of xml tags (Id, Version, ...) required to be here, but we try to keep them on original values as originally specified.
    -->
    <id>$PackageId$</id>
    <version>$Version$</version>
    <authors>$authors$</authors>
    <description>$description$</description>
    <dependencies>
      <dependency id="packtwo" version="[1.0.0, 1.1.0)" />
    </dependencies>
  </metadata>
</package>

This approach does work out of box.

But I wanted also to specify forward dependency, so my current package would pick up newer packtwo is that is available - for example bugfixes, etc...

Then I've reconfigured dependency to be something like this:

      <dependency id="packtwo" version="[1.0.*, 1.1.0)" />
or even:
      <dependency id="packtwo" version="[1.0.*-*, 1.1.0)" />

But this does not work out of box. According to debugger -

end up somewhere at following call stack:

>   NuGet.Packaging.dll!NuGet.Packaging.Xml.PackageMetadataXmlExtensions.GetXElementFromPackageDependency(System.Xml.Linq.XNamespace ns, NuGet.Packaging.Core.PackageDependency dependency) Line 218    C#
    NuGet.Packaging.dll!NuGet.Packaging.Xml.PackageMetadataXmlExtensions.GetXElementFromGroupableItemSets.AnonymousMethod__0(NuGet.Packaging.Core.PackageDependency item) Line 173  C#
    System.Core.dll!System.Linq.Enumerable.WhereSelectEnumerableIterator<NuGet.Packaging.Core.PackageDependency, System.Xml.Linq.XElement>.MoveNext()   Unknown
    mscorlib.dll!System.Collections.Generic.List<System.Xml.Linq.XElement>.InsertRange(int index, System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement> collection)  Unknown
    NuGet.Packaging.dll!NuGet.Packaging.Xml.PackageMetadataXmlExtensions.GetXElementFromGroupableItemSets<NuGet.Packaging.PackageDependencyGroup, NuGet.Packaging.Core.PackageDependency>(System.Xml.Linq.XNamespace ns, System.Collections.Generic.IEnumerable<NuGet.Packaging.PackageDependencyGroup> objectSets, System.Func<NuGet.Packaging.PackageDependencyGroup, bool> isGroupable, System.Func<NuGet.Packaging.PackageDependencyGroup, string> getGroupIdentifer, System.Func<NuGet.Packaging.PackageDependencyGroup, System.Collections.Generic.IEnumerable<NuGet.Packaging.Core.PackageDependency>> getItems, System.Func<System.Xml.Linq.XNamespace, NuGet.Packaging.Core.PackageDependency, System.Xml.Linq.XElement> getXElementFromItem, string parentName, string identifierAttributeName) Line 173  C#
    NuGet.Packaging.dll!NuGet.Packaging.Xml.PackageMetadataXmlExtensions.ToXElement(NuGet.Packaging.ManifestMetadata metadata, System.Xml.Linq.XNamespace ns, bool generateBackwardsCompatible) Line 102    C#
    NuGet.Packaging.dll!NuGet.Packaging.Manifest.Save(System.IO.Stream stream, int minimumManifestVersion, bool generateBackwardsCompatible) Line 95    C#
    NuGet.Packaging.dll!NuGet.Packaging.Manifest.Save(System.IO.Stream stream, int minimumManifestVersion) Line 78  C#
    NuGet.Packaging.dll!NuGet.Packaging.PackageBuilder.WriteManifest(System.IO.Compression.ZipArchive package, int minimumManifestVersion, string psmdcpPath) Line 1044 C#
    NuGet.Packaging.dll!NuGet.Packaging.PackageBuilder.Save(System.IO.Stream stream) Line 426   C#
    NuGet.Commands.dll!NuGet.Commands.PackCommandRunner.BuildPackage(NuGet.Packaging.PackageBuilder builder, string outputPath, bool symbolsPackage) Line 152   C#
    NuGet.Commands.dll!NuGet.Commands.PackCommandRunner.BuildFromProjectFile(string path) Line 802  C#
    NuGet.Commands.dll!NuGet.Commands.PackCommandRunner.BuildPackage(string path) Line 105  C#
    NuGet.Commands.dll!NuGet.Commands.PackCommandRunner.RunPackageBuild() Line 86   C#
    NuGet.exe!NuGet.CommandLine.PackCommand.ExecuteCommand() Line 189   C#

File: NuGet.Client\src\NuGet.Core\NuGet.Packaging\PackageCreation\Xml\PackageMetadataXmlExtensions.cs

function: GetXElementFromPackageDependency

            if (dependency.VersionRange != null && dependency.VersionRange != VersionRange.All)
            {
                attributes.Add(new XAttribute("version", dependency.VersionRange.ToLegacyShortString()));
            }

dependency.VersionRange does contain information whether asterisk was used (e.g. check OriginalString) - but for some reason it's not saved into .nupkg/ ... nuspec file - so asterisk is not written into nuspec file, resulting that asterisk cannot be used at all.

Wondering what is the story behind this.

Why cannot be fixed ?

erdembayar commented 2 years ago

@tapika Could you fill Subject/Topic for your issue? it's missing now.

image

erdembayar commented 2 years ago

Also please correct semver version syntax, you're missing closing tag ] or ), correct syntax would be something like <dependency id="newtonsoft.json" version="[12.0.*, 13.0.1]" />

tapika commented 2 years ago

Updated ticket a bit to provide all information.

erdembayar commented 2 years ago

Also please correct semver version syntax, you're missing closing tag ] or ), correct syntax would be something like <dependency id="newtonsoft.json" version="[12.0.*, 13.0.1]" />

Did you try this one?

zivkan commented 2 years ago

Floating versions (the *) are only supported in PackageReference. Packages themselves (nuspec file) can't use floating versions. NuGet chooses to make deterministic restore a priority. For this reason, package authors can't force package consumers into an "unreliable" build.

tapika commented 2 years ago

Floating versions (the *) are only supported in PackageReference. Packages themselves (nuspec file) can't use floating versions. NuGet chooses to make deterministic restore a priority. For this reason, package authors can't force package consumers into an "unreliable" build.

My assumption was that .nuspec file allows asterisk, because if you build using .nuspec - it would contain asterisk. But apparently I was mistaken - nupkg build also saves incorrect information.

So this kind of config:

    <dependencies>
      <dependency id="packtwo" version="[1.0.*-*, 2.0.0)" />
    </dependencies>

Gets saved into .nupkg as:

      <dependency id="packtwo" version="[1.0.0-0, 2.0.0)" />

I think at very least nuget should report an error if nothing else. (Usage is asterisk is not allowed)

Also this link: https://stackoverflow.com/a/43202541/2338477

Was also misleading. Need to comment in there as well.