mirror of https://github.com/dirtbags/moth.git
Make `transpile inventory` work the way I expected
This commit is contained in:
parent
7595f36100
commit
17a8b7f9cb
20
CHANGELOG.md
20
CHANGELOG.md
|
@ -7,11 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
## [unreleased]
|
## [unreleased]
|
||||||
### Changed
|
### Changed
|
||||||
- example/5/draggable.js fix for FireFox to prevent dropping a draggable trying to load a URL
|
- 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
|
### Removed
|
||||||
- ppc64le and i386 builds of github, because ppc64le keep failing mysteriously, and we don't need them anyhow.
|
- ppc64le and i386 builds of github, because ppc64le keep failing mysteriously, and we don't need them anyhow.
|
||||||
|
|
||||||
|
|
||||||
## [v4.1.0] - 2020-03-02
|
## [v4.1.0] - 2020-03-02
|
||||||
### Added
|
### Added
|
||||||
- `transpile` now has a `markdown` command,
|
- `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)
|
- More detailed [API documntation](docs/api.md)
|
||||||
- Transpiler warning if `mkpuzzle` exists but is not executable
|
- Transpiler warning if `mkpuzzle` exists but is not executable
|
||||||
|
|
||||||
|
|
||||||
## [v4.0.0] - 2020-10-14
|
## [v4.0.0] - 2020-10-14
|
||||||
### Fixed
|
### Fixed
|
||||||
- Multiple bugs preventing production server from working properly
|
- 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
|
- Documented the HTTP API
|
||||||
- Added a drawing of how things fit together
|
- Added a drawing of how things fit together
|
||||||
|
|
||||||
|
|
||||||
## [v4.0-rc1] - 2020-10-13
|
## [v4.0-rc1] - 2020-10-13
|
||||||
### Changed
|
### Changed
|
||||||
- Major rewrite/refactor of `mothd`
|
- Major rewrite/refactor of `mothd`
|
||||||
|
@ -95,13 +104,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
|
|
||||||
## [v3.5.1] - 2020-03-16
|
## [v3.5.1] - 2020-03-16
|
||||||
### Fixed
|
### Fixed
|
||||||
- Support insta-checking for legacy puzzles
|
- Support insta-checking for legacy puzzles
|
||||||
|
|
||||||
|
|
||||||
## [v3.5.0] - 2020-03-13
|
## [v3.5.0] - 2020-03-13
|
||||||
### Changed
|
### Changed
|
||||||
- We are now using SHA256 instead of djb2hash
|
- We are now using SHA256 instead of djb2hash
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- URL parameter to points.json to allow returning only the JSON for a single
|
- 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).
|
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 `*`
|
- 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
|
at the beginning, end, or both, of an answer. This is `X-` because we
|
||||||
are hoping to change how this works in the future.
|
are hoping to change how this works in the future.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Handle cases where non-legacy puzzles don't have an `author` attribute
|
- Handle cases where non-legacy puzzles don't have an `author` attribute
|
||||||
- Handle YAML-formatted file and script lists as expected
|
- Handle YAML-formatted file and script lists as expected
|
||||||
- YAML-formatted example puzzle actually works as expected
|
- YAML-formatted example puzzle actually works as expected
|
||||||
- points.log will now always be sorted chronologically
|
- points.log will now always be sorted chronologically
|
||||||
|
|
||||||
|
|
||||||
## [3.4.3] - 2019-11-20
|
## [3.4.3] - 2019-11-20
|
||||||
### Fixed
|
### Fixed
|
||||||
- Made top-scoring teams full-width
|
- Made top-scoring teams full-width
|
||||||
|
|
||||||
|
|
||||||
## [3.4.2] - 2019-11-18
|
## [3.4.2] - 2019-11-18
|
||||||
### Fixed
|
### Fixed
|
||||||
- Issue with multiple answers in devel server and YAML-format .moth
|
- Issue with multiple answers in devel server and YAML-format .moth
|
||||||
|
|
||||||
|
|
||||||
## [3.4.1] - 2019-11-17
|
## [3.4.1] - 2019-11-17
|
||||||
### Fixed
|
### Fixed
|
||||||
- Scoreboard was double-counting points
|
- Scoreboard was double-counting points
|
||||||
|
|
||||||
|
|
||||||
## [3.4] - 2019-11-13
|
## [3.4] - 2019-11-13
|
||||||
### Added
|
### Added
|
||||||
- A changelog
|
- A changelog
|
||||||
|
@ -139,5 +156,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Embedded graph in scoreboard
|
- Embedded graph in scoreboard
|
||||||
- Optional tracking of participant IDs
|
- Optional tracking of participant IDs
|
||||||
- New `notices.html` file for sending broadcast messages to players
|
- New `notices.html` file for sending broadcast messages to players
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Use native JS URL objects instead of wrangling everything by hand
|
- Use native JS URL objects instead of wrangling everything by hand
|
||||||
|
|
|
@ -99,30 +99,31 @@ func (t *T) ParseArgs() (Command, error) {
|
||||||
|
|
||||||
// PrintInventory prints a puzzle inventory to stdout
|
// PrintInventory prints a puzzle inventory to stdout
|
||||||
func (t *T) PrintInventory() error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cats := make([]string, 0, len(inv))
|
t.Stdout.Write(jinv)
|
||||||
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)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DumpPuzzle writes a puzzle's JSON to the writer.
|
// DumpPuzzle writes a puzzle's JSON to the writer.
|
||||||
func (t *T) DumpPuzzle() error {
|
func (t *T) DumpPuzzle() error {
|
||||||
|
log.Println("Hello!")
|
||||||
puzzle := transpile.NewFsPuzzle(t.fs)
|
puzzle := transpile.NewFsPuzzle(t.fs)
|
||||||
|
log.Println("Hello!")
|
||||||
|
|
||||||
p, err := puzzle.Puzzle()
|
p, err := puzzle.Puzzle()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -61,10 +61,10 @@ func TestTranspilerEverything(t *testing.T) {
|
||||||
BaseFs: newTestFs(),
|
BaseFs: newTestFs(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tp.Run("inventory"); err != nil {
|
if err := tp.Run("inventory", "-dir=cat0"); err != nil {
|
||||||
t.Error(err)
|
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())
|
t.Errorf("Bad inventory: %#v", stdout.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,10 +39,13 @@ func (b *RecursiveBasePathFs) RealPath(name string) (path string, err error) {
|
||||||
bpath := filepath.Clean(b.path)
|
bpath := filepath.Clean(b.path)
|
||||||
path = filepath.Clean(filepath.Join(bpath, name))
|
path = filepath.Clean(filepath.Join(bpath, name))
|
||||||
|
|
||||||
if parentRecursiveBasePathFs, ok := b.source.(*RecursiveBasePathFs); ok {
|
switch pfs := b.source.(type) {
|
||||||
return parentRecursiveBasePathFs.RealPath(path)
|
case *RecursiveBasePathFs:
|
||||||
} else if parentRecursiveBasePathFs, ok := b.source.(*afero.BasePathFs); ok {
|
return pfs.RealPath(path)
|
||||||
return parentRecursiveBasePathFs.RealPath(path)
|
case *afero.BasePathFs:
|
||||||
|
return pfs.RealPath(path)
|
||||||
|
case *afero.OsFs:
|
||||||
|
return path, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.HasPrefix(path, bpath) {
|
if !strings.HasPrefix(path, bpath) {
|
||||||
|
|
|
@ -56,7 +56,7 @@ func NewFsCategory(fs afero.Fs, cat string) Category {
|
||||||
bfs := NewRecursiveBasePathFs(fs, cat)
|
bfs := NewRecursiveBasePathFs(fs, cat)
|
||||||
if info, err := bfs.Stat("mkcategory"); (err == nil) && (info.Mode()&0100 != 0) {
|
if info, err := bfs.Stat("mkcategory"); (err == nil) && (info.Mode()&0100 != 0) {
|
||||||
if command, err := bfs.RealPath(info.Name()); err != nil {
|
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 {
|
} else {
|
||||||
return FsCommandCategory{
|
return FsCommandCategory{
|
||||||
fs: bfs,
|
fs: bfs,
|
||||||
|
|
|
@ -134,17 +134,11 @@ type PuzzleProvider interface {
|
||||||
func NewFsPuzzle(fs afero.Fs) PuzzleProvider {
|
func NewFsPuzzle(fs afero.Fs) PuzzleProvider {
|
||||||
var command string
|
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 {
|
if (info.Mode() & 0100) != 0 {
|
||||||
// Try to get the actual path to the executable
|
if command, err = bfs.RealPath(info.Name()); err != nil {
|
||||||
if pfs, ok := fs.(*RecursiveBasePathFs); ok {
|
log.Println("WARN: Unable to resolve full path to", info.Name())
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Println("WARN: mkpuzzle exists, but isn't executable.")
|
log.Println("WARN: mkpuzzle exists, but isn't executable.")
|
||||||
|
|
Loading…
Reference in New Issue