Skip to content

Commit 805a14c

Browse files
Racer159KN4CK3R
andauthored
Remove semver compatible flag and change pypi to an array of test cases (#21708) (#21730)
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 <[email protected]>
1 parent 69a5454 commit 805a14c

File tree

3 files changed

+50
-7
lines changed

3 files changed

+50
-7
lines changed

Diff for: routers/api/packages/pypi/pypi.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ import (
2121
packages_service "code.gitea.io/gitea/services/packages"
2222
)
2323

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

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

129129
packageName := normalizer.Replace(ctx.Req.FormValue("name"))
130130
packageVersion := ctx.Req.FormValue("version")
131-
if !nameMatcher.MatchString(packageName) || !versionMatcher.MatchString(packageVersion) {
131+
if !isValidNameAndVersion(packageName, packageVersion) {
132132
apiError(ctx, http.StatusBadRequest, "invalid name or version")
133133
return
134134
}
@@ -146,7 +146,7 @@ func UploadPackageFile(ctx *context.Context) {
146146
Name: packageName,
147147
Version: packageVersion,
148148
},
149-
SemverCompatible: true,
149+
SemverCompatible: false,
150150
Creator: ctx.Doer,
151151
Metadata: &pypi_module.Metadata{
152152
Author: ctx.Req.FormValue("author"),
@@ -177,3 +177,7 @@ func UploadPackageFile(ctx *context.Context) {
177177

178178
ctx.Status(http.StatusCreated)
179179
}
180+
181+
func isValidNameAndVersion(packageName, packageVersion string) bool {
182+
return nameMatcher.MatchString(packageName) && versionMatcher.MatchString(packageVersion)
183+
}

Diff for: routers/api/packages/pypi/pypi_test.go

+39
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+
}

Diff for: tests/integration/api_packages_pypi_test.go

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

3131
packageName := "test-package"
32-
packageVersion := "1.0.1+r1234"
32+
packageVersion := "1!1.0.1+r1234"
3333
packageAuthor := "KN4CK3R"
3434
packageDescription := "Test Description"
3535

@@ -72,7 +72,7 @@ func TestPackagePyPI(t *testing.T) {
7272

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

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

0 commit comments

Comments
 (0)