werkdock: ordered mounts with --tmpfs, images verb, :rw accepted

Session C groundwork: Werkator's git-metadata mask needs a tmpfs
BETWEEN binds (ro-bind .git, tmpfs .git/werkator, bind workspace), so
-v and --tmpfs now collect into one ordered mount list and RunSpec
carries Mounts instead of Binds. --tmpfs DEST is the docker flag of the
same name. `werkdock images` lists loaded image names one per line, so
a consumer can check existence through the CLI. -v accepts the explicit
:rw docker default instead of refusing it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-09-01 15:39:31 +02:00
co-authored by Claude Fable 5
parent 263245d49e
commit a2da6454f7
9 changed files with 236 additions and 66 deletions
+21
View File
@@ -11,6 +11,7 @@ import (
"os/exec"
"path/filepath"
"regexp"
"sort"
"strings"
"time"
)
@@ -57,6 +58,26 @@ func (s Store) RootFS(name string) (string, error) {
return rootfs, nil
}
// List returns the names of all loaded images, sorted; half-written
// `.tmp` directories from an interrupted load are not images.
func (s Store) List() ([]string, error) {
entries, err := os.ReadDir(filepath.Join(s.Root, "images"))
if os.IsNotExist(err) {
return nil, nil
}
if err != nil {
return nil, err
}
var names []string
for _, e := range entries {
if e.IsDir() && nameRe.MatchString(e.Name()) {
names = append(names, e.Name())
}
}
sort.Strings(names)
return names, nil
}
// Load imports a rootfs archive as an image. The archive is unpacked
// with the tar CLI (compression auto-detected; .tar.zst needs the zstd
// binary, which doctor checks) into a temporary directory and renamed
+19
View File
@@ -115,6 +115,25 @@ func TestRootFSValidation(t *testing.T) {
}
}
func TestListNamesLoadedImagesAndIgnoresTmpLeftovers(t *testing.T) {
st := Store{Root: t.TempDir()}
if names, err := st.List(); err != nil || names != nil {
t.Fatalf("empty store: got %v, %v", names, err)
}
for _, dir := range []string{"beta", "alpha", "broken.tmp"} {
if err := os.MkdirAll(filepath.Join(st.Root, "images", dir), 0o755); err != nil {
t.Fatal(err)
}
}
names, err := st.List()
if err != nil {
t.Fatal(err)
}
if len(names) != 2 || names[0] != "alpha" || names[1] != "beta" {
t.Errorf("got %v, want [alpha beta]", names)
}
}
func TestImageNameFromArchive(t *testing.T) {
tests := []struct{ in, want string }{
{"werkator-buildenv-trixie.tar.zst", "werkator-buildenv-trixie"},