Skip to content

Commit 12868a5

Browse files
committed
Deamon implementation and refactoring
1 parent 015f0d7 commit 12868a5

26 files changed

+1344
-1662
lines changed

cli/board/details.go

+17-6
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@
1818
package board
1919

2020
import (
21+
"context"
2122
"fmt"
2223

2324
"github.com/arduino/arduino-cli/cli"
24-
b "github.com/arduino/arduino-cli/commands/board"
25+
"github.com/arduino/arduino-cli/commands/board"
26+
"github.com/arduino/arduino-cli/common/formatter"
2527
"github.com/arduino/arduino-cli/output"
28+
"github.com/arduino/arduino-cli/rpc"
2629
"github.com/spf13/cobra"
2730
)
2831

@@ -39,15 +42,23 @@ func initDetailsCommand() *cobra.Command {
3942
}
4043

4144
func runDetailsCommand(cmd *cobra.Command, args []string) {
42-
pm := cli.InitPackageManager()
43-
res := b.Details(pm, &b.DetailsReq{Fqbn: args[0]})
45+
instance := cli.CreateInstance()
4446

45-
if !cli.OutputJSON(res) {
46-
outputDetailsResp(res)
47+
res := board.BoardDetails(context.Background(), &rpc.BoardDetailsReq{
48+
Instance: instance,
49+
Fqbn: args[0],
50+
})
51+
52+
if cli.OutputJSONOrElse(res) {
53+
if res.GetResult().Success() {
54+
outputDetailsResp(res)
55+
} else {
56+
formatter.PrintError(res.Result, "")
57+
}
4758
}
4859
}
4960

50-
func outputDetailsResp(details *b.DetailsResp) {
61+
func outputDetailsResp(details *rpc.BoardDetailsResp) {
5162
table := output.NewTable()
5263
table.SetColumnWidthMode(1, output.Average)
5364
table.AddRow("Board name:", details.Name)

cli/commands.go renamed to cli/cli.go

+53-70
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,21 @@
1818
package cli
1919

2020
import (
21+
"context"
2122
"encoding/json"
2223
"fmt"
2324
"os"
2425
"path/filepath"
2526

26-
paths "github.com/arduino/go-paths-helper"
27+
"github.com/arduino/arduino-cli/commands"
2728

28-
"github.com/arduino/arduino-cli/arduino/libraries"
29+
"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
2930
"github.com/arduino/arduino-cli/arduino/libraries/librariesmanager"
3031
"github.com/arduino/arduino-cli/arduino/sketches"
31-
"github.com/arduino/arduino-cli/configs"
32-
33-
"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
3432
"github.com/arduino/arduino-cli/common/formatter"
33+
"github.com/arduino/arduino-cli/configs"
34+
"github.com/arduino/arduino-cli/rpc"
35+
paths "github.com/arduino/go-paths-helper"
3536
"github.com/sirupsen/logrus"
3637
)
3738

@@ -63,20 +64,20 @@ var GlobalFlags struct {
6364
OutputJSON bool // true output in JSON, false output as Text
6465
}
6566

66-
// OutputJSON outputs the JSON encoding of v if the JSON output format has been
67-
// selected by the user and returns true. Otherwise no output is produced and the
68-
// function returns false.
69-
func OutputJSON(v interface{}) bool {
67+
// OutputJSONOrElse outputs the JSON encoding of v if the JSON output format has been
68+
// selected by the user and returns false. Otherwise no output is produced and the
69+
// function returns true.
70+
func OutputJSONOrElse(v interface{}) bool {
7071
if !GlobalFlags.OutputJSON {
71-
return false
72+
return true
7273
}
7374
d, err := json.MarshalIndent(v, "", " ")
7475
if err != nil {
7576
formatter.PrintError(err, "Error during JSON encoding of the output")
7677
os.Exit(ErrGeneric)
7778
}
7879
fmt.Print(string(d))
79-
return true
80+
return false
8081
}
8182

8283
// AppName is the command line name of the Arduino CLI executable
@@ -95,78 +96,60 @@ func InitPackageManagerWithoutBundles() *packagemanager.PackageManager {
9596
return InitPackageManager()
9697
}
9798

98-
// InitPackageManager initializes the PackageManager
99-
// TODO: for the daemon mode, this might be called at startup, but for now only commands needing the PM will call it
100-
func InitPackageManager() *packagemanager.PackageManager {
101-
logrus.Info("Initializing package manager")
102-
103-
pm := packagemanager.NewPackageManager(
104-
Config.IndexesDir(),
105-
Config.PackagesDir(),
106-
Config.DownloadsDir(),
107-
Config.DataDir.Join("tmp"))
108-
99+
func packageManagerInitReq() *rpc.InitReq {
100+
urls := []string{}
109101
for _, URL := range Config.BoardManagerAdditionalUrls {
110-
if err := pm.LoadPackageIndex(URL); err != nil {
111-
formatter.PrintError(err, "Failed to load "+URL.String()+" package index.\n"+
112-
"Try updating all indexes with `"+AppName+" core update-index`.")
113-
os.Exit(ErrCoreConfig)
114-
}
102+
urls = append(urls, URL.String())
115103
}
116104

117-
if err := pm.LoadHardware(Config); err != nil {
118-
formatter.PrintError(err, "Error loading hardware packages.")
119-
os.Exit(ErrCoreConfig)
105+
req := &rpc.InitReq{
106+
Configuration: &rpc.Configuration{
107+
DataDir: Config.DataDir.String(),
108+
DownloadsDir: Config.DownloadsDir().String(),
109+
BoardManagerAdditionalUrls: urls,
110+
},
120111
}
121-
122-
return pm
112+
return req
123113
}
124114

125-
// InitLibraryManager initializes the LibraryManager using the underlying packagemanager
126-
func InitLibraryManager(cfg *configs.Configuration, pm *packagemanager.PackageManager) *librariesmanager.LibrariesManager {
127-
logrus.Info("Starting libraries manager")
128-
lm := librariesmanager.NewLibraryManager(
129-
cfg.IndexesDir(),
130-
Config.DownloadsDir())
131-
132-
// Add IDE builtin libraries dir
133-
if bundledLibsDir := Config.IDEBundledLibrariesDir(); bundledLibsDir != nil {
134-
lm.AddLibrariesDir(bundledLibsDir, libraries.IDEBuiltIn)
115+
// CreateInstance creates and return an instance of the Arduino Core engine
116+
func CreateInstance() *rpc.Instance {
117+
logrus.Info("Initializing package manager")
118+
resp, err := commands.Init(context.Background(), packageManagerInitReq())
119+
if err != nil {
120+
formatter.PrintError(err, "Error initializing package manager")
121+
os.Exit(rpc.ErrGeneric)
135122
}
123+
return resp.GetInstance()
124+
}
136125

137-
// Add sketchbook libraries dir
138-
lm.AddLibrariesDir(Config.LibrariesDir(), libraries.Sketchbook)
139-
140-
// Add libraries dirs from installed platforms
141-
if pm != nil {
142-
for _, targetPackage := range pm.GetPackages().Packages {
143-
for _, platform := range targetPackage.Platforms {
144-
if platformRelease := pm.GetInstalledPlatformRelease(platform); platformRelease != nil {
145-
lm.AddPlatformReleaseLibrariesDir(platformRelease, libraries.PlatformBuiltIn)
146-
}
147-
}
148-
}
126+
// InitPackageManager initializes the PackageManager
127+
// TODO: for the daemon mode, this might be called at startup, but for now only commands needing the PM will call it
128+
func InitPackageManager() *packagemanager.PackageManager {
129+
logrus.Info("Initializing package manager")
130+
resp, err := commands.Init(context.Background(), packageManagerInitReq())
131+
if err != nil {
132+
formatter.PrintError(err, "Error initializing package manager")
133+
os.Exit(rpc.ErrGeneric)
149134
}
135+
return commands.GetPackageManager(resp)
136+
}
150137

151-
// Auto-update index if needed
152-
if err := lm.LoadIndex(); err != nil {
153-
logrus.WithError(err).Warn("Error during libraries index loading, trying to auto-update index")
154-
UpdateLibrariesIndex(lm)
155-
}
156-
if err := lm.LoadIndex(); err != nil {
157-
logrus.WithError(err).Error("Error during libraries index loading")
158-
formatter.PrintError(err, "Error loading libraries index")
159-
os.Exit(ErrGeneric)
138+
// InitLibraryManager initializes the LibraryManager. If pm is nil, the library manager will not handle core-libraries.
139+
// TODO: for the daemon mode, this might be called at startup, but for now only commands needing the PM will call it
140+
func InitLibraryManager(cfg *configs.Configuration, pm *packagemanager.PackageManager) *librariesmanager.LibrariesManager {
141+
req := packageManagerInitReq()
142+
if pm == nil {
143+
req.LibraryManagerOnly = true
160144
}
161145

162-
// Scan for libraries
163-
if err := lm.RescanLibraries(); err != nil {
164-
logrus.WithError(err).Error("Error during libraries rescan")
165-
formatter.PrintError(err, "Error during libraries rescan")
166-
os.Exit(ErrGeneric)
146+
logrus.Info("Initializing library manager")
147+
resp, err := commands.Init(context.Background(), req)
148+
if err != nil {
149+
formatter.PrintError(err, "Error initializing library manager")
150+
os.Exit(rpc.ErrGeneric)
167151
}
168-
169-
return lm
152+
return commands.GetLibraryManager(resp)
170153
}
171154

172155
// UpdateLibrariesIndex updates the library_index.json
File renamed without changes.

cli/daemon/daemon.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
3+
package daemon
4+
5+
import (
6+
"fmt"
7+
"log"
8+
"net"
9+
10+
"github.com/arduino/arduino-cli/cli"
11+
"github.com/arduino/arduino-cli/daemon"
12+
"github.com/arduino/arduino-cli/rpc"
13+
"github.com/spf13/cobra"
14+
"google.golang.org/grpc"
15+
)
16+
17+
// InitCommand initalize the command
18+
func InitCommand() *cobra.Command {
19+
cmd := &cobra.Command{
20+
Use: "daemon",
21+
Short: "Run as a daemon",
22+
Long: "Running as a daemon the initialization of cores and libraries is done only once.",
23+
Example: " " + cli.AppName + " daemon",
24+
Args: cobra.NoArgs,
25+
Run: runDaemonCommand,
26+
Hidden: true,
27+
}
28+
return cmd
29+
}
30+
31+
const (
32+
port = ":50051"
33+
)
34+
35+
func runDaemonCommand(cmd *cobra.Command, args []string) {
36+
lis, err := net.Listen("tcp", port)
37+
if err != nil {
38+
log.Fatalf("failed to listen: %v", err)
39+
}
40+
s := grpc.NewServer()
41+
rpc.RegisterArduinoCoreServer(s, &daemon.ArduinoCoreServerImpl{})
42+
if err := s.Serve(lis); err != nil {
43+
log.Fatalf("failed to serve: %v", err)
44+
}
45+
fmt.Println("Done serving")
46+
}

0 commit comments

Comments
 (0)