- 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.tags/v1.19.0-rc0
@@ -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.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") |
@@ -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.SliceContainsString(excludeAbsPath, currentAbsPath) { | |||
if err := addFile(w, currentInsidePath, currentAbsPath, false); err != nil { | |||
return err | |||
} |
@@ -409,14 +409,14 @@ 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.SliceContainsString(providedKeys, key) { | |||
providedKeys = append(providedKeys, key) | |||
} | |||
} | |||
} | |||
// 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 | |||
} | |||
@@ -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.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.ExistsInSlice(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) | |||
} |
@@ -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(app.RedirectURIs, uri.String(), true) { | |||
return true | |||
} | |||
} | |||
} | |||
} | |||
return util.IsStringInSlice(redirectURI, app.RedirectURIs, true) | |||
return util.SliceContainsString(app.RedirectURIs, redirectURI, true) | |||
} | |||
// Base32 characters, but lowercased. |
@@ -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.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.IsSliceInt64Eq(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.IsSliceInt64Eq(currentWhitelist, newWhitelist) | |||
hasTeamsChanged := !util.SliceSortedEqual(currentWhitelist, newWhitelist) | |||
if !hasTeamsChanged { | |||
return currentWhitelist, nil | |||
} | |||
@@ -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.SliceContains(newWhitelist, teams[i].ID) { | |||
whitelist = append(whitelist, teams[i].ID) | |||
} | |||
} |
@@ -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(multipleAssignees, oneAssignee) { | |||
requestAssignees = append(requestAssignees, oneAssignee) | |||
} | |||
@@ -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.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.IsInt64InSlice(issue.PosterID, userIDs) { | |||
if !util.SliceContains(userIDs, issue.PosterID) { | |||
return append(userIDs, issue.PosterID), nil | |||
} | |||
return userIDs, nil |
@@ -398,20 +398,13 @@ 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) | |||
} | |||
if len(p.ApprovalsWhitelistTeamIDs) != 0 { | |||
p.ApprovalsWhitelistTeamIDs, matched2 = util.RemoveIDFromList( | |||
p.ApprovalsWhitelistTeamIDs, t.ID) | |||
} | |||
if len(p.MergeWhitelistTeamIDs) != 0 { | |||
p.MergeWhitelistTeamIDs, matched3 = util.RemoveIDFromList( | |||
p.MergeWhitelistTeamIDs, t.ID) | |||
} | |||
if matched1 || matched2 || matched3 { | |||
lenIDs, lenApprovalIDs, lenMergeIDs := len(p.WhitelistTeamIDs), len(p.ApprovalsWhitelistTeamIDs), len(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) { | |||
if _, err = sess.ID(p.ID).Cols( | |||
"whitelist_team_i_ds", | |||
"merge_whitelist_team_i_ds", |
@@ -141,20 +141,13 @@ 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) | |||
} | |||
if len(p.ApprovalsWhitelistUserIDs) != 0 { | |||
p.ApprovalsWhitelistUserIDs, matched2 = util.RemoveIDFromList( | |||
p.ApprovalsWhitelistUserIDs, u.ID) | |||
} | |||
if len(p.MergeWhitelistUserIDs) != 0 { | |||
p.MergeWhitelistUserIDs, matched3 = util.RemoveIDFromList( | |||
p.MergeWhitelistUserIDs, u.ID) | |||
} | |||
if matched1 || matched2 || matched3 { | |||
lenIDs, lenApprovalIDs, lenMergeIDs := len(p.WhitelistUserIDs), len(p.ApprovalsWhitelistUserIDs), len(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) { | |||
if _, err = e.ID(p.ID).Cols( | |||
"whitelist_user_i_ds", | |||
"merge_whitelist_user_i_ds", |
@@ -170,7 +170,7 @@ func LoadRepoConfig() { | |||
} | |||
for _, f := range customFiles { | |||
if !util.IsStringInSlice(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.IsStringInSlice(name, Licenses, true) { | |||
if util.SliceContainsString(Licenses, name, true) { | |||
sortedLicenses = append(sortedLicenses, name) | |||
} | |||
} | |||
for _, name := range Licenses { | |||
if !util.IsStringInSlice(name, setting.Repository.PreferredLicenses, true) { | |||
if !util.SliceContainsString(setting.Repository.PreferredLicenses, name, true) { | |||
sortedLicenses = append(sortedLicenses, name) | |||
} | |||
} |
@@ -1,92 +0,0 @@ | |||
// Copyright 2017 The Gitea Authors. All rights reserved. | |||
// SPDX-License-Identifier: MIT | |||
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 | |||
} | |||
// 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) | |||
} | |||
// 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) | |||
} | |||
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 | |||
} | |||
// 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) { | |||
return false | |||
} | |||
if (target == nil) != (source == nil) { | |||
return false | |||
} | |||
sort.Strings(target) | |||
sort.Strings(source) | |||
for i, v := range target { | |||
if v != source[i] { | |||
return false | |||
} | |||
} | |||
return true | |||
} |
@@ -1,17 +1,90 @@ | |||
// 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 | |||
// 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 | |||
import "strings" | |||
// SliceContains returns true if the target exists in the 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](slice []T, targetFunc func(T) bool) bool { | |||
for _, v := range slice { | |||
if targetFunc(v) { | |||
return true | |||
} | |||
} | |||
return false | |||
} | |||
// SliceContainsString sequential searches if string exists in slice. | |||
func SliceContainsString(slice []string, target string, insensitive ...bool) bool { | |||
if len(insensitive) != 0 && insensitive[0] { | |||
target = strings.ToLower(target) | |||
return SliceContainsFunc(slice, func(t string) bool { return strings.ToLower(t) == target }) | |||
} | |||
return SliceContains(slice, target) | |||
} | |||
// 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(s1)) | |||
for _, v := range s1 { | |||
counts[v]++ | |||
} | |||
for _, v := range s2 { | |||
counts[v]-- | |||
} | |||
for _, v := range counts { | |||
if v != 0 { | |||
return false | |||
} | |||
} | |||
return true | |||
} | |||
// SliceEqual returns true if the two slices are equal. | |||
func SliceEqual[T comparable](s1, s2 []T) bool { | |||
if len(s1) != len(s2) { | |||
return false | |||
} | |||
for i, v := range s1 { | |||
if s2[i] != v { | |||
return false | |||
} | |||
} | |||
return true | |||
} | |||
// SliceRemoveAll removes all the target elements from the slice. | |||
func SliceRemoveAll[T comparable](slice []T, target T) []T { | |||
return SliceRemoveAllFunc(slice, func(t T) bool { return t == target }) | |||
} | |||
// SliceRemoveAllFunc removes all elements which satisfy the targetFunc from the slice. | |||
func SliceRemoveAllFunc[T comparable](slice []T, targetFunc func(T) bool) []T { | |||
idx := 0 | |||
for _, v := range slice { | |||
if targetFunc(v) { | |||
continue | |||
} | |||
slice[idx] = v | |||
idx++ | |||
} | |||
return list, false | |||
return slice[:idx] | |||
} |
@@ -0,0 +1,88 @@ | |||
// Copyright 2023 The Gitea Authors. All rights reserved. | |||
// SPDX-License-Identifier: MIT | |||
package util | |||
import ( | |||
"testing" | |||
"github.com/stretchr/testify/assert" | |||
) | |||
func TestSliceContains(t *testing.T) { | |||
assert.True(t, SliceContains([]int{2, 0, 2, 3}, 2)) | |||
assert.True(t, SliceContains([]int{2, 0, 2, 3}, 0)) | |||
assert.True(t, SliceContains([]int{2, 0, 2, 3}, 3)) | |||
assert.True(t, SliceContains([]string{"2", "0", "2", "3"}, "0")) | |||
assert.True(t, SliceContains([]float64{2, 0, 2, 3}, 0)) | |||
assert.True(t, SliceContains([]bool{false, true, false}, true)) | |||
assert.False(t, SliceContains([]int{2, 0, 2, 3}, 4)) | |||
assert.False(t, SliceContains([]int{}, 4)) | |||
assert.False(t, SliceContains(nil, 4)) | |||
} | |||
func TestSliceContainsString(t *testing.T) { | |||
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([]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 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{2, 0, 2, 3})) | |||
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, 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, 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}) | |||
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, 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}) | |||
} |
@@ -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(events, event, true) || util.SliceContainsString(events, string(webhook_module.HookEventIssues), 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(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.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(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.IsStringInSlice(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.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(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.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(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) |
@@ -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(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.IsStringInSlice(attachments[i].UUID, files) { | |||
if util.SliceContainsString(files, attachments[i].UUID) { | |||
continue | |||
} | |||
if err := repo_model.DeleteAttachment(attachments[i], true); err != nil { |
@@ -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(setting.Webhook.Types, hookType, true) { | |||
ctx.NotFound("checkHookType", nil) | |||
return "" | |||
} |
@@ -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([]string{"all", "open", "closed"}, state, true) { | |||
state = "all" | |||
} | |||
ctx.Data["State"] = state |
@@ -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(setting.Langs, form.Language) { | |||
ctx.Flash.Error(ctx.Tr("settings.update_language_not_found", form.Language)) | |||
ctx.Redirect(setting.AppSubURL + "/user/settings/appearance") | |||
return |
@@ -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(usersLdapGroups, group) | |||
if isUserInGroup { | |||
for org, teams := range memberships { | |||
membershipsToAdd[org] = teams |
@@ -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(strings.Split(source.AllowedDomains, ","), userName[idx+1:], true) { | |||
return nil, user_model.ErrUserNotExist{Name: userName} | |||
} | |||
} |
@@ -35,7 +35,7 @@ const ( | |||
) | |||
func nameAllowed(name string) error { | |||
if util.IsStringInSlice(name, reservedWikiNames) { | |||
if util.SliceContainsString(reservedWikiNames, name) { | |||
return repo_model.ErrWikiReservedName{ | |||
Title: name, | |||
} |
@@ -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) |