Normalize NuGet package version on upload (#22186)
Fixes #22178 After this change upload versions with different semver metadata are treated as the same version and trigger a duplicated version error. Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
parent
fe6608f72b
commit
86ace4b5c2
4 changed files with 36 additions and 21 deletions
|
@ -5,8 +5,10 @@ package nuget
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
|
"bytes"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -182,7 +184,23 @@ func ParseNuspecMetaData(r io.Reader) (*Package, error) {
|
||||||
return &Package{
|
return &Package{
|
||||||
PackageType: packageType,
|
PackageType: packageType,
|
||||||
ID: p.Metadata.ID,
|
ID: p.Metadata.ID,
|
||||||
Version: v.String(),
|
Version: toNormalizedVersion(v),
|
||||||
Metadata: m,
|
Metadata: m,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://learn.microsoft.com/en-us/nuget/concepts/package-versioning#normalized-version-numbers
|
||||||
|
// https://github.com/NuGet/NuGet.Client/blob/dccbd304b11103e08b97abf4cf4bcc1499d9235a/src/NuGet.Core/NuGet.Versioning/VersionFormatter.cs#L121
|
||||||
|
func toNormalizedVersion(v *version.Version) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
segments := v.Segments64()
|
||||||
|
fmt.Fprintf(&buf, "%d.%d.%d", segments[0], segments[1], segments[2])
|
||||||
|
if len(segments) > 3 && segments[3] > 0 {
|
||||||
|
fmt.Fprintf(&buf, ".%d", segments[3])
|
||||||
|
}
|
||||||
|
pre := v.Prerelease()
|
||||||
|
if pre != "" {
|
||||||
|
fmt.Fprint(&buf, "-", pre)
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
|
@ -146,6 +146,19 @@ func TestParseNuspecMetaData(t *testing.T) {
|
||||||
assert.Len(t, deps, 1)
|
assert.Len(t, deps, 1)
|
||||||
assert.Equal(t, dependencyID, deps[0].ID)
|
assert.Equal(t, dependencyID, deps[0].ID)
|
||||||
assert.Equal(t, dependencyVersion, deps[0].Version)
|
assert.Equal(t, dependencyVersion, deps[0].Version)
|
||||||
|
|
||||||
|
t.Run("NormalizedVersion", func(t *testing.T) {
|
||||||
|
np, err := ParseNuspecMetaData(strings.NewReader(`<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>test</id>
|
||||||
|
<version>1.04.5.2.5-rc.1+metadata</version>
|
||||||
|
</metadata>
|
||||||
|
</package>`))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, np)
|
||||||
|
assert.Equal(t, "1.4.5.2-rc.1", np.Version)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Symbols Package", func(t *testing.T) {
|
t.Run("Symbols Package", func(t *testing.T) {
|
||||||
|
|
|
@ -344,7 +344,7 @@ func createEntry(l *linkBuilder, pd *packages_model.PackageDescriptor, withNames
|
||||||
Content: content,
|
Content: content,
|
||||||
Properties: &FeedEntryProperties{
|
Properties: &FeedEntryProperties{
|
||||||
Version: pd.Version.Version,
|
Version: pd.Version.Version,
|
||||||
NormalizedVersion: normalizeVersion(pd.SemVer),
|
NormalizedVersion: pd.Version.Version,
|
||||||
Authors: metadata.Authors,
|
Authors: metadata.Authors,
|
||||||
Dependencies: buildDependencyString(metadata),
|
Dependencies: buildDependencyString(metadata),
|
||||||
Description: metadata.Description,
|
Description: metadata.Description,
|
||||||
|
|
|
@ -4,15 +4,11 @@
|
||||||
package nuget
|
package nuget
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
packages_model "code.gitea.io/gitea/models/packages"
|
packages_model "code.gitea.io/gitea/models/packages"
|
||||||
nuget_module "code.gitea.io/gitea/modules/packages/nuget"
|
nuget_module "code.gitea.io/gitea/modules/packages/nuget"
|
||||||
|
|
||||||
"github.com/hashicorp/go-version"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://docs.microsoft.com/en-us/nuget/api/service-index#resources
|
// https://docs.microsoft.com/en-us/nuget/api/service-index#resources
|
||||||
|
@ -95,8 +91,8 @@ func createRegistrationIndexResponse(l *linkBuilder, pds []*packages_model.Packa
|
||||||
{
|
{
|
||||||
RegistrationPageURL: l.GetRegistrationIndexURL(pds[0].Package.Name),
|
RegistrationPageURL: l.GetRegistrationIndexURL(pds[0].Package.Name),
|
||||||
Count: len(pds),
|
Count: len(pds),
|
||||||
Lower: normalizeVersion(pds[0].SemVer),
|
Lower: pds[0].Version.Version,
|
||||||
Upper: normalizeVersion(pds[len(pds)-1].SemVer),
|
Upper: pds[len(pds)-1].Version.Version,
|
||||||
Items: items,
|
Items: items,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -173,7 +169,7 @@ type PackageVersionsResponse struct {
|
||||||
func createPackageVersionsResponse(pds []*packages_model.PackageDescriptor) *PackageVersionsResponse {
|
func createPackageVersionsResponse(pds []*packages_model.PackageDescriptor) *PackageVersionsResponse {
|
||||||
versions := make([]string, 0, len(pds))
|
versions := make([]string, 0, len(pds))
|
||||||
for _, pd := range pds {
|
for _, pd := range pds {
|
||||||
versions = append(versions, normalizeVersion(pd.SemVer))
|
versions = append(versions, pd.Version.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &PackageVersionsResponse{
|
return &PackageVersionsResponse{
|
||||||
|
@ -248,15 +244,3 @@ func createSearchResult(l *linkBuilder, pds []*packages_model.PackageDescriptor)
|
||||||
RegistrationIndexURL: l.GetRegistrationIndexURL(latest.Package.Name),
|
RegistrationIndexURL: l.GetRegistrationIndexURL(latest.Package.Name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalizeVersion removes the metadata
|
|
||||||
func normalizeVersion(v *version.Version) string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
segments := v.Segments64()
|
|
||||||
fmt.Fprintf(&buf, "%d.%d.%d", segments[0], segments[1], segments[2])
|
|
||||||
pre := v.Prerelease()
|
|
||||||
if pre != "" {
|
|
||||||
fmt.Fprintf(&buf, "-%s", pre)
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue