Replace `util.SliceXxx` with `slices.Xxx` (#26958)

This commit is contained in:
CaiCandong 2023-09-07 17:37:47 +08:00 committed by GitHub
parent e97e883ad5
commit a78c2eae24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 46 additions and 110 deletions

View File

@ -6,6 +6,7 @@ package actions
import ( import (
"context" "context"
"fmt" "fmt"
"slices"
"strings" "strings"
"time" "time"
@ -350,7 +351,7 @@ func UpdateRun(ctx context.Context, run *ActionRun, cols ...string) error {
// It's impossible that the run is not found, since Gitea never deletes runs. // It's impossible that the run is not found, since Gitea never deletes runs.
} }
if run.Status != 0 || util.SliceContains(cols, "status") { if run.Status != 0 || slices.Contains(cols, "status") {
if run.RepoID == 0 { if run.RepoID == 0 {
run, err = GetRunByID(ctx, run.ID) run, err = GetRunByID(ctx, run.ID)
if err != nil { if err != nil {

View File

@ -6,6 +6,7 @@ package actions
import ( import (
"context" "context"
"fmt" "fmt"
"slices"
"time" "time"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
@ -107,11 +108,11 @@ func UpdateRunJob(ctx context.Context, job *ActionRunJob, cond builder.Cond, col
return 0, err return 0, err
} }
if affected == 0 || (!util.SliceContains(cols, "status") && job.Status == 0) { if affected == 0 || (!slices.Contains(cols, "status") && job.Status == 0) {
return affected, nil return affected, nil
} }
if affected != 0 && util.SliceContains(cols, "status") && job.Status.IsWaiting() { if affected != 0 && slices.Contains(cols, "status") && job.Status.IsWaiting() {
// if the status of job changes to waiting again, increase tasks version. // if the status of job changes to waiting again, increase tasks version.
if err := IncreaseTaskVersion(ctx, job.OwnerID, job.RepoID); err != nil { if err := IncreaseTaskVersion(ctx, job.OwnerID, job.RepoID); err != nil {
return 0, err return 0, err

View File

@ -7,6 +7,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"slices"
"strings" "strings"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
@ -435,7 +436,7 @@ func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, curre
whitelist = make([]int64, 0, len(teams)) whitelist = make([]int64, 0, len(teams))
for i := range teams { for i := range teams {
if util.SliceContains(newWhitelist, teams[i].ID) { if slices.Contains(newWhitelist, teams[i].ID) {
whitelist = append(whitelist, teams[i].ID) whitelist = append(whitelist, teams[i].ID)
} }
} }

View File

@ -8,6 +8,7 @@ import (
"context" "context"
"fmt" "fmt"
"regexp" "regexp"
"slices"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
project_model "code.gitea.io/gitea/models/project" project_model "code.gitea.io/gitea/models/project"
@ -605,7 +606,7 @@ func IsUserParticipantsOfIssue(user *user_model.User, issue *Issue) bool {
log.Error(err.Error()) log.Error(err.Error())
return false return false
} }
return util.SliceContains(userIDs, user.ID) return slices.Contains(userIDs, user.ID)
} }
// DependencyInfo represents high level information about an issue which is a dependency of another issue. // DependencyInfo represents high level information about an issue which is a dependency of another issue.
@ -630,7 +631,7 @@ func (issue *Issue) GetParticipantIDsByIssue(ctx context.Context) ([]int64, erro
Find(&userIDs); err != nil { Find(&userIDs); err != nil {
return nil, fmt.Errorf("get poster IDs: %w", err) return nil, fmt.Errorf("get poster IDs: %w", err)
} }
if !util.SliceContains(userIDs, issue.PosterID) { if !slices.Contains(userIDs, issue.PosterID) {
return append(userIDs, issue.PosterID), nil return append(userIDs, issue.PosterID), nil
} }
return userIDs, nil return userIDs, nil

View File

@ -6,6 +6,7 @@ package repo
import ( import (
"context" "context"
"fmt" "fmt"
"slices"
"strings" "strings"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
@ -176,7 +177,7 @@ func (cfg *ActionsConfig) ToString() string {
} }
func (cfg *ActionsConfig) IsWorkflowDisabled(file string) bool { func (cfg *ActionsConfig) IsWorkflowDisabled(file string) bool {
return util.SliceContains(cfg.DisabledWorkflows, file) return slices.Contains(cfg.DisabledWorkflows, file)
} }
func (cfg *ActionsConfig) DisableWorkflow(file string) { func (cfg *ActionsConfig) DisableWorkflow(file string) {

View File

@ -7,6 +7,7 @@ import (
"context" "context"
"os" "os"
"runtime/pprof" "runtime/pprof"
"slices"
"sync/atomic" "sync/atomic"
"time" "time"
@ -20,7 +21,6 @@ import (
"code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/queue" "code.gitea.io/gitea/modules/queue"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
) )
var ( var (
@ -54,22 +54,22 @@ func index(ctx context.Context, indexer internal.Indexer, repoID int64) error {
} }
// skip forks from being indexed if unit is not present // skip forks from being indexed if unit is not present
if !util.SliceContains(repoTypes, "forks") && repo.IsFork { if !slices.Contains(repoTypes, "forks") && repo.IsFork {
return nil return nil
} }
// skip mirrors from being indexed if unit is not present // skip mirrors from being indexed if unit is not present
if !util.SliceContains(repoTypes, "mirrors") && repo.IsMirror { if !slices.Contains(repoTypes, "mirrors") && repo.IsMirror {
return nil return nil
} }
// skip templates from being indexed if unit is not present // skip templates from being indexed if unit is not present
if !util.SliceContains(repoTypes, "templates") && repo.IsTemplate { if !slices.Contains(repoTypes, "templates") && repo.IsTemplate {
return nil return nil
} }
// skip regular repos from being indexed if unit is not present // skip regular repos from being indexed if unit is not present
if !util.SliceContains(repoTypes, "sources") && !repo.IsFork && !repo.IsMirror && !repo.IsTemplate { if !slices.Contains(repoTypes, "sources") && !repo.IsFork && !repo.IsMirror && !repo.IsTemplate {
return nil return nil
} }

View File

@ -10,6 +10,7 @@ package tests
import ( import (
"context" "context"
"fmt" "fmt"
"slices"
"testing" "testing"
"time" "time"
@ -457,7 +458,7 @@ var cases = []*testIndexerCase{
assert.Contains(t, data[v.ID].MentionIDs, int64(1)) assert.Contains(t, data[v.ID].MentionIDs, int64(1))
} }
assert.Equal(t, countIndexerData(data, func(v *internal.IndexerData) bool { assert.Equal(t, countIndexerData(data, func(v *internal.IndexerData) bool {
return util.SliceContains(v.MentionIDs, 1) return slices.Contains(v.MentionIDs, 1)
}), result.Total) }), result.Total)
}, },
}, },
@ -478,7 +479,7 @@ var cases = []*testIndexerCase{
assert.Contains(t, data[v.ID].ReviewedIDs, int64(1)) assert.Contains(t, data[v.ID].ReviewedIDs, int64(1))
} }
assert.Equal(t, countIndexerData(data, func(v *internal.IndexerData) bool { assert.Equal(t, countIndexerData(data, func(v *internal.IndexerData) bool {
return util.SliceContains(v.ReviewedIDs, 1) return slices.Contains(v.ReviewedIDs, 1)
}), result.Total) }), result.Total)
}, },
}, },
@ -499,7 +500,7 @@ var cases = []*testIndexerCase{
assert.Contains(t, data[v.ID].ReviewRequestedIDs, int64(1)) assert.Contains(t, data[v.ID].ReviewRequestedIDs, int64(1))
} }
assert.Equal(t, countIndexerData(data, func(v *internal.IndexerData) bool { assert.Equal(t, countIndexerData(data, func(v *internal.IndexerData) bool {
return util.SliceContains(v.ReviewRequestedIDs, 1) return slices.Contains(v.ReviewRequestedIDs, 1)
}), result.Total) }), result.Total)
}, },
}, },
@ -520,7 +521,7 @@ var cases = []*testIndexerCase{
assert.Contains(t, data[v.ID].SubscriberIDs, int64(1)) assert.Contains(t, data[v.ID].SubscriberIDs, int64(1))
} }
assert.Equal(t, countIndexerData(data, func(v *internal.IndexerData) bool { assert.Equal(t, countIndexerData(data, func(v *internal.IndexerData) bool {
return util.SliceContains(v.SubscriberIDs, 1) return slices.Contains(v.SubscriberIDs, 1)
}), result.Total) }), result.Total)
}, },
}, },

View File

@ -4,11 +4,11 @@
package templates package templates
import ( import (
"slices"
"strings" "strings"
"code.gitea.io/gitea/modules/assetfs" "code.gitea.io/gitea/modules/assetfs"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
) )
func AssetFS() *assetfs.LayeredFS { func AssetFS() *assetfs.LayeredFS {
@ -24,7 +24,7 @@ func ListWebTemplateAssetNames(assets *assetfs.LayeredFS) ([]string, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return util.SliceRemoveAllFunc(files, func(file string) bool { return slices.DeleteFunc(files, func(file string) bool {
return strings.HasPrefix(file, "mail/") || !strings.HasSuffix(file, ".tmpl") return strings.HasPrefix(file, "mail/") || !strings.HasSuffix(file, ".tmpl")
}), nil }), nil
} }
@ -34,7 +34,7 @@ func ListMailTemplateAssetNames(assets *assetfs.LayeredFS) ([]string, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return util.SliceRemoveAllFunc(files, func(file string) bool { return slices.DeleteFunc(files, func(file string) bool {
return !strings.HasPrefix(file, "mail/") || !strings.HasSuffix(file, ".tmpl") return !strings.HasPrefix(file, "mail/") || !strings.HasSuffix(file, ".tmpl")
}), nil }), nil
} }

View File

@ -1,37 +1,21 @@
// Copyright 2022 The Gitea Authors. All rights reserved. // Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Most of the functions in this file can have better implementations with "golang.org/x/exp/slices".
// However, "golang.org/x/exp" is experimental and unreliable, we shouldn't use it.
// So lets waiting for the "slices" has be promoted to the main repository one day.
package util package util
import "strings" import (
"slices"
// SliceContains returns true if the target exists in the slice. "strings"
func SliceContains[T comparable](slice []T, target T) bool { )
return SliceContainsFunc(slice, func(t T) bool { return t == target })
}
// SliceContainsFunc returns true if any element in the slice satisfies the targetFunc.
func SliceContainsFunc[T any](slice []T, targetFunc func(T) bool) bool {
for _, v := range slice {
if targetFunc(v) {
return true
}
}
return false
}
// SliceContainsString sequential searches if string exists in slice. // SliceContainsString sequential searches if string exists in slice.
func SliceContainsString(slice []string, target string, insensitive ...bool) bool { func SliceContainsString(slice []string, target string, insensitive ...bool) bool {
if len(insensitive) != 0 && insensitive[0] { if len(insensitive) != 0 && insensitive[0] {
target = strings.ToLower(target) target = strings.ToLower(target)
return SliceContainsFunc(slice, func(t string) bool { return strings.ToLower(t) == target }) return slices.ContainsFunc(slice, func(t string) bool { return strings.ToLower(t) == target })
} }
return SliceContains(slice, target) return slices.Contains(slice, target)
} }
// SliceSortedEqual returns true if the two slices will be equal when they get sorted. // SliceSortedEqual returns true if the two slices will be equal when they get sorted.
@ -57,34 +41,7 @@ func SliceSortedEqual[T comparable](s1, s2 []T) bool {
return true return true
} }
// SliceEqual returns true if the two slices are equal.
func SliceEqual[T comparable](s1, s2 []T) bool {
if len(s1) != len(s2) {
return false
}
for i, v := range s1 {
if s2[i] != v {
return false
}
}
return true
}
// SliceRemoveAll removes all the target elements from the slice. // SliceRemoveAll removes all the target elements from the slice.
func SliceRemoveAll[T comparable](slice []T, target T) []T { func SliceRemoveAll[T comparable](slice []T, target T) []T {
return SliceRemoveAllFunc(slice, func(t T) bool { return t == target }) return slices.DeleteFunc(slice, func(t T) bool { return t == target })
}
// SliceRemoveAllFunc removes all elements which satisfy the targetFunc from the slice.
func SliceRemoveAllFunc[T comparable](slice []T, targetFunc func(T) bool) []T {
idx := 0
for _, v := range slice {
if targetFunc(v) {
continue
}
slice[idx] = v
idx++
}
return slice[:idx]
} }

View File

@ -9,20 +9,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestSliceContains(t *testing.T) {
assert.True(t, SliceContains([]int{2, 0, 2, 3}, 2))
assert.True(t, SliceContains([]int{2, 0, 2, 3}, 0))
assert.True(t, SliceContains([]int{2, 0, 2, 3}, 3))
assert.True(t, SliceContains([]string{"2", "0", "2", "3"}, "0"))
assert.True(t, SliceContains([]float64{2, 0, 2, 3}, 0))
assert.True(t, SliceContains([]bool{false, true, false}, true))
assert.False(t, SliceContains([]int{2, 0, 2, 3}, 4))
assert.False(t, SliceContains([]int{}, 4))
assert.False(t, SliceContains(nil, 4))
}
func TestSliceContainsString(t *testing.T) { func TestSliceContainsString(t *testing.T) {
assert.True(t, SliceContainsString([]string{"c", "b", "a", "b"}, "a")) assert.True(t, SliceContainsString([]string{"c", "b", "a", "b"}, "a"))
assert.True(t, SliceContainsString([]string{"c", "b", "a", "b"}, "b")) assert.True(t, SliceContainsString([]string{"c", "b", "a", "b"}, "b"))
@ -54,25 +40,6 @@ func TestSliceSortedEqual(t *testing.T) {
assert.False(t, SliceSortedEqual([]int{2, 0, 0, 3}, []int{2, 0, 2, 3})) assert.False(t, SliceSortedEqual([]int{2, 0, 0, 3}, []int{2, 0, 2, 3}))
} }
func TestSliceEqual(t *testing.T) {
assert.True(t, SliceEqual([]int{2, 0, 2, 3}, []int{2, 0, 2, 3}))
assert.True(t, SliceEqual([]int{}, []int{}))
assert.True(t, SliceEqual([]int(nil), nil))
assert.True(t, SliceEqual([]int(nil), []int{}))
assert.True(t, SliceEqual([]int{}, []int{}))
assert.True(t, SliceEqual([]string{"2", "0", "2", "3"}, []string{"2", "0", "2", "3"}))
assert.True(t, SliceEqual([]float64{2, 0, 2, 3}, []float64{2, 0, 2, 3}))
assert.True(t, SliceEqual([]bool{false, true, false}, []bool{false, true, false}))
assert.False(t, SliceEqual([]int{3, 0, 2, 2}, []int{2, 0, 2, 3}))
assert.False(t, SliceEqual([]int{2, 0, 2}, []int{2, 0, 2, 3}))
assert.False(t, SliceEqual([]int{}, []int{2, 0, 2, 3}))
assert.False(t, SliceEqual(nil, []int{2, 0, 2, 3}))
assert.False(t, SliceEqual([]int{2, 0, 2, 4}, []int{2, 0, 2, 3}))
assert.False(t, SliceEqual([]int{2, 0, 0, 3}, []int{2, 0, 2, 3}))
}
func TestSliceRemoveAll(t *testing.T) { func TestSliceRemoveAll(t *testing.T) {
assert.ElementsMatch(t, []int{2, 2, 3}, SliceRemoveAll([]int{2, 0, 2, 3}, 0)) assert.ElementsMatch(t, []int{2, 2, 3}, SliceRemoveAll([]int{2, 0, 2, 3}, 0))
assert.ElementsMatch(t, []int{0, 3}, SliceRemoveAll([]int{2, 0, 2, 3}, 2)) assert.ElementsMatch(t, []int{0, 3}, SliceRemoveAll([]int{2, 0, 2, 3}, 2))

View File

@ -16,6 +16,7 @@ import (
"net/http" "net/http"
"path" "path"
"regexp" "regexp"
"slices"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -265,7 +266,7 @@ func verifyDataOld(signature, data []byte, pub *rsa.PublicKey) error {
} }
} }
if !util.SliceEqual(out[skip:], data) { if !slices.Equal(out[skip:], data) {
return fmt.Errorf("could not verify signature") return fmt.Errorf("could not verify signature")
} }

View File

@ -7,6 +7,7 @@ package repo
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"slices"
"strings" "strings"
"time" "time"
@ -235,7 +236,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
} }
// If the readme template does not exist, a 400 will be returned. // If the readme template does not exist, a 400 will be returned.
if opt.AutoInit && len(opt.Readme) > 0 && !util.SliceContains(repo_module.Readmes, opt.Readme) { if opt.AutoInit && len(opt.Readme) > 0 && !slices.Contains(repo_module.Readmes, opt.Readme) {
ctx.Error(http.StatusBadRequest, "", fmt.Errorf("readme template does not exist, available templates: %v", repo_module.Readmes)) ctx.Error(http.StatusBadRequest, "", fmt.Errorf("readme template does not exist, available templates: %v", repo_module.Readmes))
return return
} }

View File

@ -12,6 +12,7 @@ import (
"math/big" "math/big"
"net/http" "net/http"
"net/url" "net/url"
"slices"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@ -3628,7 +3629,7 @@ func issuePosters(ctx *context.Context, isPullList bool) {
if search == "" && ctx.Doer != nil { if search == "" && ctx.Doer != nil {
// the returned posters slice only contains limited number of users, // the returned posters slice only contains limited number of users,
// to make the current user (doer) can quickly filter their own issues, always add doer to the posters slice // to make the current user (doer) can quickly filter their own issues, always add doer to the posters slice
if !util.SliceContainsFunc(posters, func(user *user_model.User) bool { return user.ID == ctx.Doer.ID }) { if !slices.ContainsFunc(posters, func(user *user_model.User) bool { return user.ID == ctx.Doer.ID }) {
posters = append(posters, ctx.Doer) posters = append(posters, ctx.Doer)
} }
} }

View File

@ -8,6 +8,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
"slices"
"strings" "strings"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
@ -659,7 +660,7 @@ func GetBranchesList(ctx *context.Context) {
} }
resp := &branchTagSearchResponse{} resp := &branchTagSearchResponse{}
// always put default branch on the top if it exists // always put default branch on the top if it exists
if util.SliceContains(branches, ctx.Repo.Repository.DefaultBranch) { if slices.Contains(branches, ctx.Repo.Repository.DefaultBranch) {
branches = util.SliceRemoveAll(branches, ctx.Repo.Repository.DefaultBranch) branches = util.SliceRemoveAll(branches, ctx.Repo.Repository.DefaultBranch)
branches = append([]string{ctx.Repo.Repository.DefaultBranch}, branches...) branches = append([]string{ctx.Repo.Repository.DefaultBranch}, branches...)
} }
@ -693,7 +694,7 @@ func PrepareBranchList(ctx *context.Context) {
return return
} }
// always put default branch on the top if it exists // always put default branch on the top if it exists
if util.SliceContains(brs, ctx.Repo.Repository.DefaultBranch) { if slices.Contains(brs, ctx.Repo.Repository.DefaultBranch) {
brs = util.SliceRemoveAll(brs, ctx.Repo.Repository.DefaultBranch) brs = util.SliceRemoveAll(brs, ctx.Repo.Repository.DefaultBranch)
brs = append([]string{ctx.Repo.Repository.DefaultBranch}, brs...) brs = append([]string{ctx.Repo.Repository.DefaultBranch}, brs...)
} }

View File

@ -14,6 +14,7 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"path" "path"
"slices"
"strings" "strings"
"time" "time"
@ -370,7 +371,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
if workFlowErr != nil { if workFlowErr != nil {
ctx.Data["FileError"] = ctx.Locale.Tr("actions.runs.invalid_workflow_helper", workFlowErr.Error()) ctx.Data["FileError"] = ctx.Locale.Tr("actions.runs.invalid_workflow_helper", workFlowErr.Error())
} }
} else if util.SliceContains([]string{"CODEOWNERS", "docs/CODEOWNERS", ".gitea/CODEOWNERS"}, ctx.Repo.TreePath) { } else if slices.Contains([]string{"CODEOWNERS", "docs/CODEOWNERS", ".gitea/CODEOWNERS"}, ctx.Repo.TreePath) {
if data, err := blob.GetBlobContent(setting.UI.MaxDisplayFileSize); err == nil { if data, err := blob.GetBlobContent(setting.UI.MaxDisplayFileSize); err == nil {
_, warnings := issue_model.GetCodeOwnersFromContent(ctx, data) _, warnings := issue_model.GetCodeOwnersFromContent(ctx, data)
if len(warnings) > 0 { if len(warnings) > 0 {

View File

@ -9,6 +9,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"regexp" "regexp"
"slices"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@ -290,7 +291,7 @@ func Milestones(ctx *context.Context) {
if len(repoIDs) == 0 { if len(repoIDs) == 0 {
repoIDs = showRepoIds.Values() repoIDs = showRepoIds.Values()
} }
repoIDs = util.SliceRemoveAllFunc(repoIDs, func(v int64) bool { repoIDs = slices.DeleteFunc(repoIDs, func(v int64) bool {
return !showRepoIds.Contains(v) return !showRepoIds.Contains(v)
}) })
@ -534,7 +535,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
// Gets set when clicking filters on the issues overview page. // Gets set when clicking filters on the issues overview page.
selectedRepoIDs := getRepoIDs(ctx.FormString("repos")) selectedRepoIDs := getRepoIDs(ctx.FormString("repos"))
// Remove repo IDs that are not accessible to the user. // Remove repo IDs that are not accessible to the user.
selectedRepoIDs = util.SliceRemoveAllFunc(selectedRepoIDs, func(v int64) bool { selectedRepoIDs = slices.DeleteFunc(selectedRepoIDs, func(v int64) bool {
return !accessibleRepos.Contains(v) return !accessibleRepos.Contains(v)
}) })
if len(selectedRepoIDs) > 0 { if len(selectedRepoIDs) > 0 {