From aad0296df097f1db56acfb58f04062dc3af8f789 Mon Sep 17 00:00:00 2001 From: Michel Casabianca Date: Wed, 25 Sep 2024 09:43:34 +0200 Subject: [PATCH] Merge fix-15-depends --- README.md | 2 +- build.yml | 8 +-- neon/build/context.go | 40 ++++++++----- neon/build/history.go | 56 ++++++++++++++++++ neon/build/print.go | 85 +++++++++++++++++---------- neon/build/print_test.go | 4 +- neon/build/repo.go | 6 +- neon/build/target.go | 9 ++- neon/main.go | 13 ++-- neon/main_test.go | 5 +- neon/task/call.go | 4 +- neon/task/chdir.go | 2 +- neon/task/chmod.go | 2 +- neon/task/classpath.go | 2 +- neon/task/copy.go | 2 +- neon/task/delete.go | 2 +- neon/task/dotenv.go | 2 +- neon/task/javac.go | 2 +- neon/task/link.go | 2 +- neon/task/mkdir.go | 2 +- neon/task/move.go | 2 +- neon/task/path.go | 2 +- neon/task/print.go | 6 +- neon/task/prompt.go | 2 +- neon/task/replace.go | 2 +- neon/task/shell.go | 4 +- neon/task/sleep.go | 4 +- neon/task/tar.go | 2 +- neon/task/threads.go | 10 ++-- neon/task/throw.go | 4 +- neon/task/time.go | 2 +- neon/task/touch.go | 2 +- neon/task/untar.go | 2 +- neon/task/unzip.go | 2 +- neon/task/zip.go | 2 +- test/bugs/2.tst | 12 ++++ test/bugs/2.yml | 19 +++--- test/bugs/3.yml | 5 +- test/bugs/4.tst | 11 ++++ test/bugs/4.yml | 18 ++++-- test/bugs/5.tst | 15 +++++ test/bugs/5.yml | 22 +++---- test/bugs/{6.context.ank => 6.ank} | 0 test/bugs/6.parent.yml | 2 - test/bugs/6.tst | 11 ++++ test/bugs/6.yml | 8 ++- test/bugs/{infinite-1.tst => 7-1.tst} | 2 + test/bugs/7-2.tst | 15 +++++ test/bugs/{infinite-3.tst => 7-3.tst} | 2 + test/bugs/{infinite-2.tst => 7-4.tst} | 4 +- test/bugs/7-5.tst | 14 +++++ test/bugs/7-6.tst | 34 +++++++++++ test/bugs/7.yml | 63 ++++++++------------ 53 files changed, 383 insertions(+), 172 deletions(-) create mode 100644 neon/build/history.go create mode 100644 test/bugs/2.tst create mode 100644 test/bugs/4.tst create mode 100644 test/bugs/5.tst rename test/bugs/{6.context.ank => 6.ank} (100%) delete mode 100644 test/bugs/6.parent.yml create mode 100644 test/bugs/6.tst rename test/bugs/{infinite-1.tst => 7-1.tst} (75%) create mode 100644 test/bugs/7-2.tst rename test/bugs/{infinite-3.tst => 7-3.tst} (72%) rename test/bugs/{infinite-2.tst => 7-4.tst} (72%) create mode 100644 test/bugs/7-5.tst create mode 100644 test/bugs/7-6.tst diff --git a/README.md b/README.md index e5ee5205..b9cd8501 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # NeON -[![Build Status](https://travis-ci.org/c4s4/neon.svg?branch=master)](https://travis-ci.org/c4s4/neon) + [![Code Quality](https://goreportcard.com/badge/github.com/c4s4/neon)](https://goreportcard.com/report/github.com/c4s4/neon) [![Codecov](https://codecov.io/gh/c4s4/neon/branch/master/graph/badge.svg)](https://codecov.io/gh/c4s4/neon) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) diff --git a/build.yml b/build.yml index 592e4c41..d323135d 100644 --- a/build.yml +++ b/build.yml @@ -25,12 +25,10 @@ targets: depends: [version-test, build] steps: - for: file - in: 'find(joinpath("test", "bugs"), "*.yml")' + in: 'find(".", "test/bugs/*.yml")' do: - - 'path = joinpath("test", "bugs", file)' - - print: "Running build file '={path}'" - - try: - - $: ['bin/neon', '-file', =path] + - print: "Running build file '={file}'" + - $: ['neon', '-file', =file] refs: doc: Generate reference documentation diff --git a/neon/build/context.go b/neon/build/context.go index 17bc8cbc..3ccf316a 100644 --- a/neon/build/context.go +++ b/neon/build/context.go @@ -2,16 +2,17 @@ package build import ( "fmt" - "github.com/mattn/anko/core" - "github.com/mattn/anko/packages" - "github.com/mattn/anko/parser" - "github.com/mattn/anko/vm" "os" "reflect" "regexp" "runtime" "sort" "strings" + + "github.com/mattn/anko/core" + "github.com/mattn/anko/packages" + "github.com/mattn/anko/parser" + "github.com/mattn/anko/vm" ) const ( @@ -38,9 +39,10 @@ var ( // - Index: tracks steps index while running build // - Stack: tracks targets calls type Context struct { - VM *vm.Env - Build *Build - Stack *Stack + VM *vm.Env + Build *Build + Stack *Stack + History *History } // NewContext make a new build context @@ -51,9 +53,10 @@ func NewContext(build *Build) *Context { packages.DefineImport(v) LoadBuiltins(v) context := &Context{ - VM: v, - Build: build, - Stack: NewStack(), + VM: v, + Build: build, + Stack: NewStack(), + History: NewHistory(), } return context } @@ -62,9 +65,10 @@ func NewContext(build *Build) *Context { // Return: a pointer to the context copy func (context *Context) Copy() *Context { another := &Context{ - VM: context.VM.DeepCopy(), - Build: context.Build, - Stack: context.Stack.Copy(), + VM: context.VM.DeepCopy(), + Build: context.Build, + Stack: context.Stack.Copy(), + History: context.History.Copy(), } return another } @@ -372,11 +376,17 @@ func (context *Context) EvaluateEnvironment() ([]string, error) { return lines, nil } +// Message print a message on the console +// - text: the text to print on console +func (context *Context) Message(text string) { + Message(text) +} + // Message print a message on the console // - text: the text to print on console // - args: a slice of string arguments (as for fmt.Printf()) -func (context *Context) Message(text string, args ...interface{}) { - Message(text, args...) +func (context *Context) MessageArgs(text string, args ...interface{}) { + MessageArgs(text, args...) } // FormatScriptError adds line and column numbers on parser or vm errors. diff --git a/neon/build/history.go b/neon/build/history.go new file mode 100644 index 00000000..bca20de1 --- /dev/null +++ b/neon/build/history.go @@ -0,0 +1,56 @@ +package build + +import ( + "strings" +) + +// History is structure for an history +type History struct { + Targets []string +} + +// NewHistory makes a new history +// Returns: a pointer to the history +func NewHistory() *History { + history := History{ + Targets: make([]string, 0), + } + return &history +} + +// Contains tells if the history contains given target +// - target: target to test +// Returns: a boolean telling if target is in the history +func (history *History) Contains(name string) bool { + for _, target := range history.Targets { + if name == target { + return true + } + } + return false +} + +// Push a target on the history +// - target: target to push on the history +// Return: an error if we are in an infinite loop +func (history *History) Push(target *Target) error { + history.Targets = append(history.Targets, target.Name) + return nil +} + +// ToString returns string representation of the history, such as: +// "foo, bar, spam" +// Return: the history as a string +func (history *History) String() string { + names := make([]string, len(history.Targets)) + copy(names, history.Targets) + return strings.Join(names, ", ") +} + +// Copy returns a copy of the history +// Return: pointer to a copy of the history +func (history *History) Copy() *History { + another := make([]string, len(history.Targets)) + copy(another, history.Targets) + return &History{another} +} diff --git a/neon/build/print.go b/neon/build/print.go index be71565c..4942ee70 100644 --- a/neon/build/print.go +++ b/neon/build/print.go @@ -2,16 +2,17 @@ package build import ( "fmt" - "github.com/c4s4/neon/neon/util" - "github.com/fatih/color" "strings" "unicode/utf8" + + "github.com/c4s4/neon/neon/util" + "github.com/fatih/color" ) type colorizer func(a ...interface{}) string -// Grey is a flag that tells if we print on console without color -var Grey = false +// Gray is a flag that tells if we print on console without color +var Gray = false // Color definitions var colorTitle colorizer @@ -20,19 +21,35 @@ var colorError colorizer // Message prints a message on console: // - text: text to print (that might embed fields to print, such as "%s") +func Message(text string) { + printGray(text) +} + +// MessageArgs prints a message on console: +// - text: text to print (that might embed fields to print, such as "%s") // - args: arguments for the text to print -func Message(text string, args ...interface{}) { - printGrey(text, args...) +func MessageArgs(text string, args ...interface{}) { + printGrayArgs(text, args...) } // Info prints an information message on console: // - text: text to print (that might embed fields to print, such as "%s") +func Info(text string) { + if Gray { + printGray(text) + } else { + printColor(colorTitle(text)) + } +} + +// InfoArgs prints an information message on console: +// - text: text to print (that might embed fields to print, such as "%s") // - args: arguments for the text to print -func Info(text string, args ...interface{}) { - if Grey { - printGrey(text, args...) +func InfoArgs(text string, args ...interface{}) { + if Gray { + printGrayArgs(text, args...) } else { - printColor(colorTitle(text), args...) + printColorArgs(colorTitle(text), args...) } } @@ -44,8 +61,8 @@ func Title(text string) { length = 2 } message := fmt.Sprintf("%s %s --", strings.Repeat("-", length), text) - if Grey { - printGrey(message) + if Gray { + printGray(message) } else { printColor(colorTitle(message)) } @@ -53,8 +70,8 @@ func Title(text string) { // PrintOk prints a green OK on the console func PrintOk() { - if Grey { - printGrey("OK") + if Gray { + printGray("OK") } else { printColor(colorOk("OK")) } @@ -64,33 +81,37 @@ func PrintOk() { // text // - text: the explanatory text to print func PrintError(text string) { - if Grey { - printGrey("ERROR %s", text) + if Gray { + printGrayArgs("ERROR %s", text) } else { - printColor("%s %s", colorError("ERROR"), text) + printColorArgs("%s %s", colorError("ERROR"), text) } } +// PrintColor prints a string in given color +// - text: the text to print +func printColor(text string) { + fmt.Println(text) +} + // PrintColor prints a string with arguments in given color // - text: the text to print // - args: the arguments for the text to print -func printColor(text string, args ...interface{}) { - if len(args) > 0 { - fmt.Fprintf(color.Output, text, args...) - fmt.Println() - } else { - fmt.Println(text) - } +func printColorArgs(text string, args ...interface{}) { + fmt.Fprintf(color.Output, text, args...) + fmt.Println() } -// PrintGrey prints a string with arguments in grey +// PrintGrey prints a string in gray +// - text: the text to print +func printGray(text string) { + fmt.Println(text) +} + +// PrintGreyArgs prints a string with arguments in gray // - text: the text to print // - args: the arguments for the text to print -func printGrey(text string, fields ...interface{}) { - if len(fields) > 0 { - fmt.Printf(text, fields...) - fmt.Println() - } else { - fmt.Println(text) - } +func printGrayArgs(text string, fields ...interface{}) { + fmt.Printf(text, fields...) + fmt.Println() } diff --git a/neon/build/print_test.go b/neon/build/print_test.go index e9283f3a..a57d89a3 100644 --- a/neon/build/print_test.go +++ b/neon/build/print_test.go @@ -34,13 +34,13 @@ func TestInfoNotGrey(t *testing.T) { } func TestInfoGrey(t *testing.T) { - Grey = true + Gray = true stdout := os.Stdout read, write, _ := os.Pipe() os.Stdout = write Info("This is a test!") os.Stdout = stdout - Grey = false + Gray = false write.Close() out, _ := io.ReadAll(read) if string(out) != "This is a test!\n" { diff --git a/neon/build/repo.go b/neon/build/repo.go index 44fdce4b..139eedce 100644 --- a/neon/build/repo.go +++ b/neon/build/repo.go @@ -105,12 +105,12 @@ func InstallPlugin(plugin, repository string) error { } pluginPath := filepath.Join(repository, plugin) if util.DirExists(pluginPath) { - Message("Plugin '%s' already installed in '%s'", plugin, pluginPath) + MessageArgs("Plugin '%s' already installed in '%s'", plugin, pluginPath) return nil } gitRepository := "https://" + PluginSite + "/" + plugin + ".git" command := exec.Command("git", "clone", gitRepository, pluginPath) - Message("Running command '%s'...", strings.Join(command.Args, " ")) + MessageArgs("Running command '%s'...", strings.Join(command.Args, " ")) output, err := command.CombinedOutput() if err != nil { re = regexp.MustCompile("\n\n") @@ -119,7 +119,7 @@ func InstallPlugin(plugin, repository string) error { Message(message) return fmt.Errorf("installing plugin '%s'", plugin) } - Message("Plugin '%s' installed in '%s'", plugin, pluginPath) + MessageArgs("Plugin '%s' installed in '%s'", plugin, pluginPath) return nil } diff --git a/neon/build/target.go b/neon/build/target.go index f2587346..b4f6648e 100644 --- a/neon/build/target.go +++ b/neon/build/target.go @@ -140,9 +140,14 @@ func (target *Target) Run(context *Context) error { if err := context.Stack.Push(target); err != nil { return err } + if err := context.History.Push(target); err != nil { + return err + } for _, name := range target.Depends { - if err := target.Build.Root.RunTarget(context, name); err != nil { - return err + if !context.History.Contains(name) { + if err := target.Build.Root.RunTarget(context, name); err != nil { + return err + } } } Title(target.Name) diff --git a/neon/main.go b/neon/main.go index 031b7a10..34277509 100644 --- a/neon/main.go +++ b/neon/main.go @@ -3,13 +3,14 @@ package main import ( "flag" "fmt" + "os" + "path/filepath" + "time" + _build "github.com/c4s4/neon/neon/build" _ "github.com/c4s4/neon/neon/builtin" _ "github.com/c4s4/neon/neon/task" "github.com/c4s4/neon/neon/util" - "os" - "path/filepath" - "time" "gopkg.in/yaml.v2" ) @@ -65,7 +66,7 @@ func LoadConfiguration(file string) (*Configuration, error) { return nil, err } // apply grey - _build.Grey = configuration.Grey + _build.Gray = configuration.Grey // apply theme if configuration.Theme != "" { err := _build.ApplyThemeByName(configuration.Theme) @@ -178,7 +179,7 @@ func main() { } repo = util.ExpandUserHome(repo) } - _build.Grey = grey + _build.Gray = grey configuration.Time = timeit if printInfo(tasks, builtins, templates, parents, themes, tasksRef, builtinsRef, task, builtin, repo) { return @@ -229,7 +230,7 @@ func main() { err = build.Run(context, targets) duration := time.Since(start) if configuration.Time || duration.Seconds() > 10 { - _build.Info("Build duration: %s", duration.String()) + _build.InfoArgs("Build duration: %s", duration.String()) } PrintError(err) _build.PrintOk() diff --git a/neon/main_test.go b/neon/main_test.go index 55f6817e..7ecced1c 100644 --- a/neon/main_test.go +++ b/neon/main_test.go @@ -1,11 +1,12 @@ package main import ( - "github.com/c4s4/neon/neon/build" "os" "reflect" "strings" "testing" + + "github.com/c4s4/neon/neon/build" ) func TestParseConfiguration(t *testing.T) { @@ -75,7 +76,7 @@ foo: bars` if err != nil { t.Errorf("Error parsing configuration") } - if build.Grey != true { + if build.Gray != true { t.Errorf("Error parsing configuration") } } diff --git a/neon/task/call.go b/neon/task/call.go index 11e1ee81..9b5fe497 100644 --- a/neon/task/call.go +++ b/neon/task/call.go @@ -30,11 +30,13 @@ type callArgs struct { func call(context *build.Context, args interface{}) error { params := args.(callArgs) for _, target := range params.Call { - context.Message("Calling target '%s'", target) + stack := context.Stack.Copy() + context.MessageArgs("Calling target '%s'", target) err := context.Build.RunTarget(context, target) if err != nil { return err } + context.Stack = stack } return nil } diff --git a/neon/task/chdir.go b/neon/task/chdir.go index 617c4ca2..4e6bb57f 100644 --- a/neon/task/chdir.go +++ b/neon/task/chdir.go @@ -35,7 +35,7 @@ type chdirArgs struct { func chdir(context *build.Context, args interface{}) error { params := args.(chdirArgs) - context.Message("Changing working directory to '%s'", params.Chdir) + context.MessageArgs("Changing working directory to '%s'", params.Chdir) err := os.Chdir(params.Chdir) if err != nil { return fmt.Errorf("changing working directory to '%s': %s", params.Chdir, err) diff --git a/neon/task/chmod.go b/neon/task/chmod.go index 49b0713c..9311ca97 100644 --- a/neon/task/chmod.go +++ b/neon/task/chmod.go @@ -59,7 +59,7 @@ func chmod(context *build.Context, args interface{}) error { if len(files) < 1 { return nil } - context.Message("Changing %d file(s) mode to %#o", len(files), params.Mode) + context.MessageArgs("Changing %d file(s) mode to %#o", len(files), params.Mode) for _, file := range files { if params.Dir != "" { file = filepath.Join(params.Dir, file) diff --git a/neon/task/classpath.go b/neon/task/classpath.go index 4b140a30..3fa6e683 100644 --- a/neon/task/classpath.go +++ b/neon/task/classpath.go @@ -172,7 +172,7 @@ func getDependency(file string, scopes, repositories []string, context *build.Co } func downloadDependency(dependency dependency, repositories []string, context *build.Context) error { - context.Message("Downloading dependency '%s'", dependency.String()) + context.MessageArgs("Downloading dependency '%s'", dependency.String()) path := dependency.Path(LocalRepository) dir := filepath.Dir(path) if !util.DirExists(dir) { diff --git a/neon/task/copy.go b/neon/task/copy.go index 47cad187..3126c107 100644 --- a/neon/task/copy.go +++ b/neon/task/copy.go @@ -72,7 +72,7 @@ func copy(context *build.Context, args interface{}) error { if len(sources) < 1 { return nil } - context.Message("Copying %d file(s)", len(sources)) + context.MessageArgs("Copying %d file(s)", len(sources)) if params.Tofile != "" { file := filepath.Join(params.Dir, sources[0]) err = util.CopyFile(file, params.Tofile) diff --git a/neon/task/delete.go b/neon/task/delete.go index f050d987..3adf503f 100644 --- a/neon/task/delete.go +++ b/neon/task/delete.go @@ -51,7 +51,7 @@ func delete(context *build.Context, args interface{}) error { if len(files) < 1 { return nil } - context.Message("Deleting %d file(s) or directory(ies)", len(files)) + context.MessageArgs("Deleting %d file(s) or directory(ies)", len(files)) for _, file := range files { path := filepath.Join(params.Dir, file) if util.DirExists(path) { diff --git a/neon/task/dotenv.go b/neon/task/dotenv.go index f5e87ff0..ca8949cc 100644 --- a/neon/task/dotenv.go +++ b/neon/task/dotenv.go @@ -35,7 +35,7 @@ type dotenvArgs struct { func dotenv(context *build.Context, args interface{}) error { params := args.(dotenvArgs) - context.Message("Loading environment in dotenv file %s", params.Dotenv) + context.MessageArgs("Loading environment in dotenv file %s", params.Dotenv) err := LoadEnv(params.Dotenv) if err != nil { return fmt.Errorf("loading dotenv file: %v", err) diff --git a/neon/task/javac.go b/neon/task/javac.go index 67c958df..ef0041c2 100644 --- a/neon/task/javac.go +++ b/neon/task/javac.go @@ -64,7 +64,7 @@ func javac(context *build.Context, args interface{}) error { return fmt.Errorf("evaluating classpath: %v", err) } // run javac command - context.Message("Compiling %d Java source file(s)", len(sources)) + context.MessageArgs("Compiling %d Java source file(s)", len(sources)) opt := []string{"-d", params.Dest} if cp != "" { opt = append(opt, []string{"-cp", cp}...) diff --git a/neon/task/link.go b/neon/task/link.go index 0ed88d54..492413b8 100644 --- a/neon/task/link.go +++ b/neon/task/link.go @@ -34,7 +34,7 @@ type linkArgs struct { func link(context *build.Context, args interface{}) error { params := args.(linkArgs) - context.Message("Linking file '%s' to '%s'", params.Link, params.To) + context.MessageArgs("Linking file '%s' to '%s'", params.Link, params.To) err := os.Symlink(params.Link, params.To) if err != nil { return fmt.Errorf("linking files: %v", err) diff --git a/neon/task/mkdir.go b/neon/task/mkdir.go index 6baa4dea..d5f2b361 100644 --- a/neon/task/mkdir.go +++ b/neon/task/mkdir.go @@ -34,7 +34,7 @@ func mkdir(context *build.Context, args interface{}) error { params := args.(mkdirArgs) for _, dir := range params.Mkdir { if !util.DirExists(dir) { - context.Message("Making directory '%s'", dir) + context.MessageArgs("Making directory '%s'", dir) err := os.MkdirAll(dir, DirFileMode) if err != nil { return fmt.Errorf("making directory '%s': %s", dir, err) diff --git a/neon/task/move.go b/neon/task/move.go index 8620c5aa..1d907fd0 100644 --- a/neon/task/move.go +++ b/neon/task/move.go @@ -73,7 +73,7 @@ func move(context *build.Context, args interface{}) error { if len(sources) < 1 { return nil } - context.Message("Moving %d file(s)", len(sources)) + context.MessageArgs("Moving %d file(s)", len(sources)) if params.Tofile != "" { file := filepath.Join(params.Dir, sources[0]) if file != params.Tofile { diff --git a/neon/task/path.go b/neon/task/path.go index e895daba..a644de1e 100644 --- a/neon/task/path.go +++ b/neon/task/path.go @@ -47,7 +47,7 @@ func path(context *build.Context, args interface{}) error { if len(files) < 1 { return nil } - context.Message("Building path with %d file(s)", len(files)) + context.MessageArgs("Building path with %d file(s)", len(files)) path := strings.Join(files, string(filepath.ListSeparator)) context.SetProperty(params.To, path) return nil diff --git a/neon/task/print.go b/neon/task/print.go index b8503bcb..d1bb023b 100644 --- a/neon/task/print.go +++ b/neon/task/print.go @@ -34,9 +34,9 @@ Examples: } type printArgs struct { - Print string - Color string `neon:"optional"` - NoReturn bool `neon:"optional"` + Print string + Color string `neon:"optional"` + NoReturn bool `neon:"optional"` } // Colors is the color mapping diff --git a/neon/task/prompt.go b/neon/task/prompt.go index 2475be75..e5a2859d 100644 --- a/neon/task/prompt.go +++ b/neon/task/prompt.go @@ -85,7 +85,7 @@ func prompt(context *build.Context, args interface{}) error { if params.Error != "" { context.Message(params.Error) } else { - context.Message("value '%s' doesn't match pattern '%s'", value, params.Pattern) + context.MessageArgs("value '%s' doesn't match pattern '%s'", value, params.Pattern) } } else { done = true diff --git a/neon/task/replace.go b/neon/task/replace.go index 75469c55..36064d07 100644 --- a/neon/task/replace.go +++ b/neon/task/replace.go @@ -54,7 +54,7 @@ func replace(context *build.Context, args interface{}) error { return nil } for _, file := range files { - context.Message("Replacing text in file '%s'", file) + context.MessageArgs("Replacing text in file '%s'", file) if params.Dir != "" { file = filepath.Join(params.Dir, file) } diff --git a/neon/task/shell.go b/neon/task/shell.go index 49aefc8b..4f80a1f0 100644 --- a/neon/task/shell.go +++ b/neon/task/shell.go @@ -199,7 +199,7 @@ func run(command []string, args []string, stdout, stderr io.Writer, stdin io.Rea func runList(cmd []string, stdout, stderr io.Writer, stdin io.Reader, context *build.Context, verbose bool) error { if verbose { - context.Message("Running command: %s", strings.Join(cmd, " ")) + context.MessageArgs("Running command: %s", strings.Join(cmd, " ")) } environment, err := context.EvaluateEnvironment() if err != nil { @@ -242,7 +242,7 @@ func runList(cmd []string, stdout, stderr io.Writer, stdin io.Reader, context *b func runString(cmd string, stdout, stderr io.Writer, stdin io.Reader, context *build.Context, verbose bool) error { if verbose { - context.Message("Running command: %s", cmd) + context.MessageArgs("Running command: %s", cmd) } shell, err := context.Build.GetShell() if err != nil { diff --git a/neon/task/sleep.go b/neon/task/sleep.go index a693a008..92f42fa6 100644 --- a/neon/task/sleep.go +++ b/neon/task/sleep.go @@ -30,13 +30,13 @@ Examples: type sleepArgs struct { Sleep float64 - Mute bool `neon:"optional"` + Mute bool `neon:"optional"` } func sleep(context *build.Context, args interface{}) error { params := args.(sleepArgs) if !params.Mute { - context.Message("Sleeping for %g seconds...", params.Sleep) + context.MessageArgs("Sleeping for %g seconds...", params.Sleep) } t.Sleep(t.Duration(params.Sleep) * t.Second) return nil diff --git a/neon/task/tar.go b/neon/task/tar.go index 26db7ed2..d77c5f8d 100644 --- a/neon/task/tar.go +++ b/neon/task/tar.go @@ -57,7 +57,7 @@ func tar(context *build.Context, args interface{}) error { return fmt.Errorf("getting source files for tar task: %v", err) } if len(files) > 0 { - context.Message("Tarring %d file(s) into '%s'", len(files), params.Tofile) + context.MessageArgs("Tarring %d file(s) into '%s'", len(files), params.Tofile) err = writeTar(params.Dir, files, params.Prefix, params.Tofile) if err != nil { return fmt.Errorf("tarring files: %v", err) diff --git a/neon/task/threads.go b/neon/task/threads.go index c19b1a18..8ea91c05 100644 --- a/neon/task/threads.go +++ b/neon/task/threads.go @@ -78,7 +78,7 @@ func threads(context *build.Context, args interface{}) error { var wg sync.WaitGroup wg.Add(params.Threads) if params.Verbose { - context.Message("Starting %d threads", params.Threads) + context.MessageArgs("Starting %d threads", params.Threads) } output := make(chan interface{}, len(input)) for i := 0; i < params.Threads; i++ { @@ -114,8 +114,8 @@ func threads(context *build.Context, args interface{}) error { func runThread(steps build.Steps, ctx *build.Context, index int, input chan interface{}, output chan interface{}, wg *sync.WaitGroup, errors chan error, verbose bool) { if verbose { - ctx.Message("Thread %d started", index) - defer ctx.Message("Thread %d done", index) + ctx.MessageArgs("Thread %d started", index) + defer ctx.MessageArgs("Thread %d done", index) } defer wg.Done() for { @@ -127,7 +127,7 @@ func runThread(steps build.Steps, ctx *build.Context, index int, input chan inte threadContext.SetProperty(propertyInput, arg) _ = threadContext.DelProperty(propertyOutput) if verbose { - threadContext.Message("Thread %d iteration with input '%v'", index, arg) + threadContext.MessageArgs("Thread %d iteration with input '%v'", index, arg) } err := steps.Run(threadContext) out, _ := threadContext.GetProperty(propertyOutput) @@ -138,7 +138,7 @@ func runThread(steps build.Steps, ctx *build.Context, index int, input chan inte if out != nil { output <- out if verbose { - threadContext.Message("Thread %d output '%v'", index, out) + threadContext.MessageArgs("Thread %d output '%v'", index, out) } } } else { diff --git a/neon/task/throw.go b/neon/task/throw.go index 98bae805..572d35e4 100644 --- a/neon/task/throw.go +++ b/neon/task/throw.go @@ -1,7 +1,7 @@ package task import ( - "fmt" + "errors" "github.com/c4s4/neon/neon/build" "reflect" ) @@ -37,5 +37,5 @@ type throwArgs struct { func throw(context *build.Context, args interface{}) error { params := args.(throwArgs) - return fmt.Errorf(params.Throw) + return errors.New(params.Throw) } diff --git a/neon/task/time.go b/neon/task/time.go index e60bc3b2..9eb9cdc9 100644 --- a/neon/task/time.go +++ b/neon/task/time.go @@ -45,7 +45,7 @@ func time(context *build.Context, args interface{}) error { if params.To != "" { context.SetProperty(params.To, duration) } else { - context.Message("Duration: %gs", duration) + context.MessageArgs("Duration: %gs", duration) } return nil } diff --git a/neon/task/touch.go b/neon/task/touch.go index 572347fa..5a8aeac1 100644 --- a/neon/task/touch.go +++ b/neon/task/touch.go @@ -39,7 +39,7 @@ type touchArgs struct { func touch(context *build.Context, args interface{}) error { params := args.(touchArgs) - context.Message("Touching %d file(s)", len(params.Touch)) + context.MessageArgs("Touching %d file(s)", len(params.Touch)) for _, file := range params.Touch { if util.FileExists(file) { time := t.Now() diff --git a/neon/task/untar.go b/neon/task/untar.go index ec2917ac..80cd11ad 100644 --- a/neon/task/untar.go +++ b/neon/task/untar.go @@ -44,7 +44,7 @@ type untarArgs struct { func untar(context *build.Context, args interface{}) error { params := args.(untarArgs) - context.Message("Untarring archive '%s' to directory '%s'...", params.Untar, params.Todir) + context.MessageArgs("Untarring archive '%s' to directory '%s'...", params.Untar, params.Todir) err := untarFile(params.Untar, params.Todir) if err != nil { return fmt.Errorf("expanding archive: %v", err) diff --git a/neon/task/unzip.go b/neon/task/unzip.go index e09739d4..1a807d35 100644 --- a/neon/task/unzip.go +++ b/neon/task/unzip.go @@ -37,7 +37,7 @@ type unzipArgs struct { func unzip(context *build.Context, args interface{}) error { params := args.(unzipArgs) - context.Message("Unzipping archive '%s' to directory '%s'...", params.Unzip, params.Todir) + context.MessageArgs("Unzipping archive '%s' to directory '%s'...", params.Unzip, params.Todir) err := unzipFile(params.Unzip, params.Todir) if err != nil { return fmt.Errorf("expanding archive: %v", err) diff --git a/neon/task/zip.go b/neon/task/zip.go index fad6ec62..10e8690e 100644 --- a/neon/task/zip.go +++ b/neon/task/zip.go @@ -50,7 +50,7 @@ func zip(context *build.Context, args interface{}) error { return fmt.Errorf("getting source files for zip task: %v", err) } if len(files) > 0 { - context.Message("Zipping %d file(s) in '%s'", len(files), params.Tofile) + context.MessageArgs("Zipping %d file(s) in '%s'", len(files), params.Tofile) err = writeZip(params.Dir, files, params.Prefix, params.Tofile) if err != nil { return fmt.Errorf("zipping files: %v", err) diff --git a/test/bugs/2.tst b/test/bugs/2.tst new file mode 100644 index 00000000..696d4f84 --- /dev/null +++ b/test/bugs/2.tst @@ -0,0 +1,12 @@ +# Bug 2: error checking task args for mixed lists. +# Type is checked on the first element of the list only. +# Fixed on 2018-03-29. +# This build should fail with message: "field '$' must be of type '[]string'" + +default: bug-2 + +targets: + + bug-2: + steps: + - $: ['ls', 1] diff --git a/test/bugs/2.yml b/test/bugs/2.yml index 5f707974..18c88706 100644 --- a/test/bugs/2.yml +++ b/test/bugs/2.yml @@ -1,11 +1,16 @@ -# Bug 2: error checking task args for mixed lists. -# Type is checked on the first element of the list only. -# Fixed on 2018-03-29. - -default: bug-2 +default: bug +properties: + BUG: 2 targets: - bug-2: + bug: steps: - - $: ['ls', 1] + - 'fail = false' + - try: + - neon: '={BUG}.tst' + catch: + - 'fail = true' + - if: '!fail' + then: + - throw: "Should have failed" diff --git a/test/bugs/3.yml b/test/bugs/3.yml index 09aa0989..027554be 100644 --- a/test/bugs/3.yml +++ b/test/bugs/3.yml @@ -1,6 +1,7 @@ # Bug 3: Error accessing map elements +# This build must succeed and print "foo: 1" -default: bug-3 +default: bug properties: MAP: @@ -9,6 +10,6 @@ properties: targets: - bug-3: + bug: steps: - print: 'foo: ={MAP["foo"]}' diff --git a/test/bugs/4.tst b/test/bugs/4.tst new file mode 100644 index 00000000..802a60f0 --- /dev/null +++ b/test/bugs/4.tst @@ -0,0 +1,11 @@ +# Bug 4: Bad error message when parent target not found calling super +# Fixed on 2018-05-24 +# Must fail with message: "target 'bug-4' not found in parent build files" + +default: bug-4 + +targets: + + bug-4: + steps: + - super: diff --git a/test/bugs/4.yml b/test/bugs/4.yml index 3778dab8..bfc3cc58 100644 --- a/test/bugs/4.yml +++ b/test/bugs/4.yml @@ -1,10 +1,16 @@ -# Bug 4: Bad error message when parent target not found calling super -# Fixed on 2018-05-24 - -default: bug-4 +default: bug +properties: + BUG: 4 targets: - bug-4: + bug: steps: - - super: + - 'fail = false' + - try: + - neon: '={BUG}.tst' + catch: + - 'fail = true' + - if: '!fail' + then: + - throw: "Should have failed" diff --git a/test/bugs/5.tst b/test/bugs/5.tst new file mode 100644 index 00000000..2403097e --- /dev/null +++ b/test/bugs/5.tst @@ -0,0 +1,15 @@ +# Bug 5: when calling super after a call, super target is wrong +# This build must fail with message: "target 'bug-5' not found in parent build files" + +default: bug-5 + +targets: + + test: + steps: + - pass: + + bug-5: + steps: + - call: test + - super: diff --git a/test/bugs/5.yml b/test/bugs/5.yml index e5ec7285..e7918dd1 100644 --- a/test/bugs/5.yml +++ b/test/bugs/5.yml @@ -1,14 +1,16 @@ -# Bug 5: when calling super after a call, super target is wrong - -default: bug-5 +default: bug +properties: + BUG: 5 targets: - test: - steps: - - pass: - - bug-5: + bug: steps: - - call: test - - super: + - 'fail = false' + - try: + - neon: '={BUG}.tst' + catch: + - 'fail = true' + - if: '!fail' + then: + - throw: "Should have failed" diff --git a/test/bugs/6.context.ank b/test/bugs/6.ank similarity index 100% rename from test/bugs/6.context.ank rename to test/bugs/6.ank diff --git a/test/bugs/6.parent.yml b/test/bugs/6.parent.yml deleted file mode 100644 index 95028128..00000000 --- a/test/bugs/6.parent.yml +++ /dev/null @@ -1,2 +0,0 @@ -context: -- ./6.context.ank diff --git a/test/bugs/6.tst b/test/bugs/6.tst new file mode 100644 index 00000000..fd31d8b6 --- /dev/null +++ b/test/bugs/6.tst @@ -0,0 +1,11 @@ +# Bug 6: Doesn't load context script of parents build files +# This build must succeed and print "bug 6" + +context: +- ./6.ank + +targets: + + bug: + steps: + - print: "bug 6" diff --git a/test/bugs/6.yml b/test/bugs/6.yml index f11c8102..058ddf2f 100644 --- a/test/bugs/6.yml +++ b/test/bugs/6.yml @@ -1,12 +1,14 @@ # Bug 6: doesn't load parent context +# This build should succeed and print "bug 6" -default: bug-6 -extends: ./6.parent.yml +default: bug +extends: ./6.tst targets: - bug-6: + bug: steps: - if: '!defined("DEFINED")' then: - throw: 'Test failed' + - super: diff --git a/test/bugs/infinite-1.tst b/test/bugs/7-1.tst similarity index 75% rename from test/bugs/infinite-1.tst rename to test/bugs/7-1.tst index 20c2000b..e5c69bd7 100644 --- a/test/bugs/infinite-1.tst +++ b/test/bugs/7-1.tst @@ -1,3 +1,5 @@ +# This build file should succeed: test2 -> test1 + default: test1 targets: diff --git a/test/bugs/7-2.tst b/test/bugs/7-2.tst new file mode 100644 index 00000000..2ecf13de --- /dev/null +++ b/test/bugs/7-2.tst @@ -0,0 +1,15 @@ +# This build file should fail: test1 -> test2 -> test1 (infinite loop) + +default: test1 + +targets: + + test1: + steps: + - print: "test1" + - call: test2 + + test2: + steps: + - print: "test2" + - call: test1 diff --git a/test/bugs/infinite-3.tst b/test/bugs/7-3.tst similarity index 72% rename from test/bugs/infinite-3.tst rename to test/bugs/7-3.tst index e5f9dd04..cac3d301 100644 --- a/test/bugs/infinite-3.tst +++ b/test/bugs/7-3.tst @@ -1,3 +1,5 @@ +# This build file should fail: test1 -> test2 -> test1 + default: test1 targets: diff --git a/test/bugs/infinite-2.tst b/test/bugs/7-4.tst similarity index 72% rename from test/bugs/infinite-2.tst rename to test/bugs/7-4.tst index 7aee2fdf..073fbc63 100644 --- a/test/bugs/infinite-2.tst +++ b/test/bugs/7-4.tst @@ -1,11 +1,13 @@ +# This build file should fail: test1 -> test2 -> test1 + default: test1 targets: test1: steps: - - print: "test1" - call: test2 + - print: "test1" test2: steps: diff --git a/test/bugs/7-5.tst b/test/bugs/7-5.tst new file mode 100644 index 00000000..6aacd5ab --- /dev/null +++ b/test/bugs/7-5.tst @@ -0,0 +1,14 @@ +# This build file should succeed and print: test1 test1 + +default: test2 + +targets: + + test1: + steps: + - print: "test1" + + test2: + depends: test1 + steps: + - call: test1 diff --git a/test/bugs/7-6.tst b/test/bugs/7-6.tst new file mode 100644 index 00000000..a9fb502b --- /dev/null +++ b/test/bugs/7-6.tst @@ -0,0 +1,34 @@ +# This build file should succeed + +default: assert + +properties: + targets: [] + +targets: + + target1: + steps: + - print: "target 1" + - 'targets += 1' + + target2: + depends: "target1" + steps: + - print: "target 2" + - 'targets += 2' + + target3: + depends: ["target1", "target2"] + steps: + - print: "target 3" + - 'targets += 3' + + assert: + depends: target3 + steps: + - if: 'targets == [1, 2, 3]' + then: + - print: "Success!" + else: + - throw: "Failure! targets = ={targets}" diff --git a/test/bugs/7.yml b/test/bugs/7.yml index 18944aff..b2931b6d 100644 --- a/test/bugs/7.yml +++ b/test/bugs/7.yml @@ -1,44 +1,29 @@ -# Bug 7: bad infinite loop management - -default: infinite +default: bug +properties: + SUCCESS: + 1: true + 2: false + 3: false + 4: false + 5: true + 6: true targets: - infinite: - steps: - - call: infinite-1 - - call: infinite-2 - - call: infinite-3 - - infinite-1: - steps: - - try: - - neon: 'infinite-1.tst' - - throw: 'Test infinite 1 failed' - catch: - - if: > - _error != "running build 'infinite-1.tst': running target 'test1': running target 'test2': running target 'test1': infinite loop: test1 -> test2 -> test1" - then: - - throw: "Bad error message: ={_error}" - - infinite-2: - steps: - - try: - - neon: 'infinite-2.tst' - - throw: 'Test infinite 2 failed' - catch: - - if: > - _error != "running build 'infinite-2.tst': running target 'test1': in step 2: running target 'test2': in step 2: running target 'test1': infinite loop: test1 -> test2 -> test1" - then: - - throw: "Bad error message: ={_error}" - - infinite-3: + bug: steps: - - try: - - neon: 'infinite-3.tst' - - throw: 'Test infinite 3 failed' - catch: - - if: > - _error != "running build 'infinite-3.tst': running target 'test1': running target 'test2': in step 2: running target 'test1': infinite loop: test1 -> test2 -> test1" + - for: bug + in: 'keys(SUCCESS)' + do: + - if: 'SUCCESS[bug]' then: - - throw: "Bad error message: ={_error}" + - neon: '7-={bug}.tst' + else: + - 'fail = false' + - try: + - neon: '7-={bug}.tst' + catch: + - 'fail = true' + - if: '!fail' + then: + - throw: "Should have failed"