Skip to content

Commit 875cb3c

Browse files
committed
Refactoring 'compile' commands
1 parent 13bd4f1 commit 875cb3c

File tree

4 files changed

+80
-33
lines changed

4 files changed

+80
-33
lines changed

arduino/libraries/libraries.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func (library *Library) ToRPCLibrary() (*rpc.Library, error) {
111111
var err error
112112
headers, err = library.SourceHeaders()
113113
if err != nil {
114-
return nil, fmt.Errorf(tr("gathering library headers: %w"), err)
114+
return nil, fmt.Errorf(tr("reading library headers: %w"), err)
115115
}
116116
}
117117

cli/compile/compile.go

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
"github.com/arduino/arduino-cli/cli/output"
3030
"github.com/arduino/arduino-cli/configuration"
3131
"github.com/arduino/arduino-cli/i18n"
32-
"google.golang.org/grpc/status"
3332

3433
"github.com/arduino/arduino-cli/cli/errorcodes"
3534
"github.com/arduino/arduino-cli/cli/instance"
@@ -179,18 +178,18 @@ func run(cmd *cobra.Command, args []string) {
179178
SourceOverride: overrides,
180179
Library: library,
181180
}
182-
compileOut := new(bytes.Buffer)
183-
compileErr := new(bytes.Buffer)
181+
compileStdOut := new(bytes.Buffer)
182+
compileStdErr := new(bytes.Buffer)
184183
verboseCompile := configuration.Settings.GetString("logging.level") == "debug"
185184
var compileRes *rpc.CompileResponse
186-
var st *status.Status
185+
var compileError error
187186
if output.OutputFormat == "json" {
188-
compileRes, st = compile.Compile(context.Background(), compileRequest, compileOut, compileErr, verboseCompile)
187+
compileRes, compileError = compile.Compile(context.Background(), compileRequest, compileStdOut, compileStdErr, verboseCompile)
189188
} else {
190-
compileRes, st = compile.Compile(context.Background(), compileRequest, os.Stdout, os.Stderr, verboseCompile)
189+
compileRes, compileError = compile.Compile(context.Background(), compileRequest, os.Stdout, os.Stderr, verboseCompile)
191190
}
192191

193-
if st == nil && uploadAfterCompile {
192+
if compileError == nil && uploadAfterCompile {
194193
var sk *sketch.Sketch
195194
sk, err := sketch.New(sketchPath)
196195
if err != nil {
@@ -248,13 +247,13 @@ func run(cmd *cobra.Command, args []string) {
248247
}
249248

250249
feedback.PrintResult(&compileResult{
251-
CompileOut: compileOut.String(),
252-
CompileErr: compileErr.String(),
250+
CompileOut: compileStdOut.String(),
251+
CompileErr: compileStdErr.String(),
253252
BuilderResult: compileRes,
254-
Success: st == nil,
253+
Success: compileError == nil,
255254
})
256-
if st != nil && output.OutputFormat != "json" {
257-
feedback.Errorf(tr("Error during build: %v"), st.Message())
255+
if compileError != nil && output.OutputFormat != "json" {
256+
feedback.Errorf(tr("Error during build: %v"), compileError)
258257
os.Exit(errorcodes.ErrGeneric)
259258
}
260259
}

commands/compile/compile.go

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package compile
1717

1818
import (
1919
"context"
20+
"errors"
2021
"io"
2122
"path/filepath"
2223
"sort"
@@ -37,17 +38,14 @@ import (
3738
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
3839
paths "github.com/arduino/go-paths-helper"
3940
properties "github.com/arduino/go-properties-orderedmap"
40-
"github.com/pkg/errors"
4141
"github.com/segmentio/stats/v4"
4242
"github.com/sirupsen/logrus"
43-
"google.golang.org/grpc/codes"
44-
"google.golang.org/grpc/status"
4543
)
4644

4745
var tr = i18n.Tr
4846

4947
// Compile FIXMEDOC
50-
func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream io.Writer, debug bool) (r *rpc.CompileResponse, e *status.Status) {
48+
func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream io.Writer, debug bool) (r *rpc.CompileResponse, e error) {
5149

5250
// There is a binding between the export binaries setting and the CLI flag to explicitly set it,
5351
// since we want this binding to work also for the gRPC interface we must read it here in this
@@ -91,29 +89,29 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
9189

9290
pm := commands.GetPackageManager(req.GetInstance().GetId())
9391
if pm == nil {
94-
return nil, status.New(codes.InvalidArgument, tr("Invalid instance"))
92+
return nil, &commands.InvalidInstanceError{}
9593
}
9694

9795
logrus.Tracef("Compile %s for %s started", req.GetSketchPath(), req.GetFqbn())
9896
if req.GetSketchPath() == "" {
99-
return nil, status.New(codes.InvalidArgument, tr("Missing sketch path"))
97+
return nil, &commands.MissingSketchPathError{}
10098
}
10199
sketchPath := paths.New(req.GetSketchPath())
102100
sk, err := sketch.New(sketchPath)
103101
if err != nil {
104-
return nil, status.Newf(codes.NotFound, tr("Error opening sketch: %s"), err)
102+
return nil, &commands.SketchNotFoundError{Cause: err}
105103
}
106104

107105
fqbnIn := req.GetFqbn()
108106
if fqbnIn == "" && sk != nil && sk.Metadata != nil {
109107
fqbnIn = sk.Metadata.CPU.Fqbn
110108
}
111109
if fqbnIn == "" {
112-
return nil, status.New(codes.InvalidArgument, tr("No FQBN (Fully Qualified Board Name) provided"))
110+
return nil, &commands.MissingFQBNError{}
113111
}
114112
fqbn, err := cores.ParseFQBN(fqbnIn)
115113
if err != nil {
116-
return nil, status.Newf(codes.InvalidArgument, tr("Invalid FQBN: %s"), err)
114+
return nil, &commands.InvalidFQBNError{Cause: err}
117115
}
118116

119117
targetPlatform := pm.FindPlatform(&packagemanager.PlatformReference{
@@ -126,7 +124,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
126124
// "\"%[1]s:%[2]s\" platform is not installed, please install it by running \""+
127125
// version.GetAppName()+" core install %[1]s:%[2]s\".", fqbn.Package, fqbn.PlatformArch)
128126
// feedback.Error(errorMessage)
129-
return nil, status.New(codes.NotFound, tr("Platform not installed"))
127+
return nil, &commands.PlatformNotFound{Platform: targetPlatform.String(), Cause: errors.New(tr("platform not installed"))}
130128
}
131129

132130
builderCtx := &types.Context{}
@@ -149,7 +147,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
149147
builderCtx.BuildPath = paths.New(req.GetBuildPath())
150148
}
151149
if err = builderCtx.BuildPath.MkdirAll(); err != nil {
152-
return nil, status.Newf(codes.PermissionDenied, tr("Cannot create build directory: %s"), err)
150+
return nil, &commands.PermissionDeniedError{Message: tr("Cannot create build directory"), Cause: err}
153151
}
154152
builderCtx.CompilationDatabase = bldr.NewCompilationDatabase(
155153
builderCtx.BuildPath.Join("compile_commands.json"),
@@ -179,7 +177,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
179177
builderCtx.BuildCachePath = paths.New(req.GetBuildCachePath())
180178
err = builderCtx.BuildCachePath.MkdirAll()
181179
if err != nil {
182-
return nil, status.Newf(codes.PermissionDenied, tr("Cannot create build cache directory: %s"), err)
180+
return nil, &commands.PermissionDeniedError{Message: tr("Cannot create build cache directory"), Cause: err}
183181
}
184182
}
185183

@@ -222,14 +220,22 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
222220

223221
// if --preprocess or --show-properties were passed, we can stop here
224222
if req.GetShowProperties() {
225-
return r, status.Convert(builder.RunParseHardwareAndDumpBuildProperties(builderCtx))
223+
compileErr := builder.RunParseHardwareAndDumpBuildProperties(builderCtx)
224+
if compileErr != nil {
225+
compileErr = &commands.CompileFailedError{Message: err.Error()}
226+
}
227+
return r, compileErr
226228
} else if req.GetPreprocess() {
227-
return r, status.Convert(builder.RunPreprocess(builderCtx))
229+
compileErr := builder.RunPreprocess(builderCtx)
230+
if compileErr != nil {
231+
compileErr = &commands.CompileFailedError{Message: err.Error()}
232+
}
233+
return r, compileErr
228234
}
229235

230236
// if it's a regular build, go on...
231237
if err := builder.RunBuilder(builderCtx); err != nil {
232-
return r, status.Convert(err)
238+
return r, &commands.CompileFailedError{Message: err.Error()}
233239
}
234240

235241
// If the export directory is set we assume you want to export the binaries
@@ -251,17 +257,17 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
251257
}
252258
logrus.WithField("path", exportPath).Trace("Saving sketch to export path.")
253259
if err := exportPath.MkdirAll(); err != nil {
254-
return r, status.New(codes.PermissionDenied, errors.Wrap(err, tr("Error creating output dir")).Error())
260+
return r, &commands.PermissionDeniedError{Message: tr("Error creating output dir"), Cause: err}
255261
}
256262

257263
// Copy all "sketch.ino.*" artifacts to the export directory
258264
baseName, ok := builderCtx.BuildProperties.GetOk("build.project_name") // == "sketch.ino"
259265
if !ok {
260-
return r, status.New(codes.Internal, tr("Missing 'build.project_name' build property"))
266+
return r, &commands.MissingPlatformPropertyError{Property: "build.project_name"}
261267
}
262268
buildFiles, err := builderCtx.BuildPath.ReadDir()
263269
if err != nil {
264-
return r, status.Newf(codes.PermissionDenied, tr("Error reading build directory: %s"), err)
270+
return r, &commands.PermissionDeniedError{Message: tr("Error reading build directory"), Cause: err}
265271
}
266272
buildFiles.FilterPrefix(baseName)
267273
for _, buildFile := range buildFiles {
@@ -271,7 +277,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
271277
WithField("dest", exportedFile).
272278
Trace("Copying artifact.")
273279
if err = buildFile.CopyTo(exportedFile); err != nil {
274-
return r, status.New(codes.PermissionDenied, tr("Error copying output file %[1]s: %[2]s", buildFile, err))
280+
return r, &commands.PermissionDeniedError{Message: tr("Error copying output file %s", buildFile), Cause: err}
275281
}
276282
}
277283
}
@@ -280,7 +286,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
280286
for _, lib := range builderCtx.ImportedLibraries {
281287
rpcLib, err := lib.ToRPCLibrary()
282288
if err != nil {
283-
return r, status.Newf(codes.PermissionDenied, tr("Error converting library %[1]s to rpc struct: %[2]s", lib.Name, err))
289+
return r, &commands.PermissionDeniedError{Message: tr("Error getting information for library %s", lib.Name), Cause: err}
284290
}
285291
importedLibs = append(importedLibs, rpcLib)
286292
}

commands/errors.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,30 @@ func (e *MissingPlatformPropertyError) ToRPCStatus() *status.Status {
171171
return status.New(codes.FailedPrecondition, e.Error())
172172
}
173173

174+
// PlatformNotFound is returned when a platform is not found
175+
type PlatformNotFound struct {
176+
Platform string
177+
}
178+
179+
func (e *PlatformNotFound) Error() string {
180+
return tr("Platform '%s' is not installed", e.Platform)
181+
}
182+
183+
func (e *PlatformNotFound) ToRPCStatus() *status.Status {
184+
return status.New(codes.FailedPrecondition, e.Error())
185+
}
186+
187+
// MissingSketchPathError is returned when the sketch path is mandatory and not specified
188+
type MissingSketchPathError struct{}
189+
190+
func (e *MissingSketchPathError) Error() string {
191+
return tr("Missing sketch path")
192+
}
193+
194+
func (e *MissingSketchPathError) ToRPCStatus() *status.Status {
195+
return status.New(codes.InvalidArgument, e.Error())
196+
}
197+
174198
// SketchNotFoundError is returned when the sketch is not found
175199
type SketchNotFoundError struct {
176200
Cause error
@@ -206,6 +230,24 @@ func (e *FailedUploadError) ToRPCStatus() *status.Status {
206230
return status.New(codes.Internal, e.Error())
207231
}
208232

233+
// CompileFailedError is returned when the compile fails
234+
type CompileFailedError struct {
235+
Message string
236+
Cause error
237+
}
238+
239+
func (e *CompileFailedError) Error() string {
240+
return composeErrorMsg(e.Message, e.Cause)
241+
}
242+
243+
func (e *CompileFailedError) Unwrap() error {
244+
return e.Cause
245+
}
246+
247+
func (e *CompileFailedError) ToRPCStatus() *status.Status {
248+
return status.New(codes.Internal, e.Error())
249+
}
250+
209251
// InvalidArgumentError is returned when an invalid argument is passed to the command
210252
type InvalidArgumentError struct {
211253
Message string

0 commit comments

Comments
 (0)