@@ -75,16 +75,12 @@ func runDownload(cfg config.Config, flags *pflag.FlagSet, args []string) error {
75
75
return err
76
76
}
77
77
78
- for _ , file := range download .payload .Solution .Files {
79
- unparsedURL := fmt .Sprintf ("%s%s" , download .payload .Solution .FileDownloadBaseURL , file )
80
- parsedURL , err := netURL .ParseRequestURI (unparsedURL )
81
-
78
+ for _ , sf := range download .payload .files () {
79
+ url , err := sf .url ()
82
80
if err != nil {
83
81
return err
84
82
}
85
83
86
- url := parsedURL .String ()
87
-
88
84
req , err := client .NewRequest ("GET" , url , nil )
89
85
if err != nil {
90
86
return err
@@ -105,26 +101,12 @@ func runDownload(cfg config.Config, flags *pflag.FlagSet, args []string) error {
105
101
continue
106
102
}
107
103
108
- // TODO: if there's a collision, interactively resolve (show diff, ask if overwrite).
109
- // TODO: handle --force flag to overwrite without asking.
110
-
111
- // Work around a path bug due to an early design decision (later reversed) to
112
- // allow numeric suffixes for exercise directories, allowing people to have
113
- // multiple parallel versions of an exercise.
114
- pattern := fmt .Sprintf (`\A.*[/\\]%s-\d*/` , metadata .ExerciseSlug )
115
- rgxNumericSuffix := regexp .MustCompile (pattern )
116
- if rgxNumericSuffix .MatchString (file ) {
117
- file = string (rgxNumericSuffix .ReplaceAll ([]byte (file ), []byte ("" )))
118
- }
119
-
120
- // Rewrite paths submitted with an older, buggy client where the Windows path is being treated as part of the filename.
121
- file = strings .Replace (file , "\\ " , "/" , - 1 )
122
-
123
- relativePath := filepath .FromSlash (file )
124
- dir := filepath .Join (metadata .Dir , filepath .Dir (relativePath ))
104
+ // TODO: handle collisions
105
+ path := sf .relativePath ()
106
+ dir := filepath .Join (metadata .Dir , filepath .Dir (path ))
125
107
os .MkdirAll (dir , os .FileMode (0755 ))
126
108
127
- f , err := os .Create (filepath .Join (metadata .Dir , relativePath ))
109
+ f , err := os .Create (filepath .Join (metadata .Dir , path ))
128
110
if err != nil {
129
111
return err
130
112
}
@@ -311,6 +293,51 @@ func (dp downloadPayload) metadata() workspace.ExerciseMetadata {
311
293
}
312
294
}
313
295
296
+ func (dp downloadPayload ) files () []solutionFile {
297
+ fx := make ([]solutionFile , 0 , len (dp .Solution .Files ))
298
+ for _ , file := range dp .Solution .Files {
299
+ f := solutionFile {
300
+ path : file ,
301
+ baseURL : dp .Solution .FileDownloadBaseURL ,
302
+ slug : dp .Solution .Exercise .ID ,
303
+ }
304
+ fx = append (fx , f )
305
+ }
306
+ return fx
307
+ }
308
+
309
+ type solutionFile struct {
310
+ path , baseURL , slug string
311
+ }
312
+
313
+ func (sf solutionFile ) url () (string , error ) {
314
+ url , err := netURL .ParseRequestURI (fmt .Sprintf ("%s%s" , sf .baseURL , sf .path ))
315
+
316
+ if err != nil {
317
+ return "" , err
318
+ }
319
+
320
+ return url .String (), nil
321
+ }
322
+
323
+ func (sf solutionFile ) relativePath () string {
324
+ file := sf .path
325
+
326
+ // Work around a path bug due to an early design decision (later reversed) to
327
+ // allow numeric suffixes for exercise directories, letting people have
328
+ // multiple parallel versions of an exercise.
329
+ pattern := fmt .Sprintf (`\A.*[/\\]%s-\d*/` , sf .slug )
330
+ rgxNumericSuffix := regexp .MustCompile (pattern )
331
+ if rgxNumericSuffix .MatchString (sf .path ) {
332
+ file = string (rgxNumericSuffix .ReplaceAll ([]byte (sf .path ), []byte ("" )))
333
+ }
334
+
335
+ // Rewrite paths submitted with an older, buggy client where the Windows path is being treated as part of the filename.
336
+ file = strings .Replace (file , "\\ " , "/" , - 1 )
337
+
338
+ return filepath .FromSlash (file )
339
+ }
340
+
314
341
func setupDownloadFlags (flags * pflag.FlagSet ) {
315
342
flags .StringP ("uuid" , "u" , "" , "the solution UUID" )
316
343
flags .StringP ("track" , "t" , "" , "the track ID" )
0 commit comments