Skip to content

Commit

Permalink
Add js.Batch
Browse files Browse the repository at this point in the history
  • Loading branch information
bep committed Dec 6, 2024
1 parent 487bb96 commit 4e945bf
Show file tree
Hide file tree
Showing 58 changed files with 4,108 additions and 955 deletions.
6 changes: 5 additions & 1 deletion commands/hugobuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,11 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,

changed := c.changeDetector.changed()
if c.changeDetector != nil {
lrl.Logf("build changed %d files", len(changed))
if len(changed) >= 10 {
lrl.Logf("build changed %d files", len(changed))
} else {
lrl.Logf("build changed %d files: %q", len(changed), changed)
}
if len(changed) == 0 {
// Nothing has changed.
return
Expand Down
6 changes: 4 additions & 2 deletions commands/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"path"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -210,16 +211,17 @@ func (f *fileChangeDetector) changed() []string {
}
}

return f.filterIrrelevant(c)
return f.filterIrrelevantAndSort(c)
}

func (f *fileChangeDetector) filterIrrelevant(in []string) []string {
func (f *fileChangeDetector) filterIrrelevantAndSort(in []string) []string {
var filtered []string
for _, v := range in {
if !f.irrelevantRe.MatchString(v) {
filtered = append(filtered, v)
}
}
sort.Strings(filtered)
return filtered
}

Expand Down
15 changes: 15 additions & 0 deletions common/herrors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,21 @@ func IsNotExist(err error) bool {
return false
}

// IsExist returns true if the error is a file exists error.
// Unlike os.IsExist, this also considers wrapped errors.
func IsExist(err error) bool {
if os.IsExist(err) {
return true
}

// os.IsExist does not consider wrapped errors.
if os.IsExist(errors.Unwrap(err)) {
return true
}

return false
}

var nilPointerErrRe = regexp.MustCompile(`at <(.*)>: error calling (.*?): runtime error: invalid memory address or nil pointer dereference`)

const deferredPrefix = "__hdeferred/"
Expand Down
21 changes: 21 additions & 0 deletions common/hreflect/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,27 @@ func AsTime(v reflect.Value, loc *time.Location) (time.Time, bool) {
return time.Time{}, false
}

// ToSliceAny converts the given value to a slice of any if possible.
func ToSliceAny(v any) ([]any, bool) {
if v == nil {
return nil, false
}
switch vv := v.(type) {
case []any:
return vv, true
default:
vvv := reflect.ValueOf(v)
if vvv.Kind() == reflect.Slice {
out := make([]any, vvv.Len())
for i := 0; i < vvv.Len(); i++ {
out[i] = vvv.Index(i).Interface()
}
return out, true
}
}
return nil, false
}

func CallMethodByName(cxt context.Context, name string, v reflect.Value) []reflect.Value {
fn := v.MethodByName(name)
var args []reflect.Value
Expand Down
13 changes: 13 additions & 0 deletions common/hreflect/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,19 @@ func TestIsContextType(t *testing.T) {
c.Assert(IsContextType(reflect.TypeOf(valueCtx)), qt.IsTrue)
}

func TestToSliceAny(t *testing.T) {
c := qt.New(t)

checkOK := func(in any, expected []any) {
out, ok := ToSliceAny(in)
c.Assert(ok, qt.Equals, true)
c.Assert(out, qt.DeepEquals, expected)
}

checkOK([]any{1, 2, 3}, []any{1, 2, 3})
checkOK([]int{1, 2, 3}, []any{1, 2, 3})
}

func BenchmarkIsContextType(b *testing.B) {
type k string
b.Run("value", func(b *testing.B) {
Expand Down
7 changes: 5 additions & 2 deletions common/maps/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,14 @@ func (c *Cache[K, T]) set(key K, value T) {
}

// ForEeach calls the given function for each key/value pair in the cache.
func (c *Cache[K, T]) ForEeach(f func(K, T)) {
// If the function returns false, the iteration stops.
func (c *Cache[K, T]) ForEeach(f func(K, T) bool) {
c.RLock()
defer c.RUnlock()
for k, v := range c.m {
f(k, v)
if !f(k, v) {
return
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions common/types/closer.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ type Closer interface {
Close() error
}

// CloserFunc is a convenience type to create a Closer from a function.
type CloserFunc func() error

func (f CloserFunc) Close() error {
return f()
}

type CloseAdder interface {
Add(Closer)
}
Expand Down
4 changes: 2 additions & 2 deletions config/allconfig/configlanguage.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,11 @@ func (c ConfigLanguage) Watching() bool {
return c.m.Base.Internal.Watch
}

func (c ConfigLanguage) NewIdentityManager(name string) identity.Manager {
func (c ConfigLanguage) NewIdentityManager(name string, opts ...identity.ManagerOption) identity.Manager {
if !c.Watching() {
return identity.NopManager
}
return identity.NewManager(name)
return identity.NewManager(name, opts...)
}

func (c ConfigLanguage) ContentTypes() config.ContentTypesProvider {
Expand Down
2 changes: 1 addition & 1 deletion config/configProvider.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type AllProvider interface {
BuildDrafts() bool
Running() bool
Watching() bool
NewIdentityManager(name string) identity.Manager
NewIdentityManager(name string, opts ...identity.ManagerOption) identity.Manager
FastRenderMode() bool
PrintUnusedTemplates() bool
EnableMissingTranslationPlaceholders() bool
Expand Down
51 changes: 42 additions & 9 deletions deps/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"strings"
Expand Down Expand Up @@ -47,6 +48,9 @@ type Deps struct {
// The templates to use. This will usually implement the full tpl.TemplateManager.
tmplHandlers *tpl.TemplateHandlers

// The template funcs.
TmplFuncMap map[string]any

// The file systems to use.
Fs *hugofs.Fs `json:"-"`

Expand Down Expand Up @@ -83,10 +87,13 @@ type Deps struct {
Metrics metrics.Provider

// BuildStartListeners will be notified before a build starts.
BuildStartListeners *Listeners
BuildStartListeners *Listeners[any]

// BuildEndListeners will be notified after a build finishes.
BuildEndListeners *Listeners
BuildEndListeners *Listeners[any]

// OnChangeListeners will be notified when something changes.
OnChangeListeners *Listeners[identity.Identity]

// Resources that gets closed when the build is done or the server shuts down.
BuildClosers *types.Closers
Expand Down Expand Up @@ -154,17 +161,21 @@ func (d *Deps) Init() error {
}

if d.BuildStartListeners == nil {
d.BuildStartListeners = &Listeners{}
d.BuildStartListeners = &Listeners[any]{}
}

if d.BuildEndListeners == nil {
d.BuildEndListeners = &Listeners{}
d.BuildEndListeners = &Listeners[any]{}
}

if d.BuildClosers == nil {
d.BuildClosers = &types.Closers{}
}

if d.OnChangeListeners == nil {
d.OnChangeListeners = &Listeners[identity.Identity]{}
}

if d.Metrics == nil && d.Conf.TemplateMetrics() {
d.Metrics = metrics.NewProvider(d.Conf.TemplateMetricsHints())
}
Expand Down Expand Up @@ -268,6 +279,23 @@ func (d *Deps) Compile(prototype *Deps) error {
return nil
}

// MkdirTemp returns a temporary directory path that will be cleaned up on exit.
func (d Deps) MkdirTemp(pattern string) (string, error) {
filename, err := os.MkdirTemp("", pattern)
if err != nil {
return "", err
}
d.BuildClosers.Add(
types.CloserFunc(
func() error {
return os.RemoveAll(filename)
},
),
)

return filename, nil
}

type globalErrHandler struct {
logger loggers.Logger

Expand Down Expand Up @@ -306,15 +334,16 @@ func (e *globalErrHandler) StopErrorCollector() {
}

// Listeners represents an event listener.
type Listeners struct {
type Listeners[T any] struct {
sync.Mutex

// A list of funcs to be notified about an event.
listeners []func()
// If the return value is true, the listener will be removed.
listeners []func(...T) bool
}

// Add adds a function to a Listeners instance.
func (b *Listeners) Add(f func()) {
func (b *Listeners[T]) Add(f func(...T) bool) {
if b == nil {
return
}
Expand All @@ -324,12 +353,16 @@ func (b *Listeners) Add(f func()) {
}

// Notify executes all listener functions.
func (b *Listeners) Notify() {
func (b *Listeners[T]) Notify(vs ...T) {
b.Lock()
defer b.Unlock()
temp := b.listeners[:0]
for _, notify := range b.listeners {
notify()
if !notify(vs...) {
temp = append(temp, notify)
}
}
b.listeners = temp
}

// ResourceProvider is used to create and refresh, and clone resources needed.
Expand Down
6 changes: 6 additions & 0 deletions hugolib/content_map_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -1754,6 +1754,11 @@ func (sa *sitePagesAssembler) assembleResources() error {
mt = rs.rc.ContentMediaType
}

var filename string
if rs.fi != nil {
filename = rs.fi.Meta().Filename
}

rd := resources.ResourceSourceDescriptor{
OpenReadSeekCloser: rs.opener,
Path: rs.path,
Expand All @@ -1762,6 +1767,7 @@ func (sa *sitePagesAssembler) assembleResources() error {
TargetBasePaths: targetBasePaths,
BasePathRelPermalink: targetPaths.SubResourceBaseLink,
BasePathTargetPath: baseTarget,
SourceFilenameOrPath: filename,
NameNormalized: relPath,
NameOriginal: relPathOriginal,
MediaType: mt,
Expand Down
4 changes: 4 additions & 0 deletions hugolib/hugo_sites.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ func (h *HugoSites) ShouldSkipFileChangeEvent(ev fsnotify.Event) bool {
return h.skipRebuildForFilenames[ev.Name]
}

func (h *HugoSites) Close() error {
return h.Deps.Close()
}

func (h *HugoSites) isRebuild() bool {
return h.buildCounter.Load() > 0
}
Expand Down
5 changes: 4 additions & 1 deletion hugolib/hugo_sites_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,8 +520,9 @@ func (s *Site) executeDeferredTemplates(de *deps.DeferredExecutions) error {
},
})

de.FilenamesWithPostPrefix.ForEeach(func(filename string, _ bool) {
de.FilenamesWithPostPrefix.ForEeach(func(filename string, _ bool) bool {
g.Enqueue(filename)
return true
})

return g.Wait()
Expand Down Expand Up @@ -1058,6 +1059,8 @@ func (h *HugoSites) processPartialFileEvents(ctx context.Context, l logg.LevelLo
}
}

h.Deps.OnChangeListeners.Notify(changed.Changes()...)

if err := h.resolveAndClearStateForIdentities(ctx, l, cacheBusterOr, changed.Drain()); err != nil {
return err
}
Expand Down
9 changes: 3 additions & 6 deletions hugolib/hugo_sites_build_errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,8 +554,6 @@ toc line 3
toc line 4
`

t.Run("base template", func(t *testing.T) {
Expand All @@ -569,7 +567,7 @@ toc line 4
).BuildE()

b.Assert(err, qt.IsNotNil)
b.Assert(err.Error(), qt.Contains, filepath.FromSlash(`render of "home" failed: "/layouts/baseof.html:4:6"`))
b.Assert(err.Error(), qt.Contains, `baseof.html:4:6`)
})

t.Run("index template", func(t *testing.T) {
Expand All @@ -583,7 +581,7 @@ toc line 4
).BuildE()

b.Assert(err, qt.IsNotNil)
b.Assert(err.Error(), qt.Contains, filepath.FromSlash(`render of "home" failed: "/layouts/index.html:3:7"`))
b.Assert(err.Error(), qt.Contains, `index.html:3:7"`)
})

t.Run("partial from define", func(t *testing.T) {
Expand All @@ -597,8 +595,7 @@ toc line 4
).BuildE()

b.Assert(err, qt.IsNotNil)
b.Assert(err.Error(), qt.Contains, filepath.FromSlash(`render of "home" failed: "/layouts/index.html:7:8": execute of template failed`))
b.Assert(err.Error(), qt.Contains, `execute of template failed: template: partials/toc.html:2:8: executing "partials/toc.html"`)
b.Assert(err.Error(), qt.Contains, `toc.html:2:8"`)
})
}

Expand Down
Loading

0 comments on commit 4e945bf

Please sign in to comment.