]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Fix so temporary images do not get published
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 30 Jul 2023 09:26:29 +0000 (11:26 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 30 Jul 2023 16:52:34 +0000 (18:52 +0200)
Fixes #10255

hugolib/integrationtest_builder.go
resources/image_cache.go
resources/integration_test.go
resources/resource.go

index 6a5cd1ce3325a626ec0ec4b9c2cbff57bd839cb9..c06c9d25f8cfd3341014614f7f67914feb107002 100644 (file)
@@ -137,6 +137,24 @@ func (s *IntegrationTestBuilder) AssertBuildCountTranslations(count int) {
        s.Assert(s.H.init.translations.InitCount(), qt.Equals, count)
 }
 
+func (s *IntegrationTestBuilder) AssertFileCount(dirname string, expected int) {
+       s.Helper()
+       fs := s.fs.WorkingDirReadOnly
+       count := 0
+       afero.Walk(fs, dirname, func(path string, info os.FileInfo, err error) error {
+               if err != nil {
+                       return err
+               }
+               if info.IsDir() {
+                       return nil
+               }
+               count++
+               return nil
+       })
+       s.Assert(count, qt.Equals, expected)
+
+}
+
 func (s *IntegrationTestBuilder) AssertFileContent(filename string, matches ...string) {
        s.Helper()
        content := strings.TrimSpace(s.FileContent(filename))
index 636607f945254ae7e0fd75aa6fdfba8bd715fe23..542a6836fc167a8a678fce66189372ea5f93add3 100644 (file)
@@ -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).
index 543c264dcf13179d67c69b0057e499ca860952b9..2075079dcc2fa109c002bf03e4d322acded8b381 100644 (file)
@@ -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()
+       }
+
+}
index d1acc10268162b27569359bf11e986a4afae03f5..884900d5870fc800f39c86f0c8007e9320d52222 100644 (file)
@@ -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
 }