mirror of https://github.com/go-gitea/gitea.git
Compare commits
59 Commits
08cd2649f4
...
9fa5b73531
| Author | SHA1 | Date |
|---|---|---|
|
|
9fa5b73531 | |
|
|
29b28002aa | |
|
|
618e2d8106 | |
|
|
485d8f1121 | |
|
|
181db69e0c | |
|
|
a46b16f10f | |
|
|
1748045285 | |
|
|
f114c388ff | |
|
|
94c6d46faa | |
|
|
7436c6297d | |
|
|
ddd1e6ca83 | |
|
|
0548c10293 | |
|
|
7de114a332 | |
|
|
4fc626daa1 | |
|
|
81adb01713 | |
|
|
0990eb44ce | |
|
|
40dec17b5c | |
|
|
90eb831418 | |
|
|
1c28c470f8 | |
|
|
e0f3b30895 | |
|
|
719b151058 | |
|
|
4f32d32812 | |
|
|
cda90eca31 | |
|
|
d462ce149d | |
|
|
b8c9a0c323 | |
|
|
7346ae7cd4 | |
|
|
0ea958dc58 | |
|
|
67083437cd | |
|
|
b18c047d62 | |
|
|
8efc4ca334 | |
|
|
46a1d52235 | |
|
|
a2ae7c69da | |
|
|
7954f25290 | |
|
|
416ff1fd31 | |
|
|
0e6c1224e5 | |
|
|
b38813878c | |
|
|
08c634b7b7 | |
|
|
dfea75371c | |
|
|
1f35435b81 | |
|
|
71e4740946 | |
|
|
ecc6685c20 | |
|
|
a14db5c5e3 | |
|
|
ee334886f3 | |
|
|
1376cf7481 | |
|
|
f214bb40a3 | |
|
|
224aa64cd9 | |
|
|
1e644e39f9 | |
|
|
037f72bdb3 | |
|
|
4cbb482554 | |
|
|
439ebe7031 | |
|
|
3a37d63d61 | |
|
|
24ce2058e8 | |
|
|
6b8b580218 | |
|
|
bbee652e29 | |
|
|
637070e07b | |
|
|
0d3e9956cd | |
|
|
28debdbe00 | |
|
|
dcc9206a59 | |
|
|
0395d5c9f5 |
|
|
@ -4,10 +4,10 @@
|
|||
"features": {
|
||||
// installs nodejs into container
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "20"
|
||||
"version": "lts"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/git-lfs:1.2.2": {},
|
||||
"ghcr.io/devcontainers-contrib/features/poetry:2": {},
|
||||
"ghcr.io/devcontainers-extra/features/poetry:2": {},
|
||||
"ghcr.io/devcontainers/features/python:1": {
|
||||
"version": "3.12"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -36,15 +36,6 @@ _testmain.go
|
|||
coverage.all
|
||||
cpu.out
|
||||
|
||||
/modules/migration/bindata.go
|
||||
/modules/migration/bindata.go.hash
|
||||
/modules/options/bindata.go
|
||||
/modules/options/bindata.go.hash
|
||||
/modules/public/bindata.go
|
||||
/modules/public/bindata.go.hash
|
||||
/modules/templates/bindata.go
|
||||
/modules/templates/bindata.go.hash
|
||||
|
||||
*.db
|
||||
*.log
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ jobs:
|
|||
python-version: "3.12"
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: pip install poetry
|
||||
|
|
@ -66,7 +66,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend
|
||||
|
|
@ -137,7 +137,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend
|
||||
|
|
@ -186,7 +186,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
check-latest: true
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend frontend deps-backend
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
check-latest: true
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend deps-backend
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ jobs:
|
|||
check-latest: true
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend deps-backend
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
check-latest: true
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend deps-backend
|
||||
|
|
|
|||
3
.ignore
3
.ignore
|
|
@ -1,9 +1,6 @@
|
|||
*.min.css
|
||||
*.min.js
|
||||
/assets/*.json
|
||||
/modules/options/bindata.go
|
||||
/modules/public/bindata.go
|
||||
/modules/templates/bindata.go
|
||||
/options/gitignore
|
||||
/options/license
|
||||
/public/assets
|
||||
|
|
|
|||
25
Makefile
25
Makefile
|
|
@ -36,7 +36,8 @@ XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
|||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1
|
||||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1
|
||||
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1
|
||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.17.1
|
||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.19.0
|
||||
GOPLS_MODERNIZE_PACKAGE ?= golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@v0.19.0
|
||||
|
||||
DOCKER_IMAGE ?= gitea/gitea
|
||||
DOCKER_TAG ?= latest
|
||||
|
|
@ -120,7 +121,7 @@ WEBPACK_CONFIGS := webpack.config.js tailwind.config.js
|
|||
WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
|
||||
WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts
|
||||
|
||||
BINDATA_DEST := modules/public/bindata.dat modules/options/bindata.dat modules/templates/bindata.dat
|
||||
BINDATA_DEST_WILDCARD := modules/migration/bindata.* modules/public/bindata.* modules/options/bindata.* modules/templates/bindata.*
|
||||
|
||||
GENERATED_GO_DEST := modules/charset/invisible_gen.go modules/charset/ambiguous_gen.go
|
||||
|
||||
|
|
@ -219,7 +220,7 @@ clean-all: clean ## delete backend, frontend and integration files
|
|||
|
||||
.PHONY: clean
|
||||
clean: ## delete backend and integration files
|
||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) \
|
||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST_WILDCARD) \
|
||||
integrations*.test \
|
||||
e2e*.test \
|
||||
tests/integration/gitea-integration-* \
|
||||
|
|
@ -230,7 +231,7 @@ clean: ## delete backend and integration files
|
|||
tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/
|
||||
|
||||
.PHONY: fmt
|
||||
fmt: ## format the Go code
|
||||
fmt: ## format the Go and template code
|
||||
@GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
|
||||
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
|
||||
@# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only
|
||||
|
|
@ -249,6 +250,19 @@ fmt-check: fmt
|
|||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: fix
|
||||
fix: ## apply automated fixes to Go code
|
||||
$(GO) run $(GOPLS_MODERNIZE_PACKAGE) -fix ./...
|
||||
|
||||
.PHONY: fix-check
|
||||
fix-check: fix
|
||||
@diff=$$(git diff --color=always $(GO_SOURCES)); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "Please run 'make fix' and commit the result:"; \
|
||||
printf "%s" "$${diff}"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: $(TAGS_EVIDENCE)
|
||||
$(TAGS_EVIDENCE):
|
||||
@mkdir -p $(MAKE_EVIDENCE_DIR)
|
||||
|
|
@ -288,7 +302,7 @@ checks: checks-frontend checks-backend ## run various consistency checks
|
|||
checks-frontend: lockfile-check svg-check ## check frontend files
|
||||
|
||||
.PHONY: checks-backend
|
||||
checks-backend: tidy-check swagger-check fmt-check swagger-validate security-check ## check backend files
|
||||
checks-backend: tidy-check swagger-check fmt-check fix-check swagger-validate security-check ## check backend files
|
||||
|
||||
.PHONY: lint
|
||||
lint: lint-frontend lint-backend lint-spell ## lint everything
|
||||
|
|
@ -809,6 +823,7 @@ deps-tools: ## install tool dependencies
|
|||
$(GO) install $(GOVULNCHECK_PACKAGE) & \
|
||||
$(GO) install $(ACTIONLINT_PACKAGE) & \
|
||||
$(GO) install $(GOPLS_PACKAGE) & \
|
||||
$(GO) install $(GOPLS_MODERNIZE_PACKAGE) & \
|
||||
wait
|
||||
|
||||
node_modules: package-lock.json
|
||||
|
|
|
|||
|
|
@ -39,12 +39,10 @@ func smtpCLIFlags() []cli.Flag {
|
|||
&cli.BoolFlag{
|
||||
Name: "force-smtps",
|
||||
Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-verify",
|
||||
Usage: "Skip TLS verify.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "helo-hostname",
|
||||
|
|
@ -54,7 +52,6 @@ func smtpCLIFlags() []cli.Flag {
|
|||
&cli.BoolFlag{
|
||||
Name: "disable-helo",
|
||||
Usage: "Disable SMTP helo.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "allowed-domains",
|
||||
|
|
@ -64,7 +61,6 @@ func smtpCLIFlags() []cli.Flag {
|
|||
&cli.BoolFlag{
|
||||
Name: "skip-local-2fa",
|
||||
Usage: "Skip 2FA to log on.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "active",
|
||||
|
|
|
|||
|
|
@ -60,10 +60,8 @@ func TestAddSMTP(t *testing.T) {
|
|||
Auth: "PLAIN",
|
||||
Host: "localhost",
|
||||
Port: 25,
|
||||
// ForceSMTPS: true,
|
||||
// SkipVerify: true,
|
||||
},
|
||||
TwoFactorPolicy: "skip",
|
||||
TwoFactorPolicy: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -73,12 +71,12 @@ func TestAddSMTP(t *testing.T) {
|
|||
"--host", "localhost",
|
||||
"--port", "25",
|
||||
"--auth-type", "LOGIN",
|
||||
"--force-smtps=false",
|
||||
"--skip-verify=false",
|
||||
"--force-smtps",
|
||||
"--skip-verify",
|
||||
"--helo-hostname", "example.com",
|
||||
"--disable-helo=false",
|
||||
"--disable-helo=true",
|
||||
"--allowed-domains", "example.com,example.org",
|
||||
"--skip-local-2fa=false",
|
||||
"--skip-local-2fa",
|
||||
"--active=false",
|
||||
},
|
||||
source: &auth_model.Source{
|
||||
|
|
@ -89,13 +87,13 @@ func TestAddSMTP(t *testing.T) {
|
|||
Auth: "LOGIN",
|
||||
Host: "localhost",
|
||||
Port: 25,
|
||||
ForceSMTPS: false,
|
||||
SkipVerify: false,
|
||||
ForceSMTPS: true,
|
||||
SkipVerify: true,
|
||||
HeloHostname: "example.com",
|
||||
DisableHelo: false,
|
||||
DisableHelo: true,
|
||||
AllowedDomains: "example.com,example.org",
|
||||
},
|
||||
TwoFactorPolicy: "",
|
||||
TwoFactorPolicy: "skip",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -157,13 +155,10 @@ func TestUpdateSMTP(t *testing.T) {
|
|||
Name: "old name",
|
||||
IsActive: true,
|
||||
Cfg: &smtp.Source{
|
||||
Auth: "PLAIN",
|
||||
Host: "old host",
|
||||
Port: 26,
|
||||
ForceSMTPS: true,
|
||||
SkipVerify: true,
|
||||
Auth: "PLAIN",
|
||||
Host: "old host",
|
||||
Port: 26,
|
||||
},
|
||||
TwoFactorPolicy: "",
|
||||
},
|
||||
args: []string{
|
||||
"--id", "1",
|
||||
|
|
@ -177,13 +172,10 @@ func TestUpdateSMTP(t *testing.T) {
|
|||
Name: "test",
|
||||
IsActive: true,
|
||||
Cfg: &smtp.Source{
|
||||
Auth: "PLAIN",
|
||||
Host: "localhost",
|
||||
Port: 25,
|
||||
ForceSMTPS: true,
|
||||
SkipVerify: true,
|
||||
Auth: "PLAIN",
|
||||
Host: "localhost",
|
||||
Port: 25,
|
||||
},
|
||||
TwoFactorPolicy: "skip",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -197,10 +189,7 @@ func TestUpdateSMTP(t *testing.T) {
|
|||
Auth: "PLAIN",
|
||||
Host: "old host",
|
||||
Port: 26,
|
||||
ForceSMTPS: true,
|
||||
SkipVerify: true,
|
||||
HeloHostname: "old.example.com",
|
||||
DisableHelo: false,
|
||||
AllowedDomains: "old.example.com",
|
||||
},
|
||||
TwoFactorPolicy: "",
|
||||
|
|
@ -211,12 +200,12 @@ func TestUpdateSMTP(t *testing.T) {
|
|||
"--host", "localhost",
|
||||
"--port", "25",
|
||||
"--auth-type", "LOGIN",
|
||||
"--force-smtps=false",
|
||||
"--skip-verify=false",
|
||||
"--force-smtps",
|
||||
"--skip-verify",
|
||||
"--helo-hostname", "example.com",
|
||||
"--disable-helo=true",
|
||||
"--disable-helo",
|
||||
"--allowed-domains", "example.com,example.org",
|
||||
"--skip-local-2fa=true",
|
||||
"--skip-local-2fa",
|
||||
"--active=false",
|
||||
},
|
||||
authSource: &auth_model.Source{
|
||||
|
|
@ -228,8 +217,8 @@ func TestUpdateSMTP(t *testing.T) {
|
|||
Auth: "LOGIN",
|
||||
Host: "localhost",
|
||||
Port: 25,
|
||||
ForceSMTPS: false,
|
||||
SkipVerify: false,
|
||||
ForceSMTPS: true,
|
||||
SkipVerify: true,
|
||||
HeloHostname: "example.com",
|
||||
DisableHelo: true,
|
||||
AllowedDomains: "example.com,example.org",
|
||||
|
|
@ -252,11 +241,8 @@ func TestUpdateSMTP(t *testing.T) {
|
|||
Name: "test",
|
||||
IsActive: true,
|
||||
Cfg: &smtp.Source{
|
||||
Auth: "PLAIN",
|
||||
SkipVerify: true,
|
||||
ForceSMTPS: true,
|
||||
Auth: "PLAIN",
|
||||
},
|
||||
TwoFactorPolicy: "skip",
|
||||
}, nil
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -156,8 +156,8 @@ func runCert(_ context.Context, c *cli.Command) error {
|
|||
BasicConstraintsValid: true,
|
||||
}
|
||||
|
||||
hosts := strings.Split(c.String("host"), ",")
|
||||
for _, h := range hosts {
|
||||
hosts := strings.SplitSeq(c.String("host"), ",")
|
||||
for h := range hosts {
|
||||
if ip := net.ParseIP(h); ip != nil {
|
||||
template.IPAddresses = append(template.IPAddresses, ip)
|
||||
} else {
|
||||
|
|
|
|||
10
cmd/cmd.go
10
cmd/cmd.go
|
|
@ -132,3 +132,13 @@ func PrepareConsoleLoggerLevel(defaultLevel log.Level) func(context.Context, *cl
|
|||
return ctx, nil
|
||||
}
|
||||
}
|
||||
|
||||
func isValidDefaultSubCommand(cmd *cli.Command) (string, bool) {
|
||||
// Dirty patch for urfave/cli's strange design.
|
||||
// "./gitea bad-cmd" should not start the web server.
|
||||
rootArgs := cmd.Root().Args().Slice()
|
||||
if len(rootArgs) != 0 && rootArgs[0] != cmd.Name {
|
||||
return rootArgs[0], false
|
||||
}
|
||||
return "", true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func TestDefaultCommand(t *testing.T) {
|
||||
test := func(t *testing.T, args []string, expectedRetName string, expectedRetValid bool) {
|
||||
called := false
|
||||
cmd := &cli.Command{
|
||||
DefaultCommand: "test",
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "test",
|
||||
Action: func(ctx context.Context, command *cli.Command) error {
|
||||
retName, retValid := isValidDefaultSubCommand(command)
|
||||
assert.Equal(t, expectedRetName, retName)
|
||||
assert.Equal(t, expectedRetValid, retValid)
|
||||
called = true
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.NoError(t, cmd.Run(t.Context(), args))
|
||||
assert.True(t, called)
|
||||
}
|
||||
test(t, []string{"./gitea"}, "", true)
|
||||
test(t, []string{"./gitea", "test"}, "", true)
|
||||
test(t, []string{"./gitea", "other"}, "other", false)
|
||||
}
|
||||
|
|
@ -137,8 +137,8 @@ func runDumpRepository(ctx context.Context, cmd *cli.Command) error {
|
|||
opts.PullRequests = true
|
||||
opts.ReleaseAssets = true
|
||||
} else {
|
||||
units := strings.Split(cmd.String("units"), ",")
|
||||
for _, unit := range units {
|
||||
units := strings.SplitSeq(cmd.String("units"), ",")
|
||||
for unit := range units {
|
||||
switch strings.ToLower(strings.TrimSpace(unit)) {
|
||||
case "":
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -480,7 +480,7 @@ func hookPrintResult(output, isCreate bool, branch, url string) {
|
|||
func pushOptions() map[string]string {
|
||||
opts := make(map[string]string)
|
||||
if pushCount, err := strconv.Atoi(os.Getenv(private.GitPushOptionCount)); err == nil {
|
||||
for idx := 0; idx < pushCount; idx++ {
|
||||
for idx := range pushCount {
|
||||
opt := os.Getenv(fmt.Sprintf("GIT_PUSH_OPTION_%d", idx))
|
||||
kv := strings.SplitN(opt, "=", 2)
|
||||
if len(kv) == 2 {
|
||||
|
|
@ -732,7 +732,7 @@ func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType)
|
|||
|
||||
// read prefix
|
||||
lengthBytes := make([]byte, 4)
|
||||
for i := 0; i < 4; i++ {
|
||||
for i := range 4 {
|
||||
lengthBytes[i], err = in.ReadByte()
|
||||
if err != nil {
|
||||
return nil, fail(ctx, "Protocol: stdin error", "Pkt-Line: read stdin failed : %v", err)
|
||||
|
|
|
|||
|
|
@ -152,6 +152,8 @@ func NewMainApp(appVer AppVersion) *cli.Command {
|
|||
CmdDocs,
|
||||
}
|
||||
|
||||
// TODO: we should eventually drop the default command,
|
||||
// but not sure whether it would break Windows users who used to double-click the EXE to run.
|
||||
app.DefaultCommand = CmdWeb.Name
|
||||
|
||||
app.Flags = append(app.Flags, cli.VersionFlag)
|
||||
|
|
|
|||
|
|
@ -119,7 +119,6 @@ var (
|
|||
Name: "rotate",
|
||||
Aliases: []string{"r"},
|
||||
Usage: "Rotate logs",
|
||||
Value: true,
|
||||
},
|
||||
&cli.Int64Flag{
|
||||
Name: "max-size",
|
||||
|
|
@ -130,7 +129,6 @@ var (
|
|||
Name: "daily",
|
||||
Aliases: []string{"d"},
|
||||
Usage: "Rotate logs daily",
|
||||
Value: true,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "max-days",
|
||||
|
|
@ -141,7 +139,6 @@ var (
|
|||
Name: "compress",
|
||||
Aliases: []string{"z"},
|
||||
Usage: "Compress rotated logs",
|
||||
Value: true,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "compression-level",
|
||||
|
|
|
|||
|
|
@ -251,6 +251,10 @@ func runWeb(_ context.Context, cmd *cli.Command) error {
|
|||
}
|
||||
}()
|
||||
|
||||
if subCmdName, valid := isValidDefaultSubCommand(cmd); !valid {
|
||||
return fmt.Errorf("unknown command: %s", subCmdName)
|
||||
}
|
||||
|
||||
managerCtx, cancel := context.WithCancel(context.Background())
|
||||
graceful.InitManager(managerCtx)
|
||||
defer cancel()
|
||||
|
|
|
|||
|
|
@ -337,8 +337,8 @@ func determineRemote(ctx context.Context, forkUser string) (string, string, erro
|
|||
fmt.Fprintf(os.Stderr, "Unable to list git remotes:\n%s\n", string(out))
|
||||
return "", "", fmt.Errorf("unable to determine forked remote: %w", err)
|
||||
}
|
||||
lines := strings.Split(string(out), "\n")
|
||||
for _, line := range lines {
|
||||
lines := strings.SplitSeq(string(out), "\n")
|
||||
for line := range lines {
|
||||
fields := strings.Split(line, "\t")
|
||||
name, remote := fields[0], fields[1]
|
||||
// only look at pushers
|
||||
|
|
@ -356,12 +356,12 @@ func determineRemote(ctx context.Context, forkUser string) (string, string, erro
|
|||
if !strings.Contains(remote, forkUser) {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(remote, "git@github.com:") {
|
||||
forkUser = strings.TrimPrefix(remote, "git@github.com:")
|
||||
} else if strings.HasPrefix(remote, "https://github.com/") {
|
||||
forkUser = strings.TrimPrefix(remote, "https://github.com/")
|
||||
} else if strings.HasPrefix(remote, "https://www.github.com/") {
|
||||
forkUser = strings.TrimPrefix(remote, "https://www.github.com/")
|
||||
if after, ok := strings.CutPrefix(remote, "git@github.com:"); ok {
|
||||
forkUser = after
|
||||
} else if after, ok := strings.CutPrefix(remote, "https://github.com/"); ok {
|
||||
forkUser = after
|
||||
} else if after, ok := strings.CutPrefix(remote, "https://www.github.com/"); ok {
|
||||
forkUser = after
|
||||
} else if forkUser == "" {
|
||||
return "", "", fmt.Errorf("unable to extract forkUser from remote %s: %s", name, remote)
|
||||
}
|
||||
|
|
|
|||
4
go.mod
4
go.mod
|
|
@ -51,7 +51,7 @@ require (
|
|||
github.com/gliderlabs/ssh v0.3.8
|
||||
github.com/go-ap/activitypub v0.0.0-20250409143848-7113328b1f3d
|
||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
||||
github.com/go-chi/chi/v5 v5.2.1
|
||||
github.com/go-chi/chi/v5 v5.2.2
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/go-co-op/gocron v1.37.0
|
||||
github.com/go-enry/go-enry/v2 v2.9.2
|
||||
|
|
@ -91,7 +91,7 @@ require (
|
|||
github.com/minio/minio-go/v7 v7.0.91
|
||||
github.com/msteinert/pam v1.2.0
|
||||
github.com/nektos/act v0.2.63
|
||||
github.com/niklasfasching/go-org v1.7.0
|
||||
github.com/niklasfasching/go-org v1.8.0
|
||||
github.com/olivere/elastic/v7 v7.0.32
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/opencontainers/image-spec v1.1.1
|
||||
|
|
|
|||
8
go.sum
8
go.sum
|
|
@ -289,8 +289,8 @@ github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73/go.mod h1:jyveZeGw5La
|
|||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
|
||||
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
|
||||
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0=
|
||||
|
|
@ -551,8 +551,8 @@ github.com/msteinert/pam v1.2.0 h1:mYfjlvN2KYs2Pb9G6nb/1f/nPfAttT/Jee5Sq9r3bGE=
|
|||
github.com/msteinert/pam v1.2.0/go.mod h1:d2n0DCUK8rGecChV3JzvmsDjOY4R7AYbsNxAT+ftQl0=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/niklasfasching/go-org v1.7.0 h1:vyMdcMWWTe/XmANk19F4k8XGBYg0GQ/gJGMimOjGMek=
|
||||
github.com/niklasfasching/go-org v1.7.0/go.mod h1:WuVm4d45oePiE0eX25GqTDQIt/qPW1T9DGkRscqLW5o=
|
||||
github.com/niklasfasching/go-org v1.8.0 h1:WyGLaajLLp8JbQzkmapZ1y0MOzKuKV47HkZRloi+HGY=
|
||||
github.com/niklasfasching/go-org v1.8.0/go.mod h1:e2A9zJs7cdONrEGs3gvxCcaAEpwwPNPG7csDpXckMNg=
|
||||
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
|
||||
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||
|
|
|
|||
|
|
@ -166,6 +166,17 @@ func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, err
|
|||
return nil, fmt.Errorf("event %s is not a pull request event", run.Event)
|
||||
}
|
||||
|
||||
func (run *ActionRun) GetWorkflowRunEventPayload() (*api.WorkflowRunPayload, error) {
|
||||
if run.Event == webhook_module.HookEventWorkflowRun {
|
||||
var payload api.WorkflowRunPayload
|
||||
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &payload, nil
|
||||
}
|
||||
return nil, fmt.Errorf("event %s is not a workflow run event", run.Event)
|
||||
}
|
||||
|
||||
func (run *ActionRun) IsSchedule() bool {
|
||||
return run.ScheduleID > 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,22 +80,31 @@ type FindRunJobOptions struct {
|
|||
func (opts FindRunJobOptions) ToConds() builder.Cond {
|
||||
cond := builder.NewCond()
|
||||
if opts.RunID > 0 {
|
||||
cond = cond.And(builder.Eq{"run_id": opts.RunID})
|
||||
cond = cond.And(builder.Eq{"`action_run_job`.run_id": opts.RunID})
|
||||
}
|
||||
if opts.RepoID > 0 {
|
||||
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
||||
}
|
||||
if opts.OwnerID > 0 {
|
||||
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
||||
cond = cond.And(builder.Eq{"`action_run_job`.repo_id": opts.RepoID})
|
||||
}
|
||||
if opts.CommitSHA != "" {
|
||||
cond = cond.And(builder.Eq{"commit_sha": opts.CommitSHA})
|
||||
cond = cond.And(builder.Eq{"`action_run_job`.commit_sha": opts.CommitSHA})
|
||||
}
|
||||
if len(opts.Statuses) > 0 {
|
||||
cond = cond.And(builder.In("status", opts.Statuses))
|
||||
cond = cond.And(builder.In("`action_run_job`.status", opts.Statuses))
|
||||
}
|
||||
if opts.UpdatedBefore > 0 {
|
||||
cond = cond.And(builder.Lt{"updated": opts.UpdatedBefore})
|
||||
cond = cond.And(builder.Lt{"`action_run_job`.updated": opts.UpdatedBefore})
|
||||
}
|
||||
return cond
|
||||
}
|
||||
|
||||
func (opts FindRunJobOptions) ToJoins() []db.JoinFunc {
|
||||
if opts.OwnerID > 0 {
|
||||
return []db.JoinFunc{
|
||||
func(sess db.Engine) error {
|
||||
sess.Join("INNER", "repository", "repository.id = repo_id AND repository.owner_id = ?", opts.OwnerID)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,39 +72,50 @@ type FindRunOptions struct {
|
|||
TriggerEvent webhook_module.HookEventType
|
||||
Approved bool // not util.OptionalBool, it works only when it's true
|
||||
Status []Status
|
||||
CommitSHA string
|
||||
}
|
||||
|
||||
func (opts FindRunOptions) ToConds() builder.Cond {
|
||||
cond := builder.NewCond()
|
||||
if opts.RepoID > 0 {
|
||||
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
||||
}
|
||||
if opts.OwnerID > 0 {
|
||||
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
||||
cond = cond.And(builder.Eq{"`action_run`.repo_id": opts.RepoID})
|
||||
}
|
||||
if opts.WorkflowID != "" {
|
||||
cond = cond.And(builder.Eq{"workflow_id": opts.WorkflowID})
|
||||
cond = cond.And(builder.Eq{"`action_run`.workflow_id": opts.WorkflowID})
|
||||
}
|
||||
if opts.TriggerUserID > 0 {
|
||||
cond = cond.And(builder.Eq{"trigger_user_id": opts.TriggerUserID})
|
||||
cond = cond.And(builder.Eq{"`action_run`.trigger_user_id": opts.TriggerUserID})
|
||||
}
|
||||
if opts.Approved {
|
||||
cond = cond.And(builder.Gt{"approved_by": 0})
|
||||
cond = cond.And(builder.Gt{"`action_run`.approved_by": 0})
|
||||
}
|
||||
if len(opts.Status) > 0 {
|
||||
cond = cond.And(builder.In("status", opts.Status))
|
||||
cond = cond.And(builder.In("`action_run`.status", opts.Status))
|
||||
}
|
||||
if opts.Ref != "" {
|
||||
cond = cond.And(builder.Eq{"ref": opts.Ref})
|
||||
cond = cond.And(builder.Eq{"`action_run`.ref": opts.Ref})
|
||||
}
|
||||
if opts.TriggerEvent != "" {
|
||||
cond = cond.And(builder.Eq{"trigger_event": opts.TriggerEvent})
|
||||
cond = cond.And(builder.Eq{"`action_run`.trigger_event": opts.TriggerEvent})
|
||||
}
|
||||
if opts.CommitSHA != "" {
|
||||
cond = cond.And(builder.Eq{"`action_run`.commit_sha": opts.CommitSHA})
|
||||
}
|
||||
return cond
|
||||
}
|
||||
|
||||
func (opts FindRunOptions) ToJoins() []db.JoinFunc {
|
||||
if opts.OwnerID > 0 {
|
||||
return []db.JoinFunc{func(sess db.Engine) error {
|
||||
sess.Join("INNER", "repository", "repository.id = repo_id AND repository.owner_id = ?", opts.OwnerID)
|
||||
return nil
|
||||
}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (opts FindRunOptions) ToOrders() string {
|
||||
return "`id` DESC"
|
||||
return "`action_run`.`id` DESC"
|
||||
}
|
||||
|
||||
type StatusInfo struct {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
package actions
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
|
|
@ -88,12 +90,7 @@ func (s Status) IsBlocked() bool {
|
|||
|
||||
// In returns whether s is one of the given statuses
|
||||
func (s Status) In(statuses ...Status) bool {
|
||||
for _, v := range statuses {
|
||||
if s == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(statuses, s)
|
||||
}
|
||||
|
||||
func (s Status) AsResult() runnerv1.Result {
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
|
|||
if n, err := UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}); err != nil {
|
||||
return nil, false, err
|
||||
} else if n != 1 {
|
||||
return nil, false, nil
|
||||
return nil, false, fmt.Errorf("other runner picked up our job")
|
||||
}
|
||||
|
||||
task.Job = job
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -125,12 +126,7 @@ func (at ActionType) String() string {
|
|||
}
|
||||
|
||||
func (at ActionType) InActions(actions ...string) bool {
|
||||
for _, action := range actions {
|
||||
if action == at.String() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(actions, at.String())
|
||||
}
|
||||
|
||||
// Action represents user operation type and other information to
|
||||
|
|
@ -191,7 +187,7 @@ func (a *Action) LoadActUser(ctx context.Context) {
|
|||
return
|
||||
}
|
||||
var err error
|
||||
a.ActUser, err = user_model.GetUserByID(ctx, a.ActUserID)
|
||||
a.ActUser, err = user_model.GetPossibleUserByID(ctx, a.ActUserID)
|
||||
if err == nil {
|
||||
return
|
||||
} else if user_model.IsErrUserNotExist(err) {
|
||||
|
|
|
|||
|
|
@ -208,10 +208,7 @@ func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.Repository
|
|||
repos := make(map[int64]*repo_model.Repository, len(repoIDs))
|
||||
left := len(repoIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("id", repoIDs[:limit]).
|
||||
Rows(new(repo_model.Repository))
|
||||
|
|
@ -282,10 +279,7 @@ func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) {
|
|||
issues := make(map[int64]*issues_model.Issue, len(issueIDs))
|
||||
left := len(issueIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("id", issueIDs[:limit]).
|
||||
Rows(new(issues_model.Issue))
|
||||
|
|
@ -377,10 +371,7 @@ func (nl NotificationList) LoadUsers(ctx context.Context) ([]int, error) {
|
|||
users := make(map[int64]*user_model.User, len(userIDs))
|
||||
left := len(userIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("id", userIDs[:limit]).
|
||||
Rows(new(user_model.User))
|
||||
|
|
@ -428,10 +419,7 @@ func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) {
|
|||
comments := make(map[int64]*issues_model.Comment, len(commentIDs))
|
||||
left := len(commentIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("id", commentIDs[:limit]).
|
||||
Rows(new(issues_model.Comment))
|
||||
|
|
|
|||
|
|
@ -139,10 +139,7 @@ func GetActivityStatsTopAuthors(ctx context.Context, repo *repo_model.Repository
|
|||
return v[i].Commits > v[j].Commits
|
||||
})
|
||||
|
||||
cnt := count
|
||||
if cnt > len(v) {
|
||||
cnt = len(v)
|
||||
}
|
||||
cnt := min(count, len(v))
|
||||
|
||||
return v[:cnt], nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,12 +213,7 @@ func GetRequiredScopes(level AccessTokenScopeLevel, scopeCategories ...AccessTok
|
|||
|
||||
// ContainsCategory checks if a list of categories contains a specific category
|
||||
func ContainsCategory(categories []AccessTokenScopeCategory, category AccessTokenScopeCategory) bool {
|
||||
for _, c := range categories {
|
||||
if c == category {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(categories, category)
|
||||
}
|
||||
|
||||
// GetScopeLevelFromAccessMode converts permission access mode to scope level
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
|
|
@ -511,12 +512,7 @@ func (grant *OAuth2Grant) IncreaseCounter(ctx context.Context) error {
|
|||
|
||||
// ScopeContains returns true if the grant scope contains the specified scope
|
||||
func (grant *OAuth2Grant) ScopeContains(scope string) bool {
|
||||
for _, currentScope := range strings.Split(grant.Scope, " ") {
|
||||
if scope == currentScope {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(strings.Split(grant.Scope, " "), scope)
|
||||
}
|
||||
|
||||
// SetNonce updates the current nonce value of a grant
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ func contextSafetyCheck(e Engine) {
|
|||
_ = e.SQL("SELECT 1").Iterate(&m{}, func(int, any) error {
|
||||
callers := make([]uintptr, 32)
|
||||
callerNum := runtime.Callers(1, callers)
|
||||
for i := 0; i < callerNum; i++ {
|
||||
for i := range callerNum {
|
||||
if funcName := runtime.FuncForPC(callers[i]).Name(); funcName == "xorm.io/xorm.(*Session).Iterate" {
|
||||
contextSafetyDeniedFuncPCs = append(contextSafetyDeniedFuncPCs, callers[i])
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ func contextSafetyCheck(e Engine) {
|
|||
// it should be very fast: xxxx ns/op
|
||||
callers := make([]uintptr, 32)
|
||||
callerNum := runtime.Callers(3, callers) // skip 3: runtime.Callers, contextSafetyCheck, GetEngine
|
||||
for i := 0; i < callerNum; i++ {
|
||||
for i := range callerNum {
|
||||
if slices.Contains(contextSafetyDeniedFuncPCs, callers[i]) {
|
||||
panic(errors.New("using database context in an iterator would cause corrupted results"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ package db
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
|
|
@ -80,10 +81,8 @@ func IsUsableName(reservedNames, reservedPatterns []string, name string) error {
|
|||
return util.NewInvalidArgumentErrorf("name is empty")
|
||||
}
|
||||
|
||||
for i := range reservedNames {
|
||||
if name == reservedNames[i] {
|
||||
return ErrNameReserved{name}
|
||||
}
|
||||
if slices.Contains(reservedNames, name) {
|
||||
return ErrNameReserved{name}
|
||||
}
|
||||
|
||||
for _, pat := range reservedPatterns {
|
||||
|
|
|
|||
|
|
@ -46,10 +46,7 @@ func (f *file) readAt(fileMeta *dbfsMeta, offset int64, p []byte) (n int, err er
|
|||
blobPos := int(offset % f.blockSize)
|
||||
blobOffset := offset - int64(blobPos)
|
||||
blobRemaining := int(f.blockSize) - blobPos
|
||||
needRead := len(p)
|
||||
if needRead > blobRemaining {
|
||||
needRead = blobRemaining
|
||||
}
|
||||
needRead := min(len(p), blobRemaining)
|
||||
if blobOffset+int64(blobPos)+int64(needRead) > fileMeta.FileSize {
|
||||
needRead = int(fileMeta.FileSize - blobOffset - int64(blobPos))
|
||||
}
|
||||
|
|
@ -66,14 +63,8 @@ func (f *file) readAt(fileMeta *dbfsMeta, offset int64, p []byte) (n int, err er
|
|||
blobData = nil
|
||||
}
|
||||
|
||||
canCopy := len(blobData) - blobPos
|
||||
if canCopy <= 0 {
|
||||
canCopy = 0
|
||||
}
|
||||
realRead := needRead
|
||||
if realRead > canCopy {
|
||||
realRead = canCopy
|
||||
}
|
||||
canCopy := max(len(blobData)-blobPos, 0)
|
||||
realRead := min(needRead, canCopy)
|
||||
if realRead > 0 {
|
||||
copy(p[:realRead], fileData.BlobData[blobPos:blobPos+realRead])
|
||||
}
|
||||
|
|
@ -113,10 +104,7 @@ func (f *file) Write(p []byte) (n int, err error) {
|
|||
blobPos := int(f.offset % f.blockSize)
|
||||
blobOffset := f.offset - int64(blobPos)
|
||||
blobRemaining := int(f.blockSize) - blobPos
|
||||
needWrite := len(p)
|
||||
if needWrite > blobRemaining {
|
||||
needWrite = blobRemaining
|
||||
}
|
||||
needWrite := min(len(p), blobRemaining)
|
||||
buf := make([]byte, f.blockSize)
|
||||
readBytes, err := f.readAt(fileMeta, blobOffset, buf)
|
||||
if err != nil && !errors.Is(err, io.EOF) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
ref: "refs/heads/master"
|
||||
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
|
||||
event: "push"
|
||||
trigger_event: "push"
|
||||
is_fork_pull_request: 0
|
||||
status: 1
|
||||
started: 1683636528
|
||||
|
|
@ -28,6 +29,7 @@
|
|||
ref: "refs/heads/master"
|
||||
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
|
||||
event: "push"
|
||||
trigger_event: "push"
|
||||
is_fork_pull_request: 0
|
||||
status: 1
|
||||
started: 1683636528
|
||||
|
|
@ -47,6 +49,7 @@
|
|||
ref: "refs/heads/master"
|
||||
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
|
||||
event: "push"
|
||||
trigger_event: "push"
|
||||
is_fork_pull_request: 0
|
||||
status: 6 # running
|
||||
started: 1683636528
|
||||
|
|
@ -66,6 +69,47 @@
|
|||
ref: "refs/heads/test"
|
||||
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
|
||||
event: "push"
|
||||
trigger_event: "push"
|
||||
is_fork_pull_request: 0
|
||||
status: 1
|
||||
started: 1683636528
|
||||
stopped: 1683636626
|
||||
created: 1683636108
|
||||
updated: 1683636626
|
||||
need_approval: 0
|
||||
approved_by: 0
|
||||
-
|
||||
id: 802
|
||||
title: "workflow run list"
|
||||
repo_id: 5
|
||||
owner_id: 3
|
||||
workflow_id: "test.yaml"
|
||||
index: 191
|
||||
trigger_user_id: 1
|
||||
ref: "refs/heads/test"
|
||||
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
|
||||
event: "push"
|
||||
trigger_event: "push"
|
||||
is_fork_pull_request: 0
|
||||
status: 1
|
||||
started: 1683636528
|
||||
stopped: 1683636626
|
||||
created: 1683636108
|
||||
updated: 1683636626
|
||||
need_approval: 0
|
||||
approved_by: 0
|
||||
-
|
||||
id: 803
|
||||
title: "workflow run list for user"
|
||||
repo_id: 2
|
||||
owner_id: 0
|
||||
workflow_id: "test.yaml"
|
||||
index: 192
|
||||
trigger_user_id: 1
|
||||
ref: "refs/heads/test"
|
||||
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
|
||||
event: "push"
|
||||
trigger_event: "push"
|
||||
is_fork_pull_request: 0
|
||||
status: 1
|
||||
started: 1683636528
|
||||
|
|
@ -86,6 +130,7 @@
|
|||
ref: "refs/heads/test"
|
||||
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
|
||||
event: "push"
|
||||
trigger_event: "push"
|
||||
is_fork_pull_request: 0
|
||||
status: 2
|
||||
started: 1683636528
|
||||
|
|
|
|||
|
|
@ -99,3 +99,33 @@
|
|||
status: 2
|
||||
started: 1683636528
|
||||
stopped: 1683636626
|
||||
-
|
||||
id: 203
|
||||
run_id: 802
|
||||
repo_id: 5
|
||||
owner_id: 0
|
||||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
|
||||
is_fork_pull_request: 0
|
||||
name: job2
|
||||
attempt: 1
|
||||
job_id: job2
|
||||
needs: '["job1"]'
|
||||
task_id: 51
|
||||
status: 5
|
||||
started: 1683636528
|
||||
stopped: 1683636626
|
||||
-
|
||||
id: 204
|
||||
run_id: 803
|
||||
repo_id: 2
|
||||
owner_id: 0
|
||||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
|
||||
is_fork_pull_request: 0
|
||||
name: job2
|
||||
attempt: 1
|
||||
job_id: job2
|
||||
needs: '["job1"]'
|
||||
task_id: 51
|
||||
status: 5
|
||||
started: 1683636528
|
||||
stopped: 1683636626
|
||||
|
|
|
|||
|
|
@ -201,3 +201,15 @@
|
|||
is_deleted: false
|
||||
deleted_by_id: 0
|
||||
deleted_unix: 0
|
||||
|
||||
-
|
||||
id: 25
|
||||
repo_id: 54
|
||||
name: 'master'
|
||||
commit_id: '73cf03db6ece34e12bf91e8853dc58f678f2f82d'
|
||||
commit_message: 'Initial commit'
|
||||
commit_time: 1671663402
|
||||
pusher_id: 2
|
||||
is_deleted: false
|
||||
deleted_by_id: 0
|
||||
deleted_unix: 0
|
||||
|
|
|
|||
|
|
@ -112,7 +112,6 @@ type LFSMetaObject struct {
|
|||
ID int64 `xorm:"pk autoincr"`
|
||||
lfs.Pointer `xorm:"extends"`
|
||||
RepositoryID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Existing bool `xorm:"-"`
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
}
|
||||
|
|
@ -146,7 +145,6 @@ func NewLFSMetaObject(ctx context.Context, repoID int64, p lfs.Pointer) (*LFSMet
|
|||
if err != nil {
|
||||
return nil, err
|
||||
} else if exist {
|
||||
m.Existing = true
|
||||
return m, committer.Commit()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ func (protectBranch *ProtectedBranch) GetUnprotectedFilePatterns() []glob.Glob {
|
|||
|
||||
func getFilePatterns(filePatterns string) []glob.Glob {
|
||||
extarr := make([]glob.Glob, 0, 10)
|
||||
for _, expr := range strings.Split(strings.ToLower(filePatterns), ";") {
|
||||
for expr := range strings.SplitSeq(strings.ToLower(filePatterns), ";") {
|
||||
expr = strings.TrimSpace(expr)
|
||||
if expr != "" {
|
||||
if g, err := glob.Compile(expr, '.', '/'); err != nil {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"slices"
|
||||
"strconv"
|
||||
"unicode/utf8"
|
||||
|
||||
|
|
@ -196,12 +197,7 @@ func (t CommentType) HasMailReplySupport() bool {
|
|||
}
|
||||
|
||||
func (t CommentType) CountedAsConversation() bool {
|
||||
for _, ct := range ConversationCountedCommentType() {
|
||||
if t == ct {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(ConversationCountedCommentType(), t)
|
||||
}
|
||||
|
||||
// ConversationCountedCommentType returns the comment types that are counted as a conversation
|
||||
|
|
@ -614,7 +610,7 @@ func UpdateCommentAttachments(ctx context.Context, c *Comment, uuids []string) e
|
|||
if err != nil {
|
||||
return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %w", uuids, err)
|
||||
}
|
||||
for i := 0; i < len(attachments); i++ {
|
||||
for i := range attachments {
|
||||
attachments[i].IssueID = c.IssueID
|
||||
attachments[i].CommentID = c.ID
|
||||
if err := repo_model.UpdateAttachment(ctx, attachments[i]); err != nil {
|
||||
|
|
|
|||
|
|
@ -57,10 +57,7 @@ func (comments CommentList) loadLabels(ctx context.Context) error {
|
|||
commentLabels := make(map[int64]*Label, len(labelIDs))
|
||||
left := len(labelIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("id", labelIDs[:limit]).
|
||||
Rows(new(Label))
|
||||
|
|
@ -107,10 +104,7 @@ func (comments CommentList) loadMilestones(ctx context.Context) error {
|
|||
milestoneMaps := make(map[int64]*Milestone, len(milestoneIDs))
|
||||
left := len(milestoneIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
err := db.GetEngine(ctx).
|
||||
In("id", milestoneIDs[:limit]).
|
||||
Find(&milestoneMaps)
|
||||
|
|
@ -146,10 +140,7 @@ func (comments CommentList) loadOldMilestones(ctx context.Context) error {
|
|||
milestoneMaps := make(map[int64]*Milestone, len(milestoneIDs))
|
||||
left := len(milestoneIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
err := db.GetEngine(ctx).
|
||||
In("id", milestoneIDs[:limit]).
|
||||
Find(&milestoneMaps)
|
||||
|
|
@ -184,10 +175,7 @@ func (comments CommentList) loadAssignees(ctx context.Context) error {
|
|||
assignees := make(map[int64]*user_model.User, len(assigneeIDs))
|
||||
left := len(assigneeIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("id", assigneeIDs[:limit]).
|
||||
Rows(new(user_model.User))
|
||||
|
|
@ -256,10 +244,7 @@ func (comments CommentList) LoadIssues(ctx context.Context) error {
|
|||
issues := make(map[int64]*Issue, len(issueIDs))
|
||||
left := len(issueIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("id", issueIDs[:limit]).
|
||||
Rows(new(Issue))
|
||||
|
|
@ -313,10 +298,7 @@ func (comments CommentList) loadDependentIssues(ctx context.Context) error {
|
|||
issues := make(map[int64]*Issue, len(issueIDs))
|
||||
left := len(issueIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := e.
|
||||
In("id", issueIDs[:limit]).
|
||||
Rows(new(Issue))
|
||||
|
|
@ -392,10 +374,7 @@ func (comments CommentList) LoadAttachments(ctx context.Context) (err error) {
|
|||
commentsIDs := comments.getAttachmentCommentIDs()
|
||||
left := len(commentsIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("comment_id", commentsIDs[:limit]).
|
||||
Rows(new(repo_model.Attachment))
|
||||
|
|
|
|||
|
|
@ -42,10 +42,7 @@ func (issues IssueList) LoadRepositories(ctx context.Context) (repo_model.Reposi
|
|||
repoMaps := make(map[int64]*repo_model.Repository, len(repoIDs))
|
||||
left := len(repoIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
err := db.GetEngine(ctx).
|
||||
In("id", repoIDs[:limit]).
|
||||
Find(&repoMaps)
|
||||
|
|
@ -116,10 +113,7 @@ func (issues IssueList) LoadLabels(ctx context.Context) error {
|
|||
issueIDs := issues.getIssueIDs()
|
||||
left := len(issueIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).Table("label").
|
||||
Join("LEFT", "issue_label", "issue_label.label_id = label.id").
|
||||
In("issue_label.issue_id", issueIDs[:limit]).
|
||||
|
|
@ -171,10 +165,7 @@ func (issues IssueList) LoadMilestones(ctx context.Context) error {
|
|||
milestoneMaps := make(map[int64]*Milestone, len(milestoneIDs))
|
||||
left := len(milestoneIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
err := db.GetEngine(ctx).
|
||||
In("id", milestoneIDs[:limit]).
|
||||
Find(&milestoneMaps)
|
||||
|
|
@ -203,10 +194,7 @@ func (issues IssueList) LoadProjects(ctx context.Context) error {
|
|||
}
|
||||
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
|
||||
projects := make([]*projectWithIssueID, 0, limit)
|
||||
err := db.GetEngine(ctx).
|
||||
|
|
@ -245,10 +233,7 @@ func (issues IssueList) LoadAssignees(ctx context.Context) error {
|
|||
issueIDs := issues.getIssueIDs()
|
||||
left := len(issueIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).Table("issue_assignees").
|
||||
Join("INNER", "`user`", "`user`.id = `issue_assignees`.assignee_id").
|
||||
In("`issue_assignees`.issue_id", issueIDs[:limit]).OrderBy(user_model.GetOrderByName()).
|
||||
|
|
@ -306,10 +291,7 @@ func (issues IssueList) LoadPullRequests(ctx context.Context) error {
|
|||
pullRequestMaps := make(map[int64]*PullRequest, len(issuesIDs))
|
||||
left := len(issuesIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("issue_id", issuesIDs[:limit]).
|
||||
Rows(new(PullRequest))
|
||||
|
|
@ -354,10 +336,7 @@ func (issues IssueList) LoadAttachments(ctx context.Context) (err error) {
|
|||
issuesIDs := issues.getIssueIDs()
|
||||
left := len(issuesIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("issue_id", issuesIDs[:limit]).
|
||||
Rows(new(repo_model.Attachment))
|
||||
|
|
@ -399,10 +378,7 @@ func (issues IssueList) loadComments(ctx context.Context, cond builder.Cond) (er
|
|||
issuesIDs := issues.getIssueIDs()
|
||||
left := len(issuesIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).Table("comment").
|
||||
Join("INNER", "issue", "issue.id = comment.issue_id").
|
||||
In("issue.id", issuesIDs[:limit]).
|
||||
|
|
@ -466,10 +442,7 @@ func (issues IssueList) loadTotalTrackedTimes(ctx context.Context) (err error) {
|
|||
|
||||
left := len(ids)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
|
||||
// select issue_id, sum(time) from tracked_time where issue_id in (<issue ids in current page>) group by issue_id
|
||||
rows, err := db.GetEngine(ctx).Table("tracked_time").
|
||||
|
|
|
|||
|
|
@ -73,8 +73,8 @@ func (o *IssuesOptions) Copy(edit ...func(options *IssuesOptions)) *IssuesOption
|
|||
// sortType string
|
||||
func applySorts(sess *xorm.Session, sortType string, priorityRepoID int64) {
|
||||
// Since this sortType is dynamically created, it has to be treated specially.
|
||||
if strings.HasPrefix(sortType, ScopeSortPrefix) {
|
||||
scope := strings.TrimPrefix(sortType, ScopeSortPrefix)
|
||||
if after, ok := strings.CutPrefix(sortType, ScopeSortPrefix); ok {
|
||||
scope := after
|
||||
sess.Join("LEFT", "issue_label", "issue.id = issue_label.issue_id")
|
||||
// "exclusive_order=0" means "no order is set", so exclude it from the JOIN criteria and then "LEFT JOIN" result is also null
|
||||
sess.Join("LEFT", "label", "label.id = issue_label.label_id AND label.exclusive_order <> 0 AND label.name LIKE ?", scope+"/%")
|
||||
|
|
|
|||
|
|
@ -94,10 +94,7 @@ func GetIssueStats(ctx context.Context, opts *IssuesOptions) (*IssueStats, error
|
|||
// ids in a temporary table and join from them.
|
||||
accum := &IssueStats{}
|
||||
for i := 0; i < len(opts.IssueIDs); {
|
||||
chunk := i + MaxQueryParameters
|
||||
if chunk > len(opts.IssueIDs) {
|
||||
chunk = len(opts.IssueIDs)
|
||||
}
|
||||
chunk := min(i+MaxQueryParameters, len(opts.IssueIDs))
|
||||
stats, err := getIssueStatsChunk(ctx, opts, opts.IssueIDs[i:chunk])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ package issues_test
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"sort"
|
||||
"sync"
|
||||
"testing"
|
||||
|
|
@ -270,7 +271,7 @@ func TestIssue_ResolveMentions(t *testing.T) {
|
|||
for i, user := range resolved {
|
||||
ids[i] = user.ID
|
||||
}
|
||||
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
|
||||
slices.Sort(ids)
|
||||
assert.Equal(t, expected, ids)
|
||||
}
|
||||
|
||||
|
|
@ -292,7 +293,7 @@ func TestResourceIndex(t *testing.T) {
|
|||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 100; i++ {
|
||||
for i := range 100 {
|
||||
wg.Add(1)
|
||||
go func(i int) {
|
||||
testInsertIssue(t, fmt.Sprintf("issue %d", i+1), "my issue", 0)
|
||||
|
|
@ -314,7 +315,7 @@ func TestCorrectIssueStats(t *testing.T) {
|
|||
issueAmount := issues_model.MaxQueryParameters + 10
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < issueAmount; i++ {
|
||||
for i := range issueAmount {
|
||||
wg.Add(1)
|
||||
go func(i int) {
|
||||
testInsertIssue(t, fmt.Sprintf("Issue %d", i+1), "Bugs are nasty", 0)
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ func UpdateIssueAttachments(ctx context.Context, issueID int64, uuids []string)
|
|||
if err != nil {
|
||||
return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %w", uuids, err)
|
||||
}
|
||||
for i := 0; i < len(attachments); i++ {
|
||||
for i := range attachments {
|
||||
attachments[i].IssueID = issueID
|
||||
if err := repo_model.UpdateAttachment(ctx, attachments[i]); err != nil {
|
||||
return fmt.Errorf("update attachment [id: %d]: %w", attachments[i].ID, err)
|
||||
|
|
|
|||
|
|
@ -649,12 +649,6 @@ func GetAllUnmergedAgitPullRequestByPoster(ctx context.Context, uid int64) ([]*P
|
|||
return pulls, err
|
||||
}
|
||||
|
||||
// Update updates all fields of pull request.
|
||||
func (pr *PullRequest) Update(ctx context.Context) error {
|
||||
_, err := db.GetEngine(ctx).ID(pr.ID).AllCols().Update(pr)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateCols updates specific fields of pull request.
|
||||
func (pr *PullRequest) UpdateCols(ctx context.Context, cols ...string) error {
|
||||
_, err := db.GetEngine(ctx).ID(pr.ID).Cols(cols...).Update(pr)
|
||||
|
|
|
|||
|
|
@ -248,19 +248,6 @@ func TestGetPullRequestByIssueID(t *testing.T) {
|
|||
assert.True(t, issues_model.IsErrPullRequestNotExist(err))
|
||||
}
|
||||
|
||||
func TestPullRequest_Update(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})
|
||||
pr.BaseBranch = "baseBranch"
|
||||
pr.HeadBranch = "headBranch"
|
||||
pr.Update(db.DefaultContext)
|
||||
|
||||
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
|
||||
assert.Equal(t, "baseBranch", pr.BaseBranch)
|
||||
assert.Equal(t, "headBranch", pr.HeadBranch)
|
||||
unittest.CheckConsistencyFor(t, pr)
|
||||
}
|
||||
|
||||
func TestPullRequest_UpdateCols(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
pr := &issues_model.PullRequest{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ type ReviewList []*Review
|
|||
// LoadReviewers loads reviewers
|
||||
func (reviews ReviewList) LoadReviewers(ctx context.Context) error {
|
||||
reviewerIDs := make([]int64, len(reviews))
|
||||
for i := 0; i < len(reviews); i++ {
|
||||
for i := range reviews {
|
||||
reviewerIDs[i] = reviews[i].ReviewerID
|
||||
}
|
||||
reviewers, err := user_model.GetPossibleUserByIDs(ctx, reviewerIDs)
|
||||
|
|
|
|||
|
|
@ -350,10 +350,7 @@ func GetIssueTotalTrackedTime(ctx context.Context, opts *IssuesOptions, isClosed
|
|||
// we get the statistics in smaller chunks and get accumulates
|
||||
var accum int64
|
||||
for i := 0; i < len(opts.IssueIDs); {
|
||||
chunk := i + MaxQueryParameters
|
||||
if chunk > len(opts.IssueIDs) {
|
||||
chunk = len(opts.IssueIDs)
|
||||
}
|
||||
chunk := min(i+MaxQueryParameters, len(opts.IssueIDs))
|
||||
time, err := getIssueTotalTrackedTimeChunk(ctx, opts, isClosed, opts.IssueIDs[i:chunk])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
|
|
|||
|
|
@ -518,7 +518,7 @@ func ModifyColumn(x *xorm.Engine, tableName string, col *schemas.Column) error {
|
|||
|
||||
func removeAllWithRetry(dir string) error {
|
||||
var err error
|
||||
for i := 0; i < 20; i++ {
|
||||
for range 20 {
|
||||
err = os.RemoveAll(dir)
|
||||
if err == nil {
|
||||
break
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ package v1_11 //nolint
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
|
@ -344,10 +345,8 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
|||
}
|
||||
return AccessModeWrite <= perm.UnitsMode[UnitTypeCode], nil
|
||||
}
|
||||
for _, id := range protectedBranch.ApprovalsWhitelistUserIDs {
|
||||
if id == reviewer.ID {
|
||||
return true, nil
|
||||
}
|
||||
if slices.Contains(protectedBranch.ApprovalsWhitelistUserIDs, reviewer.ID) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// isUserInTeams
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ func copyOldAvatarToNewLocation(userID int64, oldAvatar string) (string, error)
|
|||
return "", fmt.Errorf("io.ReadAll: %w", err)
|
||||
}
|
||||
|
||||
newAvatar := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%x", userID, md5.Sum(data)))))
|
||||
newAvatar := fmt.Sprintf("%x", md5.Sum(fmt.Appendf(nil, "%d-%x", userID, md5.Sum(data))))
|
||||
if newAvatar == oldAvatar {
|
||||
return newAvatar, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ func ConvertScopedAccessTokens(x *xorm.Engine) error {
|
|||
for _, token := range tokens {
|
||||
var scopes []string
|
||||
allNewScopesMap := make(map[AccessTokenScope]bool)
|
||||
for _, oldScope := range strings.Split(token.Scope, ",") {
|
||||
for oldScope := range strings.SplitSeq(token.Scope, ",") {
|
||||
if newScopes, exists := accessTokenScopeMap[OldAccessTokenScope(oldScope)]; exists {
|
||||
for _, newScope := range newScopes {
|
||||
allNewScopesMap[newScope] = true
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
package v1_22 //nolint
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/migrations/base"
|
||||
|
|
@ -44,7 +43,7 @@ func Test_AddUniqueIndexForProjectIssue(t *testing.T) {
|
|||
for _, index := range tables[0].Indexes {
|
||||
if index.Type == schemas.UniqueType {
|
||||
found = true
|
||||
slices.Equal(index.Cols, []string{"project_id", "issue_id"})
|
||||
assert.ElementsMatch(t, index.Cols, []string{"project_id", "issue_id"})
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ type BlobSearchOptions struct {
|
|||
Digest string
|
||||
Tag string
|
||||
IsManifest bool
|
||||
OnlyLead bool
|
||||
Repository string
|
||||
}
|
||||
|
||||
|
|
@ -43,7 +44,10 @@ func (opts *BlobSearchOptions) toConds() builder.Cond {
|
|||
cond = cond.And(builder.Eq{"package_version.lower_version": strings.ToLower(opts.Tag)})
|
||||
}
|
||||
if opts.IsManifest {
|
||||
cond = cond.And(builder.Eq{"package_file.lower_name": ManifestFilename})
|
||||
cond = cond.And(builder.Eq{"package_file.lower_name": container_module.ManifestFilename})
|
||||
}
|
||||
if opts.OnlyLead {
|
||||
cond = cond.And(builder.Eq{"package_file.is_lead": true})
|
||||
}
|
||||
if opts.Digest != "" {
|
||||
var propsCond builder.Cond = builder.Eq{
|
||||
|
|
@ -73,11 +77,9 @@ func GetContainerBlob(ctx context.Context, opts *BlobSearchOptions) (*packages.P
|
|||
pfds, err := getContainerBlobsLimit(ctx, opts, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(pfds) != 1 {
|
||||
} else if len(pfds) == 0 {
|
||||
return nil, ErrContainerBlobNotExist
|
||||
}
|
||||
|
||||
return pfds[0], nil
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +235,7 @@ func SearchImageTags(ctx context.Context, opts *ImageTagsSearchOptions) ([]*pack
|
|||
func SearchExpiredUploadedBlobs(ctx context.Context, olderThan time.Duration) ([]*packages.PackageFile, error) {
|
||||
var cond builder.Cond = builder.Eq{
|
||||
"package_version.is_internal": true,
|
||||
"package_version.lower_version": UploadVersion,
|
||||
"package_version.lower_version": container_module.UploadVersion,
|
||||
"package.type": packages.TypeContainer,
|
||||
}
|
||||
cond = cond.And(builder.Lt{"package_file.created_unix": time.Now().Add(-olderThan).Unix()})
|
||||
|
|
|
|||
|
|
@ -103,10 +103,10 @@ func (pd *PackageDescriptor) CalculateBlobSize() int64 {
|
|||
|
||||
// GetPackageDescriptor gets the package description for a version
|
||||
func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDescriptor, error) {
|
||||
return getPackageDescriptor(ctx, pv, cache.NewEphemeralCache())
|
||||
return GetPackageDescriptorWithCache(ctx, pv, cache.NewEphemeralCache())
|
||||
}
|
||||
|
||||
func getPackageDescriptor(ctx context.Context, pv *PackageVersion, c *cache.EphemeralCache) (*PackageDescriptor, error) {
|
||||
func GetPackageDescriptorWithCache(ctx context.Context, pv *PackageVersion, c *cache.EphemeralCache) (*PackageDescriptor, error) {
|
||||
p, err := cache.GetWithEphemeralCache(ctx, c, "package", pv.PackageID, GetPackageByID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -270,7 +270,7 @@ func GetPackageDescriptors(ctx context.Context, pvs []*PackageVersion) ([]*Packa
|
|||
func getPackageDescriptors(ctx context.Context, pvs []*PackageVersion, c *cache.EphemeralCache) ([]*PackageDescriptor, error) {
|
||||
pds := make([]*PackageDescriptor, 0, len(pvs))
|
||||
for _, pv := range pvs {
|
||||
pd, err := getPackageDescriptor(ctx, pv, c)
|
||||
pd, err := GetPackageDescriptorWithCache(ctx, pv, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ func SearchVersions(ctx context.Context, opts *packages_model.PackageSearchOptio
|
|||
Where(cond).
|
||||
OrderBy("package.name ASC")
|
||||
if opts.Paginator != nil {
|
||||
skip, take := opts.GetSkipTake()
|
||||
skip, take := opts.Paginator.GetSkipTake()
|
||||
inner = inner.Limit(take, skip)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,6 +115,11 @@ func DeleteFileByID(ctx context.Context, fileID int64) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func UpdateFile(ctx context.Context, pf *PackageFile, cols []string) error {
|
||||
_, err := db.GetEngine(ctx).ID(pf.ID).Cols(cols...).Update(pf)
|
||||
return err
|
||||
}
|
||||
|
||||
// PackageFileSearchOptions are options for SearchXXX methods
|
||||
type PackageFileSearchOptions struct {
|
||||
OwnerID int64
|
||||
|
|
|
|||
|
|
@ -66,6 +66,20 @@ func UpdateProperty(ctx context.Context, pp *PackageProperty) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func InsertOrUpdateProperty(ctx context.Context, refType PropertyType, refID int64, name, value string) error {
|
||||
pp := PackageProperty{RefType: refType, RefID: refID, Name: name}
|
||||
ok, err := db.GetEngine(ctx).Get(&pp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ok {
|
||||
_, err = db.GetEngine(ctx).Where("ref_type=? AND ref_id=? AND name=?", refType, refID, name).Cols("value").Update(&PackageProperty{Value: value})
|
||||
return err
|
||||
}
|
||||
_, err = InsertProperty(ctx, refType, refID, name, value)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteAllProperties deletes all properties of a ref
|
||||
func DeleteAllProperties(ctx context.Context, refType PropertyType, refID int64) error {
|
||||
_, err := db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ?", refType, refID).Delete(&PackageProperty{})
|
||||
|
|
@ -78,8 +92,8 @@ func DeletePropertyByID(ctx context.Context, propertyID int64) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// DeletePropertyByName deletes properties by name
|
||||
func DeletePropertyByName(ctx context.Context, refType PropertyType, refID int64, name string) error {
|
||||
// DeletePropertiesByName deletes properties by name
|
||||
func DeletePropertiesByName(ctx context.Context, refType PropertyType, refID int64, name string) error {
|
||||
_, err := db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ? AND name = ?", refType, refID, name).Delete(&PackageProperty{})
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"xorm.io/builder"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
// ErrDuplicatePackageVersion indicates a duplicated package version error
|
||||
|
|
@ -187,7 +188,7 @@ type PackageSearchOptions struct {
|
|||
HasFileWithName string // only results are found which are associated with a file with the specific name
|
||||
HasFiles optional.Option[bool] // only results are found which have associated files
|
||||
Sort VersionSort
|
||||
db.Paginator
|
||||
Paginator db.Paginator
|
||||
}
|
||||
|
||||
func (opts *PackageSearchOptions) ToConds() builder.Cond {
|
||||
|
|
@ -282,6 +283,18 @@ func (opts *PackageSearchOptions) configureOrderBy(e db.Engine) {
|
|||
e.Desc("package_version.id") // Sort by id for stable order with duplicates in the other field
|
||||
}
|
||||
|
||||
func searchVersionsBySession(sess *xorm.Session, opts *PackageSearchOptions) ([]*PackageVersion, int64, error) {
|
||||
opts.configureOrderBy(sess)
|
||||
pvs := make([]*PackageVersion, 0, 10)
|
||||
if opts.Paginator != nil {
|
||||
sess = db.SetSessionPagination(sess, opts.Paginator)
|
||||
count, err := sess.FindAndCount(&pvs)
|
||||
return pvs, count, err
|
||||
}
|
||||
err := sess.Find(&pvs)
|
||||
return pvs, int64(len(pvs)), err
|
||||
}
|
||||
|
||||
// SearchVersions gets all versions of packages matching the search options
|
||||
func SearchVersions(ctx context.Context, opts *PackageSearchOptions) ([]*PackageVersion, int64, error) {
|
||||
sess := db.GetEngine(ctx).
|
||||
|
|
@ -289,16 +302,7 @@ func SearchVersions(ctx context.Context, opts *PackageSearchOptions) ([]*Package
|
|||
Table("package_version").
|
||||
Join("INNER", "package", "package.id = package_version.package_id").
|
||||
Where(opts.ToConds())
|
||||
|
||||
opts.configureOrderBy(sess)
|
||||
|
||||
if opts.Paginator != nil {
|
||||
sess = db.SetSessionPagination(sess, opts)
|
||||
}
|
||||
|
||||
pvs := make([]*PackageVersion, 0, 10)
|
||||
count, err := sess.FindAndCount(&pvs)
|
||||
return pvs, count, err
|
||||
return searchVersionsBySession(sess, opts)
|
||||
}
|
||||
|
||||
// SearchLatestVersions gets the latest version of every package matching the search options
|
||||
|
|
@ -316,15 +320,7 @@ func SearchLatestVersions(ctx context.Context, opts *PackageSearchOptions) ([]*P
|
|||
Join("INNER", "package", "package.id = package_version.package_id").
|
||||
Where(builder.In("package_version.id", in))
|
||||
|
||||
opts.configureOrderBy(sess)
|
||||
|
||||
if opts.Paginator != nil {
|
||||
sess = db.SetSessionPagination(sess, opts)
|
||||
}
|
||||
|
||||
pvs := make([]*PackageVersion, 0, 10)
|
||||
count, err := sess.FindAndCount(&pvs)
|
||||
return pvs, count, err
|
||||
return searchVersionsBySession(sess, opts)
|
||||
}
|
||||
|
||||
// ExistVersion checks if a version matching the search options exist
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ func Test_NewColumn(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Len(t, columns, 3)
|
||||
|
||||
for i := 0; i < maxProjectColumns-3; i++ {
|
||||
for i := range maxProjectColumns - 3 {
|
||||
err := NewColumn(db.DefaultContext, &Column{
|
||||
Title: fmt.Sprintf("column-%d", i+4),
|
||||
ProjectID: project1.ID,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ package pull
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
|
@ -100,9 +101,7 @@ func mergeFiles(oldFiles, newFiles map[string]ViewedState) map[string]ViewedStat
|
|||
return oldFiles
|
||||
}
|
||||
|
||||
for file, viewed := range newFiles {
|
||||
oldFiles[file] = viewed
|
||||
}
|
||||
maps.Copy(oldFiles, newFiles)
|
||||
return oldFiles
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ func AddReleaseAttachments(ctx context.Context, releaseID int64, attachmentUUIDs
|
|||
}
|
||||
attachments[i].ReleaseID = releaseID
|
||||
// No assign value could be 0, so ignore AllCols().
|
||||
if _, err = db.GetEngine(ctx).ID(attachments[i].ID).Update(attachments[i]); err != nil {
|
||||
if _, err = db.GetEngine(ctx).ID(attachments[i].ID).Cols("release_id").Update(attachments[i]); err != nil {
|
||||
return fmt.Errorf("update attachment [%d]: %w", attachments[i].ID, err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -653,7 +653,7 @@ func (repo *Repository) AllowsPulls(ctx context.Context) bool {
|
|||
|
||||
// CanEnableEditor returns true if repository meets the requirements of web editor.
|
||||
func (repo *Repository) CanEnableEditor() bool {
|
||||
return !repo.IsMirror
|
||||
return !repo.IsMirror && !repo.IsArchived
|
||||
}
|
||||
|
||||
// DescriptionHTML does special handles to description and return HTML string.
|
||||
|
|
|
|||
|
|
@ -449,7 +449,7 @@ func SearchRepositoryCondition(opts SearchRepoOptions) builder.Cond {
|
|||
if opts.Keyword != "" {
|
||||
// separate keyword
|
||||
subQueryCond := builder.NewCond()
|
||||
for _, v := range strings.Split(opts.Keyword, ",") {
|
||||
for v := range strings.SplitSeq(opts.Keyword, ",") {
|
||||
if opts.TopicOnly {
|
||||
subQueryCond = subQueryCond.Or(builder.Eq{"topic.name": strings.ToLower(v)})
|
||||
} else {
|
||||
|
|
@ -464,7 +464,7 @@ func SearchRepositoryCondition(opts SearchRepoOptions) builder.Cond {
|
|||
keywordCond := builder.In("id", subQuery)
|
||||
if !opts.TopicOnly {
|
||||
likes := builder.NewCond()
|
||||
for _, v := range strings.Split(opts.Keyword, ",") {
|
||||
for v := range strings.SplitSeq(opts.Keyword, ",") {
|
||||
likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)})
|
||||
|
||||
// If the string looks like "org/repo", match against that pattern too
|
||||
|
|
|
|||
|
|
@ -185,10 +185,8 @@ func (cfg *ActionsConfig) IsWorkflowDisabled(file string) bool {
|
|||
}
|
||||
|
||||
func (cfg *ActionsConfig) DisableWorkflow(file string) {
|
||||
for _, workflow := range cfg.DisabledWorkflows {
|
||||
if file == workflow {
|
||||
return
|
||||
}
|
||||
if slices.Contains(cfg.DisabledWorkflows, file) {
|
||||
return
|
||||
}
|
||||
|
||||
cfg.DisabledWorkflows = append(cfg.DisabledWorkflows, file)
|
||||
|
|
|
|||
|
|
@ -42,12 +42,18 @@ func UpdateRepositoryUpdatedTime(ctx context.Context, repoID int64, updateTime t
|
|||
|
||||
// UpdateRepositoryColsWithAutoTime updates repository's columns
|
||||
func UpdateRepositoryColsWithAutoTime(ctx context.Context, repo *Repository, cols ...string) error {
|
||||
if len(cols) == 0 {
|
||||
return nil
|
||||
}
|
||||
_, err := db.GetEngine(ctx).ID(repo.ID).Cols(cols...).Update(repo)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateRepositoryColsNoAutoTime updates repository's columns and but applies time change automatically
|
||||
func UpdateRepositoryColsNoAutoTime(ctx context.Context, repo *Repository, cols ...string) error {
|
||||
if len(cols) == 0 {
|
||||
return nil
|
||||
}
|
||||
_, err := db.GetEngine(ctx).ID(repo.ID).Cols(cols...).NoAutoTime().Update(repo)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ func DeleteUploads(ctx context.Context, uploads ...*Upload) (err error) {
|
|||
defer committer.Close()
|
||||
|
||||
ids := make([]int64, len(uploads))
|
||||
for i := 0; i < len(uploads); i++ {
|
||||
for i := range uploads {
|
||||
ids[i] = uploads[i].ID
|
||||
}
|
||||
if err = db.DeleteByIDs[Upload](ctx, ids...); err != nil {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ package unit
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
|
|
@ -204,22 +205,12 @@ func LoadUnitConfig() error {
|
|||
|
||||
// UnitGlobalDisabled checks if unit type is global disabled
|
||||
func (u Type) UnitGlobalDisabled() bool {
|
||||
for _, ud := range DisabledRepoUnitsGet() {
|
||||
if u == ud {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(DisabledRepoUnitsGet(), u)
|
||||
}
|
||||
|
||||
// CanBeDefault checks if the unit type can be a default repo unit
|
||||
func (u *Type) CanBeDefault() bool {
|
||||
for _, nadU := range NotAllowedDefaultRepoUnits {
|
||||
if *u == nadU {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
return !slices.Contains(NotAllowedDefaultRepoUnits, *u)
|
||||
}
|
||||
|
||||
// Unit is a section of one repository
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
package user_test
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
|
|
@ -100,12 +101,7 @@ func TestListEmails(t *testing.T) {
|
|||
assert.Greater(t, count, int64(5))
|
||||
|
||||
contains := func(match func(s *user_model.SearchEmailResult) bool) bool {
|
||||
for _, v := range emails {
|
||||
if match(v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.ContainsFunc(emails, match)
|
||||
}
|
||||
|
||||
assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 18 }))
|
||||
|
|
|
|||
|
|
@ -831,6 +831,20 @@ type CountUserFilter struct {
|
|||
IsActive optional.Option[bool]
|
||||
}
|
||||
|
||||
// HasUsers checks whether there are any users in the database, or only one user exists.
|
||||
func HasUsers(ctx context.Context) (ret struct {
|
||||
HasAnyUser, HasOnlyOneUser bool
|
||||
}, err error,
|
||||
) {
|
||||
res, err := db.GetEngine(ctx).Table(&User{}).Cols("id").Limit(2).Query()
|
||||
if err != nil {
|
||||
return ret, fmt.Errorf("error checking user existence: %w", err)
|
||||
}
|
||||
ret.HasAnyUser = len(res) != 0
|
||||
ret.HasOnlyOneUser = len(res) == 1
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// CountUsers returns number of users.
|
||||
func CountUsers(ctx context.Context, opts *CountUserFilter) int64 {
|
||||
return countUsers(ctx, opts)
|
||||
|
|
|
|||
|
|
@ -17,10 +17,7 @@ func GetUsersMapByIDs(ctx context.Context, userIDs []int64) (map[int64]*User, er
|
|||
|
||||
left := len(userIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
err := db.GetEngine(ctx).
|
||||
In("id", userIDs[:limit]).
|
||||
Find(&userMaps)
|
||||
|
|
|
|||
|
|
@ -204,9 +204,9 @@ func TestHashPasswordDeterministic(t *testing.T) {
|
|||
b := make([]byte, 16)
|
||||
u := &user_model.User{}
|
||||
algos := hash.RecommendedHashAlgorithms
|
||||
for j := 0; j < len(algos); j++ {
|
||||
for j := range algos {
|
||||
u.PasswdHashAlgo = algos[j]
|
||||
for i := 0; i < 50; i++ {
|
||||
for range 50 {
|
||||
// generate a random password
|
||||
rand.Read(b)
|
||||
pass := string(b)
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ func CreateWebhooks(ctx context.Context, ws []*Webhook) error {
|
|||
if len(ws) == 0 {
|
||||
return nil
|
||||
}
|
||||
for i := 0; i < len(ws); i++ {
|
||||
for i := range ws {
|
||||
ws[i].Type = strings.TrimSpace(ws[i].Type)
|
||||
}
|
||||
return db.Insert(ctx, ws)
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ func TestWebhook_EventsArray(t *testing.T) {
|
|||
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
|
||||
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
|
||||
"pull_request_review_comment", "pull_request_sync", "pull_request_review_request", "wiki", "repository", "release",
|
||||
"package", "status", "workflow_job",
|
||||
"package", "status", "workflow_run", "workflow_job",
|
||||
},
|
||||
(&Webhook{
|
||||
HookEvent: &webhook_module.HookEvent{SendEverything: true},
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ package actions
|
|||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
|
|
@ -245,6 +246,10 @@ func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent web
|
|||
webhook_module.HookEventPackage:
|
||||
return matchPackageEvent(payload.(*api.PackagePayload), evt)
|
||||
|
||||
case // workflow_run
|
||||
webhook_module.HookEventWorkflowRun:
|
||||
return matchWorkflowRunEvent(payload.(*api.WorkflowRunPayload), evt)
|
||||
|
||||
default:
|
||||
log.Warn("unsupported event %q", triggedEvent)
|
||||
return false
|
||||
|
|
@ -564,21 +569,12 @@ func matchPullRequestReviewEvent(prPayload *api.PullRequestPayload, evt *jobpars
|
|||
actions = append(actions, "submitted", "edited")
|
||||
}
|
||||
|
||||
matched := false
|
||||
for _, val := range vals {
|
||||
for _, action := range actions {
|
||||
if glob.MustCompile(val, '/').Match(action) {
|
||||
matched = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if matched {
|
||||
if slices.ContainsFunc(actions, glob.MustCompile(val, '/').Match) {
|
||||
matchTimes++
|
||||
break
|
||||
}
|
||||
}
|
||||
if matched {
|
||||
matchTimes++
|
||||
}
|
||||
default:
|
||||
log.Warn("pull request review event unsupported condition %q", cond)
|
||||
}
|
||||
|
|
@ -613,21 +609,12 @@ func matchPullRequestReviewCommentEvent(prPayload *api.PullRequestPayload, evt *
|
|||
actions = append(actions, "created", "edited")
|
||||
}
|
||||
|
||||
matched := false
|
||||
for _, val := range vals {
|
||||
for _, action := range actions {
|
||||
if glob.MustCompile(val, '/').Match(action) {
|
||||
matched = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if matched {
|
||||
if slices.ContainsFunc(actions, glob.MustCompile(val, '/').Match) {
|
||||
matchTimes++
|
||||
break
|
||||
}
|
||||
}
|
||||
if matched {
|
||||
matchTimes++
|
||||
}
|
||||
default:
|
||||
log.Warn("pull request review comment event unsupported condition %q", cond)
|
||||
}
|
||||
|
|
@ -708,3 +695,53 @@ func matchPackageEvent(payload *api.PackagePayload, evt *jobparser.Event) bool {
|
|||
}
|
||||
return matchTimes == len(evt.Acts())
|
||||
}
|
||||
|
||||
func matchWorkflowRunEvent(payload *api.WorkflowRunPayload, evt *jobparser.Event) bool {
|
||||
// with no special filter parameters
|
||||
if len(evt.Acts()) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
matchTimes := 0
|
||||
// all acts conditions should be satisfied
|
||||
for cond, vals := range evt.Acts() {
|
||||
switch cond {
|
||||
case "types":
|
||||
action := payload.Action
|
||||
for _, val := range vals {
|
||||
if glob.MustCompile(val, '/').Match(action) {
|
||||
matchTimes++
|
||||
break
|
||||
}
|
||||
}
|
||||
case "workflows":
|
||||
workflow := payload.Workflow
|
||||
patterns, err := workflowpattern.CompilePatterns(vals...)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if !workflowpattern.Skip(patterns, []string{workflow.Name}, &workflowpattern.EmptyTraceWriter{}) {
|
||||
matchTimes++
|
||||
}
|
||||
case "branches":
|
||||
patterns, err := workflowpattern.CompilePatterns(vals...)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if !workflowpattern.Skip(patterns, []string{payload.WorkflowRun.HeadBranch}, &workflowpattern.EmptyTraceWriter{}) {
|
||||
matchTimes++
|
||||
}
|
||||
case "branches-ignore":
|
||||
patterns, err := workflowpattern.CompilePatterns(vals...)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if !workflowpattern.Filter(patterns, []string{payload.WorkflowRun.HeadBranch}, &workflowpattern.EmptyTraceWriter{}) {
|
||||
matchTimes++
|
||||
}
|
||||
default:
|
||||
log.Warn("workflow run event unsupported condition %q", cond)
|
||||
}
|
||||
}
|
||||
return matchTimes == len(evt.Acts())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ func Generate(n int) (string, error) {
|
|||
buffer := make([]byte, n)
|
||||
maxInt := big.NewInt(int64(len(validChars)))
|
||||
for {
|
||||
for j := 0; j < n; j++ {
|
||||
for j := range n {
|
||||
rnd, err := rand.Int(rand.Reader, maxInt)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ func TestComplexity_Generate(t *testing.T) {
|
|||
|
||||
test := func(t *testing.T, modes []string) {
|
||||
testComplextity(modes)
|
||||
for i := 0; i < maxCount; i++ {
|
||||
for range maxCount {
|
||||
pwd, err := Generate(pwdLen)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, pwd, pwdLen)
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ func (c *Client) CheckPassword(pw string, padding bool) (int, error) {
|
|||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
for _, pair := range strings.Split(string(body), "\n") {
|
||||
for pair := range strings.SplitSeq(string(body), "\n") {
|
||||
parts := strings.Split(pair, ":")
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ func drawBlock(img *image.Paletted, x, y, size, angle int, points []int) {
|
|||
rotate(points, m, m, angle)
|
||||
}
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
for j := 0; j < size; j++ {
|
||||
for i := range size {
|
||||
for j := range size {
|
||||
if pointInPolygon(i, j, points) {
|
||||
img.SetColorIndex(x+i, y+j, 1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ func drawBlocks(p *image.Paletted, size int, c, b1, b2 blockFunc, b1Angle, b2Ang
|
|||
|
||||
// then we make it left-right mirror, so we didn't draw 3/6/9 before
|
||||
for x := 0; x < size/2; x++ {
|
||||
for y := 0; y < size; y++ {
|
||||
for y := range size {
|
||||
p.SetColorIndex(size-x, y, p.ColorIndexAt(x, y))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ func Init() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := 0; i < 10; i++ {
|
||||
for range 10 {
|
||||
if err = c.Ping(); err == nil {
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ func DetectEncoding(content []byte) (string, error) {
|
|||
}
|
||||
times := 1024 / len(content)
|
||||
detectContent = make([]byte, 0, times*len(content))
|
||||
for i := 0; i < times; i++ {
|
||||
for range times {
|
||||
detectContent = append(detectContent, content...)
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ func stringMustEndWith(t *testing.T, expected, value string) {
|
|||
func TestToUTF8WithFallbackReader(t *testing.T) {
|
||||
resetDefaultCharsetsOrder()
|
||||
|
||||
for testLen := 0; testLen < 2048; testLen++ {
|
||||
for testLen := range 2048 {
|
||||
pattern := " test { () }\n"
|
||||
input := ""
|
||||
for len(input) < testLen {
|
||||
|
|
|
|||
|
|
@ -277,8 +277,8 @@ func NewSearchCommitsOptions(searchString string, forAllRefs bool) SearchCommits
|
|||
var keywords, authors, committers []string
|
||||
var after, before string
|
||||
|
||||
fields := strings.Fields(searchString)
|
||||
for _, k := range fields {
|
||||
fields := strings.FieldsSeq(searchString)
|
||||
for k := range fields {
|
||||
switch {
|
||||
case strings.HasPrefix(k, "author:"):
|
||||
authors = append(authors, strings.TrimPrefix(k, "author:"))
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ package git
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"path"
|
||||
"sort"
|
||||
|
||||
|
|
@ -40,9 +39,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
for pth, found := range commits {
|
||||
revs[pth] = found
|
||||
}
|
||||
maps.Copy(revs, commits)
|
||||
}
|
||||
} else {
|
||||
sort.Strings(entryPaths)
|
||||
|
|
@ -124,48 +121,25 @@ func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
batchStdinWriter, batchReader, cancel, err := commit.repo.CatFileBatch(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
commitsMap := map[string]*Commit{}
|
||||
commitsMap[commit.ID.String()] = commit
|
||||
|
||||
commitCommits := map[string]*Commit{}
|
||||
for path, commitID := range revs {
|
||||
if len(commitID) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
c, ok := commitsMap[commitID]
|
||||
if ok {
|
||||
commitCommits[path] = c
|
||||
continue
|
||||
}
|
||||
|
||||
if len(commitID) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
_, err := batchStdinWriter.Write([]byte(commitID + "\n"))
|
||||
c, err := commit.repo.GetCommit(commitID) // Ensure the commit exists in the repository
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, typ, size, err := ReadBatchLine(batchReader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if typ != "commit" {
|
||||
if err := DiscardFull(batchReader, size+1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected type: %s for commit id: %s", typ, commitID)
|
||||
}
|
||||
c, err = CommitFromReader(commit.repo, MustIDFromString(commitID), io.LimitReader(batchReader, size))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := batchReader.Discard(1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
commitCommits[path] = c
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ func TestCutDiffAroundLine(t *testing.T) {
|
|||
}
|
||||
|
||||
func BenchmarkCutDiffAroundLine(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
for b.Loop() {
|
||||
CutDiffAroundLine(strings.NewReader(exampleDiff), 3, true, 3)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ func (f Format) Parser(r io.Reader) *Parser {
|
|||
// would turn into "%0a%00".
|
||||
func (f Format) hexEscaped(delim []byte) string {
|
||||
escaped := ""
|
||||
for i := 0; i < len(delim); i++ {
|
||||
for i := range delim {
|
||||
escaped += "%" + hex.EncodeToString([]byte{delim[i]})
|
||||
}
|
||||
return escaped
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
|
@ -25,12 +26,7 @@ var ErrNotValidHook = errors.New("not a valid Git hook")
|
|||
|
||||
// IsValidHookName returns true if given name is a valid Git hook.
|
||||
func IsValidHookName(name string) bool {
|
||||
for _, hn := range hookNames {
|
||||
if hn == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(hookNames, name)
|
||||
}
|
||||
|
||||
// Hook represents a Git hook.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import (
|
|||
)
|
||||
|
||||
func getCacheKey(repoPath, commitID, entryPath string) string {
|
||||
hashBytes := sha256.Sum256([]byte(fmt.Sprintf("%s:%s:%s", repoPath, commitID, entryPath)))
|
||||
hashBytes := sha256.Sum256(fmt.Appendf(nil, "%s:%s:%s", repoPath, commitID, entryPath))
|
||||
return fmt.Sprintf("last_commit:%x", hashBytes)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -346,10 +346,7 @@ func WalkGitLog(ctx context.Context, repo *Repository, head *Commit, treepath st
|
|||
|
||||
results := make([]string, len(paths))
|
||||
remaining := len(paths)
|
||||
nextRestart := (len(paths) * 3) / 4
|
||||
if nextRestart > 70 {
|
||||
nextRestart = 70
|
||||
}
|
||||
nextRestart := min((len(paths)*3)/4, 70)
|
||||
lastEmptyParent := head.ID.String()
|
||||
commitSinceLastEmptyParent := uint64(0)
|
||||
commitSinceNextRestart := uint64(0)
|
||||
|
|
|
|||
|
|
@ -109,8 +109,8 @@ func (ref RefName) IsFor() bool {
|
|||
}
|
||||
|
||||
func (ref RefName) nameWithoutPrefix(prefix string) string {
|
||||
if strings.HasPrefix(string(ref), prefix) {
|
||||
return strings.TrimPrefix(string(ref), prefix)
|
||||
if after, ok := strings.CutPrefix(string(ref), prefix); ok {
|
||||
return after
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,9 +44,9 @@ func (repo *Repository) parsePrettyFormatLogToList(logs []byte) ([]*Commit, erro
|
|||
return commits, nil
|
||||
}
|
||||
|
||||
parts := bytes.Split(logs, []byte{'\n'})
|
||||
parts := bytes.SplitSeq(logs, []byte{'\n'})
|
||||
|
||||
for _, commitID := range parts {
|
||||
for commitID := range parts {
|
||||
commit, err := repo.GetCommit(string(commitID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -547,11 +547,11 @@ func (repo *Repository) GetCommitBranchStart(env []string, branch, endCommitID s
|
|||
return "", runErr
|
||||
}
|
||||
|
||||
parts := bytes.Split(bytes.TrimSpace(stdout), []byte{'\n'})
|
||||
parts := bytes.SplitSeq(bytes.TrimSpace(stdout), []byte{'\n'})
|
||||
|
||||
// check the commits one by one until we find a commit contained by another branch
|
||||
// and we think this commit is the divergence point
|
||||
for _, commitID := range parts {
|
||||
for commitID := range parts {
|
||||
branches, err := repo.getBranches(env, string(commitID), 2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ func (repo *Repository) LsFiles(filenames ...string) ([]string, error) {
|
|||
return nil, err
|
||||
}
|
||||
filelist := make([]string, 0, len(filenames))
|
||||
for _, line := range bytes.Split(res, []byte{'\000'}) {
|
||||
for line := range bytes.SplitSeq(res, []byte{'\000'}) {
|
||||
filelist = append(filelist, string(line))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ func (repo *Repository) GetTagNameBySHA(sha string) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
tagRefs := strings.Split(stdout, "\n")
|
||||
for _, tagRef := range tagRefs {
|
||||
tagRefs := strings.SplitSeq(stdout, "\n")
|
||||
for tagRef := range tagRefs {
|
||||
if len(strings.TrimSpace(tagRef)) > 0 {
|
||||
fields := strings.Fields(tagRef)
|
||||
if strings.HasPrefix(fields[0], sha) && strings.HasPrefix(fields[1], TagPrefix) {
|
||||
|
|
@ -62,7 +62,7 @@ func (repo *Repository) GetTagID(name string) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
// Make sure exact match is used: "v1" != "release/v1"
|
||||
for _, line := range strings.Split(stdout, "\n") {
|
||||
for line := range strings.SplitSeq(stdout, "\n") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) == 2 && fields[1] == "refs/tags/"+name {
|
||||
return fields[0], nil
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ func (repo *Repository) LsTree(ref string, filenames ...string) ([]string, error
|
|||
return nil, err
|
||||
}
|
||||
filelist := make([]string, 0, len(filenames))
|
||||
for _, line := range bytes.Split(res, []byte{'\000'}) {
|
||||
for line := range bytes.SplitSeq(res, []byte{'\000'}) {
|
||||
filelist = append(filelist, string(line))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ func (te *TreeEntry) FollowLinks(optLimit ...int) (*TreeEntry, error) {
|
|||
}
|
||||
limit := util.OptionalArg(optLimit, 10)
|
||||
entry := te
|
||||
for i := 0; i < limit; i++ {
|
||||
for range limit {
|
||||
if !entry.IsLink() {
|
||||
break
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue