diff --git a/CHANGELOG.md b/CHANGELOG.md index e32b547..4f68a0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] ### Changed - example/5/draggable.js fix for FireFox to prevent dropping a draggable trying to load a URL +- `transpile` arguments now work the same way for the transpile binary as they do for mkpuzzle +- `transpile inventory` does what you expect: inventory of current category, not inventory of all categories -## [v4.1.1] +### Fixed +- `transpile` will now run `mkcategory` and `mkpuzzle` when invoked without `-dir` + + +## [v4.1.1] - 2020-03-02 ### Removed - ppc64le and i386 builds of github, because ppc64le keep failing mysteriously, and we don't need them anyhow. + ## [v4.1.0] - 2020-03-02 ### Added - `transpile` now has a `markdown` command, @@ -50,6 +57,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - More detailed [API documntation](docs/api.md) - Transpiler warning if `mkpuzzle` exists but is not executable + ## [v4.0.0] - 2020-10-14 ### Fixed - Multiple bugs preventing production server from working properly @@ -62,6 +70,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Documented the HTTP API - Added a drawing of how things fit together + ## [v4.0-rc1] - 2020-10-13 ### Changed - Major rewrite/refactor of `mothd` @@ -95,13 +104,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security + ## [v3.5.1] - 2020-03-16 ### Fixed - Support insta-checking for legacy puzzles + ## [v3.5.0] - 2020-03-13 ### Changed - We are now using SHA256 instead of djb2hash + ### Added - URL parameter to points.json to allow returning only the JSON for a single team by its team id (e.g., points.json?id=abc123). @@ -113,24 +125,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Mothballs can now specify `X-Answer-Pattern` header fields, which allow `*` at the beginning, end, or both, of an answer. This is `X-` because we are hoping to change how this works in the future. + ### Fixed - Handle cases where non-legacy puzzles don't have an `author` attribute - Handle YAML-formatted file and script lists as expected - YAML-formatted example puzzle actually works as expected - points.log will now always be sorted chronologically + ## [3.4.3] - 2019-11-20 ### Fixed - Made top-scoring teams full-width + ## [3.4.2] - 2019-11-18 ### Fixed - Issue with multiple answers in devel server and YAML-format .moth + ## [3.4.1] - 2019-11-17 ### Fixed - Scoreboard was double-counting points + ## [3.4] - 2019-11-13 ### Added - A changelog @@ -139,5 +156,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Embedded graph in scoreboard - Optional tracking of participant IDs - New `notices.html` file for sending broadcast messages to players + ### Changed - Use native JS URL objects instead of wrangling everything by hand diff --git a/cmd/transpile/main.go b/cmd/transpile/main.go index fd1c0a3..75fbe76 100644 --- a/cmd/transpile/main.go +++ b/cmd/transpile/main.go @@ -99,30 +99,31 @@ func (t *T) ParseArgs() (Command, error) { // PrintInventory prints a puzzle inventory to stdout func (t *T) PrintInventory() error { - inv, err := transpile.FsInventory(t.fs) + c := transpile.NewFsCategory(t.fs, "") + + inv, err := c.Inventory() + if err != nil { + return err + } + sort.Ints(inv) + jinv, err := json.Marshal( + transpile.InventoryResponse{ + Puzzles: inv, + }, + ) if err != nil { return err } - cats := make([]string, 0, len(inv)) - for cat := range inv { - cats = append(cats, cat) - } - sort.Strings(cats) - for _, cat := range cats { - puzzles := inv[cat] - fmt.Fprint(t.Stdout, cat) - for _, p := range puzzles { - fmt.Fprint(t.Stdout, " ", p) - } - fmt.Fprintln(t.Stdout) - } + t.Stdout.Write(jinv) return nil } // DumpPuzzle writes a puzzle's JSON to the writer. func (t *T) DumpPuzzle() error { + log.Println("Hello!") puzzle := transpile.NewFsPuzzle(t.fs) + log.Println("Hello!") p, err := puzzle.Puzzle() if err != nil { diff --git a/cmd/transpile/main_test.go b/cmd/transpile/main_test.go index 3f86b89..e501337 100644 --- a/cmd/transpile/main_test.go +++ b/cmd/transpile/main_test.go @@ -61,10 +61,10 @@ func TestTranspilerEverything(t *testing.T) { BaseFs: newTestFs(), } - if err := tp.Run("inventory"); err != nil { + if err := tp.Run("inventory", "-dir=cat0"); err != nil { t.Error(err) } - if stdout.String() != "cat0 1 2 3 4 5 10\nunbroken 1 2\n" { + if stdout.String() != "{\"Puzzles\":[1,2,3,4,5,10]}" { t.Errorf("Bad inventory: %#v", stdout.String()) } diff --git a/pkg/transpile/basepath.go b/pkg/transpile/basepath.go index c40a3fd..ec9e469 100644 --- a/pkg/transpile/basepath.go +++ b/pkg/transpile/basepath.go @@ -39,10 +39,13 @@ func (b *RecursiveBasePathFs) RealPath(name string) (path string, err error) { bpath := filepath.Clean(b.path) path = filepath.Clean(filepath.Join(bpath, name)) - if parentRecursiveBasePathFs, ok := b.source.(*RecursiveBasePathFs); ok { - return parentRecursiveBasePathFs.RealPath(path) - } else if parentRecursiveBasePathFs, ok := b.source.(*afero.BasePathFs); ok { - return parentRecursiveBasePathFs.RealPath(path) + switch pfs := b.source.(type) { + case *RecursiveBasePathFs: + return pfs.RealPath(path) + case *afero.BasePathFs: + return pfs.RealPath(path) + case *afero.OsFs: + return path, nil } if !strings.HasPrefix(path, bpath) { diff --git a/pkg/transpile/category.go b/pkg/transpile/category.go index 8a42d1c..0891d7e 100644 --- a/pkg/transpile/category.go +++ b/pkg/transpile/category.go @@ -56,7 +56,7 @@ func NewFsCategory(fs afero.Fs, cat string) Category { bfs := NewRecursiveBasePathFs(fs, cat) if info, err := bfs.Stat("mkcategory"); (err == nil) && (info.Mode()&0100 != 0) { if command, err := bfs.RealPath(info.Name()); err != nil { - log.Println("Unable to resolve full path to", info.Name(), bfs) + log.Println("Unable to resolve full path to", info.Name()) } else { return FsCommandCategory{ fs: bfs, diff --git a/pkg/transpile/puzzle.go b/pkg/transpile/puzzle.go index b9818ba..8222ce0 100644 --- a/pkg/transpile/puzzle.go +++ b/pkg/transpile/puzzle.go @@ -134,17 +134,11 @@ type PuzzleProvider interface { func NewFsPuzzle(fs afero.Fs) PuzzleProvider { var command string - if info, err := fs.Stat("mkpuzzle"); !os.IsNotExist(err) { + bfs := NewRecursiveBasePathFs(fs, "") + if info, err := bfs.Stat("mkpuzzle"); !os.IsNotExist(err) { if (info.Mode() & 0100) != 0 { - // Try to get the actual path to the executable - if pfs, ok := fs.(*RecursiveBasePathFs); ok { - if command, err = pfs.RealPath(info.Name()); err != nil { - log.Println("WARN: Unable to resolve full path to", info.Name(), pfs) - } - } else if pfs, ok := fs.(*afero.BasePathFs); ok { - if command, err = pfs.RealPath(info.Name()); err != nil { - log.Println("WARN: Unable to resolve full path to", info.Name(), pfs) - } + if command, err = bfs.RealPath(info.Name()); err != nil { + log.Println("WARN: Unable to resolve full path to", info.Name()) } } else { log.Println("WARN: mkpuzzle exists, but isn't executable.")