8000 Merge branch 'master' into globals.h · arduino/arduino-cli@5e76bd5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5e76bd5

Browse files
authored
Merge branch 'master' into globals.h
2 parents 7782bac + edc63f8 commit 5e76bd5

File tree

37 files changed

+536
-322
lines changed

37 files changed

+536
-322
lines changed

.github/workflows/sync-labels.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131

3232
- name: Download JSON schema for labels configuration file
3333
id: download-schema
34-
uses: carlosperate/download-file-action@v1.0.3
34+
uses: carlosperate/download-file-action@v1
3535
with:
3636
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json
3737
location: ${{ runner.temp }}/label-configuration-schema
@@ -66,7 +66,7 @@ jobs:
6666

6767
steps:
6868
- name: Download
69-
uses: carlosperate/download-file-action@v1.0.3
69+
uses: carlosperate/download-file-action@v1
7070
with:
7171
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }}
7272

arduino/cores/cores.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
"github.com/arduino/arduino-cli/arduino/resources"
2525
"github.com/arduino/arduino-cli/i18n"
26+
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
2627
paths "github.com/arduino/go-paths-helper"
2728
properties "github.com/arduino/go-properties-orderedmap"
2829
semver "go.bug.st/relaxed-semver"
@@ -342,6 +343,14 @@ func (release *PlatformRelease) String() string {
342343
return release.Platform.String() + "@" + version
343344
}
344345

346+
// ToRPCPlatformReference creates a gRPC PlatformReference message out of this PlatformRelease
347+
func (release *PlatformRelease) ToRPCPlatformReference() *rpc.PlatformReference {
348+
return &rpc.PlatformReference{
349+
Id: release.Platform.String(),
350+
Version: release.Version.String(),
351+
}
352+
}
353+
345354
// MarshalJSON provides a more user friendly serialization for
346355
// PlatformRelease objects.
347356
func (release *PlatformRelease) MarshalJSON() ([]byte, error) {

arduino/errors.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package arduino
1717

1818
import (
1919
"fmt"
20+
"strings"
2021

2122
"github.com/arduino/arduino-cli/arduino/discovery"
2223
"github.com/arduino/arduino-cli/i18n"
@@ -715,3 +716,24 @@ func (e *SignatureVerificationFailedError) Unwrap() error {
715716
func (e *SignatureVerificationFailedError) ToRPCStatus() *status.Status {
716717
return status.New(codes.Unavailable, e.Error())
717718
}
719+
720+
// MultiplePlatformsError is returned when trying to detect
721+
// the Platform the user is trying to interact with and
722+
// and multiple results are found.
723+
type MultiplePlatformsError struct {
724+
Platforms []string
725+
UserPlatform string
726+
}
727+
728+
func (e *MultiplePlatformsError) Error() string {
729+
return tr("Found %d platform for reference \"%s\":\n%s",
730+
len(e.Platforms),
731+
e.UserPlatform,
732+
strings.Join(e.Platforms, "\n"),
733+
)
734+
}
735+
736+
// ToRPCStatus converts the error into a *status.Status
737+
func (e *MultiplePlatformsError) ToRPCStatus() *status.Status {
738+
return status.New(codes.InvalidArgument, e.Error())
739+
}

cli/arguments/reference.go

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ package arguments
1818
import (
1919
"fmt"
2020
"strings"
21+
22+
"github.com/arduino/arduino-cli/arduino"
23+
"github.com/arduino/arduino-cli/cli/instance"
24+
"github.com/arduino/arduino-cli/commands/core"
25+
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
26+
"github.com/sirupsen/logrus"
2127
)
2228

2329
// Reference represents a reference item (core or library) passed to the CLI
@@ -37,10 +43,10 @@ func (r *Reference) String() string {
3743

3844
// ParseReferences is a convenient wrapper that operates on a slice of strings and
3945
// calls ParseReference for each of them. It returns at the first invalid argument.
40-
func ParseReferences(args []string, parseArch bool) ([]*Reference, error) {
46+
func ParseReferences(args []string) ([]*Reference, error) {
4147
ret := []*Reference{}
4248
for _, arg := range args {
43-
reference, err := ParseReference(arg, parseArch)
49+
reference, err := ParseReference(arg)
4450
if err != nil {
4551
return nil, err
4652
}
@@ -49,10 +55,13 @@ func ParseReferences(args []string, parseArch bool) ([]*Reference, error) {
4955
return ret, nil
5056
}
5157

52-
// ParseReference parses a string and returns a Reference object. If `parseArch` is passed,
53-
// the method also tries to parse the architecture bit, i.e. string must be in the form
54-
// "packager:arch@version", useful to represent a platform (or core) name.
55-
func ParseReference(arg string, parseArch bool) (*Reference, error) {
58+
// ParseReference parses a string and returns a Reference object.
59+
// It tries to infer the platform the user is asking for.
60+
// To achieve that, it tries to use github.com/arduino/arduino-cli/commands/core.GetPlatform
61+
// Note that the Reference is returned rightaway if the arg inserted by the user matches perfectly one in the response of core.GetPlatform
62+
// A MultiplePlatformsError is returned if the platform searched by the user matches multiple platforms
63+
func ParseReference(arg string) (*Reference, error) {
64+
logrus.Infof("Parsing reference %s", arg)
5665
ret := &Reference{}
5766
if arg == "" {
5867
return nil, fmt.Errorf(tr("invalid empty core argument"))
@@ -69,20 +78,49 @@ func ParseReference(arg string, parseArch bool) (*Reference, error) {
6978
ret.Version = toks[1]
7079
}
7180

72-
if parseArch {
73-
toks = strings.Split(ret.PackageName, ":")
74-
if len(toks) != 2 {
75-
return nil, fmt.Errorf(tr("invalid item %s"), arg)
81+
toks = strings.Split(ret.PackageName, ":")
82+
if len(toks) != 2 {
83+
return nil, fmt.Errorf(tr("invalid item %s"), arg)
84+
}
85+
if toks[0] == "" {
86+
return nil, fmt.Errorf(tr("invalid empty core name '%s'"), arg)
87+
}
88+
ret.PackageName = toks[0]
89+
if toks[1] == "" {
90+
return nil, fmt.Errorf(tr("invalid empty core architecture '%s'"), arg)
91+
}
92+
ret.Architecture = toks[1]
93+
94+
// Now that we have the required informations in `ret` we can
95+
// try to use core.GetPlatforms to optimize what the user typed
96+
// (by replacing the PackageName and Architecture in ret with the content of core.GetPlatform())
97+
platforms, _ := core.GetPlatforms(&rpc.PlatformListRequest{
98+
Instance: instance.CreateAndInit(),
99+
UpdatableOnly: false,
100+
All: true, // this is true because we want also the installable platforms
101+
})
102+
foundPlatforms := []string{}
103+
for _, platform := range platforms {
104+
platformID := platform.GetId()
105+
platformUser := ret.PackageName + ":" + ret.Architecture
106+
// At first we check if the platform the user is searching for matches an available one,
107+
// this way we do not need to adapt the casing and we can return it directly
108+
if platformUser == platformID {
109+
return ret, nil
76110
}
77-
if toks[0] == "" {
78-
return nil, fmt.Errorf(tr("invalid empty core name '%s'"), arg)
111+
if strings.EqualFold(platformUser, platformID) {
112+
logrus.Infof("Found possible match for reference %s -> %s", platformUser, platformID)
113+
toks = strings.Split(platformID, ":")
114+
foundPlatforms = append(foundPlatforms, platformID)
79115
}
116+
}
117+
// replace the returned Reference only if only one occurrence is found,
118+
// otherwise return an error to the user because we don't know on which platform operate
119+
if len(foundPlatforms) == 1 {
80120
ret.PackageName = toks[0]
81-
if toks[1] == "" {
82-
return nil, fmt.Errorf(tr("invalid empty core architecture '%s'"), arg)
83-
}
84121
ret.Architecture = toks[1]
122+
} else {
123+
return nil, &arduino.MultiplePlatformsError{Platforms: foundPlatforms, UserPlatform: arg}
85124
}
86-
87125
return ret, nil
88126
}

cli/arguments/reference_test.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"testing"
2020

2121
"github.com/arduino/arduino-cli/cli/arguments"
22+
"github.com/arduino/arduino-cli/configuration"
2223
"github.com/stretchr/testify/assert"
2324
"github.com/stretchr/testify/require"
2425
)
@@ -45,6 +46,10 @@ var badCores = []struct {
4546
{"", nil},
4647
}
4748

49+
func init() {
50+
configuration.Settings = configuration.Init("")
51+
}
52+
4853
func TestArgsStringify(t *testing.T) {
4954
for _, core := range goodCores {
5055
require.Equal(t, core.in, core.expected.String())
@@ -53,13 +58,13 @@ func TestArgsStringify(t *testing.T) {
5358

5459
func TestParseReferenceCores(t *testing.T) {
5560
for _, tt := range goodCores {
56-
actual, err := arguments.ParseReference(tt.in, true)
61+
actual, err := arguments.ParseReference(tt.in)
5762
assert.Nil(t, err)
5863
assert.Equal(t, tt.expected, actual)
5964
}
6065

6166
for _, tt := range badCores {
62-
actual, err := arguments.ParseReference(tt.in, true)
67+
actual, err := arguments.ParseReference(tt.in)
6368
require.NotNil(t, err, "Testing bad core '%s'", tt.in)
6469
require.Equal(t, tt.expected, actual, "Testing bad core '%s'", tt.in)
6570
}
@@ -71,7 +76,7 @@ func TestParseArgs(t *testing.T) {
7176
input = append(input, tt.in)
7277
}
7378

74-
refs, err := arguments.ParseReferences(input, true)
79+
refs, err := arguments.ParseReferences(input)
7580
assert.Nil(t, err)
7681
assert.Equal(t, len(goodCores), len(refs))
7782

cli/cli.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func createCliCommandTree(cmd *cobra.Command) {
116116
cmd.RegisterFlagCompletionFunc("log-format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
117117
return validLogFormats, cobra.ShellCompDirectiveDefault
118118
})
119-
validOutputFormats := []string{"text", "json", "jsonmini"}
119+
validOutputFormats := []string{"text", "json", "jsonmini", "yaml"}
120120
cmd.PersistentFlags().StringVar(&outputFormat, "format", "text", tr("The output format for the logs, can be: %s", strings.Join(validOutputFormats, ", ")))
121121
cmd.RegisterFlagCompletionFunc("format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
122122
return validOutputFormats, cobra.ShellCompDirectiveDefault
@@ -148,6 +148,7 @@ func parseFormatString(arg string) (feedback.OutputFormat, bool) {
148148
"json": feedback.JSON,
149149
"jsonmini": feedback.JSONMini,
150150
"text": feedback.Text,
151+
"yaml": feedback.YAML,
151152
}[strings.ToLower(arg)]
152153

153154
return f, found

cli/compile/compile.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,9 @@ func runCompileCommand(cmd *cobra.Command, args []string) {
199199
var compileRes *rpc.CompileResponse
200200
var compileError error
201201
if output.OutputFormat == "json" {
202-
compileRes, compileError = compile.Compile(context.Background(), compileRequest, compileStdOut, compileStdErr, verboseCompile)
202+
F438 compileRes, compileError = compile.Compile(context.Background(), compileRequest, compileStdOut, compileStdErr, nil, verboseCompile)
203203
} else {
204-
compileRes, compileError = compile.Compile(context.Background(), compileRequest, os.Stdout, os.Stderr, verboseCompile)
204+
compileRes, compileError = compile.Compile(context.Background(), compileRequest, os.Stdout, os.Stderr, nil, verboseCompile)
205205
}
206206

207207
if compileError == nil && uploadAfterCompile {

cli/core/download.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) {
5353

5454
logrus.Info("Executing `arduino-cli core download`")
5555

56-
platformsRefs, err := arguments.ParseReferences(args, true)
56+
platformsRefs, err := arguments.ParseReferences(args)
5757
if err != nil {
5858
feedback.Errorf(tr("Invalid argument passed: %v"), err)
5959
os.Exit(errorcodes.ErrBadArgument)

cli/core/install.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) {
6161
inst := instance.CreateAndInit()
6262
logrus.Info("Executing `arduino-cli core install`")
6363

64-
platformsRefs, err := arguments.ParseReferences(args, true)
64+
platformsRefs, err := arguments.ParseReferences(args)
6565
if err != nil {
6666
feedback.Errorf(tr("Invalid argument passed: %v"), err)
6767
os.Exit(errorcodes.ErrBadArgument)

cli/core/uninstall.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) {
5050
inst := instance.CreateAndInit()
5151
logrus.Info("Executing `arduino-cli core uninstall`")
5252

53-
platformsRefs, err := arguments.ParseReferences(args, true)
53+
platformsRefs, err := arguments.ParseReferences(args)
5454
if err != nil {
5555
feedback.Errorf(tr("Invalid argument passed: %v"), err)
5656
os.Exit(errorcodes.ErrBadArgument)

cli/core/upgrade.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func runUpgradeCommand(cmd *cobra.Command, args []string) {
7676

7777
// proceed upgrading, if anything is upgradable
7878
exitErr := false
79-
platformsRefs, err := arguments.ParseReferences(args, true)
79+
platformsRefs, err := arguments.ParseReferences(args)
8080
if err != nil {
8181
feedback.Errorf(tr("Invalid argument passed: %v"), err)
8282
os.Exit(errorcodes.ErrBadArgument)

cli/feedback/feedback.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"io"
2323
"os"
2424

25+
"gopkg.in/yaml.v2"
26+
2527
"github.com/arduino/arduino-cli/i18n"
2628
"github.com/sirupsen/logrus"
2729
"google.golang.org/grpc/status"
@@ -37,6 +39,8 @@ const (
3739
JSON
3840
// JSONMini is identical to JSON but without whitespaces
3941
JSONMini
42+
// YAML means YAML format
43+
YAML
4044
)
4145

4246
// Result is anything more complex than a sentence that needs to be printed
@@ -109,9 +113,12 @@ func (fb *Feedback) Printf(format string, v ...interface{}) {
109113

110114
// Print behaves like fmt.Print but writes on the out writer and adds a newline.
111115
func (fb *Feedback) Print(v interface{}) {
112-
if fb.format == JSON || fb.format == JSONMini {
116+
switch fb.format {
117+
case JSON, JSONMini:
113118
fb.printJSON(v)
114-
} else {
119+
case YAML:
120+
fb.printYAML(v)
121+
default:
115122
fmt.Fprintln(fb.out, v)
116123
}
117124
}
@@ -156,13 +163,27 @@ func (fb *Feedback) printJSON(v interface{}) {
156163
}
157164
}
158165

166+
// printYAML is a convenient wrapper to provide feedback by printing the
167+
// desired output in YAML format. It adds a newline to the output.
168+
func (fb *Feedback) printYAML(v interface{}) {
169+
d, err := yaml.Marshal(v)
170+
if err != nil {
171+
fb.Errorf(tr("Error during YAML encoding of the output: %v"), err)
172+
return
173+
}
174+
fmt.Fprintf(fb.out, "%v\n", string(d))
175+
}
176+
159177
// PrintResult is a convenient wrapper to provide feedback for complex data,
160178
// where the contents can't be just serialized to JSON but requires more
161179
// structure.
162180
func (fb *Feedback) PrintResult(res Result) {
163-
if fb.format == JSON || fb.format == JSONMini {
181+
switch fb.format {
182+
case JSON, JSONMini:
164183
fb.printJSON(res.Data())
165-
} else {
184+
case YAML:
185+
fb.printYAML(res.Data())
186+
default:
166187
fb.Print(fmt.Sprintf("%s", res))
167188
}
168189
}

cli/version/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func runVersionCommand(cmd *cobra.Command, args []string) {
6161
latestVersion := updater.ForceCheckForUpdate(currentVersion)
6262

6363
versionInfo := globals.VersionInfo
64-
if f := feedback.GetFormat(); (f == feedback.JSON || f == feedback.JSONMini) && latestVersion != nil {
64+
if f := feedback.GetFormat(); (f == feedback.JSON || f == feedback.JSONMini || f == feedback.YAML) && latestVersion != nil {
6565
// Set this only we managed to get the latest version
6666
versionInfo.LatestVersion = latestVersion.String()
6767
}

0 commit comments

Comments
 (0)
0