shithub: hugo

Download patch

ref: 3be2c25351b421a26ee1ff2a38cbab00280c0583
parent: 5e660947757023434dd7a1ec8b8239c0577fd501
author: Bjørn Erik Pedersen <[email protected]>
date: Thu Sep 5 14:03:00 EDT 2019

Fix concat with fingerprint regression

In Hugo 0.58 we optimized the transformers that only adjusted metadata, e.g. the fingerprint.

This depended on the source readers implementing `io.ReadSeeker`.

The reader produced by `concat` did that, but the implementation was buggy.

This commit fixes that.

Fixes #6309

--- a/hugolib/resource_chain_test.go
+++ b/hugolib/resource_chain_test.go
@@ -284,7 +284,7 @@
 	}
 }
 
-func TestResourceChain(t *testing.T) {
+func TestResourceChains(t *testing.T) {
 	t.Parallel()
 
 	c := qt.New(t)
@@ -389,6 +389,23 @@
 ;
 (function F {})()`)
 		}},
+
+		{"concat and fingerprint", func() bool { return true }, func(b *sitesBuilder) {
+			b.WithTemplates("home.html", `
+{{ $a := "A" | resources.FromString "a.txt"}}
+{{ $b := "B" | resources.FromString "b.txt"}}
+{{ $c := "C" | resources.FromString "c.txt"}}
+{{ $combined := slice $a $b $c | resources.Concat "bundle/concat.txt" }}
+{{ $fingerprinted := $combined | fingerprint }}
+Fingerprinted: {{ $fingerprinted.RelPermalink }}
+`)
+		}, func(b *sitesBuilder) {
+
+			b.AssertFileContent("public/index.html", "Fingerprinted: /bundle/concat.b5d4045c3f466fa91fe2cc6abe79232a1a57cdf104f7a26e716e0a1e2789df78.txt")
+			b.AssertFileContent("public/bundle/concat.b5d4045c3f466fa91fe2cc6abe79232a1a57cdf104f7a26e716e0a1e2789df78.txt", "ABC")
+
+		}},
+
 		{"fromstring", func() bool { return true }, func(b *sitesBuilder) {
 			b.WithTemplates("home.html", `
 {{ $r := "Hugo Rocks!" | resources.FromString "rocks/hugo.txt" }}
--- a/resources/resource_factories/bundler/bundler.go
+++ b/resources/resource_factories/bundler/bundler.go
@@ -15,7 +15,6 @@
 package bundler
 
 import (
-	"bytes"
 	"fmt"
 	"io"
 	"path"
@@ -43,6 +42,19 @@
 	sources []hugio.ReadSeekCloser
 }
 
+func toReaders(sources []hugio.ReadSeekCloser) []io.Reader {
+	readers := make([]io.Reader, len(sources))
+	for i, r := range sources {
+		readers[i] = r
+	}
+	return readers
+}
+
+func newMultiReadSeekCloser(sources ...hugio.ReadSeekCloser) *multiReadSeekCloser {
+	mr := io.MultiReader(toReaders(sources)...)
+	return &multiReadSeekCloser{mr, sources}
+}
+
 func (r *multiReadSeekCloser) Read(p []byte) (n int, err error) {
 	return r.mr.Read(p)
 }
@@ -54,6 +66,9 @@
 			return
 		}
 	}
+
+	r.mr = io.MultiReader(toReaders(r.sources)...)
+
 	return
 }
 
@@ -98,31 +113,24 @@
 				rcsources = append(rcsources, rc)
 			}
 
-			var readers []io.Reader
-
 			// Arbitrary JavaScript files require a barrier between them to be safely concatenated together.
 			// Without this, the last line of one file can affect the first line of the next file and change how both files are interpreted.
 			if resolvedm.MainType == media.JavascriptType.MainType && resolvedm.SubType == media.JavascriptType.SubType {
-				readers = make([]io.Reader, 2*len(rcsources)-1)
+				readers := make([]hugio.ReadSeekCloser, 2*len(rcsources)-1)
 				j := 0
 				for i := 0; i < len(rcsources); i++ {
 					if i > 0 {
-						readers[j] = bytes.NewBufferString("\n;\n")
+						readers[j] = hugio.NewReadSeekerNoOpCloserFromString("\n;\n")
 						j++
 					}
 					readers[j] = rcsources[i]
 					j++
 				}
-			} else {
-				readers = make([]io.Reader, len(rcsources))
-				for i := 0; i < len(rcsources); i++ {
-					readers[i] = rcsources[i]
-				}
+				return newMultiReadSeekCloser(readers...), nil
 			}
 
-			mr := io.MultiReader(readers...)
+			return newMultiReadSeekCloser(rcsources...), nil
 
-			return &multiReadSeekCloser{mr: mr, sources: rcsources}, nil
 		}
 
 		composite, err := c.rs.New(
--- /dev/null
+++ b/resources/resource_factories/bundler/bundler_test.go
@@ -1,0 +1,41 @@
+// Copyright 2019 The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bundler
+
+import (
+	"testing"
+
+	"github.com/gohugoio/hugo/helpers"
+
+	qt "github.com/frankban/quicktest"
+	"github.com/gohugoio/hugo/common/hugio"
+)
+
+func TestMultiReadSeekCloser(t *testing.T) {
+	c := qt.New(t)
+
+	rc := newMultiReadSeekCloser(
+		hugio.NewReadSeekerNoOpCloserFromString("A"),
+		hugio.NewReadSeekerNoOpCloserFromString("B"),
+		hugio.NewReadSeekerNoOpCloserFromString("C"),
+	)
+
+	for i := 0; i < 3; i++ {
+		s1 := helpers.ReaderToString(rc)
+		c.Assert(s1, qt.Equals, "ABC")
+		_, err := rc.Seek(0, 0)
+		c.Assert(err, qt.IsNil)
+	}
+
+}