1
1
mirror of https://github.com/go-gitea/gitea synced 2025-09-21 08:08:14 +00:00

fix: add author.name field to Swift Package Registry API response (#35410) (#35431)

Backport #35410 by ahanoff

Fixes #35159

Swift Package Manager expects an 'author.name' field in package
metadata, but Gitea was only providing schema.org format fields
(givenName, middleName, familyName). This caused SPM to fail with
keyNotFound error when fetching package metadata.

Changes:
- Add 'name' field to Person struct (inherited from
https://schema.org/Thing)
- Populate 'name' field in API response using existing String() method
- Maintains backward compatibility with existing schema.org fields
- Provides both formats for maximum compatibility

The fix ensures Swift Package Manager can successfully resolve packages
while preserving full schema.org compliance.

Co-authored-by: Akhan Zhakiyanov <ahanoff@gmail.com>
This commit is contained in:
Giteabot
2025-09-08 03:37:53 +08:00
committed by GitHub
parent 3c7e7a19dd
commit 89c99a4dcb
4 changed files with 89 additions and 1 deletions

View File

@@ -82,6 +82,7 @@ type ProgrammingLanguage struct {
// https://schema.org/Person
type Person struct {
Type string `json:"@type,omitempty"`
Name string `json:"name,omitempty"` // inherited from https://schema.org/Thing
GivenName string `json:"givenName,omitempty"`
MiddleName string `json:"middleName,omitempty"`
FamilyName string `json:"familyName,omitempty"`
@@ -184,11 +185,17 @@ func ParsePackage(sr io.ReaderAt, size int64, mr io.Reader) (*Package, error) {
p.Metadata.Description = ssc.Description
p.Metadata.Keywords = ssc.Keywords
p.Metadata.License = ssc.License
p.Metadata.Author = Person{
author := Person{
Name: ssc.Author.Name,
GivenName: ssc.Author.GivenName,
MiddleName: ssc.Author.MiddleName,
FamilyName: ssc.Author.FamilyName,
}
// If Name is not provided, generate it from individual name components
if author.Name == "" {
author.Name = author.String()
}
p.Metadata.Author = author
p.Metadata.RepositoryURL = ssc.CodeRepository
if !validation.IsValidURL(p.Metadata.RepositoryURL) {

View File

@@ -97,10 +97,49 @@ func TestParsePackage(t *testing.T) {
assert.Equal(t, packageDescription, p.Metadata.Description)
assert.ElementsMatch(t, []string{"swift", "package"}, p.Metadata.Keywords)
assert.Equal(t, packageLicense, p.Metadata.License)
assert.Equal(t, packageAuthor, p.Metadata.Author.Name)
assert.Equal(t, packageAuthor, p.Metadata.Author.GivenName)
assert.Equal(t, packageRepositoryURL, p.Metadata.RepositoryURL)
assert.ElementsMatch(t, []string{packageRepositoryURL}, p.RepositoryURLs)
})
t.Run("WithExplicitNameField", func(t *testing.T) {
data := createArchive(map[string][]byte{
"Package.swift": []byte("// swift-tools-version:5.7\n//\n// Package.swift"),
})
authorName := "John Doe"
p, err := ParsePackage(
data,
data.Size(),
strings.NewReader(`{"name":"`+packageName+`","version":"`+packageVersion+`","description":"`+packageDescription+`","author":{"name":"`+authorName+`","givenName":"John","familyName":"Doe"}}`),
)
assert.NotNil(t, p)
assert.NoError(t, err)
assert.Equal(t, authorName, p.Metadata.Author.Name)
assert.Equal(t, "John", p.Metadata.Author.GivenName)
assert.Equal(t, "Doe", p.Metadata.Author.FamilyName)
})
t.Run("NameFieldGeneration", func(t *testing.T) {
data := createArchive(map[string][]byte{
"Package.swift": []byte("// swift-tools-version:5.7\n//\n// Package.swift"),
})
// Test with only individual name components - Name should be auto-generated
p, err := ParsePackage(
data,
data.Size(),
strings.NewReader(`{"author":{"givenName":"John","middleName":"Q","familyName":"Doe"}}`),
)
assert.NotNil(t, p)
assert.NoError(t, err)
assert.Equal(t, "John Q Doe", p.Metadata.Author.Name)
assert.Equal(t, "John", p.Metadata.Author.GivenName)
assert.Equal(t, "Q", p.Metadata.Author.MiddleName)
assert.Equal(t, "Doe", p.Metadata.Author.FamilyName)
})
}
func TestTrimmedVersionString(t *testing.T) {
@@ -142,3 +181,43 @@ func TestTrimmedVersionString(t *testing.T) {
assert.Equal(t, c.Expected, TrimmedVersionString(c.Version))
}
}
func TestPersonNameString(t *testing.T) {
cases := []struct {
Name string
Person Person
Expected string
}{
{
Name: "GivenNameOnly",
Person: Person{GivenName: "John"},
Expected: "John",
},
{
Name: "GivenAndFamily",
Person: Person{GivenName: "John", FamilyName: "Doe"},
Expected: "John Doe",
},
{
Name: "FullName",
Person: Person{GivenName: "John", MiddleName: "Q", FamilyName: "Doe"},
Expected: "John Q Doe",
},
{
Name: "MiddleAndFamily",
Person: Person{MiddleName: "Q", FamilyName: "Doe"},
Expected: "Q Doe",
},
{
Name: "Empty",
Person: Person{},
Expected: "",
},
}
for _, c := range cases {
t.Run(c.Name, func(t *testing.T) {
assert.Equal(t, c.Expected, c.Person.String())
})
}
}