From 532d7fae2af441a30d2ced6744bceee6df50fe22 Mon Sep 17 00:00:00 2001 From: Ahmet Alp Balkan Date: Mon, 30 Mar 2020 14:30:42 -0700 Subject: [PATCH] various naming utilities for canonicalization and display (#570) * various naming utilities for canonicalization and display Refactoring some of the utilities from the patch that ported 'krew list' to multi-indexes. These utilities will help us implement 'krew search'. Signed-off-by: Ahmet Alp Balkan * rename file Signed-off-by: Ahmet Alp Balkan --- cmd/krew/cmd/list.go | 17 +---- cmd/krew/cmd/list_test.go | 61 ----------------- cmd/krew/cmd/namingutils.go | 50 ++++++++++++++ cmd/krew/cmd/namingutils_test.go | 114 +++++++++++++++++++++++++++++++ 4 files changed, 166 insertions(+), 76 deletions(-) delete mode 100644 cmd/krew/cmd/list_test.go create mode 100644 cmd/krew/cmd/namingutils.go create mode 100644 cmd/krew/cmd/namingutils_test.go diff --git a/cmd/krew/cmd/list.go b/cmd/krew/cmd/list.go index b3ecbdb7..5b538830 100644 --- a/cmd/krew/cmd/list.go +++ b/cmd/krew/cmd/list.go @@ -26,8 +26,6 @@ import ( "github.com/spf13/cobra" "sigs.k8s.io/krew/internal/installation" - "sigs.k8s.io/krew/pkg/constants" - "sigs.k8s.io/krew/pkg/index" ) func init() { @@ -51,7 +49,7 @@ Remarks: if !isTerminal(os.Stdout) { var names []string for _, r := range receipts { - names = append(names, displayName(r)) + names = append(names, displayName(r.Plugin, indexOf(r))) } sort.Strings(names) fmt.Fprintln(os.Stdout, strings.Join(names, "\n")) @@ -61,7 +59,7 @@ Remarks: // print table var rows [][]string for _, r := range receipts { - rows = append(rows, []string{displayName(r), r.Spec.Version}) + rows = append(rows, []string{displayName(r.Plugin, indexOf(r)), r.Spec.Version}) } rows = sortByFirstColumn(rows) return printTable(os.Stdout, []string{"PLUGIN", "VERSION"}, rows) @@ -89,14 +87,3 @@ func sortByFirstColumn(rows [][]string) [][]string { }) return rows } - -// displayName returns the index and plugin name from a receipt. -// The index name is omitted if it is the default index. -func displayName(receipt index.Receipt) string { - name := receipt.Name - indexName := receipt.Status.Source.Name - if indexName != "" && indexName != constants.DefaultIndexName { - name = receipt.Status.Source.Name + "/" + receipt.Name - } - return name -} diff --git a/cmd/krew/cmd/list_test.go b/cmd/krew/cmd/list_test.go deleted file mode 100644 index 1552a94d..00000000 --- a/cmd/krew/cmd/list_test.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2019 The Kubernetes Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// 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. - -package cmd - -import ( - "testing" - - "github.com/google/go-cmp/cmp" - - "sigs.k8s.io/krew/internal/testutil" - "sigs.k8s.io/krew/pkg/index" -) - -func Test_displayName(t *testing.T) { - tests := []struct { - name string - receipt index.Receipt - expected string - }{ - { - name: "explicit default index", - receipt: testutil.NewReceipt().WithPlugin(testutil.NewPlugin().WithName("foo").V()).V(), - expected: "foo", - }, - { - name: "no index", - receipt: testutil.NewReceipt().WithPlugin(testutil.NewPlugin().WithName("foo").V()).WithStatus(index.ReceiptStatus{}).V(), - expected: "foo", - }, - { - name: "custom index", - receipt: testutil.NewReceipt().WithPlugin(testutil.NewPlugin().WithName("bar").V()).WithStatus(index.ReceiptStatus{ - Source: index.SourceIndex{ - Name: "foo", - }, - }).V(), - expected: "foo/bar", - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - actual := displayName(test.receipt) - if diff := cmp.Diff(test.expected, actual); diff != "" { - t.Fatalf("expected name to match: %s", diff) - } - }) - } -} diff --git a/cmd/krew/cmd/namingutils.go b/cmd/krew/cmd/namingutils.go new file mode 100644 index 00000000..f73a9804 --- /dev/null +++ b/cmd/krew/cmd/namingutils.go @@ -0,0 +1,50 @@ +// Copyright 2019 The Kubernetes Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// 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. + +package cmd + +import ( + "sigs.k8s.io/krew/pkg/constants" + "sigs.k8s.io/krew/pkg/index" +) + +// indexOf returns the index name of a receipt. +func indexOf(r index.Receipt) string { + if r.Status.Source.Name == "" { + return constants.DefaultIndexName + } + return r.Status.Source.Name +} + +// displayName returns the display name of a Plugin. +// The index name is omitted if it is the default index. +func displayName(p index.Plugin, indexName string) string { + if isDefaultIndex(indexName) { + return p.Name + } + return indexName + "/" + p.Name +} + +func isDefaultIndex(name string) bool { + return name == "" || name == constants.DefaultIndexName +} + +// canonicalName returns INDEX/NAME value for a plugin, even if +// it is in the default index. +func canonicalName(p index.Plugin, indexName string) string { + if isDefaultIndex(indexName) { + indexName = constants.DefaultIndexName + } + return indexName + "/" + p.Name +} diff --git a/cmd/krew/cmd/namingutils_test.go b/cmd/krew/cmd/namingutils_test.go new file mode 100644 index 00000000..f8a508f4 --- /dev/null +++ b/cmd/krew/cmd/namingutils_test.go @@ -0,0 +1,114 @@ +// Copyright 2019 The Kubernetes Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// 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. + +package cmd + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + + "sigs.k8s.io/krew/internal/testutil" + "sigs.k8s.io/krew/pkg/constants" + "sigs.k8s.io/krew/pkg/index" +) + +func Test_isDefaultIndex(t *testing.T) { + if !isDefaultIndex("") { + t.Error("empty string must indicate default index") + } + if !isDefaultIndex("default") { // nb: intentionally not using the const to ensure compatibility + t.Error("default index must indicate default index") + } + if isDefaultIndex("foo") { + t.Error("name=foo must not indicate default index") + } +} + +func TestIndexOf(t *testing.T) { + noIndex := testutil.NewReceipt().WithPlugin(testutil.NewPlugin().V()).WithStatus(index.ReceiptStatus{}).V() + if got := indexOf(noIndex); got != constants.DefaultIndexName { + t.Errorf("expected default index for no index in status; got=%q", got) + } + defaultIndex := testutil.NewReceipt().WithPlugin(testutil.NewPlugin().V()).V() + if got := indexOf(defaultIndex); got != constants.DefaultIndexName { + t.Errorf("expected 'default' for default index; got=%q", got) + } + customIndex := testutil.NewReceipt().WithPlugin(testutil.NewPlugin().V()).WithStatus( + index.ReceiptStatus{Source: index.SourceIndex{Name: "foo"}}).V() + if got := indexOf(customIndex); got != "foo" { + t.Errorf("expected custom index name; got=%q", got) + } +} + +func Test_displayName(t *testing.T) { + type args struct { + p index.Plugin + index string + } + tests := []struct { + name string + in args + expected string + }{ + { + name: "explicit default index", + in: args{ + p: testutil.NewPlugin().WithName("foo").V(), + index: constants.DefaultIndexName, + }, + expected: "foo", + }, + { + name: "no index", + in: args{ + p: testutil.NewPlugin().WithName("foo").V(), + index: "", + }, + expected: "foo", + }, + { + name: "custom index", + in: args{ + p: testutil.NewPlugin().WithName("bar").V(), + index: "foo", + }, + expected: "foo/bar", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := displayName(tt.in.p, tt.in.index) + if diff := cmp.Diff(tt.expected, actual); diff != "" { + t.Fatalf("expected name to match: %s", diff) + } + }) + } +} + +func Test_canonicalName(t *testing.T) { + p1 := testutil.NewPlugin().WithName("foo").V() + if expected, got := "default/foo", canonicalName(p1, ""); got != expected { + t.Errorf("expected=%q; got=%q", expected, got) + } + p2 := testutil.NewPlugin().WithName("bar").V() + if expected, got := "default/bar", canonicalName(p2, "default"); got != expected { + t.Errorf("expected=%q; got=%q", expected, got) + } + p3 := testutil.NewPlugin().WithName("quux").V() + if expected, got := "custom/quux", canonicalName(p3, "custom"); got != expected { + t.Errorf("expected=%q; got=%q", expected, got) + } +}