From 2ca033651455ef7ecfdf350f4ed7d15806fe5efb Mon Sep 17 00:00:00 2001 From: Matteo Pologruto Date: Tue, 21 Feb 2023 16:03:23 +0100 Subject: [PATCH 1/4] Exclude libraries with a missing `.h` file from `lib` commands --- arduino/libraries/loader.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arduino/libraries/loader.go b/arduino/libraries/loader.go index 30c1822bfaa..ec3d1dc164a 100644 --- a/arduino/libraries/loader.go +++ b/arduino/libraries/loader.go @@ -19,6 +19,7 @@ import ( "fmt" "strings" + "github.com/arduino/arduino-cli/arduino/globals" "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/go-paths-helper" properties "github.com/arduino/go-properties-orderedmap" @@ -126,6 +127,11 @@ func makeNewLibrary(libraryDir *paths.Path, location LibraryLocation) (*Library, } func makeLegacyLibrary(path *paths.Path, location LibraryLocation) (*Library, error) { + if foundHeader, err := containsHeaderFile(path); err != nil { + return nil, err + } else if !foundHeader { + return nil, errors.Errorf(tr("invalid library: no header files found")) + } library := &Library{ InstallDir: path.Canonical(), Location: location, @@ -186,3 +192,19 @@ func addExamplesToPathList(examplesPath *paths.Path, list *paths.PathList) error } return nil } + +// containsHeaderFile returns true if the directory contains a ".h" file. +// Returns false otherwise +func containsHeaderFile(d *paths.Path) (bool, error) { + dirContent, err := d.ReadDir() + if err != nil { + return false, fmt.Errorf(tr("reading directory %[1]s content: %[2]w", d, err)) + } + dirContent.FilterOutDirs() + headerExtensions := []string{} + for k := range globals.HeaderFilesValidExtensions { + headerExtensions = append(headerExtensions, k) + } + dirContent.FilterSuffix(headerExtensions...) + return len(dirContent) > 0, nil +} From 7b332cf21e3f672dfa27e3243e14e1a958652652 Mon Sep 17 00:00:00 2001 From: Matteo Pologruto Date: Wed, 22 Feb 2023 09:40:19 +0100 Subject: [PATCH 2/4] Add TestLibListDoesNotIncludeEmptyLibraries to lib_test.go --- internal/integrationtest/lib/lib_test.go | 37 ++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/internal/integrationtest/lib/lib_test.go b/internal/integrationtest/lib/lib_test.go index 469002fbe42..b4b7f34c0f7 100644 --- a/internal/integrationtest/lib/lib_test.go +++ b/internal/integrationtest/lib/lib_test.go @@ -1587,3 +1587,40 @@ func TestLibBundlesWhenLibWithTheSameNameIsInstalledGlobally(t *testing.T) { requirejson.Parse(t, stdout).Query(`.[].library.examples[1]`).MustContain(`"OTALeds"`) } } + +func TestLibListDoesNotIncludeEmptyLibraries(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("lib", "update-index") + require.NoError(t, err) + + // Create a library that does not have neither a library.properties nor a ".h" file + emptyLib := cli.SketchbookDir().Join("libraries", "empty") + require.NoError(t, emptyLib.MkdirAll()) + + // Check that the output of lib list and lib examples is empty + stdout, _, err := cli.Run("lib", "list", "--format", "json") + require.NoError(t, err) + requirejson.Empty(t, stdout) + + stdout, _, err = cli.Run("lib", "examples", "--format", "json") + require.NoError(t, err) + requirejson.Empty(t, stdout) + + // Create a library with a header + libWithHeader := cli.SketchbookDir().Join("libraries", "libWithHeader") + require.NoError(t, libWithHeader.MkdirAll()) + f, err := libWithHeader.Join("libWithHeader.h").Create() + require.NoError(t, err) + require.NoError(t, f.Close()) + + // Check that the output of lib list and lib examples contains the library + stdout, _, err = cli.Run("lib", "list", "--format", "json") + require.NoError(t, err) + requirejson.Len(t, stdout, 1) + + stdout, _, err = cli.Run("lib", "examples", "--format", "json") + require.NoError(t, err) + requirejson.Len(t, stdout, 1) +} From 931c328d2ec150c859f871da6b1139e16ff394b2 Mon Sep 17 00:00:00 2001 From: Matteo Pologruto Date: Tue, 28 Mar 2023 12:41:56 +0200 Subject: [PATCH 3/4] Add unit tests for the changes --- arduino/libraries/libraries_test.go | 11 +++++++++++ arduino/libraries/testdata/LegacyLib/LegacyLib.h | 0 2 files changed, 11 insertions(+) create mode 100644 arduino/libraries/testdata/LegacyLib/LegacyLib.h diff --git a/arduino/libraries/libraries_test.go b/arduino/libraries/libraries_test.go index 68aef73ddf9..35c2a40ddfa 100644 --- a/arduino/libraries/libraries_test.go +++ b/arduino/libraries/libraries_test.go @@ -73,4 +73,15 @@ func TestLibrariesLoader(t *testing.T) { require.Equal(t, "LibWithNonUTF8Properties", lib.Name) require.Equal(t, "àrduìnò", lib.Author) } + { + lib, err := Load(paths.New("testdata", "EmptyLib"), User) + require.Error(t, err) + require.Nil(t, lib) + } + { + lib, err := Load(paths.New("testdata", "LegacyLib"), User) + require.NoError(t, err) + require.Equal(t, "LegacyLib", lib.Name) + require.True(t, lib.IsLegacy) + } } diff --git a/arduino/libraries/testdata/LegacyLib/LegacyLib.h b/arduino/libraries/testdata/LegacyLib/LegacyLib.h new file mode 100644 index 00000000000..e69de29bb2d From c3adae2e43832cb966a983aef8a8c1ac37520272 Mon Sep 17 00:00:00 2001 From: Matteo Pologruto Date: Tue, 28 Mar 2023 17:24:28 +0200 Subject: [PATCH 4/4] Update documentation --- docs/library-specification.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/library-specification.md b/docs/library-specification.md index 132cf2c3f35..a5fa721e57d 100644 --- a/docs/library-specification.md +++ b/docs/library-specification.md @@ -419,6 +419,6 @@ allowing the compilation to fail in a difficult to understand way): ## Old library format (pre-1.5) In order to support old libraries (from Arduino IDE 1.0.x), Arduino IDE and Arduino CLI will also compile libraries -missing a library.properties metadata file. As a result, these libraries should behave as they did in Arduino IDE 1.0.x, -although they will be available for all boards, including non-AVR ones (which wouldn’t have been present in Arduino IDE -1.0.x). +missing a library.properties metadata file (the header file is still required). As a result, these libraries should +behave as they did in Arduino IDE 1.0.x, although they will be available for all boards, including non-AVR ones (which +wouldn’t have been present in Arduino IDE 1.0.x).