Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop "unrolled/render" package #23965

Merged
merged 2 commits into from
Apr 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions assets/go-licenses.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 17 additions & 12 deletions build/generate-go-licenses.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ package main

import (
"encoding/json"
"fmt"
"io/fs"
"os"
goPath "path"
"path"
"path/filepath"
"regexp"
"sort"
Expand All @@ -27,9 +28,14 @@ type LicenseEntry struct {
}

func main() {
if len(os.Args) != 3 {
fmt.Println("usage: go run generate-go-licenses.go <base-dir> <out-json-file>")
os.Exit(1)
}

base, out := os.Args[1], os.Args[2]

paths := []string{}
var paths []string
err := filepath.WalkDir(base, func(path string, entry fs.DirEntry, err error) error {
if err != nil {
return err
Expand All @@ -46,28 +52,27 @@ func main() {

sort.Strings(paths)

entries := []LicenseEntry{}
for _, path := range paths {
path := filepath.ToSlash(path)

licenseText, err := os.ReadFile(path)
var entries []LicenseEntry
for _, filePath := range paths {
licenseText, err := os.ReadFile(filePath)
if err != nil {
panic(err)
}

path = strings.Replace(path, base+"/", "", 1)
name := goPath.Dir(path)
pkgPath := filepath.ToSlash(filePath)
pkgPath = strings.TrimPrefix(pkgPath, base+"/")
pkgName := path.Dir(pkgPath)

// There might be a bug somewhere in go-licenses that sometimes interprets the
// root package as "." and sometimes as "code.gitea.io/gitea". Workaround by
// removing both of them for the sake of stable output.
if name == "." || name == "code.gitea.io/gitea" {
if pkgName == "." || pkgName == "code.gitea.io/gitea" {
continue
}

entries = append(entries, LicenseEntry{
Name: name,
Path: path,
Name: pkgName,
Path: pkgPath,
LicenseText: string(licenseText),
})
}
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ require (
github.com/stretchr/testify v1.8.1
github.com/syndtr/goleveldb v1.0.0
github.com/tstranex/u2f v1.0.0
github.com/unrolled/render v1.5.0
github.com/urfave/cli v1.22.12
github.com/xanzy/go-gitlab v0.80.2
github.com/xeipuuv/gojsonschema v1.2.0
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1182,8 +1182,6 @@ github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0o
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
github.com/unrolled/render v1.5.0 h1:uNTHMvVoI9pyyXfgoDHHycIqFONNY2p4eQR9ty+NsxM=
github.com/unrolled/render v1.5.0/go.mod h1:eLTosBkQqEPEk7pRfkCRApXd++lm++nCsVlFOHpeedw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8=
Expand Down
3 changes: 1 addition & 2 deletions modules/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,13 @@ import (
"gitea.com/go-chi/session"
chi "github.com/go-chi/chi/v5"
"github.com/minio/sha256-simd"
"github.com/unrolled/render"
"golang.org/x/crypto/pbkdf2"
)

// Render represents a template render
type Render interface {
TemplateLookup(tmpl string) *template.Template
HTML(w io.Writer, status int, name string, binding interface{}, htmlOpt ...render.HTMLOptions) error
HTML(w io.Writer, status int, name string, data interface{}) error
}

// Context represents context of a request.
Expand Down
102 changes: 56 additions & 46 deletions modules/templates/htmlrenderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@ import (
"bytes"
"context"
"fmt"
"html/template"
"io"
"net/http"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync/atomic"

"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/watcher"

"github.com/unrolled/render"
)

var (
Expand All @@ -27,14 +30,50 @@ var (
expectedEndError = regexp.MustCompile(`^template: (.*):([0-9]+): expected end; found (.*)`)
)

// HTMLRenderer returns the current html renderer for the context or creates and stores one within the context for future use
func HTMLRenderer(ctx context.Context) (context.Context, *render.Render) {
rendererInterface := ctx.Value(rendererKey)
if rendererInterface != nil {
renderer, ok := rendererInterface.(*render.Render)
if ok {
return ctx, renderer
type HTMLRender struct {
templates atomic.Pointer[template.Template]
}

func (h *HTMLRender) HTML(w io.Writer, status int, name string, data interface{}) error {
if respWriter, ok := w.(http.ResponseWriter); ok {
if respWriter.Header().Get("Content-Type") == "" {
respWriter.Header().Set("Content-Type", "text/html; charset=utf-8")
}
respWriter.WriteHeader(status)
}
return h.templates.Load().ExecuteTemplate(w, name, data)
}

func (h *HTMLRender) TemplateLookup(t string) *template.Template {
return h.templates.Load().Lookup(t)
}

func (h *HTMLRender) CompileTemplates() error {
dirPrefix := "templates/"
tmpls := template.New("")
for _, path := range GetTemplateAssetNames() {
name := path[len(dirPrefix):]
name = strings.TrimSuffix(name, ".tmpl")
tmpl := tmpls.New(filepath.ToSlash(name))
for _, fm := range NewFuncMap() {
tmpl.Funcs(fm)
}
buf, err := GetAsset(path)
if err != nil {
return err
}
if _, err = tmpl.Parse(string(buf)); err != nil {
return err
}
}
h.templates.Store(tmpls)
return nil
}

// HTMLRenderer returns the current html renderer for the context or creates and stores one within the context for future use
func HTMLRenderer(ctx context.Context) (context.Context, *HTMLRender) {
if renderer, ok := ctx.Value(rendererKey).(*HTMLRender); ok {
return ctx, renderer
}

rendererType := "static"
Expand All @@ -43,53 +82,24 @@ func HTMLRenderer(ctx context.Context) (context.Context, *render.Render) {
}
log.Log(1, log.DEBUG, "Creating "+rendererType+" HTML Renderer")

compilingTemplates := true
defer func() {
if !compilingTemplates {
return
}

panicked := recover()
if panicked == nil {
return
}

// OK try to handle the panic...
err, ok := panicked.(error)
if ok {
handlePanicError(err)
}
log.Fatal("PANIC: Unable to compile templates!\n%v\n\nStacktrace:\n%s", panicked, log.Stack(2))
}()

renderer := render.New(render.Options{
Extensions: []string{".tmpl"},
Directory: "templates",
Funcs: NewFuncMap(),
Asset: GetAsset,
AssetNames: GetTemplateAssetNames,
UseMutexLock: !setting.IsProd,
IsDevelopment: false,
DisableHTTPErrorRendering: true,
})
compilingTemplates = false
renderer := &HTMLRender{}
if err := renderer.CompileTemplates(); err != nil {
lunny marked this conversation as resolved.
Show resolved Hide resolved
handleFatalError(err)
}
if !setting.IsProd {
watcher.CreateWatcher(ctx, "HTML Templates", &watcher.CreateWatcherOpts{
PathsCallback: walkTemplateFiles,
BetweenCallback: func() {
defer func() {
if err := recover(); err != nil {
log.Error("PANIC: %v\n%s", err, log.Stack(2))
}
}()
renderer.CompileTemplates()
if err := renderer.CompileTemplates(); err != nil {
log.Error("Template error: %v\n%s", err, log.Stack(2))
}
},
})
}
return context.WithValue(ctx, rendererKey, renderer), renderer
}

func handlePanicError(err error) {
func handleFatalError(err error) {
wrapFatal(handleNotDefinedPanicError(err))
wrapFatal(handleUnexpected(err))
wrapFatal(handleExpectedEnd(err))
Expand Down
3 changes: 1 addition & 2 deletions modules/test/context_tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (

chi "github.com/go-chi/chi/v5"
"github.com/stretchr/testify/assert"
"github.com/unrolled/render"
)

// MockContext mock context for unit tests
Expand Down Expand Up @@ -138,7 +137,7 @@ func (tr *mockRender) TemplateLookup(tmpl string) *template.Template {
return nil
}

func (tr *mockRender) HTML(w io.Writer, status int, _ string, _ interface{}, _ ...render.HTMLOptions) error {
func (tr *mockRender) HTML(w io.Writer, status int, _ string, _ interface{}) error {
if resp, ok := w.(http.ResponseWriter); ok {
resp.WriteHeader(status)
}
Expand Down
3 changes: 1 addition & 2 deletions services/auth/sspi_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (

gouuid "github.com/google/uuid"
"github.com/quasoft/websspi"
"github.com/unrolled/render"
)

const (
Expand All @@ -48,7 +47,7 @@ var (
// On successful authentication returns a valid user object.
// Returns nil if authentication fails.
type SSPI struct {
rnd *render.Render
rnd *templates.HTMLRender
}

// Init creates a new global websspi.Authenticator object
Expand Down
Loading