aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlu0r1ne <flur01ne@flu0r1ne.net>2021-09-19 00:27:55 -0500
committerFlu0r1ne <flur01ne@flu0r1ne.net>2021-09-19 00:27:55 -0500
commit1d479733bcbeb630557cd07f721d4510e989934c (patch)
tree42422bd0c2ecc51869eceb8bbead8f5c3e58855f
parent86d8789f065636779d3cecded363743b2a39bb47 (diff)
downloadplanr-master.tar.xz
planr-master.zip
Add list command, copy for bash command, and ability to run non-directory commands anywhereHEADv0.1.6master
-rw-r--r--adapters/bash/adapter.go32
-rw-r--r--adapters/bash/config.go1
-rw-r--r--cmd/planr/main.go30
-rw-r--r--cmd/planr/sub/cli.go14
-rw-r--r--cmd/planr/sub/evaluate.go28
-rw-r--r--cmd/planr/sub/list.go13
-rw-r--r--copy.go96
-rw-r--r--runner.go13
-rw-r--r--version.go2
9 files changed, 206 insertions, 23 deletions
diff --git a/adapters/bash/adapter.go b/adapters/bash/adapter.go
index 8c7713c..cfa2032 100644
--- a/adapters/bash/adapter.go
+++ b/adapters/bash/adapter.go
@@ -3,13 +3,14 @@ package bash
import (
"context"
"errors"
+ "fmt"
"log"
"os"
"os/exec"
"path"
"strings"
"time"
- "fmt"
+ "io/ioutil"
"golang.flu0r1ne.net/planr"
)
@@ -42,11 +43,34 @@ func (a *Adapter) Init(ctx planr.PipelineContext) {
a.buildDir = ctx.AdapterDir
}
+func createTmpDir(dir string) string {
+ name, err := ioutil.TempDir(dir, "tmpbuild.*")
+
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ return name
+}
+
+func removeTmpDir(dir string) {
+ if err := os.RemoveAll(dir); err != nil {
+ log.Fatal(err)
+ }
+}
+
func (adapter Adapter) Build(tcs []planr.TestCase) { }
-func executeScriptedTest(builddir, testdir string, tc planr.TestCase) planr.TestResult {
+func executeScriptedTest(builddir, testdir, srcdir string, tc planr.TestCase) planr.TestResult {
cfg := tc.AdapterConfig().(*Config)
+ tmpdir := createTmpDir(builddir)
+ defer removeTmpDir(tmpdir)
+
+ if err := planr.RecursiveCopyDir(srcdir, tmpdir); err != nil {
+ log.Fatalf("Could not copy sources: %v", err)
+ }
+
timeout := time.Duration(cfg.Timeout) * time.Millisecond
ctx, cancel := context.WithTimeout(context.Background(), timeout)
@@ -60,7 +84,7 @@ func executeScriptedTest(builddir, testdir string, tc planr.TestCase) planr.Test
cmd := exec.CommandContext(ctx, "bash", path)
- cmd.Dir = builddir
+ cmd.Dir = tmpdir
if out, err := cmd.CombinedOutput(); err != nil {
result.Status = planr.RUNTIME_FAILURE
@@ -91,7 +115,7 @@ func (adapter Adapter) Evaluate(tcs []planr.TestCase) [] planr.TestResult {
c := make(chan planr.TestResult, 0)
for i := range tcs {
go func(i int) {
- c <- executeScriptedTest(adapter.buildDir, adapter.dirs.Tests(), tcs[i])
+ c <- executeScriptedTest(adapter.buildDir, adapter.dirs.Tests(), adapter.dirs.Src(), tcs[i])
}(i)
}
diff --git a/adapters/bash/config.go b/adapters/bash/config.go
index aaa405a..7e6ca3b 100644
--- a/adapters/bash/config.go
+++ b/adapters/bash/config.go
@@ -33,6 +33,7 @@ func (c *Config) finalize(path string) {
if c.Timeout == 0 {
c.Timeout = DEFAULT_TIMEOUT;
}
+
}
func finalizeConfigs(tcs []planr.TestCase) {
diff --git a/cmd/planr/main.go b/cmd/planr/main.go
index 2243203..e2ed19f 100644
--- a/cmd/planr/main.go
+++ b/cmd/planr/main.go
@@ -80,29 +80,37 @@ func main() {
dieUsage()
}
+ subcommand := flag.Arg(0)
+ subargs := flag.Args()[1:]
+
+ switch subcommand {
+ case "version":
+ fmt.Printf("%s\n", planr.VERSION)
+ os.Exit(0)
+ case "help", "-h", "-help", "--help":
+ printUsage(os.Stdout)
+ os.Exit(0)
+ case "build", "evaluate", "eval", "clean", "config", "list":
+ break
+ default:
+ fmt.Fprintf(os.Stderr, "unrecognized command %s\n", subcommand)
+ dieUsage()
+ }
+
runner := getConfiguredRunner()
cfg := planr.DecodeConfig(runner.ConfigDir())
- subcommand := flag.Arg(0)
- subargs := flag.Args()[1:]
-
switch subcommand {
- case "version":
- fmt.Printf("%s\n", planr.VERSION)
case "build":
sub.Build(runner, subargs, cfg)
case "evaluate", "eval":
sub.Evaluate(runner, subargs, cfg)
+ case "list":
+ sub.List(runner, subargs, cfg)
case "clean":
sub.Clean(runner, subargs)
case "config":
sub.Config(runner, subargs)
- case "help", "-h", "-help", "--help":
- printUsage(os.Stdout)
- default:
- fmt.Fprintf(os.Stderr, "unrecognized command %s\n", subcommand)
- dieUsage()
}
-
}
diff --git a/cmd/planr/sub/cli.go b/cmd/planr/sub/cli.go
index 5defa96..9e1099c 100644
--- a/cmd/planr/sub/cli.go
+++ b/cmd/planr/sub/cli.go
@@ -82,6 +82,20 @@ func (opt PrintOpts) HasFlag(flag PrintOpts) bool {
return (opt & flag) == flag
}
+func tcPrint(tc planr.TestCase) {
+ title := ""
+
+ if tc.Config.Title != "" {
+ title = tc.Config.Title
+ } else {
+ title = tc.Cname
+ }
+
+ col_title.Println(title)
+ pprintLabeled("id", tc.Cname)
+ fmt.Println()
+}
+
func tcPprint(tr planr.TestResult, opt PrintOpts) {
tcStatusLine(tr)
diff --git a/cmd/planr/sub/evaluate.go b/cmd/planr/sub/evaluate.go
index 4f5e4e1..3f1718f 100644
--- a/cmd/planr/sub/evaluate.go
+++ b/cmd/planr/sub/evaluate.go
@@ -2,9 +2,10 @@ package sub
import (
"encoding/json"
+ "flag"
"fmt"
+ "io/ioutil"
"log"
- "flag"
"golang.flu0r1ne.net/planr"
)
@@ -30,26 +31,39 @@ func prettyPrint(results gradingResults, verbose, summarize bool) {
}
}
-func jsonPrint(results gradingResults) {
+func jsonPrint(results gradingResults, file string) {
res, err := json.Marshal(results)
if err != nil {
log.Fatalf("Error printing JSON: %v\n", err)
}
- fmt.Println(string(res))
+ if file == "" {
+ fmt.Println(string(res))
+ return
+ }
+
+
+ if err := ioutil.WriteFile(file, res, 0664); err != nil {
+ log.Fatalf("Could not write JSON file %v", err)
+ }
}
func Evaluate(runner planr.Runner, params []string, cfg *planr.Config) {
f := flag.NewFlagSet("evaluate", flag.ExitOnError)
jsonOutput := f.Bool("json", false, "print json output")
+ jsonFile := f.String("json_to_file", "", "export json to a file")
extra := f.Bool("extra", false, "print extra grading information")
dieIncompatibleVersion(cfg)
f.Parse(params)
+ if *jsonFile != "" && *jsonOutput {
+ log.Fatalf("-json and -json_to_file are mutually exclusive")
+ }
+
tcs := runner.CollectCases()
// Filter those tests which patch IDs in params
@@ -80,9 +94,11 @@ func Evaluate(runner planr.Runner, params []string, cfg *planr.Config) {
Score: planr.Score(trs),
}
- if *jsonOutput {
- jsonPrint(results)
- } else {
+ if *jsonOutput || *jsonFile != "" {
+ jsonPrint(results, *jsonFile)
+ }
+
+ if ! *jsonOutput {
prettyPrint(results, *extra, summarizeScore)
}
}
diff --git a/cmd/planr/sub/list.go b/cmd/planr/sub/list.go
new file mode 100644
index 0000000..911a7e6
--- /dev/null
+++ b/cmd/planr/sub/list.go
@@ -0,0 +1,13 @@
+package sub
+
+import (
+ "golang.flu0r1ne.net/planr"
+)
+
+func List(runner planr.Runner, params []string, cfg * planr.Config) {
+ tcs := runner.CollectCases()
+
+ for _, tc := range tcs {
+ tcPrint(tc)
+ }
+}
diff --git a/copy.go b/copy.go
new file mode 100644
index 0000000..72d9635
--- /dev/null
+++ b/copy.go
@@ -0,0 +1,96 @@
+package planr
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "io"
+)
+
+
+func Exists(filePath string) bool {
+ if _, err := os.Stat(filePath); os.IsNotExist(err) {
+ return false
+ }
+
+ return true
+}
+
+func CreateIfNotExists(dir string, perm os.FileMode) error {
+ if Exists(dir) {
+ return nil
+ }
+
+ if err := os.MkdirAll(dir, perm); err != nil {
+ return fmt.Errorf("failed to create directory: '%s', error: '%s'", dir, err.Error())
+ }
+
+ return nil
+}
+
+func CopySymlink(src, dst string, perm os.FileMode) error {
+ link, err := os.Readlink(src)
+ if err != nil {
+ return err
+ }
+
+ if err := os.Chmod(src, perm); err != nil {
+ return err
+ }
+
+ return os.Symlink(link, dst)
+}
+
+func Copy(srcFile, dstFile string, perm os.FileMode) error {
+ src, err := os.Open(srcFile)
+ if err != nil {
+ return err
+ }
+
+ defer src.Close()
+
+ dst, err := os.OpenFile(dstFile, os.O_CREATE | os.O_WRONLY | os.O_TRUNC, perm)
+ if err != nil {
+ return err
+ }
+
+ defer dst.Close()
+
+ _, err = io.Copy(dst, src)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+
+func RecursiveCopyDir(source, destination string) error {
+ err := filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
+ relPath, err := filepath.Rel(source, path)
+
+ if err != nil {
+ return err
+ }
+
+ dst := filepath.Join(destination, relPath)
+ src := filepath.Join(source, relPath)
+
+ mode := info.Mode()
+
+ if relPath == "" {
+ return nil
+ }
+
+ switch info.Mode() & os.ModeType {
+ case os.ModeDir:
+ return CreateIfNotExists(dst, mode)
+ case os.ModeSymlink:
+ return CopySymlink(src, dst, mode)
+ default:
+ return Copy(src, dst, mode)
+ }
+ });
+
+ return err
+}
diff --git a/runner.go b/runner.go
index 2f86d2e..11fceab 100644
--- a/runner.go
+++ b/runner.go
@@ -92,6 +92,10 @@ func (r Runner) CollectCases() []TestCase {
}
func (r Runner) Build(tcs []TestCase) {
+ wd, err := os.Getwd()
+ if err != nil {
+ log.Fatal(err)
+ }
if !directoryExists(r.dirs.Build()) {
r.dirs.MkBuild()
@@ -107,9 +111,16 @@ func (r Runner) Build(tcs []TestCase) {
adapter.Build(cases)
}
+
+ safeCd(wd)
}
func (r Runner) Evaluate(tcs []TestCase) []TestResult {
+ wd, err := os.Getwd()
+ if err != nil {
+ log.Fatal(err)
+ }
+
testSets := r.groupByAdapter(tcs)
results := make([]TestResult, 0)
@@ -131,7 +142,7 @@ func (r Runner) Evaluate(tcs []TestCase) []TestResult {
sort.Sort(ByReadIdx(results))
- safeCd(r.dirs.Config())
+ safeCd(wd)
return results
}
diff --git a/version.go b/version.go
index 72a80a2..907dd02 100644
--- a/version.go
+++ b/version.go
@@ -1,3 +1,3 @@
package planr
-const VERSION = "0.1.5"
+const VERSION = "0.1.6"