diff --git a/cmd/api/src/api/agi.go b/cmd/api/src/api/agi.go index 808099213..7fa83fe78 100644 --- a/cmd/api/src/api/agi.go +++ b/cmd/api/src/api/agi.go @@ -1,28 +1,28 @@ // Copyright 2023 Specter Ops, Inc. -// +// // Licensed under the Apache License, Version 2.0 // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +// // SPDX-License-Identifier: Apache-2.0 package api import ( "fmt" + "slices" "sort" "strconv" "github.com/specterops/bloodhound/src/model" - "github.com/specterops/bloodhound/slices" ) type AssetGroupMember struct { @@ -82,7 +82,7 @@ func (s AssetGroupMembers) SortBy(columns []string) (AssetGroupMembers, error) { } if descending { - s = slices.Reverse(s) + slices.Reverse(s) } } return s, nil diff --git a/cmd/api/src/api/v2/agi.go b/cmd/api/src/api/v2/agi.go index 50250a253..ac824efcd 100644 --- a/cmd/api/src/api/v2/agi.go +++ b/cmd/api/src/api/v2/agi.go @@ -20,6 +20,7 @@ import ( "fmt" "net/http" "net/url" + "slices" "strconv" "strings" @@ -31,7 +32,6 @@ import ( "github.com/specterops/bloodhound/graphschema/common" "github.com/specterops/bloodhound/headers" "github.com/specterops/bloodhound/log" - "github.com/specterops/bloodhound/slices" "github.com/specterops/bloodhound/src/api" "github.com/specterops/bloodhound/src/ctx" "github.com/specterops/bloodhound/src/model" diff --git a/cmd/api/src/api/v2/audit.go b/cmd/api/src/api/v2/audit.go index 6d159a95c..1230f06c4 100644 --- a/cmd/api/src/api/v2/audit.go +++ b/cmd/api/src/api/v2/audit.go @@ -19,10 +19,10 @@ package v2 import ( "fmt" "net/http" + "slices" "strings" "time" - "github.com/specterops/bloodhound/slices" "github.com/specterops/bloodhound/src/api" "github.com/specterops/bloodhound/src/model" ) diff --git a/cmd/api/src/api/v2/auth/auth.go b/cmd/api/src/api/v2/auth/auth.go index 91f83685a..b0e3ca5c0 100644 --- a/cmd/api/src/api/v2/auth/auth.go +++ b/cmd/api/src/api/v2/auth/auth.go @@ -20,13 +20,19 @@ import ( "fmt" "io" "net/http" + "slices" "strconv" "strings" "time" + "github.com/crewjam/saml" + "github.com/crewjam/saml/samlsp" + "github.com/gofrs/uuid" + "github.com/gorilla/mux" + "github.com/pkg/errors" + "github.com/pquerna/otp/totp" "github.com/specterops/bloodhound/crypto" "github.com/specterops/bloodhound/log" - "github.com/specterops/bloodhound/slices" "github.com/specterops/bloodhound/src/api" v2 "github.com/specterops/bloodhound/src/api/v2" "github.com/specterops/bloodhound/src/auth" @@ -40,13 +46,6 @@ import ( "github.com/specterops/bloodhound/src/serde" "github.com/specterops/bloodhound/src/utils" "github.com/specterops/bloodhound/src/utils/validation" - - "github.com/crewjam/saml" - "github.com/crewjam/saml/samlsp" - "github.com/gofrs/uuid" - "github.com/gorilla/mux" - "github.com/pkg/errors" - "github.com/pquerna/otp/totp" ) const ( diff --git a/cmd/api/src/api/v2/file_uploads.go b/cmd/api/src/api/v2/file_uploads.go index 8a9512fa2..87b8526d2 100644 --- a/cmd/api/src/api/v2/file_uploads.go +++ b/cmd/api/src/api/v2/file_uploads.go @@ -20,12 +20,12 @@ import ( "errors" "fmt" "net/http" + "slices" "strconv" "strings" "github.com/gorilla/mux" "github.com/specterops/bloodhound/log" - "github.com/specterops/bloodhound/slices" "github.com/specterops/bloodhound/src/api" "github.com/specterops/bloodhound/src/auth" "github.com/specterops/bloodhound/src/ctx" diff --git a/cmd/api/src/api/v2/pathfinding.go b/cmd/api/src/api/v2/pathfinding.go index 0efd1d70e..7d0d51ca8 100644 --- a/cmd/api/src/api/v2/pathfinding.go +++ b/cmd/api/src/api/v2/pathfinding.go @@ -26,7 +26,7 @@ import ( "github.com/specterops/bloodhound/graphschema/ad" "github.com/specterops/bloodhound/graphschema/azure" "github.com/specterops/bloodhound/params" - "github.com/specterops/bloodhound/slices" + "github.com/specterops/bloodhound/slicesext" "github.com/specterops/bloodhound/src/api" "github.com/specterops/bloodhound/src/api/bloodhoundgraph" "github.com/specterops/bloodhound/src/model" @@ -62,11 +62,11 @@ func writeShortestPathsResult(paths graph.PathSet, response http.ResponseWriter, graphResponse.Nodes[n.ID.String()] = model.FromDAWGSNode(n, false) } - edges := slices.FlatMap(paths, func(path graph.Path) []model.UnifiedEdge { - return slices.Map(path.Edges, model.FromDAWGSRelationship(false)) + edges := slicesext.FlatMap(paths, func(path graph.Path) []model.UnifiedEdge { + return slicesext.Map(path.Edges, model.FromDAWGSRelationship(false)) }) - graphResponse.Edges = slices.UniqueBy(edges, func(edge model.UnifiedEdge) string { + graphResponse.Edges = slicesext.UniqueBy(edges, func(edge model.UnifiedEdge) string { return edge.Source + edge.Kind + edge.Target }) diff --git a/cmd/api/src/model/filter.go b/cmd/api/src/model/filter.go index a4afa4143..fd2b0cd0f 100644 --- a/cmd/api/src/model/filter.go +++ b/cmd/api/src/model/filter.go @@ -1,17 +1,17 @@ // Copyright 2023 Specter Ops, Inc. -// +// // Licensed under the Apache License, Version 2.0 // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +// // SPDX-License-Identifier: Apache-2.0 package model @@ -20,6 +20,7 @@ import ( "fmt" "net/http" "regexp" + "slices" "strconv" "strings" @@ -27,7 +28,6 @@ import ( "github.com/specterops/bloodhound/dawgs/query" "github.com/specterops/bloodhound/errors" - "github.com/specterops/bloodhound/slices" ) type FilterOperator string diff --git a/cmd/api/src/model/search.go b/cmd/api/src/model/search.go index 4e8069702..8eee9d4f3 100644 --- a/cmd/api/src/model/search.go +++ b/cmd/api/src/model/search.go @@ -1,17 +1,17 @@ // Copyright 2023 Specter Ops, Inc. -// +// // Licensed under the Apache License, Version 2.0 // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +// // SPDX-License-Identifier: Apache-2.0 package model @@ -20,12 +20,12 @@ import ( "fmt" "net/http" "net/url" + "slices" "github.com/specterops/bloodhound/dawgs/graph" "github.com/specterops/bloodhound/dawgs/query" "github.com/specterops/bloodhound/graphschema/ad" "github.com/specterops/bloodhound/graphschema/azure" - "github.com/specterops/bloodhound/slices" ) type DomainSelector struct { diff --git a/go.work b/go.work index 22dfbb4ed..dcb1debce 100644 --- a/go.work +++ b/go.work @@ -33,6 +33,6 @@ use ( ./packages/go/mediatypes ./packages/go/params ./packages/go/schemagen - ./packages/go/slices + ./packages/go/slicesext ./packages/go/stbernard ) diff --git a/packages/go/analysis/ad/esc3.go b/packages/go/analysis/ad/esc3.go index b26804047..dbf892eeb 100644 --- a/packages/go/analysis/ad/esc3.go +++ b/packages/go/analysis/ad/esc3.go @@ -18,13 +18,13 @@ package ad import ( "context" + "slices" "github.com/specterops/bloodhound/analysis" "github.com/specterops/bloodhound/dawgs/graph" "github.com/specterops/bloodhound/dawgs/util/channels" "github.com/specterops/bloodhound/graphschema/ad" "github.com/specterops/bloodhound/log" - "github.com/specterops/bloodhound/slices" ) func PostEnrollOnBehalfOf(certTemplates []*graph.Node, operation analysis.StatTrackedOperation[analysis.CreatePostRelationshipJob]) error { diff --git a/packages/go/analysis/ad/esc_shared.go b/packages/go/analysis/ad/esc_shared.go index 0a86d9f33..bf24234dc 100644 --- a/packages/go/analysis/ad/esc_shared.go +++ b/packages/go/analysis/ad/esc_shared.go @@ -29,7 +29,7 @@ import ( "github.com/specterops/bloodhound/dawgs/util/channels" "github.com/specterops/bloodhound/graphschema/ad" "github.com/specterops/bloodhound/log" - "github.com/specterops/bloodhound/slices" + "github.com/specterops/bloodhound/slicesext" ) func PostTrustedForNTAuth(ctx context.Context, db graph.Database, operation analysis.StatTrackedOperation[analysis.CreatePostRelationshipJob]) error { @@ -150,7 +150,7 @@ func processCertChainParent(node *graph.Node, tx graph.Transaction) ([]analysis. if targetNodes, err := findNodesByCertThumbprint(parentCert, tx, ad.EnterpriseCA, ad.RootCA); err != nil { return []analysis.CreatePostRelationshipJob{}, err } else { - return slices.Map(targetNodes, func(nodeId graph.ID) analysis.CreatePostRelationshipJob { + return slicesext.Map(targetNodes, func(nodeId graph.ID) analysis.CreatePostRelationshipJob { return analysis.CreatePostRelationshipJob{ FromID: node.ID, ToID: nodeId, diff --git a/packages/go/analysis/analysis.go b/packages/go/analysis/analysis.go index 396e0273d..81cd13a20 100644 --- a/packages/go/analysis/analysis.go +++ b/packages/go/analysis/analysis.go @@ -19,6 +19,7 @@ package analysis import ( "context" "fmt" + "slices" "strings" "github.com/specterops/bloodhound/dawgs/graph" @@ -28,7 +29,7 @@ import ( "github.com/specterops/bloodhound/graphschema/azure" "github.com/specterops/bloodhound/graphschema/common" "github.com/specterops/bloodhound/log" - "github.com/specterops/bloodhound/slices" + "github.com/specterops/bloodhound/slicesext" ) const ( @@ -110,17 +111,10 @@ func ClearSystemTags(ctx context.Context, db graph.Database) error { func ValidKinds() []graph.Kind { var ( - lenCalc = len(ad.Nodes()) + len(ad.Relationships()) + len(azure.NodeKinds()) + len(azure.Relationships()) - kinds = make([]graph.Kind, 0, lenCalc) + metaKinds = []graph.Kind{metaKind, metaDetailKind} ) - kinds = append(kinds, ad.Nodes()...) - kinds = append(kinds, ad.Relationships()...) - kinds = append(kinds, azure.NodeKinds()...) - kinds = append(kinds, azure.Relationships()...) - kinds = append(kinds, metaKind, metaDetailKind) - - return kinds + return slicesext.Concat(ad.Nodes(), ad.Relationships(), azure.NodeKinds(), azure.Relationships(), metaKinds) } func ParseKind(rawKind string) (graph.Kind, error) { @@ -138,7 +132,7 @@ func ParseKinds(rawKinds ...string) (graph.Kinds, error) { return graph.Kinds{ad.Entity, azure.Entity}, nil } - return slices.MapWithErr(rawKinds, ParseKind) + return slicesext.MapWithErr(rawKinds, ParseKind) } func nodeByIndexedKindProperty(property, value string, kind graph.Kind) graph.Criteria { diff --git a/packages/go/analysis/analysis_test.go b/packages/go/analysis/analysis_test.go index 58241faa5..2b7ebc828 100644 --- a/packages/go/analysis/analysis_test.go +++ b/packages/go/analysis/analysis_test.go @@ -23,6 +23,7 @@ import ( "github.com/specterops/bloodhound/dawgs/graph" "github.com/specterops/bloodhound/graphschema/ad" "github.com/specterops/bloodhound/graphschema/azure" + "github.com/specterops/bloodhound/slicesext" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -46,17 +47,7 @@ func (s kindStr) Is(others ...graph.Kind) bool { } func validKinds() graph.Kinds { - var ( - lenCalc = len(ad.NodeKinds()) + len(ad.Relationships()) + len(azure.NodeKinds()) + len(azure.Relationships()) - kinds = make(graph.Kinds, 0, lenCalc) - ) - - kinds = append(kinds, ad.NodeKinds()...) - kinds = append(kinds, ad.Relationships()...) - kinds = append(kinds, azure.NodeKinds()...) - kinds = append(kinds, azure.Relationships()...) - - return kinds + return slicesext.Concat(ad.NodeKinds(), ad.Relationships(), azure.NodeKinds(), azure.Relationships()) } func validKindStrings() []string { diff --git a/packages/go/analysis/azure/post.go b/packages/go/analysis/azure/post.go index 79857da96..4f1589ba9 100644 --- a/packages/go/analysis/azure/post.go +++ b/packages/go/analysis/azure/post.go @@ -19,11 +19,13 @@ package azure import ( "context" "fmt" + "slices" "strings" "github.com/RoaringBitmap/roaring" "github.com/RoaringBitmap/roaring/roaring64" "github.com/bloodhoundad/azurehound/v2/constants" + "github.com/specterops/bloodhound/analysis" "github.com/specterops/bloodhound/dawgs/graph" "github.com/specterops/bloodhound/dawgs/ops" "github.com/specterops/bloodhound/dawgs/query" @@ -31,9 +33,6 @@ import ( "github.com/specterops/bloodhound/graphschema/azure" "github.com/specterops/bloodhound/graphschema/common" "github.com/specterops/bloodhound/log" - "github.com/specterops/bloodhound/slices" - - "github.com/specterops/bloodhound/analysis" ) func AddMemberAllGroupsTargetRoles() []string { diff --git a/packages/go/ein/ad.go b/packages/go/ein/ad.go index b0acf1543..8cb84e37e 100644 --- a/packages/go/ein/ad.go +++ b/packages/go/ein/ad.go @@ -23,7 +23,7 @@ import ( "github.com/specterops/bloodhound/dawgs/graph" "github.com/specterops/bloodhound/graphschema/ad" "github.com/specterops/bloodhound/log" - "github.com/specterops/bloodhound/slices" + "github.com/specterops/bloodhound/slicesext" ) func ConvertSessionObject(session Session) IngestibleSession { @@ -510,7 +510,7 @@ func handleEnterpriseCAEnrollmentAgentRestrictions(enterpriseCA EnterpriseCA, re func handleEnterpriseCASecurity(enterpriseCA EnterpriseCA, relationships []IngestibleRelationship) []IngestibleRelationship { if enterpriseCA.CARegistryData.CASecurity.Collected { - caSecurityData := slices.Filter(enterpriseCA.CARegistryData.CASecurity.Data, func(s ACE) bool { + caSecurityData := slicesext.Filter(enterpriseCA.CARegistryData.CASecurity.Data, func(s ACE) bool { if s.PrincipalType == ad.LocalGroup.String() { return false } @@ -521,7 +521,7 @@ func handleEnterpriseCASecurity(enterpriseCA EnterpriseCA, relationships []Inges } }) - filteredACES := slices.Filter(enterpriseCA.Aces, func(s ACE) bool { + filteredACES := slicesext.Filter(enterpriseCA.Aces, func(s ACE) bool { if s.PrincipalSID == enterpriseCA.HostingComputer { return true } else { diff --git a/packages/go/ein/azure.go b/packages/go/ein/azure.go index 5b816e2fa..e2f992792 100644 --- a/packages/go/ein/azure.go +++ b/packages/go/ein/azure.go @@ -20,21 +20,20 @@ import ( "encoding/json" "fmt" "regexp" + "slices" "strings" "time" "github.com/bloodhoundad/azurehound/v2/constants" "github.com/bloodhoundad/azurehound/v2/enums" + "github.com/bloodhoundad/azurehound/v2/models" azure2 "github.com/bloodhoundad/azurehound/v2/models/azure" "github.com/specterops/bloodhound/dawgs/graph" "github.com/specterops/bloodhound/errors" "github.com/specterops/bloodhound/graphschema/ad" - "github.com/specterops/bloodhound/log" - "github.com/specterops/bloodhound/slices" - - "github.com/bloodhoundad/azurehound/v2/models" "github.com/specterops/bloodhound/graphschema/azure" "github.com/specterops/bloodhound/graphschema/common" + "github.com/specterops/bloodhound/log" ) const ( diff --git a/packages/go/graphschema/schema.go b/packages/go/graphschema/schema.go index b14e8be6d..632a57d80 100644 --- a/packages/go/graphschema/schema.go +++ b/packages/go/graphschema/schema.go @@ -21,6 +21,7 @@ import ( "github.com/specterops/bloodhound/graphschema/ad" "github.com/specterops/bloodhound/graphschema/azure" "github.com/specterops/bloodhound/graphschema/common" + "github.com/specterops/bloodhound/slicesext" ) const ( @@ -39,8 +40,8 @@ func AzureGraphName(suffix string) string { func CombinedGraphSchema(name string) graph.Graph { return graph.Graph{ Name: name, - Nodes: append(common.NodeKinds(), append(azure.NodeKinds(), ad.NodeKinds()...)...), - Edges: append(common.Relationships(), append(azure.Relationships(), ad.Relationships()...)...), + Nodes: slicesext.Concat(common.NodeKinds(), azure.NodeKinds(), ad.NodeKinds()), + Edges: slicesext.Concat(common.Relationships(), azure.Relationships(), ad.Relationships()), NodeConstraints: []graph.Constraint{{ Field: common.ObjectID.String(), Type: graph.BTreeIndex, diff --git a/packages/go/headers/header.go b/packages/go/headers/header.go index c6e7494f3..28e14c3cb 100644 --- a/packages/go/headers/header.go +++ b/packages/go/headers/header.go @@ -1,22 +1,22 @@ // Copyright 2023 Specter Ops, Inc. -// +// // Licensed under the Apache License, Version 2.0 // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +// // SPDX-License-Identifier: Apache-2.0 package headers -//go:generate go run generate.go +//go:generate go run cmd/generate.go type Header string diff --git a/packages/go/mediatypes/generate.go b/packages/go/mediatypes/cmd/generate.go similarity index 95% rename from packages/go/mediatypes/generate.go rename to packages/go/mediatypes/cmd/generate.go index b608a7e19..8055d08b0 100644 --- a/packages/go/mediatypes/generate.go +++ b/packages/go/mediatypes/cmd/generate.go @@ -1,17 +1,17 @@ // Copyright 2023 Specter Ops, Inc. -// +// // Licensed under the Apache License, Version 2.0 // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +// // SPDX-License-Identifier: Apache-2.0 //go:build ignored @@ -36,7 +36,7 @@ import ( "text/template" "time" - "github.com/specterops/bloodhound/slices" + "github.com/specterops/bloodhound/slicesext" ) var packageTemplate = template.Must(template.New("").Parse(`// Code generated by gen.go; DO NOT EDIT. @@ -126,7 +126,7 @@ func mediaTypesFromCSV(category string, readcloser io.ReadCloser) ([]MediaType, entries := []MediaType{} for _, row := range types[1:] { if row[1] != "" { - symbol := strings.Join(slices.Map(regex.Split(row[0], -1), func(word string) string { + symbol := strings.Join(slicesext.Map(regex.Split(row[0], -1), func(word string) string { return strings.Title(word) }), "") entries = append(entries, MediaType{ diff --git a/packages/go/mediatypes/mediatype.go b/packages/go/mediatypes/mediatype.go index daaa50d6e..6388ad7d4 100644 --- a/packages/go/mediatypes/mediatype.go +++ b/packages/go/mediatypes/mediatype.go @@ -1,24 +1,24 @@ // Copyright 2023 Specter Ops, Inc. -// +// // Licensed under the Apache License, Version 2.0 // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +// // SPDX-License-Identifier: Apache-2.0 package mediatypes import "fmt" -//go:generate go run generate.go +//go:generate go run cmd/generate.go type MediaType string diff --git a/packages/go/slices/slices_test.go b/packages/go/slices/slices_test.go deleted file mode 100644 index ec0aa9946..000000000 --- a/packages/go/slices/slices_test.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2023 Specter Ops, Inc. -// -// Licensed under the Apache License, Version 2.0 -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 - -package slices_test - -import ( - "fmt" - "strconv" - "strings" - "testing" - - "github.com/stretchr/testify/require" - "github.com/specterops/bloodhound/slices" -) - -var ( - listEmpty = []int{} - listSingle = []int{0} - listDuo = []int{0, 1} - reversedListDuo = []int{1, 0} - listEven = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} - reversedListEven = []int{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} - listOdd = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} - reversedListOdd = []int{14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} -) - -func TestFilter(t *testing.T) { - require.Equal(t, []int{1, 3}, slices.Filter([]int{1, 2, 3, 4}, isOdd)) - require.Equal(t, []string{"bbbbbb", "cccccccc"}, slices.Filter([]string{"aaaa", "bbbbbb", "cccccccc", "dd"}, isLong)) -} - -func TestMap(t *testing.T) { - require.Equal(t, []uint{1, 3, 4, 12}, slices.Map([]int{-1, -3, 4, -12}, abs)) - require.Equal(t, []string{"abc", "def", "hij"}, slices.Map([]string{"ABC", "DEF", "HIJ"}, strings.ToLower)) - require.Equal(t, []int{3, 6, 9, 12}, slices.Map([]int{1, 2, 3, 4}, triple)) -} - -func TestFlatMap(t *testing.T) { - require.Equal(t, []string{"a", "a", "b", "b"}, slices.FlatMap([]string{"a", "b"}, duplicate[string])) - require.Equal(t, []int{1, 1, 2, 2}, slices.FlatMap([]int{1, 2}, duplicate[int])) -} - -func TestUnique(t *testing.T) { - var ( - in = []string{"a", "a", "b", "b"} - out = slices.Unique(in) - ) - - require.Equal(t, []string{"a", "b"}, out) - require.NotSame(t, in, out) // ensure we didn't mutate the original slice - require.Equal(t, []string{"a", "b"}, slices.Unique([]string{"a", "b", "b", "a"})) - require.Equal(t, []string{"a"}, slices.Unique([]string{"a"})) - require.Equal(t, []int{1, 2, 3}, slices.Unique([]int{1, 1, 2, 2, 3})) -} - -func TestContains(t *testing.T) { - require.True(t, slices.Contains([]string{"a", "b", "c"}, "c")) - require.False(t, slices.Contains([]string{"a", "b", "c"}, "d")) -} - -func TestReverse(t *testing.T) { - require.Equal(t, []int{}, slices.Reverse(listEmpty)) - require.Equal(t, []int{0}, slices.Reverse(listSingle)) - require.Equal(t, reversedListDuo, slices.Reverse(listDuo)) - require.Equal(t, reversedListEven, slices.Reverse(listEven)) - require.Equal(t, reversedListOdd, slices.Reverse(listOdd)) -} - -func BenchmarkReverse(b *testing.B) { - for i := 10; i < 1000000; i = i * 10 { - list := make([]int, i) - for idx := range list { - list[idx] = idx - } - - b.Run(fmt.Sprintf("reverse_%d", i), func(b *testing.B) { - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - slices.Reverse(list) - } - }) - }) - } -} - -func BenchmarkHead(b *testing.B) { - for i := 10; i < 1000000; i = i * 10 { - list := make([]int, i) - for idx := range list { - list[idx] = idx - } - - b.Run(fmt.Sprintf("head_%d", i), func(b *testing.B) { - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - a := slices.Head(list) - require.IsType(b, int(0), a) - } - }) - }) - - b.Run(fmt.Sprintf("[0]_%d", i), func(b *testing.B) { - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - a := list[0] - require.IsType(b, int(0), a) - } - }) - }) - } -} - -func BenchmarkTail(b *testing.B) { - for i := 10; i < 1000000; i = i * 10 { - list := make([]int, i) - for idx := range list { - list[idx] = idx - } - - b.Run(fmt.Sprintf("tail_%d", i), func(b *testing.B) { - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - a := slices.Tail(list) - require.IsType(b, []int{}, a) - } - }) - }) - - b.Run(fmt.Sprintf("[1:]_%d", i), func(b *testing.B) { - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - a := list[1:] - require.IsType(b, []int{}, a) - } - }) - }) - } -} - -func abs(n int) uint { - mask := n >> (strconv.IntSize - 1) - return uint((n ^ mask) - mask) -} - -func duplicate[T any](t T) []T { - return []T{t, t} -} - -func isOdd(n int) bool { - return n%2 == 1 -} - -func isLong(s string) bool { - return len(s) > 5 -} - -func triple(n int) int { - return n * 3 -} diff --git a/packages/go/slices/foldl.go b/packages/go/slicesext/foldl.go similarity index 98% rename from packages/go/slices/foldl.go rename to packages/go/slicesext/foldl.go index afd8454fa..7964416a7 100644 --- a/packages/go/slices/foldl.go +++ b/packages/go/slicesext/foldl.go @@ -1,20 +1,20 @@ // Copyright 2023 Specter Ops, Inc. -// +// // Licensed under the Apache License, Version 2.0 // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +// // SPDX-License-Identifier: Apache-2.0 -package slices +package slicesext // Foldl returns an accumulative value by applying the provided function to each // element in the list and the accumulation starting with the first list element. diff --git a/packages/go/slices/foldl_test.go b/packages/go/slicesext/foldl_test.go similarity index 79% rename from packages/go/slices/foldl_test.go rename to packages/go/slicesext/foldl_test.go index 8c2e6f2e6..5e0090a0d 100644 --- a/packages/go/slices/foldl_test.go +++ b/packages/go/slicesext/foldl_test.go @@ -1,27 +1,27 @@ // Copyright 2023 Specter Ops, Inc. -// +// // Licensed under the Apache License, Version 2.0 // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +// // SPDX-License-Identifier: Apache-2.0 -package slices_test +package slicesext_test import ( "fmt" "testing" + "github.com/specterops/bloodhound/slicesext" "github.com/stretchr/testify/require" - "github.com/specterops/bloodhound/slices" ) func TestFoldl(t *testing.T) { @@ -46,23 +46,23 @@ func TestFoldl(t *testing.T) { switch c := c.(type) { case Case[int, int]: t.Run(c.Name, func(t *testing.T) { - require.Equal(t, c.Output, slices.Foldl(c.InitVal, c.List, c.Accumulator)) - require.Equal(t, c.Output, slices.FoldlLazy(c.InitVal, c.List, c.Accumulator)) + require.Equal(t, c.Output, slicesext.Foldl(c.InitVal, c.List, c.Accumulator)) + require.Equal(t, c.Output, slicesext.FoldlLazy(c.InitVal, c.List, c.Accumulator)) }) } } t.Run("should handle multiple reducers", func(t *testing.T) { // ((((5 +1)*1)+1)*1)+2)*2 = 18 - require.Equal(t, 18, slices.Foldl(5, []int{1, 1, 2}, sum, mult)) - require.Equal(t, 18, slices.FoldlLazy(5, []int{1, 1, 2}, sum, mult)) + require.Equal(t, 18, slicesext.Foldl(5, []int{1, 1, 2}, sum, mult)) + require.Equal(t, 18, slicesext.FoldlLazy(5, []int{1, 1, 2}, sum, mult)) }) } func FuzzFoldl(f *testing.F) { f.Add([]byte{5}, []byte{1, 2, 3, 4}) f.Fuzz(func(t *testing.T, a []byte, b []byte) { - out := slices.Foldl(a, b, func(x []byte, y byte) []byte { + out := slicesext.Foldl(a, b, func(x []byte, y byte) []byte { return cons(x, y) }) require.Equal(t, len(a)+len(b), len(out)) @@ -72,7 +72,7 @@ func FuzzFoldl(f *testing.F) { func FuzzFoldlLazy(f *testing.F) { f.Add([]byte{5}, []byte{1, 2, 3, 4}) f.Fuzz(func(t *testing.T, a []byte, b []byte) { - out := slices.FoldlLazy(a, b, func(x []byte, y byte) []byte { + out := slicesext.FoldlLazy(a, b, func(x []byte, y byte) []byte { return cons(x, y) }) require.Equal(t, len(a)+len(b), len(out)) @@ -86,7 +86,7 @@ func BenchmarkFoldl(b *testing.B) { b.Run(fmt.Sprintf("lazy_%d", i), func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { - slices.Foldl(0, list, sum) + slicesext.Foldl(0, list, sum) } }) }) @@ -94,7 +94,7 @@ func BenchmarkFoldl(b *testing.B) { b.Run(fmt.Sprintf("eager_%d", i), func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { - slices.FoldlLazy(0, list, sum) + slicesext.FoldlLazy(0, list, sum) } }) }) diff --git a/packages/go/slices/foldr.go b/packages/go/slicesext/foldr.go similarity index 98% rename from packages/go/slices/foldr.go rename to packages/go/slicesext/foldr.go index c7915c649..782ab031d 100644 --- a/packages/go/slices/foldr.go +++ b/packages/go/slicesext/foldr.go @@ -1,20 +1,20 @@ // Copyright 2023 Specter Ops, Inc. -// +// // Licensed under the Apache License, Version 2.0 // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +// // SPDX-License-Identifier: Apache-2.0 -package slices +package slicesext // Foldr returns an accumulative value by recursively applying the provided function to each element in the list and the accumulation // starting with the last list element. diff --git a/packages/go/slices/foldr_test.go b/packages/go/slicesext/foldr_test.go similarity index 80% rename from packages/go/slices/foldr_test.go rename to packages/go/slicesext/foldr_test.go index 8da91c779..177627405 100644 --- a/packages/go/slices/foldr_test.go +++ b/packages/go/slicesext/foldr_test.go @@ -1,27 +1,27 @@ // Copyright 2023 Specter Ops, Inc. -// +// // Licensed under the Apache License, Version 2.0 // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +// // SPDX-License-Identifier: Apache-2.0 -package slices_test +package slicesext_test import ( "fmt" "testing" + "github.com/specterops/bloodhound/slicesext" "github.com/stretchr/testify/require" - "github.com/specterops/bloodhound/slices" ) func sum(a, b int) int { @@ -72,21 +72,21 @@ func TestFoldr(t *testing.T) { switch c := c.(type) { case Case[int, int]: t.Run(c.Name, func(t *testing.T) { - require.Equal(t, c.Output, slices.Foldr(c.InitVal, c.List, c.Reducer)) - require.Equal(t, c.Output, slices.FoldrEager(c.InitVal, c.List, c.Reducer)) + require.Equal(t, c.Output, slicesext.Foldr(c.InitVal, c.List, c.Reducer)) + require.Equal(t, c.Output, slicesext.FoldrEager(c.InitVal, c.List, c.Reducer)) }) case Case[bool, bool]: t.Run(c.Name, func(t *testing.T) { - require.Equal(t, c.Output, slices.Foldr(c.InitVal, c.List, c.Reducer)) - require.Equal(t, c.Output, slices.FoldrEager(c.InitVal, c.List, c.Reducer)) + require.Equal(t, c.Output, slicesext.Foldr(c.InitVal, c.List, c.Reducer)) + require.Equal(t, c.Output, slicesext.FoldrEager(c.InitVal, c.List, c.Reducer)) }) } } t.Run("should handle multiple reducers", func(t *testing.T) { // 1*(1+(1*(1+(2*(2+5))))) = 16 - require.Equal(t, 16, slices.Foldr(5, []int{1, 1, 2}, sum, mult)) - require.Equal(t, 16, slices.FoldrEager(5, []int{1, 1, 2}, sum, mult)) + require.Equal(t, 16, slicesext.Foldr(5, []int{1, 1, 2}, sum, mult)) + require.Equal(t, 16, slicesext.FoldrEager(5, []int{1, 1, 2}, sum, mult)) }) } @@ -97,7 +97,7 @@ func cons(a []byte, b byte) []byte { func FuzzFoldr(f *testing.F) { f.Add([]byte{5}, []byte{1, 2, 3, 4}) f.Fuzz(func(t *testing.T, a []byte, b []byte) { - out := slices.Foldr(a, b, cons) + out := slicesext.Foldr(a, b, cons) require.Equal(t, len(a)+len(b), len(out)) }) } @@ -109,7 +109,7 @@ func BenchmarkFoldr(b *testing.B) { b.Run(fmt.Sprintf("lazy_%d", i), func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { - slices.Foldr(0, list, sum) + slicesext.Foldr(0, list, sum) } }) }) @@ -117,7 +117,7 @@ func BenchmarkFoldr(b *testing.B) { b.Run(fmt.Sprintf("eager_%d", i), func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { - slices.Foldr(0, list, sum) + slicesext.Foldr(0, list, sum) } }) }) diff --git a/packages/go/slices/go.mod b/packages/go/slicesext/go.mod similarity index 95% rename from packages/go/slices/go.mod rename to packages/go/slicesext/go.mod index 4571e4be5..bd7369fb3 100644 --- a/packages/go/slices/go.mod +++ b/packages/go/slicesext/go.mod @@ -14,7 +14,7 @@ // // SPDX-License-Identifier: Apache-2.0 -module github.com/specterops/bloodhound/slices +module github.com/specterops/bloodhound/slicesext go 1.21 diff --git a/packages/go/slices/go.sum b/packages/go/slicesext/go.sum similarity index 100% rename from packages/go/slices/go.sum rename to packages/go/slicesext/go.sum diff --git a/packages/go/slices/slices.go b/packages/go/slicesext/slicesext.go similarity index 80% rename from packages/go/slices/slices.go rename to packages/go/slicesext/slicesext.go index fc3b07f84..db4abcf2c 100644 --- a/packages/go/slices/slices.go +++ b/packages/go/slicesext/slicesext.go @@ -14,7 +14,10 @@ // // SPDX-License-Identifier: Apache-2.0 -package slices +// Package slicesext extends the standard library slices package with additional slice utilities +package slicesext + +import "slices" // Filter applies a predicate function over each element in a given slice and returns a new slice containing only the elements in which the predicate returns true func Filter[T any](slice []T, fn func(T) bool) []T { @@ -99,16 +102,6 @@ func UniqueBy[T any, U comparable](slice []T, fn func(T) U) []T { return out } -// Contains returns true if a slice contains an element that is equal to the given value -func Contains[T comparable](slice []T, value T) bool { - for _, sliceValue := range slice { - if sliceValue == value { - return true - } - } - return false -} - func Head[T any](list []T) T { return list[0] } @@ -125,12 +118,21 @@ func Init[T any](list []T) []T { return list[:len(list)-1] } -// Reverse reverses the order of a slice by doing an in place reverse -// This will reorder the provided slice in place, and uses zero allocations -func Reverse[T any](list []T) []T { - for low, high := 0, len(list)-1; low < high; low, high = low+1, high-1 { - list[low], list[high] = list[high], list[low] +// Copyright 2021 The Go Authors. All rights reserved. +// Concat returns a new slice concatenating the passed in slices. +// This was ripped from go1.22 source and should be replaced with the stdlib implementation when we move to 1.22 +// Original source: https://github.com/golang/go/blob/5c0d0929d3a6378c710376b55a49abd55b31a805/src/slices/slices.go#L502 +func Concat[S ~[]E, E any](s ...S) S { + size := 0 + for _, slice := range s { + size += len(slice) + if size < 0 { + panic("len out of range") + } } - - return list + newslice := slices.Grow[S](nil, size) + for _, s := range s { + newslice = append(newslice, s...) + } + return newslice } diff --git a/packages/go/slicesext/slicesext_test.go b/packages/go/slicesext/slicesext_test.go new file mode 100644 index 000000000..612f66986 --- /dev/null +++ b/packages/go/slicesext/slicesext_test.go @@ -0,0 +1,245 @@ +// Copyright 2023 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +package slicesext_test + +import ( + "fmt" + "math" + "slices" + "strconv" + "strings" + "testing" + + "github.com/specterops/bloodhound/slicesext" + "github.com/stretchr/testify/require" +) + +var ( + listEmpty = []int{} + listSingle = []int{0} + listDuo = []int{0, 1} + reversedListDuo = []int{1, 0} + listEven = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} + reversedListEven = []int{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} + listOdd = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} + reversedListOdd = []int{14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} +) + +func TestFilter(t *testing.T) { + require.Equal(t, []int{1, 3}, slicesext.Filter([]int{1, 2, 3, 4}, isOdd)) + require.Equal(t, []string{"bbbbbb", "cccccccc"}, slicesext.Filter([]string{"aaaa", "bbbbbb", "cccccccc", "dd"}, isLong)) +} + +func TestMap(t *testing.T) { + require.Equal(t, []uint{1, 3, 4, 12}, slicesext.Map([]int{-1, -3, 4, -12}, abs)) + require.Equal(t, []string{"abc", "def", "hij"}, slicesext.Map([]string{"ABC", "DEF", "HIJ"}, strings.ToLower)) + require.Equal(t, []int{3, 6, 9, 12}, slicesext.Map([]int{1, 2, 3, 4}, triple)) +} + +func TestFlatMap(t *testing.T) { + require.Equal(t, []string{"a", "a", "b", "b"}, slicesext.FlatMap([]string{"a", "b"}, duplicate[string])) + require.Equal(t, []int{1, 1, 2, 2}, slicesext.FlatMap([]int{1, 2}, duplicate[int])) +} + +func TestUnique(t *testing.T) { + var ( + in = []string{"a", "a", "b", "b"} + out = slicesext.Unique(in) + ) + + require.Equal(t, []string{"a", "b"}, out) + require.NotSame(t, in, out) // ensure we didn't mutate the original slice + require.Equal(t, []string{"a", "b"}, slicesext.Unique([]string{"a", "b", "b", "a"})) + require.Equal(t, []string{"a"}, slicesext.Unique([]string{"a"})) + require.Equal(t, []int{1, 2, 3}, slicesext.Unique([]int{1, 1, 2, 2, 3})) +} + +func BenchmarkHead(b *testing.B) { + for i := 10; i < 1000000; i = i * 10 { + list := make([]int, i) + for idx := range list { + list[idx] = idx + } + + b.Run(fmt.Sprintf("head_%d", i), func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + a := slicesext.Head(list) + require.IsType(b, int(0), a) + } + }) + }) + + b.Run(fmt.Sprintf("[0]_%d", i), func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + a := list[0] + require.IsType(b, int(0), a) + } + }) + }) + } +} + +func BenchmarkTail(b *testing.B) { + for i := 10; i < 1000000; i = i * 10 { + list := make([]int, i) + for idx := range list { + list[idx] = idx + } + + b.Run(fmt.Sprintf("tail_%d", i), func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + a := slicesext.Tail(list) + require.IsType(b, []int{}, a) + } + }) + }) + + b.Run(fmt.Sprintf("[1:]_%d", i), func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + a := list[1:] + require.IsType(b, []int{}, a) + } + }) + }) + } +} + +// Copyright 2021 The Go Authors. All rights reserved. +// TestConcat was ripped from go1.22 source and should be replaced with the stdlib implementation when we move to 1.22 +// Original source: https://github.com/golang/go/blob/5c0d0929d3a6378c710376b55a49abd55b31a805/src/slices/slices_test.go#L1228 +func TestConcat(t *testing.T) { + cases := []struct { + s [][]int + want []int + }{ + { + s: [][]int{nil}, + want: nil, + }, + { + s: [][]int{{1}}, + want: []int{1}, + }, + { + s: [][]int{{1}, {2}}, + want: []int{1, 2}, + }, + { + s: [][]int{{1}, nil, {2}}, + want: []int{1, 2}, + }, + } + for _, tc := range cases { + got := slicesext.Concat(tc.s...) + if !slices.Equal(tc.want, got) { + t.Errorf("Concat(%v) = %v, want %v", tc.s, got, tc.want) + } + var sink []int + allocs := testing.AllocsPerRun(5, func() { + sink = slicesext.Concat(tc.s...) + }) + _ = sink + if allocs > 1 { + errorf := t.Errorf + errorf("Concat(%v) allocated %v times; want 1", tc.s, allocs) + } + } +} + +// Copyright 2021 The Go Authors. All rights reserved. +// TestConcat was ripped from go1.22 source and should be replaced with the stdlib implementation when we move to 1.22 +// Original source: https://github.com/golang/go/blob/5c0d0929d3a6378c710376b55a49abd55b31a805/src/slices/slices_test.go#L1228 +func TestConcat_too_large(t *testing.T) { + // Use zero length element to minimize memory in testing + type void struct{} + cases := []struct { + lengths []int + shouldPanic bool + }{ + { + lengths: []int{0, 0}, + shouldPanic: false, + }, + { + lengths: []int{math.MaxInt, 0}, + shouldPanic: false, + }, + { + lengths: []int{0, math.MaxInt}, + shouldPanic: false, + }, + { + lengths: []int{math.MaxInt - 1, 1}, + shouldPanic: false, + }, + { + lengths: []int{math.MaxInt - 1, 1, 1}, + shouldPanic: true, + }, + { + lengths: []int{math.MaxInt, 1}, + shouldPanic: true, + }, + { + lengths: []int{math.MaxInt, math.MaxInt}, + shouldPanic: true, + }, + } + for _, tc := range cases { + var r any + ss := make([][]void, 0, len(tc.lengths)) + for _, l := range tc.lengths { + s := make([]void, l) + ss = append(ss, s) + } + func() { + defer func() { + r = recover() + }() + _ = slicesext.Concat(ss...) + }() + if didPanic := r != nil; didPanic != tc.shouldPanic { + t.Errorf("slices.Concat(lens(%v)) got panic == %v", + tc.lengths, didPanic) + } + } +} + +func abs(n int) uint { + mask := n >> (strconv.IntSize - 1) + return uint((n ^ mask) - mask) +} + +func duplicate[T any](t T) []T { + return []T{t, t} +} + +func isOdd(n int) bool { + return n%2 == 1 +} + +func isLong(s string) bool { + return len(s) > 5 +} + +func triple(n int) int { + return n * 3 +} diff --git a/packages/go/stbernard/analyzers/golang/golang.go b/packages/go/stbernard/analyzers/golang/golang.go index 7b77ea1d9..24b8aa209 100644 --- a/packages/go/stbernard/analyzers/golang/golang.go +++ b/packages/go/stbernard/analyzers/golang/golang.go @@ -27,7 +27,7 @@ import ( "github.com/specterops/bloodhound/log" "github.com/specterops/bloodhound/packages/go/stbernard/analyzers/codeclimate" - "github.com/specterops/bloodhound/slices" + "github.com/specterops/bloodhound/slicesext" ) var ( @@ -60,7 +60,7 @@ func Run(cwd string, modPaths []string, env []string) ([]codeclimate.Entry, erro outb bytes.Buffer ) - args = append(args, slices.Map(modPaths, func(modPath string) string { + args = append(args, slicesext.Map(modPaths, func(modPath string) string { return path.Join(modPath, "...") })...) diff --git a/packages/go/stbernard/workspace/sync.go b/packages/go/stbernard/workspace/sync.go index e622d2f9e..c9fee15e9 100644 --- a/packages/go/stbernard/workspace/sync.go +++ b/packages/go/stbernard/workspace/sync.go @@ -24,7 +24,7 @@ import ( "os/exec" "path/filepath" - "github.com/specterops/bloodhound/slices" + "github.com/specterops/bloodhound/slicesext" "golang.org/x/mod/modfile" ) @@ -106,7 +106,7 @@ func ParseJsAbsPaths(cwd string) ([]string, error) { } else { var workDir = filepath.Dir(ywPath) - return slices.Map(paths, func(path string) string { return filepath.Join(workDir, path) }), nil + return slicesext.Map(paths, func(path string) string { return filepath.Join(workDir, path) }), nil } }