Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 477a1cc

Browse files
authoredJan 11, 2023
Improve utils of slices (#22379)
- Move the file `compare.go` and `slice.go` to `slice.go`. - Fix `ExistsInSlice`, it's buggy - It uses `sort.Search`, so it assumes that the input slice is sorted. - It passes `func(i int) bool { return slice[i] == target })` to `sort.Search`, that's incorrect, check the doc of `sort.Search`. - Conbine `IsInt64InSlice(int64, []int64)` and `ExistsInSlice(string, []string)` to `SliceContains[T]([]T, T)`. - Conbine `IsSliceInt64Eq([]int64, []int64)` and `IsEqualSlice([]string, []string)` to `SliceSortedEqual[T]([]T, T)`. - Add `SliceEqual[T]([]T, T)` as a distinction from `SliceSortedEqual[T]([]T, T)`. - Redesign `RemoveIDFromList([]int64, int64) ([]int64, bool)` to `SliceRemoveAll[T]([]T, T) []T`. - Add `SliceContainsFunc[T]([]T, func(T) bool)` and `SliceRemoveAllFunc[T]([]T, func(T) bool)` for general use. - Add comments to explain why not `golang.org/x/exp/slices`. - Add unit tests.
1 parent dc5f2cf commit 477a1cc

File tree

22 files changed

+228
-182
lines changed

22 files changed

+228
-182
lines changed
 

‎cmd/admin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,7 @@ func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error {
950950
if c.IsSet("auth-type") {
951951
conf.Auth = c.String("auth-type")
952952
validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"}
953-
if !contains(validAuthTypes, strings.ToUpper(c.String("auth-type"))) {
953+
if !util.SliceContainsString(validAuthTypes, strings.ToUpper(c.String("auth-type"))) {
954954
return errors.New("Auth must be one of PLAIN/LOGIN/CRAM-MD5")
955955
}
956956
conf.Auth = c.String("auth-type")

‎cmd/dump.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -409,15 +409,6 @@ func runDump(ctx *cli.Context) error {
409409
return nil
410410
}
411411

412-
func contains(slice []string, s string) bool {
413-
for _, v := range slice {
414-
if v == s {
415-
return true
416-
}
417-
}
418-
return false
419-
}
420-
421412
// addRecursiveExclude zips absPath to specified insidePath inside writer excluding excludeAbsPath
422413
func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeAbsPath []string, verbose bool) error {
423414
absPath, err := filepath.Abs(absPath)
@@ -438,7 +429,7 @@ func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeA
438429
currentAbsPath := path.Join(absPath, file.Name())
439430
currentInsidePath := path.Join(insidePath, file.Name())
440431
if file.IsDir() {
441-
if !contains(excludeAbsPath, currentAbsPath) {
432+
if !util.SliceContainsString(excludeAbsPath, currentAbsPath) {
442433
if err := addFile(w, currentInsidePath, currentAbsPath, false); err != nil {
443434
return err
444435
}

‎models/asymkey/ssh_key.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -409,14 +409,14 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [
409409
sshKeySplit := strings.Split(v, " ")
410410
if len(sshKeySplit) > 1 {
411411
key := strings.Join(sshKeySplit[:2], " ")
412-
if !util.ExistsInSlice(key, providedKeys) {
412+
if !util.SliceContainsString(providedKeys, key) {
413413
providedKeys = append(providedKeys, key)
414414
}
415415
}
416416
}
417417

418418
// Check if Public Key sync is needed
419-
if util.IsEqualSlice(giteaKeys, providedKeys) {
419+
if util.SliceSortedEqual(giteaKeys, providedKeys) {
420420
log.Trace("synchronizePublicKeys[%s]: Public Keys are already in sync for %s (Source:%v/DB:%v)", s.Name, usr.Name, len(providedKeys), len(giteaKeys))
421421
return false
422422
}
@@ -425,7 +425,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [
425425
// Add new Public SSH Keys that doesn't already exist in DB
426426
var newKeys []string
427427
for _, key := range providedKeys {
428-
if !util.ExistsInSlice(key, giteaKeys) {
428+
if !util.SliceContainsString(giteaKeys, key) {
429429
newKeys = append(newKeys, key)
430430
}
431431
}
@@ -436,7 +436,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [
436436
// Mark keys from DB that no longer exist in the source for deletion
437437
var giteaKeysToDelete []string
438438
for _, giteaKey := range giteaKeys {
439-
if !util.ExistsInSlice(giteaKey, providedKeys) {
439+
if !util.SliceContainsString(providedKeys, giteaKey) {
440440
log.Trace("synchronizePublicKeys[%s]: Marking Public SSH Key for deletion for user %s: %v", s.Name, usr.Name, giteaKey)
441441
giteaKeysToDelete = append(giteaKeysToDelete, giteaKey)
442442
}

‎models/auth/oauth2.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ func (app *OAuth2Application) ContainsRedirectURI(redirectURI string) bool {
6969
if ip != nil && ip.IsLoopback() {
7070
// strip port
7171
uri.Host = uri.Hostname()
72-
if util.IsStringInSlice(uri.String(), app.RedirectURIs, true) {
72+
if util.SliceContainsString(app.RedirectURIs, uri.String(), true) {
7373
return true
7474
}
7575
}
7676
}
7777
}
78-
return util.IsStringInSlice(redirectURI, app.RedirectURIs, true)
78+
return util.SliceContainsString(app.RedirectURIs, redirectURI, true)
7979
}
8080

8181
// Base32 characters, but lowercased.

‎models/git/branches.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ func IsProtectedBranch(ctx context.Context, repoID int64, branchName string) (bo
342342
// updateApprovalWhitelist checks whether the user whitelist changed and returns a whitelist with
343343
// the users from newWhitelist which have explicit read or write access to the repo.
344344
func updateApprovalWhitelist(ctx context.Context, repo *repo_model.Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) {
345-
hasUsersChanged := !util.IsSliceInt64Eq(currentWhitelist, newWhitelist)
345+
hasUsersChanged := !util.SliceSortedEqual(currentWhitelist, newWhitelist)
346346
if !hasUsersChanged {
347347
return currentWhitelist, nil
348348
}
@@ -363,7 +363,7 @@ func updateApprovalWhitelist(ctx context.Context, repo *repo_model.Repository, c
363363
// updateUserWhitelist checks whether the user whitelist changed and returns a whitelist with
364364
// the users from newWhitelist which have write access to the repo.
365365
func updateUserWhitelist(ctx context.Context, repo *repo_model.Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) {
366-
hasUsersChanged := !util.IsSliceInt64Eq(currentWhitelist, newWhitelist)
366+
hasUsersChanged := !util.SliceSortedEqual(currentWhitelist, newWhitelist)
367367
if !hasUsersChanged {
368368
return currentWhitelist, nil
369369
}
@@ -392,7 +392,7 @@ func updateUserWhitelist(ctx context.Context, repo *repo_model.Repository, curre
392392
// updateTeamWhitelist checks whether the team whitelist changed and returns a whitelist with
393393
// the teams from newWhitelist which have write access to the repo.
394394
func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) {
395-
hasTeamsChanged := !util.IsSliceInt64Eq(currentWhitelist, newWhitelist)
395+
hasTeamsChanged := !util.SliceSortedEqual(currentWhitelist, newWhitelist)
396396
if !hasTeamsChanged {
397397
return currentWhitelist, nil
398398
}
@@ -404,7 +404,7 @@ func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, curre
404404

405405
whitelist = make([]int64, 0, len(teams))
406406
for i := range teams {
407-
if util.IsInt64InSlice(teams[i].ID, newWhitelist) {
407+
if util.SliceContains(newWhitelist, teams[i].ID) {
408408
whitelist = append(whitelist, teams[i].ID)
409409
}
410410
}

‎models/issues/assignees.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ func MakeIDsFromAPIAssigneesToAdd(ctx context.Context, oneAssignee string, multi
155155
var requestAssignees []string
156156

157157
// Keeping the old assigning method for compatibility reasons
158-
if oneAssignee != "" && !util.IsStringInSlice(oneAssignee, multipleAssignees) {
158+
if oneAssignee != "" && !util.SliceContainsString(multipleAssignees, oneAssignee) {
159159
requestAssignees = append(requestAssignees, oneAssignee)
160160
}
161161

‎models/issues/issue.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,7 +1529,7 @@ func IsUserParticipantsOfIssue(user *user_model.User, issue *Issue) bool {
15291529
log.Error(err.Error())
15301530
return false
15311531
}
1532-
return util.IsInt64InSlice(user.ID, userIDs)
1532+
return util.SliceContains(userIDs, user.ID)
15331533
}
15341534

15351535
// UpdateIssueMentions updates issue-user relations for mentioned users.
@@ -2023,7 +2023,7 @@ func (issue *Issue) GetParticipantIDsByIssue(ctx context.Context) ([]int64, erro
20232023
Find(&userIDs); err != nil {
20242024
return nil, fmt.Errorf("get poster IDs: %w", err)
20252025
}
2026-
if !util.IsInt64InSlice(issue.PosterID, userIDs) {
2026+
if !util.SliceContains(userIDs, issue.PosterID) {
20272027
return append(userIDs, issue.PosterID), nil
20282028
}
20292029
return userIDs, nil

‎models/org_team.go

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -398,20 +398,13 @@ func DeleteTeam(t *organization.Team) error {
398398
return fmt.Errorf("findProtectedBranches: %w", err)
399399
}
400400
for _, p := range protections {
401-
var matched1, matched2, matched3 bool
402-
if len(p.WhitelistTeamIDs) != 0 {
403-
p.WhitelistTeamIDs, matched1 = util.RemoveIDFromList(
404-
p.WhitelistTeamIDs, t.ID)
405-
}
406-
if len(p.ApprovalsWhitelistTeamIDs) != 0 {
407-
p.ApprovalsWhitelistTeamIDs, matched2 = util.RemoveIDFromList(
408-
p.ApprovalsWhitelistTeamIDs, t.ID)
409-
}
410-
if len(p.MergeWhitelistTeamIDs) != 0 {
411-
p.MergeWhitelistTeamIDs, matched3 = util.RemoveIDFromList(
412-
p.MergeWhitelistTeamIDs, t.ID)
413-
}
414-
if matched1 || matched2 || matched3 {
401+
lenIDs, lenApprovalIDs, lenMergeIDs := len(p.WhitelistTeamIDs), len(p.ApprovalsWhitelistTeamIDs), len(p.MergeWhitelistTeamIDs)
402+
p.WhitelistTeamIDs = util.SliceRemoveAll(p.WhitelistTeamIDs, t.ID)
403+
p.ApprovalsWhitelistTeamIDs = util.SliceRemoveAll(p.ApprovalsWhitelistTeamIDs, t.ID)
404+
p.MergeWhitelistTeamIDs = util.SliceRemoveAll(p.MergeWhitelistTeamIDs, t.ID)
405+
if lenIDs != len(p.WhitelistTeamIDs) ||
406+
lenApprovalIDs != len(p.ApprovalsWhitelistTeamIDs) ||
407+
lenMergeIDs != len(p.MergeWhitelistTeamIDs) {
415408
if _, err = sess.ID(p.ID).Cols(
416409
"whitelist_team_i_ds",
417410
"merge_whitelist_team_i_ds",

‎models/user.go

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -141,20 +141,13 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
141141
break
142142
}
143143
for _, p := range protections {
144-
var matched1, matched2, matched3 bool
145-
if len(p.WhitelistUserIDs) != 0 {
146-
p.WhitelistUserIDs, matched1 = util.RemoveIDFromList(
147-
p.WhitelistUserIDs, u.ID)
148-
}
149-
if len(p.ApprovalsWhitelistUserIDs) != 0 {
150-
p.ApprovalsWhitelistUserIDs, matched2 = util.RemoveIDFromList(
151-
p.ApprovalsWhitelistUserIDs, u.ID)
152-
}
153-
if len(p.MergeWhitelistUserIDs) != 0 {
154-
p.MergeWhitelistUserIDs, matched3 = util.RemoveIDFromList(
155-
p.MergeWhitelistUserIDs, u.ID)
156-
}
157-
if matched1 || matched2 || matched3 {
144+
lenIDs, lenApprovalIDs, lenMergeIDs := len(p.WhitelistUserIDs), len(p.ApprovalsWhitelistUserIDs), len(p.MergeWhitelistUserIDs)
145+
p.WhitelistUserIDs = util.SliceRemoveAll(p.WhitelistUserIDs, u.ID)
146+
p.ApprovalsWhitelistUserIDs = util.SliceRemoveAll(p.ApprovalsWhitelistUserIDs, u.ID)
147+
p.MergeWhitelistUserIDs = util.SliceRemoveAll(p.MergeWhitelistUserIDs, u.ID)
148+
if lenIDs != len(p.WhitelistUserIDs) ||
149+
lenApprovalIDs != len(p.ApprovalsWhitelistUserIDs) ||
150+
lenMergeIDs != len(p.MergeWhitelistUserIDs) {
158151
if _, err = e.ID(p.ID).Cols(
159152
"whitelist_user_i_ds",
160153
"merge_whitelist_user_i_ds",

‎modules/repository/init.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ func LoadRepoConfig() {
170170
}
171171

172172
for _, f := range customFiles {
173-
if !util.IsStringInSlice(f, files, true) {
173+
if !util.SliceContainsString(files, f, true) {
174174
files = append(files, f)
175175
}
176176
}
@@ -200,12 +200,12 @@ func LoadRepoConfig() {
200200
// Filter out invalid names and promote preferred licenses.
201201
sortedLicenses := make([]string, 0, len(Licenses))
202202
for _, name := range setting.Repository.PreferredLicenses {
203-
if util.IsStringInSlice(name, Licenses, true) {
203+
if util.SliceContainsString(Licenses, name, true) {
204204
sortedLicenses = append(sortedLicenses, name)
205205
}
206206
}
207207
for _, name := range Licenses {
208-
if !util.IsStringInSlice(name, setting.Repository.PreferredLicenses, true) {
208+
if !util.SliceContainsString(setting.Repository.PreferredLicenses, name, true) {
209209
sortedLicenses = append(sortedLicenses, name)
210210
}
211211
}

‎modules/util/compare.go

Lines changed: 0 additions & 92 deletions
This file was deleted.

‎modules/util/slice.go

Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,90 @@
11
// Copyright 2022 The Gitea Authors. All rights reserved.
22
// SPDX-License-Identifier: MIT
33

4+
// Most of the functions in this file can have better implementations with "golang.org/x/exp/slices".
5+
// However, "golang.org/x/exp" is experimental and unreliable, we shouldn't use it.
6+
// So lets waiting for the "slices" has be promoted to the main repository one day.
7+
48
package util
59

6-
// RemoveIDFromList removes the given ID from the slice, if found.
7-
// It does not preserve order, and assumes the ID is unique.
8-
func RemoveIDFromList(list []int64, id int64) ([]int64, bool) {
9-
n := len(list) - 1
10-
for i, item := range list {
11-
if item == id {
12-
list[i] = list[n]
13-
return list[:n], true
10+
import "strings"
11+
12+
// SliceContains returns true if the target exists in the slice.
13+
func SliceContains[T comparable](slice []T, target T) bool {
14+
return SliceContainsFunc(slice, func(t T) bool { return t == target })
15+
}
16+
17+
// SliceContainsFunc returns true if any element in the slice satisfies the targetFunc.
18+
func SliceContainsFunc[T any](slice []T, targetFunc func(T) bool) bool {
19+
for _, v := range slice {
20+
if targetFunc(v) {
21+
return true
22+
}
23+
}
24+
return false
25+
}
26+
27+
// SliceContainsString sequential searches if string exists in slice.
28+
func SliceContainsString(slice []string, target string, insensitive ...bool) bool {
29+
if len(insensitive) != 0 && insensitive[0] {
30+
target = strings.ToLower(target)
31+
return SliceContainsFunc(slice, func(t string) bool { return strings.ToLower(t) == target })
32+
}
33+
34+
return SliceContains(slice, target)
35+
}
36+
37+
// SliceSortedEqual returns true if the two slices will be equal when they get sorted.
38+
// It doesn't require that the slices have been sorted, and it doesn't sort them either.
39+
func SliceSortedEqual[T comparable](s1, s2 []T) bool {
40+
if len(s1) != len(s2) {
41+
return false
42+
}
43+
44+
counts := make(map[T]int, len(s1))
45+
for _, v := range s1 {
46+
counts[v]++
47+
}
48+
for _, v := range s2 {
49+
counts[v]--
50+
}
51+
52+
for _, v := range counts {
53+
if v != 0 {
54+
return false
55+
}
56+
}
57+
return true
58+
}
59+
60+
// SliceEqual returns true if the two slices are equal.
61+
func SliceEqual[T comparable](s1, s2 []T) bool {
62+
if len(s1) != len(s2) {
63+
return false
64+
}
65+
66+
for i, v := range s1 {
67+
if s2[i] != v {
68+
return false
69+
}
70+
}
71+
return true
72+
}
73+
74+
// SliceRemoveAll removes all the target elements from the slice.
75+
func SliceRemoveAll[T comparable](slice []T, target T) []T {
76+
return SliceRemoveAllFunc(slice, func(t T) bool { return t == target })
77+
}
78+
79+
// SliceRemoveAllFunc removes all elements which satisfy the targetFunc from the slice.
80+
func SliceRemoveAllFunc[T comparable](slice []T, targetFunc func(T) bool) []T {
81+
idx := 0
82+
for _, v := range slice {
83+
if targetFunc(v) {
84+
continue
1485
}
86+
slice[idx] = v
87+
idx++
1588
}
16-
return list, false
89+
return slice[:idx]
1790
}

‎modules/util/slice_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package util
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestSliceContains(t *testing.T) {
13+
assert.True(t, SliceContains([]int{2, 0, 2, 3}, 2))
14+
assert.True(t, SliceContains([]int{2, 0, 2, 3}, 0))
15+
assert.True(t, SliceContains([]int{2, 0, 2, 3}, 3))
16+
17+
assert.True(t, SliceContains([]string{"2", "0", "2", "3"}, "0"))
18+
assert.True(t, SliceContains([]float64{2, 0, 2, 3}, 0))
19+
assert.True(t, SliceContains([]bool{false, true, false}, true))
20+
21+
assert.False(t, SliceContains([]int{2, 0, 2, 3}, 4))
22+
assert.False(t, SliceContains([]int{}, 4))
23+
assert.False(t, SliceContains(nil, 4))
24+
}
25+
26+
func TestSliceContainsString(t *testing.T) {
27+
assert.True(t, SliceContainsString([]string{"c", "b", "a", "b"}, "a"))
28+
assert.True(t, SliceContainsString([]string{"c", "b", "a", "b"}, "b"))
29+
assert.True(t, SliceContainsString([]string{"c", "b", "a", "b"}, "A", true))
30+
assert.True(t, SliceContainsString([]string{"C", "B", "A", "B"}, "a", true))
31+
32+
assert.False(t, SliceContainsString([]string{"c", "b", "a", "b"}, "z"))
33+
assert.False(t, SliceContainsString([]string{"c", "b", "a", "b"}, "A"))
34+
assert.False(t, SliceContainsString([]string{}, "a"))
35+
assert.False(t, SliceContainsString(nil, "a"))
36+
}
37+
38+
func TestSliceSortedEqual(t *testing.T) {
39+
assert.True(t, SliceSortedEqual([]int{2, 0, 2, 3}, []int{2, 0, 2, 3}))
40+
assert.True(t, SliceSortedEqual([]int{3, 0, 2, 2}, []int{2, 0, 2, 3}))
41+
assert.True(t, SliceSortedEqual([]int{}, []int{}))
42+
assert.True(t, SliceSortedEqual([]int(nil), nil))
43+
assert.True(t, SliceSortedEqual([]int(nil), []int{}))
44+
assert.True(t, SliceSortedEqual([]int{}, []int{}))
45+
46+
assert.True(t, SliceSortedEqual([]string{"2", "0", "2", "3"}, []string{"2", "0", "2", "3"}))
47+
assert.True(t, SliceSortedEqual([]float64{2, 0, 2, 3}, []float64{2, 0, 2, 3}))
48+
assert.True(t, SliceSortedEqual([]bool{false, true, false}, []bool{false, true, false}))
49+
50+
assert.False(t, SliceSortedEqual([]int{2, 0, 2}, []int{2, 0, 2, 3}))
51+
assert.False(t, SliceSortedEqual([]int{}, []int{2, 0, 2, 3}))
52+
assert.False(t, SliceSortedEqual(nil, []int{2, 0, 2, 3}))
53+
assert.False(t, SliceSortedEqual([]int{2, 0, 2, 4}, []int{2, 0, 2, 3}))
54+
assert.False(t, SliceSortedEqual([]int{2, 0, 0, 3}, []int{2, 0, 2, 3}))
55+
}
56+
57+
func TestSliceEqual(t *testing.T) {
58+
assert.True(t, SliceEqual([]int{2, 0, 2, 3}, []int{2, 0, 2, 3}))
59+
assert.True(t, SliceEqual([]int{}, []int{}))
60+
assert.True(t, SliceEqual([]int(nil), nil))
61+
assert.True(t, SliceEqual([]int(nil), []int{}))
62+
assert.True(t, SliceEqual([]int{}, []int{}))
63+
64+
assert.True(t, SliceEqual([]string{"2", "0", "2", "3"}, []string{"2", "0", "2", "3"}))
65+
assert.True(t, SliceEqual([]float64{2, 0, 2, 3}, []float64{2, 0, 2, 3}))
66+
assert.True(t, SliceEqual([]bool{false, true, false}, []bool{false, true, false}))
67+
68+
assert.False(t, SliceEqual([]int{3, 0, 2, 2}, []int{2, 0, 2, 3}))
69+
assert.False(t, SliceEqual([]int{2, 0, 2}, []int{2, 0, 2, 3}))
70+
assert.False(t, SliceEqual([]int{}, []int{2, 0, 2, 3}))
71+
assert.False(t, SliceEqual(nil, []int{2, 0, 2, 3}))
72+
assert.False(t, SliceEqual([]int{2, 0, 2, 4}, []int{2, 0, 2, 3}))
73+
assert.False(t, SliceEqual([]int{2, 0, 0, 3}, []int{2, 0, 2, 3}))
74+
}
75+
76+
func TestSliceRemoveAll(t *testing.T) {
77+
assert.Equal(t, SliceRemoveAll([]int{2, 0, 2, 3}, 0), []int{2, 2, 3})
78+
assert.Equal(t, SliceRemoveAll([]int{2, 0, 2, 3}, 2), []int{0, 3})
79+
assert.Equal(t, SliceRemoveAll([]int{0, 0, 0, 0}, 0), []int{})
80+
assert.Equal(t, SliceRemoveAll([]int{2, 0, 2, 3}, 4), []int{2, 0, 2, 3})
81+
assert.Equal(t, SliceRemoveAll([]int{}, 0), []int{})
82+
assert.Equal(t, SliceRemoveAll([]int(nil), 0), []int(nil))
83+
assert.Equal(t, SliceRemoveAll([]int{}, 0), []int{})
84+
85+
assert.Equal(t, SliceRemoveAll([]string{"2", "0", "2", "3"}, "0"), []string{"2", "2", "3"})
86+
assert.Equal(t, SliceRemoveAll([]float64{2, 0, 2, 3}, 0), []float64{2, 2, 3})
87+
assert.Equal(t, SliceRemoveAll([]bool{false, true, false}, true), []bool{false, false})
88+
}

‎routers/api/v1/utils/hook.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,11 @@ func toAPIHook(ctx *context.APIContext, repoLink string, hook *webhook.Webhook)
107107
}
108108

109109
func issuesHook(events []string, event string) bool {
110-
return util.IsStringInSlice(event, events, true) || util.IsStringInSlice(string(webhook_module.HookEventIssues), events, true)
110+
return util.SliceContainsString(events, event, true) || util.SliceContainsString(events, string(webhook_module.HookEventIssues), true)
111111
}
112112

113113
func pullHook(events []string, event string) bool {
114-
return util.IsStringInSlice(event, events, true) || util.IsStringInSlice(string(webhook_module.HookEventPullRequest), events, true)
114+
return util.SliceContainsString(events, event, true) || util.SliceContainsString(events, string(webhook_module.HookEventPullRequest), true)
115115
}
116116

117117
// addHook add the hook specified by `form`, `orgID` and `repoID`. If there is
@@ -130,25 +130,25 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID
130130
HookEvent: &webhook_module.HookEvent{
131131
ChooseEvents: true,
132132
HookEvents: webhook_module.HookEvents{
133-
Create: util.IsStringInSlice(string(webhook_module.HookEventCreate), form.Events, true),
134-
Delete: util.IsStringInSlice(string(webhook_module.HookEventDelete), form.Events, true),
135-
Fork: util.IsStringInSlice(string(webhook_module.HookEventFork), form.Events, true),
133+
Create: util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true),
134+
Delete: util.SliceContainsString(form.Events, string(webhook_module.HookEventDelete), true),
135+
Fork: util.SliceContainsString(form.Events, string(webhook_module.HookEventFork), true),
136136
Issues: issuesHook(form.Events, "issues_only"),
137137
IssueAssign: issuesHook(form.Events, string(webhook_module.HookEventIssueAssign)),
138138
IssueLabel: issuesHook(form.Events, string(webhook_module.HookEventIssueLabel)),
139139
IssueMilestone: issuesHook(form.Events, string(webhook_module.HookEventIssueMilestone)),
140140
IssueComment: issuesHook(form.Events, string(webhook_module.HookEventIssueComment)),
141-
Push: util.IsStringInSlice(string(webhook_module.HookEventPush), form.Events, true),
141+
Push: util.SliceContainsString(form.Events, string(webhook_module.HookEventPush), true),
142142
PullRequest: pullHook(form.Events, "pull_request_only"),
143143
PullRequestAssign: pullHook(form.Events, string(webhook_module.HookEventPullRequestAssign)),
144144
PullRequestLabel: pullHook(form.Events, string(webhook_module.HookEventPullRequestLabel)),
145145
PullRequestMilestone: pullHook(form.Events, string(webhook_module.HookEventPullRequestMilestone)),
146146
PullRequestComment: pullHook(form.Events, string(webhook_module.HookEventPullRequestComment)),
147147
PullRequestReview: pullHook(form.Events, "pull_request_review"),
148148
PullRequestSync: pullHook(form.Events, string(webhook_module.HookEventPullRequestSync)),
149-
Wiki: util.IsStringInSlice(string(webhook_module.HookEventWiki), form.Events, true),
150-
Repository: util.IsStringInSlice(string(webhook_module.HookEventRepository), form.Events, true),
151-
Release: util.IsStringInSlice(string(webhook_module.HookEventRelease), form.Events, true),
149+
Wiki: util.SliceContainsString(form.Events, string(webhook_module.HookEventWiki), true),
150+
Repository: util.SliceContainsString(form.Events, string(webhook_module.HookEventRepository), true),
151+
Release: util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true),
152152
},
153153
BranchFilter: form.BranchFilter,
154154
},
@@ -277,14 +277,14 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webh
277277
w.PushOnly = false
278278
w.SendEverything = false
279279
w.ChooseEvents = true
280-
w.Create = util.IsStringInSlice(string(webhook_module.HookEventCreate), form.Events, true)
281-
w.Push = util.IsStringInSlice(string(webhook_module.HookEventPush), form.Events, true)
282-
w.Create = util.IsStringInSlice(string(webhook_module.HookEventCreate), form.Events, true)
283-
w.Delete = util.IsStringInSlice(string(webhook_module.HookEventDelete), form.Events, true)
284-
w.Fork = util.IsStringInSlice(string(webhook_module.HookEventFork), form.Events, true)
285-
w.Repository = util.IsStringInSlice(string(webhook_module.HookEventRepository), form.Events, true)
286-
w.Wiki = util.IsStringInSlice(string(webhook_module.HookEventWiki), form.Events, true)
287-
w.Release = util.IsStringInSlice(string(webhook_module.HookEventRelease), form.Events, true)
280+
w.Create = util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true)
281+
w.Push = util.SliceContainsString(form.Events, string(webhook_module.HookEventPush), true)
282+
w.Create = util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true)
283+
w.Delete = util.SliceContainsString(form.Events, string(webhook_module.HookEventDelete), true)
284+
w.Fork = util.SliceContainsString(form.Events, string(webhook_module.HookEventFork), true)
285+
w.Repository = util.SliceContainsString(form.Events, string(webhook_module.HookEventRepository), true)
286+
w.Wiki = util.SliceContainsString(form.Events, string(webhook_module.HookEventWiki), true)
287+
w.Release = util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true)
288288
w.BranchFilter = form.BranchFilter
289289

290290
err := w.SetHeaderAuthorization(form.AuthorizationHeader)

‎routers/web/repo/issue.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
139139
viewType := ctx.FormString("type")
140140
sortType := ctx.FormString("sort")
141141
types := []string{"all", "your_repositories", "assigned", "created_by", "mentioned", "review_requested"}
142-
if !util.IsStringInSlice(viewType, types, true) {
142+
if !util.SliceContainsString(types, viewType, true) {
143143
viewType = "all"
144144
}
145145

@@ -3087,7 +3087,7 @@ func updateAttachments(ctx *context.Context, item interface{}, files []string) e
30873087
return fmt.Errorf("unknown Type: %T", content)
30883088
}
30893089
for i := 0; i < len(attachments); i++ {
3090-
if util.IsStringInSlice(attachments[i].UUID, files) {
3090+
if util.SliceContainsString(files, attachments[i].UUID) {
30913091
continue
30923092
}
30933093
if err := repo_model.DeleteAttachment(attachments[i], true); err != nil {

‎routers/web/repo/webhook.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func getOrgRepoCtx(ctx *context.Context) (*orgRepoCtx, error) {
110110

111111
func checkHookType(ctx *context.Context) string {
112112
hookType := strings.ToLower(ctx.Params(":type"))
113-
if !util.IsStringInSlice(hookType, setting.Webhook.Types, true) {
113+
if !util.SliceContainsString(setting.Webhook.Types, hookType, true) {
114114
ctx.NotFound("checkHookType", nil)
115115
return ""
116116
}

‎routers/web/user/notification.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ func NotificationSubscriptions(ctx *context.Context) {
214214
ctx.Data["SortType"] = sortType
215215

216216
state := ctx.FormString("state")
217-
if !util.IsStringInSlice(state, []string{"all", "open", "closed"}, true) {
217+
if !util.SliceContainsString([]string{"all", "open", "closed"}, state, true) {
218218
state = "all"
219219
}
220220
ctx.Data["State"] = state

‎routers/web/user/setting/profile.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ func UpdateUserLang(ctx *context.Context) {
413413
ctx.Data["PageIsSettingsAppearance"] = true
414414

415415
if len(form.Language) != 0 {
416-
if !util.IsStringInSlice(form.Language, setting.Langs) {
416+
if !util.SliceContainsString(setting.Langs, form.Language) {
417417
ctx.Flash.Error(ctx.Tr("settings.update_language_not_found", form.Language))
418418
ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
419419
return

‎services/auth/source/ldap/source_search.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ func (source *Source) getMappedMemberships(l *ldap.Conn, uid string) (map[string
246246
membershipsToAdd := map[string][]string{}
247247
membershipsToRemove := map[string][]string{}
248248
for group, memberships := range ldapGroupsToTeams {
249-
isUserInGroup := util.IsStringInSlice(group, usersLdapGroups)
249+
isUserInGroup := util.SliceContainsString(usersLdapGroups, group)
250250
if isUserInGroup {
251251
for org, teams := range memberships {
252252
membershipsToAdd[org] = teams

‎services/auth/source/smtp/source_authenticate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func (source *Source) Authenticate(user *user_model.User, userName, password str
2323
idx := strings.Index(userName, "@")
2424
if idx == -1 {
2525
return nil, user_model.ErrUserNotExist{Name: userName}
26-
} else if !util.IsStringInSlice(userName[idx+1:], strings.Split(source.AllowedDomains, ","), true) {
26+
} else if !util.SliceContainsString(strings.Split(source.AllowedDomains, ","), userName[idx+1:], true) {
2727
return nil, user_model.ErrUserNotExist{Name: userName}
2828
}
2929
}

‎services/wiki/wiki.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const (
3535
)
3636

3737
func nameAllowed(name string) error {
38-
if util.IsStringInSlice(name, reservedWikiNames) {
38+
if util.SliceContainsString(reservedWikiNames, name) {
3939
return repo_model.ErrWikiReservedName{
4040
Title: name,
4141
}

‎tests/integration/api_repo_teams_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func TestAPIRepoTeams(t *testing.T) {
3838
if assert.Len(t, teams, 2) {
3939
assert.EqualValues(t, "Owners", teams[0].Name)
4040
assert.True(t, teams[0].CanCreateOrgRepo)
41-
assert.True(t, util.IsEqualSlice(unit.AllUnitKeyNames(), teams[0].Units), fmt.Sprintf("%v == %v", unit.AllUnitKeyNames(), teams[0].Units))
41+
assert.True(t, util.SliceSortedEqual(unit.AllUnitKeyNames(), teams[0].Units), fmt.Sprintf("%v == %v", unit.AllUnitKeyNames(), teams[0].Units))
4242
assert.EqualValues(t, "owner", teams[0].Permission)
4343

4444
assert.EqualValues(t, "test_team", teams[1].Name)

0 commit comments

Comments
 (0)
Please sign in to comment.