Skip to content

Commit 6a223b8

Browse files
committed
download: Infer track and exercise slug from CWD
If I'm in the `exercism/c` directory and invoke: exercism download --exercise hello-world I would like `--track c` to be inferred. If I'm in the `exercism/c/hello-world` directory and invoke without arguments: exercism download I would like both `--track c` and `--exercise hello-world` to be inferred.
1 parent d95de6b commit 6a223b8

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

cmd/download.go

+34
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,27 @@ Download other people's solutions by providing the UUID.
5050
},
5151
}
5252

53+
func nthComponentAfterWorkspace(workspace string, n int) (string, bool) {
54+
cwd, err := os.Getwd()
55+
if err != nil {
56+
return "", false
57+
}
58+
59+
if !strings.HasPrefix(cwd, workspace) {
60+
return "", false
61+
}
62+
remaining := cwd[len(workspace):]
63+
if remaining[0] == '/' {
64+
remaining = remaining[1:]
65+
}
66+
67+
components := strings.Split(remaining, "/")
68+
if n < len(components) {
69+
return components[n], true
70+
}
71+
return "", false
72+
}
73+
5374
func runDownload(cfg config.Config, flags *pflag.FlagSet, args []string) error {
5475
usrCfg := cfg.UserViperConfig
5576
if err := validateUserConfig(usrCfg); err != nil {
@@ -162,6 +183,19 @@ func newDownload(flags *pflag.FlagSet, usrCfg *viper.Viper) (*download, error) {
162183
d.apibaseurl = usrCfg.GetString("apibaseurl")
163184
d.workspace = usrCfg.GetString("workspace")
164185

186+
if d.uuid == "" {
187+
if d.slug == "" {
188+
if slug, ok := nthComponentAfterWorkspace(d.workspace, 1); ok {
189+
d.slug = slug
190+
}
191+
}
192+
if d.track == "" && d.team == "" {
193+
if track, ok := nthComponentAfterWorkspace(d.workspace, 0); ok {
194+
d.track = track
195+
}
196+
}
197+
}
198+
165199
if err = d.needsSlugXorUUID(); err != nil {
166200
return nil, err
167201
}

cmd/download_test.go

+57
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,63 @@ func TestDownloadWithoutFlags(t *testing.T) {
7777
}
7878
}
7979

80+
func TestDownloadInferringFlags(t *testing.T) {
81+
co := newCapturedOutput()
82+
co.override()
83+
defer co.reset()
84+
85+
originalCwd, err := os.Getwd()
86+
defer os.Chdir(originalCwd)
87+
assert.NoError(t, err)
88+
89+
testCases := []struct {
90+
cwd string
91+
flags map[string]string
92+
}{
93+
{
94+
cwd: "bogus-track",
95+
flags: map[string]string{"exercise": "bogus-exercise"},
96+
},
97+
{
98+
cwd: "bogus-track/bogus-exercise",
99+
flags: nil,
100+
},
101+
}
102+
103+
for _, tc := range testCases {
104+
tmpDir, err := ioutil.TempDir("", "download-infer")
105+
defer os.RemoveAll(tmpDir)
106+
assert.NoError(t, err)
107+
108+
subdir := filepath.Join(tmpDir, tc.cwd)
109+
err = os.MkdirAll(subdir, 0755)
110+
assert.NoError(t, err)
111+
os.Chdir(subdir)
112+
113+
ts := fakeDownloadServer(strconv.FormatBool(true), "")
114+
defer ts.Close()
115+
116+
v := viper.New()
117+
v.Set("workspace", tmpDir)
118+
v.Set("apibaseurl", ts.URL)
119+
v.Set("token", "abc123")
120+
121+
cfg := config.Config{
122+
UserViperConfig: v,
123+
}
124+
flags := pflag.NewFlagSet("fake", pflag.PanicOnError)
125+
setupDownloadFlags(flags)
126+
for name, value := range tc.flags {
127+
flags.Set(name, value)
128+
}
129+
130+
err = runDownload(cfg, flags, []string{})
131+
assert.NoError(t, err)
132+
133+
assertDownloadedCorrectFiles(t, tmpDir)
134+
}
135+
}
136+
80137
func TestSolutionFile(t *testing.T) {
81138
testCases := []struct {
82139
name, file, expectedPath, expectedURL string

0 commit comments

Comments
 (0)