Skip to content

Commit e43422b

Browse files
authored
Swift registry metadata: preserve more JSON fields and accept empty metadata (#37254)
1 parent a9108ab commit e43422b

5 files changed

Lines changed: 143 additions & 65 deletions

File tree

models/packages/package_property.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ func InsertProperty(ctx context.Context, refType PropertyType, refID int64, name
5252
// GetProperties gets all properties
5353
func GetProperties(ctx context.Context, refType PropertyType, refID int64) ([]*PackageProperty, error) {
5454
pps := make([]*PackageProperty, 0, 10)
55-
return pps, db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ?", refType, refID).Find(&pps)
55+
return pps, db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ?", refType, refID).OrderBy("id").Find(&pps)
5656
}
5757

5858
// GetPropertiesByName gets all properties with a specific name
5959
func GetPropertiesByName(ctx context.Context, refType PropertyType, refID int64, name string) ([]*PackageProperty, error) {
6060
pps := make([]*PackageProperty, 0, 10)
61-
return pps, db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ? AND name = ?", refType, refID, name).Find(&pps)
61+
return pps, db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ? AND name = ?", refType, refID, name).OrderBy("id").Find(&pps)
6262
}
6363

6464
// UpdateProperty updates a property

modules/packages/swift/metadata.go

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type Metadata struct {
4747
Keywords []string `json:"keywords,omitempty"`
4848
RepositoryURL string `json:"repository_url,omitempty"`
4949
License string `json:"license,omitempty"`
50+
LicenseURL string `json:"license_url,omitempty"`
5051
Author Person `json:"author"`
5152
Manifests map[string]*Manifest `json:"manifests,omitempty"`
5253
}
@@ -67,7 +68,8 @@ type SoftwareSourceCode struct {
6768
Keywords []string `json:"keywords,omitempty"`
6869
CodeRepository string `json:"codeRepository,omitempty"`
6970
License string `json:"license,omitempty"`
70-
Author Person `json:"author"`
71+
LicenseURL string `json:"licenseURL,omitempty"`
72+
Author *Person `json:"author,omitempty"`
7173
ProgrammingLanguage ProgrammingLanguage `json:"programmingLanguage"`
7274
RepositoryURLs []string `json:"repositoryURLs,omitempty"`
7375
}
@@ -181,26 +183,31 @@ func ParsePackage(sr io.ReaderAt, size int64, mr io.Reader) (*Package, error) {
181183
if err := json.NewDecoder(mr).Decode(&ssc); err != nil {
182184
return nil, err
183185
}
184-
185186
p.Metadata.Description = ssc.Description
186187
p.Metadata.Keywords = ssc.Keywords
187188
p.Metadata.License = ssc.License
188-
author := Person{
189-
Name: ssc.Author.Name,
190-
GivenName: ssc.Author.GivenName,
191-
MiddleName: ssc.Author.MiddleName,
192-
FamilyName: ssc.Author.FamilyName,
193-
}
194-
// If Name is not provided, generate it from individual name components
195-
if author.Name == "" {
196-
author.Name = author.String()
189+
p.Metadata.LicenseURL = ssc.LicenseURL
190+
if ssc.Author != nil {
191+
author := Person{
192+
Name: ssc.Author.Name,
193+
GivenName: ssc.Author.GivenName,
194+
MiddleName: ssc.Author.MiddleName,
195+
FamilyName: ssc.Author.FamilyName,
196+
}
197+
// If Name is not provided, generate it from individual name components
198+
if author.Name == "" {
199+
author.Name = author.String()
200+
}
201+
p.Metadata.Author = author
197202
}
198-
p.Metadata.Author = author
199203

200204
p.Metadata.RepositoryURL = ssc.CodeRepository
201205
if !validation.IsValidURL(p.Metadata.RepositoryURL) {
202206
p.Metadata.RepositoryURL = ""
203207
}
208+
if !validation.IsValidURL(p.Metadata.LicenseURL) {
209+
p.Metadata.LicenseURL = ""
210+
}
204211

205212
p.RepositoryURLs = ssc.RepositoryURLs
206213
}

modules/packages/swift/metadata_test.go

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
package swift
55

66
import (
7-
"archive/zip"
87
"bytes"
98
"strings"
109
"testing"
1110

11+
"code.gitea.io/gitea/modules/test"
12+
1213
"github.com/hashicorp/go-version"
1314
"github.com/stretchr/testify/assert"
1415
)
@@ -18,36 +19,24 @@ const (
1819
packageVersion = "1.0.1"
1920
packageDescription = "Package Description"
2021
packageRepositoryURL = "https://gitea.io/gitea/gitea"
22+
packageLicenseURL = "https://opensource.org/license/mit"
2123
packageAuthor = "KN4CK3R"
2224
packageLicense = "MIT"
2325
)
2426

2527
func TestParsePackage(t *testing.T) {
26-
createArchive := func(files map[string][]byte) *bytes.Reader {
27-
var buf bytes.Buffer
28-
zw := zip.NewWriter(&buf)
29-
for filename, content := range files {
30-
w, _ := zw.Create(filename)
31-
w.Write(content)
32-
}
33-
zw.Close()
34-
return bytes.NewReader(buf.Bytes())
35-
}
36-
3728
t.Run("MissingManifestFile", func(t *testing.T) {
38-
data := createArchive(map[string][]byte{"dummy.txt": {}})
39-
40-
p, err := ParsePackage(data, data.Size(), nil)
29+
data := test.WriteZipArchive(map[string]string{"dummy.txt": ""})
30+
p, err := ParsePackage(bytes.NewReader(data.Bytes()), int64(data.Len()), nil)
4131
assert.Nil(t, p)
4232
assert.ErrorIs(t, err, ErrMissingManifestFile)
4333
})
4434

4535
t.Run("ManifestFileTooLarge", func(t *testing.T) {
46-
data := createArchive(map[string][]byte{
47-
"Package.swift": make([]byte, maxManifestFileSize+1),
36+
data := test.WriteZipArchive(map[string]string{
37+
"Package.swift": strings.Repeat("a", maxManifestFileSize+1),
4838
})
49-
50-
p, err := ParsePackage(data, data.Size(), nil)
39+
p, err := ParsePackage(bytes.NewReader(data.Bytes()), int64(data.Len()), nil)
5140
assert.Nil(t, p)
5241
assert.ErrorIs(t, err, ErrManifestFileTooLarge)
5342
})
@@ -56,12 +45,12 @@ func TestParsePackage(t *testing.T) {
5645
content1 := "// swift-tools-version:5.7\n//\n// Package.swift"
5746
content2 := "// swift-tools-version:5.6\n//\n// Package@swift-5.6.swift"
5847

59-
data := createArchive(map[string][]byte{
60-
"Package.swift": []byte(content1),
61-
"Package@swift-5.5.swift": []byte(content2),
48+
data := test.WriteZipArchive(map[string]string{
49+
"Package.swift": content1,
50+
"Package@swift-5.5.swift": content2,
6251
})
6352

64-
p, err := ParsePackage(data, data.Size(), nil)
53+
p, err := ParsePackage(bytes.NewReader(data.Bytes()), int64(data.Len()), nil)
6554
assert.NotNil(t, p)
6655
assert.NoError(t, err)
6756

@@ -77,14 +66,13 @@ func TestParsePackage(t *testing.T) {
7766
})
7867

7968
t.Run("WithMetadata", func(t *testing.T) {
80-
data := createArchive(map[string][]byte{
81-
"Package.swift": []byte("// swift-tools-version:5.7\n//\n// Package.swift"),
69+
data := test.WriteZipArchive(map[string]string{
70+
"Package.swift": "// swift-tools-version:5.7\n//\n// Package.swift",
8271
})
8372

8473
p, err := ParsePackage(
85-
data,
86-
data.Size(),
87-
strings.NewReader(`{"name":"`+packageName+`","version":"`+packageVersion+`","description":"`+packageDescription+`","keywords":["swift","package"],"license":"`+packageLicense+`","codeRepository":"`+packageRepositoryURL+`","author":{"givenName":"`+packageAuthor+`"},"repositoryURLs":["`+packageRepositoryURL+`"]}`),
74+
bytes.NewReader(data.Bytes()), int64(data.Len()),
75+
strings.NewReader(`{"name":"`+packageName+`","version":"`+packageVersion+`","description":"`+packageDescription+`","keywords":["swift","package"],"license":"`+packageLicense+`","licenseURL":"`+packageLicenseURL+`","codeRepository":"`+packageRepositoryURL+`","author":{"givenName":"`+packageAuthor+`"},"repositoryURLs":["`+packageRepositoryURL+`"]}`),
8876
)
8977
assert.NotNil(t, p)
9078
assert.NoError(t, err)
@@ -97,21 +85,21 @@ func TestParsePackage(t *testing.T) {
9785
assert.Equal(t, packageDescription, p.Metadata.Description)
9886
assert.ElementsMatch(t, []string{"swift", "package"}, p.Metadata.Keywords)
9987
assert.Equal(t, packageLicense, p.Metadata.License)
88+
assert.Equal(t, packageLicenseURL, p.Metadata.LicenseURL)
10089
assert.Equal(t, packageAuthor, p.Metadata.Author.Name)
10190
assert.Equal(t, packageAuthor, p.Metadata.Author.GivenName)
10291
assert.Equal(t, packageRepositoryURL, p.Metadata.RepositoryURL)
10392
assert.ElementsMatch(t, []string{packageRepositoryURL}, p.RepositoryURLs)
10493
})
10594

10695
t.Run("WithExplicitNameField", func(t *testing.T) {
107-
data := createArchive(map[string][]byte{
108-
"Package.swift": []byte("// swift-tools-version:5.7\n//\n// Package.swift"),
96+
data := test.WriteZipArchive(map[string]string{
97+
"Package.swift": "// swift-tools-version:5.7\n//\n// Package.swift",
10998
})
11099

111100
authorName := "John Doe"
112101
p, err := ParsePackage(
113-
data,
114-
data.Size(),
102+
bytes.NewReader(data.Bytes()), int64(data.Len()),
115103
strings.NewReader(`{"name":"`+packageName+`","version":"`+packageVersion+`","description":"`+packageDescription+`","author":{"name":"`+authorName+`","givenName":"John","familyName":"Doe"}}`),
116104
)
117105
assert.NotNil(t, p)
@@ -122,15 +110,30 @@ func TestParsePackage(t *testing.T) {
122110
assert.Equal(t, "Doe", p.Metadata.Author.FamilyName)
123111
})
124112

113+
t.Run("WithEmptyJSONMetadata", func(t *testing.T) {
114+
data := test.WriteZipArchive(map[string]string{
115+
"Package.swift": "// swift-tools-version:5.7\n//\n// Package.swift",
116+
})
117+
118+
p, err := ParsePackage(
119+
bytes.NewReader(data.Bytes()), int64(data.Len()),
120+
strings.NewReader(`{}`),
121+
)
122+
assert.NotNil(t, p)
123+
assert.NoError(t, err)
124+
assert.NotNil(t, p.Metadata)
125+
assert.Empty(t, p.Metadata.Author.Name)
126+
assert.Empty(t, p.RepositoryURLs)
127+
})
128+
125129
t.Run("NameFieldGeneration", func(t *testing.T) {
126-
data := createArchive(map[string][]byte{
127-
"Package.swift": []byte("// swift-tools-version:5.7\n//\n// Package.swift"),
130+
data := test.WriteZipArchive(map[string]string{
131+
"Package.swift": "// swift-tools-version:5.7\n//\n// Package.swift",
128132
})
129133

130134
// Test with only individual name components - Name should be auto-generated
131135
p, err := ParsePackage(
132-
data,
133-
data.Size(),
136+
bytes.NewReader(data.Bytes()), int64(data.Len()),
134137
strings.NewReader(`{"author":{"givenName":"John","middleName":"Q","familyName":"Doe"}}`),
135138
)
136139
assert.NotNil(t, p)

routers/api/packages/swift/swift.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,23 @@ func PackageVersionMetadata(ctx *context.Context) {
198198
}
199199

200200
metadata := pd.Metadata.(*swift_module.Metadata)
201+
repositoryURLs := make([]string, 0, len(pd.VersionProperties))
202+
for _, property := range pd.VersionProperties {
203+
if property.Name == swift_module.PropertyRepositoryURL {
204+
repositoryURLs = append(repositoryURLs, property.Value)
205+
}
206+
}
207+
208+
var author *swift_module.Person
209+
if metadata.Author.Name != "" || metadata.Author.GivenName != "" || metadata.Author.MiddleName != "" || metadata.Author.FamilyName != "" {
210+
author = &swift_module.Person{
211+
Type: "Person",
212+
Name: metadata.Author.Name,
213+
GivenName: metadata.Author.GivenName,
214+
MiddleName: metadata.Author.MiddleName,
215+
FamilyName: metadata.Author.FamilyName,
216+
}
217+
}
201218

202219
setResponseHeaders(ctx.Resp, &headers{})
203220

@@ -220,18 +237,14 @@ func PackageVersionMetadata(ctx *context.Context) {
220237
Keywords: metadata.Keywords,
221238
CodeRepository: metadata.RepositoryURL,
222239
License: metadata.License,
240+
LicenseURL: metadata.LicenseURL,
241+
Author: author,
223242
ProgrammingLanguage: swift_module.ProgrammingLanguage{
224243
Type: "ComputerLanguage",
225244
Name: "Swift",
226245
URL: "https://swift.org",
227246
},
228-
Author: swift_module.Person{
229-
Type: "Person",
230-
Name: metadata.Author.String(),
231-
GivenName: metadata.Author.GivenName,
232-
MiddleName: metadata.Author.MiddleName,
233-
FamilyName: metadata.Author.FamilyName,
234-
},
247+
RepositoryURLs: repositoryURLs,
235248
},
236249
})
237250
}

0 commit comments

Comments
 (0)