Skip to content

Commit e7db62f

Browse files
silvanocerzaper1234
andcommitted
Fix library verification when installing from git repo or zip file (arduino#1466)
* Fix library verification when installing from git repo or zip file * Enhance code comments and unit tests Co-authored-by: per1234 <accounts@perglass.com> Co-authored-by: per1234 <accounts@perglass.com>
1 parent 59f748d commit e7db62f

File tree

7 files changed

+130
-47
lines changed

7 files changed

+130
-47
lines changed

arduino/globals/globals.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,11 @@ var (
4949
".cpp": empty,
5050
".S": empty,
5151
}
52+
53+
// HeaderFilesValidExtensions lists valid extensions for header files
54+
HeaderFilesValidExtensions = map[string]struct{}{
55+
".h": empty,
56+
".hpp": empty,
57+
".hh": empty,
58+
}
5259
)

arduino/libraries/libraries.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"fmt"
2020

2121
"github.com/arduino/arduino-cli/arduino/cores"
22+
"github.com/arduino/arduino-cli/arduino/globals"
2223
"github.com/arduino/arduino-cli/i18n"
2324
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
2425
paths "github.com/arduino/go-paths-helper"
@@ -233,7 +234,11 @@ func (library *Library) SourceHeaders() ([]string, error) {
233234
if err != nil {
234235
return nil, fmt.Errorf(tr("reading lib src dir: %s"), err)
235236
}
236-
cppHeaders.FilterSuffix(".h", ".hpp", ".hh")
237+
headerExtensions := []string{}
238+
for k := range globals.HeaderFilesValidExtensions {
239+
headerExtensions = append(headerExtensions, k)
240+
}
241+
cppHeaders.FilterSuffix(headerExtensions...)
237242
res := []string{}
238243
for _, cppHeader := range cppHeaders {
239244
res = append(res, cppHeader.Base())

arduino/libraries/librariesmanager/install.go

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"os"
2424
"strings"
2525

26+
"github.com/arduino/arduino-cli/arduino/globals"
2627
"github.com/arduino/arduino-cli/arduino/libraries"
2728
"github.com/arduino/arduino-cli/arduino/libraries/librariesindex"
2829
"github.com/arduino/arduino-cli/arduino/utils"
@@ -134,7 +135,7 @@ func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath strin
134135
extractionPath := paths[0]
135136
libraryName := extractionPath.Base()
136137

137-
if err := validateLibrary(libraryName, extractionPath); err != nil {
138+
if err := validateLibrary(extractionPath); err != nil {
138139
return err
139140
}
140141

@@ -224,7 +225,7 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error {
224225
return err
225226
}
226227

227-
if err := validateLibrary(libraryName, installPath); err != nil {
228+
if err := validateLibrary(installPath); err != nil {
228229
// Clean up installation directory since this is not a valid library
229230
installPath.RemoveAll()
230231
return err
@@ -254,22 +255,47 @@ func parseGitURL(gitURL string) (string, error) {
254255
return res, nil
255256
}
256257

257-
// validateLibrary verifies the dir contains a valid library, meaning it has both
258-
// an header <name>.h, either in src or root folder, and a library.properties file
259-
func validateLibrary(name string, dir *paths.Path) error {
260-
// Verify library contains library header.
261-
// Checks also root folder for legacy reasons.
262-
// For more info see:
258+
// validateLibrary verifies the dir contains a valid library, meaning it has either
259+
// library.properties file and an header in src/ or an header in its root folder.
260+
// Returns nil if dir contains a valid library, error on all other cases.
261+
func validateLibrary(dir *paths.Path) error {
262+
if dir.NotExist() {
263+
return fmt.Errorf(tr("directory doesn't exist: %s", dir))
264+
}
265+
266+
searchHeaderFile := func(d *paths.Path) (bool, error) {
267+
if d.NotExist() {
268+
// A directory that doesn't exist can't obviously contain any header file
269+
return false, nil
270+
}
271+
dirContent, err := d.ReadDir()
272+
if err != nil {
273+
return false, fmt.Errorf(tr("reading directory %s content: %w", dir, err))
274+
}
275+
dirContent.FilterOutDirs()
276+
headerExtensions := []string{}
277+
for k := range globals.HeaderFilesValidExtensions {
278+
headerExtensions = append(headerExtensions, k)
279+
}
280+
dirContent.FilterSuffix(headerExtensions...)
281+
return len(dirContent) > 0, nil
282+
}
283+
284+
// Recursive library layout
263285
// https://arduino.github.io/arduino-cli/latest/library-specification/#source-code
264-
libraryHeader := name + ".h"
265-
if !dir.Join("src", libraryHeader).Exist() && !dir.Join(libraryHeader).Exist() {
266-
return fmt.Errorf(tr(`library is not valid: missing header file "%s"`), libraryHeader)
286+
if headerFound, err := searchHeaderFile(dir.Join("src")); err != nil {
287+
return err
288+
} else if dir.Join("library.properties").Exist() && headerFound {
289+
return nil
267290
}
268291

269-
// Verifies library contains library.properties
270-
if !dir.Join("library.properties").Exist() {
271-
return fmt.Errorf(tr(`library is not valid: missing file "library.properties"`))
292+
// Flat library layout
293+
// https://arduino.github.io/arduino-cli/latest/library-specification/#source-code
294+
if headerFound, err := searchHeaderFile(dir); err != nil {
295+
return err
296+
} else if headerFound {
297+
return nil
272298
}
273299

274-
return nil
300+
return fmt.Errorf(tr("library not valid"))
275301
}

arduino/libraries/librariesmanager/install_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package librariesmanager
1818
import (
1919
"testing"
2020

21+
"github.com/arduino/go-paths-helper"
2122
"github.com/stretchr/testify/require"
2223
)
2324

@@ -62,3 +63,43 @@ func TestParseGitURL(t *testing.T) {
6263
require.Equal(t, "arduino-lib", libraryName)
6364
require.NoError(t, err)
6465
}
66+
67+
func TestValidateLibrary(t *testing.T) {
68+
tmpDir := paths.New(t.TempDir())
69+
70+
nonExistingDirLib := tmpDir.Join("nonExistingDirLib")
71+
err := validateLibrary(nonExistingDirLib)
72+
require.Errorf(t, err, "directory doesn't exist: %s", nonExistingDirLib)
73+
74+
emptyLib := tmpDir.Join("emptyLib")
75+
emptyLib.Mkdir()
76+
err = validateLibrary(emptyLib)
77+
require.Errorf(t, err, "library not valid")
78+
79+
onlyPropertiesLib := tmpDir.Join("onlyPropertiesLib")
80+
onlyPropertiesLib.Mkdir()
81+
onlyPropertiesLib.Join("library.properties").WriteFile([]byte{})
82+
err = validateLibrary(onlyPropertiesLib)
83+
require.Errorf(t, err, "library not valid")
84+
85+
missingPropertiesLib := tmpDir.Join("missingPropertiesLib")
86+
missingPropertiesLibSourceDir := missingPropertiesLib.Join("src")
87+
missingPropertiesLibSourceDir.MkdirAll()
88+
missingPropertiesLibSourceDir.Join("some_file.hpp").WriteFile([]byte{})
89+
err = validateLibrary(missingPropertiesLib)
90+
require.Errorf(t, err, "library not valid")
91+
92+
validLib := tmpDir.Join("valiLib")
93+
validLibSourceDir := validLib.Join("src")
94+
validLibSourceDir.MkdirAll()
95+
validLibSourceDir.Join("some_file.hpp").WriteFile([]byte{})
96+
validLib.Join("library.properties").WriteFile([]byte{})
97+
err = validateLibrary(validLib)
98+
require.NoError(t, err)
99+
100+
validLegacyLib := tmpDir.Join("validLegacyLib")
101+
validLegacyLib.Mkdir()
102+
validLegacyLib.Join("some_file.hpp").WriteFile([]byte{})
103+
err = validateLibrary(validLib)
104+
require.NoError(t, err)
105+
}

i18n/data/en.po

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2268,10 +2268,10 @@ msgstr "Use %s for more information about a command."
22682268
msgid "Use the specified programmer to upload."
22692269
msgstr "Use the specified programmer to upload."
22702270

2271-
#: arduino/libraries/librariesmanager/install.go:62
2272-
#: arduino/libraries/librariesmanager/install.go:78
2273-
#: arduino/libraries/librariesmanager/install.go:100
2274-
#: arduino/libraries/librariesmanager/install.go:184
2271+
#: arduino/libraries/librariesmanager/install.go:63
2272+
#: arduino/libraries/librariesmanager/install.go:79
2273+
#: arduino/libraries/librariesmanager/install.go:101
2274+
#: arduino/libraries/librariesmanager/install.go:185
22752275
msgid "User directory not set"
22762276
msgstr "User directory not set"
22772277

@@ -2397,7 +2397,7 @@ msgstr "[DEPRECATED] %s"
23972397
msgid "archive hash differs from hash in index"
23982398
msgstr "archive hash differs from hash in index"
23992399

2400-
#: arduino/libraries/librariesmanager/install.go:131
2400+
#: arduino/libraries/librariesmanager/install.go:132
24012401
msgid "archive is not valid: multiple files found in zip file top level"
24022402
msgstr "archive is not valid: multiple files found in zip file top level"
24032403

@@ -2547,10 +2547,14 @@ msgstr "dependency '%s' is not available"
25472547
msgid "destination already exists"
25482548
msgstr "destination already exists"
25492549

2550-
#: arduino/libraries/librariesmanager/install.go:69
2550+
#: arduino/libraries/librariesmanager/install.go:70
25512551
msgid "destination dir %s already exists, cannot install"
25522552
msgstr "destination dir %s already exists, cannot install"
25532553

2554+
#: arduino/libraries/librariesmanager/install.go:263
2555+
msgid "directory doesn't exist: %s"
2556+
msgstr "directory doesn't exist: %s"
2557+
25542558
#: arduino/discovery/discoverymanager/discoverymanager.go:112
25552559
msgid "discovery %[1]s process not started: %[2]w"
25562560
msgstr "discovery %[1]s process not started: %[2]w"
@@ -2615,7 +2619,7 @@ msgstr "error: %s and %s flags cannot be used together"
26152619
msgid "extracting archive: %s"
26162620
msgstr "extracting archive: %s"
26172621

2618-
#: arduino/libraries/librariesmanager/install.go:119
2622+
#: arduino/libraries/librariesmanager/install.go:120
26192623
msgid "extracting archive: %w"
26202624
msgstr "extracting archive: %w"
26212625

@@ -2714,7 +2718,7 @@ msgstr "getting tool dependencies for platform %[1]s: %[2]s"
27142718
msgid "importing sketch metadata: %s"
27152719
msgstr "importing sketch metadata: %s"
27162720

2717-
#: arduino/libraries/librariesmanager/install.go:86
2721+
#: arduino/libraries/librariesmanager/install.go:87
27182722
msgid "install directory not set"
27192723
msgstr "install directory not set"
27202724

@@ -2775,7 +2779,7 @@ msgstr "invalid empty library version: %s"
27752779
msgid "invalid empty option found"
27762780
msgstr "invalid empty option found"
27772781

2778-
#: arduino/libraries/librariesmanager/install.go:252
2782+
#: arduino/libraries/librariesmanager/install.go:253
27792783
msgid "invalid git url"
27802784
msgstr "invalid git url"
27812785

@@ -2839,22 +2843,18 @@ msgstr "key not found in settings"
28392843
msgid "keywords"
28402844
msgstr "keywords"
28412845

2842-
#: arduino/libraries/librariesmanager/install.go:157
2843-
#: arduino/libraries/librariesmanager/install.go:200
2846+
#: arduino/libraries/librariesmanager/install.go:158
2847+
#: arduino/libraries/librariesmanager/install.go:201
28442848
msgid "library %s already installed"
28452849
msgstr "library %s already installed"
28462850

2847-
#: arduino/libraries/librariesmanager/install.go:38
2851+
#: arduino/libraries/librariesmanager/install.go:39
28482852
msgid "library already installed"
28492853
msgstr "library already installed"
28502854

2851-
#: arduino/libraries/librariesmanager/install.go:271
2852-
msgid "library is not valid: missing file \"library.properties\""
2853-
msgstr "library is not valid: missing file \"library.properties\""
2854-
2855-
#: arduino/libraries/librariesmanager/install.go:266
2856-
msgid "library is not valid: missing header file \"%s\""
2857-
msgstr "library is not valid: missing header file \"%s\""
2855+
#: arduino/libraries/librariesmanager/install.go:300
2856+
msgid "library not valid"
2857+
msgstr "library not valid"
28582858

28592859
#: arduino/libraries/librariesmanager/librariesmanager.go:226
28602860
msgid "library path does not exist: %s"
@@ -2933,7 +2933,7 @@ msgstr "missing platform %[1]s:%[2]s referenced by board %[3]s"
29332933
msgid "missing platform release %[1]s:%[2]s referenced by board %[3]s"
29342934
msgstr "missing platform release %[1]s:%[2]s referenced by board %[3]s"
29352935

2936-
#: arduino/libraries/librariesmanager/install.go:174
2936+
#: arduino/libraries/librariesmanager/install.go:175
29372937
#: arduino/resources/install.go:94
29382938
msgid "moving extracted archive to destination dir: %s"
29392939
msgstr "moving extracted archive to destination dir: %s"
@@ -3091,6 +3091,10 @@ msgstr "reading dir %[1]s: %[2]s"
30913091
msgid "reading directory %[1]s: %[2]s"
30923092
msgstr "reading directory %[1]s: %[2]s"
30933093

3094+
#: arduino/libraries/librariesmanager/install.go:273
3095+
msgid "reading directory %s content: %w"
3096+
msgstr "reading directory %s content: %w"
3097+
30943098
#: arduino/builder/sketch.go:76
30953099
msgid "reading file %[1]s: %[2]s"
30963100
msgstr "reading file %[1]s: %[2]s"
@@ -3107,11 +3111,11 @@ msgstr "reading inventory file: %w"
31073111
msgid "reading lib headers: %s"
31083112
msgstr "reading lib headers: %s"
31093113

3110-
#: arduino/libraries/libraries.go:234
3114+
#: arduino/libraries/libraries.go:235
31113115
msgid "reading lib src dir: %s"
31123116
msgstr "reading lib src dir: %s"
31133117

3114-
#: arduino/libraries/libraries.go:114
3118+
#: arduino/libraries/libraries.go:115
31153119
msgid "reading library headers: %w"
31163120
msgstr "reading library headers: %w"
31173121

@@ -3148,7 +3152,7 @@ msgstr "release not found"
31483152
msgid "removing corrupted archive file: %s"
31493153
msgstr "removing corrupted archive file: %s"
31503154

3151-
#: arduino/libraries/librariesmanager/install.go:89
3155+
#: arduino/libraries/librariesmanager/install.go:90
31523156
msgid "removing lib directory: %s"
31533157
msgstr "removing lib directory: %s"
31543158

i18n/rice-box.go

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/test_lib.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ def test_install_zip_invalid_library(run_command, data_dir, downloads_dir):
925925
# Test zip-path install
926926
res = run_command(f"lib install --zip-path {zip_path}")
927927
assert res.failed
928-
assert 'library is not valid: missing header file "lib-without-header.h"' in res.stderr
928+
assert "library not valid" in res.stderr
929929

930930
lib_install_dir = Path(data_dir, "libraries", "lib-without-properties")
931931
# Verifies library is not already installed
@@ -935,7 +935,7 @@ def test_install_zip_invalid_library(run_command, data_dir, downloads_dir):
935935
# Test zip-path install
936936
res = run_command(f"lib install --zip-path {zip_path}")
937937
assert res.failed
938-
assert 'library is not valid: missing file "library.properties"' in res.stderr
938+
assert "library not valid" in res.stderr
939939

940940

941941
def test_install_git_invalid_library(run_command, data_dir, downloads_dir):
@@ -962,7 +962,7 @@ def test_install_git_invalid_library(run_command, data_dir, downloads_dir):
962962

963963
res = run_command(f"lib install --git-url {repo_dir}", custom_env=env)
964964
assert res.failed
965-
assert 'library is not valid: missing header file "lib-without-header.h"' in res.stderr
965+
assert "library not valid" in res.stderr
966966
assert not lib_install_dir.exists()
967967

968968
# Create another fake library repository
@@ -980,5 +980,5 @@ def test_install_git_invalid_library(run_command, data_dir, downloads_dir):
980980

981981
res = run_command(f"lib install --git-url {repo_dir}", custom_env=env)
982982
assert res.failed
983-
assert 'library is not valid: missing file "library.properties"' in res.stderr
983+
assert "library not valid" in res.stderr
984984
assert not lib_install_dir.exists()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy