Generation installed bundles into dist/bundles and a dev run had to be pointed there by hand, while an installed application read a different directory entirely -- two places for the same files, joined by an environment variable. tools/generate now installs straight into the central library: bundles/ under the application's own data directory, resolved by the tools through the same convention the framework gives the running application. go generate fills the library, go run -tags dev . serves it with no pointing at anything, and because the library is watched, an application already running picks a fresh build up the moment the bundler lands it. The corpus tests read the same place. -bundles still writes a registry anywhere else for exports, and ATLAS_BUNDLES_DIR still isolates a run when isolation is wanted.
- commit
- 06b3e84284b962bff3e933b798a8fdf6b15b9443
- parent
- 8120d30badea2b8c77e645a4c6c05e88cae30cfb
- author
- Dami <dami.etoile@gmail.com>
| M | README.md | 39 | +++++++++++++++++------------- |
| A | internal/ | 24 | ++++++++++++++++++ |
| M | main.go | 2 | +- |
| M | routes_test.go | 31 | +++++++++++++++--------- |
| M | tools/ | 20 | +++++++++++++-- |
@@ -20,14 +20,18 @@ Keep the three repositories beside one another:
2020 Run Atlas from this repository:2121 2222 ```sh23-go generate . # once, to build the bundles24-ATLAS_BUNDLES_DIR=$PWD/dist/bundles go run -tags dev .23+go generate . # once, to build the bundles into the library24+go run -tags dev .2525 ```2626 27-Without `ATLAS_BUNDLES_DIR` the application reads `.atlas` files from28-`bundles/` under its own data directory (on macOS,29-`~/Library/Application Support/dev.felinestatemachine.atlas/bundles`), which30-is where an installed copy finds the games its user has added.27+Generation installs bundles straight into the central library -- `bundles/`28+under the application's data directory (on macOS,29+`~/Library/Application Support/dev.felinestatemachine.atlas/bundles`) -- and30+the application reads the same place, so a dev run serves whatever has been31+built with no pointing at anything. `ATLAS_BUNDLES_DIR` overrides the library32+for either side when isolation is wanted, and `tools/generate -bundles`33+writes a registry elsewhere (for an export, say) without touching the34+library.3135 3236 Wails requires a desktop build tag even when it is invoked through `go run`.3337 Atlas supplies the additional macOS `UniformTypeIdentifiers` linker flag@@ -80,15 +84,16 @@ go generate .
8084 tool that derived them, so a layer nothing has changed under is left where8185 it is: a run that captures one new game costs seconds rather than the half8286 minute of re-deriving the rest. `-force` derives everything again.83-2. `tools/generate` writes one `.atlas` bundle per game into `dist/bundles`:84- the game's manifest, one payload per map, its tile pyramids, and its85- archive SVG icons, validated as each bundle is written. Maps with missing86- snapshots or incomplete configured layers are omitted. Bundles are named87- `<game>-<capture-day>-<stamp>.atlas`, versioned by the newest snapshot88- capture across the game's maps -- building the same archive anywhere89- yields the same file -- and a build already present is left untouched.90- Older versions are never pruned: the directory is a registry, and91- `index.json` beside the bundles lists every game's builds, newest first.87+2. `tools/generate` writes one `.atlas` bundle per game into the central88+ library: the game's manifest, one payload per map, its tile pyramids, and89+ its archive SVG icons, validated as each bundle is written. Maps with90+ missing snapshots or incomplete configured layers are omitted. Bundles are91+ named `<game>-<capture-day>-<stamp>.atlas`, versioned by the newest92+ snapshot capture across the game's maps -- building the same archive93+ anywhere yields the same file -- and a build already present is left94+ untouched. Older versions are never pruned: the library is a registry,95+ and `index.json` beside the bundles lists every game's builds, newest96+ first.9297 3. `npm ci` and the local esbuild/OpenLayers installation produce the9398 self-contained `assets/app.js` and `assets/app.css` bundles.9499 @@ -160,6 +165,6 @@ go vet ./...
160165 go build -tags dev .161166 ```162167 163-The corpus-dependent tests read `dist/bundles` and skip themselves when no164-bundles have been built, so `go test ./...` passes on a checkout without168+The corpus-dependent tests read the central library and skip themselves when169+no bundles have been built, so `go test ./...` passes on a checkout without165170 `../gamemap`.@@ -0,0 +1,24 @@
1+package bundle2+3+import (4+ "os"5+ "path/filepath"6+)7+8+// appID mirrors the identity main.go gives the framework. It lives here so9+// the build tools, which are separate programs, resolve the same library the10+// running application serves from.11+const appID = "dev.felinestatemachine.atlas"12+13+// DefaultDir is the central .atlas library: the bundles directory under the14+// application's own data directory. The application arrives at the same path15+// through the framework; the bundler installs straight into it, so a dev run16+// needs no pointing at anything -- and a running application, watching this17+// directory, picks a fresh build up the moment it lands.18+func DefaultDir() (string, error) {19+ root, err := os.UserConfigDir()20+ if err != nil {21+ return "", err22+ }23+ return filepath.Join(root, appID, "bundles"), nil24+}@@ -32,7 +32,7 @@ const catalogChangedTopic = "atlas:catalog-changed"
3232 // node tools/icons/render-icons.mjs --game skyrim3333 3434 //go:generate go run ./tools/tiles -source ../gamemap/fmg-archive -output build/tiles35-//go:generate go run ./tools/generate -source ../gamemap -tiles build/tiles/index.json -bundles dist/bundles35+//go:generate go run ./tools/generate -source ../gamemap -tiles build/tiles/index.json3636 //go:generate npm --prefix frontend ci3737 //go:generate npm --prefix frontend run build3838 @@ -253,19 +253,29 @@ func gameBase(t *testing.T, handler http.Handler, slug string) string {
253253 }254254 255255 // ---------------------------------------------------------------------------256-// Everything below runs against the real bundles when they have been built,257-// and is skipped when they have not: the corpus lives outside the repository,258-// so a checkout without ../gamemap still tests everything above.256+// Everything below runs against the real bundles when they have been built257+// into the central library, and is skipped when they have not: the corpus258+// lives outside the repository, so a checkout without ../gamemap still tests259+// everything above.259260 260-func builtBundles(t *testing.T) map[string]*bundle.Bundle {261+func builtRegistry(t *testing.T) *bundle.Registry {261262 t.Helper()262- registry := bundle.NewRegistry("dist/bundles")263+ library, err := bundle.DefaultDir()264+ if err != nil {265+ t.Fatal(err)266+ }267+ registry := bundle.NewRegistry(library)263268 if err := registry.Rescan(); err != nil {264269 t.Fatal(err)265270 }266- games := registry.Snapshot().Games271+ return registry272+}273+274+func builtBundles(t *testing.T) map[string]*bundle.Bundle {275+ t.Helper()276+ games := builtRegistry(t).Snapshot().Games267277 if len(games) == 0 {268- t.Skip("no built bundles under dist/bundles; run go generate first")278+ t.Skip("no built bundles in the library; run go generate first")269279 }270280 return games271281 }@@ -374,12 +384,9 @@ func TestBuiltBundlesKeepTheirPromises(t *testing.T) {
374384 // The catalog is fetched every time Atlas opens, so its size is the cost of375385 // starting up. It must not grow with what the bundles hold.376386 func TestComposedCatalogStaysSmall(t *testing.T) {377- registry := bundle.NewRegistry("dist/bundles")378- if err := registry.Rescan(); err != nil {379- t.Fatal(err)380- }387+ registry := builtRegistry(t)381388 if len(registry.Snapshot().Games) == 0 {382- t.Skip("no built bundles under dist/bundles; run go generate first")389+ t.Skip("no built bundles in the library; run go generate first")383390 }384391 if size := len(registry.Snapshot().Catalog); size > 64*1024 {385392 t.Errorf("composed catalog = %d bytes, want under 64 KiB", size)@@ -14,6 +14,8 @@ import (
1414 "sort"1515 "strconv"1616 "strings"17+18+ "github.com/FelineStateMachine/atlas/internal/bundle"1719 )1820 1921 type archive struct {@@ -309,13 +311,25 @@ func iconOutsetFor(raw rawMap) string {
309311 func main() {310312 source := flag.String("source", "", "path containing fmg-archive")311313 tiles := flag.String("tiles", "", "generated tile manifest")312- bundles := flag.String("bundles", "", "directory receiving one .atlas bundle per game")314+ bundles := flag.String("bundles", "",315+ "registry directory receiving .atlas bundles (default: the application's own library)")313316 flag.Parse()314317 315- if *source == "" || *tiles == "" || *bundles == "" {316- fmt.Fprintln(os.Stderr, "generate: -source, -tiles, and -bundles are required")318+ if *source == "" || *tiles == "" {319+ fmt.Fprintln(os.Stderr, "generate: -source and -tiles are required")317320 os.Exit(2)318321 }322+ if *bundles == "" {323+ // Installing straight into the application's library is the default:324+ // a dev run then serves the freshest builds with no pointing, and a325+ // running application watching the directory picks them up live.326+ library, err := bundle.DefaultDir()327+ if err != nil {328+ fmt.Fprintln(os.Stderr, "generate: resolving the bundle library:", err)329+ os.Exit(1)330+ }331+ *bundles = library332+ }319333 if err := run(*source, *tiles, *bundles); err != nil {320334 fmt.Fprintln(os.Stderr, "generate:", err)321335 os.Exit(1)