Skip to content

Commit 3c07ed0

Browse files
Racer159KN4CK3R
andauthored
Remove semver compatible flag and change pypi to an array of test cases (#21708) (#21729)
Backport (#21708) This addresses #21707 and adds a second package test case for a non-semver compatible version (this might be overkill though since you could also edit the old package version to have an epoch in front and see the error, this just seemed more flexible for the future). Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
1 parent 995ae06 commit 3c07ed0

File tree

3 files changed

+50
-7
lines changed

3 files changed

+50
-7
lines changed

integrations/api_packages_pypi_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func TestPackagePyPI(t *testing.T) {
2828
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
2929

3030
packageName := "test-package"
31-
packageVersion := "1.0.1+r1234"
31+
packageVersion := "1!1.0.1+r1234"
3232
packageAuthor := "KN4CK3R"
3333
packageDescription := "Test Description"
3434

@@ -71,7 +71,7 @@ func TestPackagePyPI(t *testing.T) {
7171

7272
pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
7373
assert.NoError(t, err)
74-
assert.NotNil(t, pd.SemVer)
74+
assert.Nil(t, pd.SemVer)
7575
assert.IsType(t, &pypi.Metadata{}, pd.Metadata)
7676
assert.Equal(t, packageName, pd.Package.Name)
7777
assert.Equal(t, packageVersion, pd.Version.Version)
@@ -99,7 +99,7 @@ func TestPackagePyPI(t *testing.T) {
9999

100100
pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
101101
assert.NoError(t, err)
102-
assert.NotNil(t, pd.SemVer)
102+
assert.Nil(t, pd.SemVer)
103103
assert.IsType(t, &pypi.Metadata{}, pd.Metadata)
104104
assert.Equal(t, packageName, pd.Package.Name)
105105
assert.Equal(t, packageVersion, pd.Version.Version)

routers/api/packages/pypi/pypi.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ import (
2222
packages_service "code.gitea.io/gitea/services/packages"
2323
)
2424

25-
// https://www.python.org/dev/peps/pep-0503/#normalized-names
25+
// https://peps.python.org/pep-0426/#name
2626
var normalizer = strings.NewReplacer(".", "-", "_", "-")
27-
var nameMatcher = regexp.MustCompile(`\A[a-zA-Z0-9\.\-_]+\z`)
27+
var nameMatcher = regexp.MustCompile(`\A(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\.\-_]*[a-zA-Z0-9])\z`)
2828

2929
// https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions
3030
var versionMatcher = regexp.MustCompile(`\Av?` +
@@ -130,7 +130,7 @@ func UploadPackageFile(ctx *context.Context) {
130130

131131
packageName := normalizer.Replace(ctx.Req.FormValue("name"))
132132
packageVersion := ctx.Req.FormValue("version")
133-
if !nameMatcher.MatchString(packageName) || !versionMatcher.MatchString(packageVersion) {
133+
if !isValidNameAndVersion(packageName, packageVersion) {
134134
apiError(ctx, http.StatusBadRequest, "invalid name or version")
135135
return
136136
}
@@ -148,7 +148,7 @@ func UploadPackageFile(ctx *context.Context) {
148148
Name: packageName,
149149
Version: packageVersion,
150150
},
151-
SemverCompatible: true,
151+
SemverCompatible: false,
152152
Creator: ctx.Doer,
153153
Metadata: &pypi_module.Metadata{
154154
Author: ctx.Req.FormValue("author"),
@@ -179,3 +179,7 @@ func UploadPackageFile(ctx *context.Context) {
179179

180180
ctx.Status(http.StatusCreated)
181181
}
182+
183+
func isValidNameAndVersion(packageName, packageVersion string) bool {
184+
return nameMatcher.MatchString(packageName) && versionMatcher.MatchString(packageVersion)
185+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package pypi
6+
7+
import (
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestIsValidNameAndVersion(t *testing.T) {
14+
// The test cases below were created from the following Python PEPs:
15+
// https://peps.python.org/pep-0426/#name
16+
// https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions
17+
18+
// Valid Cases
19+
assert.True(t, isValidNameAndVersion("A", "1.0.1"))
20+
assert.True(t, isValidNameAndVersion("Test.Name.1234", "1.0.1"))
21+
assert.True(t, isValidNameAndVersion("test_name", "1.0.1"))
22+
assert.True(t, isValidNameAndVersion("test-name", "1.0.1"))
23+
assert.True(t, isValidNameAndVersion("test-name", "v1.0.1"))
24+
assert.True(t, isValidNameAndVersion("test-name", "2012.4"))
25+
assert.True(t, isValidNameAndVersion("test-name", "1.0.1-alpha"))
26+
assert.True(t, isValidNameAndVersion("test-name", "1.0.1a1"))
27+
assert.True(t, isValidNameAndVersion("test-name", "1.0b2.r345.dev456"))
28+
assert.True(t, isValidNameAndVersion("test-name", "1!1.0.1"))
29+
assert.True(t, isValidNameAndVersion("test-name", "1.0.1+local.1"))
30+
31+
// Invalid Cases
32+
assert.False(t, isValidNameAndVersion(".test-name", "1.0.1"))
33+
assert.False(t, isValidNameAndVersion("test!name", "1.0.1"))
34+
assert.False(t, isValidNameAndVersion("-test-name", "1.0.1"))
35+
assert.False(t, isValidNameAndVersion("test-name-", "1.0.1"))
36+
assert.False(t, isValidNameAndVersion("test-name", "a1.0.1"))
37+
assert.False(t, isValidNameAndVersion("test-name", "1.0.1aa"))
38+
assert.False(t, isValidNameAndVersion("test-name", "1.0.0-alpha.beta"))
39+
}

0 commit comments

Comments
 (0)