mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
parent
87d9bffe74
commit
fbb8eb39ec
4 changed files with 83 additions and 49 deletions
|
@ -137,6 +137,24 @@ func (s *IntegrationTestBuilder) AssertBuildCountTranslations(count int) {
|
||||||
s.Assert(s.H.init.translations.InitCount(), qt.Equals, count)
|
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) {
|
func (s *IntegrationTestBuilder) AssertFileContent(filename string, matches ...string) {
|
||||||
s.Helper()
|
s.Helper()
|
||||||
content := strings.TrimSpace(s.FileContent(filename))
|
content := strings.TrimSpace(s.FileContent(filename))
|
||||||
|
|
|
@ -106,28 +106,10 @@ func (c *ImageCache) getOrCreate(
|
||||||
rp := img.getResourcePaths()
|
rp := img.getResourcePaths()
|
||||||
rp.relTargetDirFile.file = relTarget.file
|
rp.relTargetDirFile.file = relTarget.file
|
||||||
img.setSourceFilename(info.Name)
|
img.setSourceFilename(info.Name)
|
||||||
|
img.setSourfeFilenameIsHash(true)
|
||||||
img.setMediaType(conf.TargetFormat.MediaType())
|
img.setMediaType(conf.TargetFormat.MediaType())
|
||||||
|
|
||||||
if err := img.InitConfig(r); err != nil {
|
return img.InitConfig(r)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create creates the image and encodes it to the cache (w).
|
// create creates the image and encodes it to the cache (w).
|
||||||
|
|
|
@ -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 }}`)
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -161,7 +161,6 @@ type baseResourceInternal interface {
|
||||||
specProvider
|
specProvider
|
||||||
getResourcePaths() *resourcePathDescriptor
|
getResourcePaths() *resourcePathDescriptor
|
||||||
getTargetFilenames() []string
|
getTargetFilenames() []string
|
||||||
openDestinationsForWriting() (io.WriteCloser, error)
|
|
||||||
openPublishFileForWriting(relTargetPath string) (io.WriteCloser, error)
|
openPublishFileForWriting(relTargetPath string) (io.WriteCloser, error)
|
||||||
|
|
||||||
relTargetPathForRel(rel string, addBaseTargetPath, isAbs, isURL bool) string
|
relTargetPathForRel(rel string, addBaseTargetPath, isAbs, isURL bool) string
|
||||||
|
@ -216,6 +215,7 @@ func (d dirFile) path() string {
|
||||||
type fileInfo interface {
|
type fileInfo interface {
|
||||||
getSourceFilename() string
|
getSourceFilename() string
|
||||||
setSourceFilename(string)
|
setSourceFilename(string)
|
||||||
|
setSourfeFilenameIsHash(bool)
|
||||||
setSourceFs(afero.Fs)
|
setSourceFs(afero.Fs)
|
||||||
getFileInfo() hugofs.FileMetaInfo
|
getFileInfo() hugofs.FileMetaInfo
|
||||||
hash() (string, error)
|
hash() (string, error)
|
||||||
|
@ -304,6 +304,21 @@ func (l *genericResource) Permalink() string {
|
||||||
func (l *genericResource) Publish() error {
|
func (l *genericResource) Publish() error {
|
||||||
var err error
|
var err error
|
||||||
l.publishInit.Do(func() {
|
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
|
var fr hugio.ReadSeekCloser
|
||||||
fr, err = l.ReadSeekCloser()
|
fr, err = l.ReadSeekCloser()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -312,7 +327,7 @@ func (l *genericResource) Publish() error {
|
||||||
defer fr.Close()
|
defer fr.Close()
|
||||||
|
|
||||||
var fw io.WriteCloser
|
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 {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -475,33 +490,6 @@ func (l genericResource) clone() *genericResource {
|
||||||
return &l
|
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) {
|
func (r *genericResource) openPublishFileForWriting(relTargetPath string) (io.WriteCloser, error) {
|
||||||
return helpers.OpenFilesForWriting(r.spec.BaseFs.PublishFs, r.relTargetPathsFor(relTargetPath)...)
|
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.
|
// the path to the file on the real filesystem.
|
||||||
sourceFilename string
|
sourceFilename string
|
||||||
|
|
||||||
|
// For performance. This means that whenever the content changes, the filename changes.
|
||||||
|
sourceFilenameIsHash bool
|
||||||
|
|
||||||
fi hugofs.FileMetaInfo
|
fi hugofs.FileMetaInfo
|
||||||
|
|
||||||
// A hash of the source content. Is only calculated in caching situations.
|
// 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
|
fi.sourceFilename = s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fi *resourceFileInfo) setSourfeFilenameIsHash(b bool) {
|
||||||
|
fi.sourceFilenameIsHash = b
|
||||||
|
}
|
||||||
|
|
||||||
func (fi *resourceFileInfo) getSourceFs() afero.Fs {
|
func (fi *resourceFileInfo) getSourceFs() afero.Fs {
|
||||||
return fi.sourceFs
|
return fi.sourceFs
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue