@@ -44,9 +44,11 @@ type commander struct {
4444func NewCommander () (arduino.Commander , error ) {
4545 // Discard arduino-cli log info messages
4646 logrus .SetLevel (logrus .ErrorLevel )
47- // Initialize arduino-cli configuration
47+
48+ // Initialize arduino-cli configuration.
4849 configuration .Settings = configuration .Init (configuration .FindConfigFileInArgsOrWorkingDirectory (os .Args ))
49- // Create arduino-cli instance, needed to execute arduino-cli commands
50+
51+ // Create and init an arduino-cli instance, needed to execute arduino-cli commands.
5052 inst , err := instance .Create ()
5153 if err != nil {
5254 err = fmt .Errorf ("creating arduino-cli instance: %w" , err )
@@ -61,34 +63,64 @@ func NewCommander() (arduino.Commander, error) {
6163 return cmd , nil
6264}
6365
66+ func mergeErrors (err error , errs []error ) error {
67+ merr := errors .New ("merged errors: " )
68+ empty := true
69+
70+ if err != nil {
71+ merr = fmt .Errorf ("%w%v; " , merr , err )
72+ empty = false
73+ }
74+
75+ if len (errs ) > 0 {
76+ empty = false
77+ for _ , e := range errs {
78+ merr = fmt .Errorf ("%w%v; " , merr , e )
79+ }
80+ }
81+
82+ if ! empty {
83+ return merr
84+ }
85+ return nil
86+ }
87+
6488// BoardList executes the 'arduino-cli board list' command
6589// and returns its result.
66- func (c * commander ) BoardList () ([]* rpc.DetectedPort , error ) {
90+ func (c * commander ) BoardList (ctx context. Context ) ([]* rpc.DetectedPort , error ) {
6791 req := & rpc.BoardListRequest {
6892 Instance : c .Instance ,
6993 Timeout : time .Second .Milliseconds (),
7094 }
7195
72- ports , errs , err := board .List (req )
73- if err != nil {
74- err = fmt .Errorf ("%s: %w" , "detecting boards" , err )
75- return nil , err
96+ // There is no obvious way to cancel the execution of this command.
97+ // So, we execute it in a goroutine and leave it running alone if ctx gets cancelled.
98+ type resp struct {
99+ err error
100+ ports []* rpc.DetectedPort
76101 }
102+ quit := make (chan resp , 1 )
103+ go func () {
104+ ports , errs , err := board .List (req )
105+ quit <- resp {err : mergeErrors (err , errs ), ports : ports }
106+ close (quit )
107+ }()
77108
78- if len (errs ) > 0 {
79- err = errors .New ("starting discovery procedure: received errors: " )
80- for _ , e := range errs {
81- err = fmt .Errorf ("%w%v; " , err , e )
109+ // Wait for the command to complete or the context to be terminated.
110+ select {
111+ case <- ctx .Done ():
112+ return nil , errors .New ("board list command cancelled" )
113+ case r := <- quit :
114+ if r .err != nil {
115+ return nil , fmt .Errorf ("executing board list command: %w" , r .err )
82116 }
83- return nil , err
117+ return r . ports , nil
84118 }
85-
86- return ports , nil
87119}
88120
89121// UploadBin executes the 'arduino-cli upload -i' command
90122// and returns its result.
91- func (c * commander ) UploadBin (fqbn , bin , address , protocol string ) error {
123+ func (c * commander ) UploadBin (ctx context. Context , fqbn , bin , address , protocol string ) error {
92124 req := & rpc.UploadRequest {
93125 Instance : c .Instance ,
94126 Fqbn : fqbn ,
@@ -97,11 +129,25 @@ func (c *commander) UploadBin(fqbn, bin, address, protocol string) error {
97129 Port : & rpc.Port {Address : address , Protocol : protocol },
98130 Verbose : false ,
99131 }
100-
101132 l := logrus .StandardLogger ().WithField ("source" , "arduino-cli" ).Writer ()
102- if _ , err := upload .Upload (context .Background (), req , l , l ); err != nil {
103- err = fmt .Errorf ("%s: %w" , "uploading binary" , err )
104- return err
133+
134+ // There is no obvious way to cancel the execution of this command.
135+ // So, we execute it in a goroutine and leave it running if ctx gets cancelled.
136+ quit := make (chan error , 1 )
137+ go func () {
138+ _ , err := upload .Upload (ctx , req , l , l )
139+ quit <- err
140+ close (quit )
141+ }()
142+
143+ // Wait for the upload to complete or the context to be terminated.
144+ select {
145+ case <- ctx .Done ():
146+ return errors .New ("upload cancelled" )
147+ case err := <- quit :
148+ if err != nil {
149+ return fmt .Errorf ("uploading binary: %w" , err )
150+ }
151+ return nil
105152 }
106- return nil
107153}
0 commit comments