Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow star-patterns in resource IDs for push/pull #114

Merged
merged 2 commits into from
Oct 19, 2022
Merged
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
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,11 @@ resource in Transifex is
`https://www.transifex.com/myorganization/myproject/myresource`, then the
resource ID will be `myproject.myresource`.

You can also use the `*` character to select multiple resources with the same
pattern. So, for instance, if you have the `abc.def` resource ID in your
configuration, you can select it with either `abc.*`, `*.def`, `ab*ef` or even
`a*.d*f`.

> Note: for backwards compatibility with previous versions of the client, you
> can also use the `-r/--resources` flag. You can also use both at the same
> time:
Expand Down Expand Up @@ -571,6 +576,11 @@ You can limit the resources you want to pull with:
As stated in the `tx push` section, a resource ID must refer to a resource that has
already been configured with `tx add` and has the form `<project>.<resource>`.

You can also use the `*` character to select multiple resources with the same
pattern. So, for instance, if you have the `abc.def` resource ID in your
configuration, you can select it with either `abc.*`, `*.def`, `ab*ef` or even
`a*.d*f`.

> Note: for backwards compatibility with previous versions of the client, you
> can also use the `-r/--resources` flag. You can also use both at the same
> time:
Expand Down
28 changes: 23 additions & 5 deletions internal/txlib/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"errors"
"fmt"
"os"
"regexp"
"strings"
"time"

"github.com/gosimple/slug"
Expand All @@ -29,18 +31,34 @@ func figureOutResources(
var result []*config.Resource

if len(resourceIds) != 0 {
result = make([]*config.Resource, 0, len(resourceIds))
existingResourceIds := make(map[string]*config.Resource)
for i := range cfg.Local.Resources {
resource := &cfg.Local.Resources[i]
resourceId := fmt.Sprintf("%s.%s", resource.ProjectSlug, resource.ResourceSlug)
existingResourceIds[resourceId] = resource
}

for _, resourceId := range resourceIds {
cfgResource := cfg.FindResource(resourceId)
if cfgResource == nil {
pattern, err := regexp.Compile(
"^" + strings.ReplaceAll(regexp.QuoteMeta(resourceId), "\\*", ".*") + "$",
)
if err != nil {
return nil, err
}
atLeastOne := false
for existingResourceId := range existingResourceIds {
if pattern.MatchString(existingResourceId) {
result = append(result, existingResourceIds[existingResourceId])
atLeastOne = true
}
}
if !atLeastOne {
return nil, fmt.Errorf(
"could not find resource '%s' in local configuration or your "+
"resource slug is invalid",
resourceId,
)
}

result = append(result, cfgResource)
}
} else {
for i := range cfg.Local.Resources {
Expand Down
66 changes: 66 additions & 0 deletions internal/txlib/utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package txlib

import (
"reflect"
"sort"
"testing"

"github.com/transifex/cli/internal/txlib/config"
)

func TestFigureOutResources(t *testing.T) {
resources := []config.Resource{
{ProjectSlug: "abc", ResourceSlug: "def"},
{ProjectSlug: "abc", ResourceSlug: "dfg"},
{ProjectSlug: "oab", ResourceSlug: "def"},
}
cfg := config.Config{Local: &config.LocalConfig{Resources: resources}}

test := func(pattern string, expectedStrings [][]string) {
result, err := figureOutResources([]string{pattern}, &cfg)
if err != nil {
t.Error(err)
}
sort.SliceStable(result, func(i, j int) bool {
if result[i].ProjectSlug == result[j].ProjectSlug {
return result[i].ResourceSlug < result[j].ResourceSlug
} else {
return result[i].ProjectSlug < result[j].ProjectSlug
}
})
var expected []*config.Resource
for _, row := range expectedStrings {
expected = append(
expected,
&config.Resource{ProjectSlug: row[0], ResourceSlug: row[1]},
)
}
if !reflect.DeepEqual(result, expected) {
t.Errorf("Got wrong result with pattern %s\n", pattern)
}
}

test("abc.def", [][]string{{"abc", "def"}})
test("a*", [][]string{{"abc", "def"}, {"abc", "dfg"}})
test("ab*", [][]string{{"abc", "def"}, {"abc", "dfg"}})
test("abc*", [][]string{{"abc", "def"}, {"abc", "dfg"}})
test("abc.*", [][]string{{"abc", "def"}, {"abc", "dfg"}})
test("abc.d*", [][]string{{"abc", "def"}, {"abc", "dfg"}})
test("abc.de*", [][]string{{"abc", "def"}})
test("abc*def", [][]string{{"abc", "def"}})
test("ab*def", [][]string{{"abc", "def"}})
test("a*def", [][]string{{"abc", "def"}})
test("*def", [][]string{{"abc", "def"}, {"oab", "def"}})
test("abc*ef", [][]string{{"abc", "def"}})
test("abc*f", [][]string{{"abc", "def"}})
test("*bc.def", [][]string{{"abc", "def"}})
test("*c.def", [][]string{{"abc", "def"}})
test("*.def", [][]string{{"abc", "def"}, {"oab", "def"}})
test("*bc.de*", [][]string{{"abc", "def"}})
test("*bc*de*", [][]string{{"abc", "def"}})

result, err := figureOutResources([]string{"foo*"}, &cfg)
if result != nil || err == nil {
t.Error("Did not get error with unfound pattern")
}
}