Skip to content

Commit ab96ed6

Browse files
Add profile lib add command
It adds one or multiple libraries to the specified profile.
1 parent c282cc6 commit ab96ed6

File tree

7 files changed

+657
-228
lines changed

7 files changed

+657
-228
lines changed

commands/cmderrors/cmderrors.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,3 +883,15 @@ func (e *InstanceNeedsReinitialization) GRPCStatus() *status.Status {
883883
WithDetails(&rpc.InstanceNeedsReinitializationError{})
884884
return st
885885
}
886+
887+
// MissingProfileError is returned when the Profile is mandatory and not specified
888+
type MissingProfileError struct{}
889+
890+
func (e *MissingProfileError) Error() string {
891+
return i18n.Tr("Missing Profile name")
892+
}
893+
894+
// GRPCStatus converts the error into a *status.Status
895+
func (e *MissingProfileError) GRPCStatus() *status.Status {
896+
return status.New(codes.InvalidArgument, e.Error())
897+
}

commands/service_profile_lib_add.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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 [email protected].
15+
16+
package commands
17+
18+
import (
19+
"context"
20+
21+
"github.com/arduino/arduino-cli/commands/cmderrors"
22+
"github.com/arduino/arduino-cli/commands/internal/instances"
23+
"github.com/arduino/arduino-cli/internal/arduino/sketch"
24+
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
25+
paths "github.com/arduino/go-paths-helper"
26+
)
27+
28+
func (s *arduinoCoreServerImpl) ProfileLibAdd(ctx context.Context, req *rpc.ProfileLibAddRequest) (*rpc.ProfileLibAddResponse, error) {
29+
sketchPath := paths.New(req.GetSketchPath())
30+
projectFilePath, err := sketchPath.Join("sketch.yaml").Abs()
31+
if err != nil {
32+
return nil, err
33+
}
34+
35+
if req.GetProfileName() == "" {
36+
return nil, &cmderrors.MissingProfileError{}
37+
}
38+
39+
// Returns an error if the main file is missing from the sketch so there is no need to check if the path exists
40+
sk, err := sketch.New(sketchPath)
41+
if err != nil {
42+
return nil, err
43+
}
44+
45+
profile, err := sk.GetProfile(req.ProfileName)
46+
if err != nil {
47+
return nil, err
48+
}
49+
50+
newLib := &sketch.ProfileLibraryReference{Library: req.GetLibName()}
51+
// Obtain the library index from the manager
52+
li, err := instances.GetLibrariesIndex(req.GetInstance())
53+
if err != nil {
54+
return nil, err
55+
}
56+
version, err := parseVersion(req.LibVersion)
57+
if err != nil {
58+
return nil, err
59+
}
60+
libRelease, err := li.FindRelease(req.GetLibName(), version)
61+
if err != nil {
62+
return nil, err
63+
}
64+
newLib.Version = libRelease.GetVersion()
65+
66+
profile.Libraries = append(profile.Libraries, newLib)
67+
68+
err = projectFilePath.WriteFile([]byte(sk.Project.AsYaml()))
69+
if err != nil {
70+
return nil, err
71+
}
72+
73+
return &rpc.ProfileLibAddResponse{ProjectFilePath: projectFilePath.String()}, nil
74+
}

internal/cli/profile/lib.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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 [email protected].
15+
16+
package profile
17+
18+
import (
19+
"context"
20+
"fmt"
21+
"os"
22+
23+
"github.com/arduino/arduino-cli/internal/cli/arguments"
24+
"github.com/arduino/arduino-cli/internal/cli/feedback"
25+
"github.com/arduino/arduino-cli/internal/cli/instance"
26+
"github.com/arduino/arduino-cli/internal/cli/lib"
27+
"github.com/arduino/arduino-cli/internal/i18n"
28+
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
29+
"github.com/spf13/cobra"
30+
)
31+
32+
func initLibCommand(srv rpc.ArduinoCoreServiceServer) *cobra.Command {
33+
libCommand := &cobra.Command{
34+
Use: "lib",
35+
Short: i18n.Tr("Profile commands about libraries."),
36+
Long: i18n.Tr("Profile commands about libraries."),
37+
Example: "" +
38+
" " + os.Args[0] + " profile lib add AudioZero -m my_profile\n" +
39+
" " + os.Args[0] + " profile lib remove Arduino_JSON --profile my_profile\n",
40+
}
41+
42+
libCommand.AddCommand(initLibAddCommand(srv))
43+
44+
return libCommand
45+
}
46+
47+
func initLibAddCommand(srv rpc.ArduinoCoreServiceServer) *cobra.Command {
48+
var destDir string
49+
50+
addCommand := &cobra.Command{
51+
Use: fmt.Sprintf("add %s[@%s]...", i18n.Tr("LIBRARY"), i18n.Tr("VERSION_NUMBER")),
52+
Short: i18n.Tr("Adds a library to the profile."),
53+
Long: i18n.Tr("Adds a library to the profile."),
54+
Example: "" +
55+
" " + os.Args[0] + " profile lib add AudioZero -m my_profile\n" +
56+
" " + os.Args[0] + " profile lib add [email protected] --profile my_profile\n",
57+
Args: cobra.MinimumNArgs(1),
58+
Run: func(cmd *cobra.Command, args []string) {
59+
runLibAddCommand(cmd.Context(), args, srv, destDir)
60+
},
61+
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
62+
return arguments.GetInstallableLibs(cmd.Context(), srv), cobra.ShellCompDirectiveDefault
63+
},
64+
}
65+
66+
addCommand.Flags().StringVar(&destDir, "dest-dir", "", i18n.Tr("Location of the project file."))
67+
profileArg.AddToCommand(addCommand, srv)
68+
69+
return addCommand
70+
}
71+
72+
func runLibAddCommand(ctx context.Context, args []string, srv rpc.ArduinoCoreServiceServer, destDir string) {
73+
sketchPath := arguments.InitSketchPath(destDir)
74+
75+
instance := instance.CreateAndInit(ctx, srv)
76+
libRefs, err := lib.ParseLibraryReferenceArgsAndAdjustCase(ctx, srv, instance, args)
77+
if err != nil {
78+
feedback.Fatal(i18n.Tr("Arguments error: %v", err), feedback.ErrBadArgument)
79+
}
80+
for _, lib := range libRefs {
81+
_, err := srv.ProfileLibAdd(ctx, &rpc.ProfileLibAddRequest{
82+
Instance: instance,
83+
SketchPath: sketchPath.String(),
84+
ProfileName: profileArg.Get(),
85+
LibName: lib.Name,
86+
LibVersion: lib.Version,
87+
})
88+
if err != nil {
89+
feedback.Fatal(i18n.Tr("Error adding %s to the profile %s: %v", lib.Name, profileArg.Get(), err), feedback.ErrGeneric)
90+
}
91+
}
92+
93+
feedback.Printf("Lib added: %s", sketchPath.String())
94+
}

internal/cli/profile/profile.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ func NewCommand(srv rpc.ArduinoCoreServiceServer) *cobra.Command {
3838
}
3939

4040
profileCommand.AddCommand(initInitCommand(srv))
41+
profileCommand.AddCommand(initLibCommand(srv))
4142

4243
return profileCommand
4344
}

0 commit comments

Comments
 (0)