Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions modules/packages/npm/creator.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,28 @@ type PackageMetadata struct {
Author User `json:"author"`
ReadmeFilename string `json:"readmeFilename,omitempty"`
Users map[string]bool `json:"users,omitempty"`
License string `json:"license,omitempty"`
License License `json:"license,omitempty"`
}

type License string

func (l *License) UnmarshalJSON(data []byte) error {
switch data[0] {
case '"':
var value string
if err := json.Unmarshal(data, &value); err != nil {
return err
}
*l = License(value)
case '{':
var values map[string]any
if err := json.Unmarshal(data, &values); err != nil {
return err
}
value, _ := values["type"].(string)
*l = License(value)
}
return nil
}

// PackageMetadataVersion documentation: https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#version
Expand All @@ -74,7 +95,7 @@ type PackageMetadataVersion struct {
Description string `json:"description"`
Author User `json:"author"`
Homepage string `json:"homepage,omitempty"`
License string `json:"license,omitempty"`
License License `json:"license,omitempty"`
Repository Repository `json:"repository"`
Keywords []string `json:"keywords,omitempty"`
Dependencies map[string]string `json:"dependencies,omitempty"`
Expand Down
28 changes: 27 additions & 1 deletion modules/packages/npm/creator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"code.gitea.io/gitea/modules/json"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestParsePackage(t *testing.T) {
Expand Down Expand Up @@ -291,11 +292,36 @@ func TestParsePackage(t *testing.T) {
assert.Equal(t, packageDescription, p.Metadata.Readme)
assert.Equal(t, packageAuthor, p.Metadata.Author)
assert.Equal(t, packageBin, p.Metadata.Bin["bin"])
assert.Equal(t, "MIT", p.Metadata.License)
assert.Equal(t, "MIT", string(p.Metadata.License))
assert.Equal(t, "https://gitea.io/", p.Metadata.ProjectURL)
assert.Contains(t, p.Metadata.Dependencies, "package")
assert.Equal(t, "1.2.0", p.Metadata.Dependencies["package"])
assert.Equal(t, repository.Type, p.Metadata.Repository.Type)
assert.Equal(t, repository.URL, p.Metadata.Repository.URL)
})

t.Run("ValidLicenseMap", func(t *testing.T) {
packageJSON := `{
"versions": {
"0.1.1": {
"name": "dev-null",
"version": "0.1.1",
"license": {
"type": "MIT"
},
"dist": {
"integrity": "sha256-"
}
}
},
"_attachments": {
"foo": {
"data": "AAAA"
}
}
}`
p, err := ParsePackage(strings.NewReader(packageJSON))
require.NoError(t, err)
require.Equal(t, "MIT", string(p.Metadata.License))
})
}
2 changes: 1 addition & 1 deletion modules/packages/npm/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type Metadata struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Author string `json:"author,omitempty"`
License string `json:"license,omitempty"`
License License `json:"license,omitempty"`
ProjectURL string `json:"project_url,omitempty"`
Keywords []string `json:"keywords,omitempty"`
Dependencies map[string]string `json:"dependencies,omitempty"`
Expand Down
4 changes: 1 addition & 3 deletions routers/web/repo/editor_cherry_pick.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ func CherryPick(ctx *context.Context) {
ctx.Data["commit_message"] = "revert " + cherryPickCommit.Message()
} else {
ctx.Data["CherryPickType"] = "cherry-pick"
splits := strings.SplitN(cherryPickCommit.Message(), "\n", 2)
ctx.Data["commit_summary"] = splits[0]
ctx.Data["commit_message"] = splits[1]
ctx.Data["commit_summary"], ctx.Data["commit_message"], _ = strings.Cut(cherryPickCommit.Message(), "\n")
}

ctx.HTML(http.StatusOK, tplCherryPick)
Expand Down
31 changes: 12 additions & 19 deletions services/mailer/sender/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
package sender

import (
"errors"
"io"

"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)

type Sender interface {
Expand All @@ -16,23 +14,18 @@ type Sender interface {

var Send = send

func send(sender Sender, msgs ...*Message) error {
if setting.MailService == nil {
log.Error("Mailer: Send is being invoked but mail service hasn't been initialized")
return nil
func send(sender Sender, msg *Message) error {
m := msg.ToMessage()
froms := m.GetFrom()
to, err := m.GetRecipients()
if err != nil {
return err
}
for _, msg := range msgs {
m := msg.ToMessage()
froms := m.GetFrom()
to, err := m.GetRecipients()
if err != nil {
return err
}

// TODO: implement sending from multiple addresses
if err := sender.Send(froms[0].Address, to, m); err != nil {
return err
}
// TODO: implement sending from multiple addresses
if len(froms) == 0 {
// FIXME: no idea why sometimes the "froms" can be empty, need to figure out the root problem
return errors.New("no FROM specified")
}
return nil
return sender.Send(froms[0].Address, to, m)
}
4 changes: 2 additions & 2 deletions services/repository/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func substGiteaTemplateFile(ctx context.Context, tmpDir, tmpDirSubPath string, t
}

generatedContent := generateExpansion(ctx, string(content), templateRepo, generateRepo)
substSubPath := filepath.Clean(filePathSanitize(generateExpansion(ctx, tmpDirSubPath, templateRepo, generateRepo)))
substSubPath := filePathSanitize(generateExpansion(ctx, tmpDirSubPath, templateRepo, generateRepo))
newLocalPath := filepath.Join(tmpDir, substSubPath)
regular, err := util.IsRegularFile(newLocalPath)
if canWrite := regular || errors.Is(err, fs.ErrNotExist); !canWrite {
Expand Down Expand Up @@ -358,5 +358,5 @@ func filePathSanitize(s string) string {
}
fields[i] = field
}
return filepath.FromSlash(strings.Join(fields, "/"))
return filepath.Clean(filepath.FromSlash(strings.Trim(strings.Join(fields, "/"), "/")))
}
21 changes: 13 additions & 8 deletions services/repository/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,24 @@ text/*.txt
}

func TestFilePathSanitize(t *testing.T) {
assert.Equal(t, "test_CON", filePathSanitize("test_CON"))
assert.Equal(t, "test CON", filePathSanitize("test CON "))
assert.Equal(t, "__/traverse/__", filePathSanitize(".. /traverse/ .."))
assert.Equal(t, "./__/a/_git/b_", filePathSanitize("./../a/.git/ b: "))
// path clean
assert.Equal(t, "a", filePathSanitize("//a/"))
assert.Equal(t, "_a", filePathSanitize(`\a`))
assert.Equal(t, "__/a/__", filePathSanitize(".. /a/ .."))
assert.Equal(t, "__/a/_git/b_", filePathSanitize("./../a/.git/ b: "))

// Windows reserved names
assert.Equal(t, "_", filePathSanitize("CoN"))
assert.Equal(t, "_", filePathSanitize("LpT1"))
assert.Equal(t, "_", filePathSanitize("CoM1"))
assert.Equal(t, "test_CON", filePathSanitize("test_CON"))
assert.Equal(t, "test CON", filePathSanitize("test CON "))

// special chars
assert.Equal(t, "_", filePathSanitize("\u0000"))
assert.Equal(t, "目标", filePathSanitize("目标"))
// unlike filepath.Clean, it only sanitizes, doesn't change the separator layout
assert.Equal(t, "", filePathSanitize("")) //nolint:testifylint // for easy reading
assert.Equal(t, ".", filePathSanitize(""))
assert.Equal(t, ".", filePathSanitize("."))
assert.Equal(t, "/", filePathSanitize("/"))
assert.Equal(t, ".", filePathSanitize("/"))
}

func TestProcessGiteaTemplateFile(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion templates/package/content/pypi.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div class="ui form">
<div class="field">
<label>{{svg "octicon-terminal"}} {{ctx.Locale.Tr "packages.pypi.install"}}</label>
<div class="markup"><pre class="code-block"><code>pip install --index-url <origin-url data-url="{{AppSubUrl}}/api/packages/{{.PackageDescriptor.Owner.Name}}/pypi/simple/"></origin-url> --extra-index-url https://pypi.org/ {{.PackageDescriptor.Package.Name}}</code></pre></div>
<div class="markup"><pre class="code-block"><code>pip install --index-url <origin-url data-url="{{AppSubUrl}}/api/packages/{{.PackageDescriptor.Owner.Name}}/pypi/simple/"></origin-url> --extra-index-url https://pypi.org/simple {{.PackageDescriptor.Package.Name}}</code></pre></div>
</div>
<div class="field">
<label>{{ctx.Locale.Tr "packages.registry.documentation" "PyPI" "https://docs.gitea.com/usage/packages/pypi/"}}</label>
Expand Down