]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Fix partial rebuilds for SCSS fetched with GetMatch and similar
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sat, 20 Apr 2024 09:05:35 +0000 (11:05 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sat, 20 Apr 2024 13:09:12 +0000 (15:09 +0200)
Fixes #12395

cache/dynacache/dynacache.go
cache/dynacache/dynacache_test.go
commands/commandeer.go
hugolib/content_map_page.go
hugolib/hugo_sites_build.go
resources/resource_transformers/tocss/scss/scss_integration_test.go

index eab251e5d3aea260bd5fc39e6c45c3252401236f..e79de5a5bb9507ac0722e2db16a62d5bad07026e 100644 (file)
@@ -140,16 +140,25 @@ func (c *Cache) DrainEvictedIdentities() []identity.Identity {
 }
 
 // ClearMatching clears all partition for which the predicate returns true.
-func (c *Cache) ClearMatching(predicate func(k, v any) bool) {
+func (c *Cache) ClearMatching(predicatePartition func(k string, p PartitionManager) bool, predicateValue func(k, v any) bool) {
+       if predicatePartition == nil {
+               predicatePartition = func(k string, p PartitionManager) bool { return true }
+       }
+       if predicateValue == nil {
+               panic("nil predicateValue")
+       }
        g := rungroup.Run[PartitionManager](context.Background(), rungroup.Config[PartitionManager]{
                NumWorkers: len(c.partitions),
                Handle: func(ctx context.Context, partition PartitionManager) error {
-                       partition.clearMatching(predicate)
+                       partition.clearMatching(predicateValue)
                        return nil
                },
        })
 
-       for _, p := range c.partitions {
+       for k, p := range c.partitions {
+               if !predicatePartition(k, p) {
+                       continue
+               }
                g.Enqueue(p)
        }
 
@@ -356,6 +365,7 @@ func GetOrCreatePartition[K comparable, V any](c *Cache, name string, opts Optio
                trace:   c.opts.Log.Logger().WithLevel(logg.LevelTrace).WithField("partition", name),
                opts:    opts,
        }
+
        c.partitions[name] = partition
 
        return partition
index 53de2385e849fec07611f90f724c5975f2f0660b..275e63f0be65efc66de38f0eec68efa07a4deab3 100644 (file)
@@ -156,7 +156,7 @@ func TestClear(t *testing.T) {
 
        cache = newTestCache(t)
 
-       cache.ClearMatching(func(k, v any) bool {
+       cache.ClearMatching(nil, func(k, v any) bool {
                return k.(string) == "clearOnRebuild"
        })
 
index f18c3f81311c05441c74347d62f55712735ba6b1..616a3c867f433b53a8d7c2263d46ca57dfcff1ad 100644 (file)
@@ -128,6 +128,7 @@ type rootCommand struct {
        verbose bool
        debug   bool
        quiet   bool
+       devMode bool // Hidden flag.
 
        renderToMemory bool
 
@@ -423,29 +424,33 @@ func (r *rootCommand) PreRun(cd, runner *simplecobra.Commandeer) error {
 func (r *rootCommand) createLogger(running bool) (loggers.Logger, error) {
        level := logg.LevelWarn
 
-       if r.logLevel != "" {
-               switch strings.ToLower(r.logLevel) {
-               case "debug":
-                       level = logg.LevelDebug
-               case "info":
-                       level = logg.LevelInfo
-               case "warn", "warning":
-                       level = logg.LevelWarn
-               case "error":
-                       level = logg.LevelError
-               default:
-                       return nil, fmt.Errorf("invalid log level: %q, must be one of debug, warn, info or error", r.logLevel)
-               }
+       if r.devMode {
+               level = logg.LevelTrace
        } else {
-               if r.verbose {
-                       hugo.Deprecate("--verbose", "use --logLevel info", "v0.114.0")
-                       hugo.Deprecate("--verbose", "use --logLevel info", "v0.114.0")
-                       level = logg.LevelInfo
-               }
+               if r.logLevel != "" {
+                       switch strings.ToLower(r.logLevel) {
+                       case "debug":
+                               level = logg.LevelDebug
+                       case "info":
+                               level = logg.LevelInfo
+                       case "warn", "warning":
+                               level = logg.LevelWarn
+                       case "error":
+                               level = logg.LevelError
+                       default:
+                               return nil, fmt.Errorf("invalid log level: %q, must be one of debug, warn, info or error", r.logLevel)
+                       }
+               } else {
+                       if r.verbose {
+                               hugo.Deprecate("--verbose", "use --logLevel info", "v0.114.0")
+                               hugo.Deprecate("--verbose", "use --logLevel info", "v0.114.0")
+                               level = logg.LevelInfo
+                       }
 
-               if r.debug {
-                       hugo.Deprecate("--debug", "use --logLevel debug", "v0.114.0")
-                       level = logg.LevelDebug
+                       if r.debug {
+                               hugo.Deprecate("--debug", "use --logLevel debug", "v0.114.0")
+                               level = logg.LevelDebug
+                       }
                }
        }
 
@@ -505,10 +510,13 @@ Complete documentation is available at https://gohugo.io/.`
 
        cmd.PersistentFlags().BoolVarP(&r.verbose, "verbose", "v", false, "verbose output")
        cmd.PersistentFlags().BoolVarP(&r.debug, "debug", "", false, "debug output")
+       cmd.PersistentFlags().BoolVarP(&r.devMode, "devMode", "", false, "only used for internal testing, flag hidden.")
        cmd.PersistentFlags().StringVar(&r.logLevel, "logLevel", "", "log level (debug|info|warn|error)")
        _ = cmd.RegisterFlagCompletionFunc("logLevel", cobra.FixedCompletions([]string{"debug", "info", "warn", "error"}, cobra.ShellCompDirectiveNoFileComp))
        cmd.Flags().BoolVarP(&r.buildWatch, "watch", "w", false, "watch filesystem for changes and recreate as needed")
 
+       cmd.PersistentFlags().MarkHidden("devMode")
+
        // Configure local flags
        applyLocalFlagsBuild(cmd, r)
 
index aa32b5320719e295705f50ad5d45ed10bdacdbfc..50e1bc35dcb709aad552adae055299f78031fd3f 100644 (file)
@@ -1084,7 +1084,7 @@ func (h *HugoSites) resolveAndClearStateForIdentities(
                                return b
                        }
 
-                       h.MemCache.ClearMatching(shouldDelete)
+                       h.MemCache.ClearMatching(nil, shouldDelete)
 
                        return ll, nil
                }); err != nil {
index 411f90734e7587ed14ef5a55ebdf019d7ce9171e..3beb072e3c7fb3ac15451ab50a29f25c03cc60cb 100644 (file)
@@ -23,6 +23,7 @@ import (
        "path"
        "path/filepath"
        "strings"
+       "sync"
        "time"
 
        "github.com/bep/logg"
@@ -46,6 +47,7 @@ import (
        "github.com/gohugoio/hugo/resources/page"
        "github.com/gohugoio/hugo/resources/page/siteidentities"
        "github.com/gohugoio/hugo/resources/postpub"
+       "github.com/gohugoio/hugo/resources/resource"
 
        "github.com/spf13/afero"
 
@@ -758,15 +760,45 @@ func (h *HugoSites) processPartial(ctx context.Context, l logg.LevelLogger, conf
                                }
                        }
                case files.ComponentFolderAssets:
-                       logger.Println("Asset changed", pathInfo.Path())
+                       p := pathInfo.Path()
+                       logger.Println("Asset changed", p)
+
+                       var matches []any
+                       var mu sync.Mutex
+
+                       h.MemCache.ClearMatching(
+                               func(k string, pm dynacache.PartitionManager) bool {
+                                       // Avoid going through everything.
+                                       return strings.HasPrefix(k, "/res")
+                               },
+                               func(k, v any) bool {
+                                       if strings.Contains(k.(string), p) {
+                                               mu.Lock()
+                                               defer mu.Unlock()
+                                               switch vv := v.(type) {
+                                               case resource.Resources:
+                                                       // GetMatch/Match.
+                                                       for _, r := range vv {
+                                                               matches = append(matches, r)
+                                                       }
+                                                       return true
+                                               default:
+                                                       matches = append(matches, vv)
+                                                       return true
+
+                                               }
+                                       }
+                                       return false
+                               })
 
                        var hasID bool
-                       r, _ := h.ResourceSpec.ResourceCache.Get(context.Background(), dynacache.CleanKey(pathInfo.Base()))
-                       identity.WalkIdentitiesShallow(r, func(level int, rid identity.Identity) bool {
-                               hasID = true
-                               changes = append(changes, rid)
-                               return false
-                       })
+                       for _, r := range matches {
+                               identity.WalkIdentitiesShallow(r, func(level int, rid identity.Identity) bool {
+                                       hasID = true
+                                       changes = append(changes, rid)
+                                       return false
+                               })
+                       }
                        if !hasID {
                                changes = append(changes, pathInfo)
                        }
index c193ca8af6b987115ae9a96d9dd23085e874257a..02e2b920000d72b53ecd434dee0ac903841bee19 100644 (file)
@@ -327,3 +327,34 @@ Styles: {{ $r.RelPermalink }}
 
        b.AssertFileContent("public/index.html", "Styles: /scss/main.css")
 }
+
+func TestRebuildAssetGetMatch(t *testing.T) {
+       t.Parallel()
+       if !scss.Supports() {
+               t.Skip()
+       }
+
+       files := `
+-- assets/scss/main.scss --
+b {
+       color: red;
+}
+-- layouts/index.html --
+{{ $r := resources.GetMatch "scss/main.scss" |  toCSS  }}
+T1: {{ $r.Content }}
+       `
+
+       b := hugolib.NewIntegrationTestBuilder(
+               hugolib.IntegrationTestConfig{
+                       T:           t,
+                       TxtarString: files,
+                       NeedsOsFS:   true,
+                       Running:     true,
+               }).Build()
+
+       b.AssertFileContent("public/index.html", `color: red`)
+
+       b.EditFiles("assets/scss/main.scss", `b { color: blue; }`).Build()
+
+       b.AssertFileContent("public/index.html", `color: blue`)
+}