mirror of
https://github.com/mattermost/mattermost.git
synced 2026-05-28 04:35:04 -04:00
MM-68150: Upgrade golangci-lint to v2.12.2 (#36554)
Some checks are pending
API / build (push) Waiting to run
Server CI / Compute Go Version (push) Waiting to run
Server CI / Check mocks (push) Blocked by required conditions
Server CI / Check go mod tidy (push) Blocked by required conditions
Server CI / Check go fix (push) Blocked by required conditions
Server CI / check-style (push) Blocked by required conditions
Server CI / Check serialization methods for hot structs (push) Blocked by required conditions
Server CI / Vet API (push) Blocked by required conditions
Server CI / Check migration files (push) Blocked by required conditions
Server CI / Generate email templates (push) Blocked by required conditions
Server CI / Check store layers (push) Blocked by required conditions
Server CI / Check mmctl docs (push) Blocked by required conditions
Server CI / Postgres (shard 0) (push) Blocked by required conditions
Server CI / Postgres (shard 1) (push) Blocked by required conditions
Server CI / Postgres (shard 2) (push) Blocked by required conditions
Server CI / Postgres (shard 3) (push) Blocked by required conditions
Server CI / Merge Postgres Test Results (push) Blocked by required conditions
Server CI / Elasticsearch v8 Compatibility (push) Blocked by required conditions
Server CI / Postgres FIPS (shard 0) (push) Blocked by required conditions
Server CI / Postgres FIPS (shard 1) (push) Blocked by required conditions
Server CI / Postgres FIPS (shard 2) (push) Blocked by required conditions
Server CI / Postgres FIPS (shard 3) (push) Blocked by required conditions
Server CI / Merge Postgres FIPS Test Results (push) Blocked by required conditions
Server CI / Run mmctl tests (push) Blocked by required conditions
Server CI / Run mmctl tests (FIPS) (push) Blocked by required conditions
Server CI / Build mattermost server app (push) Blocked by required conditions
Tools CI / check-style (mattermost-govet) (push) Waiting to run
Tools CI / Test (mattermost-govet) (push) Waiting to run
Web App CI / check-lint (push) Waiting to run
Web App CI / check-i18n (push) Blocked by required conditions
Web App CI / check-external-links (push) Blocked by required conditions
Web App CI / check-types (push) Blocked by required conditions
Web App CI / test (platform) (push) Blocked by required conditions
Web App CI / test (mattermost-redux) (push) Blocked by required conditions
Web App CI / test (channels shard 1/4) (push) Blocked by required conditions
Web App CI / test (channels shard 2/4) (push) Blocked by required conditions
Web App CI / test (channels shard 3/4) (push) Blocked by required conditions
Web App CI / test (channels shard 4/4) (push) Blocked by required conditions
Web App CI / upload-coverage (push) Blocked by required conditions
Web App CI / build (push) Blocked by required conditions
YAML Lint / yamllint (push) Waiting to run
Some checks are pending
API / build (push) Waiting to run
Server CI / Compute Go Version (push) Waiting to run
Server CI / Check mocks (push) Blocked by required conditions
Server CI / Check go mod tidy (push) Blocked by required conditions
Server CI / Check go fix (push) Blocked by required conditions
Server CI / check-style (push) Blocked by required conditions
Server CI / Check serialization methods for hot structs (push) Blocked by required conditions
Server CI / Vet API (push) Blocked by required conditions
Server CI / Check migration files (push) Blocked by required conditions
Server CI / Generate email templates (push) Blocked by required conditions
Server CI / Check store layers (push) Blocked by required conditions
Server CI / Check mmctl docs (push) Blocked by required conditions
Server CI / Postgres (shard 0) (push) Blocked by required conditions
Server CI / Postgres (shard 1) (push) Blocked by required conditions
Server CI / Postgres (shard 2) (push) Blocked by required conditions
Server CI / Postgres (shard 3) (push) Blocked by required conditions
Server CI / Merge Postgres Test Results (push) Blocked by required conditions
Server CI / Elasticsearch v8 Compatibility (push) Blocked by required conditions
Server CI / Postgres FIPS (shard 0) (push) Blocked by required conditions
Server CI / Postgres FIPS (shard 1) (push) Blocked by required conditions
Server CI / Postgres FIPS (shard 2) (push) Blocked by required conditions
Server CI / Postgres FIPS (shard 3) (push) Blocked by required conditions
Server CI / Merge Postgres FIPS Test Results (push) Blocked by required conditions
Server CI / Run mmctl tests (push) Blocked by required conditions
Server CI / Run mmctl tests (FIPS) (push) Blocked by required conditions
Server CI / Build mattermost server app (push) Blocked by required conditions
Tools CI / check-style (mattermost-govet) (push) Waiting to run
Tools CI / Test (mattermost-govet) (push) Waiting to run
Web App CI / check-lint (push) Waiting to run
Web App CI / check-i18n (push) Blocked by required conditions
Web App CI / check-external-links (push) Blocked by required conditions
Web App CI / check-types (push) Blocked by required conditions
Web App CI / test (platform) (push) Blocked by required conditions
Web App CI / test (mattermost-redux) (push) Blocked by required conditions
Web App CI / test (channels shard 1/4) (push) Blocked by required conditions
Web App CI / test (channels shard 2/4) (push) Blocked by required conditions
Web App CI / test (channels shard 3/4) (push) Blocked by required conditions
Web App CI / test (channels shard 4/4) (push) Blocked by required conditions
Web App CI / upload-coverage (push) Blocked by required conditions
Web App CI / build (push) Blocked by required conditions
YAML Lint / yamllint (push) Waiting to run
* Simplify invite_people email parsing Replace backwards in-place mutation loop with a straightforward forward filter into a new slice. Extract into parseEmailList so the logic can be unit tested directly. * MM-68150: Upgrade golangci-lint to v2.12.2 Remove //go:fix inline from NewPointer, which is a generic function not yet supported by the inline analyzer, and fix 11 slicesbackward modernize issues flagged by the new version. * MM-68150: Enable all linters by default; disable those with >20 existing issues Switch from opt-in (default: none) to opt-out (default: all) so new linters added to golangci-lint are evaluated automatically. Explicitly disable every linter that has more than 20 pre-existing violations, deferring those for later cleanup. Also disable a handful of linters whose violations are intentional patterns in this codebase (nilerr, dogsled, sqlclosecheck, iotamixing, predeclared, containedctx, iface, gocheckcompilerdirectives, promlinter, goprintffuncname, gomoddirectives). * MM-68150: Fix mirror linter issues Replace Write([]byte(s)) with WriteString(s), and FindIndex([]byte(s)) with FindStringIndex(s), to avoid unnecessary allocations. * MM-68150: Fix nosprintfhostport linter issue Use net.JoinHostPort to construct host:port strings instead of fmt.Sprintf with a manually formatted pattern. * MM-68150: Fix rowserrcheck and sqlclosecheck linter issues Check rows.Err() after iteration loops in schema_dump.go. In the sqlx_wrapper test, defer rows.Close() rather than closing inline. * MM-68150: Fix nilnesserr linter issues — wrong variable in error handlers In 11 places, a stale variable (often the outer err from a prior assignment) was used instead of the freshly-checked error variable (appErr, rowErr, jsonErr, writeErr, esErr). Each produces a typed-nil wrapped in a non-nil interface, silently discarding the real error. * MM-68150: Add i18n string for app.compile_csv_chunks.write_error --------- Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
parent
d43dbe972e
commit
d4fc0ecb1c
33 changed files with 215 additions and 77 deletions
|
|
@ -1,20 +1,84 @@
|
|||
version: "2"
|
||||
linters:
|
||||
default: none
|
||||
enable:
|
||||
- bidichk
|
||||
- errcheck
|
||||
- govet
|
||||
- ineffassign
|
||||
- makezero
|
||||
- misspell
|
||||
- modernize
|
||||
- revive
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- unqueryvet
|
||||
- unused
|
||||
- whitespace
|
||||
default: all
|
||||
disable:
|
||||
- bodyclose
|
||||
- canonicalheader
|
||||
- containedctx # storing context.Context in a struct is an established pattern here
|
||||
- contextcheck
|
||||
- cyclop
|
||||
- depguard
|
||||
- dogsled # test helpers return many values; blank-heavy destructuring is idiomatic
|
||||
- dupl
|
||||
- dupword
|
||||
- embeddedstructfieldcheck
|
||||
- err113
|
||||
- errchkjson
|
||||
- errname
|
||||
- errorlint
|
||||
- exhaustive
|
||||
- exhaustruct
|
||||
- forbidigo
|
||||
- forcetypeassert
|
||||
- funcorder
|
||||
- funlen
|
||||
- gocheckcompilerdirectives # //go:fix is a valid directive in Go 1.24+; linter doesn't know it yet
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gocognit
|
||||
- goconst
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- godoclint
|
||||
- godot
|
||||
- godox
|
||||
- gomoddirectives # replace directives in go.mod are intentional forks
|
||||
- gomodguard # deprecated since v2.12.0; replaced by gomodguard_v2 (enabled via default: all)
|
||||
- goprintffuncname # Ephemeral → Ephemeralf rename is a plugin API breaking change; deferred
|
||||
- gosec
|
||||
- gosmopolitan
|
||||
- iface # identical job interfaces are intentional — type-safe scheduling without coupling
|
||||
- inamedparam
|
||||
- interfacebloat
|
||||
- intrange
|
||||
- iotamixing # const blocks intentionally mix iota with explicit values (ABI stability, ASCII)
|
||||
- ireturn
|
||||
- lll
|
||||
- maintidx
|
||||
- mnd
|
||||
- musttag
|
||||
- nakedret
|
||||
- nestif
|
||||
- nilerr # intentionally dropping errors is common here (graceful degradation, security non-disclosure, fallbacks)
|
||||
- nilnil
|
||||
- nlreturn
|
||||
- noctx
|
||||
- noinlineerr
|
||||
- nolintlint
|
||||
- nonamedreturns
|
||||
- paralleltest
|
||||
- perfsprint
|
||||
- prealloc
|
||||
- predeclared # variable named 'copy' is intentional; already suppressed for revive
|
||||
- promlinter # metric renames are a breaking change; deferred
|
||||
- protogetter
|
||||
- recvcheck
|
||||
- sqlclosecheck # wrapper functions return *sqlx.Rows to callers who close them; not a real leak
|
||||
- tagalign
|
||||
- tagliatelle
|
||||
- testableexamples
|
||||
- testifylint
|
||||
- testpackage
|
||||
- thelper
|
||||
- tparallel
|
||||
- unparam
|
||||
- usestdlibvars
|
||||
- usetesting
|
||||
- varnamelen
|
||||
- wastedassign
|
||||
- wrapcheck
|
||||
- wsl
|
||||
- wsl_v5
|
||||
settings:
|
||||
govet:
|
||||
disable:
|
||||
|
|
|
|||
|
|
@ -328,7 +328,7 @@ golang-versions: ## Install Golang versions used for compatibility testing (e.g.
|
|||
export GO_COMPATIBILITY_TEST_VERSIONS="${GO_COMPATIBILITY_TEST_VERSIONS}"
|
||||
|
||||
golangci-lint: setup-go-work ## Run golangci-lint on codebase
|
||||
$(GO) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.4
|
||||
$(GO) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2
|
||||
ifeq ($(BUILD_ENTERPRISE_READY),true)
|
||||
$(GOBIN)/golangci-lint run ./... ./public/... $(BUILD_ENTERPRISE_DIR)/...
|
||||
else
|
||||
|
|
|
|||
|
|
@ -942,7 +942,7 @@ func TestHandlerOutgoingOAuthConnectionUpdate(t *testing.T) {
|
|||
th.AddPermissionToRole(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
|
||||
|
||||
body := &bytes.Buffer{}
|
||||
body.Write([]byte(`{/}`))
|
||||
body.WriteString(`{/}`)
|
||||
|
||||
req, err := http.NewRequest("PUT", "/", body)
|
||||
if err != nil {
|
||||
|
|
@ -990,7 +990,7 @@ func TestHandlerOutgoingOAuthConnectionUpdate(t *testing.T) {
|
|||
th.AddPermissionToRole(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
|
||||
|
||||
body := &bytes.Buffer{}
|
||||
body.Write([]byte(`{"Id": "` + model.NewId() + `", "name": "changed name"}`))
|
||||
body.WriteString(`{"Id": "` + model.NewId() + `", "name": "changed name"}`)
|
||||
|
||||
req, err := http.NewRequest("PUT", "/", body)
|
||||
if err != nil {
|
||||
|
|
@ -1133,7 +1133,7 @@ func TestHandlerOutgoingOAuthConnectionHandlerCreate(t *testing.T) {
|
|||
th.AddPermissionToRole(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
|
||||
|
||||
body := &bytes.Buffer{}
|
||||
body.Write([]byte(`{/}`))
|
||||
body.WriteString(`{/}`)
|
||||
|
||||
req, err := http.NewRequest("POST", "/", body)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -4153,7 +4153,7 @@ func (a *App) setSidebarCategoriesForConvertedGroupMessage(rctx request.CTX, gmC
|
|||
channelsCategory := categories.Categories[0]
|
||||
_, appErr = a.UpdateSidebarCategories(rctx, user.Id, gmConversionRequest.TeamID, []*model.SidebarCategoryWithChannels{channelsCategory})
|
||||
if appErr != nil {
|
||||
rctx.Logger().Error("Failed to add converted GM to default sidebar category for user", mlog.String("user_id", user.Id), mlog.Err(err))
|
||||
rctx.Logger().Error("Failed to add converted GM to default sidebar category for user", mlog.String("user_id", user.Id), mlog.Err(appErr))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ func (ps *PlatformService) GetHubForUserId(userID string) *Hub {
|
|||
// https://mattermost.atlassian.net/browse/MM-26629.
|
||||
var hash maphash.Hash
|
||||
hash.SetSeed(ps.hashSeed)
|
||||
_, err := hash.Write([]byte(userID))
|
||||
_, err := hash.WriteString(userID)
|
||||
if err != nil {
|
||||
ps.logger.Error("Unable to write userID to hash", mlog.String("userID", userID), mlog.Err(err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ func (ch *Channels) servePluginRequest(w http.ResponseWriter, r *http.Request, h
|
|||
session, appErr := app.GetSession(token)
|
||||
if appErr != nil {
|
||||
if appErr.StatusCode == http.StatusInternalServerError {
|
||||
handleInternalServerError(rctx, "Internal server error while loading session", err)
|
||||
handleInternalServerError(rctx, "Internal server error while loading session", appErr)
|
||||
return
|
||||
}
|
||||
rctx.Logger().Debug("Token in plugin request is invalid. Treating request as unauthenticated",
|
||||
|
|
@ -254,7 +254,7 @@ func (ch *Channels) servePluginRequest(w http.ResponseWriter, r *http.Request, h
|
|||
// If MFA is required and user has not activated it, treat it as unauthenticated
|
||||
if appErr := app.MFARequired(rctx); appErr != nil {
|
||||
if appErr.StatusCode == http.StatusInternalServerError {
|
||||
handleInternalServerError(rctx, "Internal server error during MFA validation", err)
|
||||
handleInternalServerError(rctx, "Internal server error during MFA validation", appErr)
|
||||
return
|
||||
}
|
||||
rctx.Logger().Warn("Treating session as unauthenticated since MFA required",
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ func (a *App) DeleteReactionForPost(rctx request.CTX, reaction *model.Reaction)
|
|||
|
||||
restrictDM, appErr := a.CheckIfChannelIsRestrictedDM(rctx, channel)
|
||||
if appErr != nil {
|
||||
return err
|
||||
return appErr
|
||||
}
|
||||
|
||||
if restrictDM {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ func (a *App) compileCSVChunks(prefix string, numberOfChunks int, headers []stri
|
|||
}
|
||||
_, writeErr := compiledBuf.Write(chunk)
|
||||
if writeErr != nil {
|
||||
return err
|
||||
return model.NewAppError("compileCSVChunks", "app.compile_csv_chunks.write_error", nil, "", http.StatusInternalServerError).Wrap(writeErr)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ func GetCustomStatus(message string) *model.CustomStatus {
|
|||
|
||||
func removeUnicodeSkinTone(unicodeString string) string {
|
||||
skinToneDetectorRegex := regexp.MustCompile("-(1f3fb|1f3fc|1f3fd|1f3fe|1f3ff)")
|
||||
skinToneLocations := skinToneDetectorRegex.FindIndex([]byte(unicodeString))
|
||||
skinToneLocations := skinToneDetectorRegex.FindStringIndex(unicodeString)
|
||||
|
||||
if len(skinToneLocations) == 0 {
|
||||
return unicodeString
|
||||
|
|
|
|||
|
|
@ -41,6 +41,17 @@ func (*InvitePeopleProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model
|
|||
}
|
||||
}
|
||||
|
||||
func parseEmailList(message string) []string {
|
||||
var emails []string
|
||||
for token := range strings.FieldsSeq(message) {
|
||||
token = strings.Trim(token, ",")
|
||||
if strings.Contains(token, "@") {
|
||||
emails = append(emails, token)
|
||||
}
|
||||
}
|
||||
return emails
|
||||
}
|
||||
|
||||
func (*InvitePeopleProvider) DoCommand(a *app.App, rctx request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
|
||||
if !a.HasPermissionToTeam(rctx, args.UserId, args.TeamId, model.PermissionInviteUser) {
|
||||
return &model.CommandResponse{Text: args.T("api.command_invite_people.permission.app_error"), ResponseType: model.CommandResponseTypeEphemeral}
|
||||
|
|
@ -62,14 +73,7 @@ func (*InvitePeopleProvider) DoCommand(a *app.App, rctx request.CTX, args *model
|
|||
return &model.CommandResponse{ResponseType: model.CommandResponseTypeEphemeral, Text: args.T("api.command.invite_people.email_invitations_off")}
|
||||
}
|
||||
|
||||
emailList := strings.Fields(message)
|
||||
|
||||
for i := len(emailList) - 1; i >= 0; i-- {
|
||||
emailList[i] = strings.Trim(emailList[i], ",")
|
||||
if !strings.Contains(emailList[i], "@") {
|
||||
emailList = append(emailList[:i], emailList[i+1:]...)
|
||||
}
|
||||
}
|
||||
emailList := parseEmailList(message)
|
||||
|
||||
if len(emailList) == 0 {
|
||||
return &model.CommandResponse{ResponseType: model.CommandResponseTypeEphemeral, Text: args.T("api.command.invite_people.no_email")}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,62 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost/server/public/model"
|
||||
)
|
||||
|
||||
func TestParseEmailList(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "single valid email",
|
||||
input: "user@example.com",
|
||||
expected: []string{"user@example.com"},
|
||||
},
|
||||
{
|
||||
name: "multiple valid emails",
|
||||
input: "a@example.com b@example.com",
|
||||
expected: []string{"a@example.com", "b@example.com"},
|
||||
},
|
||||
{
|
||||
name: "trailing commas stripped",
|
||||
input: "a@example.com, b@example.com,",
|
||||
expected: []string{"a@example.com", "b@example.com"},
|
||||
},
|
||||
{
|
||||
name: "non-email tokens filtered out",
|
||||
input: "notanemail a@example.com alsoinvalid",
|
||||
expected: []string{"a@example.com"},
|
||||
},
|
||||
{
|
||||
name: "comma immediately after email treated as one token",
|
||||
input: "a@example.com,b@example.com",
|
||||
expected: []string{"a@example.com,b@example.com"},
|
||||
},
|
||||
{
|
||||
name: "empty input",
|
||||
input: "",
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
name: "all tokens invalid",
|
||||
input: "notanemail alsoinvalid",
|
||||
expected: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := parseEmailList(tc.input)
|
||||
require.Equal(t, tc.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvitePeopleProvider(t *testing.T) {
|
||||
th := setup(t).initBasic(t)
|
||||
|
||||
|
|
|
|||
|
|
@ -1832,7 +1832,7 @@ func (a *App) CreatePasswordRecoveryToken(rctx request.CTX, userID, email string
|
|||
// remove any previously created tokens for user
|
||||
appErr := a.InvalidatePasswordRecoveryTokensForUser(userID)
|
||||
if appErr != nil {
|
||||
rctx.Logger().Warn("Error while deleting additional user tokens.", mlog.Err(err))
|
||||
rctx.Logger().Warn("Error while deleting additional user tokens.", mlog.Err(appErr))
|
||||
}
|
||||
|
||||
token := model.NewToken(model.TokenTypePasswordRecovery, string(jsonData))
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ func (worker *BatchReportWorker) processChunk(job *model.Job, reportData []model
|
|||
|
||||
appErr := worker.app.SaveReportChunk(worker.reportFormat, job.Id, fileCount, reportData)
|
||||
if appErr != nil {
|
||||
return err
|
||||
return appErr
|
||||
}
|
||||
|
||||
fileCount++
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ func getData(app ExportUsersToCSVAppIFace) func(jobData model.StringMap) ([]mode
|
|||
|
||||
users, appErr := app.GetUsersForReporting(filter)
|
||||
if appErr != nil {
|
||||
return nil, nil, false, errors.Wrapf(err, "failed to get the next batch (column_value=%v, user_id=%v)", filter.FromColumnValue, filter.FromId)
|
||||
return nil, nil, false, errors.Wrapf(appErr, "failed to get the next batch (column_value=%v, user_id=%v)", filter.FromColumnValue, filter.FromId)
|
||||
}
|
||||
|
||||
if len(users) == 0 {
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ func (jss SqlJobStore) Cleanup(expiryTime int64, batchSize int) error {
|
|||
var rowErr error
|
||||
rowsAffected, rowErr = sqlResult.RowsAffected()
|
||||
if rowErr != nil {
|
||||
return errors.Wrap(err, "unable to delete jobs")
|
||||
return errors.Wrap(rowErr, "unable to delete jobs")
|
||||
}
|
||||
|
||||
time.Sleep(jobsCleanupDelay)
|
||||
|
|
|
|||
|
|
@ -177,6 +177,9 @@ func (ss *SqlStore) getTableOptions() (map[string]map[string]string, error) {
|
|||
// Add option to the table
|
||||
tableOptions[tableName][key] = value
|
||||
}
|
||||
if err := optionsRows.Err(); err != nil {
|
||||
rErr = multierror.Append(rErr, errors.Wrap(err, "error iterating table options rows"))
|
||||
}
|
||||
|
||||
return tableOptions, rErr.ErrorOrNil()
|
||||
}
|
||||
|
|
@ -253,6 +256,9 @@ func (ss *SqlStore) getTableSchemaInformation() (map[string]*model.DatabaseTable
|
|||
})
|
||||
}
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
rErr = multierror.Append(rErr, errors.Wrap(err, "error iterating schema rows"))
|
||||
}
|
||||
|
||||
return tablesMap, tableCollations, rErr.ErrorOrNil()
|
||||
}
|
||||
|
|
@ -298,6 +304,9 @@ func (ss *SqlStore) getTableIndexes() (map[string][]model.DatabaseIndex, error)
|
|||
|
||||
tableIndexes[tableName] = append(tableIndexes[tableName], index)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
rErr = multierror.Append(rErr, errors.Wrap(err, "error iterating index rows"))
|
||||
}
|
||||
|
||||
return tableIndexes, rErr.ErrorOrNil()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -381,7 +381,7 @@ func (me SqlSessionStore) Cleanup(expiryTime int64, batchSize int64) error {
|
|||
var rowErr error
|
||||
rowsAffected, rowErr = sqlResult.RowsAffected()
|
||||
if rowErr != nil {
|
||||
return errors.Wrap(err, "unable to delete sessions")
|
||||
return errors.Wrap(rowErr, "unable to delete sessions")
|
||||
}
|
||||
|
||||
time.Sleep(sessionsCleanupDelay)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,10 @@ func TestSqlX(t *testing.T) {
|
|||
|
||||
query := `SELECT pg_sleep(:timeout);`
|
||||
arg := struct{ Timeout int }{Timeout: 2}
|
||||
_, err = tx.NamedQuery(query, arg)
|
||||
rows, err := tx.NamedQuery(query, arg)
|
||||
if rows != nil {
|
||||
defer rows.Close()
|
||||
}
|
||||
require.Equal(t, context.DeadlineExceeded, err)
|
||||
require.NoError(t, tx.Commit())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ func GetAndValidateLicenseFileFromDisk(location string) (*model.License, []byte,
|
|||
|
||||
var license model.License
|
||||
if jsonErr := json.Unmarshal([]byte(licenseStr), &license); jsonErr != nil {
|
||||
return nil, nil, fmt.Errorf("Found license key at %s but it appears to be invalid: %w", fileName, err)
|
||||
return nil, nil, fmt.Errorf("Found license key at %s but it appears to be invalid: %w", fileName, jsonErr)
|
||||
}
|
||||
|
||||
return &license, licenseBytes, nil
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ func (s *MmctlE2ETestSuite) TestConfigPatchCmd() {
|
|||
invalidFile, err := os.CreateTemp(os.TempDir(), "invalid_config_*.json")
|
||||
s.Require().Nil(err)
|
||||
|
||||
_, err = tmpFile.Write([]byte(configFilePayload))
|
||||
_, err = tmpFile.WriteString(configFilePayload)
|
||||
s.Require().Nil(err)
|
||||
|
||||
defer func() {
|
||||
|
|
@ -212,7 +212,7 @@ rm $1'old'`
|
|||
defer func() {
|
||||
os.Remove(file.Name())
|
||||
}()
|
||||
_, err = file.Write([]byte(content))
|
||||
_, err = file.WriteString(content)
|
||||
s.Require().Nil(err)
|
||||
s.Require().Nil(file.Close())
|
||||
s.Require().Nil(os.Chmod(file.Name(), 0700))
|
||||
|
|
|
|||
|
|
@ -600,10 +600,10 @@ func (s *MmctlUnitTestSuite) TestConfigPatchCmd() {
|
|||
pluginFile, err := os.CreateTemp(os.TempDir(), "plugin_config_*.json")
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = tmpFile.Write([]byte(configFilePayload))
|
||||
_, err = tmpFile.WriteString(configFilePayload)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = pluginFile.Write([]byte(configFilePluginPayload))
|
||||
_, err = pluginFile.WriteString(configFilePluginPayload)
|
||||
s.Require().NoError(err)
|
||||
|
||||
defer func() {
|
||||
|
|
|
|||
|
|
@ -2308,7 +2308,7 @@ func checkMaxVersion(ctx context.Context, client *opensearchapi.Client) (string,
|
|||
|
||||
major, _, _, esErr := common.GetVersionComponents(resp.Version.Number)
|
||||
if esErr != nil {
|
||||
return "", 0, model.NewAppError("Opensearch.checkMaxVersion", "ent.elasticsearch.start.parse_server_version.app_error", map[string]any{"Backend": model.ElasticsearchSettingsOSBackend}, "", http.StatusInternalServerError).Wrap(err)
|
||||
return "", 0, model.NewAppError("Opensearch.checkMaxVersion", "ent.elasticsearch.start.parse_server_version.app_error", map[string]any{"Backend": model.ElasticsearchSettingsOSBackend}, "", http.StatusInternalServerError).Wrap(esErr)
|
||||
}
|
||||
|
||||
if major > opensearchMaxVersion {
|
||||
|
|
|
|||
|
|
@ -5846,6 +5846,10 @@
|
|||
"id": "app.compile_csv_chunks.header_error",
|
||||
"translation": "Failed to write CSV headers."
|
||||
},
|
||||
{
|
||||
"id": "app.compile_csv_chunks.write_error",
|
||||
"translation": "Failed to write CSV data."
|
||||
},
|
||||
{
|
||||
"id": "app.compile_report_chunks.unsupported_format",
|
||||
"translation": "Unsupported report format."
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ package sharedchannel
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/mattermost/mattermost/server/public/model"
|
||||
|
|
@ -529,8 +530,7 @@ func (scs *Service) notifyRemoteOffline(posts []*model.Post, rc *model.RemoteClu
|
|||
|
||||
// range the slice in reverse so the newest posts are visited first; this ensures an ephemeral
|
||||
// get added where it is mostly likely to be seen.
|
||||
for i := len(posts) - 1; i >= 0; i-- {
|
||||
post := posts[i]
|
||||
for _, post := range slices.Backward(posts) {
|
||||
if didNotify := notified[post.UserId]; didNotify {
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
|
@ -178,5 +179,5 @@ func getInbucketHost() (host string) {
|
|||
if inbucket_port == "" {
|
||||
inbucket_port = "9001"
|
||||
}
|
||||
return fmt.Sprintf("http://%s:%s", inbucket_host, inbucket_port)
|
||||
return "http://" + net.JoinHostPort(inbucket_host, inbucket_port)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -254,13 +254,13 @@ func TestSendMailUsingConfigAdvanced(t *testing.T) {
|
|||
file1, err := os.CreateTemp("", "*")
|
||||
require.NoError(t, err)
|
||||
defer os.Remove(file1.Name())
|
||||
file1.Write([]byte("hello world"))
|
||||
file1.WriteString("hello world")
|
||||
file1.Close()
|
||||
file2, err := os.CreateTemp("", "*")
|
||||
|
||||
require.NoError(t, err)
|
||||
defer os.Remove(file2.Name())
|
||||
file2.Write([]byte("foo bar"))
|
||||
file2.WriteString("foo bar")
|
||||
file2.Close()
|
||||
|
||||
embeddedFiles := map[string]io.Reader{
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@
|
|||
package model
|
||||
|
||||
// NewPointer returns a pointer to the object passed.
|
||||
//
|
||||
//go:fix inline
|
||||
func NewPointer[T any](t T) *T { return new(t) }
|
||||
|
||||
// SafeDereference returns the zero value of T if t is nil.
|
||||
|
|
|
|||
|
|
@ -5397,7 +5397,7 @@ func structToMapFilteredByTag(t any, typeOfTag, filterTag string) map[string]any
|
|||
switch field.Kind() {
|
||||
case reflect.Struct:
|
||||
value = structToMapFilteredByTag(field.Interface(), typeOfTag, filterTag)
|
||||
case reflect.Ptr:
|
||||
case reflect.Pointer:
|
||||
indirectType := field.Elem()
|
||||
if indirectType.Kind() == reflect.Struct {
|
||||
value = structToMapFilteredByTag(indirectType.Interface(), typeOfTag, filterTag)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ func TestConfigDefaults(t *testing.T) {
|
|||
t.Run("nowhere nil when partially initialized", func(t *testing.T) {
|
||||
var recursivelyUninitialize func(*Config, string, reflect.Value)
|
||||
recursivelyUninitialize = func(config *Config, name string, v reflect.Value) {
|
||||
if v.Type().Kind() == reflect.Ptr {
|
||||
if v.Type().Kind() == reflect.Pointer {
|
||||
// Ignoring these 2 settings.
|
||||
// TODO: remove them completely in v8.0.
|
||||
if name == "config.ElasticsearchSettings.BulkIndexingTimeWindowSeconds" ||
|
||||
|
|
@ -2937,10 +2937,10 @@ func TestConfigAccessTagsMapToValidPermissions(t *testing.T) {
|
|||
fieldPath := path + "." + field.Name
|
||||
|
||||
elemType := field.Type
|
||||
if elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Slice {
|
||||
if elemType.Kind() == reflect.Pointer || elemType.Kind() == reflect.Slice {
|
||||
elemType = elemType.Elem()
|
||||
}
|
||||
if elemType.Kind() == reflect.Ptr {
|
||||
if elemType.Kind() == reflect.Pointer {
|
||||
elemType = elemType.Elem()
|
||||
}
|
||||
if elemType.Kind() == reflect.Struct {
|
||||
|
|
|
|||
|
|
@ -1087,7 +1087,7 @@ func checkNowhereNil(t *testing.T, name string, value any) bool {
|
|||
|
||||
v := reflect.ValueOf(value)
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Ptr:
|
||||
case reflect.Pointer:
|
||||
// Ignoring these 2 settings.
|
||||
// TODO: remove them completely in v8.0.
|
||||
if name == "config.ElasticsearchSettings.BulkIndexingTimeWindowSeconds" ||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
package markdown
|
||||
|
||||
import "slices"
|
||||
|
||||
const (
|
||||
// Assuming 64k maxSize of a post which can be stored in DB.
|
||||
// Allow scanning upto twice(arbitrary value) the post size.
|
||||
|
|
@ -58,20 +60,20 @@ func InspectBlock(block Block, f func(Block) bool) {
|
|||
|
||||
switch v := block.(type) {
|
||||
case *Document:
|
||||
for i := len(v.Children) - 1; i >= 0; i-- {
|
||||
stack = append(stack, v.Children[i])
|
||||
for _, v0 := range slices.Backward(v.Children) {
|
||||
stack = append(stack, v0)
|
||||
}
|
||||
case *List:
|
||||
for i := len(v.Children) - 1; i >= 0; i-- {
|
||||
stack = append(stack, v.Children[i])
|
||||
for _, v0 := range slices.Backward(v.Children) {
|
||||
stack = append(stack, v0)
|
||||
}
|
||||
case *ListItem:
|
||||
for i := len(v.Children) - 1; i >= 0; i-- {
|
||||
stack = append(stack, v.Children[i])
|
||||
for _, v0 := range slices.Backward(v.Children) {
|
||||
stack = append(stack, v0)
|
||||
}
|
||||
case *BlockQuote:
|
||||
for i := len(v.Children) - 1; i >= 0; i-- {
|
||||
stack = append(stack, v.Children[i])
|
||||
for _, v0 := range slices.Backward(v.Children) {
|
||||
stack = append(stack, v0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -103,20 +105,20 @@ func InspectInline(inline Inline, f func(Inline) bool) {
|
|||
|
||||
switch v := inline.(type) {
|
||||
case *InlineImage:
|
||||
for i := len(v.Children) - 1; i >= 0; i-- {
|
||||
stack = append(stack, v.Children[i])
|
||||
for _, v0 := range slices.Backward(v.Children) {
|
||||
stack = append(stack, v0)
|
||||
}
|
||||
case *InlineLink:
|
||||
for i := len(v.Children) - 1; i >= 0; i-- {
|
||||
stack = append(stack, v.Children[i])
|
||||
for _, v0 := range slices.Backward(v.Children) {
|
||||
stack = append(stack, v0)
|
||||
}
|
||||
case *ReferenceImage:
|
||||
for i := len(v.Children) - 1; i >= 0; i-- {
|
||||
stack = append(stack, v.Children[i])
|
||||
for _, v0 := range slices.Backward(v.Children) {
|
||||
stack = append(stack, v0)
|
||||
}
|
||||
case *ReferenceLink:
|
||||
for i := len(v.Children) - 1; i >= 0; i-- {
|
||||
stack = append(stack, v.Children[i])
|
||||
for _, v0 := range slices.Backward(v.Children) {
|
||||
stack = append(stack, v0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
package markdown
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
|
@ -51,8 +52,8 @@ func (b *Paragraph) Close() {
|
|||
b.Text = remaining
|
||||
}
|
||||
|
||||
for i := len(b.Text) - 1; i >= 0; i-- {
|
||||
b.Text[i] = trimRightSpace(b.markdown, b.Text[i])
|
||||
for i, v := range slices.Backward(b.Text) {
|
||||
b.Text[i] = trimRightSpace(b.markdown, v)
|
||||
if b.Text[i].Position < b.Text[i].End {
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ clean:
|
|||
rm -rf dist
|
||||
|
||||
golangci-lint:
|
||||
$(GO) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.4
|
||||
$(GO) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2
|
||||
$(GOBIN)/golangci-lint run ./...
|
||||
|
||||
check-style: golangci-lint
|
||||
|
|
|
|||
Loading…
Reference in a new issue