fix: relative mount paths to be joined to repo root

This commit is contained in:
2026-03-22 15:59:44 +00:00
parent 517dc908bc
commit 5db731a55e
3 changed files with 73 additions and 9 deletions
+28 -1
View File
@@ -7,6 +7,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
) )
@@ -151,7 +152,33 @@ func validateSandbox(path string, sandbox map[string]string, mounts []string) (m
return nil, nil, fmt.Errorf("failed to read %s: sandbox.home must be an absolute path", path) return nil, nil, fmt.Errorf("failed to read %s: sandbox.home must be an absolute path", path)
} }
return validated, cloneMounts(mounts), nil validatedMounts, err := normalizeMounts(path, mounts)
if err != nil {
return nil, nil, err
}
return validated, validatedMounts, nil
}
func normalizeMounts(configPath string, mounts []string) ([]string, error) {
baseDir := filepath.Dir(configPath)
normalized := make([]string, 0, len(mounts))
for _, mount := range mounts {
hostPath, sandboxPath, ok := strings.Cut(mount, ":")
if !ok {
normalized = append(normalized, mount)
continue
}
if !filepath.IsAbs(hostPath) {
hostPath = filepath.Clean(filepath.Join(baseDir, hostPath))
}
if _, err := os.Stat(hostPath); err != nil {
return nil, fmt.Errorf("failed to read %s: sandbox mount host path %q does not exist", configPath, hostPath)
}
normalized = append(normalized, hostPath+":"+sandboxPath)
}
return normalized, nil
} }
func cloneSandbox(sandbox map[string]string) map[string]string { func cloneSandbox(sandbox map[string]string) map[string]string {
+44 -8
View File
@@ -17,16 +17,26 @@ func TestReadConfig(t *testing.T) {
wantMounts []string wantMounts []string
wantErr string wantErr string
wantMissing bool wantMissing bool
setup func(t *testing.T, dir string) (string, []string)
}{ }{
{ {
name: "with test dir and sandbox", name: "with test dir and sandbox",
content: "[mire]\ntest_dir = \"custom/suite\"\n\n[sandbox]\nhome = \"/home/test\"\nmounts = [\"/host/data:/sandbox/data\", \"/host/cache:/sandbox/cache\"]\nkey_word = \"value\"\n", setup: func(t *testing.T, dir string) (string, []string) {
hostData := filepath.Join(dir, "host-data")
hostCache := filepath.Join(dir, "host-cache")
for _, path := range []string{hostData, hostCache} {
if err := os.MkdirAll(path, 0o755); err != nil {
t.Fatalf("MkdirAll(%q) error = %v", path, err)
}
}
return "[mire]\ntest_dir = \"custom/suite\"\n\n[sandbox]\nhome = \"/home/test\"\nmounts = [\"" + hostData + ":/sandbox/data\", \"" + hostCache + ":/sandbox/cache\"]\nkey_word = \"value\"\n",
[]string{hostData + ":/sandbox/data", hostCache + ":/sandbox/cache"}
},
wantDir: "custom/suite", wantDir: "custom/suite",
wantSandbox: map[string]string{ wantSandbox: map[string]string{
"home": "/home/test", "home": "/home/test",
"key_word": "value", "key_word": "value",
}, },
wantMounts: []string{"/host/data:/sandbox/data", "/host/cache:/sandbox/cache"},
}, },
{ {
name: "legacy top level key", name: "legacy top level key",
@@ -97,13 +107,39 @@ func TestReadConfig(t *testing.T) {
name: "missing file", name: "missing file",
wantMissing: true, wantMissing: true,
}, },
{
name: "normalizes relative mount host path",
setup: func(t *testing.T, dir string) (string, []string) {
hostBuild := filepath.Join(dir, "build")
if err := os.MkdirAll(hostBuild, 0o755); err != nil {
t.Fatalf("MkdirAll(%q) error = %v", hostBuild, err)
}
return "[mire]\ntest_dir = \"custom/suite\"\n\n[sandbox]\nhome = \"/home/test\"\nmounts = [\"./build:/sandbox/build\"]\n",
[]string{hostBuild + ":/sandbox/build"}
},
wantDir: "custom/suite",
wantSandbox: map[string]string{
"home": "/home/test",
},
},
{
name: "missing mount host path",
content: "[mire]\ntest_dir = \"custom/suite\"\n\n[sandbox]\nhome = \"/home/test\"\nmounts = [\"./missing:/sandbox/build\"]\n",
wantErr: "sandbox mount host path",
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
path := filepath.Join(t.TempDir(), "mire.toml") dir := t.TempDir()
path := filepath.Join(dir, "mire.toml")
wantMounts := tt.wantMounts
content := tt.content
if tt.setup != nil {
content, wantMounts = tt.setup(t, dir)
}
if !tt.wantMissing { if !tt.wantMissing {
if err := os.WriteFile(path, []byte(tt.content), 0o644); err != nil { if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
t.Fatalf("WriteFile() error = %v", err) t.Fatalf("WriteFile() error = %v", err)
} }
} }
@@ -138,10 +174,10 @@ func TestReadConfig(t *testing.T) {
t.Fatalf("ReadConfig() Sandbox[%q] = %q, want %q", key, got.Sandbox[key], want) t.Fatalf("ReadConfig() Sandbox[%q] = %q, want %q", key, got.Sandbox[key], want)
} }
} }
if len(got.Mounts) != len(tt.wantMounts) { if len(got.Mounts) != len(wantMounts) {
t.Fatalf("ReadConfig() Mounts = %#v, want %#v", got.Mounts, tt.wantMounts) t.Fatalf("ReadConfig() Mounts = %#v, want %#v", got.Mounts, wantMounts)
} }
for i, want := range tt.wantMounts { for i, want := range wantMounts {
if got.Mounts[i] != want { if got.Mounts[i] != want {
t.Fatalf("ReadConfig() Mounts[%d] = %q, want %q", i, got.Mounts[i], want) t.Fatalf("ReadConfig() Mounts[%d] = %q, want %q", i, got.Mounts[i], want)
} }
+1
View File
@@ -6,4 +6,5 @@
# home is where mire would drop you by default on record # home is where mire would drop you by default on record
home = "/home/test" home = "/home/test"
# read only paths from host, entry looks like "path on host:path on sanbox" # read only paths from host, entry looks like "path on host:path on sanbox"
# paths on host are absolute or relative to repo root
mounts = [] mounts = []