aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--hugolib/image_test.go3
-rw-r--r--hugolib/testhelpers_test.go8
-rw-r--r--resources/resource.go71
3 files changed, 55 insertions, 27 deletions
diff --git a/hugolib/image_test.go b/hugolib/image_test.go
index 4db57e4a5..a13338afc 100644
--- a/hugolib/image_test.go
+++ b/hugolib/image_test.go
@@ -211,4 +211,7 @@ SUNSET2: {{ $resized2.RelPermalink }}/{{ $resized2.Width }}/Lat: {{ $resized2.Ex
b.AssertFileContent("resources/_gen/images/sunset_17701188623491591036.json",
"DateTimeDigitized|time.Time", "PENTAX")
+ // TODO(bep) add this as a default assertion after Build()?
+ b.AssertNoDuplicateWrites()
+
}
diff --git a/hugolib/testhelpers_test.go b/hugolib/testhelpers_test.go
index 6e62a2442..6e00a8ee0 100644
--- a/hugolib/testhelpers_test.go
+++ b/hugolib/testhelpers_test.go
@@ -486,6 +486,8 @@ func (s *sitesBuilder) CreateSitesE() error {
return errors.Wrap(err, "failed to load config")
}
+ s.Fs.Destination = hugofs.NewCreateCountingFs(s.Fs.Destination)
+
depsCfg := s.depsCfg
depsCfg.Fs = s.Fs
depsCfg.Cfg = s.Cfg
@@ -680,6 +682,12 @@ func (s *sitesBuilder) AssertImage(width, height int, filename string) {
s.Assert(cfg.Height, qt.Equals, height)
}
+func (s *sitesBuilder) AssertNoDuplicateWrites() {
+ s.Helper()
+ d := s.Fs.Destination.(hugofs.DuplicatesReporter)
+ s.Assert(d.ReportDuplicates(), qt.Equals, "")
+}
+
func (s *sitesBuilder) FileContent(filename string) string {
s.T.Helper()
filename = filepath.FromSlash(filename)
diff --git a/resources/resource.go b/resources/resource.go
index 637f8e8fd..7e755bdbc 100644
--- a/resources/resource.go
+++ b/resources/resource.go
@@ -233,19 +233,26 @@ func (l *genericResource) Permalink() string {
}
func (l *genericResource) Publish() error {
- fr, err := l.ReadSeekCloser()
- if err != nil {
- return err
- }
- defer fr.Close()
+ var err error
+ l.publishInit.Do(func() {
+ var fr hugio.ReadSeekCloser
+ fr, err = l.ReadSeekCloser()
+ if err != nil {
+ return
+ }
+ defer fr.Close()
- fw, err := helpers.OpenFilesForWriting(l.spec.BaseFs.PublishFs, l.getTargetFilenames()...)
- if err != nil {
- return err
- }
- defer fw.Close()
+ var fw io.WriteCloser
+ fw, err = helpers.OpenFilesForWriting(l.spec.BaseFs.PublishFs, l.getTargetFilenames()...)
+ if err != nil {
+ return
+ }
+ defer fw.Close()
+
+ _, err = io.Copy(fw, fr)
+
+ })
- _, err = io.Copy(fw, fr)
return err
}
@@ -400,26 +407,34 @@ func (l genericResource) clone() *genericResource {
return &l
}
-// returns an opened file or nil if nothing to write.
-func (l *genericResource) openDestinationsForWriting() (io.WriteCloser, error) {
- targetFilenames := l.getTargetFilenames()
- var changedFilenames []string
+// returns an opened file or nil if nothing to write (it may already be published).
+func (l *genericResource) openDestinationsForWriting() (w io.WriteCloser, err error) {
+
+ l.publishInit.Do(func() {
+ targetFilenames := l.getTargetFilenames()
+ var changedFilenames []string
+
+ // Fast path:
+ // This is a processed version of the original;
+ // check if it already existis at the destination.
+ for _, targetFilename := range targetFilenames {
+ if _, err := l.getSpec().BaseFs.PublishFs.Stat(targetFilename); err == nil {
+ continue
+ }
- // Fast path:
- // This is a processed version of the original;
- // check if it already existis at the destination.
- for _, targetFilename := range targetFilenames {
- if _, err := l.getSpec().BaseFs.PublishFs.Stat(targetFilename); err == nil {
- continue
+ changedFilenames = append(changedFilenames, targetFilename)
}
- changedFilenames = append(changedFilenames, targetFilename)
- }
- if len(changedFilenames) == 0 {
- return nil, nil
- }
+ if len(changedFilenames) == 0 {
+ return
+ }
+
+ w, err = helpers.OpenFilesForWriting(l.getSpec().BaseFs.PublishFs, changedFilenames...)
+
+ })
+
+ return
- return helpers.OpenFilesForWriting(l.getSpec().BaseFs.PublishFs, changedFilenames...)
}
func (r *genericResource) openPublishFileForWriting(relTargetPath string) (io.WriteCloser, error) {
@@ -524,6 +539,8 @@ type permalinker interface {
type resourceContent struct {
content string
contentInit sync.Once
+
+ publishInit sync.Once
}
type resourceFileInfo struct {