Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c7742fa

Browse files
cmaglieRoberto Sora
and
Roberto Sora
authored
'arduino-cli lib' command arguments are now case insensitive (#628)
* Library install arguments are no more case sensitive This should make easier to install libraries from command line. * Moved lib args parsing functions in cli/lib * Factored ParseLibraryReferenceArgAndAdjustCase function Now the cli/lib module uses ParseLibraryReferenceArgAndAdjustCase so the cose-insensitive argument is allowed in all lib commands. * Added test for case sensitiveness in cli/lib params * Update test/test_lib.py Co-Authored-By: Roberto Sora <r.sora@arduino.cc>
1 parent adf9192 commit c7742fa

File tree

9 files changed

+209
-100
lines changed

9 files changed

+209
-100
lines changed

‎cli/globals/args.go‎

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -86,51 +86,3 @@ func ParseReferenceArg(arg string, parseArch bool) (*ReferenceArg, error) {
8686

8787
return ret, nil
8888
}
89-
90-
// LibraryReferenceArg is a command line argument that reference a library.
91-
type LibraryReferenceArg struct {
92-
Name string
93-
Version string
94-
}
95-
96-
func (r *LibraryReferenceArg) String() string {
97-
if r.Version != "" {
98-
return r.Name + "@" + r.Version
99-
}
100-
return r.Name
101-
}
102-
103-
// ParseLibraryReferenceArg parse a command line argument that reference a
104-
// library in the form "LibName@Version" or just "LibName".
105-
func ParseLibraryReferenceArg(arg string) (*LibraryReferenceArg, error) {
106-
tokens := strings.SplitN(arg, "@", 2)
107-
108-
ret := &LibraryReferenceArg{}
109-
// TODO: check library Name constraints
110-
// TODO: check library Version constraints
111-
if tokens[0] == "" {
112-
return nil, fmt.Errorf("invalid empty library name")
113-
}
114-
ret.Name = tokens[0]
115-
if len(tokens) > 1 {
116-
if tokens[1] == "" {
117-
return nil, fmt.Errorf("invalid empty library version: %s", arg)
118-
}
119-
ret.Version = tokens[1]
120-
}
121-
return ret, nil
122-
}
123-
124-
// ParseLibraryReferenceArgs is a convenient wrapper that operates on a slice of strings and
125-
// calls ParseLibraryReferenceArg for each of them. It returns at the first invalid argument.
126-
func ParseLibraryReferenceArgs(args []string) ([]*LibraryReferenceArg, error) {
127-
ret := []*LibraryReferenceArg{}
128-
for _, arg := range args {
129-
if reference, err := ParseLibraryReferenceArg(arg); err == nil {
130-
ret = append(ret, reference)
131-
} else {
132-
return nil, err
133-
}
134-
}
135-
return ret, nil
136-
}

‎cli/globals/args_test.go‎

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,6 @@ var goodCores = []struct {
3131
{"arduino:avr@1.6.20", &globals.ReferenceArg{"arduino", "avr", "1.6.20"}},
3232
}
3333

34-
var goodLibs = []struct {
35-
in string
36-
expected *globals.LibraryReferenceArg
37-
}{
38-
{"mylib", &globals.LibraryReferenceArg{"mylib", ""}},
39-
{"mylib@1.0", &globals.LibraryReferenceArg{"mylib", "1.0"}},
40-
}
41-
4234
var badCores = []struct {
4335
in string
4436
expected *globals.ReferenceArg
@@ -53,18 +45,7 @@ var badCores = []struct {
5345
{"", nil},
5446
}
5547

56-
var badLibs = []struct {
57-
in string
58-
expected *globals.LibraryReferenceArg
59-
}{
60-
{"", nil},
61-
{"mylib@", nil},
62-
}
63-
6448
func TestArgsStringify(t *testing.T) {
65-
for _, lib := range goodLibs {
66-
require.Equal(t, lib.in, lib.expected.String())
67-
}
6849
for _, core := range goodCores {
6950
require.Equal(t, core.in, core.expected.String())
7051
}
@@ -84,32 +65,6 @@ func TestParseReferenceArgCores(t *testing.T) {
8465
}
8566
}
8667

87-
func TestParseReferenceArgLibs(t *testing.T) {
88-
for _, tt := range goodLibs {
89-
actual, err := globals.ParseLibraryReferenceArg(tt.in)
90-
assert.Nil(t, err, "Testing good arg '%s'", tt.in)
91-
assert.Equal(t, tt.expected, actual, "Testing good arg '%s'", tt.in)
92-
}
93-
for _, tt := range badLibs {
94-
res, err := globals.ParseLibraryReferenceArg(tt.in)
95-
require.Nil(t, res, "Testing bad arg '%s'", tt.in)
96-
require.NotNil(t, err, "Testing bad arg '%s'", tt.in)
97-
}
98-
}
99-
100-
func TestParseLibraryReferenceArgs(t *testing.T) {
101-
args := []string{}
102-
for _, tt := range goodLibs {
103-
args = append(args, tt.in)
104-
}
105-
refs, err := globals.ParseLibraryReferenceArgs(args)
106-
require.Nil(t, err)
107-
require.Len(t, refs, len(goodLibs))
108-
for i, tt := range goodLibs {
109-
assert.Equal(t, tt.expected, refs[i])
110-
}
111-
}
112-
11368
func TestParseArgs(t *testing.T) {
11469
input := []string{}
11570
for _, tt := range goodCores {

‎cli/lib/args.go‎

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to license@arduino.cc.
15+
16+
package lib
17+
18+
import (
19+
"context"
20+
"fmt"
21+
"strings"
22+
23+
"github.com/arduino/arduino-cli/commands/lib"
24+
rpc "github.com/arduino/arduino-cli/rpc/commands"
25+
)
26+
27+
// LibraryReferenceArg is a command line argument that reference a library.
28+
type LibraryReferenceArg struct {
29+
Name string
30+
Version string
31+
}
32+
33+
func (r *LibraryReferenceArg) String() string {
34+
if r.Version != "" {
35+
return r.Name + "@" + r.Version
36+
}
37+
return r.Name
38+
}
39+
40+
// ParseLibraryReferenceArg parse a command line argument that reference a
41+
// library in the form "LibName@Version" or just "LibName".
42+
func ParseLibraryReferenceArg(arg string) (*LibraryReferenceArg, error) {
43+
tokens := strings.SplitN(arg, "@", 2)
44+
45+
ret := &LibraryReferenceArg{}
46+
// TODO: check library Name constraints
47+
// TODO: check library Version constraints
48+
if tokens[0] == "" {
49+
return nil, fmt.Errorf("invalid empty library name")
50+
}
51+
ret.Name = tokens[0]
52+
if len(tokens) > 1 {
53+
if tokens[1] == "" {
54+
return nil, fmt.Errorf("invalid empty library version: %s", arg)
55+
}
56+
ret.Version = tokens[1]
57+
}
58+
return ret, nil
59+
}
60+
61+
// ParseLibraryReferenceArgs is a convenient wrapper that operates on a slice of strings and
62+
// calls ParseLibraryReferenceArg for each of them. It returns at the first invalid argument.
63+
func ParseLibraryReferenceArgs(args []string) ([]*LibraryReferenceArg, error) {
64+
ret := []*LibraryReferenceArg{}
65+
for _, arg := range args {
66+
if reference, err := ParseLibraryReferenceArg(arg); err == nil {
67+
ret = append(ret, reference)
68+
} else {
69+
return nil, err
70+
}
71+
}
72+
return ret, nil
73+
}
74+
75+
// ParseLibraryReferenceArgAndAdjustCase parse a command line argument that reference a
76+
// library and possibly adjust the case of the name to match a library in the index
77+
func ParseLibraryReferenceArgAndAdjustCase(instance *rpc.Instance, arg string) (*LibraryReferenceArg, error) {
78+
libRef, err := ParseLibraryReferenceArg(arg)
79+
res, err := lib.LibrarySearch(context.Background(), &rpc.LibrarySearchReq{
80+
Instance: instance,
81+
Query: libRef.Name,
82+
})
83+
if err != nil {
84+
return nil, err
85+
}
86+
87+
candidates := []*rpc.SearchedLibrary{}
88+
for _, foundLib := range res.GetLibraries() {
89+
if strings.ToLower(foundLib.GetName()) == strings.ToLower(libRef.Name) {
90+
candidates = append(candidates, foundLib)
91+
}
92+
}
93+
if len(candidates) == 1 {
94+
libRef.Name = candidates[0].GetName()
95+
}
96+
return libRef, nil
97+
}
98+
99+
// ParseLibraryReferenceArgsAndAdjustCase is a convenient wrapper that operates on a slice of
100+
// strings and calls ParseLibraryReferenceArgAndAdjustCase for each of them. It returns at the first invalid argument.
101+
func ParseLibraryReferenceArgsAndAdjustCase(instance *rpc.Instance, args []string) ([]*LibraryReferenceArg, error) {
102+
ret := []*LibraryReferenceArg{}
103+
for _, arg := range args {
104+
if reference, err := ParseLibraryReferenceArgAndAdjustCase(instance, arg); err == nil {
105+
ret = append(ret, reference)
106+
} else {
107+
return nil, err
108+
}
109+
}
110+
return ret, nil
111+
}

‎cli/lib/args_test.go‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to license@arduino.cc.
15+
16+
package lib
17+
18+
import (
19+
"testing"
20+
21+
"github.com/stretchr/testify/assert"
22+
"github.com/stretchr/testify/require"
23+
)
24+
25+
var goodLibs = []struct {
26+
in string
27+
expected *LibraryReferenceArg
28+
}{
29+
{"mylib", &LibraryReferenceArg{"mylib", ""}},
30+
{"mylib@1.0", &LibraryReferenceArg{"mylib", "1.0"}},
31+
}
32+
33+
var badLibs = []struct {
34+
in string
35+
expected *LibraryReferenceArg
36+
}{
37+
{"", nil},
38+
{"mylib@", nil},
39+
}
40+
41+
func TestArgsStringify(t *testing.T) {
42+
for _, lib := range goodLibs {
43+
require.Equal(t, lib.in, lib.expected.String())
44+
}
45+
}
46+
47+
func TestParseReferenceArgLibs(t *testing.T) {
48+
for _, tt := range goodLibs {
49+
actual, err := ParseLibraryReferenceArg(tt.in)
50+
assert.Nil(t, err, "Testing good arg '%s'", tt.in)
51+
assert.Equal(t, tt.expected, actual, "Testing good arg '%s'", tt.in)
52+
}
53+
for _, tt := range badLibs {
54+
res, err := ParseLibraryReferenceArg(tt.in)
55+
require.Nil(t, res, "Testing bad arg '%s'", tt.in)
56+
require.NotNil(t, err, "Testing bad arg '%s'", tt.in)
57+
}
58+
}
59+
60+
func TestParseLibraryReferenceArgs(t *testing.T) {
61+
args := []string{}
62+
for _, tt := range goodLibs {
63+
args = append(args, tt.in)
64+
}
65+
refs, err := ParseLibraryReferenceArgs(args)
66+
require.Nil(t, err)
67+
require.Len(t, refs, len(goodLibs))
68+
for i, tt := range goodLibs {
69+
assert.Equal(t, tt.expected, refs[i])
70+
}
71+
}

‎cli/lib/check_deps.go‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222

2323
"github.com/arduino/arduino-cli/cli/errorcodes"
2424
"github.com/arduino/arduino-cli/cli/feedback"
25-
"github.com/arduino/arduino-cli/cli/globals"
2625
"github.com/arduino/arduino-cli/cli/instance"
2726
"github.com/arduino/arduino-cli/commands/lib"
2827
rpc "github.com/arduino/arduino-cli/rpc/commands"
@@ -45,13 +44,13 @@ func initDepsCommand() *cobra.Command {
4544
}
4645

4746
func runDepsCommand(cmd *cobra.Command, args []string) {
48-
libRef, err := globals.ParseLibraryReferenceArg(args[0])
47+
instance := instance.CreateInstanceIgnorePlatformIndexErrors()
48+
libRef, err := ParseLibraryReferenceArgAndAdjustCase(instance, args[0])
4949
if err != nil {
5050
feedback.Errorf("Arguments error: %v", err)
5151
os.Exit(errorcodes.ErrBadArgument)
5252
}
5353

54-
instance := instance.CreateInstanceIgnorePlatformIndexErrors()
5554
deps, err := lib.LibraryResolveDependencies(context.Background(), &rpc.LibraryResolveDependenciesReq{
5655
Instance: instance,
5756
Name: libRef.Name,

‎cli/lib/download.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func initDownloadCommand() *cobra.Command {
4545

4646
func runDownloadCommand(cmd *cobra.Command, args []string) {
4747
instance := instance.CreateInstanceIgnorePlatformIndexErrors()
48-
refs, err := globals.ParseLibraryReferenceArgs(args)
48+
refs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args)
4949
if err != nil {
5050
feedback.Errorf("Invalid argument passed: %v", err)
5151
os.Exit(errorcodes.ErrBadArgument)

‎cli/lib/install.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ var installFlags struct {
5050

5151
func runInstallCommand(cmd *cobra.Command, args []string) {
5252
instance := instance.CreateInstanceIgnorePlatformIndexErrors()
53-
libRefs, err := globals.ParseLibraryReferenceArgs(args)
53+
libRefs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args)
5454
if err != nil {
5555
feedback.Errorf("Arguments error: %v", err)
5656
os.Exit(errorcodes.ErrBadArgument)

‎cli/lib/uninstall.go‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121

2222
"github.com/arduino/arduino-cli/cli/errorcodes"
2323
"github.com/arduino/arduino-cli/cli/feedback"
24-
"github.com/arduino/arduino-cli/cli/globals"
2524
"github.com/arduino/arduino-cli/cli/instance"
2625
"github.com/arduino/arduino-cli/cli/output"
2726
"github.com/arduino/arduino-cli/commands/lib"
@@ -46,7 +45,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) {
4645
logrus.Info("Executing `arduino lib uninstall`")
4746

4847
instance := instance.CreateInstanceIgnorePlatformIndexErrors()
49-
refs, err := globals.ParseLibraryReferenceArgs(args)
48+
refs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args)
5049
if err != nil {
5150
feedback.Errorf("Invalid argument passed: %v", err)
5251
os.Exit(errorcodes.ErrBadArgument)

‎test/test_lib.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,28 @@ def test_uninstall_spaces(run_command):
9292
assert result.ok
9393
assert len(json.loads(result.stdout)) == 0
9494

95+
def test_lib_ops_caseinsensitive(run_command):
96+
"""
97+
This test is supposed to (un)install the following library,
98+
As you can see the name is all caps:
99+
100+
Name: "PCM"
101+
Author: David Mellis <d.mellis@bcmi-labs.cc>, Michael Smith <michael@hurts.ca>
102+
Maintainer: David Mellis <d.mellis@bcmi-labs.cc>
103+
Sentence: Playback of short audio samples.
104+
Paragraph: These samples are encoded directly in the Arduino sketch as an array of numbers.
105+
Website: http://highlowtech.org/?p=1963
106+
Category: Signal Input/Output
107+
Architecture: avr
108+
Types: Contributed
109+
Versions: [1.0.0]
110+
"""
111+
key = 'pcm'
112+
assert run_command("lib install {}".format(key))
113+
assert run_command("lib uninstall {}".format(key))
114+
result = run_command("lib list --format json")
115+
assert result.ok
116+
assert len(json.loads(result.stdout)) == 0
95117

96118
def test_search(run_command):
97119
assert run_command("lib update-index")

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /