diff --git a/.github/workflows/pull-compliance.yml b/.github/workflows/pull-compliance.yml index c93aed05f4c..b4f5002082c 100644 --- a/.github/workflows/pull-compliance.yml +++ b/.github/workflows/pull-compliance.yml @@ -122,7 +122,7 @@ jobs: go-version-file: go.mod check-latest: true - run: make deps-backend deps-tools - - run: make lint-go-windows lint-go-gitea-vet + - run: make lint-go-windows env: TAGS: bindata sqlite sqlite_unlock_notify GOOS: windows diff --git a/.golangci.yml b/.golangci.yml index afd91d65e59..570942bdd32 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -13,6 +13,7 @@ linters: - forbidigo - gocheckcompilerdirectives - gocritic + - goheader - govet - ineffassign - mirror @@ -51,6 +52,14 @@ linters: desc: do not use the go-chi cache package, use gitea's cache system - pkg: github.com/pkg/errors desc: use builtin errors package instead + migrations: + files: + - '**/models/migrations/**/*.go' + deny: + - pkg: code.gitea.io/gitea/models$ + desc: migrations must not depend on the models package + - pkg: code.gitea.io/gitea/modules/structs + desc: migrations must not depend on modules/structs (API structures change over time) nolintlint: allow-unused: false require-explanation: true @@ -109,6 +118,11 @@ linters: enable: - nilness - unusedwrite + goheader: + values: + regexp: + HEADER: '((Copyright [^\n]+|All rights reserved\.)\n)*Copyright \d{4} (The (Gogs|Gitea) Authors|Gitea Authors|Gitea)\.( All rights reserved\.)?(\n(Copyright [^\n]+|All rights reserved\.))*\nSPDX-License-Identifier: [\w.-]+' + template: '{{ HEADER }}' exclusions: generated: lax presets: @@ -158,9 +172,16 @@ issues: max-same-issues: 0 formatters: enable: - - gofmt + - gci - gofumpt settings: + gci: + custom-order: true + sections: + - standard + - prefix(code.gitea.io/gitea) + - blank + - default gofumpt: extra-rules: true exclusions: @@ -170,9 +191,6 @@ formatters: - .venv - public - web_src - - third_party$ - - builtin$ - - examples$ run: timeout: 10m diff --git a/Makefile b/Makefile index 8c73dc350d4..e621cc362fc 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,6 @@ XGO_VERSION := go-1.25.x AIR_PACKAGE ?= github.com/air-verse/air@v1 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3 -GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.9.2 GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.4 GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.15 MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.8.0 @@ -206,7 +205,7 @@ clean: ## delete backend and integration files .PHONY: fmt fmt: ## format the Go and template code - @GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run tools/code-batch-process.go gitea-fmt -w '{file-list}' + $(GO) run $(GOLANGCI_LINT_PACKAGE) fmt $(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl')) @# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only @# whitespace before it @@ -278,10 +277,10 @@ lint-frontend: lint-js lint-css ## lint frontend files lint-frontend-fix: lint-js-fix lint-css-fix ## lint frontend files and fix issues .PHONY: lint-backend -lint-backend: lint-go lint-go-gitea-vet lint-editorconfig ## lint backend files +lint-backend: lint-go lint-editorconfig ## lint backend files .PHONY: lint-backend-fix -lint-backend-fix: lint-go-fix lint-go-gitea-vet lint-editorconfig ## lint backend files and fix issues +lint-backend-fix: lint-go-fix lint-editorconfig ## lint backend files and fix issues .PHONY: lint-js lint-js: node_modules ## lint js and ts files @@ -336,11 +335,6 @@ lint-go-windows: @GOOS= GOARCH= $(GO) install $(GOLANGCI_LINT_PACKAGE) golangci-lint run -.PHONY: lint-go-gitea-vet -lint-go-gitea-vet: ## lint go files with gitea-vet - @echo "Running gitea-vet..." - @$(GO) vet -vettool="$(shell GOOS= GOARCH= go tool -n gitea-vet)" ./... - .PHONY: lint-editorconfig lint-editorconfig: @echo "Running editorconfig check..." @@ -730,7 +724,6 @@ deps-backend: ## install backend dependencies deps-tools: ## install tool dependencies $(GO) install $(AIR_PACKAGE) & \ $(GO) install $(EDITORCONFIG_CHECKER_PACKAGE) & \ - $(GO) install $(GOFUMPT_PACKAGE) & \ $(GO) install $(GOLANGCI_LINT_PACKAGE) & \ $(GO) install $(GXZ_PACKAGE) & \ $(GO) install $(MISSPELL_PACKAGE) & \ diff --git a/go.mod b/go.mod index 4efce828a1c..d87bf6840c2 100644 --- a/go.mod +++ b/go.mod @@ -129,7 +129,6 @@ require ( require ( cloud.google.com/go/compute/metadata v0.9.0 // indirect - code.gitea.io/gitea-vet v0.2.3 // indirect dario.cat/mergo v1.0.2 // indirect filippo.io/edwards25519 v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect @@ -306,5 +305,3 @@ replace github.com/Azure/azure-sdk-for-go/sdk/azcore => github.com/Azure/azure-s replace github.com/Azure/azure-sdk-for-go/sdk/storage/azblob => github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 // v1.6.4+ uses API version unsupported by Azurite in CI replace github.com/microsoft/go-mssqldb => github.com/microsoft/go-mssqldb v1.9.7 // downgraded with Azure SDK - -tool code.gitea.io/gitea-vet diff --git a/go.sum b/go.sum index 2392b4ab3fd..ee60fd36e43 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,6 @@ cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdB cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= code.gitea.io/actions-proto-go v0.4.1 h1:l0EYhjsgpUe/1VABo2eK7zcoNX2W44WOnb0MSLrKfls= code.gitea.io/actions-proto-go v0.4.1/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas= -code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI= -code.gitea.io/gitea-vet v0.2.3/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE= code.gitea.io/sdk/gitea v0.24.1 h1:hpaqcdGcBmfMpV7JSbBJVwE99qo+WqGreJYKrDKEyW8= code.gitea.io/sdk/gitea v0.24.1/go.mod h1:5/77BL3sHneCMEiZaMT9lfTvnnibsYxyO48mceCF3qA= code.pfad.fr/check v1.1.0 h1:GWvjdzhSEgHvEHe2uJujDcpmZoySKuHQNrZMfzfO0bE= @@ -732,7 +730,6 @@ github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZ github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yohcop/openid-go v1.0.1 h1:DPRd3iPO5F6O5zX2e62XpVAbPT6wV51cuucH0z9g3js= github.com/yohcop/openid-go v1.0.1/go.mod h1:b/AvD03P0KHj4yuihb+VtLD6bYYgsy0zqBzPCRjkCNs= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -793,7 +790,6 @@ golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww= golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= @@ -805,7 +801,6 @@ golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -825,7 +820,6 @@ golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -899,7 +893,6 @@ golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200928182047-19e03678916f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/models/db/engine.go b/models/db/engine.go index b08799210e8..fbcc3fa15e8 100755 --- a/models/db/engine.go +++ b/models/db/engine.go @@ -11,11 +11,11 @@ import ( "reflect" "strings" - "xorm.io/xorm" - _ "github.com/go-sql-driver/mysql" // Needed for the MySQL driver _ "github.com/lib/pq" // Needed for the Postgresql driver _ "github.com/microsoft/go-mssqldb" // Needed for the MSSQL driver + + "xorm.io/xorm" ) var ( diff --git a/models/migrations/v1_19/v233.go b/models/migrations/v1_19/v233.go index 9eb6d405099..44ced874b32 100644 --- a/models/migrations/v1_19/v233.go +++ b/models/migrations/v1_19/v233.go @@ -9,7 +9,6 @@ import ( "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/secret" "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" "xorm.io/builder" "xorm.io/xorm" @@ -129,11 +128,11 @@ func AddHeaderAuthorizationEncryptedColWebhook(x *xorm.Engine) error { } type MatrixPayloadSafe struct { - Body string `json:"body"` - MsgType string `json:"msgtype"` - Format string `json:"format"` - FormattedBody string `json:"formatted_body"` - Commits []*api.PayloadCommit `json:"io.gitea.commits,omitempty"` + Body string `json:"body"` + MsgType string `json:"msgtype"` + Format string `json:"format"` + FormattedBody string `json:"formatted_body"` + Commits json.Value `json:"io.gitea.commits,omitempty"` } type MatrixPayloadUnsafe struct { MatrixPayloadSafe diff --git a/models/migrations/v1_26/v326.go b/models/migrations/v1_26/v326.go index 76532e2f858..dcf548bec0e 100644 --- a/models/migrations/v1_26/v326.go +++ b/models/migrations/v1_26/v326.go @@ -13,7 +13,6 @@ import ( "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" webhook_module "code.gitea.io/gitea/modules/webhook" "xorm.io/xorm" @@ -59,6 +58,29 @@ type migrationCommitStatus struct { TargetURL string } +// Frozen subsets of modules/structs payload types, decoded from stored +// action_run.event_payload values. Inlined so the migration is insulated +// from future field changes in modules/structs. +type migrationPayloadCommit struct { + ID string `json:"id"` +} + +type migrationPushPayload struct { + HeadCommit *migrationPayloadCommit `json:"head_commit"` +} + +type migrationPRBranchInfo struct { + Sha string `json:"sha"` +} + +type migrationPullRequest struct { + Head *migrationPRBranchInfo `json:"head"` +} + +type migrationPullRequestPayload struct { + PullRequest *migrationPullRequest `json:"pull_request"` +} + type commitSHAAndRuns struct { commitSHA string runs map[int64]*migrationActionRun @@ -292,22 +314,22 @@ func getCommitStatusCommitID(run *migrationActionRun) (string, error) { } } -func getPushEventPayload(run *migrationActionRun) (*api.PushPayload, error) { +func getPushEventPayload(run *migrationActionRun) (*migrationPushPayload, error) { if run.Event != webhook_module.HookEventPush { return nil, fmt.Errorf("event %s is not a push event", run.Event) } - var payload api.PushPayload + var payload migrationPushPayload if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil { return nil, err } return &payload, nil } -func getPullRequestEventPayload(run *migrationActionRun) (*api.PullRequestPayload, error) { +func getPullRequestEventPayload(run *migrationActionRun) (*migrationPullRequestPayload, error) { if !run.Event.IsPullRequest() && !run.Event.IsPullRequestReview() { return nil, fmt.Errorf("event %s is not a pull request event", run.Event) } - var payload api.PullRequestPayload + var payload migrationPullRequestPayload if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil { return nil, err } diff --git a/models/repo.go b/models/repo.go index c5c5364da01..34e7b108033 100644 --- a/models/repo.go +++ b/models/repo.go @@ -9,8 +9,6 @@ import ( "strconv" "strings" - _ "image/jpeg" // Needed for jpeg support - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" @@ -18,6 +16,8 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" + _ "image/jpeg" // Needed for jpeg support + "xorm.io/builder" ) diff --git a/models/user/user.go b/models/user/user.go index 0f4066378e8..c9dc59b5430 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -20,8 +20,6 @@ import ( "time" "unicode" - _ "image/jpeg" // Needed for jpeg support - "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/auth/openid" @@ -39,6 +37,8 @@ import ( "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/validation" + _ "image/jpeg" // Needed for jpeg support + "golang.org/x/text/runes" "golang.org/x/text/transform" "golang.org/x/text/unicode/norm" diff --git a/modules/avatar/avatar.go b/modules/avatar/avatar.go index 3b622b99af0..44c61e1ff67 100644 --- a/modules/avatar/avatar.go +++ b/modules/avatar/avatar.go @@ -11,15 +11,14 @@ import ( "image/color" "image/png" - _ "image/gif" // for processing gif images - _ "image/jpeg" // for processing jpeg images - "code.gitea.io/gitea/modules/avatar/identicon" "code.gitea.io/gitea/modules/setting" - "golang.org/x/image/draw" - _ "golang.org/x/image/webp" // for processing webp images + _ "image/gif" // for processing gif images + _ "image/jpeg" // for processing jpeg images + + "golang.org/x/image/draw" ) // DefaultAvatarSize is the target CSS pixel size for avatar generation. It is diff --git a/modules/graceful/manager_windows.go b/modules/graceful/manager_windows.go index 457768d6ca0..9592dd6b39c 100644 --- a/modules/graceful/manager_windows.go +++ b/modules/graceful/manager_windows.go @@ -1,5 +1,6 @@ // Copyright 2019 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT + // This code is heavily inspired by the archived gofacebook/gracenet/net.go handler //go:build windows diff --git a/modules/migration/schemas_bindata.go b/modules/migration/schemas_bindata.go index 2f0e2544081..d7c70815962 100644 --- a/modules/migration/schemas_bindata.go +++ b/modules/migration/schemas_bindata.go @@ -12,10 +12,10 @@ import ( "path" "sync" - _ "embed" - "code.gitea.io/gitea/modules/assetfs" + _ "embed" + "github.com/santhosh-tekuri/jsonschema/v6" ) diff --git a/modules/options/options_bindata.go b/modules/options/options_bindata.go index b2321d7eb50..f85f30065e2 100644 --- a/modules/options/options_bindata.go +++ b/modules/options/options_bindata.go @@ -10,9 +10,9 @@ package options import ( "sync" - _ "embed" - "code.gitea.io/gitea/modules/assetfs" + + _ "embed" ) //go:embed bindata.dat diff --git a/modules/session/redis.go b/modules/session/redis.go index 083869f4e1e..f5cac8e636c 100644 --- a/modules/session/redis.go +++ b/modules/session/redis.go @@ -1,18 +1,6 @@ // Copyright 2013 Beego Authors // Copyright 2014 The Macaron Authors // Copyright 2020 The Gitea Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. // SPDX-License-Identifier: Apache-2.0 package session diff --git a/modules/templates/templates_bindata.go b/modules/templates/templates_bindata.go index a919591ecfd..0399b2c49ac 100644 --- a/modules/templates/templates_bindata.go +++ b/modules/templates/templates_bindata.go @@ -10,9 +10,9 @@ package templates import ( "sync" - _ "embed" - "code.gitea.io/gitea/modules/assetfs" + + _ "embed" ) //go:embed bindata.dat diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index 7f59e6b3893..b455f918456 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -16,10 +16,6 @@ import ( "strings" "time" - _ "image/gif" // for processing gif images - _ "image/jpeg" // for processing jpeg images - _ "image/png" // for processing png images - activities_model "code.gitea.io/gitea/models/activities" admin_model "code.gitea.io/gitea/models/admin" asymkey_model "code.gitea.io/gitea/models/asymkey" @@ -46,6 +42,9 @@ import ( _ "golang.org/x/image/bmp" // for processing bmp images _ "golang.org/x/image/webp" // for processing webp images + _ "image/gif" // for processing gif images + _ "image/jpeg" // for processing jpeg images + _ "image/png" // for processing png images ) const ( diff --git a/routers/web/web.go b/routers/web/web.go index 879a6f3afd6..1dff6cbc04e 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -45,7 +45,7 @@ import ( "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/forms" - _ "code.gitea.io/gitea/modules/session" // to registers all internal adapters + _ "code.gitea.io/gitea/modules/session" // to register all internal adapters "gitea.com/go-chi/captcha" chi_middleware "github.com/go-chi/chi/v5/middleware" diff --git a/services/user/delete.go b/services/user/delete.go index 39c6ef052dc..6047694b0c6 100644 --- a/services/user/delete.go +++ b/services/user/delete.go @@ -8,8 +8,6 @@ import ( "fmt" "time" - _ "image/jpeg" // Needed for jpeg support - actions_model "code.gitea.io/gitea/models/actions" activities_model "code.gitea.io/gitea/models/activities" asymkey_model "code.gitea.io/gitea/models/asymkey" @@ -24,6 +22,8 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" + _ "image/jpeg" // Needed for jpeg support + "xorm.io/builder" ) diff --git a/tests/integration/migration-test/migration_test.go b/tests/integration/migration-test/migration_test.go index 2e25afb43c0..5d240263801 100644 --- a/tests/integration/migration-test/migration_test.go +++ b/tests/integration/migration-test/migration_test.go @@ -27,6 +27,7 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/testlogger" "code.gitea.io/gitea/modules/util" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "xorm.io/xorm" diff --git a/tools/code-batch-process.go b/tools/code-batch-process.go deleted file mode 100644 index 5030d8bbc3d..00000000000 --- a/tools/code-batch-process.go +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2021 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -//go:build ignore - -package main - -import ( - "fmt" - "log" - "os" - "os/exec" - "path/filepath" - "regexp" - "slices" - "strconv" - "strings" - - "code.gitea.io/gitea/tools/codeformat" -) - -// Windows has a limitation for command line arguments, the size can not exceed 32KB. -// So we have to feed the files to some tools (like gofmt) batch by batch - -// We also introduce a `gitea-fmt` command, it does better import formatting than gofmt/goimports. `gitea-fmt` calls `gofmt` internally. - -var optionLogVerbose bool - -func logVerbose(msg string, args ...any) { - if optionLogVerbose { - log.Printf(msg, args...) - } -} - -func passThroughCmd(cmd string, args []string) error { - foundCmd, err := exec.LookPath(cmd) - if err != nil { - log.Fatalf("can not find cmd: %s", cmd) - } - c := exec.Cmd{ - Path: foundCmd, - Args: append([]string{cmd}, args...), - Stdin: os.Stdin, - Stdout: os.Stdout, - Stderr: os.Stderr, - } - return c.Run() -} - -type fileCollector struct { - dirs []string - includePatterns []*regexp.Regexp - excludePatterns []*regexp.Regexp - batchSize int -} - -func newFileCollector(fileFilter string, batchSize int) (*fileCollector, error) { - co := &fileCollector{batchSize: batchSize} - if fileFilter == "go-own" { - co.dirs = []string{ - "build", - "cmd", - "contrib", - "tests", - "models", - "modules", - "routers", - "services", - } - co.includePatterns = append(co.includePatterns, regexp.MustCompile(`.*\.go$`)) - - co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`.*\bbindata\.go$`)) - co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`\.pb\.go$`)) - co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/gitea-repositories-meta`)) - co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/integration/migration-test`)) - co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`modules/git/tests`)) - co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`models/fixtures`)) - co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`models/migrations/fixtures`)) - co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`services/gitdiff/testdata`)) - } - - if co.dirs == nil { - return nil, fmt.Errorf("unknown file-filter: %s", fileFilter) - } - return co, nil -} - -func (fc *fileCollector) matchPatterns(path string, regexps []*regexp.Regexp) bool { - path = strings.ReplaceAll(path, "\\", "/") - for _, re := range regexps { - if re.MatchString(path) { - return true - } - } - return false -} - -func (fc *fileCollector) collectFiles() (res [][]string, err error) { - var batch []string - for _, dir := range fc.dirs { - err = filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { - include := len(fc.includePatterns) == 0 || fc.matchPatterns(path, fc.includePatterns) - exclude := fc.matchPatterns(path, fc.excludePatterns) - process := include && !exclude - if !process { - if d.IsDir() { - if exclude { - logVerbose("exclude dir %s", path) - return filepath.SkipDir - } - // for a directory, if it is not excluded explicitly, we should walk into - return nil - } - // for a file, we skip it if it shouldn't be processed - logVerbose("skip process %s", path) - return nil - } - if d.IsDir() { - // skip dir, we don't add dirs to the file list now - return nil - } - if len(batch) >= fc.batchSize { - res = append(res, batch) - batch = nil - } - batch = append(batch, path) - return nil - }) - if err != nil { - return nil, err - } - } - res = append(res, batch) - return res, nil -} - -// substArgFiles expands the {file-list} to a real file list for commands -func substArgFiles(args, files []string) []string { - for i, s := range args { - if s == "{file-list}" { - newArgs := append(args[:i], files...) - newArgs = append(newArgs, args[i+1:]...) - return newArgs - } - } - return args -} - -func exitWithCmdErrors(subCmd string, subArgs []string, cmdErrors []error) { - for _, err := range cmdErrors { - if err != nil { - if exitError, ok := err.(*exec.ExitError); ok { - exitCode := exitError.ExitCode() - log.Printf("run command failed (code=%d): %s %v", exitCode, subCmd, subArgs) - os.Exit(exitCode) - } else { - log.Fatalf("run command failed (err=%s) %s %v", err, subCmd, subArgs) - } - } - } -} - -func parseArgs() (mainOptions map[string]string, subCmd string, subArgs []string) { - mainOptions = map[string]string{} - for i := 1; i < len(os.Args); i++ { - arg := os.Args[i] - if arg == "" { - break - } - if arg[0] == '-' { - arg = strings.TrimPrefix(arg, "-") - arg = strings.TrimPrefix(arg, "-") - fields := strings.SplitN(arg, "=", 2) - if len(fields) == 1 { - mainOptions[fields[0]] = "1" - } else { - mainOptions[fields[0]] = fields[1] - } - } else { - subCmd = arg - subArgs = os.Args[i+1:] - break - } - } - return mainOptions, subCmd, subArgs -} - -func showUsage() { - fmt.Printf(`Usage: %[1]s [options] {command} [arguments] - -Options: - --verbose - --file-filter=go-own - --batch-size=100 - -Commands: - %[1]s gofmt ... - -Arguments: - {file-list} the file list - -Example: - %[1]s gofmt -s -d {file-list} - -`, "file-batch-exec") -} - -func newFileCollectorFromMainOptions(mainOptions map[string]string) (fc *fileCollector, err error) { - fileFilter := mainOptions["file-filter"] - if fileFilter == "" { - fileFilter = "go-own" - } - batchSize, _ := strconv.Atoi(mainOptions["batch-size"]) - if batchSize == 0 { - batchSize = 100 - } - - return newFileCollector(fileFilter, batchSize) -} - -func giteaFormatGoImports(files []string, doWriteFile bool) error { - for _, file := range files { - if err := codeformat.FormatGoImports(file, doWriteFile); err != nil { - log.Printf("failed to format go imports: %s, err=%v", file, err) - return err - } - } - return nil -} - -func main() { - mainOptions, subCmd, subArgs := parseArgs() - if subCmd == "" { - showUsage() - os.Exit(1) - } - optionLogVerbose = mainOptions["verbose"] != "" - - fc, err := newFileCollectorFromMainOptions(mainOptions) - if err != nil { - log.Fatalf("can not create file collector: %s", err.Error()) - } - - fileBatches, err := fc.collectFiles() - if err != nil { - log.Fatalf("can not collect files: %s", err.Error()) - } - - processed := 0 - var cmdErrors []error - for _, files := range fileBatches { - if len(files) == 0 { - break - } - substArgs := substArgFiles(subArgs, files) - logVerbose("batch cmd: %s %v", subCmd, substArgs) - switch subCmd { - case "gitea-fmt": - if slices.Contains(subArgs, "-d") { - log.Print("the -d option is not supported by gitea-fmt") - } - cmdErrors = append(cmdErrors, giteaFormatGoImports(files, slices.Contains(subArgs, "-w"))) - cmdErrors = append(cmdErrors, passThroughCmd("gofmt", append([]string{"-w", "-r", "interface{} -> any"}, substArgs...))) - cmdErrors = append(cmdErrors, passThroughCmd("go", append([]string{"run", os.Getenv("GOFUMPT_PACKAGE"), "-extra"}, substArgs...))) - default: - log.Fatalf("unknown cmd: %s %v", subCmd, subArgs) - } - processed += len(files) - } - - logVerbose("processed %d files", processed) - exitWithCmdErrors(subCmd, subArgs, cmdErrors) -} diff --git a/tools/codeformat/formatimports.go b/tools/codeformat/formatimports.go deleted file mode 100644 index c9fc2a27b4a..00000000000 --- a/tools/codeformat/formatimports.go +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2021 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package codeformat - -import ( - "bytes" - "errors" - "io" - "os" - "sort" - "strings" -) - -var importPackageGroupOrders = map[string]int{ - "": 1, // internal - "code.gitea.io/gitea/": 2, -} - -var errInvalidCommentBetweenImports = errors.New("comments between imported packages are invalid, please move comments to the end of the package line") - -var ( - importBlockBegin = []byte("\nimport (\n") - importBlockEnd = []byte("\n)") -) - -type importLineParsed struct { - group string - pkg string - content string -} - -func parseImportLine(line string) (*importLineParsed, error) { - il := &importLineParsed{content: line} - p1 := strings.IndexRune(line, '"') - if p1 == -1 { - return nil, errors.New("invalid import line: " + line) - } - p1++ - p := strings.IndexRune(line[p1:], '"') - if p == -1 { - return nil, errors.New("invalid import line: " + line) - } - p2 := p1 + p - il.pkg = line[p1:p2] - - pDot := strings.IndexRune(il.pkg, '.') - pSlash := strings.IndexRune(il.pkg, '/') - if pDot != -1 && pDot < pSlash { - il.group = "domain-package" - } - for groupName := range importPackageGroupOrders { - if groupName == "" { - continue // skip internal - } - if strings.HasPrefix(il.pkg, groupName) { - il.group = groupName - } - } - return il, nil -} - -type ( - importLineGroup []*importLineParsed - importLineGroupMap map[string]importLineGroup -) - -func formatGoImports(contentBytes []byte) ([]byte, error) { - p1 := bytes.Index(contentBytes, importBlockBegin) - if p1 == -1 { - return nil, nil - } - p1 += len(importBlockBegin) - p := bytes.Index(contentBytes[p1:], importBlockEnd) - if p == -1 { - return nil, nil - } - p2 := p1 + p - - importGroups := importLineGroupMap{} - r := bytes.NewBuffer(contentBytes[p1:p2]) - eof := false - for !eof { - line, err := r.ReadString('\n') - eof = err == io.EOF - if err != nil && !eof { - return nil, err - } - line = strings.TrimSpace(line) - if line != "" { - if strings.HasPrefix(line, "//") || strings.HasPrefix(line, "/*") { - return nil, errInvalidCommentBetweenImports - } - importLine, err := parseImportLine(line) - if err != nil { - return nil, err - } - importGroups[importLine.group] = append(importGroups[importLine.group], importLine) - } - } - - var groupNames []string - for groupName, importLines := range importGroups { - groupNames = append(groupNames, groupName) - sort.Slice(importLines, func(i, j int) bool { - return strings.Compare(importLines[i].pkg, importLines[j].pkg) < 0 - }) - } - - sort.Slice(groupNames, func(i, j int) bool { - n1 := groupNames[i] - n2 := groupNames[j] - o1 := importPackageGroupOrders[n1] - o2 := importPackageGroupOrders[n2] - if o1 != 0 && o2 != 0 { - return o1 < o2 - } - if o1 == 0 && o2 == 0 { - return strings.Compare(n1, n2) < 0 - } - return o1 != 0 - }) - - formattedBlock := bytes.Buffer{} - for _, groupName := range groupNames { - hasNormalImports := false - hasDummyImports := false - // non-dummy import comes first - for _, importLine := range importGroups[groupName] { - if strings.HasPrefix(importLine.content, "_") { - hasDummyImports = true - } else { - formattedBlock.WriteString("\t" + importLine.content + "\n") - hasNormalImports = true - } - } - // dummy (_ "pkg") comes later - if hasDummyImports { - if hasNormalImports { - formattedBlock.WriteString("\n") - } - for _, importLine := range importGroups[groupName] { - if strings.HasPrefix(importLine.content, "_") { - formattedBlock.WriteString("\t" + importLine.content + "\n") - } - } - } - formattedBlock.WriteString("\n") - } - formattedBlockBytes := bytes.TrimRight(formattedBlock.Bytes(), "\n") - - var formattedBytes []byte - formattedBytes = append(formattedBytes, contentBytes[:p1]...) - formattedBytes = append(formattedBytes, formattedBlockBytes...) - formattedBytes = append(formattedBytes, contentBytes[p2:]...) - return formattedBytes, nil -} - -// FormatGoImports format the imports by our rules (see unit tests) -func FormatGoImports(file string, doWriteFile bool) error { - f, err := os.Open(file) - if err != nil { - return err - } - var contentBytes []byte - { - defer f.Close() - contentBytes, err = io.ReadAll(f) - if err != nil { - return err - } - } - formattedBytes, err := formatGoImports(contentBytes) - if err != nil { - return err - } - if formattedBytes == nil { - return nil - } - if bytes.Equal(contentBytes, formattedBytes) { - return nil - } - - if doWriteFile { - f, err = os.OpenFile(file, os.O_TRUNC|os.O_WRONLY, 0o644) - if err != nil { - return err - } - defer f.Close() - _, err = f.Write(formattedBytes) - return err - } - - return err -} diff --git a/tools/codeformat/formatimports_test.go b/tools/codeformat/formatimports_test.go deleted file mode 100644 index c66181d3513..00000000000 --- a/tools/codeformat/formatimports_test.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2021 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package codeformat - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestFormatImportsSimple(t *testing.T) { - formatted, err := formatGoImports([]byte(` -package codeformat - -import ( - "github.com/stretchr/testify/assert" - "testing" -) -`)) - - expected := ` -package codeformat - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) -` - - assert.NoError(t, err) - assert.Equal(t, expected, string(formatted)) -} - -func TestFormatImportsGroup(t *testing.T) { - // gofmt/goimports won't group the packages, for example, they produce such code: - // "bytes" - // "image" - // (a blank line) - // "fmt" - // "image/color/palette" - // our formatter does better, and these packages are grouped into one. - - formatted, err := formatGoImports([]byte(` -package test - -import ( - "bytes" - "fmt" - "image" - "image/color" - - _ "image/gif" // for processing gif images - _ "image/jpeg" // for processing jpeg images - _ "image/png" // for processing png images - - "code.gitea.io/other/package" - - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/util" - - "xorm.io/the/package" - - "github.com/issue9/identicon" - "github.com/nfnt/resize" - "github.com/oliamb/cutter" -) -`)) - - expected := ` -package test - -import ( - "bytes" - "fmt" - "image" - "image/color" - - _ "image/gif" // for processing gif images - _ "image/jpeg" // for processing jpeg images - _ "image/png" // for processing png images - - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/util" - - "code.gitea.io/other/package" - "github.com/issue9/identicon" - "github.com/nfnt/resize" - "github.com/oliamb/cutter" - "xorm.io/the/package" -) -` - - assert.NoError(t, err) - assert.Equal(t, expected, string(formatted)) -} - -func TestFormatImportsInvalidComment(t *testing.T) { - // why we shouldn't write comments between imports: it breaks the grouping of imports - // for example: - // "pkg1" - // "pkg2" - // // a comment - // "pkgA" - // "pkgB" - // the comment splits the packages into two groups, pkg1/2 are sorted separately, pkgA/B are sorted separately - // we don't want such code, so the code should be: - // "pkg1" - // "pkg2" - // "pkgA" // a comment - // "pkgB" - - _, err := formatGoImports([]byte(` -package test - -import ( - "image/jpeg" - // for processing gif images - "image/gif" -) -`)) - assert.ErrorIs(t, err, errInvalidCommentBetweenImports) -}