mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-11-27 20:26:09 +01:00
50a72e7a83
The idea is to use a Layered Asset File-system (modules/assetfs/layered.go) For example: when there are 2 layers: "custom", "builtin", when access to asset "my/page.tmpl", the Layered Asset File-system will first try to use "custom" assets, if not found, then use "builtin" assets. This approach will hugely simplify a lot of code, make them testable. Other changes: * Simplify the AssetsHandlerFunc code * Simplify the `gitea embedded` sub-command code --------- Co-authored-by: Jason Song <i@wolfogre.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
110 lines
2.8 KiB
Go
110 lines
2.8 KiB
Go
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package assetfs
|
|
|
|
import (
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestLayered(t *testing.T) {
|
|
dir := filepath.Join(t.TempDir(), "assetfs-layers")
|
|
dir1 := filepath.Join(dir, "l1")
|
|
dir2 := filepath.Join(dir, "l2")
|
|
|
|
mkdir := func(elems ...string) {
|
|
assert.NoError(t, os.MkdirAll(filepath.Join(elems...), 0o755))
|
|
}
|
|
write := func(content string, elems ...string) {
|
|
assert.NoError(t, os.WriteFile(filepath.Join(elems...), []byte(content), 0o644))
|
|
}
|
|
|
|
// d1 & f1: only in "l1"; d2 & f2: only in "l2"
|
|
// da & fa: in both "l1" and "l2"
|
|
mkdir(dir1, "d1")
|
|
mkdir(dir1, "da")
|
|
mkdir(dir1, "da/sub1")
|
|
|
|
mkdir(dir2, "d2")
|
|
mkdir(dir2, "da")
|
|
mkdir(dir2, "da/sub2")
|
|
|
|
write("dummy", dir1, ".DS_Store")
|
|
write("f1", dir1, "f1")
|
|
write("fa-1", dir1, "fa")
|
|
write("d1-f", dir1, "d1/f")
|
|
write("da-f-1", dir1, "da/f")
|
|
|
|
write("f2", dir2, "f2")
|
|
write("fa-2", dir2, "fa")
|
|
write("d2-f", dir2, "d2/f")
|
|
write("da-f-2", dir2, "da/f")
|
|
|
|
assets := Layered(Local("l1", dir1), Local("l2", dir2))
|
|
|
|
f, err := assets.Open("f1")
|
|
assert.NoError(t, err)
|
|
bs, err := io.ReadAll(f)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, "f1", string(bs))
|
|
_ = f.Close()
|
|
|
|
assertRead := func(expected string, expectedErr error, elems ...string) {
|
|
bs, err := assets.ReadFile(elems...)
|
|
if err != nil {
|
|
assert.ErrorAs(t, err, &expectedErr)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, expected, string(bs))
|
|
}
|
|
}
|
|
assertRead("f1", nil, "f1")
|
|
assertRead("f2", nil, "f2")
|
|
assertRead("fa-1", nil, "fa")
|
|
|
|
assertRead("d1-f", nil, "d1/f")
|
|
assertRead("d2-f", nil, "d2/f")
|
|
assertRead("da-f-1", nil, "da/f")
|
|
|
|
assertRead("", fs.ErrNotExist, "no-such")
|
|
|
|
files, err := assets.ListFiles(".", true)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, []string{"f1", "f2", "fa"}, files)
|
|
|
|
files, err = assets.ListFiles(".", false)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, []string{"d1", "d2", "da"}, files)
|
|
|
|
files, err = assets.ListFiles(".")
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, []string{"d1", "d2", "da", "f1", "f2", "fa"}, files)
|
|
|
|
files, err = assets.ListAllFiles(".", true)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, []string{"d1/f", "d2/f", "da/f", "f1", "f2", "fa"}, files)
|
|
|
|
files, err = assets.ListAllFiles(".", false)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, []string{"d1", "d2", "da", "da/sub1", "da/sub2"}, files)
|
|
|
|
files, err = assets.ListAllFiles(".")
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, []string{
|
|
"d1", "d1/f",
|
|
"d2", "d2/f",
|
|
"da", "da/f", "da/sub1", "da/sub2",
|
|
"f1", "f2", "fa",
|
|
}, files)
|
|
|
|
assert.Empty(t, assets.GetFileLayerName("no-such"))
|
|
assert.EqualValues(t, "l1", assets.GetFileLayerName("f1"))
|
|
assert.EqualValues(t, "l2", assets.GetFileLayerName("f2"))
|
|
}
|