@@ -38,15 +38,18 @@ import (
38
38
"os"
39
39
"path/filepath"
40
40
"strings"
41
+ "time"
41
42
42
43
"github.com/bcmi-labs/arduino-cli/auth"
43
44
"github.com/bcmi-labs/arduino-cli/create_client_helpers"
44
45
"github.com/bgentry/go-netrc/netrc"
46
+ "github.com/briandowns/spinner"
45
47
homedir "github.com/mitchellh/go-homedir"
46
48
47
49
"github.com/bcmi-labs/arduino-modules/sketches"
48
50
49
51
"github.com/bcmi-labs/arduino-cli/cmd/formatter"
52
+ "github.com/bcmi-labs/arduino-cli/cmd/output"
50
53
"github.com/bcmi-labs/arduino-cli/common"
51
54
52
55
"github.com/spf13/cobra"
@@ -86,12 +89,58 @@ func executeSketchSyncCommand(cmd *cobra.Command, args []string) {
86
89
os .Exit (errCoreConfig )
87
90
}
88
91
92
+ priority := arduinoSketchSyncFlags .Priority
93
+
94
+ if priority == "ask-once" {
95
+ if ! formatter .IsCurrentFormat ("text" ) {
96
+ formatter .PrintErrorMessage ("ask mode for this command is only supported using text format" )
97
+ os .Exit (errBadCall )
98
+ }
99
+ firstAsk := true
100
+ for priority != "pull-remote" &&
101
+ priority != "push-local" &&
102
+ priority != "skip" {
103
+ if ! firstAsk {
104
+ formatter .Print ("Invalid option: " + priority )
105
+ }
106
+ formatter .Print ("What should I do when I detect a conflict? [pull-remote | push-local | skip]" )
107
+ fmt .Scanln (& priority )
108
+ firstAsk = false
109
+ }
110
+ }
111
+
112
+ //loader
113
+ isTextMode := formatter .IsCurrentFormat ("text" )
114
+
115
+ var loader * spinner.Spinner
116
+
117
+ if isTextMode {
118
+ loader = spinner .New (spinner .CharSets [39 ], 100 * time .Millisecond )
119
+ loader .Prefix = "Syncing Sketches... "
120
+
121
+ loader .Start ()
122
+ }
123
+
124
+ stopSpinner := func () {
125
+ if isTextMode {
126
+ loader .Stop ()
127
+ }
128
+ }
129
+
130
+ startSpinner := func () {
131
+ if isTextMode {
132
+ loader .Start ()
133
+ }
134
+ }
135
+
89
136
username , bearerToken , err := login ()
90
137
if err != nil {
91
138
if GlobalFlags .Verbose == 0 {
92
139
formatter .PrintErrorMessage ("Cannot login automatically: try arduino login the run again this command" )
93
140
} else {
141
+ stopSpinner ()
94
142
formatter .PrintError (err )
143
+ os .Exit (errNetwork )
95
144
}
96
145
}
97
146
@@ -101,13 +150,15 @@ func executeSketchSyncCommand(cmd *cobra.Command, args []string) {
101
150
tok := "Bearer " + bearerToken
102
151
resp , err := client .SearchSketches (context .Background (), createClient .SearchSketchesPath (), nil , & username , & tok )
103
152
if err != nil {
153
+ stopSpinner ()
104
154
formatter .PrintErrorMessage ("Cannot get create sketches, sync failed" )
105
155
os .Exit (errNetwork )
106
156
}
107
157
defer resp .Body .Close ()
108
158
109
159
onlineSketches , err := client .DecodeArduinoCreateSketches (resp )
110
160
if err != nil {
161
+ stopSpinner ()
111
162
formatter .PrintErrorMessage ("Cannot unmarshal response from create, sync failed" )
112
163
os .Exit (errGeneric )
113
164
}
@@ -117,32 +168,25 @@ func executeSketchSyncCommand(cmd *cobra.Command, args []string) {
117
168
onlineSketchesMap [* item .Name ] = item
118
169
}
119
170
120
- priority := arduinoSketchSyncFlags . Priority
171
+ maxLength := len ( sketchMap ) + len ( onlineSketchesMap )
121
172
122
- if priority == "ask-once" {
123
- if ! formatter .IsCurrentFormat ("text" ) {
124
- formatter .PrintErrorMessage ("ask mode for this command is only supported using text format" )
125
- os .Exit (errBadCall )
126
- }
127
- firstAsk := true
128
- for priority != "pull-remote" &&
129
- priority != "push-local" &&
130
- priority != "skip" {
131
- if ! firstAsk {
132
- formatter .Print ("Invalid option: " + priority )
133
- }
134
- formatter .Print ("What should I do when I detect a conflict? [pull-remote | push-local | skip]" )
135
- fmt .Scanln (& priority )
136
- firstAsk = false
137
- }
173
+ // create output result struct with empty arrays.
174
+ result := output.SketchSyncResult {
175
+ PushedSketches : make ([]string , 0 , maxLength ),
176
+ PulledSketches : make ([]string , 0 , maxLength ),
177
+ SkippedSketches : make ([]string , 0 , maxLength ),
178
+ Errors : make ([]output.SketchSyncError , 0 , maxLength ),
138
179
}
180
+
139
181
for _ , item := range sketchMap {
140
182
141
183
itemOnline , hasConflict := onlineSketchesMap [item .Name ]
142
184
if hasConflict {
143
185
item .ID = itemOnline .ID .String ()
144
186
//solve conflicts
145
187
if priority == "ask-always" {
188
+ stopSpinner ()
189
+
146
190
if ! formatter .IsCurrentFormat ("text" ) {
147
191
formatter .PrintErrorMessage ("ask mode for this command is only supported using text format" )
148
192
os .Exit (errBadCall )
@@ -158,43 +202,50 @@ func executeSketchSyncCommand(cmd *cobra.Command, args []string) {
158
202
fmt .Scanln (& priority )
159
203
firstAsk = false
160
204
}
205
+
206
+ startSpinner ()
161
207
}
162
208
switch priority {
163
209
case "push-local" :
164
- if GlobalFlags .Verbose > 0 {
165
- formatter .Print ("pushing edits of sketch: " + item .Name )
166
- }
167
210
err := editSketch (* item , sketchbook , bearerToken )
168
211
if err != nil {
169
- formatter .PrintError (err )
212
+ result .Errors = append (result .Errors , output.SketchSyncError {
213
+ Sketch : item .Name ,
214
+ Error : err ,
215
+ })
216
+ } else {
217
+ result .PushedSketches = append (result .PushedSketches , item .Name )
170
218
}
171
219
break
172
220
case "pull-remote" :
173
- if GlobalFlags .Verbose > 0 {
174
- formatter .Print ("pulling " + item .Name )
175
- }
176
221
err := pullSketch (itemOnline , sketchbook , bearerToken )
177
222
if err != nil {
178
- formatter .PrintError (err )
223
+ result .Errors = append (result .Errors , output.SketchSyncError {
224
+ Sketch : item .Name ,
225
+ Error : err ,
226
+ })
227
+ } else {
228
+ result .PulledSketches = append (result .PulledSketches , item .Name )
179
229
}
180
230
break
181
231
case "skip" :
182
- if GlobalFlags .Verbose > 0 {
183
- formatter .Print ("skipping " + item .Name )
184
- }
232
+ result .SkippedSketches = append (result .SkippedSketches , item .Name )
185
233
break
186
234
default :
187
235
priority = "skip"
188
- if GlobalFlags .Verbose > 0 {
189
- formatter .Print ("Priority not recognized, using skipping by default" )
190
- formatter .Print ("skipping " + item .Name )
191
- }
192
-
236
+ result .SkippedSketches = append (result .SkippedSketches , item .Name )
193
237
}
194
238
195
239
} else { //only local, push
196
- formatter .Print ("pushing " + item .Name )
197
- pushSketch (* item , sketchbook , bearerToken )
240
+ err := pushSketch (* item , sketchbook , bearerToken )
241
+ if err != nil {
242
+ result .Errors = append (result .Errors , output.SketchSyncError {
243
+ Sketch : item .Name ,
244
+ Error : err ,
245
+ })
246
+ } else {
247
+ result .PushedSketches = append (result .PushedSketches , item .Name )
248
+ }
198
249
}
199
250
}
200
251
for _ , item := range onlineSketches .Sketches {
@@ -203,13 +254,26 @@ func executeSketchSyncCommand(cmd *cobra.Command, args []string) {
203
254
continue
204
255
}
205
256
//only online, pull
206
- formatter .Print ("pulling " + * item .Name )
207
257
err := pullSketch (item , sketchbook , bearerToken )
208
258
if err != nil {
209
- formatter .PrintError (err )
259
+ result .Errors = append (result .Errors , output.SketchSyncError {
260
+ Sketch : * item .Name ,
261
+ Error : err ,
262
+ })
263
+ } else {
264
+ result .PulledSketches = append (result .PulledSketches , * item .Name )
210
265
}
211
266
}
212
- formatter .PrintResult ("Sync Completed" ) // Issue # : Provide output struct to print the result in a prettier way.
267
+
268
+ stopSpinner ()
269
+
270
+ // for text mode, show full info (aka String()) only if verbose > 0.
271
+ // for other formats always print full info.
272
+ if GlobalFlags .Verbose > 0 || ! formatter .IsCurrentFormat ("text" ) {
273
+ formatter .Print (result )
274
+ } else {
275
+ formatter .PrintResult ("Sync Completed" )
276
+ }
213
277
}
214
278
215
279
func pushSketch (sketch sketches.Sketch , sketchbook string , bearerToken string ) error {
0 commit comments