diff --git a/docs/faq.md b/docs/faq.md index fac1428d..c08f2de4 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -216,6 +216,21 @@ requires a number of seconds as an argument. ./mgmt run lang examples/lang/hello0.mcl --converged-timeout=5 ``` +### Can I run `mgmt` for type-checking only? + +Yes, you can, add the `--only-unify` option to the lang frontend while using the +`run` command, and it will exit after type unification. + +#### Example: + +``` +./mgmt run --tmp-prefix lang --only-unify examples/lang/hello0.mcl +``` + +It will also print how long it took on either success or failure. Keep in mind +that even if you pass type unification, an `mgmt` run can still fail later on +for other reasons, although these are mostly runtime considerations. + ### Why does my file resource error with `no such file or directory`? If you create a file resource and only specify the content like this: diff --git a/lang/gapi/gapi.go b/lang/gapi/gapi.go index 40205da2..ea837b48 100644 --- a/lang/gapi/gapi.go +++ b/lang/gapi/gapi.go @@ -24,6 +24,7 @@ import ( "fmt" "strings" "sync" + "time" "github.com/purpleidea/mgmt/gapi" "github.com/purpleidea/mgmt/lang" @@ -97,6 +98,10 @@ func (obj *GAPI) CliFlags(command string) []cli.Flag { Name: "update", Usage: "update all dependencies to the latest versions", }, + &cli.BoolFlag{ + Name: "only-unify", + Usage: "stop after type unification", + }, } result = append(result, runFlags...) } @@ -318,14 +323,25 @@ func (obj *GAPI) Cli(cliInfo *gapi.CliInfo) (*gapi.Deploy, error) { } } logf("running type unification...") + startTime := time.Now() unifier := &unification.Unifier{ AST: iast, Solver: unification.SimpleInvariantSolverLogger(unificationLogf), Debug: debug, Logf: unificationLogf, } - if err := unifier.Unify(); err != nil { - return nil, errwrap.Wrapf(err, "could not unify types") + unifyErr := unifier.Unify() + delta := time.Since(startTime) + if unifyErr != nil { + if c.Bool("only-unify") { + logf("type unification failed after %s", delta) + } + return nil, errwrap.Wrapf(unifyErr, "could not unify types") + } + + if c.Bool("only-unify") { + logf("type unification succeeded in %s", delta) + return nil, nil // we end early } // get the list of needed files (this is available after SetScope) diff --git a/lib/run.go b/lib/run.go index e0856c2f..93a1d435 100644 --- a/lib/run.go +++ b/lib/run.go @@ -79,6 +79,9 @@ func run(c *cli.Context, name string, gapiObj gapi.GAPI) error { if err != nil { return errwrap.Wrapf(err, "cli parse error") } + if c.Bool("only-unify") && deploy == nil { + return nil // we end early + } obj.Deploy = deploy if obj.Deploy == nil { // nobody activated, but we'll still watch the etcd deploy chan,