diff options
author | Bjørn Erik Pedersen <[email protected]> | 2023-07-30 11:26:29 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2023-07-30 18:52:34 +0200 |
commit | fbb8eb39ecda4151e1f50355688071c67f8bbcf1 (patch) | |
tree | f1148914a743bbd4fd16c4a42e4c09165e067422 /resources | |
parent | 87d9bffe7402fabb8e91cc8c2b48e01e830aeb36 (diff) | |
download | hugo-fbb8eb39ecda4151e1f50355688071c67f8bbcf1.tar.gz hugo-fbb8eb39ecda4151e1f50355688071c67f8bbcf1.zip |
Fix so temporary images do not get published
Fixes #10255
Diffstat (limited to 'resources')
-rw-r--r-- | resources/image_cache.go | 22 | ||||
-rw-r--r-- | resources/integration_test.go | 39 | ||||
-rw-r--r-- | resources/resource.go | 53 |
3 files changed, 65 insertions, 49 deletions
diff --git a/resources/image_cache.go b/resources/image_cache.go index 636607f94..542a6836f 100644 --- a/resources/image_cache.go +++ b/resources/image_cache.go @@ -106,28 +106,10 @@ func (c *ImageCache) getOrCreate( rp := img.getResourcePaths() rp.relTargetDirFile.file = relTarget.file img.setSourceFilename(info.Name) + img.setSourfeFilenameIsHash(true) img.setMediaType(conf.TargetFormat.MediaType()) - if err := img.InitConfig(r); err != nil { - return err - } - - r.Seek(0, 0) - - w, err := img.openDestinationsForWriting() - if err != nil { - return err - } - - if w == nil { - // Nothing to write. - return nil - } - - defer w.Close() - _, err = io.Copy(w, r) - - return err + return img.InitConfig(r) } // create creates the image and encodes it to the cache (w). diff --git a/resources/integration_test.go b/resources/integration_test.go index 543c264dc..2075079dc 100644 --- a/resources/integration_test.go +++ b/resources/integration_test.go @@ -100,3 +100,42 @@ Width: {{ $svg.Width }} b.Assert(err.Error(), qt.Contains, `error calling Width: this method is only available for raster images. To determine if an image is SVG, you can do {{ if eq .MediaType.SubType "svg" }}{{ end }}`) } + +// Issue 10255. +func TestNoPublishOfUnusedProcessedImage(t *testing.T) { + t.Parallel() + + workingDir := t.TempDir() + + files := ` +-- assets/images/pixel.png -- +iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg== +-- layouts/index.html -- +{{ $image := resources.Get "images/pixel.png" }} +{{ $image = $image.Resize "400x" }} +{{ $image = $image.Resize "300x" }} +{{ $image = $image.Resize "200x" }} +{{ $image = $image.Resize "100x" }} +{{ $image = $image.Crop "50x50" }} +{{ $image = $image.Filter (images.GaussianBlur 6) }} +{{ ($image | fingerprint).Permalink }} + + +` + + for i := 0; i < 3; i++ { + + b := hugolib.NewIntegrationTestBuilder( + hugolib.IntegrationTestConfig{ + T: t, + TxtarString: files, + NeedsOsFS: true, + WorkingDir: workingDir, + }).Build() + + b.AssertFileCount("resources/_gen/images", 6) + b.AssertFileCount("public/images", 1) + b.Build() + } + +} diff --git a/resources/resource.go b/resources/resource.go index d1acc1026..884900d58 100644 --- a/resources/resource.go +++ b/resources/resource.go @@ -161,7 +161,6 @@ type baseResourceInternal interface { specProvider getResourcePaths() *resourcePathDescriptor getTargetFilenames() []string - openDestinationsForWriting() (io.WriteCloser, error) openPublishFileForWriting(relTargetPath string) (io.WriteCloser, error) relTargetPathForRel(rel string, addBaseTargetPath, isAbs, isURL bool) string @@ -216,6 +215,7 @@ func (d dirFile) path() string { type fileInfo interface { getSourceFilename() string setSourceFilename(string) + setSourfeFilenameIsHash(bool) setSourceFs(afero.Fs) getFileInfo() hugofs.FileMetaInfo hash() (string, error) @@ -304,6 +304,21 @@ func (l *genericResource) Permalink() string { func (l *genericResource) Publish() error { var err error l.publishInit.Do(func() { + targetFilenames := l.getTargetFilenames() + if l.sourceFilenameIsHash { + // This is a processed image. We want to avoid copying it if it hasn't changed. + var changedFilenames []string + for _, targetFilename := range targetFilenames { + if _, err := l.getSpec().BaseFs.PublishFs.Stat(targetFilename); err == nil { + continue + } + changedFilenames = append(changedFilenames, targetFilename) + } + if len(changedFilenames) == 0 { + return + } + targetFilenames = changedFilenames + } var fr hugio.ReadSeekCloser fr, err = l.ReadSeekCloser() if err != nil { @@ -312,7 +327,7 @@ func (l *genericResource) Publish() error { defer fr.Close() var fw io.WriteCloser - fw, err = helpers.OpenFilesForWriting(l.spec.BaseFs.PublishFs, l.getTargetFilenames()...) + fw, err = helpers.OpenFilesForWriting(l.spec.BaseFs.PublishFs, targetFilenames...) if err != nil { return } @@ -475,33 +490,6 @@ func (l genericResource) clone() *genericResource { return &l } -// 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 exists at the destination. - for _, targetFilename := range targetFilenames { - if _, err := l.getSpec().BaseFs.PublishFs.Stat(targetFilename); err == nil { - continue - } - - changedFilenames = append(changedFilenames, targetFilename) - } - - if len(changedFilenames) == 0 { - return - } - - w, err = helpers.OpenFilesForWriting(l.getSpec().BaseFs.PublishFs, changedFilenames...) - }) - - return -} - func (r *genericResource) openPublishFileForWriting(relTargetPath string) (io.WriteCloser, error) { return helpers.OpenFilesForWriting(r.spec.BaseFs.PublishFs, r.relTargetPathsFor(relTargetPath)...) } @@ -622,6 +610,9 @@ type resourceFileInfo struct { // the path to the file on the real filesystem. sourceFilename string + // For performance. This means that whenever the content changes, the filename changes. + sourceFilenameIsHash bool + fi hugofs.FileMetaInfo // A hash of the source content. Is only calculated in caching situations. @@ -654,6 +645,10 @@ func (fi *resourceFileInfo) setSourceFilename(s string) { fi.sourceFilename = s } +func (fi *resourceFileInfo) setSourfeFilenameIsHash(b bool) { + fi.sourceFilenameIsHash = b +} + func (fi *resourceFileInfo) getSourceFs() afero.Fs { return fi.sourceFs } |