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: improve $after semantics and errors
Browse files Browse the repository at this point in the history
- report error if not a reference
- reference must be exact (may not point inside task)
- reference may refer to task group

Issue #245

Change-Id: Ib210ab38e0cb6bb750d4c020f9e7138442169ac3
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/4906
Reviewed-by: Grant Zvolský <grant@zvolsky.org>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
  • Loading branch information
mpvl committed Feb 9, 2020
1 parent f8afaed commit 8fbf67e
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 24 deletions.
51 changes: 38 additions & 13 deletions cmd/cue/cmd/custom.go
Expand Up @@ -19,7 +19,6 @@ package cmd
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
Expand All @@ -33,6 +32,7 @@ import (
"golang.org/x/sync/errgroup"

"cuelang.org/go/cue"
"cuelang.org/go/cue/errors"
"cuelang.org/go/internal"
itask "cuelang.org/go/internal/task"
"cuelang.org/go/internal/walk"
Expand Down Expand Up @@ -129,7 +129,7 @@ func (r *customRunner) keyForTask(t *task) taskKey {
}

func keyForReference(ref ...string) (k taskKey) {
return taskKey(strings.Join(ref, "\000"))
return taskKey(strings.Join(ref, "\000") + "\000")
}

func (r *customRunner) taskPath(t *task) []string {
Expand All @@ -146,14 +146,38 @@ func doTasks(cmd *Command, typ, command string, root *cue.Instance) error {
return err
}

func (r *customRunner) referredTask(ref cue.Value) (t *task, ok bool) {
func (r *customRunner) tagReference(t *task, ref cue.Value) error {
inst, path := ref.Reference()
if path != nil && inst == r.root {
if task := r.findTask(path); task != nil {
return task, true
if len(path) == 0 {
return errors.Newf(ref.Pos(),
"$after must be a reference or list of references, found %s", ref)
}
if inst != r.root {
return errors.Newf(ref.Pos(),
"reference in $after must refer to value in same package")
}
// TODO: allow referring to group of tasks.
if !r.tagDependencies(t, path) {
return errors.Newf(ref.Pos(),
"reference %s does not refer to task or task group",
strings.Join(path, "."), // TODO: more correct representation.
)

}
return nil
}

// tagDependencies marks dependencies in t correpsoning to ref
func (r *customRunner) tagDependencies(t *task, ref []string) bool {
found := false
prefix := keyForReference(ref...)
for key, task := range r.index {
if strings.HasPrefix(string(key), string(prefix)) {
found = true
t.dep[task] = true
}
}
return nil, false
return found
}

func (r *customRunner) findTask(ref []string) *task {
Expand Down Expand Up @@ -221,14 +245,15 @@ func executeTasks(cmd *Command, typ, command string, inst *cue.Instance) (err er
// Inject dependency in `$after` field
after := task.Lookup("$after")
if after.Err() == nil {
if dep, ok := cr.referredTask(after); ok {
t.dep[dep] = true
}
for iter, _ := after.List(); iter.Next(); {
if dep, ok := cr.referredTask(iter.Value()); ok {
t.dep[dep] = true
if after.Kind() != cue.ListKind {
err = cr.tagReference(t, after)
} else {
for iter, _ := after.List(); iter.Next(); {
err = cr.tagReference(t, iter.Value())
exitIfErr(cmd, inst, err, true)
}
}
exitIfErr(cmd, inst, err, true)
}

task.Walk(func(v cue.Value) bool {
Expand Down
27 changes: 16 additions & 11 deletions cmd/cue/cmd/testdata/script/cmd_after.txt
Expand Up @@ -4,6 +4,7 @@ cmp stdout expect-stdout
-- expect-stdout --
true

SUCCESS
-- after_tool.cue --
package home

Expand All @@ -14,21 +15,25 @@ import (
)

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

Expand Down

0 comments on commit 8fbf67e

Please sign in to comment.