diff --git a/.golangci.yml b/.golangci.yml index 5ef5481f7e4..038b4c93b25 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -17,7 +17,7 @@ linters: - govet - ineffassign - mirror - # - modernize # re-enable it in a future PR, after clearly fixing all the issues it reports + - modernize - nakedret - nilnil - nolintlint @@ -62,6 +62,9 @@ linters: desc: "migrations must not depend on the models package. HINT: MIGRATION-STRUCT-FROZEN" - pkg: gitea.dev/modules/structs desc: "migrations must not depend on modules/structs. HINT: MIGRATION-STRUCT-FROZEN" + modernize: + disable: + - embedlit nolintlint: allow-unused: false require-explanation: true diff --git a/go.mod b/go.mod index b8258cc170e..6492011acc3 100644 --- a/go.mod +++ b/go.mod @@ -60,7 +60,6 @@ require ( github.com/google/go-github/v89 v89.0.0 github.com/google/licenseclassifier/v2 v2.0.0 github.com/google/pprof v0.0.0-20260802141513-ef3492d7dac3 - github.com/google/uuid v1.6.0 github.com/gorilla/feeds v1.2.0 github.com/gorilla/sessions v1.4.0 github.com/hashicorp/go-version v1.9.0 @@ -194,6 +193,7 @@ require ( github.com/google/flatbuffers v25.12.19+incompatible // indirect github.com/google/go-querystring v1.2.0 // indirect github.com/google/go-tpm v0.9.8 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect @@ -276,6 +276,9 @@ require ( ignore ( ./.venv ./node_modules + ./public + ./vendor + ./web_src ) // When doing "go get -u ./...", Golang will try to update all dependencies diff --git a/models/auth/oauth2.go b/models/auth/oauth2.go index b9e4a6b0ba5..bff4b9db6d9 100644 --- a/models/auth/oauth2.go +++ b/models/auth/oauth2.go @@ -14,6 +14,7 @@ import ( "slices" "strings" "time" + "uuid" "gitea.dev/models/db" "gitea.dev/modules/container" @@ -21,7 +22,6 @@ import ( "gitea.dev/modules/timeutil" "gitea.dev/modules/util" - uuid "github.com/google/uuid" "golang.org/x/crypto/bcrypt" "golang.org/x/oauth2" "xorm.io/builder" diff --git a/models/issues/label.go b/models/issues/label.go index 0c3010601ad..24ca9d8c1cb 100644 --- a/models/issues/label.go +++ b/models/issues/label.go @@ -186,11 +186,11 @@ func (l *Label) ExclusiveScope() string { if !l.Exclusive { return "" } - lastIndex := strings.LastIndex(l.Name, "/") - if lastIndex == -1 || lastIndex == 0 || lastIndex == len(l.Name)-1 { + scope, name, found := strings.CutLast(l.Name, "/") + if !found || scope == "" || name == "" { return "" } - return l.Name[:lastIndex] + return scope } // CompareLabelForDisplay compares labels for displaying them in dropdowns or lists. diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go index 7131aa4b6b0..066f75df2c4 100644 --- a/models/repo/repo_list.go +++ b/models/repo/repo_list.go @@ -617,7 +617,7 @@ func searchRepositoryByCondition(ctx context.Context, opts SearchRepoOptions, co args = append(args, opts.PriorityOwnerID) } else if strings.Count(opts.Keyword, "/") == 1 { // With "owner/repo" search times, prioritise results which match the owner field - orgName := strings.Split(opts.Keyword, "/")[0] + orgName, _, _ := strings.Cut(opts.Keyword, "/") orderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_name LIKE ? THEN 0 ELSE 1 END, %s", orderBy)) args = append(args, orgName) } diff --git a/models/repo/upload.go b/models/repo/upload.go index 6bfcd022aec..3004c1d5659 100644 --- a/models/repo/upload.go +++ b/models/repo/upload.go @@ -11,13 +11,12 @@ import ( "mime/multipart" "os" "path/filepath" + "uuid" "gitea.dev/models/db" "gitea.dev/modules/log" "gitea.dev/modules/setting" "gitea.dev/modules/util" - - gouuid "github.com/google/uuid" ) // ErrUploadNotExist represents a "UploadNotExist" kind of error. @@ -60,7 +59,7 @@ func (upload *Upload) LocalPath() string { // NewUpload creates a new upload object. func NewUpload(ctx context.Context, name string, buf []byte, file multipart.File) (_ *Upload, err error) { upload := &Upload{ - UUID: gouuid.New().String(), + UUID: uuid.New().String(), Name: name, } diff --git a/models/webhook/hooktask.go b/models/webhook/hooktask.go index a0a6eef60f4..2c60e34227d 100644 --- a/models/webhook/hooktask.go +++ b/models/webhook/hooktask.go @@ -7,6 +7,7 @@ import ( "context" "errors" "time" + "uuid" "gitea.dev/models/db" "gitea.dev/modules/json" @@ -15,7 +16,6 @@ import ( "gitea.dev/modules/timeutil" webhook_module "gitea.dev/modules/webhook" - gouuid "github.com/google/uuid" "xorm.io/builder" ) @@ -119,7 +119,7 @@ func HookTasks(ctx context.Context, hookID int64, page int) ([]*HookTask, error) // CreateHookTask creates a new hook task, // it handles conversion from Payload to PayloadContent. func CreateHookTask(ctx context.Context, t *HookTask) (*HookTask, error) { - t.UUID = gouuid.New().String() + t.UUID = uuid.New().String() if t.Delivered == 0 { t.Delivered = timeutil.TimeStampNanoNow() } diff --git a/models/webhook/webhook_test.go b/models/webhook/webhook_test.go index cd527d11591..4e2a4ec36d5 100644 --- a/models/webhook/webhook_test.go +++ b/models/webhook/webhook_test.go @@ -7,6 +7,7 @@ import ( "context" "testing" "time" + "uuid" "gitea.dev/models/db" "gitea.dev/models/unittest" @@ -15,7 +16,6 @@ import ( "gitea.dev/modules/timeutil" webhook_module "gitea.dev/modules/webhook" - "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "xorm.io/builder" diff --git a/modules/avatar/federated.go b/modules/avatar/federated.go index 27d3778cf68..ed8d1cdd863 100644 --- a/modules/avatar/federated.go +++ b/modules/avatar/federated.go @@ -16,11 +16,11 @@ import ( // LookupFederatedHost returns the avatar host from the email domain's SRV record. https://wiki.libravatar.org/api/ func LookupFederatedHost(ctx context.Context, email string, secure bool) string { - at := strings.LastIndexByte(email, '@') - if at < 0 { + _, domain, found := strings.CutLast(email, "@") + if !found { return "" } - domain := strings.ToLower(email[at+1:]) + domain = strings.ToLower(domain) service, defaultPort := "avatars", uint16(80) if secure { diff --git a/modules/git/commit.go b/modules/git/commit.go index 05397f11d8c..600ed15ef87 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -114,8 +114,7 @@ func (c *Commit) HasPreviousCommit(ctx context.Context, gitRepo *Repository, obj if err == nil { return true, nil } - var exitError *exec.ExitError - if errors.As(err, &exitError) { + if exitError, ok := errors.AsType[*exec.ExitError](err); ok { if exitError.ProcessState.ExitCode() == 1 && len(exitError.Stderr) == 0 { return false, nil } diff --git a/modules/log/logger_impl.go b/modules/log/logger_impl.go index 082ab21ace5..909d1dad1eb 100644 --- a/modules/log/logger_impl.go +++ b/modules/log/logger_impl.go @@ -184,7 +184,7 @@ func asLogStringer(v any) LogStringer { // in case the receiver is a pointer, but the value is a struct vp := reflect.New(a.Type()) vp.Elem().Set(a) - if s, ok := vp.Interface().(LogStringer); ok { + if s, ok := reflect.TypeAssert[LogStringer](vp); ok { return s } } diff --git a/modules/setting/actions.go b/modules/setting/actions.go index c811de29a90..2605b297d67 100644 --- a/modules/setting/actions.go +++ b/modules/setting/actions.go @@ -102,7 +102,7 @@ func loadActionsFrom(rootCfg ConfigProvider) error { } if urls := string(Actions.DefaultActionsURL); urls != defaultActionsURLGitHub && urls != defaultActionsURLSelf { - url := strings.Split(urls, ",")[0] + url, _, _ := strings.Cut(urls, ",") if strings.HasPrefix(url, "https://") || strings.HasPrefix(url, "http://") { log.Error("[actions] DEFAULT_ACTIONS_URL does not support %q as custom URL any longer, fallback to %q", urls, diff --git a/modules/structs/attachment.go b/modules/structs/attachment.go index 5d1788f7151..b2ace3e6cfa 100644 --- a/modules/structs/attachment.go +++ b/modules/structs/attachment.go @@ -1,7 +1,7 @@ // Copyright 2017 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package structs // import "gitea.dev/modules/structs" +package structs import ( "time" diff --git a/modules/util/error.go b/modules/util/error.go index 4c2566a2a33..d503cadf288 100644 --- a/modules/util/error.go +++ b/modules/util/error.go @@ -99,8 +99,7 @@ func ErrorWrapTranslatable(err error, trKey string, trArgs ...any) ErrorTranslat } func ErrorAsTranslatable(err error) ErrorTranslatable { - var e *errorTranslatableWrapper - if errors.As(err, &e) { + if e, ok := errors.AsType[*errorTranslatableWrapper](err); ok { return e } return nil diff --git a/modules/validation/helpers.go b/modules/validation/helpers.go index 43ad7c16499..a84d08ca97e 100644 --- a/modules/validation/helpers.go +++ b/modules/validation/helpers.go @@ -64,12 +64,12 @@ func IsEmailDomainListed(globs []glob.Glob, email string) bool { return false } - n := strings.LastIndex(email, "@") - if n <= 0 { + localPart, domain, found := strings.CutLast(email, "@") + if !found || localPart == "" { return false } - domain := strings.ToLower(email[n+1:]) + domain = strings.ToLower(domain) for _, g := range globs { if g.Match(domain) { diff --git a/modules/web/handler.go b/modules/web/handler.go index d8ce8df9552..62fb0709b45 100644 --- a/modules/web/handler.go +++ b/modules/web/handler.go @@ -66,7 +66,7 @@ var ( func preCheckHandler(fn reflect.Value, argsIn []reflect.Value) { hasStatusProvider := false for _, argIn := range argsIn { - if _, hasStatusProvider = argIn.Interface().(types.ResponseStatusProvider); hasStatusProvider { + if _, hasStatusProvider = reflect.TypeAssert[types.ResponseStatusProvider](argIn); hasStatusProvider { break } } @@ -119,7 +119,7 @@ func handleResponse(fn reflect.Value, ret []reflect.Value) { func hasResponseBeenWritten(argsIn []reflect.Value) bool { for _, argIn := range argsIn { - if statusProvider, ok := argIn.Interface().(types.ResponseStatusProvider); ok { + if statusProvider, ok := reflect.TypeAssert[types.ResponseStatusProvider](argIn); ok { if statusProvider.WrittenStatus() != 0 { return true } diff --git a/routers/api/actions/artifacts_utils.go b/routers/api/actions/artifacts_utils.go index b4962939e02..64bf6497958 100644 --- a/routers/api/actions/artifacts_utils.go +++ b/routers/api/actions/artifacts_utils.go @@ -83,7 +83,7 @@ func parseArtifactItemPath(ctx *ArtifactContext) (string, string, bool) { // it's formatted as {artifact_name}/{artfict_path_in_runner} // runner in host mode on Windows, itemPath is joined by Windows slash '\' itemPath := util.PathJoinRelX(ctx.Req.URL.Query().Get("itemPath")) - artifactName := strings.Split(itemPath, "/")[0] + artifactName, _, _ := strings.Cut(itemPath, "/") artifactPath := strings.TrimPrefix(itemPath, artifactName+"/") if !validateArtifactHash(ctx, artifactName) { return "", "", false diff --git a/routers/api/actions/runner/runner.go b/routers/api/actions/runner/runner.go index 96e6a90e156..3a05cc73155 100644 --- a/routers/api/actions/runner/runner.go +++ b/routers/api/actions/runner/runner.go @@ -8,6 +8,7 @@ import ( "errors" "net/http" "slices" + "uuid" runnerv1 "gitea.dev/actionslib/runner/v1" "gitea.dev/actionslib/runner/v1/runnerv1connect" @@ -20,7 +21,6 @@ import ( actions_service "gitea.dev/services/actions" "connectrpc.com/connect" - gouuid "github.com/google/uuid" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" @@ -74,7 +74,7 @@ func (s *Service) Register( // create new runner name := util.EllipsisDisplayString(req.Msg.Name, 255) runner := &actions_model.ActionRunner{ - UUID: gouuid.New().String(), + UUID: uuid.New().String(), Name: name, OwnerID: runnerToken.OwnerID, RepoID: runnerToken.RepoID, diff --git a/routers/api/packages/container/container.go b/routers/api/packages/container/container.go index a293cac08d8..a9124b70cb0 100644 --- a/routers/api/packages/container/container.go +++ b/routers/api/packages/container/container.go @@ -598,8 +598,7 @@ func PutManifest(ctx *context.Context) { digest, err := processManifest(ctx, mci, buf) if err != nil { - var namedError *namedError - if errors.As(err, &namedError) { + if namedError, ok := errors.AsType[*namedError](err); ok { apiErrorDefined(ctx, namedError) } else if errors.Is(err, container_model.ErrContainerBlobNotExist) { apiErrorDefined(ctx, errBlobUnknown) diff --git a/routers/web/repo/treelist.go b/routers/web/repo/treelist.go index d75d31444a6..dda100f699a 100644 --- a/routers/web/repo/treelist.go +++ b/routers/web/repo/treelist.go @@ -84,12 +84,10 @@ func transformDiffTreeForWeb(renderedIconPool *fileicon.RenderedIconPool, diffTr dirNodes := map[string]*WebDiffFileItem{"": &dft.TreeRoot} addItem := func(item *WebDiffFileItem) { var parentPath string - pos := strings.LastIndexByte(item.FullName, '/') - if pos == -1 { - item.DisplayName = item.FullName + if dir, name, found := strings.CutLast(item.FullName, "/"); found { + parentPath, item.DisplayName = dir, name } else { - parentPath = item.FullName[:pos] - item.DisplayName = item.FullName[pos+1:] + item.DisplayName = item.FullName } parentNode, parentExists := dirNodes[parentPath] if !parentExists { diff --git a/routers/web/user/package.go b/routers/web/user/package.go index bd363bfc8ce..22bb60dc5d0 100644 --- a/routers/web/user/package.go +++ b/routers/web/user/package.go @@ -9,6 +9,7 @@ import ( "net/http" "net/url" "time" + "uuid" "gitea.dev/models/db" org_model "gitea.dev/models/organization" @@ -35,8 +36,6 @@ import ( "gitea.dev/services/forms" packages_service "gitea.dev/services/packages" container_service "gitea.dev/services/packages/container" - - "github.com/google/uuid" ) const ( diff --git a/services/attachment/attachment.go b/services/attachment/attachment.go index 372cfb62f9f..61b0d7d4435 100644 --- a/services/attachment/attachment.go +++ b/services/attachment/attachment.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "net/http" + "uuid" "gitea.dev/models/db" repo_model "gitea.dev/models/repo" @@ -17,8 +18,6 @@ import ( "gitea.dev/modules/storage" "gitea.dev/modules/util" "gitea.dev/services/context/upload" - - "github.com/google/uuid" ) // NewAttachment creates a new attachment object, but do not verify. @@ -85,8 +84,7 @@ func uploadAttachment(ctx context.Context, file *UploaderFile, allowedTypes stri } attach, err := NewAttachment(ctx, attach, io.MultiReader(bytes.NewReader(buf), src), file.size) - var maxBytesError *http.MaxBytesError - if errors.As(err, &maxBytesError) { + if _, ok := errors.AsType[*http.MaxBytesError](err); ok { return nil, util.ErrorWrap(util.ErrContentTooLarge, "attachment exceeds limit %d", maxFileSize) } return attach, err diff --git a/services/auth/auth.go b/services/auth/auth.go index fb7d0fa9a19..050ecb0e6f1 100644 --- a/services/auth/auth.go +++ b/services/auth/auth.go @@ -25,8 +25,7 @@ func (e ErrUserAuthMessage) Error() string { } func ErrAsUserAuthMessage(err error) (string, bool) { - var msg ErrUserAuthMessage - if errors.As(err, &msg) { + if msg, ok := errors.AsType[ErrUserAuthMessage](err); ok { return msg.Error(), true } return "", false diff --git a/services/auth/reverseproxy.go b/services/auth/reverseproxy.go index b7d8d013c33..8a1c3535404 100644 --- a/services/auth/reverseproxy.go +++ b/services/auth/reverseproxy.go @@ -7,14 +7,13 @@ package auth import ( "net/http" "strings" + "uuid" user_model "gitea.dev/models/user" "gitea.dev/modules/log" "gitea.dev/modules/optional" "gitea.dev/modules/session" "gitea.dev/modules/setting" - - gouuid "github.com/google/uuid" ) // Ensure the struct implements the interface. @@ -143,7 +142,7 @@ func (r *ReverseProxy) newUser(req *http.Request) *user_model.User { return nil } - email := gouuid.New().String() + "@localhost" + email := uuid.New().String() + "@localhost" if setting.Service.EnableReverseProxyEmail { webAuthEmail := req.Header.Get(setting.ReverseProxyAuthEmail) if len(webAuthEmail) > 0 { diff --git a/services/auth/source/oauth2/init.go b/services/auth/source/oauth2/init.go index e67c695b4a0..1a15972a684 100644 --- a/services/auth/source/oauth2/init.go +++ b/services/auth/source/oauth2/init.go @@ -8,6 +8,7 @@ import ( "encoding/gob" "net/http" "sync" + "uuid" "gitea.dev/models/auth" "gitea.dev/models/db" @@ -15,7 +16,6 @@ import ( "gitea.dev/modules/optional" "gitea.dev/modules/setting" - "github.com/google/uuid" "github.com/gorilla/sessions" "github.com/markbates/goth/gothic" ) diff --git a/services/auth/source/pam/source_authenticate.go b/services/auth/source/pam/source_authenticate.go index 510e1c2b93d..ee5e3eeeb43 100644 --- a/services/auth/source/pam/source_authenticate.go +++ b/services/auth/source/pam/source_authenticate.go @@ -7,14 +7,13 @@ import ( "context" "fmt" "strings" + "uuid" "gitea.dev/models/auth" user_model "gitea.dev/models/user" "gitea.dev/modules/auth/pam" "gitea.dev/modules/optional" "gitea.dev/modules/setting" - - "github.com/google/uuid" ) // Authenticate queries if login/password is valid against the PAM, diff --git a/services/auth/sspi.go b/services/auth/sspi.go index d3cca5d1391..9aa43159dea 100644 --- a/services/auth/sspi.go +++ b/services/auth/sspi.go @@ -9,6 +9,7 @@ import ( "net/http" "strings" "sync" + "uuid" "gitea.dev/models/auth" "gitea.dev/models/db" @@ -19,8 +20,6 @@ import ( "gitea.dev/modules/templates" "gitea.dev/services/auth/source/sspi" gitea_context "gitea.dev/services/context" - - gouuid "github.com/google/uuid" ) const ( @@ -156,7 +155,7 @@ func (s *SSPI) shouldAuthenticate(req *http.Request) (shouldAuth bool) { // newUser creates a new user object for the purpose of automatic registration // and populates its name and email with the information present in request headers. func (s *SSPI) newUser(ctx context.Context, username string, cfg *sspi.Source) (*user_model.User, error) { - email := gouuid.New().String() + "@localhost.localdomain" + email := uuid.New().String() + "@localhost.localdomain" user := &user_model.User{ Name: username, Email: email, diff --git a/services/migrations/dump.go b/services/migrations/dump.go index 6ed155c6989..83c1b05f31f 100644 --- a/services/migrations/dump.go +++ b/services/migrations/dump.go @@ -14,6 +14,7 @@ import ( "strconv" "strings" "time" + "uuid" user_model "gitea.dev/models/user" "gitea.dev/modules/git" @@ -25,7 +26,6 @@ import ( "gitea.dev/modules/setting" "gitea.dev/modules/structs" - "github.com/google/uuid" "go.yaml.in/yaml/v4" ) diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index c610443147d..57f407a3afb 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -12,6 +12,7 @@ import ( "strconv" "strings" "time" + "uuid" "gitea.dev/models/db" issues_model "gitea.dev/models/issues" @@ -32,8 +33,6 @@ import ( "gitea.dev/modules/util" "gitea.dev/services/pull" repo_service "gitea.dev/services/repository" - - "github.com/google/uuid" ) var _ base.Uploader = &GiteaLocalUploader{} diff --git a/tests/integration/api_packages_terraform_test.go b/tests/integration/api_packages_terraform_test.go index c823923692a..c98d4b27446 100644 --- a/tests/integration/api_packages_terraform_test.go +++ b/tests/integration/api_packages_terraform_test.go @@ -8,13 +8,13 @@ import ( "net/http" "strings" "testing" + "uuid" "gitea.dev/models/packages" "gitea.dev/models/unittest" user_model "gitea.dev/models/user" "gitea.dev/tests" - "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/tests/integration/oauth_test.go b/tests/integration/oauth_test.go index 13adb67e266..e5d95d783a2 100644 --- a/tests/integration/oauth_test.go +++ b/tests/integration/oauth_test.go @@ -869,7 +869,7 @@ func issueOAuthAccessTokenForScope(t *testing.T, user *user_model.User, scope st authorizeURL := fmt.Sprintf("/login/oauth/authorize?client_id=%s&redirect_uri=https://example.com&response_type=code&state=thestate", app.ClientID) authorizeReq := NewRequest(t, "GET", authorizeURL) authorizeResp := ctx.MakeRequest(t, authorizeReq, http.StatusSeeOther) - authcode := strings.Split(strings.Split(authorizeResp.Body.String(), "?code=")[1], "&")[0] + authcode, _, _ := strings.Cut(strings.Split(authorizeResp.Body.String(), "?code=")[1], "&") accessTokenReq := NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{ "grant_type": "authorization_code", @@ -923,7 +923,7 @@ func testOAuthGrantScopesReadRepositoryFailOrganization(t *testing.T) { authorizeReq := NewRequest(t, "GET", authorizeURL) authorizeResp := ctx.MakeRequest(t, authorizeReq, http.StatusSeeOther) - authcode := strings.Split(strings.Split(authorizeResp.Body.String(), "?code=")[1], "&")[0] + authcode, _, _ := strings.Cut(strings.Split(authorizeResp.Body.String(), "?code=")[1], "&") accessTokenReq := NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{ "grant_type": "authorization_code", "client_id": app.ClientID, @@ -1060,7 +1060,7 @@ func testOAuthGrantScopesClaimPublicOnlyGroups(t *testing.T) { authorizeReq := NewRequest(t, "GET", authorizeURL) authorizeResp := ctx.MakeRequest(t, authorizeReq, http.StatusSeeOther) - authcode := strings.Split(strings.Split(authorizeResp.Body.String(), "?code=")[1], "&")[0] + authcode, _, _ := strings.Cut(strings.Split(authorizeResp.Body.String(), "?code=")[1], "&") accessTokenReq := NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{ "grant_type": "authorization_code", @@ -1158,7 +1158,7 @@ func testOAuthGrantScopesClaimAllGroups(t *testing.T) { authorizeReq := NewRequest(t, "GET", authorizeURL) authorizeResp := ctx.MakeRequest(t, authorizeReq, http.StatusSeeOther) - authcode := strings.Split(strings.Split(authorizeResp.Body.String(), "?code=")[1], "&")[0] + authcode, _, _ := strings.Cut(strings.Split(authorizeResp.Body.String(), "?code=")[1], "&") accessTokenReq := NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{ "grant_type": "authorization_code", diff --git a/tools/lint-go-all.go b/tools/lint-go-all.go index 1560bf6798b..9d6b4156570 100644 --- a/tools/lint-go-all.go +++ b/tools/lint-go-all.go @@ -12,26 +12,45 @@ import ( "path/filepath" "regexp" "strings" + + "golang.org/x/mod/modfile" ) +// goModIgnoredDirs returns the go.mod "ignore" directories, which the go tool skips but a filesystem walk does not. +func goModIgnoredDirs() (map[string]bool, error) { + data, err := os.ReadFile("go.mod") + if err != nil { + return nil, err + } + mod, err := modfile.Parse("go.mod", data, nil) + if err != nil { + return nil, err + } + dirs := make(map[string]bool, len(mod.Ignore)) + for _, ignore := range mod.Ignore { + dirs[filepath.ToSlash(filepath.Clean(ignore.Path))] = true + } + return dirs, nil +} + func lintGoHeader() bool { headerRE := regexp.MustCompile(`^(// (Copyright [^\n]+|All rights reserved\.)\n)*// Copyright \d{4} (The Gogs Authors|The Gitea Authors|Gitea Authors|Gitea)\.( All rights reserved\.)?\n(// (Copyright [^\n]+|All rights reserved\.)\n)*// SPDX-License-Identifier: [\w.-]+`) generatedRE := regexp.MustCompile(`(?m)^// (Code|This file is) [Gg]enerated.*DO NOT EDIT`) - skipDirs := map[string]bool{ - ".git": true, - ".venv": true, - "node_modules": true, - "public": true, - "vendor": true, - "web_src": true, + skipDirs, err := goModIgnoredDirs() + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + return false } root, bad := ".", 0 - err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { + err = filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { if err != nil { return err } if d.IsDir() { - if rel, _ := filepath.Rel(root, path); skipDirs[filepath.ToSlash(rel)] { + if path == root { + return nil + } + if skipDirs[filepath.ToSlash(path)] || strings.HasPrefix(d.Name(), ".") { return fs.SkipDir } return nil