From 743c3e9b3c94eded62b44081a03650d571fa230c Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Thu, 24 Sep 2020 17:47:14 +0200 Subject: [PATCH] lib list command now only shows compatible libraries when specifying fqbn --- arduino/libraries/libraries.go | 1 + cli/lib/list.go | 12 +++- commands/lib/list.go | 91 ++++++++++++++------------ rpc/commands/lib.pb.go | 115 +++++++++++++++++++-------------- rpc/commands/lib.proto | 4 +- test/test_lib.py | 70 ++++++++++++++++++++ 6 files changed, 203 insertions(+), 90 deletions(-) diff --git a/arduino/libraries/libraries.go b/arduino/libraries/libraries.go index da154d23e2d..7bf6f3e0f3d 100644 --- a/arduino/libraries/libraries.go +++ b/arduino/libraries/libraries.go @@ -75,6 +75,7 @@ type Library struct { Examples paths.PathList declaredHeaders []string sourceHeaders []string + CompatibleWith map[string]bool } func (library *Library) String() string { diff --git a/cli/lib/list.go b/cli/lib/list.go index d0d33246a3c..3b88cc8bff2 100644 --- a/cli/lib/list.go +++ b/cli/lib/list.go @@ -76,7 +76,16 @@ func runListCommand(cmd *cobra.Command, args []string) { os.Exit(errorcodes.ErrGeneric) } - libs := res.GetInstalledLibrary() + libs := []*rpc.InstalledLibrary{} + if listFlags.fqbn == "" { + libs = res.GetInstalledLibrary() + } else { + for _, lib := range res.GetInstalledLibrary() { + if lib.Library.CompatibleWith[listFlags.fqbn] { + libs = append(libs, lib) + } + } + } // To uniform the output to other commands, when there are no result // print out an empty slice. @@ -139,7 +148,6 @@ func (ir installedResult) String() string { } else if len(sentence) > 40 { sentence = sentence[:37] + "..." } - t.AddRow(name, lib.Version, available, location, sentence) } } diff --git a/commands/lib/list.go b/commands/lib/list.go index e34ea5e07c4..07a21de3889 100644 --- a/commands/lib/list.go +++ b/commands/lib/list.go @@ -50,57 +50,67 @@ func LibraryList(ctx context.Context, req *rpc.LibraryListReq) (*rpc.LibraryList instaledLib := []*rpc.InstalledLibrary{} res := listLibraries(lm, req.GetUpdatable(), req.GetAll()) - if len(res) > 0 { - if f := req.GetFqbn(); f != "" { - fqbn, err := cores.ParseFQBN(req.GetFqbn()) - if err != nil { - return nil, fmt.Errorf("parsing fqbn: %s", err) - } - _, boardPlatform, _, _, refBoardPlatform, err := pm.ResolveFQBN(fqbn) - if err != nil { - return nil, fmt.Errorf("loading board data: %s", err) - } + if f := req.GetFqbn(); f != "" { + fqbn, err := cores.ParseFQBN(req.GetFqbn()) + if err != nil { + return nil, fmt.Errorf("parsing fqbn: %s", err) + } + _, boardPlatform, _, _, refBoardPlatform, err := pm.ResolveFQBN(fqbn) + if err != nil { + return nil, fmt.Errorf("loading board data: %s", err) + } - filteredRes := map[string]*installedLib{} - for _, lib := range res { - if cp := lib.Library.ContainerPlatform; cp != nil { - if cp != boardPlatform && cp != refBoardPlatform { - // Filter all libraries from extraneous platforms - continue - } + filteredRes := map[string]*installedLib{} + for _, lib := range res { + if cp := lib.Library.ContainerPlatform; cp != nil { + if cp != boardPlatform && cp != refBoardPlatform { + // Filter all libraries from extraneous platforms + continue } - if latest, has := filteredRes[lib.Library.Name]; has { - if latest.Library.LocationPriorityFor(boardPlatform, refBoardPlatform) >= lib.Library.LocationPriorityFor(boardPlatform, refBoardPlatform) { - continue - } + } + if latest, has := filteredRes[lib.Library.Name]; has { + if latest.Library.LocationPriorityFor(boardPlatform, refBoardPlatform) >= lib.Library.LocationPriorityFor(boardPlatform, refBoardPlatform) { + continue } - filteredRes[lib.Library.Name] = lib } - res = []*installedLib{} - for _, lib := range filteredRes { - res = append(res, lib) + // Check if library is compatible with board specified by FBQN + compatible := false + for _, arch := range lib.Library.Architectures { + compatible = (arch == fqbn.PlatformArch || arch == "*") + if compatible { + break + } + } + lib.Library.CompatibleWith = map[string]bool{ + f: compatible, } + + filteredRes[lib.Library.Name] = lib } - for _, lib := range res { - if nameFilter != "" && strings.ToLower(lib.Library.Name) != nameFilter { - continue - } - libtmp, err := GetOutputLibrary(lib.Library) - if err != nil { - return nil, err - } - release := GetOutputRelease(lib.Available) - instaledLib = append(instaledLib, &rpc.InstalledLibrary{ - Library: libtmp, - Release: release, - }) + res = []*installedLib{} + for _, lib := range filteredRes { + res = append(res, lib) } + } - return &rpc.LibraryListResp{InstalledLibrary: instaledLib}, nil + for _, lib := range res { + if nameFilter != "" && strings.ToLower(lib.Library.Name) != nameFilter { + continue + } + libtmp, err := GetOutputLibrary(lib.Library) + if err != nil { + return nil, err + } + release := GetOutputRelease(lib.Available) + instaledLib = append(instaledLib, &rpc.InstalledLibrary{ + Library: libtmp, + Release: release, + }) } - return &rpc.LibraryListResp{}, nil + + return &rpc.LibraryListResp{InstalledLibrary: instaledLib}, nil } // listLibraries returns the list of installed libraries. If updatable is true it @@ -171,6 +181,7 @@ func GetOutputLibrary(lib *libraries.Library) (*rpc.Library, error) { License: lib.License, Examples: lib.Examples.AsStrings(), ProvidesIncludes: lib.DeclaredHeaders(), + CompatibleWith: lib.CompatibleWith, }, nil } diff --git a/rpc/commands/lib.pb.go b/rpc/commands/lib.pb.go index 913963df787..4135cef80a5 100644 --- a/rpc/commands/lib.pb.go +++ b/rpc/commands/lib.pb.go @@ -1567,6 +1567,8 @@ type Library struct { // Value of the `includes` field in library.properties or, if missing, the list of // include files available on the library source root directory. ProvidesIncludes []string `protobuf:"bytes,27,rep,name=provides_includes,json=providesIncludes,proto3" json:"provides_includes,omitempty"` + // Map of FQBNs that specifies if library is compatible with this library + CompatibleWith map[string]bool `protobuf:"bytes,28,rep,name=compatible_with,json=compatibleWith,proto3" json:"compatible_with,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` } func (x *Library) Reset() { @@ -1776,6 +1778,13 @@ func (x *Library) GetProvidesIncludes() []string { return nil } +func (x *Library) GetCompatibleWith() map[string]bool { + if x != nil { + return x.CompatibleWith + } + return nil +} + var File_commands_lib_proto protoreflect.FileDescriptor var file_commands_lib_proto_rawDesc = []byte{ @@ -1979,8 +1988,8 @@ var file_commands_lib_proto_rawDesc = []byte{ 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0xc0, - 0x07, 0x0a, 0x07, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0xe2, + 0x08, 0x0a, 0x07, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, @@ -2036,27 +2045,37 @@ var file_commands_lib_proto_rawDesc = []byte{ 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x18, 0x1b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, - 0x65, 0x73, 0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x2a, 0x2e, 0x0a, 0x13, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0a, 0x0a, 0x06, 0x66, 0x61, 0x69, 0x6c, - 0x65, 0x64, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x10, - 0x01, 0x2a, 0x36, 0x0a, 0x0d, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x61, 0x79, 0x6f, - 0x75, 0x74, 0x12, 0x0f, 0x0a, 0x0b, 0x66, 0x6c, 0x61, 0x74, 0x5f, 0x6c, 0x61, 0x79, 0x6f, 0x75, - 0x74, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, - 0x5f, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x10, 0x01, 0x2a, 0x63, 0x0a, 0x0f, 0x4c, 0x69, 0x62, - 0x72, 0x61, 0x72, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0f, 0x0a, 0x0b, - 0x69, 0x64, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x10, 0x00, 0x12, 0x08, 0x0a, - 0x04, 0x75, 0x73, 0x65, 0x72, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x70, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x10, 0x02, 0x12, 0x1f, 0x0a, - 0x1b, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x64, 0x5f, 0x70, 0x6c, 0x61, 0x74, - 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x10, 0x03, 0x42, 0x2d, - 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, - 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, - 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x12, 0x5d, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, + 0x5f, 0x77, 0x69, 0x74, 0x68, 0x18, 0x1c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x63, 0x63, + 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x43, 0x6f, + 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x57, 0x69, 0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x57, 0x69, 0x74, + 0x68, 0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x1a, 0x41, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x57, 0x69, + 0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x2a, 0x2e, 0x0a, 0x13, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0a, 0x0a, 0x06, 0x66, 0x61, + 0x69, 0x6c, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x10, 0x01, 0x2a, 0x36, 0x0a, 0x0d, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x61, + 0x79, 0x6f, 0x75, 0x74, 0x12, 0x0f, 0x0a, 0x0b, 0x66, 0x6c, 0x61, 0x74, 0x5f, 0x6c, 0x61, 0x79, + 0x6f, 0x75, 0x74, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, + 0x76, 0x65, 0x5f, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x10, 0x01, 0x2a, 0x63, 0x0a, 0x0f, 0x4c, + 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0f, + 0x0a, 0x0b, 0x69, 0x64, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x10, 0x00, 0x12, + 0x08, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x10, 0x02, 0x12, + 0x1f, 0x0a, 0x1b, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x64, 0x5f, 0x70, 0x6c, + 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x10, 0x03, + 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, + 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, + 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2072,7 +2091,7 @@ func file_commands_lib_proto_rawDescGZIP() []byte { } var file_commands_lib_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_commands_lib_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_commands_lib_proto_msgTypes = make([]protoimpl.MessageInfo, 24) var file_commands_lib_proto_goTypes = []interface{}{ (LibrarySearchStatus)(0), // 0: cc.arduino.cli.commands.LibrarySearchStatus (LibraryLayout)(0), // 1: cc.arduino.cli.commands.LibraryLayout @@ -2100,43 +2119,45 @@ var file_commands_lib_proto_goTypes = []interface{}{ (*Library)(nil), // 23: cc.arduino.cli.commands.Library nil, // 24: cc.arduino.cli.commands.SearchedLibrary.ReleasesEntry nil, // 25: cc.arduino.cli.commands.Library.PropertiesEntry - (*Instance)(nil), // 26: cc.arduino.cli.commands.Instance - (*DownloadProgress)(nil), // 27: cc.arduino.cli.commands.DownloadProgress - (*TaskProgress)(nil), // 28: cc.arduino.cli.commands.TaskProgress + nil, // 26: cc.arduino.cli.commands.Library.CompatibleWithEntry + (*Instance)(nil), // 27: cc.arduino.cli.commands.Instance + (*DownloadProgress)(nil), // 28: cc.arduino.cli.commands.DownloadProgress + (*TaskProgress)(nil), // 29: cc.arduino.cli.commands.TaskProgress } var file_commands_lib_proto_depIdxs = []int32{ - 26, // 0: cc.arduino.cli.commands.LibraryDownloadReq.instance:type_name -> cc.arduino.cli.commands.Instance - 27, // 1: cc.arduino.cli.commands.LibraryDownloadResp.progress:type_name -> cc.arduino.cli.commands.DownloadProgress - 26, // 2: cc.arduino.cli.commands.LibraryInstallReq.instance:type_name -> cc.arduino.cli.commands.Instance - 27, // 3: cc.arduino.cli.commands.LibraryInstallResp.progress:type_name -> cc.arduino.cli.commands.DownloadProgress - 28, // 4: cc.arduino.cli.commands.LibraryInstallResp.task_progress:type_name -> cc.arduino.cli.commands.TaskProgress - 26, // 5: cc.arduino.cli.commands.LibraryUninstallReq.instance:type_name -> cc.arduino.cli.commands.Instance - 28, // 6: cc.arduino.cli.commands.LibraryUninstallResp.task_progress:type_name -> cc.arduino.cli.commands.TaskProgress - 26, // 7: cc.arduino.cli.commands.LibraryUpgradeAllReq.instance:type_name -> cc.arduino.cli.commands.Instance - 27, // 8: cc.arduino.cli.commands.LibraryUpgradeAllResp.progress:type_name -> cc.arduino.cli.commands.DownloadProgress - 28, // 9: cc.arduino.cli.commands.LibraryUpgradeAllResp.task_progress:type_name -> cc.arduino.cli.commands.TaskProgress - 26, // 10: cc.arduino.cli.commands.LibraryResolveDependenciesReq.instance:type_name -> cc.arduino.cli.commands.Instance + 27, // 0: cc.arduino.cli.commands.LibraryDownloadReq.instance:type_name -> cc.arduino.cli.commands.Instance + 28, // 1: cc.arduino.cli.commands.LibraryDownloadResp.progress:type_name -> cc.arduino.cli.commands.DownloadProgress + 27, // 2: cc.arduino.cli.commands.LibraryInstallReq.instance:type_name -> cc.arduino.cli.commands.Instance + 28, // 3: cc.arduino.cli.commands.LibraryInstallResp.progress:type_name -> cc.arduino.cli.commands.DownloadProgress + 29, // 4: cc.arduino.cli.commands.LibraryInstallResp.task_progress:type_name -> cc.arduino.cli.commands.TaskProgress + 27, // 5: cc.arduino.cli.commands.LibraryUninstallReq.instance:type_name -> cc.arduino.cli.commands.Instance + 29, // 6: cc.arduino.cli.commands.LibraryUninstallResp.task_progress:type_name -> cc.arduino.cli.commands.TaskProgress + 27, // 7: cc.arduino.cli.commands.LibraryUpgradeAllReq.instance:type_name -> cc.arduino.cli.commands.Instance + 28, // 8: cc.arduino.cli.commands.LibraryUpgradeAllResp.progress:type_name -> cc.arduino.cli.commands.DownloadProgress + 29, // 9: cc.arduino.cli.commands.LibraryUpgradeAllResp.task_progress:type_name -> cc.arduino.cli.commands.TaskProgress + 27, // 10: cc.arduino.cli.commands.LibraryResolveDependenciesReq.instance:type_name -> cc.arduino.cli.commands.Instance 13, // 11: cc.arduino.cli.commands.LibraryResolveDependenciesResp.dependencies:type_name -> cc.arduino.cli.commands.LibraryDependencyStatus - 26, // 12: cc.arduino.cli.commands.LibrarySearchReq.instance:type_name -> cc.arduino.cli.commands.Instance + 27, // 12: cc.arduino.cli.commands.LibrarySearchReq.instance:type_name -> cc.arduino.cli.commands.Instance 16, // 13: cc.arduino.cli.commands.LibrarySearchResp.libraries:type_name -> cc.arduino.cli.commands.SearchedLibrary 0, // 14: cc.arduino.cli.commands.LibrarySearchResp.status:type_name -> cc.arduino.cli.commands.LibrarySearchStatus 24, // 15: cc.arduino.cli.commands.SearchedLibrary.releases:type_name -> cc.arduino.cli.commands.SearchedLibrary.ReleasesEntry 17, // 16: cc.arduino.cli.commands.SearchedLibrary.latest:type_name -> cc.arduino.cli.commands.LibraryRelease 19, // 17: cc.arduino.cli.commands.LibraryRelease.resources:type_name -> cc.arduino.cli.commands.DownloadResource 18, // 18: cc.arduino.cli.commands.LibraryRelease.dependencies:type_name -> cc.arduino.cli.commands.LibraryDependency - 26, // 19: cc.arduino.cli.commands.LibraryListReq.instance:type_name -> cc.arduino.cli.commands.Instance + 27, // 19: cc.arduino.cli.commands.LibraryListReq.instance:type_name -> cc.arduino.cli.commands.Instance 22, // 20: cc.arduino.cli.commands.LibraryListResp.installed_library:type_name -> cc.arduino.cli.commands.InstalledLibrary 23, // 21: cc.arduino.cli.commands.InstalledLibrary.library:type_name -> cc.arduino.cli.commands.Library 17, // 22: cc.arduino.cli.commands.InstalledLibrary.release:type_name -> cc.arduino.cli.commands.LibraryRelease 25, // 23: cc.arduino.cli.commands.Library.properties:type_name -> cc.arduino.cli.commands.Library.PropertiesEntry 2, // 24: cc.arduino.cli.commands.Library.location:type_name -> cc.arduino.cli.commands.LibraryLocation 1, // 25: cc.arduino.cli.commands.Library.layout:type_name -> cc.arduino.cli.commands.LibraryLayout - 17, // 26: cc.arduino.cli.commands.SearchedLibrary.ReleasesEntry.value:type_name -> cc.arduino.cli.commands.LibraryRelease - 27, // [27:27] is the sub-list for method output_type - 27, // [27:27] is the sub-list for method input_type - 27, // [27:27] is the sub-list for extension type_name - 27, // [27:27] is the sub-list for extension extendee - 0, // [0:27] is the sub-list for field type_name + 26, // 26: cc.arduino.cli.commands.Library.compatible_with:type_name -> cc.arduino.cli.commands.Library.CompatibleWithEntry + 17, // 27: cc.arduino.cli.commands.SearchedLibrary.ReleasesEntry.value:type_name -> cc.arduino.cli.commands.LibraryRelease + 28, // [28:28] is the sub-list for method output_type + 28, // [28:28] is the sub-list for method input_type + 28, // [28:28] is the sub-list for extension type_name + 28, // [28:28] is the sub-list for extension extendee + 0, // [0:28] is the sub-list for field type_name } func init() { file_commands_lib_proto_init() } @@ -2405,7 +2426,7 @@ func file_commands_lib_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_commands_lib_proto_rawDesc, NumEnums: 3, - NumMessages: 23, + NumMessages: 24, NumExtensions: 0, NumServices: 0, }, diff --git a/rpc/commands/lib.proto b/rpc/commands/lib.proto index cb8c5d24f7f..e259bfa5046 100644 --- a/rpc/commands/lib.proto +++ b/rpc/commands/lib.proto @@ -271,6 +271,8 @@ message Library { // Value of the `includes` field in library.properties or, if missing, the list of // include files available on the library source root directory. repeated string provides_includes = 27; + // Map of FQBNs that specifies if library is compatible with this library + map compatible_with = 28; } enum LibraryLayout { @@ -287,7 +289,7 @@ enum LibraryLocation { user = 1; // In the `libraries` subdirectory of a platform. platform_builtin = 2; - // When `LibraryLocation` is used in a context where a board is specified, + // When `LibraryLocation` is used in a context where a board is specified, // this indicates the library is in the `libraries` subdirectory of a // platform referenced by the board's platform. referenced_platform_builtin = 3; diff --git a/test/test_lib.py b/test/test_lib.py index e4335f2ebc5..4a138262706 100644 --- a/test/test_lib.py +++ b/test/test_lib.py @@ -70,6 +70,76 @@ def test_list(run_command): assert "Arduino_APDS9960.h" == data[0]["library"]["provides_includes"][0] +def test_list_exit_code(run_command): + # Init the environment explicitly + assert run_command("core update-index") + + assert run_command("core list") + + # Verifies lib list doesn't fail when platform is not specified + result = run_command("lib list") + assert result.ok + assert result.stderr.strip() == "" + + # Verify lib list command fails because specified platform is not installed + result = run_command("lib list -b arduino:samd:mkr1000") + assert result.failed + assert ( + result.stderr.strip() == "Error listing Libraries: loading board data: platform arduino:samd is not installed" + ) + + assert run_command('lib install "AllThingsTalk LoRaWAN SDK"') + + # Verifies lib list command keeps failing + result = run_command("lib list -b arduino:samd:mkr1000") + assert result.failed + assert ( + result.stderr.strip() == "Error listing Libraries: loading board data: platform arduino:samd is not installed" + ) + + assert run_command("core install arduino:samd") + + # Verifies lib list command now works since platform has been installed + result = run_command("lib list -b arduino:samd:mkr1000") + assert result.ok + assert result.stderr.strip() == "" + + +def test_list_with_fqbn(run_command): + # Init the environment explicitly + assert run_command("core update-index") + + # Install core + assert run_command("core install arduino:avr") + + # Install some library + assert run_command("lib install ArduinoJson") + assert run_command("lib install wm8978-esp32") + + # Look at the plain text output + result = run_command("lib list -b arduino:avr:uno") + assert result.ok + assert "" == result.stderr + lines = result.stdout.strip().splitlines() + assert 2 == len(lines) + + # Verifies library is compatible + toks = [t.strip() for t in lines[1].split(maxsplit=4)] + assert 5 == len(toks) + assert "ArduinoJson" == toks[0] + + # Look at the JSON output + result = run_command("lib list -b arduino:avr:uno --format json") + assert result.ok + assert "" == result.stderr + data = json.loads(result.stdout) + assert 1 == len(data) + + # Verifies library is compatible + assert data[0]["library"]["name"] == "ArduinoJson" + assert data[0]["library"]["compatible_with"]["arduino:avr:uno"] + + def test_install(run_command): libs = ['"AzureIoTProtocol_MQTT"', '"CMMC MQTT Connector"', '"WiFiNINA"'] # Should be safe to run install multiple times