diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 78042a7598..fc6f38ec53 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -811,7 +811,7 @@ rules: wc/no-constructor-params: [2] wc/no-constructor: [2] wc/no-customized-built-in-elements: [2] - wc/no-exports-with-element: [2] + wc/no-exports-with-element: [0] wc/no-invalid-element-name: [2] wc/no-invalid-extends: [2] wc/no-method-prefixed-with-on: [2] diff --git a/Makefile b/Makefile index aea352e6d5..6ef4c521c9 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-che GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0 GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.2 GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 -MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4 +MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1 SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5 XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 @@ -134,6 +134,8 @@ TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMAN GO_DIRS := build cmd models modules routers services tests WEB_DIRS := web_src/js web_src/css +SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) docs/content templates options/locale/locale_en-US.ini .github + GO_SOURCES := $(wildcard *.go) GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go) GO_SOURCES += $(GENERATED_GO_DEST) @@ -212,6 +214,8 @@ help: @echo " - lint-swagger lint swagger files" @echo " - lint-templates lint template files" @echo " - lint-yaml lint yaml files" + @echo " - lint-spell lint spelling" + @echo " - lint-spell-fix lint spelling and fix issues" @echo " - checks run various consistency checks" @echo " - checks-frontend check frontend files" @echo " - checks-backend check backend files" @@ -303,10 +307,6 @@ fmt-check: fmt exit 1; \ fi -.PHONY: misspell-check -misspell-check: - go run $(MISSPELL_PACKAGE) -error $(GO_DIRS) $(WEB_DIRS) - .PHONY: $(TAGS_EVIDENCE) $(TAGS_EVIDENCE): @mkdir -p $(MAKE_EVIDENCE_DIR) @@ -368,13 +368,13 @@ checks: checks-frontend checks-backend checks-frontend: lockfile-check svg-check .PHONY: checks-backend -checks-backend: tidy-check swagger-check fmt-check misspell-check forgejo-api-validate swagger-validate security-check +checks-backend: tidy-check swagger-check fmt-check swagger-validate security-check .PHONY: lint -lint: lint-frontend lint-backend +lint: lint-frontend lint-backend lint-spell .PHONY: lint-fix -lint-fix: lint-frontend-fix lint-backend-fix +lint-fix: lint-frontend-fix lint-backend-fix lint-spell-fix .PHONY: lint-frontend lint-frontend: lint-js lint-css @@ -412,6 +412,14 @@ lint-swagger: node_modules lint-md: node_modules npx markdownlint docs *.md +.PHONY: lint-spell +lint-spell: + @go run $(MISSPELL_PACKAGE) -error $(SPELLCHECK_FILES) + +.PHONY: lint-spell-fix +lint-spell-fix: + @go run $(MISSPELL_PACKAGE) -w $(SPELLCHECK_FILES) + .PHONY: lint-go lint-go: $(GO) run $(GOLANGCI_LINT_PACKAGE) run $(GOLANGCI_LINT_ARGS) diff --git a/cmd/serv.go b/cmd/serv.go index e014877bc6..ac754ee12f 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -216,16 +216,18 @@ func runServ(c *cli.Context) error { } } - // LowerCase and trim the repoPath as that's how they are stored. - repoPath = strings.ToLower(strings.TrimSpace(repoPath)) - rr := strings.SplitN(repoPath, "/", 2) if len(rr) != 2 { return fail(ctx, "Invalid repository path", "Invalid repository path: %v", repoPath) } - username := strings.ToLower(rr[0]) - reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git")) + username := rr[0] + reponame := strings.TrimSuffix(rr[1], ".git") + + // LowerCase and trim the repoPath as that's how they are stored. + // This should be done after splitting the repoPath into username and reponame + // so that username and reponame are not affected. + repoPath = strings.ToLower(strings.TrimSpace(repoPath)) if alphaDashDotPattern.MatchString(reponame) { return fail(ctx, "Invalid repo name", "Invalid repo name: %s", reponame) diff --git a/docs/content/administration/config-cheat-sheet.zh-cn.md b/docs/content/administration/config-cheat-sheet.zh-cn.md index 2cee70daab..8236852ad3 100644 --- a/docs/content/administration/config-cheat-sheet.zh-cn.md +++ b/docs/content/administration/config-cheat-sheet.zh-cn.md @@ -29,7 +29,7 @@ menu: [ini](https://github.com/go-ini/ini/#recursive-values) 这里的说明。 标注了 :exclamation: 的配置项表明除非你真的理解这个配置项的意义,否则最好使用默认值。 -在下面的默认值中,`$XYZ`代表环境变量`XYZ`的值(详见:`enviroment-to-ini`)。 _`XxYyZz`_是指默认配置的一部分列出的值。这些在 app.ini 文件中不起作用,仅在此处列出作为文档说明。 +在下面的默认值中,`$XYZ`代表环境变量`XYZ`的值(详见:`environment-to-ini`)。 _`XxYyZz`_是指默认配置的一部分列出的值。这些在 app.ini 文件中不起作用,仅在此处列出作为文档说明。 包含`#`或者`;`的变量必须使用引号(`` ` ``或者`""""`)包裹,否则会被解析为注释。 diff --git a/docs/content/development/hacking-on-gitea.en-us.md b/docs/content/development/hacking-on-gitea.en-us.md index 4b132c49d9..df8a9047d6 100644 --- a/docs/content/development/hacking-on-gitea.en-us.md +++ b/docs/content/development/hacking-on-gitea.en-us.md @@ -243,10 +243,10 @@ documentation using: make generate-swagger ``` -You should validate your generated Swagger file and spell-check it with: +You should validate your generated Swagger file: ```bash -make swagger-validate misspell-check +make swagger-validate ``` You should commit the changed swagger JSON file. The continuous integration diff --git a/docs/content/development/hacking-on-gitea.zh-cn.md b/docs/content/development/hacking-on-gitea.zh-cn.md index 364bbf1ffe..2dba3c92b6 100644 --- a/docs/content/development/hacking-on-gitea.zh-cn.md +++ b/docs/content/development/hacking-on-gitea.zh-cn.md @@ -228,10 +228,10 @@ Gitea Logo的 PNG 和 SVG 版本是使用 `TAGS="gitea" make generate-images` make generate-swagger ``` -您应该验证生成的 Swagger 文件并使用以下命令对其进行拼写检查: +您应该验证生成的 Swagger 文件: ```bash -make swagger-validate misspell-check +make swagger-validate ``` 您应该提交更改后的 swagger JSON 文件。持续集成服务器将使用以下方法检查是否已完成: diff --git a/docs/content/installation/from-source.en-us.md b/docs/content/installation/from-source.en-us.md index 601e074745..cd9fd56511 100644 --- a/docs/content/installation/from-source.en-us.md +++ b/docs/content/installation/from-source.en-us.md @@ -27,13 +27,7 @@ Next, [install Node.js with npm](https://nodejs.org/en/download/) which is required to build the JavaScript and CSS files. The minimum supported Node.js version is @minNodeVersion@ and the latest LTS version is recommended. -**Note**: When executing make tasks that require external tools, like -`make misspell-check`, Gitea will automatically download and build these as -necessary. To be able to use these, you must have the `"$GOPATH/bin"` directory -on the executable path. If you don't add the go bin directory to the -executable path, you will have to manage this yourself. - -**Note 2**: Go version @minGoVersion@ or higher is required. However, it is recommended to +**Note**: Go version @minGoVersion@ or higher is required. However, it is recommended to obtain the same version as our continuous integration, see the advice given in [Hacking on Gitea](development/hacking-on-gitea.md) diff --git a/docs/content/installation/from-source.zh-cn.md b/docs/content/installation/from-source.zh-cn.md index c2bd5785b2..3ff7efb4ed 100644 --- a/docs/content/installation/from-source.zh-cn.md +++ b/docs/content/installation/from-source.zh-cn.md @@ -21,9 +21,7 @@ menu: 接下来,[安装 Node.js 和 npm](https://nodejs.org/zh-cn/download/), 这是构建 JavaScript 和 CSS 文件所需的。最低支持的 Node.js 版本是 @minNodeVersion@,建议使用最新的 LTS 版本。 -**注意**:当执行需要外部工具的 make 任务(如`make misspell-check`)时,Gitea 将根据需要自动下载和构建这些工具。为了能够实现这个目的,你必须将`"$GOPATH/bin"`目录添加到可执行路径中。如果没有将 Go 的二进制目录添加到可执行路径中,你需要自行解决产生的问题。 - -**注意2**:需要 Go 版本 @minGoVersion@ 或更高版本。不过,建议获取与我们的持续集成(continuous integration, CI)相同的版本,请参阅在 [Hacking on Gitea](development/hacking-on-gitea.md) 中给出的建议。 +**注意**:需要 Go 版本 @minGoVersion@ 或更高版本。不过,建议获取与我们的持续集成(continuous integration, CI)相同的版本,请参阅在 [Hacking on Gitea](development/hacking-on-gitea.md) 中给出的建议。 ## 下载 diff --git a/docs/content/usage/packages/overview.en-us.md b/docs/content/usage/packages/overview.en-us.md index 44d18ff482..89fc6f286e 100644 --- a/docs/content/usage/packages/overview.en-us.md +++ b/docs/content/usage/packages/overview.en-us.md @@ -42,7 +42,7 @@ The following package managers are currently supported: | [PyPI](usage/packages/pypi.md) | Python | `pip`, `twine` | | [RPM](usage/packages/rpm.md) | - | `yum`, `dnf`, `zypper` | | [RubyGems](usage/packages/rubygems.md) | Ruby | `gem`, `Bundler` | -| [Swift](usage/packages/rubygems.md) | Swift | `swift` | +| [Swift](usage/packages/swift.md) | Swift | `swift` | | [Vagrant](usage/packages/vagrant.md) | - | `vagrant` | **The following paragraphs only apply if Packages are not globally disabled!** diff --git a/docs/content/usage/packages/swift.en-us.md b/docs/content/usage/packages/swift.en-us.md index 606fa20b36..38eb155641 100644 --- a/docs/content/usage/packages/swift.en-us.md +++ b/docs/content/usage/packages/swift.en-us.md @@ -26,7 +26,8 @@ To work with the Swift package registry, you need to use [swift](https://www.swi To register the package registry and provide credentials, execute: ```shell -swift package-registry set https://gitea.example.com/api/packages/{owner}/swift -login {username} -password {password} +swift package-registry set https://gitea.example.com/api/packages/{owner}/swift +swift package-registry login https://gitea.example.com/api/packages/{owner}/swift --username {username} --password {password} ``` | Placeholder | Description | diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go index 69f3505c28..af5c31f157 100644 --- a/models/unittest/testdb.go +++ b/models/unittest/testdb.go @@ -44,12 +44,12 @@ func fatalTestError(fmtStr string, args ...any) { } // InitSettings initializes config provider and load common settings for tests -func InitSettings(extraConfigs ...string) { +func InitSettings() { if setting.CustomConf == "" { setting.CustomConf = filepath.Join(setting.CustomPath, "conf/app-unittest-tmp.ini") _ = os.Remove(setting.CustomConf) } - setting.InitCfgProvider(setting.CustomConf, strings.Join(extraConfigs, "\n")) + setting.InitCfgProvider(setting.CustomConf) setting.LoadCommonSettings() if err := setting.PrepareAppDataPath(); err != nil { diff --git a/modules/git/repo.go b/modules/git/repo.go index db99d285a8..60078f3273 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -271,7 +271,7 @@ func GetLatestCommitTime(ctx context.Context, repoPath string) (time.Time, error return time.Time{}, err } commitTime := strings.TrimSpace(stdout) - return time.Parse(GitTimeLayout, commitTime) + return time.Parse("Mon Jan _2 15:04:05 2006 -0700", commitTime) } // DivergeObject represents commit count diverging commits diff --git a/modules/git/repo_tag.go b/modules/git/repo_tag.go index af9a75b29c..ae5dbd171f 100644 --- a/modules/git/repo_tag.go +++ b/modules/git/repo_tag.go @@ -183,11 +183,7 @@ func parseTagRef(objectFormat ObjectFormat, ref map[string]string) (tag *Tag, er } } - tag.Tagger, err = newSignatureFromCommitline([]byte(ref["creator"])) - if err != nil { - return nil, fmt.Errorf("parse tagger: %w", err) - } - + tag.Tagger = parseSignatureFromCommitLine(ref["creator"]) tag.Message = ref["contents"] // strip PGP signature if present in contents field pgpStart := strings.Index(tag.Message, beginpgp) diff --git a/modules/git/repo_tag_test.go b/modules/git/repo_tag_test.go index da7b1455a8..9816e311a8 100644 --- a/modules/git/repo_tag_test.go +++ b/modules/git/repo_tag_test.go @@ -227,7 +227,7 @@ func TestRepository_parseTagRef(t *testing.T) { ID: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"), Object: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"), Type: "commit", - Tagger: parseAuthorLine(t, "Foo Bar 1565789218 +0300"), + Tagger: parseSignatureFromCommitLine("Foo Bar 1565789218 +0300"), Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n", Signature: nil, }, @@ -256,7 +256,7 @@ func TestRepository_parseTagRef(t *testing.T) { ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"), Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"), Type: "tag", - Tagger: parseAuthorLine(t, "Foo Bar 1565789218 +0300"), + Tagger: parseSignatureFromCommitLine("Foo Bar 1565789218 +0300"), Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n", Signature: nil, }, @@ -314,7 +314,7 @@ qbHDASXl ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"), Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"), Type: "tag", - Tagger: parseAuthorLine(t, "Foo Bar 1565789218 +0300"), + Tagger: parseSignatureFromCommitLine("Foo Bar 1565789218 +0300"), Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md", Signature: &CommitGPGSignature{ Signature: `-----BEGIN PGP SIGNATURE----- @@ -363,14 +363,3 @@ Add changelog of v1.9.1 (#7859) }) } } - -func parseAuthorLine(t *testing.T, committer string) *Signature { - t.Helper() - - sig, err := newSignatureFromCommitline([]byte(committer)) - if err != nil { - t.Fatalf("parse author line '%s': %v", committer, err) - } - - return sig -} diff --git a/modules/git/signature.go b/modules/git/signature.go index b5b17f23b0..f50a097758 100644 --- a/modules/git/signature.go +++ b/modules/git/signature.go @@ -4,7 +4,46 @@ package git -const ( - // GitTimeLayout is the (default) time layout used by git. - GitTimeLayout = "Mon Jan _2 15:04:05 2006 -0700" +import ( + "strconv" + "strings" + "time" + + "code.gitea.io/gitea/modules/log" ) + +// Helper to get a signature from the commit line, which looks like: +// +// full name 1378823654 +0200 +// +// Haven't found the official reference for the standard format yet. +// This function never fails, if the "line" can't be parsed, it returns a default Signature with "zero" time. +func parseSignatureFromCommitLine(line string) *Signature { + sig := &Signature{} + s1, sx, ok1 := strings.Cut(line, " <") + s2, s3, ok2 := strings.Cut(sx, "> ") + if !ok1 || !ok2 { + sig.Name = line + return sig + } + sig.Name, sig.Email = s1, s2 + + if strings.Count(s3, " ") == 1 { + ts, tz, _ := strings.Cut(s3, " ") + seconds, _ := strconv.ParseInt(ts, 10, 64) + if tzTime, err := time.Parse("-0700", tz); err == nil { + sig.When = time.Unix(seconds, 0).In(tzTime.Location()) + } + } else { + // the old gitea code tried to parse the date in a few different formats, but it's not clear why. + // according to public document, only the standard format "timestamp timezone" could be found, so drop other formats. + log.Error("suspicious commit line format: %q", line) + for _, fmt := range []string{ /*"Mon Jan _2 15:04:05 2006 -0700"*/ } { + if t, err := time.Parse(fmt, s3); err == nil { + sig.When = t + break + } + } + } + return sig +} diff --git a/modules/git/signature_gogit.go b/modules/git/signature_gogit.go index c984ad6e20..1fc6aabceb 100644 --- a/modules/git/signature_gogit.go +++ b/modules/git/signature_gogit.go @@ -7,52 +7,8 @@ package git import ( - "bytes" - "strconv" - "strings" - "time" - "github.com/go-git/go-git/v5/plumbing/object" ) // Signature represents the Author or Committer information. type Signature = object.Signature - -// Helper to get a signature from the commit line, which looks like these: -// -// author Patrick Gundlach 1378823654 +0200 -// author Patrick Gundlach Thu, 07 Apr 2005 22:13:13 +0200 -// -// but without the "author " at the beginning (this method should) -// be used for author and committer. -// -// FIXME: include timezone for timestamp! -func newSignatureFromCommitline(line []byte) (_ *Signature, err error) { - sig := new(Signature) - emailStart := bytes.IndexByte(line, '<') - if emailStart > 0 { // Empty name has already occurred, even if it shouldn't - sig.Name = strings.TrimSpace(string(line[:emailStart-1])) - } - emailEnd := bytes.IndexByte(line, '>') - sig.Email = string(line[emailStart+1 : emailEnd]) - - // Check date format. - if len(line) > emailEnd+2 { - firstChar := line[emailEnd+2] - if firstChar >= 48 && firstChar <= 57 { - timestop := bytes.IndexByte(line[emailEnd+2:], ' ') - timestring := string(line[emailEnd+2 : emailEnd+2+timestop]) - seconds, _ := strconv.ParseInt(timestring, 10, 64) - sig.When = time.Unix(seconds, 0) - } else { - sig.When, err = time.Parse(GitTimeLayout, string(line[emailEnd+2:])) - if err != nil { - return nil, err - } - } - } else { - // Fall back to unix 0 time - sig.When = time.Unix(0, 0) - } - return sig, nil -} diff --git a/modules/git/signature_nogogit.go b/modules/git/signature_nogogit.go index 25277f99d5..0d19c0abdc 100644 --- a/modules/git/signature_nogogit.go +++ b/modules/git/signature_nogogit.go @@ -7,21 +7,17 @@ package git import ( - "bytes" "fmt" - "strconv" - "strings" "time" + + "code.gitea.io/gitea/modules/util" ) -// Signature represents the Author or Committer information. +// Signature represents the Author, Committer or Tagger information. type Signature struct { - // Name represents a person name. It is an arbitrary string. - Name string - // Email is an email, but it cannot be assumed to be well-formed. - Email string - // When is the timestamp of the signature. - When time.Time + Name string // the committer name, it can be anything + Email string // the committer email, it can be anything + When time.Time // the timestamp of the signature } func (s *Signature) String() string { @@ -30,71 +26,5 @@ func (s *Signature) String() string { // Decode decodes a byte array representing a signature to signature func (s *Signature) Decode(b []byte) { - sig, _ := newSignatureFromCommitline(b) - s.Email = sig.Email - s.Name = sig.Name - s.When = sig.When -} - -// Helper to get a signature from the commit line, which looks like these: -// -// author Patrick Gundlach 1378823654 +0200 -// author Patrick Gundlach Thu, 07 Apr 2005 22:13:13 +0200 -// -// but without the "author " at the beginning (this method should) -// be used for author and committer. -// FIXME: there are a lot of "return sig, err" (but the err is also nil), that's the old behavior, to avoid breaking -func newSignatureFromCommitline(line []byte) (sig *Signature, err error) { - sig = new(Signature) - emailStart := bytes.LastIndexByte(line, '<') - emailEnd := bytes.LastIndexByte(line, '>') - if emailStart == -1 || emailEnd == -1 || emailEnd < emailStart { - return sig, err - } - - if emailStart > 0 { // Empty name has already occurred, even if it shouldn't - sig.Name = strings.TrimSpace(string(line[:emailStart-1])) - } - sig.Email = string(line[emailStart+1 : emailEnd]) - - hasTime := emailEnd+2 < len(line) - if !hasTime { - return sig, err - } - - // Check date format. - firstChar := line[emailEnd+2] - if firstChar >= 48 && firstChar <= 57 { - idx := bytes.IndexByte(line[emailEnd+2:], ' ') - if idx < 0 { - return sig, err - } - - timestring := string(line[emailEnd+2 : emailEnd+2+idx]) - seconds, _ := strconv.ParseInt(timestring, 10, 64) - sig.When = time.Unix(seconds, 0) - - idx += emailEnd + 3 - if idx >= len(line) || idx+5 > len(line) { - return sig, err - } - - timezone := string(line[idx : idx+5]) - tzhours, err1 := strconv.ParseInt(timezone[0:3], 10, 64) - tzmins, err2 := strconv.ParseInt(timezone[3:], 10, 64) - if err1 != nil || err2 != nil { - return sig, err - } - if tzhours < 0 { - tzmins *= -1 - } - tz := time.FixedZone("", int(tzhours*60*60+tzmins*60)) - sig.When = sig.When.In(tz) - } else { - sig.When, err = time.Parse(GitTimeLayout, string(line[emailEnd+2:])) - if err != nil { - return sig, err - } - } - return sig, err + *s = *parseSignatureFromCommitLine(util.UnsafeBytesToString(b)) } diff --git a/modules/git/signature_test.go b/modules/git/signature_test.go new file mode 100644 index 0000000000..92681feea9 --- /dev/null +++ b/modules/git/signature_test.go @@ -0,0 +1,47 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package git + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestParseSignatureFromCommitLine(t *testing.T) { + tests := []struct { + line string + want *Signature + }{ + { + line: "a b 12345 +0100", + want: &Signature{ + Name: "a b", + Email: "c@d.com", + When: time.Unix(12345, 0).In(time.FixedZone("", 3600)), + }, + }, + { + line: "bad line", + want: &Signature{Name: "bad line"}, + }, + { + line: "bad < line", + want: &Signature{Name: "bad < line"}, + }, + { + line: "bad > line", + want: &Signature{Name: "bad > line"}, + }, + { + line: "bad-line ", + want: &Signature{Name: "bad-line "}, + }, + } + for _, test := range tests { + got := parseSignatureFromCommitLine(test.line) + assert.EqualValues(t, test.want, got) + } +} diff --git a/modules/git/tag.go b/modules/git/tag.go index 01a8d6f6a5..94e5cd7c63 100644 --- a/modules/git/tag.go +++ b/modules/git/tag.go @@ -7,6 +7,8 @@ import ( "bytes" "sort" "strings" + + "code.gitea.io/gitea/modules/util" ) const ( @@ -59,11 +61,7 @@ l: // A commit can have one or more parents tag.Type = string(line[spacepos+1:]) case "tagger": - sig, err := newSignatureFromCommitline(line[spacepos+1:]) - if err != nil { - return nil, err - } - tag.Tagger = sig + tag.Tagger = parseSignatureFromCommitLine(util.UnsafeBytesToString(line[spacepos+1:])) } nextline += eol + 1 case eol == 0: diff --git a/modules/indexer/code/elasticsearch/elasticsearch.go b/modules/indexer/code/elasticsearch/elasticsearch.go index 2fadbfeb06..0f70f13485 100644 --- a/modules/indexer/code/elasticsearch/elasticsearch.go +++ b/modules/indexer/code/elasticsearch/elasticsearch.go @@ -180,11 +180,17 @@ func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha st } if len(reqs) > 0 { - _, err := b.inner.Client.Bulk(). - Index(b.inner.VersionedIndexName()). - Add(reqs...). - Do(ctx) - return err + esBatchSize := 50 + + for i := 0; i < len(reqs); i += esBatchSize { + _, err := b.inner.Client.Bulk(). + Index(b.inner.VersionedIndexName()). + Add(reqs[i:min(i+esBatchSize, len(reqs))]...). + Do(ctx) + if err != nil { + return err + } + } } return nil } diff --git a/modules/setting/config_provider.go b/modules/setting/config_provider.go index e1c25ed9c7..12cf36aa59 100644 --- a/modules/setting/config_provider.go +++ b/modules/setting/config_provider.go @@ -197,7 +197,7 @@ func NewConfigProviderFromData(configContent string) (ConfigProvider, error) { // NewConfigProviderFromFile load configuration from file. // NOTE: do not print any log except error. -func NewConfigProviderFromFile(file string, extraConfigs ...string) (ConfigProvider, error) { +func NewConfigProviderFromFile(file string) (ConfigProvider, error) { cfg := ini.Empty(configProviderLoadOptions()) loadedFromEmpty := true @@ -214,12 +214,6 @@ func NewConfigProviderFromFile(file string, extraConfigs ...string) (ConfigProvi } } - for _, s := range extraConfigs { - if err := cfg.Append([]byte(s)); err != nil { - return nil, fmt.Errorf("unable to append more config: %v", err) - } - } - cfg.NameMapper = ini.SnackCase return &iniConfigProvider{ file: file, diff --git a/modules/setting/setting.go b/modules/setting/setting.go index c0d8d0ee23..87e7b08c6e 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -92,9 +92,9 @@ func PrepareAppDataPath() error { return nil } -func InitCfgProvider(file string, extraConfigs ...string) { +func InitCfgProvider(file string) { var err error - if CfgProvider, err = NewConfigProviderFromFile(file, extraConfigs...); err != nil { + if CfgProvider, err = NewConfigProviderFromFile(file); err != nil { log.Fatal("Unable to init config provider from %q: %v", file, err) } CfgProvider.DisableSaving() // do not allow saving the CfgProvider into file, it will be polluted by the "MustXxx" calls diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index aab8ebb3fc..74498be9a4 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -1030,10 +1030,10 @@ reactions_more=再加载 %d unit_disabled=站点管理员已禁用此仓库单元。 language_other=其它 adopt_search=输入用户名以搜索未被收录的仓库... (留空以查找全部) -adopt_preexisting_label=收录文件 -adopt_preexisting=收录已存在的文件 +adopt_preexisting_label=收录仓库 +adopt_preexisting=收录已存在的仓库 adopt_preexisting_content=从 %s 创建仓库 -adopt_preexisting_success=从 %s 收录文件并创建仓库成功 +adopt_preexisting_success=从 %s 收录仓库成功 delete_preexisting_label=刪除 delete_preexisting=删除已存在的文件 delete_preexisting_content=删除 %s 中的文件 diff --git a/package-lock.json b/package-lock.json index 3572749b89..6918dc64b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,6 @@ "jquery": "3.7.1", "katex": "0.16.9", "license-checker-webpack-plugin": "0.2.1", - "lightningcss-loader": "2.1.0", "mermaid": "10.7.0", "mini-css-extract-plugin": "2.8.0", "minimatch": "9.0.3", @@ -2261,13 +2260,13 @@ "dev": true }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", - "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2278,9 +2277,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", - "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2291,13 +2290,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", - "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2319,17 +2318,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz", - "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.20.0", - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", "semver": "^7.5.4" }, "engines": { @@ -2344,12 +2343,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", - "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2449,9 +2448,9 @@ } }, "node_modules/@vitest/snapshot/node_modules/magic-string": { - "version": "0.30.6", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.6.tgz", - "integrity": "sha512-n62qCLbPjNjyo+owKtveQxZFZTBm+Ms6YoGD23Wew6Vw337PElFNifQpknPruVRQV57kVShPnLGo9vWxVhpPvA==", + "version": "0.30.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", + "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" @@ -4372,17 +4371,6 @@ "node": ">=6" } }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/diff": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", @@ -6993,224 +6981,6 @@ "node": ">=8" } }, - "node_modules/lightningcss": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.23.0.tgz", - "integrity": "sha512-SEArWKMHhqn/0QzOtclIwH5pXIYQOUEkF8DgICd/105O+GCgd7jxjNod/QPnBCSWvpRHQBGVz5fQ9uScby03zA==", - "dependencies": { - "detect-libc": "^1.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-darwin-arm64": "1.23.0", - "lightningcss-darwin-x64": "1.23.0", - "lightningcss-freebsd-x64": "1.23.0", - "lightningcss-linux-arm-gnueabihf": "1.23.0", - "lightningcss-linux-arm64-gnu": "1.23.0", - "lightningcss-linux-arm64-musl": "1.23.0", - "lightningcss-linux-x64-gnu": "1.23.0", - "lightningcss-linux-x64-musl": "1.23.0", - "lightningcss-win32-x64-msvc": "1.23.0" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.23.0.tgz", - "integrity": "sha512-kl4Pk3Q2lnE6AJ7Qaij47KNEfY2/UXRZBT/zqGA24B8qwkgllr/j7rclKOf1axcslNXvvUdztjo4Xqh39Yq1aA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.23.0.tgz", - "integrity": "sha512-KeRFCNoYfDdcolcFXvokVw+PXCapd2yHS1Diko1z1BhRz/nQuD5XyZmxjWdhmhN/zj5sH8YvWsp0/lPLVzqKpg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.23.0.tgz", - "integrity": "sha512-xhnhf0bWPuZxcqknvMDRFFo2TInrmQRWZGB0f6YoAsZX8Y+epfjHeeOIGCfAmgF0DgZxHwYc8mIR5tQU9/+ROA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.23.0.tgz", - "integrity": "sha512-fBamf/bULvmWft9uuX+bZske236pUZEoUlaHNBjnueaCTJ/xd8eXgb0cEc7S5o0Nn6kxlauMBnqJpF70Bgq3zg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.23.0.tgz", - "integrity": "sha512-RS7sY77yVLOmZD6xW2uEHByYHhQi5JYWmgVumYY85BfNoVI3DupXSlzbw+b45A9NnVKq45+oXkiN6ouMMtTwfg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.23.0.tgz", - "integrity": "sha512-cU00LGb6GUXCwof6ACgSMKo3q7XYbsyTj0WsKHLi1nw7pV0NCq8nFTn6ZRBYLoKiV8t+jWl0Hv8KkgymmK5L5g==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.23.0.tgz", - "integrity": "sha512-q4jdx5+5NfB0/qMbXbOmuC6oo7caPnFghJbIAV90cXZqgV8Am3miZhC4p+sQVdacqxfd+3nrle4C8icR3p1AYw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.23.0.tgz", - "integrity": "sha512-G9Ri3qpmF4qef2CV/80dADHKXRAQeQXpQTLx7AiQrBYQHqBjB75oxqj06FCIe5g4hNCqLPnM9fsO4CyiT1sFSQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-loader": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lightningcss-loader/-/lightningcss-loader-2.1.0.tgz", - "integrity": "sha512-mB+M/lvs/GdXT4yc8ZiNgLUAbYpPI9grDyC3ybz/Zo6s4GZv53iZnLTnkJT/Qm3Sh89dbFUm+omoHFXCfZtcXw==", - "dependencies": { - "browserslist": "^4.21.4", - "lightningcss": "^1.16.0", - "webpack-sources": "^3.2.3" - }, - "peerDependencies": { - "webpack": ">=5" - } - }, - "node_modules/lightningcss-loader/node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.23.0.tgz", - "integrity": "sha512-1rcBDJLU+obPPJM6qR5fgBUiCdZwZLafZM5f9kwjFLkb/UBNIzmae39uCSmh71nzPCTXZqHbvwu23OWnWEz+eg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -10620,12 +10390,12 @@ "integrity": "sha512-B5CXihaVzXw+1UHhNFyAwUTMDk1EfoLP5Tj1VhD9yybZ1I8DZJEv8tZ1l0RJo0t0tk9ZhR8eG5tEsaCvRigmdQ==" }, "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", "dev": true, "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" @@ -10769,9 +10539,9 @@ "dev": true }, "node_modules/ufo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", - "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", + "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==", "dev": true }, "node_modules/uint8-to-base64": { @@ -11149,9 +10919,9 @@ } }, "node_modules/vitest/node_modules/magic-string": { - "version": "0.30.6", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.6.tgz", - "integrity": "sha512-n62qCLbPjNjyo+owKtveQxZFZTBm+Ms6YoGD23Wew6Vw337PElFNifQpknPruVRQV57kVShPnLGo9vWxVhpPvA==", + "version": "0.30.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", + "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" diff --git a/package.json b/package.json index 3defca1a3d..ef1fcca545 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "jquery": "3.7.1", "katex": "0.16.9", "license-checker-webpack-plugin": "0.2.1", - "lightningcss-loader": "2.1.0", "mermaid": "10.7.0", "mini-css-extract-plugin": "2.8.0", "minimatch": "9.0.3", @@ -86,8 +85,6 @@ "vitest": "1.2.2" }, "browserslist": [ - "defaults", - "not ie > 0", - "not ie_mob > 0" + "defaults" ] } diff --git a/routers/api/packages/swift/swift.go b/routers/api/packages/swift/swift.go index 427e262d06..6ad289e51e 100644 --- a/routers/api/packages/swift/swift.go +++ b/routers/api/packages/swift/swift.go @@ -157,7 +157,7 @@ func EnumeratePackageVersions(ctx *context.Context) { } type Resource struct { - Name string `json:"id"` + Name string `json:"name"` Type string `json:"type"` Checksum string `json:"checksum"` } diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go index fe528a483b..5f6a1ec36a 100644 --- a/routers/web/repo/actions/actions.go +++ b/routers/web/repo/actions/actions.go @@ -61,17 +61,17 @@ func List(ctx *context.Context) { var workflows []Workflow if empty, err := ctx.Repo.GitRepo.IsEmpty(); err != nil { - ctx.Error(http.StatusInternalServerError, err.Error()) + ctx.ServerError("IsEmpty", err) return } else if !empty { commit, err := ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch) if err != nil { - ctx.Error(http.StatusInternalServerError, err.Error()) + ctx.ServerError("GetBranchCommit", err) return } entries, err := actions.ListWorkflows(commit) if err != nil { - ctx.Error(http.StatusInternalServerError, err.Error()) + ctx.ServerError("ListWorkflows", err) return } @@ -95,7 +95,7 @@ func List(ctx *context.Context) { workflow := Workflow{Entry: *entry} content, err := actions.GetContentFromEntry(entry) if err != nil { - ctx.Error(http.StatusInternalServerError, err.Error()) + ctx.ServerError("GetContentFromEntry", err) return } wf, err := model.ReadWorkflow(bytes.NewReader(content)) @@ -172,7 +172,7 @@ func List(ctx *context.Context) { runs, total, err := db.FindAndCount[actions_model.ActionRun](ctx, opts) if err != nil { - ctx.Error(http.StatusInternalServerError, err.Error()) + ctx.ServerError("FindAndCount", err) return } @@ -181,7 +181,7 @@ func List(ctx *context.Context) { } if err := actions_model.RunList(runs).LoadTriggerUser(ctx); err != nil { - ctx.Error(http.StatusInternalServerError, err.Error()) + ctx.ServerError("LoadTriggerUser", err) return } @@ -189,7 +189,7 @@ func List(ctx *context.Context) { actors, err := actions_model.GetActors(ctx, ctx.Repo.Repository.ID) if err != nil { - ctx.Error(http.StatusInternalServerError, err.Error()) + ctx.ServerError("GetActors", err) return } ctx.Data["Actors"] = repo.MakeSelfOnTop(ctx.Doer, actors) diff --git a/services/mailer/mail_release.go b/services/mailer/mail_release.go index 801c2476c2..5e8e5b6af3 100644 --- a/services/mailer/mail_release.go +++ b/services/mailer/mail_release.go @@ -74,6 +74,7 @@ func mailNewRelease(ctx context.Context, lang string, tos []string, rel *repo_mo "Release": rel, "Subject": subject, "Language": locale.Language(), + "Link": rel.HTMLURL(), } var mailBody bytes.Buffer diff --git a/templates/repo/branch_dropdown.tmpl b/templates/repo/branch_dropdown.tmpl index bee5363296..8a5cdc7cc7 100644 --- a/templates/repo/branch_dropdown.tmpl +++ b/templates/repo/branch_dropdown.tmpl @@ -1,7 +1,7 @@ {{/* Attributes: * root * ContainerClasses -* (TODO: search "branch_dropdown" in the template direcotry) +* (TODO: search "branch_dropdown" in the template directory) */}} {{$defaultSelectedRefName := $.root.BranchName}} {{if and .root.IsViewTag (not .noTag)}} diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index 53c20a68bb..a8e0aaf430 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -371,7 +371,7 @@
{{if .OriginalAuthor}} {{else}} - {{/* Some timeline avatars need a offset to correctly allign with their speech + {{/* Some timeline avatars need a offset to correctly align with their speech bubble. The condition depends on review type and for positive reviews whether there is a comment element or not */}} diff --git a/templates/repo/release/list.tmpl b/templates/repo/release/list.tmpl index ccea14c4e2..fb2fce2950 100644 --- a/templates/repo/release/list.tmpl +++ b/templates/repo/release/list.tmpl @@ -8,8 +8,8 @@ {{range $idx, $release := .Releases}}
  • - {{svg "octicon-tag" 16 "gt-mr-2"}}{{.TagName}} - {{if .Sha1}} + {{svg "octicon-tag" 16 "gt-mr-2"}}{{.TagName}} + {{if and .Sha1 ($.Permission.CanRead $.UnitTypeCode)}} {{svg "octicon-git-commit" 16 "gt-mr-2"}}{{ShortSha .Sha1}} {{template "repo/branch_dropdown" dict "root" $ "release" .}} {{end}} @@ -22,36 +22,18 @@ {{ctx.Locale.Tr "repo.release.draft"}} {{else if .IsPrerelease}} {{ctx.Locale.Tr "repo.release.prerelease"}} - {{else if not .IsTag}} + {{else}} {{ctx.Locale.Tr "repo.release.stable"}} {{end}}
    - {{if and $.CanCreateRelease (not .IsTag)}} + {{if $.CanCreateRelease}} {{svg "octicon-pencil"}} {{end}}
    - {{if .IsTag}} -

    - {{if gt .Publisher.ID 0}} - - {{ctx.AvatarUtils.Avatar .Publisher 20 "gt-mr-2"}} - {{.Publisher.Name}} - - - {{ctx.Locale.Tr "repo.tagged_this"}} - - {{if .CreatedUnix}} - {{TimeSinceUnix .CreatedUnix ctx.Locale}} - {{end}} - | - {{end}} - {{ctx.Locale.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}} {{ctx.Locale.Tr "repo.tag.ahead.target" .TargetBehind}} -

    - {{else}}

    {{if .OriginalAuthor}} @@ -69,11 +51,10 @@ {{if .CreatedUnix}} {{TimeSinceUnix .CreatedUnix ctx.Locale}} {{end}} - {{if not .IsDraft}} + {{if and (not .IsDraft) ($.Permission.CanRead $.UnitTypeCode)}} | {{ctx.Locale.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}} {{ctx.Locale.Tr "repo.release.ahead.target" .TargetBehind}} {{end}}

    - {{end}}
    {{Str2html .Note}}
    diff --git a/vitest.config.js b/vitest.config.js index 9a6cb4e560..be6c0eadfa 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -5,7 +5,7 @@ import {stringPlugin} from 'vite-string-plugin'; export default defineConfig({ test: { include: ['web_src/**/*.test.js'], - setupFiles: ['./web_src/js/test/setup.js'], + setupFiles: ['web_src/js/vitest.setup.js'], environment: 'jsdom', testTimeout: 20000, open: false, diff --git a/web_src/js/modules/dirauto.js b/web_src/js/modules/dirauto.js index c917bf8cff..cd90f8155b 100644 --- a/web_src/js/modules/dirauto.js +++ b/web_src/js/modules/dirauto.js @@ -1,5 +1,6 @@ -// for performance considerations, it only uses performant syntax +import {isDocumentFragmentOrElementNode} from '../utils/dom.js'; +// for performance considerations, it only uses performant syntax function attachDirAuto(el) { if (el.type !== 'hidden' && el.type !== 'checkbox' && @@ -18,7 +19,7 @@ export function initDirAuto() { const len = mutation.addedNodes.length; for (let i = 0; i < len; i++) { const addedNode = mutation.addedNodes[i]; - if (addedNode.nodeType !== Node.ELEMENT_NODE && addedNode.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) continue; + if (!isDocumentFragmentOrElementNode(addedNode)) continue; if (addedNode.nodeName === 'INPUT' || addedNode.nodeName === 'TEXTAREA') attachDirAuto(addedNode); const children = addedNode.querySelectorAll('input, textarea'); const len = children.length; diff --git a/web_src/js/modules/tippy.js b/web_src/js/modules/tippy.js index 7f8423e319..27f371fd88 100644 --- a/web_src/js/modules/tippy.js +++ b/web_src/js/modules/tippy.js @@ -1,4 +1,5 @@ import tippy, {followCursor} from 'tippy.js'; +import {isDocumentFragmentOrElementNode} from '../utils/dom.js'; const visibleInstances = new Set(); @@ -136,8 +137,6 @@ function attachChildrenLazyTooltip(target) { } } -const elementNodeTypes = new Set([Node.ELEMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE]); - export function initGlobalTooltips() { // use MutationObserver to detect new "data-tooltip-content" elements added to the DOM, or attributes changed const observerConnect = (observer) => observer.observe(document, { @@ -152,11 +151,10 @@ export function initGlobalTooltips() { if (mutation.type === 'childList') { // mainly for Vue components and AJAX rendered elements for (const el of mutation.addedNodes) { - if (elementNodeTypes.has(el.nodeType)) { - attachChildrenLazyTooltip(el); - if (el.hasAttribute('data-tooltip-content')) { - attachLazyTooltip(el); - } + if (!isDocumentFragmentOrElementNode(el)) continue; + attachChildrenLazyTooltip(el); + if (el.hasAttribute('data-tooltip-content')) { + attachLazyTooltip(el); } } } else if (mutation.type === 'attributes') { diff --git a/web_src/js/utils/dom.js b/web_src/js/utils/dom.js index 64a6a5affc..4dc55a518a 100644 --- a/web_src/js/utils/dom.js +++ b/web_src/js/utils/dom.js @@ -59,6 +59,17 @@ export function onDomReady(cb) { } } +// checks whether an element is owned by the current document, and whether it is a document fragment or element node +// if it is, it means it is a "normal" element managed by us, which can be modified safely. +export function isDocumentFragmentOrElementNode(el) { + try { + return el.ownerDocument === document && el.nodeType === Node.ELEMENT_NODE || el.nodeType === Node.DOCUMENT_FRAGMENT_NODE; + } catch { + // in case the el is not in the same origin, then the access to nodeType would fail + return false; + } +} + // autosize a textarea to fit content. Based on // https://github.com/github/textarea-autosize // --------------------------------------------------------------------- diff --git a/web_src/js/test/setup.js b/web_src/js/vitest.setup.js similarity index 100% rename from web_src/js/test/setup.js rename to web_src/js/vitest.setup.js diff --git a/web_src/js/webcomponents/GiteaOriginUrl.js b/web_src/js/webcomponents/GiteaOriginUrl.js index fca736064c..5d71d95c60 100644 --- a/web_src/js/webcomponents/GiteaOriginUrl.js +++ b/web_src/js/webcomponents/GiteaOriginUrl.js @@ -1,17 +1,21 @@ // Convert an absolute or relative URL to an absolute URL with the current origin +export function toOriginUrl(urlStr) { + try { + // only process absolute HTTP/HTTPS URL or relative URLs ('/xxx' or '//host/xxx') + if (urlStr.startsWith('http://') || urlStr.startsWith('https://') || urlStr.startsWith('/')) { + const {origin, protocol, hostname, port} = window.location; + const url = new URL(urlStr, origin); + url.protocol = protocol; + url.hostname = hostname; + url.port = port || (protocol === 'https:' ? '443' : '80'); + return url.toString(); + } + } catch {} + return urlStr; +} + window.customElements.define('gitea-origin-url', class extends HTMLElement { connectedCallback() { - const urlStr = this.getAttribute('data-url'); - try { - // only process absolute HTTP/HTTPS URL or relative URLs ('/xxx' or '//host/xxx') - if (urlStr.startsWith('http://') || urlStr.startsWith('https://') || urlStr.startsWith('/')) { - const url = new URL(urlStr, window.origin); - url.protocol = window.location.protocol; - url.host = window.location.host; - this.textContent = url.toString(); - return; - } - } catch {} - this.textContent = urlStr; + this.textContent = toOriginUrl(this.getAttribute('data-url')); } }); diff --git a/web_src/js/webcomponents/GiteaOriginUrl.test.js b/web_src/js/webcomponents/GiteaOriginUrl.test.js new file mode 100644 index 0000000000..f0629842b8 --- /dev/null +++ b/web_src/js/webcomponents/GiteaOriginUrl.test.js @@ -0,0 +1,17 @@ +import {toOriginUrl} from './GiteaOriginUrl.js'; + +test('toOriginUrl', () => { + const oldLocation = window.location; + for (const origin of ['https://example.com', 'https://example.com:3000']) { + window.location = new URL(`${origin}/`); + expect(toOriginUrl('/')).toEqual(`${origin}/`); + expect(toOriginUrl('/org/repo.git')).toEqual(`${origin}/org/repo.git`); + expect(toOriginUrl('https://another.com')).toEqual(`${origin}/`); + expect(toOriginUrl('https://another.com/')).toEqual(`${origin}/`); + expect(toOriginUrl('https://another.com/org/repo.git')).toEqual(`${origin}/org/repo.git`); + expect(toOriginUrl('https://another.com:4000')).toEqual(`${origin}/`); + expect(toOriginUrl('https://another.com:4000/')).toEqual(`${origin}/`); + expect(toOriginUrl('https://another.com:4000/org/repo.git')).toEqual(`${origin}/org/repo.git`); + } + window.location = oldLocation; +}); diff --git a/webpack.config.js b/webpack.config.js index 0071c01834..3779e860d9 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -55,12 +55,6 @@ const filterCssImport = (url, ...args) => { return true; }; -// in case lightningcss fails to load, fall back to esbuild for css minify -let LightningCssMinifyPlugin; -try { - ({LightningCssMinifyPlugin} = await import('lightningcss-loader')); -} catch {} - /** @type {import("webpack").Configuration} */ export default { mode: isProduction ? 'production' : 'development', @@ -110,12 +104,9 @@ export default { new EsbuildPlugin({ target: 'es2020', minify: true, - css: !LightningCssMinifyPlugin, + css: true, legalComments: 'none', }), - LightningCssMinifyPlugin && new LightningCssMinifyPlugin({ - sourceMap: sourceMaps === 'true', - }), ], splitChunks: { chunks: 'async',