diff --git a/dagger/gen.go b/dagger/gen.go index a0e44ad1..694e42f1 100644 --- a/dagger/gen.go +++ b/dagger/gen.go @@ -60,7 +60,7 @@ package dagger #Script: [...#Op] // One operation in a script -#Op: #FetchContainer | #FetchGit | #Export | #Exec | #Local | #Copy | #Load +#Op: #FetchContainer | #FetchGit | #Export | #Exec | #Local | #Copy | #Load | #Subdir // Export a value from fs state to cue #Export: { @@ -83,6 +83,11 @@ package dagger from: #Component | #Script } +#Subdir: { + do: "subdir" + dir: string | *"/" +} + #Exec: { do: "exec" args: [...string] diff --git a/dagger/op.go b/dagger/op.go index aa5a4243..9a91da0c 100644 --- a/dagger/op.go +++ b/dagger/op.go @@ -94,6 +94,7 @@ func (op *Op) Action() (Action, error) { "#FetchGit": op.FetchGit, "#Local": op.Local, "#Load": op.Load, + "#Subdir": op.Subdir, } for def, action := range actions { if err := op.Validate(def); err == nil { @@ -108,6 +109,26 @@ func (op *Op) Validate(defs ...string) error { return op.v.Validate(defs...) } +func (op *Op) Subdir(ctx context.Context, fs FS, out *Fillable) (FS, error) { + // FIXME: this could be more optimized by carrying subdir path as metadata, + // and using it in copy, load or mount. + + dir, err := op.Get("dir").String() + if err != nil { + return fs, err + } + return fs.Change(func(st llb.State) llb.State { + return st.File(llb.Copy( + fs.LLB(), + dir, + "/", + &llb.CopyInfo{ + CopyDirContentsOnly: true, + }, + )) + }), nil +} + func (op *Op) Copy(ctx context.Context, fs FS, out *Fillable) (FS, error) { // Decode copy options src, err := op.Get("src").String() diff --git a/dagger/spec.cue b/dagger/spec.cue index f7999f2f..d3e8c023 100644 --- a/dagger/spec.cue +++ b/dagger/spec.cue @@ -55,7 +55,7 @@ package dagger #Script: [...#Op] // One operation in a script -#Op: #FetchContainer | #FetchGit | #Export | #Exec | #Local | #Copy | #Load +#Op: #FetchContainer | #FetchGit | #Export | #Exec | #Local | #Copy | #Load | #Subdir // Export a value from fs state to cue #Export: { @@ -78,6 +78,11 @@ package dagger from: #Component | #Script } +#Subdir: { + do: "subdir" + dir: string | *"/" +} + #Exec: { do: "exec" args: [...string] diff --git a/tests/subdir/simple/main.cue b/tests/subdir/simple/main.cue new file mode 100644 index 00000000..59ed8417 --- /dev/null +++ b/tests/subdir/simple/main.cue @@ -0,0 +1,29 @@ +package main + +hello: { + string + + #dagger: compute: [ + { + do: "fetch-container" + ref: "alpine" + }, + { + do: "exec" + args: ["mkdir", "-p", "/tmp/foo"] + }, + { + do: "exec" + args: ["sh", "-c", "echo -n world > /tmp/foo/hello"] + }, + { + do: "subdir" + dir: "/tmp/foo" + }, + { + do: "export" + source: "/hello" + format: "string" + }, + ] +} diff --git a/tests/test.sh b/tests/test.sh index 78e11172..58008d37 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -217,6 +217,11 @@ test::input() { } +test::subdir() { + test::one "Subdir: simple usage" --exit=0 --stdout='{"hello":"world"}' \ + "$dagger" "${DAGGER_BINARY_ARGS[@]}" compute "$d"/subdir/simple +} + test::all(){ local dagger="$1" @@ -231,6 +236,7 @@ test::all(){ test::exec "$dagger" test::export "$dagger" test::input "$dagger" + test::subdir "$dagger" } case "${1:-all}" in