Skip to content

Commit 766a2e7

Browse files
committed
Make sure that unreferenced but changed bundle resources gets republished
Fixes #13748
1 parent 13e1617 commit 766a2e7

File tree

8 files changed

+73
-34
lines changed

8 files changed

+73
-34
lines changed

‎hugolib/content_map_page.go‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"sort"
2222
"strconv"
2323
"strings"
24-
"sync"
2524
"sync/atomic"
2625
"time"
2726

@@ -1310,7 +1309,6 @@ func (h *HugoSites) resolveAndResetDependententPageOutputs(ctx context.Context,
13101309
}
13111310

13121311
po.renderState = 0
1313-
po.p.resourcesPublishInit = &sync.Once{}
13141312
if r == identity.FinderFoundOneOfMany || po.f.Name == output.HTTPStatus404HTMLFormat.Name {
13151313
// Will force a re-render even in fast render mode.
13161314
po.renderOnce = false

‎hugolib/hugo_sites_build.go‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -905,7 +905,6 @@ func (h *HugoSites) processPartialFileEvents(ctx context.Context, l logg.LevelLo
905905
handleChange := func(pathInfo *paths.Path, delete, isDir bool) {
906906
switch pathInfo.Component() {
907907
case files.ComponentFolderContent:
908-
logger.Println("Source changed", pathInfo.Path())
909908
isContentDataFile := pathInfo.IsContentData()
910909
if !isContentDataFile {
911910
if ids := h.pageTrees.collectAndMarkStaleIdentities(pathInfo); len(ids) > 0 {

‎hugolib/page.go‎

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"path/filepath"
2020
"strconv"
2121
"strings"
22-
"sync"
2322
"sync/atomic"
2423

2524
"github.com/gohugoio/hugo/hugofs"
@@ -29,6 +28,7 @@ import (
2928
"github.com/gohugoio/hugo/media"
3029
"github.com/gohugoio/hugo/output"
3130
"github.com/gohugoio/hugo/related"
31+
"github.com/gohugoio/hugo/resources"
3232
"github.com/gohugoio/hugo/tpl/tplimpl"
3333
"github.com/spf13/afero"
3434

@@ -110,8 +110,7 @@ type pageState struct {
110110
*pageCommon
111111

112112
resource.Staler
113-
dependencyManager identity.Manager
114-
resourcesPublishInit *sync.Once
113+
dependencyManager identity.Manager
115114
}
116115

117116
func (p *pageState) incrPageOutputTemplateVariation() {
@@ -522,39 +521,41 @@ func (p *pageState) initPage() error {
522521
}
523522

524523
func (p *pageState) renderResources() error {
525-
var initErr error
524+
for _, r := range p.Resources() {
526525

527-
p.resourcesPublishInit.Do(func() {
528-
for _, r := range p.Resources() {
529-
if _, ok := r.(page.Page); ok {
526+
if _, ok := r.(page.Page); ok {
527+
if p.s.h.buildCounter.Load() == 0 {
530528
// Pages gets rendered with the owning page but we count them here.
531529
p.s.PathSpec.ProcessingStats.Incr(&p.s.PathSpec.ProcessingStats.Pages)
532-
continue
533530
}
531+
continue
532+
}
534533

535-
if _, isWrapper := r.(resource.ResourceWrapper); isWrapper {
536-
// Skip resources that are wrapped.
537-
// These gets published on its own.
538-
continue
539-
}
534+
if resources.IsPublished(r) {
535+
continue
536+
}
540537

541-
src, ok := r.(resource.Source)
542-
if !ok {
543-
initErr = fmt.Errorf("resource %T does not support resource.Source", r)
544-
return
545-
}
538+
if _, isWrapper := r.(resource.ResourceWrapper); isWrapper {
539+
// Skip resources that are wrapped.
540+
// These gets published on its own.
541+
continue
542+
}
546543

547-
if err := src.Publish(); err != nil {
548-
if !herrors.IsNotExist(err) {
549-
p.s.Log.Errorf("Failed to publish Resource for page %q: %s", p.pathOrTitle(), err)
550-
}
551-
} else {
552-
p.s.PathSpec.ProcessingStats.Incr(&p.s.PathSpec.ProcessingStats.Files)
544+
src, ok := r.(resource.Source)
545+
if !ok {
546+
return fmt.Errorf("resource %T does not support resource.Source", r)
547+
}
548+
549+
if err := src.Publish(); err != nil {
550+
if !herrors.IsNotExist(err) {
551+
p.s.Log.Errorf("Failed to publish Resource for page %q: %s", p.pathOrTitle(), err)
553552
}
553+
} else {
554+
p.s.PathSpec.ProcessingStats.Incr(&p.s.PathSpec.ProcessingStats.Files)
554555
}
555-
})
556+
}
556557

557-
return initErr
558+
return nil
558559
}
559560

560561
func (p *pageState) AlternativeOutputFormats() page.OutputFormats {

‎hugolib/page__new.go‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ package hugolib
1616
import (
1717
"fmt"
1818
"strings"
19-
"sync"
2019
"sync/atomic"
2120

2221
"github.com/gohugoio/hugo/hugofs/files"
@@ -190,7 +189,6 @@ func (h *HugoSites) doNewPage(m *pageMeta) (*pageState, *paths.Path, error) {
190189
pid: pid,
191190
pageOutput: nopPageOutput,
192191
pageOutputTemplateVariationsState: &atomic.Uint32{},
193-
resourcesPublishInit: &sync.Once{},
194192
Staler: m,
195193
dependencyManager: m.s.Conf.NewIdentityManager(m.Path()),
196194
pageCommon: &pageCommon{

‎hugolib/rebuild_test.go‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1946,3 +1946,23 @@ tags: ["tag1"]
19461946
// But that is a harder problem to tackle.
19471947
b.AssertFileContent("public/tags/index.html", "All. Tag1|Tag2|")
19481948
}
1949+
1950+
func TestRebuildEditNonReferencedResourceIssue13748(t *testing.T) {
1951+
t.Parallel()
1952+
1953+
files := `
1954+
-- hugo.toml --
1955+
baseURL = "https://example.com"
1956+
disableLiveReload = true
1957+
-- content/mybundle/index.md --
1958+
-- content/mybundle/resource.txt --
1959+
This is a resource file.
1960+
-- layouts/all.html --
1961+
All.
1962+
`
1963+
b := TestRunning(t, files)
1964+
1965+
b.AssertFileContent("public/mybundle/resource.txt", "This is a resource file.")
1966+
b.EditFileReplaceAll("content/mybundle/resource.txt", "This is a resource file.", "This is an edited resource file.").Build()
1967+
b.AssertFileContent("public/mybundle/resource.txt", "This is an edited resource file.")
1968+
}

‎resources/resource.go‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"sync/atomic"
2525

2626
"github.com/gohugoio/hugo/identity"
27+
"github.com/gohugoio/hugo/lazy"
2728
"github.com/gohugoio/hugo/resources/internal"
2829

2930
"github.com/gohugoio/hugo/common/hashing"
@@ -54,6 +55,7 @@ var (
5455
_ identity.DependencyManagerProvider = (*genericResource)(nil)
5556
_ identity.Identity = (*genericResource)(nil)
5657
_ fileInfo = (*genericResource)(nil)
58+
_ isPublishedProvider = (*genericResource)(nil)
5759
)
5860

5961
type ResourceSourceDescriptor struct {
@@ -242,6 +244,7 @@ type baseResourceInternal interface {
242244
fileInfo
243245
mediaTypeAssigner
244246
targetPather
247+
isPublishedProvider
245248

246249
ReadSeekCloser() (hugio.ReadSeekCloser, error)
247250

@@ -355,7 +358,7 @@ func GetTestInfoForResource(r resource.Resource) GenericResourceTestInfo {
355358

356359
// genericResource represents a generic linkable resource.
357360
type genericResource struct {
358-
publishInit *sync.Once
361+
publishInit *lazy.OnceMore
359362

360363
key string
361364
keyInit *sync.Once
@@ -536,6 +539,10 @@ func (l *genericResource) Publish() error {
536539
return err
537540
}
538541

542+
func (l *genericResource) isPublished() bool {
543+
return l.publishInit.Done()
544+
}
545+
539546
func (l *genericResource) RelPermalink() string {
540547
return l.spec.PathSpec.GetBasePath(false) + paths.PathEscape(l.paths.TargetLink())
541548
}
@@ -629,7 +636,7 @@ func (rc *genericResource) cloneWithUpdates(u *transformationUpdate) (baseResour
629636
}
630637

631638
func (l genericResource) clone() *genericResource {
632-
l.publishInit = &sync.Once{}
639+
l.publishInit = &lazy.OnceMore{}
633640
l.keyInit = &sync.Once{}
634641
return &l
635642
}
@@ -643,6 +650,10 @@ type targetPather interface {
643650
TargetPath() string
644651
}
645652

653+
type isPublishedProvider interface {
654+
isPublished() bool
655+
}
656+
646657
type resourceHash struct {
647658
value uint64
648659
size int64
@@ -702,6 +713,11 @@ func InternalResourceSourcePathBestEffort(r resource.Resource) string {
702713
return InternalResourceTargetPath(r)
703714
}
704715

716+
// isPublished returns true if the resource is published.
717+
func IsPublished(r resource.Resource) bool {
718+
return r.(isPublishedProvider).isPublished()
719+
}
720+
705721
type targetPathProvider interface {
706722
// targetPath is the relative path to this resource.
707723
// In most cases this will be the same as the RelPermalink(),

‎resources/resource_spec.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
"github.com/gohugoio/hugo/config"
2222
"github.com/gohugoio/hugo/config/allconfig"
23+
"github.com/gohugoio/hugo/lazy"
2324
"github.com/gohugoio/hugo/output"
2425
"github.com/gohugoio/hugo/resources/internal"
2526
"github.com/gohugoio/hugo/resources/jsconfig"
@@ -189,7 +190,7 @@ func (r *Spec) NewResource(rd ResourceSourceDescriptor) (resource.Resource, erro
189190
gr := &genericResource{
190191
Staler: &AtomicStaler{},
191192
h: &resourceHash{},
192-
publishInit: &sync.Once{},
193+
publishInit: &lazy.OnceMore{},
193194
keyInit: &sync.Once{},
194195
includeHashInKey: isImage,
195196
paths: rp,

‎resources/transform.go‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ var (
6161
_ identity.DependencyManagerProvider = (*resourceAdapter)(nil)
6262
_ identity.IdentityGroupProvider = (*resourceAdapter)(nil)
6363
_ resource.NameNormalizedProvider = (*resourceAdapter)(nil)
64+
_ isPublishedProvider = (*resourceAdapter)(nil)
6465
)
6566

6667
// These are transformations that need special support in Hugo that may not
@@ -325,6 +326,11 @@ func (r *resourceAdapter) Publish() error {
325326
return r.target.Publish()
326327
}
327328

329+
func (r *resourceAdapter) isPublished() bool {
330+
r.init(false, false)
331+
return r.target.isPublished()
332+
}
333+
328334
func (r *resourceAdapter) ReadSeekCloser() (hugio.ReadSeekCloser, error) {
329335
r.init(false, false)
330336
return r.target.ReadSeekCloser()

0 commit comments

Comments
 (0)