Skip to content

Commit 870b750

Browse files
authored
added guidance for initializing training in a fresh directory when git is not enabled (#54)
1 parent 279c482 commit 870b750

3 files changed

Lines changed: 110 additions & 2 deletions

File tree

trainings/init.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,13 @@ func (h *Handlers) Init(ctx context.Context, trainingName string, dir string, no
4646

4747
if alreadyInitialized {
4848
trainingRootFs := newTrainingRootFs(trainingRootDir)
49+
cfg := h.config.TrainingConfig(trainingRootFs)
50+
if !cfg.GitEnabled {
51+
printInitNeedsFreshDir(cfg)
52+
return nil
53+
}
4954
if files.DirOrFileExists(trainingRootFs, ".tdl-exercise") {
50-
fmt.Println("Training is already initialised, nothing to do.")
55+
fmt.Println("Training is already initialized, nothing to do.")
5156
return nil
5257
}
5358
// Partial init: exercise not yet set up, fall through to nextExercise.
@@ -342,7 +347,7 @@ func (h *Handlers) startTraining(
342347

343348
alreadyExistingTrainingRoot, err := h.config.FindTrainingRoot()
344349
if err == nil {
345-
fmt.Println(color.BlueString("Training was already initialised. Training root:" + alreadyExistingTrainingRoot))
350+
fmt.Println(color.BlueString("Found existing training workspace at: " + alreadyExistingTrainingRoot))
346351
trainingRootDir = alreadyExistingTrainingRoot
347352
} else if !errors.Is(err, config.TrainingRootNotFoundError) {
348353
return "", false, false, errors.Wrap(err, "can't check if training root exists")

trainings/migration.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,44 @@ func printGitNotices(cfg config.TrainingConfig) {
103103
printGitNowAvailableNotice(cfg)
104104
}
105105

106+
// printInitNeedsFreshDir is shown during `tdl training init` when the user runs init
107+
// in a directory that was already set up without git. Unlike printGitNowAvailableNotice
108+
// (rate-limited, shown during run/next/etc.), this fires unconditionally because the
109+
// user explicitly ran init and needs clear, actionable guidance.
110+
func printInitNeedsFreshDir(cfg config.TrainingConfig) {
111+
sep := color.HiBlackString(strings.Repeat("─", internal.TerminalWidth()))
112+
initCmd := color.CyanString("tdl training init %s .", cfg.TrainingName)
113+
114+
_, gitErr := git.CheckVersion()
115+
gitAvailable := gitErr == nil
116+
117+
fmt.Println(sep)
118+
if gitAvailable {
119+
title := color.New(color.Bold, color.FgHiGreen).Sprint(" *** Git is now available! ***")
120+
fmt.Println(title)
121+
fmt.Println()
122+
fmt.Println(" Git is now installed, but this workspace was set up without git tracking.")
123+
fmt.Println(" To enable git integration, initialize in a fresh empty directory.")
124+
} else {
125+
title := color.New(color.Bold, color.FgHiYellow).Sprint(" *** Fresh directory required ***")
126+
fmt.Println(title)
127+
fmt.Println()
128+
fmt.Println(" This workspace was set up without git tracking.")
129+
fmt.Println(" Once git is installed, initialize in a fresh directory to enable it.")
130+
}
131+
fmt.Println()
132+
fmt.Println(" Your progress is saved on the server and will be restored")
133+
fmt.Println(" automatically: solutions, completion history, everything.")
134+
fmt.Println()
135+
fmt.Println(" Create a new directory and reinitialize:")
136+
fmt.Println()
137+
fmt.Printf(" cd ..\n")
138+
fmt.Printf(" mkdir my-training && cd my-training\n")
139+
fmt.Printf(" %s\n", initCmd)
140+
fmt.Println(sep)
141+
fmt.Println()
142+
}
143+
106144
// showGitInstallNoticeIfDue shows the "git not installed" notice at most once per 24 h.
107145
// Fires whenever git is disabled and still not installed — covers both workspaces where
108146
// git was missing at init (GitUnavailable=true) and older workspaces that were silently

trainings/migration_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package trainings
2+
3+
import (
4+
"bytes"
5+
"io"
6+
"os"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
11+
"github.com/ThreeDotsLabs/cli/trainings/config"
12+
"github.com/ThreeDotsLabs/cli/trainings/git"
13+
)
14+
15+
func captureStdout(f func()) string {
16+
old := os.Stdout
17+
r, w, _ := os.Pipe()
18+
os.Stdout = w
19+
f()
20+
w.Close()
21+
os.Stdout = old
22+
var buf bytes.Buffer
23+
_, _ = io.Copy(&buf, r)
24+
return buf.String()
25+
}
26+
27+
func TestPrintInitNeedsFreshDir_GitAvailable(t *testing.T) {
28+
cfg := config.TrainingConfig{
29+
TrainingName: "go-event-driven",
30+
GitConfigured: true,
31+
GitEnabled: false,
32+
GitUnavailable: true,
33+
}
34+
35+
out := captureStdout(func() { printInitNeedsFreshDir(cfg) })
36+
37+
assert.Contains(t, out, "go-event-driven")
38+
assert.Contains(t, out, "cd ..")
39+
assert.Contains(t, out, "mkdir my-training")
40+
assert.Contains(t, out, "tdl training init go-event-driven .")
41+
assert.Contains(t, out, "Git is now available")
42+
}
43+
44+
func TestPrintInitNeedsFreshDir_GitNotAvailable(t *testing.T) {
45+
origPath := os.Getenv("PATH")
46+
t.Cleanup(func() {
47+
os.Setenv("PATH", origPath)
48+
git.ResetCheckVersion()
49+
})
50+
os.Setenv("PATH", "")
51+
git.ResetCheckVersion()
52+
53+
cfg := config.TrainingConfig{
54+
TrainingName: "go-event-driven",
55+
GitConfigured: false,
56+
GitEnabled: false,
57+
}
58+
59+
out := captureStdout(func() { printInitNeedsFreshDir(cfg) })
60+
61+
assert.Contains(t, out, "go-event-driven")
62+
assert.Contains(t, out, "Once git is installed")
63+
assert.Contains(t, out, "tdl training init go-event-driven .")
64+
assert.NotContains(t, out, "Git is now available")
65+
}

0 commit comments

Comments
 (0)