Fix asset provisioning to strip embedded share/radiantwave root
This commit is contained in:
@@ -150,7 +150,7 @@ func Run(bundled fs.FS) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if err := assets.Provision(bundled, config.AssetsDir); err != nil {
|
if err := assets.ProvisionAssets(bundled, config.AssetsDir); err != nil {
|
||||||
logger.Error("failed to provision bundled assets into %s: %v", config.AssetsDir, err)
|
logger.Error("failed to provision bundled assets into %s: %v", config.AssetsDir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,25 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// embeddedRoot is the directory in the source tree (and therefore in the
|
||||||
|
// embedded FS) where the bundled assets live. It mirrors the nix store
|
||||||
|
// layout, but consumers expect the assets directly under the assets dir,
|
||||||
|
// so this root is stripped during provisioning.
|
||||||
|
const embeddedRoot = "share/radiantwave"
|
||||||
|
|
||||||
|
// ProvisionAssets provisions the bundled static assets (fonts, shaders, and
|
||||||
|
// terms-of-service pages) into destDir, stripping the embedded
|
||||||
|
// share/radiantwave root so the files land directly in destDir rather than
|
||||||
|
// in a nested share/radiantwave/ subdirectory. Existing files are
|
||||||
|
// overwritten so the deployed assets always match the running binary.
|
||||||
|
func ProvisionAssets(bundled fs.FS, destDir string) error {
|
||||||
|
root, err := fs.Sub(bundled, embeddedRoot)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("bundled assets missing %s root: %w", embeddedRoot, err)
|
||||||
|
}
|
||||||
|
return Provision(root, destDir)
|
||||||
|
}
|
||||||
|
|
||||||
// Provision copies every file from the embedded filesystem into destDir,
|
// Provision copies every file from the embedded filesystem into destDir,
|
||||||
// preserving the relative directory structure. Existing files are
|
// preserving the relative directory structure. Existing files are
|
||||||
// overwritten so the deployed assets always match the running binary.
|
// overwritten so the deployed assets always match the running binary.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
"testing/fstest"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed testdata
|
//go:embed testdata
|
||||||
@@ -38,6 +39,40 @@ func TestProvisionCopiesBundledFiles(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestProvisionAssetsStripsEmbeddedRoot is a regression test: provisioning
|
||||||
|
// used to preserve the embedded share/radiantwave root, so assets landed in
|
||||||
|
// <dataDir>/share/radiantwave/fonts instead of <dataDir>/fonts. ProvisionAssets
|
||||||
|
// strips that root so consumers find the assets directly under the assets dir.
|
||||||
|
func TestProvisionAssetsStripsEmbeddedRoot(t *testing.T) {
|
||||||
|
fsys := fstest.MapFS{
|
||||||
|
"share/radiantwave/fonts/TestFont.ttf": &fstest.MapFile{Data: []byte("font")},
|
||||||
|
"share/radiantwave/shaders/text.frag": &fstest.MapFile{Data: []byte("frag")},
|
||||||
|
"share/radiantwave/shaders/text.vert": &fstest.MapFile{Data: []byte("vert")},
|
||||||
|
"share/radiantwave/tos/01 - WELCOME.html": &fstest.MapFile{Data: []byte("welcome")},
|
||||||
|
}
|
||||||
|
dest := t.TempDir()
|
||||||
|
|
||||||
|
if err := ProvisionAssets(fsys, dest); err != nil {
|
||||||
|
t.Fatalf("ProvisionAssets returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assets must land directly under dest, not under dest/share/radiantwave.
|
||||||
|
for _, rel := range []string{
|
||||||
|
"fonts/TestFont.ttf",
|
||||||
|
"shaders/text.frag",
|
||||||
|
"shaders/text.vert",
|
||||||
|
"tos/01 - WELCOME.html",
|
||||||
|
} {
|
||||||
|
if _, err := os.Stat(filepath.Join(dest, filepath.FromSlash(rel))); err != nil {
|
||||||
|
t.Errorf("expected %s to be provisioned directly under dest: %v", rel, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(filepath.Join(dest, "share")); !os.IsNotExist(err) {
|
||||||
|
t.Errorf("unexpected share/ directory created under dest: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestProvisionOverwritesStaleFiles(t *testing.T) {
|
func TestProvisionOverwritesStaleFiles(t *testing.T) {
|
||||||
dest := t.TempDir()
|
dest := t.TempDir()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user