1
0
Fork 0
forked from forgejo/forgejo

Use a general approach to access custom/static/builtin assets (#24022)

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>
This commit is contained in:
wxiaoguang 2023-04-12 18:16:45 +08:00 committed by GitHub
parent 42919ccb7c
commit 50a72e7a83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 689 additions and 1055 deletions

View file

@ -21,7 +21,6 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/watcher"
)
var (
@ -66,20 +65,23 @@ func (h *HTMLRender) TemplateLookup(name string) (*template.Template, error) {
}
func (h *HTMLRender) CompileTemplates() error {
dirPrefix := "templates/"
extSuffix := ".tmpl"
tmpls := template.New("")
for _, path := range GetTemplateAssetNames() {
if !strings.HasSuffix(path, extSuffix) {
assets := AssetFS()
files, err := ListWebTemplateAssetNames(assets)
if err != nil {
return nil
}
for _, file := range files {
if !strings.HasSuffix(file, extSuffix) {
continue
}
name := strings.TrimPrefix(path, dirPrefix)
name = strings.TrimSuffix(name, extSuffix)
name := strings.TrimSuffix(file, extSuffix)
tmpl := tmpls.New(filepath.ToSlash(name))
for _, fm := range NewFuncMap() {
tmpl.Funcs(fm)
}
buf, err := GetAsset(path)
buf, err := assets.ReadFile(file)
if err != nil {
return err
}
@ -112,13 +114,10 @@ func HTMLRenderer(ctx context.Context) (context.Context, *HTMLRender) {
log.Fatal("HTMLRenderer error: %v", err)
}
if !setting.IsProd {
watcher.CreateWatcher(ctx, "HTML Templates", &watcher.CreateWatcherOpts{
PathsCallback: walkTemplateFiles,
BetweenCallback: func() {
if err := renderer.CompileTemplates(); err != nil {
log.Error("Template error: %v\n%s", err, log.Stack(2))
}
},
go AssetFS().WatchLocalChanges(ctx, func() {
if err := renderer.CompileTemplates(); err != nil {
log.Error("Template error: %v\n%s", err, log.Stack(2))
}
})
}
return context.WithValue(ctx, rendererKey, renderer), renderer
@ -138,14 +137,8 @@ func handleGenericTemplateError(err error) (string, []interface{}) {
}
templateName, lineNumberStr, message := groups[1], groups[2], groups[3]
filename, assetErr := GetAssetFilename("templates/" + templateName + ".tmpl")
if assetErr != nil {
return "", nil
}
filename := fmt.Sprintf("%s (provided by %s)", templateName, AssetFS().GetFileLayerName(templateName+".tmpl"))
lineNumber, _ := strconv.Atoi(lineNumberStr)
line := GetLineFromTemplate(templateName, lineNumber, "", -1)
return "PANIC: Unable to compile templates!\n%s in template file %s at line %d:\n\n%s\nStacktrace:\n\n%s", []interface{}{message, filename, lineNumber, log.NewColoredValue(line, log.Reset), log.Stack(2)}
@ -158,16 +151,9 @@ func handleNotDefinedPanicError(err error) (string, []interface{}) {
}
templateName, lineNumberStr, functionName := groups[1], groups[2], groups[3]
functionName, _ = strconv.Unquote(`"` + functionName + `"`)
filename, assetErr := GetAssetFilename("templates/" + templateName + ".tmpl")
if assetErr != nil {
return "", nil
}
filename := fmt.Sprintf("%s (provided by %s)", templateName, AssetFS().GetFileLayerName(templateName+".tmpl"))
lineNumber, _ := strconv.Atoi(lineNumberStr)
line := GetLineFromTemplate(templateName, lineNumber, functionName, -1)
return "PANIC: Unable to compile templates!\nUndefined function %q in template file %s at line %d:\n\n%s", []interface{}{functionName, filename, lineNumber, log.NewColoredValue(line, log.Reset)}
@ -181,14 +167,8 @@ func handleUnexpected(err error) (string, []interface{}) {
templateName, lineNumberStr, unexpected := groups[1], groups[2], groups[3]
unexpected, _ = strconv.Unquote(`"` + unexpected + `"`)
filename, assetErr := GetAssetFilename("templates/" + templateName + ".tmpl")
if assetErr != nil {
return "", nil
}
filename := fmt.Sprintf("%s (provided by %s)", templateName, AssetFS().GetFileLayerName(templateName+".tmpl"))
lineNumber, _ := strconv.Atoi(lineNumberStr)
line := GetLineFromTemplate(templateName, lineNumber, unexpected, -1)
return "PANIC: Unable to compile templates!\nUnexpected %q in template file %s at line %d:\n\n%s", []interface{}{unexpected, filename, lineNumber, log.NewColoredValue(line, log.Reset)}
@ -201,14 +181,8 @@ func handleExpectedEnd(err error) (string, []interface{}) {
}
templateName, lineNumberStr, unexpected := groups[1], groups[2], groups[3]
filename, assetErr := GetAssetFilename("templates/" + templateName + ".tmpl")
if assetErr != nil {
return "", nil
}
filename := fmt.Sprintf("%s (provided by %s)", templateName, AssetFS().GetFileLayerName(templateName+".tmpl"))
lineNumber, _ := strconv.Atoi(lineNumberStr)
line := GetLineFromTemplate(templateName, lineNumber, unexpected, -1)
return "PANIC: Unable to compile templates!\nMissing end with unexpected %q in template file %s at line %d:\n\n%s", []interface{}{unexpected, filename, lineNumber, log.NewColoredValue(line, log.Reset)}
@ -218,7 +192,7 @@ const dashSeparator = "---------------------------------------------------------
// GetLineFromTemplate returns a line from a template with some context
func GetLineFromTemplate(templateName string, targetLineNum int, target string, position int) string {
bs, err := GetAsset("templates/" + templateName + ".tmpl")
bs, err := AssetFS().ReadFile(templateName + ".tmpl")
if err != nil {
return fmt.Sprintf("(unable to read template file: %v)", err)
}