Skip to content
This repository has been archived by the owner on Nov 18, 2021. It is now read-only.

Commit

Permalink
cmd/cue/cmd: control task dependency using before and after fields
Browse files Browse the repository at this point in the history
  • Loading branch information
adieu committed Dec 3, 2019
1 parent d372ba8 commit 17939e0
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 1 deletion.
51 changes: 50 additions & 1 deletion cmd/cue/cmd/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ func doTasks(cmd *Command, typ, command string, root *cue.Instance) error {
return err
}

func isTask(index map[taskKey]*task, root *cue.Instance, value cue.Value) (*task, bool) {
inst, path := value.Reference()
if path != nil && inst == root {
if task, ok := index[keyForReference(path)]; ok {
return task, true
}
}
return nil, false
}

// executeTasks runs user-defined tasks as part of a user-defined command.
//
// All tasks are started at once, but will block until tasks that they depend
Expand Down Expand Up @@ -155,9 +165,48 @@ func executeTasks(typ, command string, root *cue.Instance) (err error) {
// Mark dependencies for unresolved nodes.
for _, t := range queue {
task := tasks.Lookup(t.name)

// Inject dependency in `after` field
after := task.Lookup("after")
if after.Err() == nil {
if dep, ok := isTask(index, root, after); ok {
t.dep[dep] = true
}
iter, err := after.List()
if err == nil {
for iter.Next() {
if dep, ok := isTask(index, root, iter.Value()); ok {
t.dep[dep] = true
}
}
}
}

// Inject reverse dependency in `before` field
before := task.Lookup("before")
if before.Err() == nil {
if dep, ok := isTask(index, root, before); ok {
dep.dep[t] = true
}
iter, err := before.List()
if err == nil {
for iter.Next() {
if dep, ok := isTask(index, root, iter.Value()); ok {
dep.dep[t] = true
}
}
}
}

task.Walk(func(v cue.Value) bool {
if v == task {
return true
}
if (after.Err() == nil && v.Equals(after)) || (before.Err() == nil && v.Equals(before)) {
return false
}
for _, r := range appendReferences(nil, root, v) {
if dep, ok := index[keyForReference(r)]; ok {
if dep, ok := index[keyForReference(r)]; ok && t != dep {
v := root.Lookup(r...)
if v.IsIncomplete() && v.Kind() != cue.StructKind {
t.dep[dep] = true
Expand Down
40 changes: 40 additions & 0 deletions cmd/cue/cmd/testdata/script/cmd_after.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
cue cmd after
cmp stdout expect-stdout

-- expect-stdout --
true

-- after_tool.cue --
package home

import (
"tool/exec"
"tool/cli"
"strings"
)

command: after: {
task: {
t1: exec.Run & {
cmd: ["sh", "-c", "sleep 1; date +%s%N"]
stdout: string
}
t2: exec.Run & {
cmd: ["sh", "-c", "date +%s%N"]
stdout: string
after: task.t1
}
t3: exec.Run & {
cmd: ["sh", "-c", "a=\(strings.TrimSpace(task.t1.stdout));b=\(strings.TrimSpace(task.t2.stdout));if [ $a -lt $b ]; then echo 'true'; fi"]
stdout: string
}
t4: cli.Print & {
text: task.t3.stdout
}
}
}

-- task.cue --
package home

-- cue.mod --
45 changes: 45 additions & 0 deletions cmd/cue/cmd/testdata/script/cmd_before.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
cue cmd before
cmp stdout expect-stdout

-- expect-stdout --
true

-- before_tool.cue --
package home

import (
"tool/exec"
"tool/cli"
"strings"
)

command: before: {
task: {
t1: exec.Run & {
cmd: ["sh", "-c", "sleep 1; date +%s%N"]
stdout: string
before: [task.t2, task.t3]
}
t2: exec.Run & {
cmd: ["sh", "-c", "date +%s%N"]
stdout: string
before: task.t4
}
t3: exec.Run & {
cmd: ["sh", "-c", "date +%s%N"]
stdout: string
}
t4: exec.Run & {
cmd: ["sh", "-c", "a=\(strings.TrimSpace(task.t1.stdout));b=\(strings.TrimSpace(task.t2.stdout));if [ $a -lt $b ]; then echo 'true'; fi"]
stdout: string
}
t5: cli.Print & {
text: task.t4.stdout
}
}
}

-- task.cue --
package home

-- cue.mod --

0 comments on commit 17939e0

Please sign in to comment.