Skip to content

Commit 3ed08d2

Browse files
author
Katrina Owen
committed
Handle exercise directories with numeric suffixes
An early design decision was to allow people to work on multiple solutions to the same exercise at the same time. We later decided not to do this, but the CLI still had logic that supported it. This caused us to (incorrectly) create exercise directories that were named with a numeric suffix, which would then get submitted to the backend server, which doesn't care about filepaths. Because the exercise with the numeric suffix doesn't match the expected path, we did not correctly trim off any leading directories on submit, which further caused the download command to put the solution in a weirdly and deeply nested directory, making the solution hard to find and review.
1 parent 9b0f559 commit 3ed08d2

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

cmd/download.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
netURL "net/url"
1010
"os"
1111
"path/filepath"
12+
"regexp"
1213
"strings"
1314

1415
"github.com/exercism/cli/api"
@@ -200,6 +201,15 @@ func runDownload(cfg config.Config, flags *pflag.FlagSet, args []string) error {
200201
// TODO: if there's a collision, interactively resolve (show diff, ask if overwrite).
201202
// TODO: handle --force flag to overwrite without asking.
202203

204+
// Work around a path bug due to an early design decision (later reversed) to
205+
// allow numeric suffixes for exercise directories, allowing people to have
206+
// multiple parallel versions of an exercise.
207+
pattern := fmt.Sprintf(`\A.*[/\\]%s-\d*/`, solution.Exercise)
208+
rgxNumericSuffix := regexp.MustCompile(pattern)
209+
if rgxNumericSuffix.MatchString(file) {
210+
file = string(rgxNumericSuffix.ReplaceAll([]byte(file), []byte("")))
211+
}
212+
203213
// Rewrite paths submitted with an older, buggy client where the Windows path is being treated as part of the filename.
204214
file = strings.Replace(file, "\\", "/", -1)
205215

cmd/download_test.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ func fakeDownloadServer(requestor, teamSlug string) *httptest.Server {
166166
fmt.Fprint(w, "this is file 2")
167167
})
168168

169+
mux.HandleFunc("/full/path/with/numeric-suffix/bogus-track/bogus-exercise-12345/subdir/numeric.txt", func(w http.ResponseWriter, r *http.Request) {
170+
fmt.Fprint(w, "with numeric suffix")
171+
})
172+
169173
mux.HandleFunc("/special-char-filename#.txt", func(w http.ResponseWriter, r *http.Request) {
170174
fmt.Fprint(w, "this is a special file")
171175
})
@@ -217,6 +221,11 @@ func assertDownloadedCorrectFiles(t *testing.T, targetDir string) {
217221
path: filepath.Join(targetDir, "bogus-track", "bogus-exercise", "subdir", "file-2.txt"),
218222
contents: "this is file 2",
219223
},
224+
{
225+
desc: "a path with a numeric suffix",
226+
path: filepath.Join(targetDir, "bogus-track", "bogus-exercise", "subdir", "numeric.txt"),
227+
contents: "with numeric suffix",
228+
},
220229
{
221230
desc: "a file that requires URL encoding",
222231
path: filepath.Join(targetDir, "bogus-track", "bogus-exercise", "special-char-filename#.txt"),
@@ -278,7 +287,8 @@ const payloadTemplate = `
278287
"/with-leading-slash.txt",
279288
"\\with-leading-backslash.txt",
280289
"\\with\\backslashes\\in\\path.txt",
281-
"file-3.txt"
290+
"file-3.txt",
291+
"/full/path/with/numeric-suffix/bogus-track/bogus-exercise-12345/subdir/numeric.txt"
282292
],
283293
"iteration": {
284294
"submitted_at": "2017-08-21t10:11:12.130z"

0 commit comments

Comments
 (0)