Skip to content

New Flag: -nodeps: skip target dependencies when executing target #251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions mage/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ type Invocation struct {
List bool // tells the magefile to print out a list of targets
Help bool // tells the magefile to print out help for a specific target
Keep bool // tells mage to keep the generated main file after compiling
NoDeps bool // tells mage to execute the given target without dependencies
Timeout time.Duration // tells mage to set a timeout to running the targets
CompileOut string // tells mage to compile a static binary to this path, but not execute
GOOS string // sets the GOOS when producing a binary with -compileout
Expand Down Expand Up @@ -174,6 +175,7 @@ func Parse(stderr, stdout io.Writer, args []string) (inv Invocation, cmd Command
fs.BoolVar(&inv.Help, "h", false, "show this help")
fs.DurationVar(&inv.Timeout, "t", 0, "timeout in duration parsable format (e.g. 5m30s)")
fs.BoolVar(&inv.Keep, "keep", false, "keep intermediate mage files around after running")
fs.BoolVar(&inv.NoDeps, "nodeps", false, "execute the given target without it's dependencies")
fs.StringVar(&inv.Dir, "d", ".", "run magefiles in the given directory")
fs.StringVar(&inv.GoCmd, "gocmd", mg.GoCmd(), "use the given go binary to compile the output")
fs.StringVar(&inv.GOOS, "goos", "", "set GOOS for binary produced with -compile")
Expand Down Expand Up @@ -213,6 +215,7 @@ Options:
-h show description of a target
-f force recreation of compiled magefile
-keep keep intermediate mage files around after running
-nodeps execute the given target without it's dependencies
-gocmd <string>
use the given go binary to compile the output (default: "go")
-goos sets the GOOS for the binary created by -compile (default: current OS)
Expand Down Expand Up @@ -625,6 +628,9 @@ func RunCompiled(inv Invocation, exePath string, errlog *log.Logger) int {
if inv.Timeout > 0 {
c.Env = append(c.Env, fmt.Sprintf("MAGEFILE_TIMEOUT=%s", inv.Timeout.String()))
}
if inv.NoDeps {
c.Env = append(c.Env, "MAGEFILE_NODEPS=1")
}
debug.Print("running magefile with mage vars:\n", strings.Join(filter(c.Env, "MAGEFILE"), "\n"))
err := c.Run()
if !sh.CmdRan(err) {
Expand Down
4 changes: 4 additions & 0 deletions mg/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ func CtxDeps(ctx context.Context, fns ...interface{}) {

// runDeps assumes you've already called checkFns.
func runDeps(ctx context.Context, types []funcType, fns []interface{}) {
if os.Getenv(NoDepsEnv) == "1" {
return
}

mu := &sync.Mutex{}
var errs []string
var exit int
Expand Down
60 changes: 60 additions & 0 deletions mg/deps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log"
"os"
"testing"
"time"
)
Expand Down Expand Up @@ -192,3 +193,62 @@ func TestDepsErrors(t *testing.T) {
}()
f()
}

func TestDepsWithNoDepsSet(t *testing.T) {
if err := os.Setenv(NoDepsEnv, "1"); err != nil {
t.Fatalf("Failed to set %s for test", NoDepsEnv)
}
defer func() {
if err := os.Unsetenv(NoDepsEnv); err != nil {
t.Fatalf("Failed to clear %s after test", NoDepsEnv)
}
}()

ch := make(chan string, 3)
// this->f->g->h
h := func() {
ch <- "h"
}
g := func() {
Deps(h)
ch <- "g"
}
f := func() {
Deps(g)
ch <- "f"
}
Deps(f)

if len(ch) != 0 {
t.Errorf("Expected no deps to run but %d ran", len(ch))
}
}

func TestSerialDepsWithNoDepsSet(t *testing.T) {
if err := os.Setenv(NoDepsEnv, "1"); err != nil {
t.Fatalf("Failed to set %s for test", NoDepsEnv)
}
defer func() {
if err := os.Unsetenv(NoDepsEnv); err != nil {
t.Fatalf("Failed to clear %s after test", NoDepsEnv)
}
}()

ch := make(chan string, 3)
// this->f->g->h
h := func() {
ch <- "h"
}
g := func() {
ch <- "g"
}
f := func() {
SerialDeps(g, h)
ch <- "f"
}
Deps(f)

if len(ch) != 0 {
t.Errorf("Expected no deps to run but %d ran", len(ch))
}
}
4 changes: 4 additions & 0 deletions mg/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ const GoCmdEnv = "MAGEFILE_GOCMD"
// to ignore the default target specified in the magefile.
const IgnoreDefaultEnv = "MAGEFILE_IGNOREDEFAULT"

// NoDepsEnv is the environment variable that indicates the user requested
// that dependencies of the target not be executed
const NoDepsEnv = "MAGEFILE_NODEPS"

// Verbose reports whether a magefile was run with the verbose flag.
func Verbose() bool {
b, _ := strconv.ParseBool(os.Getenv(VerboseEnv))
Expand Down
10 changes: 10 additions & 0 deletions site/content/dependencies/_index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,13 @@ Build running
Note that since f and g do not depend on each other, and they're running in
their own goroutines, their order is non-deterministic, other than they are
guaranteed to run after h has finished, and before Build continues.

### Skipping Dependencies

You can tell mage to execute a target but not its dependencies by passing
the `-nodeps` flag when running mage. Using the example above, running
`mage -nodeps build` will produce the following output:

```bash
Build running
```