Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 19 additions & 25 deletions cmd/docker/aliases_utils.go
Original file line number Diff line number Diff line change
@@ -1,32 +1,26 @@
package main

func stringSliceIndex(s, subs []string) int {
j := 0
if len(subs) > 0 {
for i, x := range s {
if j < len(subs) && subs[j] == x {
j++
} else {
j = 0
}
if len(subs) == j {
return i + 1 - j
}
}
}
return -1
}
import "slices"

// stringSliceReplaceAt replaces the sub-slice find, with the sub-slice replace, in the string
// slice s, returning a new slice and a boolean indicating if the replacement happened.
// requireIdx is the index at which old needs to be found at (or -1 to disregard that).
// stringSliceReplaceAt replaces the sub-slice find with the sub-slice replace in s,
// returning a new slice and a boolean indicating whether the replacement happened.
// requireIndex is the index at which find must be found, or -1 to disregard it.
func stringSliceReplaceAt(s, find, replace []string, requireIndex int) ([]string, bool) {
idx := stringSliceIndex(s, find)
if (requireIndex != -1 && requireIndex != idx) || idx == -1 {
if len(find) == 0 {
return s, false
}
out := append([]string{}, s[:idx]...)
out = append(out, replace...)
out = append(out, s[idx+len(find):]...)
return out, true

if requireIndex >= 0 {
if requireIndex+len(find) > len(s) || !slices.Equal(s[requireIndex:requireIndex+len(find)], find) {
return s, false
}
return slices.Concat(s[:requireIndex], replace, s[requireIndex+len(find):]), true
}

for i := range len(s) - len(find) + 1 {
if slices.Equal(s[i:i+len(find)], find) {
return slices.Concat(s[:i], replace, s[i+len(find):]), true
}
}
return s, false
}
97 changes: 75 additions & 22 deletions cmd/docker/aliases_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,80 @@ import (
)

func TestStringSliceReplaceAt(t *testing.T) {
out, ok := stringSliceReplaceAt([]string{"abc", "foo", "bar", "bax"}, []string{"foo", "bar"}, []string{"baz"}, -1)
assert.Assert(t, ok)
assert.DeepEqual(t, []string{"abc", "baz", "bax"}, out)
tests := []struct {
name string
s []string
find []string
replace []string
requireIndex int
expected []string
ok bool
}{
{
name: "replace",
s: []string{"abc", "foo", "bar", "bax"},
find: []string{"foo", "bar"},
replace: []string{"baz"},
requireIndex: -1,
expected: []string{"abc", "baz", "bax"},
ok: true,
},
{
name: "find longer than input",
s: []string{"foo"},
find: []string{"foo", "bar"},
replace: []string{"baz"},
requireIndex: -1,
expected: []string{"foo"},
},
{
name: "wrong required index",
s: []string{"abc", "foo", "bar", "bax"},
find: []string{"foo", "bar"},
replace: []string{"baz"},
requireIndex: 0,
expected: []string{"abc", "foo", "bar", "bax"},
},
{
name: "required index",
s: []string{"foo", "bar", "bax"},
find: []string{"foo", "bar"},
replace: []string{"baz"},
requireIndex: 0,
expected: []string{"baz", "bax"},
ok: true,
},
{
name: "remove",
s: []string{"abc", "foo", "bar", "baz"},
find: []string{"foo", "bar"},
requireIndex: -1,
expected: []string{"abc", "baz"},
ok: true,
},
{
name: "empty find",
s: []string{"foo"},
replace: []string{"baz"},
requireIndex: -1,
expected: []string{"foo"},
},
{
name: "overlapping match",
s: []string{"a", "a", "b"},
find: []string{"a", "b"},
replace: []string{"c"},
requireIndex: -1,
expected: []string{"a", "c"},
ok: true,
},
}

out, ok = stringSliceReplaceAt([]string{"foo"}, []string{"foo", "bar"}, []string{"baz"}, -1)
assert.Assert(t, !ok)
assert.DeepEqual(t, []string{"foo"}, out)

out, ok = stringSliceReplaceAt([]string{"abc", "foo", "bar", "bax"}, []string{"foo", "bar"}, []string{"baz"}, 0)
assert.Assert(t, !ok)
assert.DeepEqual(t, []string{"abc", "foo", "bar", "bax"}, out)

out, ok = stringSliceReplaceAt([]string{"foo", "bar", "bax"}, []string{"foo", "bar"}, []string{"baz"}, 0)
assert.Assert(t, ok)
assert.DeepEqual(t, []string{"baz", "bax"}, out)

out, ok = stringSliceReplaceAt([]string{"abc", "foo", "bar", "baz"}, []string{"foo", "bar"}, nil, -1)
assert.Assert(t, ok)
assert.DeepEqual(t, []string{"abc", "baz"}, out)

out, ok = stringSliceReplaceAt([]string{"foo"}, nil, []string{"baz"}, -1)
assert.Assert(t, !ok)
assert.DeepEqual(t, []string{"foo"}, out)
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
out, ok := stringSliceReplaceAt(tc.s, tc.find, tc.replace, tc.requireIndex)
assert.Equal(t, tc.ok, ok)
assert.DeepEqual(t, tc.expected, out)
})
}
}