From 972e934ad9934f4bb7848889f3c0271fcca03004 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 15:51:30 +0800 Subject: [PATCH 01/21] chore: use IsStringInSlice --- cmd/admin.go | 2 +- cmd/dump.go | 11 +---------- models/asymkey/ssh_key.go | 6 +++--- modules/util/compare.go | 7 ++++--- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/cmd/admin.go b/cmd/admin.go index 7463b21d81ab6..1a4e09cf7c0b3 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -950,7 +950,7 @@ func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error { if c.IsSet("auth-type") { conf.Auth = c.String("auth-type") validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"} - if !contains(validAuthTypes, strings.ToUpper(c.String("auth-type"))) { + if !util.IsStringInSlice(strings.ToUpper(c.String("auth-type")), validAuthTypes) { return errors.New("Auth must be one of PLAIN/LOGIN/CRAM-MD5") } conf.Auth = c.String("auth-type") diff --git a/cmd/dump.go b/cmd/dump.go index 672a8cdc9c21c..de5bf08808f07 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -409,15 +409,6 @@ func runDump(ctx *cli.Context) error { return nil } -func contains(slice []string, s string) bool { - for _, v := range slice { - if v == s { - return true - } - } - return false -} - // addRecursiveExclude zips absPath to specified insidePath inside writer excluding excludeAbsPath func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeAbsPath []string, verbose bool) error { absPath, err := filepath.Abs(absPath) @@ -438,7 +429,7 @@ func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeA currentAbsPath := path.Join(absPath, file.Name()) currentInsidePath := path.Join(insidePath, file.Name()) if file.IsDir() { - if !contains(excludeAbsPath, currentAbsPath) { + if !util.IsStringInSlice(currentAbsPath, excludeAbsPath) { if err := addFile(w, currentInsidePath, currentAbsPath, false); err != nil { return err } diff --git a/models/asymkey/ssh_key.go b/models/asymkey/ssh_key.go index 4d6ae8103cd8e..87711100a0a08 100644 --- a/models/asymkey/ssh_key.go +++ b/models/asymkey/ssh_key.go @@ -409,7 +409,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [ sshKeySplit := strings.Split(v, " ") if len(sshKeySplit) > 1 { key := strings.Join(sshKeySplit[:2], " ") - if !util.ExistsInSlice(key, providedKeys) { + if !util.IsStringInSlice(key, providedKeys) { providedKeys = append(providedKeys, key) } } @@ -425,7 +425,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [ // Add new Public SSH Keys that doesn't already exist in DB var newKeys []string for _, key := range providedKeys { - if !util.ExistsInSlice(key, giteaKeys) { + if !util.IsStringInSlice(key, giteaKeys) { newKeys = append(newKeys, key) } } @@ -436,7 +436,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [ // Mark keys from DB that no longer exist in the source for deletion var giteaKeysToDelete []string for _, giteaKey := range giteaKeys { - if !util.ExistsInSlice(giteaKey, providedKeys) { + if !util.IsStringInSlice(giteaKey, providedKeys) { log.Trace("synchronizePublicKeys[%s]: Marking Public SSH Key for deletion for user %s: %v", s.Name, usr.Name, giteaKey) giteaKeysToDelete = append(giteaKeysToDelete, giteaKey) } diff --git a/modules/util/compare.go b/modules/util/compare.go index 9ac778dfd3ef2..f997598e41a95 100644 --- a/modules/util/compare.go +++ b/modules/util/compare.go @@ -32,9 +32,10 @@ func IsSliceInt64Eq(a, b []int64) bool { // ExistsInSlice returns true if string exists in slice. func ExistsInSlice(target string, slice []string) bool { - i := sort.Search(len(slice), - func(i int) bool { return slice[i] == target }) - return i < len(slice) + panic("it's incorrect") + //i := sort.Search(len(slice), + // func(i int) bool { return slice[i] == target }) + //return i < len(slice) } // IsStringInSlice sequential searches if string exists in slice. From 2e8a26360ea835656a259238524951bd387b7388 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 16:22:37 +0800 Subject: [PATCH 02/21] feat: IsInSlice --- modules/util/compare.go | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/modules/util/compare.go b/modules/util/compare.go index f997598e41a95..4c96d59e1d813 100644 --- a/modules/util/compare.go +++ b/modules/util/compare.go @@ -30,34 +30,29 @@ func IsSliceInt64Eq(a, b []int64) bool { return true } -// ExistsInSlice returns true if string exists in slice. -func ExistsInSlice(target string, slice []string) bool { - panic("it's incorrect") - //i := sort.Search(len(slice), - // func(i int) bool { return slice[i] == target }) - //return i < len(slice) +// IsInSlice returns true if the target exists in the slice. +func IsInSlice[T comparable](target T, slice []T) bool { + return IsInSliceFunc(func(t T) bool { return t == target }, slice) +} + +// IsInSliceFunc returns true if any element in the slice satisfies the targetF. +func IsInSliceFunc[T comparable](targetF func(T) bool, slice []T) bool { + for _, v := range slice { + if targetF(v) { + return true + } + } + return false } // IsStringInSlice sequential searches if string exists in slice. func IsStringInSlice(target string, slice []string, insensitive ...bool) bool { - caseInsensitive := false if len(insensitive) != 0 && insensitive[0] { - caseInsensitive = true target = strings.ToLower(target) + return IsInSliceFunc(func(t string) bool { return strings.ToLower(t) == target }, slice) } - for i := 0; i < len(slice); i++ { - if caseInsensitive { - if strings.ToLower(slice[i]) == target { - return true - } - } else { - if slice[i] == target { - return true - } - } - } - return false + return IsInSlice(target, slice) } // IsInt64InSlice sequential searches if int64 exists in slice. From 7dac83b86bf147f294896aebf66fe2d970f6c7a4 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 16:24:33 +0800 Subject: [PATCH 03/21] feat: replace IsInt64InSlice --- models/git/branches.go | 2 +- models/issues/issue.go | 4 ++-- modules/util/compare.go | 10 ---------- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/models/git/branches.go b/models/git/branches.go index 2becbc3d13dd8..68cf7571db5df 100644 --- a/models/git/branches.go +++ b/models/git/branches.go @@ -404,7 +404,7 @@ func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, curre whitelist = make([]int64, 0, len(teams)) for i := range teams { - if util.IsInt64InSlice(teams[i].ID, newWhitelist) { + if util.IsInSlice(teams[i].ID, newWhitelist) { whitelist = append(whitelist, teams[i].ID) } } diff --git a/models/issues/issue.go b/models/issues/issue.go index 417d6a1557892..fa2d85b8d337f 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -1529,7 +1529,7 @@ func IsUserParticipantsOfIssue(user *user_model.User, issue *Issue) bool { log.Error(err.Error()) return false } - return util.IsInt64InSlice(user.ID, userIDs) + return util.IsInSlice(user.ID, userIDs) } // UpdateIssueMentions updates issue-user relations for mentioned users. @@ -2023,7 +2023,7 @@ func (issue *Issue) GetParticipantIDsByIssue(ctx context.Context) ([]int64, erro Find(&userIDs); err != nil { return nil, fmt.Errorf("get poster IDs: %w", err) } - if !util.IsInt64InSlice(issue.PosterID, userIDs) { + if !util.IsInSlice(issue.PosterID, userIDs) { return append(userIDs, issue.PosterID), nil } return userIDs, nil diff --git a/modules/util/compare.go b/modules/util/compare.go index 4c96d59e1d813..c31821b50fae8 100644 --- a/modules/util/compare.go +++ b/modules/util/compare.go @@ -55,16 +55,6 @@ func IsStringInSlice(target string, slice []string, insensitive ...bool) bool { return IsInSlice(target, slice) } -// IsInt64InSlice sequential searches if int64 exists in slice. -func IsInt64InSlice(target int64, slice []int64) bool { - for i := 0; i < len(slice); i++ { - if slice[i] == target { - return true - } - } - return false -} - // IsEqualSlice returns true if slices are equal. func IsEqualSlice(target, source []string) bool { if len(target) != len(source) { From 6cb8d32ab28d8f1bbe45729f48f3ceae3f1c15dc Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 16:31:51 +0800 Subject: [PATCH 04/21] feat: new IsEqualSlice --- modules/util/compare.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/modules/util/compare.go b/modules/util/compare.go index c31821b50fae8..2d1ffdac7dede 100644 --- a/modules/util/compare.go +++ b/modules/util/compare.go @@ -56,7 +56,7 @@ func IsStringInSlice(target string, slice []string, insensitive ...bool) bool { } // IsEqualSlice returns true if slices are equal. -func IsEqualSlice(target, source []string) bool { +func IsEqualSlice[T comparable](target, source []T) bool { if len(target) != len(source) { return false } @@ -65,14 +65,18 @@ func IsEqualSlice(target, source []string) bool { return false } - sort.Strings(target) - sort.Strings(source) + counts := make(map[T]int, len(target)) + for _, v := range target { + counts[v]++ + } + for _, v := range source { + counts[v]-- + } - for i, v := range target { - if v != source[i] { + for _, v := range counts { + if v != 0 { return false } } - return true } From 8f3f1cef85186e84b237615f2dd1d698c1433bcf Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 16:47:54 +0800 Subject: [PATCH 05/21] repalce: IsSliceInt64Eq --- models/git/branches.go | 6 +++--- modules/util/compare.go | 23 ----------------------- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/models/git/branches.go b/models/git/branches.go index 68cf7571db5df..a9215b0ed4ae0 100644 --- a/models/git/branches.go +++ b/models/git/branches.go @@ -342,7 +342,7 @@ func IsProtectedBranch(ctx context.Context, repoID int64, branchName string) (bo // updateApprovalWhitelist checks whether the user whitelist changed and returns a whitelist with // the users from newWhitelist which have explicit read or write access to the repo. func updateApprovalWhitelist(ctx context.Context, repo *repo_model.Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) { - hasUsersChanged := !util.IsSliceInt64Eq(currentWhitelist, newWhitelist) + hasUsersChanged := !util.IsEqualSlice(currentWhitelist, newWhitelist) if !hasUsersChanged { return currentWhitelist, nil } @@ -363,7 +363,7 @@ func updateApprovalWhitelist(ctx context.Context, repo *repo_model.Repository, c // updateUserWhitelist checks whether the user whitelist changed and returns a whitelist with // the users from newWhitelist which have write access to the repo. func updateUserWhitelist(ctx context.Context, repo *repo_model.Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) { - hasUsersChanged := !util.IsSliceInt64Eq(currentWhitelist, newWhitelist) + hasUsersChanged := !util.IsEqualSlice(currentWhitelist, newWhitelist) if !hasUsersChanged { return currentWhitelist, nil } @@ -392,7 +392,7 @@ func updateUserWhitelist(ctx context.Context, repo *repo_model.Repository, curre // updateTeamWhitelist checks whether the team whitelist changed and returns a whitelist with // the teams from newWhitelist which have write access to the repo. func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) { - hasTeamsChanged := !util.IsSliceInt64Eq(currentWhitelist, newWhitelist) + hasTeamsChanged := !util.IsEqualSlice(currentWhitelist, newWhitelist) if !hasTeamsChanged { return currentWhitelist, nil } diff --git a/modules/util/compare.go b/modules/util/compare.go index 2d1ffdac7dede..38bda9427f593 100644 --- a/modules/util/compare.go +++ b/modules/util/compare.go @@ -4,32 +4,9 @@ package util import ( - "sort" "strings" ) -// Int64Slice attaches the methods of Interface to []int64, sorting in increasing order. -type Int64Slice []int64 - -func (p Int64Slice) Len() int { return len(p) } -func (p Int64Slice) Less(i, j int) bool { return p[i] < p[j] } -func (p Int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } - -// IsSliceInt64Eq returns if the two slice has the same elements but different sequences. -func IsSliceInt64Eq(a, b []int64) bool { - if len(a) != len(b) { - return false - } - sort.Sort(Int64Slice(a)) - sort.Sort(Int64Slice(b)) - for i := 0; i < len(a); i++ { - if a[i] != b[i] { - return false - } - } - return true -} - // IsInSlice returns true if the target exists in the slice. func IsInSlice[T comparable](target T, slice []T) bool { return IsInSliceFunc(func(t T) bool { return t == target }, slice) From 273f32ecd94f52d706c1ec70ef2f6d2460303f38 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 16:53:08 +0800 Subject: [PATCH 06/21] chore: add comment --- modules/util/compare.go | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/util/compare.go b/modules/util/compare.go index 38bda9427f593..2eaae0ce5de6f 100644 --- a/modules/util/compare.go +++ b/modules/util/compare.go @@ -33,6 +33,7 @@ func IsStringInSlice(target string, slice []string, insensitive ...bool) bool { } // IsEqualSlice returns true if slices are equal. +// Be careful, two slice has the same elements but different order are considered equal here. func IsEqualSlice[T comparable](target, source []T) bool { if len(target) != len(source) { return false From 7136481865ffb734acc3a87b42b1d99c4cf82d6c Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 16:56:13 +0800 Subject: [PATCH 07/21] chore: conbine files to slice.go --- modules/util/compare.go | 60 ----------------------------------------- modules/util/slice.go | 54 +++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 60 deletions(-) delete mode 100644 modules/util/compare.go diff --git a/modules/util/compare.go b/modules/util/compare.go deleted file mode 100644 index 2eaae0ce5de6f..0000000000000 --- a/modules/util/compare.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2017 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package util - -import ( - "strings" -) - -// IsInSlice returns true if the target exists in the slice. -func IsInSlice[T comparable](target T, slice []T) bool { - return IsInSliceFunc(func(t T) bool { return t == target }, slice) -} - -// IsInSliceFunc returns true if any element in the slice satisfies the targetF. -func IsInSliceFunc[T comparable](targetF func(T) bool, slice []T) bool { - for _, v := range slice { - if targetF(v) { - return true - } - } - return false -} - -// IsStringInSlice sequential searches if string exists in slice. -func IsStringInSlice(target string, slice []string, insensitive ...bool) bool { - if len(insensitive) != 0 && insensitive[0] { - target = strings.ToLower(target) - return IsInSliceFunc(func(t string) bool { return strings.ToLower(t) == target }, slice) - } - - return IsInSlice(target, slice) -} - -// IsEqualSlice returns true if slices are equal. -// Be careful, two slice has the same elements but different order are considered equal here. -func IsEqualSlice[T comparable](target, source []T) bool { - if len(target) != len(source) { - return false - } - - if (target == nil) != (source == nil) { - return false - } - - counts := make(map[T]int, len(target)) - for _, v := range target { - counts[v]++ - } - for _, v := range source { - counts[v]-- - } - - for _, v := range counts { - if v != 0 { - return false - } - } - return true -} diff --git a/modules/util/slice.go b/modules/util/slice.go index 17345cbc49d97..80bff1dfb02d1 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -3,6 +3,60 @@ package util +import "strings" + +// IsInSlice returns true if the target exists in the slice. +func IsInSlice[T comparable](target T, slice []T) bool { + return IsInSliceFunc(func(t T) bool { return t == target }, slice) +} + +// IsInSliceFunc returns true if any element in the slice satisfies the targetF. +func IsInSliceFunc[T comparable](targetF func(T) bool, slice []T) bool { + for _, v := range slice { + if targetF(v) { + return true + } + } + return false +} + +// IsStringInSlice sequential searches if string exists in slice. +func IsStringInSlice(target string, slice []string, insensitive ...bool) bool { + if len(insensitive) != 0 && insensitive[0] { + target = strings.ToLower(target) + return IsInSliceFunc(func(t string) bool { return strings.ToLower(t) == target }, slice) + } + + return IsInSlice(target, slice) +} + +// IsEqualSlice returns true if slices are equal. +// Be careful, two slice has the same elements but different order are considered equal here. +func IsEqualSlice[T comparable](target, source []T) bool { + if len(target) != len(source) { + return false + } + + if (target == nil) != (source == nil) { + return false + } + + counts := make(map[T]int, len(target)) + for _, v := range target { + counts[v]++ + } + for _, v := range source { + counts[v]-- + } + + for _, v := range counts { + if v != 0 { + return false + } + } + return true +} + // RemoveIDFromList removes the given ID from the slice, if found. // It does not preserve order, and assumes the ID is unique. func RemoveIDFromList(list []int64, id int64) ([]int64, bool) { From d2d83e4bda40e63d02c2d08601a4e5ed238e6e94 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 17:26:59 +0800 Subject: [PATCH 08/21] feat: RemoveFromSlice --- modules/util/slice.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/modules/util/slice.go b/modules/util/slice.go index 80bff1dfb02d1..6a5008b2fe865 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -10,10 +10,10 @@ func IsInSlice[T comparable](target T, slice []T) bool { return IsInSliceFunc(func(t T) bool { return t == target }, slice) } -// IsInSliceFunc returns true if any element in the slice satisfies the targetF. -func IsInSliceFunc[T comparable](targetF func(T) bool, slice []T) bool { +// IsInSliceFunc returns true if any element in the slice satisfies the targetFunc. +func IsInSliceFunc[T comparable](targetFunc func(T) bool, slice []T) bool { for _, v := range slice { - if targetF(v) { + if targetFunc(v) { return true } } @@ -69,3 +69,21 @@ func RemoveIDFromList(list []int64, id int64) ([]int64, bool) { } return list, false } + +// RemoveFromSlice removes all the target elements from the slice. +func RemoveFromSlice[T comparable](target T, slice []T) []T { + return RemoveFromSliceFunc(func(t T) bool { return t == target }, slice) +} + +// RemoveFromSliceFunc removes all elements which satisfy the targetFunc from the slice. +func RemoveFromSliceFunc[T comparable](targetFunc func(T) bool, slice []T) []T { + idx := 0 + for _, v := range slice { + if targetFunc(v) { + continue + } + slice[idx] = v + idx++ + } + return slice[:idx] +} From ffc758ff5842626f589fe8bcaa43dd2e32d1f5c7 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 17:34:31 +0800 Subject: [PATCH 09/21] chore: replace RemoveIDFromList --- models/org_team.go | 21 ++++++++++----------- models/user.go | 21 ++++++++++----------- modules/util/slice.go | 13 ------------- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/models/org_team.go b/models/org_team.go index b3ee842c1f297..b239286d9d9a9 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -398,20 +398,19 @@ func DeleteTeam(t *organization.Team) error { return fmt.Errorf("findProtectedBranches: %w", err) } for _, p := range protections { - var matched1, matched2, matched3 bool - if len(p.WhitelistTeamIDs) != 0 { - p.WhitelistTeamIDs, matched1 = util.RemoveIDFromList( - p.WhitelistTeamIDs, t.ID) + lenIDs, lenApprovalIDs, lenMergeIDs := len(p.WhitelistTeamIDs), len(p.ApprovalsWhitelistTeamIDs), len(p.MergeWhitelistTeamIDs) + if lenIDs != 0 { + p.WhitelistTeamIDs = util.RemoveFromSlice(t.ID, p.WhitelistTeamIDs) } - if len(p.ApprovalsWhitelistTeamIDs) != 0 { - p.ApprovalsWhitelistTeamIDs, matched2 = util.RemoveIDFromList( - p.ApprovalsWhitelistTeamIDs, t.ID) + if lenApprovalIDs != 0 { + p.ApprovalsWhitelistTeamIDs = util.RemoveFromSlice(t.ID, p.ApprovalsWhitelistTeamIDs) } - if len(p.MergeWhitelistTeamIDs) != 0 { - p.MergeWhitelistTeamIDs, matched3 = util.RemoveIDFromList( - p.MergeWhitelistTeamIDs, t.ID) + if lenMergeIDs != 0 { + p.MergeWhitelistTeamIDs = util.RemoveFromSlice(t.ID, p.MergeWhitelistTeamIDs) } - if matched1 || matched2 || matched3 { + if lenIDs != len(p.WhitelistTeamIDs) || + lenApprovalIDs != len(p.ApprovalsWhitelistTeamIDs) || + lenMergeIDs != len(p.MergeWhitelistTeamIDs) { if _, err = sess.ID(p.ID).Cols( "whitelist_team_i_ds", "merge_whitelist_team_i_ds", diff --git a/models/user.go b/models/user.go index 715d0e3866d5f..231c16ef54a2e 100644 --- a/models/user.go +++ b/models/user.go @@ -141,20 +141,19 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) (err error) break } for _, p := range protections { - var matched1, matched2, matched3 bool - if len(p.WhitelistUserIDs) != 0 { - p.WhitelistUserIDs, matched1 = util.RemoveIDFromList( - p.WhitelistUserIDs, u.ID) + lenIDs, lenApprovalIDs, lenMergeIDs := len(p.WhitelistUserIDs), len(p.ApprovalsWhitelistUserIDs), len(p.MergeWhitelistUserIDs) + if lenIDs != 0 { + p.WhitelistUserIDs = util.RemoveFromSlice(u.ID, p.WhitelistUserIDs) } - if len(p.ApprovalsWhitelistUserIDs) != 0 { - p.ApprovalsWhitelistUserIDs, matched2 = util.RemoveIDFromList( - p.ApprovalsWhitelistUserIDs, u.ID) + if lenApprovalIDs != 0 { + p.ApprovalsWhitelistUserIDs = util.RemoveFromSlice(u.ID, p.ApprovalsWhitelistUserIDs) } - if len(p.MergeWhitelistUserIDs) != 0 { - p.MergeWhitelistUserIDs, matched3 = util.RemoveIDFromList( - p.MergeWhitelistUserIDs, u.ID) + if lenMergeIDs != 0 { + p.MergeWhitelistUserIDs = util.RemoveFromSlice(u.ID, p.MergeWhitelistUserIDs) } - if matched1 || matched2 || matched3 { + if lenIDs != len(p.WhitelistUserIDs) || + lenApprovalIDs != len(p.ApprovalsWhitelistUserIDs) || + lenMergeIDs != len(p.MergeWhitelistUserIDs) { if _, err = e.ID(p.ID).Cols( "whitelist_user_i_ds", "merge_whitelist_user_i_ds", diff --git a/modules/util/slice.go b/modules/util/slice.go index 6a5008b2fe865..33225f47764ce 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -57,19 +57,6 @@ func IsEqualSlice[T comparable](target, source []T) bool { return true } -// RemoveIDFromList removes the given ID from the slice, if found. -// It does not preserve order, and assumes the ID is unique. -func RemoveIDFromList(list []int64, id int64) ([]int64, bool) { - n := len(list) - 1 - for i, item := range list { - if item == id { - list[i] = list[n] - return list[:n], true - } - } - return list, false -} - // RemoveFromSlice removes all the target elements from the slice. func RemoveFromSlice[T comparable](target T, slice []T) []T { return RemoveFromSliceFunc(func(t T) bool { return t == target }, slice) From 1bf153e1f6e31394df98a14d445f072a0a9bdbf8 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 18:16:35 +0800 Subject: [PATCH 10/21] test: add tests --- modules/util/slice_test.go | 66 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 modules/util/slice_test.go diff --git a/modules/util/slice_test.go b/modules/util/slice_test.go new file mode 100644 index 0000000000000..421980a2430e6 --- /dev/null +++ b/modules/util/slice_test.go @@ -0,0 +1,66 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package util + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestIsInSlice(t *testing.T) { + assert.True(t, IsInSlice(2, []int{2, 0, 2, 3})) + assert.True(t, IsInSlice(0, []int{2, 0, 2, 3})) + assert.True(t, IsInSlice(3, []int{2, 0, 2, 3})) + + assert.True(t, IsInSlice("0", []string{"2", "0", "2", "3"})) + assert.True(t, IsInSlice(0, []float64{2, 0, 2, 3})) + assert.True(t, IsInSlice(true, []bool{false, true, false})) + + assert.False(t, IsInSlice(4, []int{2, 0, 2, 3})) + assert.False(t, IsInSlice(4, []int{})) + assert.False(t, IsInSlice(4, nil)) +} + +func TestIsStringInSlice(t *testing.T) { + assert.True(t, IsStringInSlice("a", []string{"c", "b", "a", "b"})) + assert.True(t, IsStringInSlice("b", []string{"c", "b", "a", "b"})) + assert.True(t, IsStringInSlice("A", []string{"c", "b", "a", "b"}, true)) + assert.True(t, IsStringInSlice("a", []string{"C", "B", "A", "B"}, true)) + + assert.False(t, IsStringInSlice("z", []string{"c", "b", "a", "b"})) + assert.False(t, IsStringInSlice("A", []string{"c", "b", "a", "b"})) + assert.False(t, IsStringInSlice("a", []string{})) + assert.False(t, IsStringInSlice("a", nil)) +} + +func TestIsEqualSlice(t *testing.T) { + assert.True(t, IsEqualSlice([]int{2, 0, 2, 3}, []int{2, 0, 2, 3})) + assert.True(t, IsEqualSlice([]int{3, 0, 2, 2}, []int{3, 0, 2, 2})) + assert.True(t, IsEqualSlice([]int{}, []int{})) + assert.True(t, IsEqualSlice([]int(nil), nil)) + + assert.True(t, IsEqualSlice([]string{"2", "0", "2", "3"}, []string{"2", "0", "2", "3"})) + assert.True(t, IsEqualSlice([]float64{2, 0, 2, 3}, []float64{2, 0, 2, 3})) + assert.True(t, IsEqualSlice([]bool{false, true, false}, []bool{false, true, false})) + + assert.False(t, IsEqualSlice([]int{2, 0, 2}, []int{2, 0, 2, 3})) + assert.False(t, IsEqualSlice([]int{2, 0, 2, 4}, []int{2, 0, 2, 3})) + assert.False(t, IsEqualSlice([]int{2, 0, 0, 3}, []int{2, 0, 2, 3})) + assert.False(t, IsEqualSlice([]int(nil), []int{})) +} + +func TestRemoveFromSlice(t *testing.T) { + assert.Equal(t, RemoveFromSlice(0, []int{2, 0, 2, 3}), []int{2, 2, 3}) + assert.Equal(t, RemoveFromSlice(2, []int{2, 0, 2, 3}), []int{0, 3}) + assert.Equal(t, RemoveFromSlice(0, []int{0, 0, 0, 0}), []int{}) + assert.Equal(t, RemoveFromSlice(4, []int{2, 0, 2, 3}), []int{2, 0, 2, 3}) + assert.Equal(t, RemoveFromSlice(0, []int{}), []int{}) + assert.Equal(t, RemoveFromSlice(0, []int(nil)), []int(nil)) + assert.Equal(t, RemoveFromSlice(0, []int{}), []int{}) + + assert.Equal(t, RemoveFromSlice("0", []string{"2", "0", "2", "3"}), []string{"2", "2", "3"}) + assert.Equal(t, RemoveFromSlice(0, []float64{2, 0, 2, 3}), []float64{2, 2, 3}) + assert.Equal(t, RemoveFromSlice(true, []bool{false, true, false}), []bool{false, false}) +} From 7fdd87448ca5cbba642cf08f2a5f4c3c6ced2a05 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 18:23:03 +0800 Subject: [PATCH 11/21] chore: add comments --- modules/util/slice.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/util/slice.go b/modules/util/slice.go index 33225f47764ce..1fd7b836901a0 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -1,6 +1,10 @@ // Copyright 2022 The Gitea Authors. All rights reserved. // 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 import "strings" From 9d3c9bca6561760137f1c89d22774713173933f6 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 18:43:32 +0800 Subject: [PATCH 12/21] fix: typo --- modules/util/slice.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/util/slice.go b/modules/util/slice.go index 1fd7b836901a0..ab7bd0bce3f0a 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -35,7 +35,7 @@ func IsStringInSlice(target string, slice []string, insensitive ...bool) bool { } // IsEqualSlice returns true if slices are equal. -// Be careful, two slice has the same elements but different order are considered equal here. +// Be careful, two slice which have the same elements but different order are considered equal here. func IsEqualSlice[T comparable](target, source []T) bool { if len(target) != len(source) { return false From 7fc64c2e8f52959e04ec10b7fbf529c78f4fdbc2 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 20:39:21 +0800 Subject: [PATCH 13/21] fix: remove checking --- models/org_team.go | 12 +++--------- models/user.go | 12 +++--------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/models/org_team.go b/models/org_team.go index b239286d9d9a9..b815258b61a58 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -399,15 +399,9 @@ func DeleteTeam(t *organization.Team) error { } for _, p := range protections { lenIDs, lenApprovalIDs, lenMergeIDs := len(p.WhitelistTeamIDs), len(p.ApprovalsWhitelistTeamIDs), len(p.MergeWhitelistTeamIDs) - if lenIDs != 0 { - p.WhitelistTeamIDs = util.RemoveFromSlice(t.ID, p.WhitelistTeamIDs) - } - if lenApprovalIDs != 0 { - p.ApprovalsWhitelistTeamIDs = util.RemoveFromSlice(t.ID, p.ApprovalsWhitelistTeamIDs) - } - if lenMergeIDs != 0 { - p.MergeWhitelistTeamIDs = util.RemoveFromSlice(t.ID, p.MergeWhitelistTeamIDs) - } + p.WhitelistTeamIDs = util.RemoveFromSlice(t.ID, p.WhitelistTeamIDs) + p.ApprovalsWhitelistTeamIDs = util.RemoveFromSlice(t.ID, p.ApprovalsWhitelistTeamIDs) + p.MergeWhitelistTeamIDs = util.RemoveFromSlice(t.ID, p.MergeWhitelistTeamIDs) if lenIDs != len(p.WhitelistTeamIDs) || lenApprovalIDs != len(p.ApprovalsWhitelistTeamIDs) || lenMergeIDs != len(p.MergeWhitelistTeamIDs) { diff --git a/models/user.go b/models/user.go index 231c16ef54a2e..8a7a1d7e0283e 100644 --- a/models/user.go +++ b/models/user.go @@ -142,15 +142,9 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) (err error) } for _, p := range protections { lenIDs, lenApprovalIDs, lenMergeIDs := len(p.WhitelistUserIDs), len(p.ApprovalsWhitelistUserIDs), len(p.MergeWhitelistUserIDs) - if lenIDs != 0 { - p.WhitelistUserIDs = util.RemoveFromSlice(u.ID, p.WhitelistUserIDs) - } - if lenApprovalIDs != 0 { - p.ApprovalsWhitelistUserIDs = util.RemoveFromSlice(u.ID, p.ApprovalsWhitelistUserIDs) - } - if lenMergeIDs != 0 { - p.MergeWhitelistUserIDs = util.RemoveFromSlice(u.ID, p.MergeWhitelistUserIDs) - } + p.WhitelistUserIDs = util.RemoveFromSlice(u.ID, p.WhitelistUserIDs) + p.ApprovalsWhitelistUserIDs = util.RemoveFromSlice(u.ID, p.ApprovalsWhitelistUserIDs) + p.MergeWhitelistUserIDs = util.RemoveFromSlice(u.ID, p.MergeWhitelistUserIDs) if lenIDs != len(p.WhitelistUserIDs) || lenApprovalIDs != len(p.ApprovalsWhitelistUserIDs) || lenMergeIDs != len(p.MergeWhitelistUserIDs) { From b7b6ceea977813c1caf9f53b53ac5c7f6b6a0e5a Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 9 Jan 2023 20:47:43 +0800 Subject: [PATCH 14/21] fix: treat nil and [] as equal slices --- modules/util/slice.go | 4 ---- modules/util/slice_test.go | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/util/slice.go b/modules/util/slice.go index ab7bd0bce3f0a..1a5f7fd857c71 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -41,10 +41,6 @@ func IsEqualSlice[T comparable](target, source []T) bool { return false } - if (target == nil) != (source == nil) { - return false - } - counts := make(map[T]int, len(target)) for _, v := range target { counts[v]++ diff --git a/modules/util/slice_test.go b/modules/util/slice_test.go index 421980a2430e6..cceaca47da84e 100644 --- a/modules/util/slice_test.go +++ b/modules/util/slice_test.go @@ -40,6 +40,8 @@ func TestIsEqualSlice(t *testing.T) { assert.True(t, IsEqualSlice([]int{3, 0, 2, 2}, []int{3, 0, 2, 2})) assert.True(t, IsEqualSlice([]int{}, []int{})) assert.True(t, IsEqualSlice([]int(nil), nil)) + assert.True(t, IsEqualSlice([]int(nil), []int{})) + assert.True(t, IsEqualSlice([]int{}, []int{})) assert.True(t, IsEqualSlice([]string{"2", "0", "2", "3"}, []string{"2", "0", "2", "3"})) assert.True(t, IsEqualSlice([]float64{2, 0, 2, 3}, []float64{2, 0, 2, 3})) @@ -48,7 +50,6 @@ func TestIsEqualSlice(t *testing.T) { assert.False(t, IsEqualSlice([]int{2, 0, 2}, []int{2, 0, 2, 3})) assert.False(t, IsEqualSlice([]int{2, 0, 2, 4}, []int{2, 0, 2, 3})) assert.False(t, IsEqualSlice([]int{2, 0, 0, 3}, []int{2, 0, 2, 3})) - assert.False(t, IsEqualSlice([]int(nil), []int{})) } func TestRemoveFromSlice(t *testing.T) { From 08791627b61396d23ee95e1a0c71413b84e170fb Mon Sep 17 00:00:00 2001 From: Jason Song Date: Wed, 11 Jan 2023 10:29:40 +0800 Subject: [PATCH 15/21] chore: rename to SliceContains --- models/git/branches.go | 2 +- models/issues/issue.go | 4 ++-- modules/util/slice.go | 14 +++++++------- modules/util/slice_test.go | 18 +++++++++--------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/models/git/branches.go b/models/git/branches.go index a9215b0ed4ae0..e09cd4fcb83fa 100644 --- a/models/git/branches.go +++ b/models/git/branches.go @@ -404,7 +404,7 @@ func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, curre whitelist = make([]int64, 0, len(teams)) for i := range teams { - if util.IsInSlice(teams[i].ID, newWhitelist) { + if util.SliceContains(teams[i].ID, newWhitelist) { whitelist = append(whitelist, teams[i].ID) } } diff --git a/models/issues/issue.go b/models/issues/issue.go index fa2d85b8d337f..2273e99c4fdee 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -1529,7 +1529,7 @@ func IsUserParticipantsOfIssue(user *user_model.User, issue *Issue) bool { log.Error(err.Error()) return false } - return util.IsInSlice(user.ID, userIDs) + return util.SliceContains(user.ID, userIDs) } // UpdateIssueMentions updates issue-user relations for mentioned users. @@ -2023,7 +2023,7 @@ func (issue *Issue) GetParticipantIDsByIssue(ctx context.Context) ([]int64, erro Find(&userIDs); err != nil { return nil, fmt.Errorf("get poster IDs: %w", err) } - if !util.IsInSlice(issue.PosterID, userIDs) { + if !util.SliceContains(issue.PosterID, userIDs) { return append(userIDs, issue.PosterID), nil } return userIDs, nil diff --git a/modules/util/slice.go b/modules/util/slice.go index 1a5f7fd857c71..ae6f75d64b38d 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -9,13 +9,13 @@ package util import "strings" -// IsInSlice returns true if the target exists in the slice. -func IsInSlice[T comparable](target T, slice []T) bool { - return IsInSliceFunc(func(t T) bool { return t == target }, slice) +// SliceContains returns true if the target exists in the slice. +func SliceContains[T comparable](target T, slice []T) bool { + return SliceContainsFunc(func(t T) bool { return t == target }, slice) } -// IsInSliceFunc returns true if any element in the slice satisfies the targetFunc. -func IsInSliceFunc[T comparable](targetFunc func(T) bool, slice []T) bool { +// SliceContainsFunc returns true if any element in the slice satisfies the targetFunc. +func SliceContainsFunc[T comparable](targetFunc func(T) bool, slice []T) bool { for _, v := range slice { if targetFunc(v) { return true @@ -28,10 +28,10 @@ func IsInSliceFunc[T comparable](targetFunc func(T) bool, slice []T) bool { func IsStringInSlice(target string, slice []string, insensitive ...bool) bool { if len(insensitive) != 0 && insensitive[0] { target = strings.ToLower(target) - return IsInSliceFunc(func(t string) bool { return strings.ToLower(t) == target }, slice) + return SliceContainsFunc(func(t string) bool { return strings.ToLower(t) == target }, slice) } - return IsInSlice(target, slice) + return SliceContains(target, slice) } // IsEqualSlice returns true if slices are equal. diff --git a/modules/util/slice_test.go b/modules/util/slice_test.go index cceaca47da84e..fdb74754ccc7c 100644 --- a/modules/util/slice_test.go +++ b/modules/util/slice_test.go @@ -10,17 +10,17 @@ import ( ) func TestIsInSlice(t *testing.T) { - assert.True(t, IsInSlice(2, []int{2, 0, 2, 3})) - assert.True(t, IsInSlice(0, []int{2, 0, 2, 3})) - assert.True(t, IsInSlice(3, []int{2, 0, 2, 3})) + assert.True(t, SliceContains(2, []int{2, 0, 2, 3})) + assert.True(t, SliceContains(0, []int{2, 0, 2, 3})) + assert.True(t, SliceContains(3, []int{2, 0, 2, 3})) - assert.True(t, IsInSlice("0", []string{"2", "0", "2", "3"})) - assert.True(t, IsInSlice(0, []float64{2, 0, 2, 3})) - assert.True(t, IsInSlice(true, []bool{false, true, false})) + assert.True(t, SliceContains("0", []string{"2", "0", "2", "3"})) + assert.True(t, SliceContains(0, []float64{2, 0, 2, 3})) + assert.True(t, SliceContains(true, []bool{false, true, false})) - assert.False(t, IsInSlice(4, []int{2, 0, 2, 3})) - assert.False(t, IsInSlice(4, []int{})) - assert.False(t, IsInSlice(4, nil)) + assert.False(t, SliceContains(4, []int{2, 0, 2, 3})) + assert.False(t, SliceContains(4, []int{})) + assert.False(t, SliceContains(4, nil)) } func TestIsStringInSlice(t *testing.T) { From 7caaa153638fbbcfc2b3c148c6622c06dbf56cc8 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Wed, 11 Jan 2023 10:31:03 +0800 Subject: [PATCH 16/21] fix: SliceContainsFunc[T any] --- modules/util/slice.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/util/slice.go b/modules/util/slice.go index ae6f75d64b38d..9fa3830476c5a 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -15,7 +15,7 @@ func SliceContains[T comparable](target T, slice []T) bool { } // SliceContainsFunc returns true if any element in the slice satisfies the targetFunc. -func SliceContainsFunc[T comparable](targetFunc func(T) bool, slice []T) bool { +func SliceContainsFunc[T any](targetFunc func(T) bool, slice []T) bool { for _, v := range slice { if targetFunc(v) { return true From 62fc8adcc858ac0dd2829edf2222a3b96935c49f Mon Sep 17 00:00:00 2001 From: Jason Song Date: Wed, 11 Jan 2023 10:34:43 +0800 Subject: [PATCH 17/21] chore: rename to SliceContainsString --- cmd/admin.go | 2 +- cmd/dump.go | 2 +- models/asymkey/ssh_key.go | 6 ++-- models/auth/oauth2.go | 4 +-- models/issues/assignees.go | 2 +- modules/repository/init.go | 6 ++-- modules/util/slice.go | 4 +-- modules/util/slice_test.go | 20 +++++------ routers/api/v1/utils/hook.go | 34 +++++++++---------- routers/web/repo/issue.go | 4 +-- routers/web/repo/webhook.go | 2 +- routers/web/user/notification.go | 2 +- routers/web/user/setting/profile.go | 2 +- services/auth/source/ldap/source_search.go | 2 +- .../auth/source/smtp/source_authenticate.go | 2 +- services/wiki/wiki.go | 2 +- 16 files changed, 48 insertions(+), 48 deletions(-) diff --git a/cmd/admin.go b/cmd/admin.go index 1a4e09cf7c0b3..f5b06117e9821 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -950,7 +950,7 @@ func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error { if c.IsSet("auth-type") { conf.Auth = c.String("auth-type") validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"} - if !util.IsStringInSlice(strings.ToUpper(c.String("auth-type")), validAuthTypes) { + if !util.SliceContainsString(strings.ToUpper(c.String("auth-type")), validAuthTypes) { return errors.New("Auth must be one of PLAIN/LOGIN/CRAM-MD5") } conf.Auth = c.String("auth-type") diff --git a/cmd/dump.go b/cmd/dump.go index de5bf08808f07..963ec65d6b16b 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -429,7 +429,7 @@ func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeA currentAbsPath := path.Join(absPath, file.Name()) currentInsidePath := path.Join(insidePath, file.Name()) if file.IsDir() { - if !util.IsStringInSlice(currentAbsPath, excludeAbsPath) { + if !util.SliceContainsString(currentAbsPath, excludeAbsPath) { if err := addFile(w, currentInsidePath, currentAbsPath, false); err != nil { return err } diff --git a/models/asymkey/ssh_key.go b/models/asymkey/ssh_key.go index 87711100a0a08..9031f44245136 100644 --- a/models/asymkey/ssh_key.go +++ b/models/asymkey/ssh_key.go @@ -409,7 +409,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [ sshKeySplit := strings.Split(v, " ") if len(sshKeySplit) > 1 { key := strings.Join(sshKeySplit[:2], " ") - if !util.IsStringInSlice(key, providedKeys) { + if !util.SliceContainsString(key, providedKeys) { providedKeys = append(providedKeys, key) } } @@ -425,7 +425,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [ // Add new Public SSH Keys that doesn't already exist in DB var newKeys []string for _, key := range providedKeys { - if !util.IsStringInSlice(key, giteaKeys) { + if !util.SliceContainsString(key, giteaKeys) { newKeys = append(newKeys, key) } } @@ -436,7 +436,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [ // Mark keys from DB that no longer exist in the source for deletion var giteaKeysToDelete []string for _, giteaKey := range giteaKeys { - if !util.IsStringInSlice(giteaKey, providedKeys) { + if !util.SliceContainsString(giteaKey, providedKeys) { log.Trace("synchronizePublicKeys[%s]: Marking Public SSH Key for deletion for user %s: %v", s.Name, usr.Name, giteaKey) giteaKeysToDelete = append(giteaKeysToDelete, giteaKey) } diff --git a/models/auth/oauth2.go b/models/auth/oauth2.go index 8e5a003d194f5..86062de09634e 100644 --- a/models/auth/oauth2.go +++ b/models/auth/oauth2.go @@ -69,13 +69,13 @@ func (app *OAuth2Application) ContainsRedirectURI(redirectURI string) bool { if ip != nil && ip.IsLoopback() { // strip port uri.Host = uri.Hostname() - if util.IsStringInSlice(uri.String(), app.RedirectURIs, true) { + if util.SliceContainsString(uri.String(), app.RedirectURIs, true) { return true } } } } - return util.IsStringInSlice(redirectURI, app.RedirectURIs, true) + return util.SliceContainsString(redirectURI, app.RedirectURIs, true) } // Base32 characters, but lowercased. diff --git a/models/issues/assignees.go b/models/issues/assignees.go index 159086bd01052..8774fddfc055e 100644 --- a/models/issues/assignees.go +++ b/models/issues/assignees.go @@ -155,7 +155,7 @@ func MakeIDsFromAPIAssigneesToAdd(ctx context.Context, oneAssignee string, multi var requestAssignees []string // Keeping the old assigning method for compatibility reasons - if oneAssignee != "" && !util.IsStringInSlice(oneAssignee, multipleAssignees) { + if oneAssignee != "" && !util.SliceContainsString(oneAssignee, multipleAssignees) { requestAssignees = append(requestAssignees, oneAssignee) } diff --git a/modules/repository/init.go b/modules/repository/init.go index 59284a5bafc81..0568b4ec15409 100644 --- a/modules/repository/init.go +++ b/modules/repository/init.go @@ -170,7 +170,7 @@ func LoadRepoConfig() { } for _, f := range customFiles { - if !util.IsStringInSlice(f, files, true) { + if !util.SliceContainsString(f, files, true) { files = append(files, f) } } @@ -200,12 +200,12 @@ func LoadRepoConfig() { // Filter out invalid names and promote preferred licenses. sortedLicenses := make([]string, 0, len(Licenses)) for _, name := range setting.Repository.PreferredLicenses { - if util.IsStringInSlice(name, Licenses, true) { + if util.SliceContainsString(name, Licenses, true) { sortedLicenses = append(sortedLicenses, name) } } for _, name := range Licenses { - if !util.IsStringInSlice(name, setting.Repository.PreferredLicenses, true) { + if !util.SliceContainsString(name, setting.Repository.PreferredLicenses, true) { sortedLicenses = append(sortedLicenses, name) } } diff --git a/modules/util/slice.go b/modules/util/slice.go index 9fa3830476c5a..9a7379c585179 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -24,8 +24,8 @@ func SliceContainsFunc[T any](targetFunc func(T) bool, slice []T) bool { return false } -// IsStringInSlice sequential searches if string exists in slice. -func IsStringInSlice(target string, slice []string, insensitive ...bool) bool { +// SliceContainsString sequential searches if string exists in slice. +func SliceContainsString(target string, slice []string, insensitive ...bool) bool { if len(insensitive) != 0 && insensitive[0] { target = strings.ToLower(target) return SliceContainsFunc(func(t string) bool { return strings.ToLower(t) == target }, slice) diff --git a/modules/util/slice_test.go b/modules/util/slice_test.go index fdb74754ccc7c..6f7382b177917 100644 --- a/modules/util/slice_test.go +++ b/modules/util/slice_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestIsInSlice(t *testing.T) { +func TestSliceContains(t *testing.T) { assert.True(t, SliceContains(2, []int{2, 0, 2, 3})) assert.True(t, SliceContains(0, []int{2, 0, 2, 3})) assert.True(t, SliceContains(3, []int{2, 0, 2, 3})) @@ -23,16 +23,16 @@ func TestIsInSlice(t *testing.T) { assert.False(t, SliceContains(4, nil)) } -func TestIsStringInSlice(t *testing.T) { - assert.True(t, IsStringInSlice("a", []string{"c", "b", "a", "b"})) - assert.True(t, IsStringInSlice("b", []string{"c", "b", "a", "b"})) - assert.True(t, IsStringInSlice("A", []string{"c", "b", "a", "b"}, true)) - assert.True(t, IsStringInSlice("a", []string{"C", "B", "A", "B"}, true)) +func TestSliceContainsString(t *testing.T) { + assert.True(t, SliceContainsString("a", []string{"c", "b", "a", "b"})) + assert.True(t, SliceContainsString("b", []string{"c", "b", "a", "b"})) + assert.True(t, SliceContainsString("A", []string{"c", "b", "a", "b"}, true)) + assert.True(t, SliceContainsString("a", []string{"C", "B", "A", "B"}, true)) - assert.False(t, IsStringInSlice("z", []string{"c", "b", "a", "b"})) - assert.False(t, IsStringInSlice("A", []string{"c", "b", "a", "b"})) - assert.False(t, IsStringInSlice("a", []string{})) - assert.False(t, IsStringInSlice("a", nil)) + assert.False(t, SliceContainsString("z", []string{"c", "b", "a", "b"})) + assert.False(t, SliceContainsString("A", []string{"c", "b", "a", "b"})) + assert.False(t, SliceContainsString("a", []string{})) + assert.False(t, SliceContainsString("a", nil)) } func TestIsEqualSlice(t *testing.T) { diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go index 065b761adb35b..b74a14a9d8c43 100644 --- a/routers/api/v1/utils/hook.go +++ b/routers/api/v1/utils/hook.go @@ -107,11 +107,11 @@ func toAPIHook(ctx *context.APIContext, repoLink string, hook *webhook.Webhook) } func issuesHook(events []string, event string) bool { - return util.IsStringInSlice(event, events, true) || util.IsStringInSlice(string(webhook_module.HookEventIssues), events, true) + return util.SliceContainsString(event, events, true) || util.SliceContainsString(string(webhook_module.HookEventIssues), events, true) } func pullHook(events []string, event string) bool { - return util.IsStringInSlice(event, events, true) || util.IsStringInSlice(string(webhook_module.HookEventPullRequest), events, true) + return util.SliceContainsString(event, events, true) || util.SliceContainsString(string(webhook_module.HookEventPullRequest), events, true) } // addHook add the hook specified by `form`, `orgID` and `repoID`. If there is @@ -130,15 +130,15 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID HookEvent: &webhook_module.HookEvent{ ChooseEvents: true, HookEvents: webhook_module.HookEvents{ - Create: util.IsStringInSlice(string(webhook_module.HookEventCreate), form.Events, true), - Delete: util.IsStringInSlice(string(webhook_module.HookEventDelete), form.Events, true), - Fork: util.IsStringInSlice(string(webhook_module.HookEventFork), form.Events, true), + Create: util.SliceContainsString(string(webhook_module.HookEventCreate), form.Events, true), + Delete: util.SliceContainsString(string(webhook_module.HookEventDelete), form.Events, true), + Fork: util.SliceContainsString(string(webhook_module.HookEventFork), form.Events, true), Issues: issuesHook(form.Events, "issues_only"), IssueAssign: issuesHook(form.Events, string(webhook_module.HookEventIssueAssign)), IssueLabel: issuesHook(form.Events, string(webhook_module.HookEventIssueLabel)), IssueMilestone: issuesHook(form.Events, string(webhook_module.HookEventIssueMilestone)), IssueComment: issuesHook(form.Events, string(webhook_module.HookEventIssueComment)), - Push: util.IsStringInSlice(string(webhook_module.HookEventPush), form.Events, true), + Push: util.SliceContainsString(string(webhook_module.HookEventPush), form.Events, true), PullRequest: pullHook(form.Events, "pull_request_only"), PullRequestAssign: pullHook(form.Events, string(webhook_module.HookEventPullRequestAssign)), PullRequestLabel: pullHook(form.Events, string(webhook_module.HookEventPullRequestLabel)), @@ -146,9 +146,9 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID PullRequestComment: pullHook(form.Events, string(webhook_module.HookEventPullRequestComment)), PullRequestReview: pullHook(form.Events, "pull_request_review"), PullRequestSync: pullHook(form.Events, string(webhook_module.HookEventPullRequestSync)), - Wiki: util.IsStringInSlice(string(webhook_module.HookEventWiki), form.Events, true), - Repository: util.IsStringInSlice(string(webhook_module.HookEventRepository), form.Events, true), - Release: util.IsStringInSlice(string(webhook_module.HookEventRelease), form.Events, true), + Wiki: util.SliceContainsString(string(webhook_module.HookEventWiki), form.Events, true), + Repository: util.SliceContainsString(string(webhook_module.HookEventRepository), form.Events, true), + Release: util.SliceContainsString(string(webhook_module.HookEventRelease), form.Events, true), }, BranchFilter: form.BranchFilter, }, @@ -277,14 +277,14 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webh w.PushOnly = false w.SendEverything = false w.ChooseEvents = true - w.Create = util.IsStringInSlice(string(webhook_module.HookEventCreate), form.Events, true) - w.Push = util.IsStringInSlice(string(webhook_module.HookEventPush), form.Events, true) - w.Create = util.IsStringInSlice(string(webhook_module.HookEventCreate), form.Events, true) - w.Delete = util.IsStringInSlice(string(webhook_module.HookEventDelete), form.Events, true) - w.Fork = util.IsStringInSlice(string(webhook_module.HookEventFork), form.Events, true) - w.Repository = util.IsStringInSlice(string(webhook_module.HookEventRepository), form.Events, true) - w.Wiki = util.IsStringInSlice(string(webhook_module.HookEventWiki), form.Events, true) - w.Release = util.IsStringInSlice(string(webhook_module.HookEventRelease), form.Events, true) + w.Create = util.SliceContainsString(string(webhook_module.HookEventCreate), form.Events, true) + w.Push = util.SliceContainsString(string(webhook_module.HookEventPush), form.Events, true) + w.Create = util.SliceContainsString(string(webhook_module.HookEventCreate), form.Events, true) + w.Delete = util.SliceContainsString(string(webhook_module.HookEventDelete), form.Events, true) + w.Fork = util.SliceContainsString(string(webhook_module.HookEventFork), form.Events, true) + w.Repository = util.SliceContainsString(string(webhook_module.HookEventRepository), form.Events, true) + w.Wiki = util.SliceContainsString(string(webhook_module.HookEventWiki), form.Events, true) + w.Release = util.SliceContainsString(string(webhook_module.HookEventRelease), form.Events, true) w.BranchFilter = form.BranchFilter err := w.SetHeaderAuthorization(form.AuthorizationHeader) diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 07dd98f1a512a..df3365a50ac26 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -139,7 +139,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti viewType := ctx.FormString("type") sortType := ctx.FormString("sort") types := []string{"all", "your_repositories", "assigned", "created_by", "mentioned", "review_requested"} - if !util.IsStringInSlice(viewType, types, true) { + if !util.SliceContainsString(viewType, types, true) { viewType = "all" } @@ -3087,7 +3087,7 @@ func updateAttachments(ctx *context.Context, item interface{}, files []string) e return fmt.Errorf("unknown Type: %T", content) } for i := 0; i < len(attachments); i++ { - if util.IsStringInSlice(attachments[i].UUID, files) { + if util.SliceContainsString(attachments[i].UUID, files) { continue } if err := repo_model.DeleteAttachment(attachments[i], true); err != nil { diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go index bf56e3d0bdc83..6fe9e5cd752ae 100644 --- a/routers/web/repo/webhook.go +++ b/routers/web/repo/webhook.go @@ -110,7 +110,7 @@ func getOrgRepoCtx(ctx *context.Context) (*orgRepoCtx, error) { func checkHookType(ctx *context.Context) string { hookType := strings.ToLower(ctx.Params(":type")) - if !util.IsStringInSlice(hookType, setting.Webhook.Types, true) { + if !util.SliceContainsString(hookType, setting.Webhook.Types, true) { ctx.NotFound("checkHookType", nil) return "" } diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go index b21d52bbfdea0..1e758d528e0ae 100644 --- a/routers/web/user/notification.go +++ b/routers/web/user/notification.go @@ -214,7 +214,7 @@ func NotificationSubscriptions(ctx *context.Context) { ctx.Data["SortType"] = sortType state := ctx.FormString("state") - if !util.IsStringInSlice(state, []string{"all", "open", "closed"}, true) { + if !util.SliceContainsString(state, []string{"all", "open", "closed"}, true) { state = "all" } ctx.Data["State"] = state diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index ef45ad8a862d1..c4dd693f2e49e 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -413,7 +413,7 @@ func UpdateUserLang(ctx *context.Context) { ctx.Data["PageIsSettingsAppearance"] = true if len(form.Language) != 0 { - if !util.IsStringInSlice(form.Language, setting.Langs) { + if !util.SliceContainsString(form.Language, setting.Langs) { ctx.Flash.Error(ctx.Tr("settings.update_language_not_found", form.Language)) ctx.Redirect(setting.AppSubURL + "/user/settings/appearance") return diff --git a/services/auth/source/ldap/source_search.go b/services/auth/source/ldap/source_search.go index 6b6b56db2f06f..735e8161f36c9 100644 --- a/services/auth/source/ldap/source_search.go +++ b/services/auth/source/ldap/source_search.go @@ -246,7 +246,7 @@ func (source *Source) getMappedMemberships(l *ldap.Conn, uid string) (map[string membershipsToAdd := map[string][]string{} membershipsToRemove := map[string][]string{} for group, memberships := range ldapGroupsToTeams { - isUserInGroup := util.IsStringInSlice(group, usersLdapGroups) + isUserInGroup := util.SliceContainsString(group, usersLdapGroups) if isUserInGroup { for org, teams := range memberships { membershipsToAdd[org] = teams diff --git a/services/auth/source/smtp/source_authenticate.go b/services/auth/source/smtp/source_authenticate.go index 00aaa8e084fb9..17aad4c533cdb 100644 --- a/services/auth/source/smtp/source_authenticate.go +++ b/services/auth/source/smtp/source_authenticate.go @@ -23,7 +23,7 @@ func (source *Source) Authenticate(user *user_model.User, userName, password str idx := strings.Index(userName, "@") if idx == -1 { return nil, user_model.ErrUserNotExist{Name: userName} - } else if !util.IsStringInSlice(userName[idx+1:], strings.Split(source.AllowedDomains, ","), true) { + } else if !util.SliceContainsString(userName[idx+1:], strings.Split(source.AllowedDomains, ","), true) { return nil, user_model.ErrUserNotExist{Name: userName} } } diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index e483416fda76f..be303d1f2c7bc 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -35,7 +35,7 @@ const ( ) func nameAllowed(name string) error { - if util.IsStringInSlice(name, reservedWikiNames) { + if util.SliceContainsString(name, reservedWikiNames) { return repo_model.ErrWikiReservedName{ Title: name, } From 3a16168404be30c696c426be6435375e22b167fb Mon Sep 17 00:00:00 2001 From: Jason Song Date: Wed, 11 Jan 2023 10:47:40 +0800 Subject: [PATCH 18/21] chore: update func signatures --- cmd/admin.go | 2 +- cmd/dump.go | 2 +- models/asymkey/ssh_key.go | 6 ++-- models/auth/oauth2.go | 4 +-- models/git/branches.go | 2 +- models/issues/assignees.go | 2 +- models/issues/issue.go | 4 +-- modules/repository/init.go | 6 ++-- modules/util/slice.go | 12 +++---- modules/util/slice_test.go | 34 +++++++++---------- routers/api/v1/utils/hook.go | 34 +++++++++---------- routers/web/repo/issue.go | 4 +-- routers/web/repo/webhook.go | 2 +- routers/web/user/notification.go | 2 +- routers/web/user/setting/profile.go | 2 +- services/auth/source/ldap/source_search.go | 2 +- .../auth/source/smtp/source_authenticate.go | 2 +- services/wiki/wiki.go | 2 +- 18 files changed, 62 insertions(+), 62 deletions(-) diff --git a/cmd/admin.go b/cmd/admin.go index f5b06117e9821..a662011f9c079 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -950,7 +950,7 @@ func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error { if c.IsSet("auth-type") { conf.Auth = c.String("auth-type") validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"} - if !util.SliceContainsString(strings.ToUpper(c.String("auth-type")), validAuthTypes) { + if !util.SliceContainsString(validAuthTypes, strings.ToUpper(c.String("auth-type"))) { return errors.New("Auth must be one of PLAIN/LOGIN/CRAM-MD5") } conf.Auth = c.String("auth-type") diff --git a/cmd/dump.go b/cmd/dump.go index 963ec65d6b16b..f40ddbac23e83 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -429,7 +429,7 @@ func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeA currentAbsPath := path.Join(absPath, file.Name()) currentInsidePath := path.Join(insidePath, file.Name()) if file.IsDir() { - if !util.SliceContainsString(currentAbsPath, excludeAbsPath) { + if !util.SliceContainsString(excludeAbsPath, currentAbsPath) { if err := addFile(w, currentInsidePath, currentAbsPath, false); err != nil { return err } diff --git a/models/asymkey/ssh_key.go b/models/asymkey/ssh_key.go index 9031f44245136..ed1e60e9be9aa 100644 --- a/models/asymkey/ssh_key.go +++ b/models/asymkey/ssh_key.go @@ -409,7 +409,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [ sshKeySplit := strings.Split(v, " ") if len(sshKeySplit) > 1 { key := strings.Join(sshKeySplit[:2], " ") - if !util.SliceContainsString(key, providedKeys) { + if !util.SliceContainsString(providedKeys, key) { providedKeys = append(providedKeys, key) } } @@ -425,7 +425,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [ // Add new Public SSH Keys that doesn't already exist in DB var newKeys []string for _, key := range providedKeys { - if !util.SliceContainsString(key, giteaKeys) { + if !util.SliceContainsString(giteaKeys, key) { newKeys = append(newKeys, key) } } @@ -436,7 +436,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [ // Mark keys from DB that no longer exist in the source for deletion var giteaKeysToDelete []string for _, giteaKey := range giteaKeys { - if !util.SliceContainsString(giteaKey, providedKeys) { + if !util.SliceContainsString(providedKeys, giteaKey) { log.Trace("synchronizePublicKeys[%s]: Marking Public SSH Key for deletion for user %s: %v", s.Name, usr.Name, giteaKey) giteaKeysToDelete = append(giteaKeysToDelete, giteaKey) } diff --git a/models/auth/oauth2.go b/models/auth/oauth2.go index 86062de09634e..09d4bfc4ea35e 100644 --- a/models/auth/oauth2.go +++ b/models/auth/oauth2.go @@ -69,13 +69,13 @@ func (app *OAuth2Application) ContainsRedirectURI(redirectURI string) bool { if ip != nil && ip.IsLoopback() { // strip port uri.Host = uri.Hostname() - if util.SliceContainsString(uri.String(), app.RedirectURIs, true) { + if util.SliceContainsString(app.RedirectURIs, uri.String(), true) { return true } } } } - return util.SliceContainsString(redirectURI, app.RedirectURIs, true) + return util.SliceContainsString(app.RedirectURIs, redirectURI, true) } // Base32 characters, but lowercased. diff --git a/models/git/branches.go b/models/git/branches.go index e09cd4fcb83fa..e3d53450842e6 100644 --- a/models/git/branches.go +++ b/models/git/branches.go @@ -404,7 +404,7 @@ func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, curre whitelist = make([]int64, 0, len(teams)) for i := range teams { - if util.SliceContains(teams[i].ID, newWhitelist) { + if util.SliceContains(newWhitelist, teams[i].ID) { whitelist = append(whitelist, teams[i].ID) } } diff --git a/models/issues/assignees.go b/models/issues/assignees.go index 8774fddfc055e..16f675a83f875 100644 --- a/models/issues/assignees.go +++ b/models/issues/assignees.go @@ -155,7 +155,7 @@ func MakeIDsFromAPIAssigneesToAdd(ctx context.Context, oneAssignee string, multi var requestAssignees []string // Keeping the old assigning method for compatibility reasons - if oneAssignee != "" && !util.SliceContainsString(oneAssignee, multipleAssignees) { + if oneAssignee != "" && !util.SliceContainsString(multipleAssignees, oneAssignee) { requestAssignees = append(requestAssignees, oneAssignee) } diff --git a/models/issues/issue.go b/models/issues/issue.go index 2273e99c4fdee..4a8ab06824aaa 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -1529,7 +1529,7 @@ func IsUserParticipantsOfIssue(user *user_model.User, issue *Issue) bool { log.Error(err.Error()) return false } - return util.SliceContains(user.ID, userIDs) + return util.SliceContains(userIDs, user.ID) } // UpdateIssueMentions updates issue-user relations for mentioned users. @@ -2023,7 +2023,7 @@ func (issue *Issue) GetParticipantIDsByIssue(ctx context.Context) ([]int64, erro Find(&userIDs); err != nil { return nil, fmt.Errorf("get poster IDs: %w", err) } - if !util.SliceContains(issue.PosterID, userIDs) { + if !util.SliceContains(userIDs, issue.PosterID) { return append(userIDs, issue.PosterID), nil } return userIDs, nil diff --git a/modules/repository/init.go b/modules/repository/init.go index 0568b4ec15409..2b0d0be7bc99c 100644 --- a/modules/repository/init.go +++ b/modules/repository/init.go @@ -170,7 +170,7 @@ func LoadRepoConfig() { } for _, f := range customFiles { - if !util.SliceContainsString(f, files, true) { + if !util.SliceContainsString(files, f, true) { files = append(files, f) } } @@ -200,12 +200,12 @@ func LoadRepoConfig() { // Filter out invalid names and promote preferred licenses. sortedLicenses := make([]string, 0, len(Licenses)) for _, name := range setting.Repository.PreferredLicenses { - if util.SliceContainsString(name, Licenses, true) { + if util.SliceContainsString(Licenses, name, true) { sortedLicenses = append(sortedLicenses, name) } } for _, name := range Licenses { - if !util.SliceContainsString(name, setting.Repository.PreferredLicenses, true) { + if !util.SliceContainsString(setting.Repository.PreferredLicenses, name, true) { sortedLicenses = append(sortedLicenses, name) } } diff --git a/modules/util/slice.go b/modules/util/slice.go index 9a7379c585179..9d5297bf7ed7f 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -10,12 +10,12 @@ package util import "strings" // SliceContains returns true if the target exists in the slice. -func SliceContains[T comparable](target T, slice []T) bool { - return SliceContainsFunc(func(t T) bool { return t == target }, slice) +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](targetFunc func(T) bool, slice []T) bool { +func SliceContainsFunc[T any](slice []T, targetFunc func(T) bool) bool { for _, v := range slice { if targetFunc(v) { return true @@ -25,13 +25,13 @@ func SliceContainsFunc[T any](targetFunc func(T) bool, slice []T) bool { } // SliceContainsString sequential searches if string exists in slice. -func SliceContainsString(target string, slice []string, insensitive ...bool) bool { +func SliceContainsString(slice []string, target string, insensitive ...bool) bool { if len(insensitive) != 0 && insensitive[0] { target = strings.ToLower(target) - return SliceContainsFunc(func(t string) bool { return strings.ToLower(t) == target }, slice) + return SliceContainsFunc(slice, func(t string) bool { return strings.ToLower(t) == target }) } - return SliceContains(target, slice) + return SliceContains(slice, target) } // IsEqualSlice returns true if slices are equal. diff --git a/modules/util/slice_test.go b/modules/util/slice_test.go index 6f7382b177917..d54de6059cb4c 100644 --- a/modules/util/slice_test.go +++ b/modules/util/slice_test.go @@ -10,29 +10,29 @@ import ( ) func TestSliceContains(t *testing.T) { - assert.True(t, SliceContains(2, []int{2, 0, 2, 3})) - assert.True(t, SliceContains(0, []int{2, 0, 2, 3})) - assert.True(t, SliceContains(3, []int{2, 0, 2, 3})) + 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("0", []string{"2", "0", "2", "3"})) - assert.True(t, SliceContains(0, []float64{2, 0, 2, 3})) - assert.True(t, SliceContains(true, []bool{false, true, false})) + 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(4, []int{2, 0, 2, 3})) - assert.False(t, SliceContains(4, []int{})) - assert.False(t, SliceContains(4, nil)) + 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) { - assert.True(t, SliceContainsString("a", []string{"c", "b", "a", "b"})) - assert.True(t, SliceContainsString("b", []string{"c", "b", "a", "b"})) - assert.True(t, SliceContainsString("A", []string{"c", "b", "a", "b"}, true)) - assert.True(t, SliceContainsString("a", []string{"C", "B", "A", "B"}, true)) + 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"}, "A", true)) + assert.True(t, SliceContainsString([]string{"C", "B", "A", "B"}, "a", true)) - assert.False(t, SliceContainsString("z", []string{"c", "b", "a", "b"})) - assert.False(t, SliceContainsString("A", []string{"c", "b", "a", "b"})) - assert.False(t, SliceContainsString("a", []string{})) - assert.False(t, SliceContainsString("a", nil)) + assert.False(t, SliceContainsString([]string{"c", "b", "a", "b"}, "z")) + assert.False(t, SliceContainsString([]string{"c", "b", "a", "b"}, "A")) + assert.False(t, SliceContainsString([]string{}, "a")) + assert.False(t, SliceContainsString(nil, "a")) } func TestIsEqualSlice(t *testing.T) { diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go index b74a14a9d8c43..44fba22b5afed 100644 --- a/routers/api/v1/utils/hook.go +++ b/routers/api/v1/utils/hook.go @@ -107,11 +107,11 @@ func toAPIHook(ctx *context.APIContext, repoLink string, hook *webhook.Webhook) } func issuesHook(events []string, event string) bool { - return util.SliceContainsString(event, events, true) || util.SliceContainsString(string(webhook_module.HookEventIssues), events, true) + return util.SliceContainsString(events, event, true) || util.SliceContainsString(events, string(webhook_module.HookEventIssues), true) } func pullHook(events []string, event string) bool { - return util.SliceContainsString(event, events, true) || util.SliceContainsString(string(webhook_module.HookEventPullRequest), events, true) + return util.SliceContainsString(events, event, true) || util.SliceContainsString(events, string(webhook_module.HookEventPullRequest), true) } // addHook add the hook specified by `form`, `orgID` and `repoID`. If there is @@ -130,15 +130,15 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID HookEvent: &webhook_module.HookEvent{ ChooseEvents: true, HookEvents: webhook_module.HookEvents{ - Create: util.SliceContainsString(string(webhook_module.HookEventCreate), form.Events, true), - Delete: util.SliceContainsString(string(webhook_module.HookEventDelete), form.Events, true), - Fork: util.SliceContainsString(string(webhook_module.HookEventFork), form.Events, true), + Create: util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true), + Delete: util.SliceContainsString(form.Events, string(webhook_module.HookEventDelete), true), + Fork: util.SliceContainsString(form.Events, string(webhook_module.HookEventFork), true), Issues: issuesHook(form.Events, "issues_only"), IssueAssign: issuesHook(form.Events, string(webhook_module.HookEventIssueAssign)), IssueLabel: issuesHook(form.Events, string(webhook_module.HookEventIssueLabel)), IssueMilestone: issuesHook(form.Events, string(webhook_module.HookEventIssueMilestone)), IssueComment: issuesHook(form.Events, string(webhook_module.HookEventIssueComment)), - Push: util.SliceContainsString(string(webhook_module.HookEventPush), form.Events, true), + Push: util.SliceContainsString(form.Events, string(webhook_module.HookEventPush), true), PullRequest: pullHook(form.Events, "pull_request_only"), PullRequestAssign: pullHook(form.Events, string(webhook_module.HookEventPullRequestAssign)), PullRequestLabel: pullHook(form.Events, string(webhook_module.HookEventPullRequestLabel)), @@ -146,9 +146,9 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID PullRequestComment: pullHook(form.Events, string(webhook_module.HookEventPullRequestComment)), PullRequestReview: pullHook(form.Events, "pull_request_review"), PullRequestSync: pullHook(form.Events, string(webhook_module.HookEventPullRequestSync)), - Wiki: util.SliceContainsString(string(webhook_module.HookEventWiki), form.Events, true), - Repository: util.SliceContainsString(string(webhook_module.HookEventRepository), form.Events, true), - Release: util.SliceContainsString(string(webhook_module.HookEventRelease), form.Events, true), + Wiki: util.SliceContainsString(form.Events, string(webhook_module.HookEventWiki), true), + Repository: util.SliceContainsString(form.Events, string(webhook_module.HookEventRepository), true), + Release: util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true), }, BranchFilter: form.BranchFilter, }, @@ -277,14 +277,14 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webh w.PushOnly = false w.SendEverything = false w.ChooseEvents = true - w.Create = util.SliceContainsString(string(webhook_module.HookEventCreate), form.Events, true) - w.Push = util.SliceContainsString(string(webhook_module.HookEventPush), form.Events, true) - w.Create = util.SliceContainsString(string(webhook_module.HookEventCreate), form.Events, true) - w.Delete = util.SliceContainsString(string(webhook_module.HookEventDelete), form.Events, true) - w.Fork = util.SliceContainsString(string(webhook_module.HookEventFork), form.Events, true) - w.Repository = util.SliceContainsString(string(webhook_module.HookEventRepository), form.Events, true) - w.Wiki = util.SliceContainsString(string(webhook_module.HookEventWiki), form.Events, true) - w.Release = util.SliceContainsString(string(webhook_module.HookEventRelease), form.Events, true) + w.Create = util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true) + w.Push = util.SliceContainsString(form.Events, string(webhook_module.HookEventPush), true) + w.Create = util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true) + w.Delete = util.SliceContainsString(form.Events, string(webhook_module.HookEventDelete), true) + w.Fork = util.SliceContainsString(form.Events, string(webhook_module.HookEventFork), true) + w.Repository = util.SliceContainsString(form.Events, string(webhook_module.HookEventRepository), true) + w.Wiki = util.SliceContainsString(form.Events, string(webhook_module.HookEventWiki), true) + w.Release = util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true) w.BranchFilter = form.BranchFilter err := w.SetHeaderAuthorization(form.AuthorizationHeader) diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index df3365a50ac26..f037c771d475b 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -139,7 +139,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti viewType := ctx.FormString("type") sortType := ctx.FormString("sort") types := []string{"all", "your_repositories", "assigned", "created_by", "mentioned", "review_requested"} - if !util.SliceContainsString(viewType, types, true) { + if !util.SliceContainsString(types, viewType, true) { viewType = "all" } @@ -3087,7 +3087,7 @@ func updateAttachments(ctx *context.Context, item interface{}, files []string) e return fmt.Errorf("unknown Type: %T", content) } for i := 0; i < len(attachments); i++ { - if util.SliceContainsString(attachments[i].UUID, files) { + if util.SliceContainsString(files, attachments[i].UUID) { continue } if err := repo_model.DeleteAttachment(attachments[i], true); err != nil { diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go index 6fe9e5cd752ae..96261af674461 100644 --- a/routers/web/repo/webhook.go +++ b/routers/web/repo/webhook.go @@ -110,7 +110,7 @@ func getOrgRepoCtx(ctx *context.Context) (*orgRepoCtx, error) { func checkHookType(ctx *context.Context) string { hookType := strings.ToLower(ctx.Params(":type")) - if !util.SliceContainsString(hookType, setting.Webhook.Types, true) { + if !util.SliceContainsString(setting.Webhook.Types, hookType, true) { ctx.NotFound("checkHookType", nil) return "" } diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go index 1e758d528e0ae..e96b3dd27a95e 100644 --- a/routers/web/user/notification.go +++ b/routers/web/user/notification.go @@ -214,7 +214,7 @@ func NotificationSubscriptions(ctx *context.Context) { ctx.Data["SortType"] = sortType state := ctx.FormString("state") - if !util.SliceContainsString(state, []string{"all", "open", "closed"}, true) { + if !util.SliceContainsString([]string{"all", "open", "closed"}, state, true) { state = "all" } ctx.Data["State"] = state diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index c4dd693f2e49e..dac00850b1c24 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -413,7 +413,7 @@ func UpdateUserLang(ctx *context.Context) { ctx.Data["PageIsSettingsAppearance"] = true if len(form.Language) != 0 { - if !util.SliceContainsString(form.Language, setting.Langs) { + if !util.SliceContainsString(setting.Langs, form.Language) { ctx.Flash.Error(ctx.Tr("settings.update_language_not_found", form.Language)) ctx.Redirect(setting.AppSubURL + "/user/settings/appearance") return diff --git a/services/auth/source/ldap/source_search.go b/services/auth/source/ldap/source_search.go index 735e8161f36c9..68ebba391769d 100644 --- a/services/auth/source/ldap/source_search.go +++ b/services/auth/source/ldap/source_search.go @@ -246,7 +246,7 @@ func (source *Source) getMappedMemberships(l *ldap.Conn, uid string) (map[string membershipsToAdd := map[string][]string{} membershipsToRemove := map[string][]string{} for group, memberships := range ldapGroupsToTeams { - isUserInGroup := util.SliceContainsString(group, usersLdapGroups) + isUserInGroup := util.SliceContainsString(usersLdapGroups, group) if isUserInGroup { for org, teams := range memberships { membershipsToAdd[org] = teams diff --git a/services/auth/source/smtp/source_authenticate.go b/services/auth/source/smtp/source_authenticate.go index 17aad4c533cdb..36b351198acba 100644 --- a/services/auth/source/smtp/source_authenticate.go +++ b/services/auth/source/smtp/source_authenticate.go @@ -23,7 +23,7 @@ func (source *Source) Authenticate(user *user_model.User, userName, password str idx := strings.Index(userName, "@") if idx == -1 { return nil, user_model.ErrUserNotExist{Name: userName} - } else if !util.SliceContainsString(userName[idx+1:], strings.Split(source.AllowedDomains, ","), true) { + } else if !util.SliceContainsString(strings.Split(source.AllowedDomains, ","), userName[idx+1:], true) { return nil, user_model.ErrUserNotExist{Name: userName} } } diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index be303d1f2c7bc..e5cb2db02bdeb 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -35,7 +35,7 @@ const ( ) func nameAllowed(name string) error { - if util.SliceContainsString(name, reservedWikiNames) { + if util.SliceContainsString(reservedWikiNames, name) { return repo_model.ErrWikiReservedName{ Title: name, } From a65b857b432757b35990976431d9f60a000e45c6 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Wed, 11 Jan 2023 11:35:48 +0800 Subject: [PATCH 19/21] chore: SliceSortedEqual --- models/asymkey/ssh_key.go | 2 +- models/git/branches.go | 6 ++--- modules/util/slice.go | 28 ++++++++++++++++++------ modules/util/slice_test.go | 26 +++++++++++----------- tests/integration/api_repo_teams_test.go | 2 +- 5 files changed, 39 insertions(+), 25 deletions(-) diff --git a/models/asymkey/ssh_key.go b/models/asymkey/ssh_key.go index ed1e60e9be9aa..8d84c2f7dcdf3 100644 --- a/models/asymkey/ssh_key.go +++ b/models/asymkey/ssh_key.go @@ -416,7 +416,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [ } // Check if Public Key sync is needed - if util.IsEqualSlice(giteaKeys, providedKeys) { + if util.SliceSortedEqual(giteaKeys, providedKeys) { log.Trace("synchronizePublicKeys[%s]: Public Keys are already in sync for %s (Source:%v/DB:%v)", s.Name, usr.Name, len(providedKeys), len(giteaKeys)) return false } diff --git a/models/git/branches.go b/models/git/branches.go index e3d53450842e6..5ec9fc1735236 100644 --- a/models/git/branches.go +++ b/models/git/branches.go @@ -342,7 +342,7 @@ func IsProtectedBranch(ctx context.Context, repoID int64, branchName string) (bo // updateApprovalWhitelist checks whether the user whitelist changed and returns a whitelist with // the users from newWhitelist which have explicit read or write access to the repo. func updateApprovalWhitelist(ctx context.Context, repo *repo_model.Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) { - hasUsersChanged := !util.IsEqualSlice(currentWhitelist, newWhitelist) + hasUsersChanged := !util.SliceSortedEqual(currentWhitelist, newWhitelist) if !hasUsersChanged { return currentWhitelist, nil } @@ -363,7 +363,7 @@ func updateApprovalWhitelist(ctx context.Context, repo *repo_model.Repository, c // updateUserWhitelist checks whether the user whitelist changed and returns a whitelist with // the users from newWhitelist which have write access to the repo. func updateUserWhitelist(ctx context.Context, repo *repo_model.Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) { - hasUsersChanged := !util.IsEqualSlice(currentWhitelist, newWhitelist) + hasUsersChanged := !util.SliceSortedEqual(currentWhitelist, newWhitelist) if !hasUsersChanged { return currentWhitelist, nil } @@ -392,7 +392,7 @@ func updateUserWhitelist(ctx context.Context, repo *repo_model.Repository, curre // updateTeamWhitelist checks whether the team whitelist changed and returns a whitelist with // the teams from newWhitelist which have write access to the repo. func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) { - hasTeamsChanged := !util.IsEqualSlice(currentWhitelist, newWhitelist) + hasTeamsChanged := !util.SliceSortedEqual(currentWhitelist, newWhitelist) if !hasTeamsChanged { return currentWhitelist, nil } diff --git a/modules/util/slice.go b/modules/util/slice.go index 9d5297bf7ed7f..767cb2ecb3be5 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -34,18 +34,18 @@ func SliceContainsString(slice []string, target string, insensitive ...bool) boo return SliceContains(slice, target) } -// IsEqualSlice returns true if slices are equal. -// Be careful, two slice which have the same elements but different order are considered equal here. -func IsEqualSlice[T comparable](target, source []T) bool { - if len(target) != len(source) { +// SliceSortedEqual returns true if the two slices will be equal when they get sorted. +// It doesn't require that the slices have been sorted, and it doesn't sort them either. +func SliceSortedEqual[T comparable](s1, s2 []T) bool { + if len(s1) != len(s2) { return false } - counts := make(map[T]int, len(target)) - for _, v := range target { + counts := make(map[T]int, len(s1)) + for _, v := range s1 { counts[v]++ } - for _, v := range source { + for _, v := range s2 { counts[v]-- } @@ -57,6 +57,20 @@ func IsEqualSlice[T comparable](target, source []T) bool { 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 +} + // RemoveFromSlice removes all the target elements from the slice. func RemoveFromSlice[T comparable](target T, slice []T) []T { return RemoveFromSliceFunc(func(t T) bool { return t == target }, slice) diff --git a/modules/util/slice_test.go b/modules/util/slice_test.go index d54de6059cb4c..a20b1641cd7c2 100644 --- a/modules/util/slice_test.go +++ b/modules/util/slice_test.go @@ -35,21 +35,21 @@ func TestSliceContainsString(t *testing.T) { assert.False(t, SliceContainsString(nil, "a")) } -func TestIsEqualSlice(t *testing.T) { - assert.True(t, IsEqualSlice([]int{2, 0, 2, 3}, []int{2, 0, 2, 3})) - assert.True(t, IsEqualSlice([]int{3, 0, 2, 2}, []int{3, 0, 2, 2})) - assert.True(t, IsEqualSlice([]int{}, []int{})) - assert.True(t, IsEqualSlice([]int(nil), nil)) - assert.True(t, IsEqualSlice([]int(nil), []int{})) - assert.True(t, IsEqualSlice([]int{}, []int{})) +func TestSliceSortedEqual(t *testing.T) { + assert.True(t, SliceSortedEqual([]int{2, 0, 2, 3}, []int{2, 0, 2, 3})) + assert.True(t, SliceSortedEqual([]int{3, 0, 2, 2}, []int{3, 0, 2, 2})) + assert.True(t, SliceSortedEqual([]int{}, []int{})) + assert.True(t, SliceSortedEqual([]int(nil), nil)) + assert.True(t, SliceSortedEqual([]int(nil), []int{})) + assert.True(t, SliceSortedEqual([]int{}, []int{})) - assert.True(t, IsEqualSlice([]string{"2", "0", "2", "3"}, []string{"2", "0", "2", "3"})) - assert.True(t, IsEqualSlice([]float64{2, 0, 2, 3}, []float64{2, 0, 2, 3})) - assert.True(t, IsEqualSlice([]bool{false, true, false}, []bool{false, true, false})) + assert.True(t, SliceSortedEqual([]string{"2", "0", "2", "3"}, []string{"2", "0", "2", "3"})) + assert.True(t, SliceSortedEqual([]float64{2, 0, 2, 3}, []float64{2, 0, 2, 3})) + assert.True(t, SliceSortedEqual([]bool{false, true, false}, []bool{false, true, false})) - assert.False(t, IsEqualSlice([]int{2, 0, 2}, []int{2, 0, 2, 3})) - assert.False(t, IsEqualSlice([]int{2, 0, 2, 4}, []int{2, 0, 2, 3})) - assert.False(t, IsEqualSlice([]int{2, 0, 0, 3}, []int{2, 0, 2, 3})) + assert.False(t, SliceSortedEqual([]int{2, 0, 2}, []int{2, 0, 2, 3})) + assert.False(t, SliceSortedEqual([]int{2, 0, 2, 4}, []int{2, 0, 2, 3})) + assert.False(t, SliceSortedEqual([]int{2, 0, 0, 3}, []int{2, 0, 2, 3})) } func TestRemoveFromSlice(t *testing.T) { diff --git a/tests/integration/api_repo_teams_test.go b/tests/integration/api_repo_teams_test.go index e4d054aaf845d..102f170d94f74 100644 --- a/tests/integration/api_repo_teams_test.go +++ b/tests/integration/api_repo_teams_test.go @@ -38,7 +38,7 @@ func TestAPIRepoTeams(t *testing.T) { if assert.Len(t, teams, 2) { assert.EqualValues(t, "Owners", teams[0].Name) assert.True(t, teams[0].CanCreateOrgRepo) - assert.True(t, util.IsEqualSlice(unit.AllUnitKeyNames(), teams[0].Units), fmt.Sprintf("%v == %v", unit.AllUnitKeyNames(), teams[0].Units)) + assert.True(t, util.SliceSortedEqual(unit.AllUnitKeyNames(), teams[0].Units), fmt.Sprintf("%v == %v", unit.AllUnitKeyNames(), teams[0].Units)) assert.EqualValues(t, "owner", teams[0].Permission) assert.EqualValues(t, "test_team", teams[1].Name) From 45b1f72b0dc6f0890190c4245326a6d6c6b88eb5 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Wed, 11 Jan 2023 11:39:01 +0800 Subject: [PATCH 20/21] chore: SliceRemoveAll --- models/org_team.go | 6 +++--- models/user.go | 6 +++--- modules/util/slice.go | 10 +++++----- modules/util/slice_test.go | 22 +++++++++++----------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/models/org_team.go b/models/org_team.go index b815258b61a58..2bbf1d8d8c06c 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -399,9 +399,9 @@ func DeleteTeam(t *organization.Team) error { } for _, p := range protections { lenIDs, lenApprovalIDs, lenMergeIDs := len(p.WhitelistTeamIDs), len(p.ApprovalsWhitelistTeamIDs), len(p.MergeWhitelistTeamIDs) - p.WhitelistTeamIDs = util.RemoveFromSlice(t.ID, p.WhitelistTeamIDs) - p.ApprovalsWhitelistTeamIDs = util.RemoveFromSlice(t.ID, p.ApprovalsWhitelistTeamIDs) - p.MergeWhitelistTeamIDs = util.RemoveFromSlice(t.ID, p.MergeWhitelistTeamIDs) + p.WhitelistTeamIDs = util.SliceRemoveAll(p.WhitelistTeamIDs, t.ID) + p.ApprovalsWhitelistTeamIDs = util.SliceRemoveAll(p.ApprovalsWhitelistTeamIDs, t.ID) + p.MergeWhitelistTeamIDs = util.SliceRemoveAll(p.MergeWhitelistTeamIDs, t.ID) if lenIDs != len(p.WhitelistTeamIDs) || lenApprovalIDs != len(p.ApprovalsWhitelistTeamIDs) || lenMergeIDs != len(p.MergeWhitelistTeamIDs) { diff --git a/models/user.go b/models/user.go index 8a7a1d7e0283e..10282d0db4860 100644 --- a/models/user.go +++ b/models/user.go @@ -142,9 +142,9 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) (err error) } for _, p := range protections { lenIDs, lenApprovalIDs, lenMergeIDs := len(p.WhitelistUserIDs), len(p.ApprovalsWhitelistUserIDs), len(p.MergeWhitelistUserIDs) - p.WhitelistUserIDs = util.RemoveFromSlice(u.ID, p.WhitelistUserIDs) - p.ApprovalsWhitelistUserIDs = util.RemoveFromSlice(u.ID, p.ApprovalsWhitelistUserIDs) - p.MergeWhitelistUserIDs = util.RemoveFromSlice(u.ID, p.MergeWhitelistUserIDs) + p.WhitelistUserIDs = util.SliceRemoveAll(p.WhitelistUserIDs, u.ID) + p.ApprovalsWhitelistUserIDs = util.SliceRemoveAll(p.ApprovalsWhitelistUserIDs, u.ID) + p.MergeWhitelistUserIDs = util.SliceRemoveAll(p.MergeWhitelistUserIDs, u.ID) if lenIDs != len(p.WhitelistUserIDs) || lenApprovalIDs != len(p.ApprovalsWhitelistUserIDs) || lenMergeIDs != len(p.MergeWhitelistUserIDs) { diff --git a/modules/util/slice.go b/modules/util/slice.go index 767cb2ecb3be5..74356f5496205 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -71,13 +71,13 @@ func SliceEqual[T comparable](s1, s2 []T) bool { return true } -// RemoveFromSlice removes all the target elements from the slice. -func RemoveFromSlice[T comparable](target T, slice []T) []T { - return RemoveFromSliceFunc(func(t T) bool { return t == target }, slice) +// SliceRemoveAll removes all the target elements from the slice. +func SliceRemoveAll[T comparable](slice []T, target T) []T { + return SliceRemoveAllFunc(slice, func(t T) bool { return t == target }) } -// RemoveFromSliceFunc removes all elements which satisfy the targetFunc from the slice. -func RemoveFromSliceFunc[T comparable](targetFunc func(T) bool, slice []T) []T { +// 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) { diff --git a/modules/util/slice_test.go b/modules/util/slice_test.go index a20b1641cd7c2..084b79f9b100e 100644 --- a/modules/util/slice_test.go +++ b/modules/util/slice_test.go @@ -52,16 +52,16 @@ func TestSliceSortedEqual(t *testing.T) { assert.False(t, SliceSortedEqual([]int{2, 0, 0, 3}, []int{2, 0, 2, 3})) } -func TestRemoveFromSlice(t *testing.T) { - assert.Equal(t, RemoveFromSlice(0, []int{2, 0, 2, 3}), []int{2, 2, 3}) - assert.Equal(t, RemoveFromSlice(2, []int{2, 0, 2, 3}), []int{0, 3}) - assert.Equal(t, RemoveFromSlice(0, []int{0, 0, 0, 0}), []int{}) - assert.Equal(t, RemoveFromSlice(4, []int{2, 0, 2, 3}), []int{2, 0, 2, 3}) - assert.Equal(t, RemoveFromSlice(0, []int{}), []int{}) - assert.Equal(t, RemoveFromSlice(0, []int(nil)), []int(nil)) - assert.Equal(t, RemoveFromSlice(0, []int{}), []int{}) +func TestSliceRemoveAll(t *testing.T) { + assert.Equal(t, SliceRemoveAll([]int{2, 0, 2, 3}, 0), []int{2, 2, 3}) + assert.Equal(t, SliceRemoveAll([]int{2, 0, 2, 3}, 2), []int{0, 3}) + assert.Equal(t, SliceRemoveAll([]int{0, 0, 0, 0}, 0), []int{}) + assert.Equal(t, SliceRemoveAll([]int{2, 0, 2, 3}, 4), []int{2, 0, 2, 3}) + assert.Equal(t, SliceRemoveAll([]int{}, 0), []int{}) + assert.Equal(t, SliceRemoveAll([]int(nil), 0), []int(nil)) + assert.Equal(t, SliceRemoveAll([]int{}, 0), []int{}) - assert.Equal(t, RemoveFromSlice("0", []string{"2", "0", "2", "3"}), []string{"2", "2", "3"}) - assert.Equal(t, RemoveFromSlice(0, []float64{2, 0, 2, 3}), []float64{2, 2, 3}) - assert.Equal(t, RemoveFromSlice(true, []bool{false, true, false}), []bool{false, false}) + assert.Equal(t, SliceRemoveAll([]string{"2", "0", "2", "3"}, "0"), []string{"2", "2", "3"}) + assert.Equal(t, SliceRemoveAll([]float64{2, 0, 2, 3}, 0), []float64{2, 2, 3}) + assert.Equal(t, SliceRemoveAll([]bool{false, true, false}, true), []bool{false, false}) } From 3590d774083519493285c93ef26fc439d71ddaa1 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Wed, 11 Jan 2023 11:43:11 +0800 Subject: [PATCH 21/21] test: more cases --- modules/util/slice_test.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/modules/util/slice_test.go b/modules/util/slice_test.go index 084b79f9b100e..b0b771a79a8fd 100644 --- a/modules/util/slice_test.go +++ b/modules/util/slice_test.go @@ -37,7 +37,7 @@ func TestSliceContainsString(t *testing.T) { func TestSliceSortedEqual(t *testing.T) { assert.True(t, SliceSortedEqual([]int{2, 0, 2, 3}, []int{2, 0, 2, 3})) - assert.True(t, SliceSortedEqual([]int{3, 0, 2, 2}, []int{3, 0, 2, 2})) + assert.True(t, SliceSortedEqual([]int{3, 0, 2, 2}, []int{2, 0, 2, 3})) assert.True(t, SliceSortedEqual([]int{}, []int{})) assert.True(t, SliceSortedEqual([]int(nil), nil)) assert.True(t, SliceSortedEqual([]int(nil), []int{})) @@ -48,10 +48,31 @@ func TestSliceSortedEqual(t *testing.T) { assert.True(t, SliceSortedEqual([]bool{false, true, false}, []bool{false, true, false})) assert.False(t, SliceSortedEqual([]int{2, 0, 2}, []int{2, 0, 2, 3})) + assert.False(t, SliceSortedEqual([]int{}, []int{2, 0, 2, 3})) + assert.False(t, SliceSortedEqual(nil, []int{2, 0, 2, 3})) assert.False(t, SliceSortedEqual([]int{2, 0, 2, 4}, []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) { assert.Equal(t, SliceRemoveAll([]int{2, 0, 2, 3}, 0), []int{2, 2, 3}) assert.Equal(t, SliceRemoveAll([]int{2, 0, 2, 3}, 2), []int{0, 3})