From 8ff1f281332754d5b438b05cbb011bf67bd78296 Mon Sep 17 00:00:00 2001 From: tuckerrrrrrrrrrrr Date: Wed, 26 Feb 2020 10:17:17 -0800 Subject: [PATCH 1/4] Show similar library names in lib search --- cli/lib/search.go | 17 ++++++++++++---- commands/lib/search.go | 19 ++++++++++++++--- go.mod | 1 + go.sum | 2 ++ rpc/commands/lib.pb.go | 46 ++++++++++++++++++++++++++++++++++++------ rpc/commands/lib.proto | 6 ++++++ 6 files changed, 78 insertions(+), 13 deletions(-) diff --git a/cli/lib/search.go b/cli/lib/search.go index 57258e9c363..c57fb8d0ba0 100644 --- a/cli/lib/search.go +++ b/cli/lib/search.go @@ -88,8 +88,8 @@ func (res result) Data() interface{} { names := []LibName{} results := res.results.GetLibraries() - for _, lsr := range results { - names = append(names, LibName{lsr.Name}) + for _, lib := range results { + names = append(names, LibName{lib.Name}) } return NamesOnly{ @@ -113,9 +113,18 @@ func (res result) String() string { var out strings.Builder + if res.results.GetStatus() == rpc.LibrarySearchStatus_failed { + out.WriteString("No libraries matching your search.\nDid you mean...\n") + } + for _, lib := range results { - out.WriteString(fmt.Sprintf("Name: \"%s\"\n", lib.Name)) - if res.namesOnly { + if res.results.GetStatus() == rpc.LibrarySearchStatus_success { + out.WriteString(fmt.Sprintf("Name: \"%s\"\n", lib.Name)) + if res.namesOnly { + continue + } + } else { + out.WriteString(fmt.Sprintf("%s\n", lib.Name)) continue } diff --git a/commands/lib/search.go b/commands/lib/search.go index e8f92339f1b..ab0605a8d47 100644 --- a/commands/lib/search.go +++ b/commands/lib/search.go @@ -23,6 +23,7 @@ import ( "github.com/arduino/arduino-cli/arduino/libraries/librariesindex" "github.com/arduino/arduino-cli/commands" rpc "github.com/arduino/arduino-cli/rpc/commands" + "github.com/imjasonmiller/godice" semver "go.bug.st/relaxed-semver" ) @@ -34,6 +35,7 @@ func LibrarySearch(ctx context.Context, req *rpc.LibrarySearchReq) (*rpc.Library } res := []*rpc.SearchedLibrary{} + status := rpc.LibrarySearchStatus_success for _, lib := range lm.Index.Libraries { qry := strings.ToLower(req.GetQuery()) @@ -46,16 +48,27 @@ func LibrarySearch(ctx context.Context, req *rpc.LibrarySearchReq) (*rpc.Library } latest := GetLibraryParameters(lib.Latest) - searchedlib := &rpc.SearchedLibrary{ + searchedLib := &rpc.SearchedLibrary{ Name: lib.Name, Releases: releases, Latest: latest, } - res = append(res, searchedlib) + res = append(res, searchedLib) } } - return &rpc.LibrarySearchResp{Libraries: res}, nil + if len(res) == 0 { + status = rpc.LibrarySearchStatus_failed + for _, lib := range lm.Index.Libraries { + if godice.CompareString(req.GetQuery(), lib.Name) > 0.7 { + res = append(res, &rpc.SearchedLibrary{ + Name: lib.Name, + }) + } + } + } + + return &rpc.LibrarySearchResp{Libraries: res, Status: status}, nil } // GetLibraryParameters FIXMEDOC diff --git a/go.mod b/go.mod index 36b6983841d..b03a4bec9ab 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/gofrs/uuid v3.2.0+incompatible github.com/golang/protobuf v1.3.3 github.com/h2non/filetype v1.0.8 // indirect + github.com/imjasonmiller/godice v0.1.2 github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5 // indirect github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect github.com/juju/testing v0.0.0-20190429233213-dfc56b8c09fc // indirect diff --git a/go.sum b/go.sum index a4b55be2b0b..84b52be5bca 100644 --- a/go.sum +++ b/go.sum @@ -85,6 +85,8 @@ github.com/h2non/filetype v1.0.8 h1:le8gpf+FQA0/DlDABbtisA1KiTS0Xi+YSC/E8yY3Y14= github.com/h2non/filetype v1.0.8/go.mod h1:isekKqOuhMj+s/7r3rIeTErIRy4Rub5uBWHfvMusLMU= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/imjasonmiller/godice v0.1.2 h1:T1/sW/HoDzFeuwzOOuQjmeMELz9CzZ53I2CnD+08zD4= +github.com/imjasonmiller/godice v0.1.2/go.mod h1:8cTkdnVI+NglU2d6sv+ilYcNaJ5VSTBwvMbFULJd/QQ= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= diff --git a/rpc/commands/lib.pb.go b/rpc/commands/lib.pb.go index cefe6232ee5..3906f264c8a 100644 --- a/rpc/commands/lib.pb.go +++ b/rpc/commands/lib.pb.go @@ -20,6 +20,31 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +type LibrarySearchStatus int32 + +const ( + LibrarySearchStatus_failed LibrarySearchStatus = 0 + LibrarySearchStatus_success LibrarySearchStatus = 1 +) + +var LibrarySearchStatus_name = map[int32]string{ + 0: "failed", + 1: "success", +} + +var LibrarySearchStatus_value = map[string]int32{ + "failed": 0, + "success": 1, +} + +func (x LibrarySearchStatus) String() string { + return proto.EnumName(LibrarySearchStatus_name, int32(x)) +} + +func (LibrarySearchStatus) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_9feed0d29806df6c, []int{0} +} + type LibraryLayout int32 const ( @@ -42,7 +67,7 @@ func (x LibraryLayout) String() string { } func (LibraryLayout) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_9feed0d29806df6c, []int{0} + return fileDescriptor_9feed0d29806df6c, []int{1} } type LibraryLocation int32 @@ -73,7 +98,7 @@ func (x LibraryLocation) String() string { } func (LibraryLocation) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_9feed0d29806df6c, []int{1} + return fileDescriptor_9feed0d29806df6c, []int{2} } type LibraryDownloadReq struct { @@ -649,10 +674,11 @@ func (m *LibrarySearchReq) GetQuery() string { } type LibrarySearchResp struct { - Libraries []*SearchedLibrary `protobuf:"bytes,1,rep,name=libraries,proto3" json:"libraries,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Libraries []*SearchedLibrary `protobuf:"bytes,1,rep,name=libraries,proto3" json:"libraries,omitempty"` + Status LibrarySearchStatus `protobuf:"varint,2,opt,name=status,proto3,enum=cc.arduino.cli.commands.LibrarySearchStatus" json:"status,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *LibrarySearchResp) Reset() { *m = LibrarySearchResp{} } @@ -687,6 +713,13 @@ func (m *LibrarySearchResp) GetLibraries() []*SearchedLibrary { return nil } +func (m *LibrarySearchResp) GetStatus() LibrarySearchStatus { + if m != nil { + return m.Status + } + return LibrarySearchStatus_failed +} + type SearchedLibrary struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Releases map[string]*LibraryRelease `protobuf:"bytes,2,rep,name=releases,proto3" json:"releases,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` @@ -1352,6 +1385,7 @@ func (m *Library) GetLayout() LibraryLayout { } func init() { + proto.RegisterEnum("cc.arduino.cli.commands.LibrarySearchStatus", LibrarySearchStatus_name, LibrarySearchStatus_value) proto.RegisterEnum("cc.arduino.cli.commands.LibraryLayout", LibraryLayout_name, LibraryLayout_value) proto.RegisterEnum("cc.arduino.cli.commands.LibraryLocation", LibraryLocation_name, LibraryLocation_value) proto.RegisterType((*LibraryDownloadReq)(nil), "cc.arduino.cli.commands.LibraryDownloadReq") diff --git a/rpc/commands/lib.proto b/rpc/commands/lib.proto index a1ddb861f83..e5d7d9534ce 100644 --- a/rpc/commands/lib.proto +++ b/rpc/commands/lib.proto @@ -82,8 +82,14 @@ message LibrarySearchReq { string query = 2; } +enum LibrarySearchStatus { + failed = 0; + success = 1; +} + message LibrarySearchResp { repeated SearchedLibrary libraries = 1; + LibrarySearchStatus status = 2; } message SearchedLibrary { From 99e1cfe876aada7d51087dd4c12e3836b299db75 Mon Sep 17 00:00:00 2001 From: tuckerrrrrrrrrrrr Date: Wed, 1 Apr 2020 10:52:53 -0700 Subject: [PATCH 2/4] make similarity threshold for lib search a package variable --- commands/lib/search.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/commands/lib/search.go b/commands/lib/search.go index ab0605a8d47..4321ecd9428 100644 --- a/commands/lib/search.go +++ b/commands/lib/search.go @@ -27,6 +27,8 @@ import ( semver "go.bug.st/relaxed-semver" ) +var similarityThreshold = 0.7 + // LibrarySearch FIXMEDOC func LibrarySearch(ctx context.Context, req *rpc.LibrarySearchReq) (*rpc.LibrarySearchResp, error) { lm := commands.GetLibraryManager(req.GetInstance().GetId()) @@ -60,7 +62,7 @@ func LibrarySearch(ctx context.Context, req *rpc.LibrarySearchReq) (*rpc.Library if len(res) == 0 { status = rpc.LibrarySearchStatus_failed for _, lib := range lm.Index.Libraries { - if godice.CompareString(req.GetQuery(), lib.Name) > 0.7 { + if godice.CompareString(req.GetQuery(), lib.Name) > similarityThreshold { res = append(res, &rpc.SearchedLibrary{ Name: lib.Name, }) From 54cd87faf8861e47fd8ac732f31f09467526a5eb Mon Sep 17 00:00:00 2001 From: tuckerrrrrrrrrrrr Date: Wed, 1 Apr 2020 11:57:58 -0700 Subject: [PATCH 3/4] Add library search tests --- commands/lib/search.go | 5 +++ commands/lib/search_test.go | 53 ++++++++++++++++++++++++ commands/lib/testdata/library_index.json | 13 ++++++ 3 files changed, 71 insertions(+) create mode 100644 commands/lib/search_test.go create mode 100644 commands/lib/testdata/library_index.json diff --git a/commands/lib/search.go b/commands/lib/search.go index 4321ecd9428..d46ddef4b59 100644 --- a/commands/lib/search.go +++ b/commands/lib/search.go @@ -21,6 +21,7 @@ import ( "strings" "github.com/arduino/arduino-cli/arduino/libraries/librariesindex" + "github.com/arduino/arduino-cli/arduino/libraries/librariesmanager" "github.com/arduino/arduino-cli/commands" rpc "github.com/arduino/arduino-cli/rpc/commands" "github.com/imjasonmiller/godice" @@ -36,6 +37,10 @@ func LibrarySearch(ctx context.Context, req *rpc.LibrarySearchReq) (*rpc.Library return nil, errors.New("invalid instance") } + return searchLibrary(req, lm) +} + +func searchLibrary(req *rpc.LibrarySearchReq, lm *librariesmanager.LibrariesManager) (*rpc.LibrarySearchResp, error) { res := []*rpc.SearchedLibrary{} status := rpc.LibrarySearchStatus_success diff --git a/commands/lib/search_test.go b/commands/lib/search_test.go new file mode 100644 index 00000000000..77a7e02216a --- /dev/null +++ b/commands/lib/search_test.go @@ -0,0 +1,53 @@ +package lib + +import ( + "testing" + + "github.com/arduino/arduino-cli/arduino/libraries/librariesmanager" + rpc "github.com/arduino/arduino-cli/rpc/commands" + paths "github.com/arduino/go-paths-helper" + "github.com/stretchr/testify/assert" +) + +var customIndexPath = paths.New("testdata") + +func TestSearchLibrary(t *testing.T) { + lm := librariesmanager.NewLibraryManager(customIndexPath, nil) + lm.LoadIndex() + + req := &rpc.LibrarySearchReq{ + Instance: &rpc.Instance{Id: 1}, + Query: "test", + } + + resp, err := searchLibrary(req, lm) + if err != nil { + t.Fatal(err) + } + + assert := assert.New(t) + assert.Equal(resp.GetStatus(), rpc.LibrarySearchStatus_success) + assert.Equal(len(resp.GetLibraries()), 2) + assert.Equal(resp.GetLibraries()[0].Name, "ArduinoTestPackage") + assert.Equal(resp.GetLibraries()[1].Name, "Test") +} + +func TestSearchLibrarySimilar(t *testing.T) { + lm := librariesmanager.NewLibraryManager(customIndexPath, nil) + lm.LoadIndex() + + req := &rpc.LibrarySearchReq{ + Instance: &rpc.Instance{Id: 1}, + Query: "ardino", + } + + resp, err := searchLibrary(req, lm) + if err != nil { + t.Fatal(err) + } + + assert := assert.New(t) + assert.Equal(resp.GetStatus(), rpc.LibrarySearchStatus_failed) + assert.Equal(len(resp.GetLibraries()), 1) + assert.Equal(resp.GetLibraries()[0].Name, "Arduino") +} diff --git a/commands/lib/testdata/library_index.json b/commands/lib/testdata/library_index.json new file mode 100644 index 00000000000..21d658d25c3 --- /dev/null +++ b/commands/lib/testdata/library_index.json @@ -0,0 +1,13 @@ +{ + "libraries": [ + { + "name": "ArduinoTestPackage" + }, + { + "name": "Arduino" + }, + { + "name": "Test" + } + ] +} From 86532e8e7f868c3226fe06fea61a178b3d15e398 Mon Sep 17 00:00:00 2001 From: tuckerrrrrrrrrrrr Date: Wed, 1 Apr 2020 12:06:21 -0700 Subject: [PATCH 4/4] Redo name asserts in TestSearchLibrary Just check that the library names have "Test" in them instead of checking the names at each index, which won't always be the same --- commands/lib/search_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/commands/lib/search_test.go b/commands/lib/search_test.go index 77a7e02216a..65ca2ca801f 100644 --- a/commands/lib/search_test.go +++ b/commands/lib/search_test.go @@ -1,6 +1,7 @@ package lib import ( + "strings" "testing" "github.com/arduino/arduino-cli/arduino/libraries/librariesmanager" @@ -28,8 +29,8 @@ func TestSearchLibrary(t *testing.T) { assert := assert.New(t) assert.Equal(resp.GetStatus(), rpc.LibrarySearchStatus_success) assert.Equal(len(resp.GetLibraries()), 2) - assert.Equal(resp.GetLibraries()[0].Name, "ArduinoTestPackage") - assert.Equal(resp.GetLibraries()[1].Name, "Test") + assert.True(strings.Contains(resp.GetLibraries()[0].Name, "Test")) + assert.True(strings.Contains(resp.GetLibraries()[1].Name, "Test")) } func TestSearchLibrarySimilar(t *testing.T) {