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 6076d14

Browse files
MatteoPologrutocmaglie
andauthored
Add first set of profile commands (#2917)
* Improved handling of ProfileLibraryReference results * Implementation of profile commands * Improved some help description * Moved args into their correct place * Added remove deps * Fixed completion in profile lib remove * Rename 'profile init' -> 'profile create' * Proper behaviour for 'profile create' command * Added profile management integration tests * Rename --dest-dir to --sketch-path * Fixed json output for 'profile set-default' command --------- Co-authored-by: Cristian Maglie <c.maglie@arduino.cc>
1 parent 6756f78 commit 6076d14

File tree

12 files changed

+866
-104
lines changed

12 files changed

+866
-104
lines changed

‎commands/service_profile_create.go‎

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2025 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 commands
17+
18+
import (
19+
"context"
20+
"errors"
21+
"fmt"
22+
23+
"github.com/arduino/arduino-cli/commands/cmderrors"
24+
"github.com/arduino/arduino-cli/commands/internal/instances"
25+
"github.com/arduino/arduino-cli/internal/arduino/sketch"
26+
"github.com/arduino/arduino-cli/internal/i18n"
27+
"github.com/arduino/arduino-cli/pkg/fqbn"
28+
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
29+
"github.com/arduino/go-paths-helper"
30+
)
31+
32+
// ProfileCreate creates a new project file if it does not exist. If a profile name with the associated FQBN is specified,
33+
// it is added to the project.
34+
func (s *arduinoCoreServerImpl) ProfileCreate(ctx context.Context, req *rpc.ProfileCreateRequest) (*rpc.ProfileCreateResponse, error) {
35+
if req.GetProfileName() == "" {
36+
return nil, &cmderrors.MissingProfileError{}
37+
}
38+
if req.GetFqbn() == "" {
39+
return nil, &cmderrors.MissingFQBNError{}
40+
}
41+
42+
// Returns an error if the main file is missing from the sketch so there is no need to check if the path exists
43+
sk, err := sketch.New(paths.New(req.GetSketchPath()))
44+
if err != nil {
45+
return nil, err
46+
}
47+
48+
fqbn, err := fqbn.Parse(req.GetFqbn())
49+
if err != nil {
50+
return nil, &cmderrors.InvalidFQBNError{Cause: err}
51+
}
52+
53+
// Check that the profile name is unique
54+
if profile, _ := sk.GetProfile(req.ProfileName); profile != nil {
55+
return nil, &cmderrors.ProfileAlreadyExitsError{Profile: req.ProfileName}
56+
}
57+
58+
pme, release, err := instances.GetPackageManagerExplorer(req.GetInstance())
59+
if err != nil {
60+
return nil, err
61+
}
62+
defer release()
63+
if pme.Dirty() {
64+
return nil, &cmderrors.InstanceNeedsReinitialization{}
65+
}
66+
67+
// Automatically detect the target platform if it is installed on the user's machine
68+
_, targetPlatform, _, _, _, err := pme.ResolveFQBN(fqbn)
69+
if err != nil {
70+
if targetPlatform == nil {
71+
return nil, &cmderrors.PlatformNotFoundError{
72+
Platform: fmt.Sprintf("%s:%s", fqbn.Vendor, fqbn.Architecture),
73+
Cause: errors.New(i18n.Tr("platform not installed")),
74+
}
75+
}
76+
return nil, &cmderrors.InvalidFQBNError{Cause: err}
77+
}
78+
79+
newProfile := &sketch.Profile{Name: req.GetProfileName(), FQBN: req.GetFqbn()}
80+
// TODO: what to do with the PlatformIndexURL?
81+
newProfile.Platforms = append(newProfile.Platforms, &sketch.ProfilePlatformReference{
82+
Packager: targetPlatform.Platform.Package.Name,
83+
Architecture: targetPlatform.Platform.Architecture,
84+
Version: targetPlatform.Version,
85+
})
86+
87+
sk.Project.Profiles = append(sk.Project.Profiles, newProfile)
88+
if req.DefaultProfile {
89+
sk.Project.DefaultProfile = newProfile.Name
90+
}
91+
92+
projectFilePath := sk.GetProjectPath()
93+
err = projectFilePath.WriteFile([]byte(sk.Project.AsYaml()))
94+
if err != nil {
95+
return nil, err
96+
}
97+
98+
return &rpc.ProfileCreateResponse{}, nil
99+
}

‎commands/service_profile_init.go‎

Lines changed: 0 additions & 104 deletions
This file was deleted.

‎internal/cli/arguments/completion.go‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
"github.com/arduino/arduino-cli/internal/cli/instance"
2222
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
23+
"github.com/arduino/go-paths-helper"
2324
"go.bug.st/f"
2425
)
2526

@@ -172,3 +173,19 @@ func GetAvailablePorts(ctx context.Context, srv rpc.ArduinoCoreServiceServer) []
172173
// Transform the data structure for the completion (DetectedPort -> Port)
173174
return f.Map(list.GetPorts(), (*rpc.DetectedPort).GetPort)
174175
}
176+
177+
// GetProfileLibraries is an helper function useful to autocomplete.
178+
// It returns a list of libraries present in the specified profile.
179+
func GetProfileLibraries(ctx context.Context, srv rpc.ArduinoCoreServiceServer, sketchPath *paths.Path, profile string) []string {
180+
resp, err := srv.ProfileLibList(ctx, &rpc.ProfileLibListRequest{
181+
SketchPath: sketchPath.String(),
182+
ProfileName: profile,
183+
})
184+
if err != nil {
185+
return nil
186+
}
187+
res := f.Map(resp.GetLibraries(), func(lib *rpc.ProfileLibraryReference) string {
188+
return lib.GetIndexLibrary().GetName()
189+
})
190+
return res
191+
}

‎internal/cli/cli.go‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"github.com/arduino/arduino-cli/internal/cli/lib"
3737
"github.com/arduino/arduino-cli/internal/cli/monitor"
3838
"github.com/arduino/arduino-cli/internal/cli/outdated"
39+
"github.com/arduino/arduino-cli/internal/cli/profile"
3940
"github.com/arduino/arduino-cli/internal/cli/sketch"
4041
"github.com/arduino/arduino-cli/internal/cli/update"
4142
"github.com/arduino/arduino-cli/internal/cli/updater"
@@ -162,6 +163,7 @@ func NewCommand(srv rpc.ArduinoCoreServiceServer) *cobra.Command {
162163
cmd.AddCommand(burnbootloader.NewCommand(srv))
163164
cmd.AddCommand(version.NewCommand(srv))
164165
cmd.AddCommand(feedback.NewCommand())
166+
cmd.AddCommand(profile.NewCommand(srv))
165167

166168
cmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, i18n.Tr("Print the logs on the standard output."))
167169
cmd.Flag("verbose").Hidden = true

‎internal/cli/feedback/result/rpc.go‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,12 @@ type ProfileLibraryReference_LocalLibraryResult struct {
11301130
Path string `json:"path,omitempty"`
11311131
}
11321132

1133+
func (*ProfileLibraryReference_LocalLibraryResult) isProfileLibraryReference() {}
1134+
1135+
func (l *ProfileLibraryReference_LocalLibraryResult) String() string {
1136+
return fmt.Sprintf("lib: %s", l.Path)
1137+
}
1138+
11331139
func NewProfileLibraryReference_LocalLibraryResult(resp *rpc.ProfileLibraryReference_LocalLibrary) *ProfileLibraryReference_LocalLibraryResult {
11341140
return &ProfileLibraryReference_LocalLibraryResult{
11351141
Path: resp.GetPath(),
@@ -1142,10 +1148,49 @@ type ProfileLibraryReference_IndexLibraryResult struct {
11421148
IsDependency bool `json:"is_dependency,omitempty"`
11431149
}
11441150

1151+
func (*ProfileLibraryReference_IndexLibraryResult) isProfileLibraryReference() {}
1152+
1153+
func (l *ProfileLibraryReference_IndexLibraryResult) String() string {
1154+
if l.IsDependency {
1155+
return fmt.Sprintf("dependency: %s@%s", l.Name, l.Version)
1156+
}
1157+
return fmt.Sprintf("%s@%s", l.Name, l.Version)
1158+
}
1159+
11451160
func NewProfileLibraryReference_IndexLibraryResult(resp *rpc.ProfileLibraryReference_IndexLibrary) *ProfileLibraryReference_IndexLibraryResult {
11461161
return &ProfileLibraryReference_IndexLibraryResult{
11471162
Name: resp.GetName(),
11481163
Version: resp.GetVersion(),
11491164
IsDependency: resp.GetIsDependency(),
11501165
}
11511166
}
1167+
1168+
type ProfileLibraryReference struct {
1169+
Kind string `json:"kind,omitempty"`
1170+
Library ProfileLibraryReference_Library `json:"library,omitempty"`
1171+
}
1172+
1173+
type ProfileLibraryReference_Library interface {
1174+
isProfileLibraryReference()
1175+
fmt.Stringer
1176+
}
1177+
1178+
func NewProfileLibraryReference(resp *rpc.ProfileLibraryReference) *ProfileLibraryReference {
1179+
if lib := resp.GetIndexLibrary(); lib != nil {
1180+
return &ProfileLibraryReference{
1181+
Library: NewProfileLibraryReference_IndexLibraryResult(lib),
1182+
Kind: "index",
1183+
}
1184+
}
1185+
if lib := resp.GetLocalLibrary(); lib != nil {
1186+
return &ProfileLibraryReference{
1187+
Library: NewProfileLibraryReference_LocalLibraryResult(lib),
1188+
Kind: "local",
1189+
}
1190+
}
1191+
return nil
1192+
}
1193+
1194+
func (p *ProfileLibraryReference) String() string {
1195+
return p.Library.String()
1196+
}

‎internal/cli/profile/profile.go‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2025 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 profile
17+
18+
import (
19+
"os"
20+
21+
"github.com/arduino/arduino-cli/internal/i18n"
22+
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
23+
"github.com/spf13/cobra"
24+
)
25+
26+
func NewCommand(srv rpc.ArduinoCoreServiceServer) *cobra.Command {
27+
profileCommand := &cobra.Command{
28+
Use: "profile",
29+
Short: i18n.Tr("Build profile operations."),
30+
Long: i18n.Tr("Build profile operations."),
31+
Example: " " + os.Args[0] + " profile init",
32+
}
33+
34+
profileCommand.AddCommand(initProfileCreateCommand(srv))
35+
profileCommand.AddCommand(initProfileLibCommand(srv))
36+
profileCommand.AddCommand(initProfileSetDefaultCommand(srv))
37+
return profileCommand
38+
}

0 commit comments

Comments
(0)

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