Skip to content

Commit fcef8c8

Browse files
authored
Merge branch 'main' into fix/113-pip-older-python
2 parents 46f139e + f123331 commit fcef8c8

2 files changed

Lines changed: 134 additions & 0 deletions

File tree

src/cmd/global.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ func setRuntimeVersion(runtimeName, version, scope string, setter func(string) e
1515
return
1616
}
1717

18+
// Validate that the version is installed
19+
installed, err := provider.IsInstalled(version)
20+
if err != nil {
21+
ui.Error("Failed to check if version is installed: %v", err)
22+
return
23+
}
24+
if !installed {
25+
ui.Error("%s %s is not installed", provider.DisplayName(), version)
26+
ui.Info("Run 'dtvem list %s' to see installed versions", runtimeName)
27+
ui.Info("Run 'dtvem install %s %s' to install it first", runtimeName, version)
28+
return
29+
}
30+
1831
ui.Info("Setting %s %s version to %s...", scope, provider.DisplayName(), version)
1932

2033
if err := setter(version); err != nil {

src/cmd/global_test.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"testing"
7+
8+
"github.com/dtvem/dtvem/src/internal/config"
9+
)
10+
11+
func TestVersionValidation_InstalledVersion(t *testing.T) {
12+
// Create a temporary dtvem root directory
13+
tempDir := t.TempDir()
14+
originalRoot := os.Getenv("DTVEM_ROOT")
15+
if err := os.Setenv("DTVEM_ROOT", tempDir); err != nil {
16+
t.Fatalf("Failed to set DTVEM_ROOT: %v", err)
17+
}
18+
defer func() { _ = os.Setenv("DTVEM_ROOT", originalRoot) }()
19+
20+
// Reset cached paths to use the new root
21+
config.ResetPathsCache()
22+
defer config.ResetPathsCache()
23+
24+
// Create a fake installed version directory for python
25+
versionDir := filepath.Join(tempDir, "versions", "python", "3.11.0")
26+
err := os.MkdirAll(versionDir, 0755)
27+
if err != nil {
28+
t.Fatalf("Failed to create version directory: %v", err)
29+
}
30+
31+
// Verify the directory exists (simulating an installed version)
32+
if _, err := os.Stat(versionDir); os.IsNotExist(err) {
33+
t.Fatalf("Version directory should exist")
34+
}
35+
}
36+
37+
func TestVersionValidation_NotInstalledVersion(t *testing.T) {
38+
// Create a temporary dtvem root directory
39+
tempDir := t.TempDir()
40+
originalRoot := os.Getenv("DTVEM_ROOT")
41+
if err := os.Setenv("DTVEM_ROOT", tempDir); err != nil {
42+
t.Fatalf("Failed to set DTVEM_ROOT: %v", err)
43+
}
44+
defer func() { _ = os.Setenv("DTVEM_ROOT", originalRoot) }()
45+
46+
// Reset cached paths to use the new root
47+
config.ResetPathsCache()
48+
defer config.ResetPathsCache()
49+
50+
// Version directory does not exist (not installed)
51+
versionDir := filepath.Join(tempDir, "versions", "python", "3.99.0")
52+
53+
// Verify the directory does NOT exist
54+
if _, err := os.Stat(versionDir); !os.IsNotExist(err) {
55+
t.Fatalf("Version directory should not exist for uninstalled version")
56+
}
57+
}
58+
59+
func TestVersionValidation_VersionPathFormat(t *testing.T) {
60+
tests := []struct {
61+
name string
62+
runtimeName string
63+
version string
64+
}{
65+
{
66+
name: "Python version",
67+
runtimeName: "python",
68+
version: "3.11.0",
69+
},
70+
{
71+
name: "Node version",
72+
runtimeName: "node",
73+
version: "18.16.0",
74+
},
75+
{
76+
name: "Version with only major.minor",
77+
runtimeName: "python",
78+
version: "3.12",
79+
},
80+
{
81+
name: "Typo version (issue example)",
82+
runtimeName: "python",
83+
version: "3.47",
84+
},
85+
}
86+
87+
for _, tt := range tests {
88+
t.Run(tt.name, func(t *testing.T) {
89+
versionPath := config.RuntimeVersionPath(tt.runtimeName, tt.version)
90+
91+
// Path should be absolute
92+
if !filepath.IsAbs(versionPath) {
93+
t.Errorf("Version path should be absolute, got: %s", versionPath)
94+
}
95+
96+
// Path should contain the runtime name
97+
if !containsPathComponent(versionPath, tt.runtimeName) {
98+
t.Errorf("Version path should contain runtime name %q, got: %s", tt.runtimeName, versionPath)
99+
}
100+
101+
// Path should contain the version
102+
if !containsPathComponent(versionPath, tt.version) {
103+
t.Errorf("Version path should contain version %q, got: %s", tt.version, versionPath)
104+
}
105+
})
106+
}
107+
}
108+
109+
// containsPathComponent checks if a path contains a specific component
110+
func containsPathComponent(path, component string) bool {
111+
// Split path and check each component
112+
for _, part := range filepath.SplitList(path) {
113+
if part == component {
114+
return true
115+
}
116+
}
117+
// Also check using string contains as fallback for nested paths
118+
return filepath.Base(path) == component ||
119+
filepath.Base(filepath.Dir(path)) == component ||
120+
filepath.Base(filepath.Dir(filepath.Dir(path))) == component
121+
}

0 commit comments

Comments
 (0)