summaryrefslogtreecommitdiffhomepage
path: root/resource
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2018-03-21 17:21:46 +0100
committerBjørn Erik Pedersen <[email protected]>2018-04-02 08:06:21 +0200
commiteb42774e587816b1fbcafbcea59ed65df703882a (patch)
treefdb62cf17355b47fa485941f3c3fffd604896daa /resource
parentf27977809ce5d5dce4db41db6323a4ad1b095985 (diff)
downloadhugo-eb42774e587816b1fbcafbcea59ed65df703882a.tar.gz
hugo-eb42774e587816b1fbcafbcea59ed65df703882a.zip
Add support for a content dir set per language
A sample config: ```toml defaultContentLanguage = "en" defaultContentLanguageInSubdir = true [Languages] [Languages.en] weight = 10 title = "In English" languageName = "English" contentDir = "content/english" [Languages.nn] weight = 20 title = "På Norsk" languageName = "Norsk" contentDir = "content/norwegian" ``` The value of `contentDir` can be any valid path, even absolute path references. The only restriction is that the content dirs cannot overlap. The content files will be assigned a language by 1. The placement: `content/norwegian/post/my-post.md` will be read as Norwegian content. 2. The filename: `content/english/post/my-post.nn.md` will be read as Norwegian even if it lives in the English content folder. The content directories will be merged into a big virtual filesystem with one simple rule: The most specific language file will win. This means that if both `content/norwegian/post/my-post.md` and `content/english/post/my-post.nn.md` exists, they will be considered duplicates and the version inside `content/norwegian` will win. Note that translations will be automatically assigned by Hugo by the content file's relative placement, so `content/norwegian/post/my-post.md` will be a translation of `content/english/post/my-post.md`. If this does not work for you, you can connect the translations together by setting a `translationKey` in the content files' front matter. Fixes #4523 Fixes #4552 Fixes #4553
Diffstat (limited to 'resource')
-rw-r--r--resource/image.go41
-rw-r--r--resource/image_cache.go19
-rw-r--r--resource/image_test.go29
-rw-r--r--resource/resource.go84
-rw-r--r--resource/resource_test.go76
-rw-r--r--resource/testhelpers_test.go45
6 files changed, 171 insertions, 123 deletions
diff --git a/resource/image.go b/resource/image.go
index a1e0aac70..84dc56fa7 100644
--- a/resource/image.go
+++ b/resource/image.go
@@ -419,7 +419,7 @@ func (i *Image) initConfig() error {
config image.Config
)
- f, err = i.spec.Fs.Source.Open(i.AbsSourceFilename())
+ f, err = i.sourceFs().Open(i.AbsSourceFilename())
if err != nil {
return
}
@@ -432,13 +432,17 @@ func (i *Image) initConfig() error {
i.config = config
})
- return err
+ if err != nil {
+ return fmt.Errorf("failed to load image config: %s", err)
+ }
+
+ return nil
}
func (i *Image) decodeSource() (image.Image, error) {
- file, err := i.spec.Fs.Source.Open(i.AbsSourceFilename())
+ file, err := i.sourceFs().Open(i.AbsSourceFilename())
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("failed to open image for decode: %s", err)
}
defer file.Close()
img, _, err := image.Decode(file)
@@ -448,32 +452,32 @@ func (i *Image) decodeSource() (image.Image, error) {
func (i *Image) copyToDestination(src string) error {
var res error
i.copyToDestinationInit.Do(func() {
- target := filepath.Join(i.absPublishDir, i.target())
+ target := i.target()
// Fast path:
// This is a processed version of the original.
// If it exists on destination with the same filename and file size, it is
// the same file, so no need to transfer it again.
- if fi, err := i.spec.Fs.Destination.Stat(target); err == nil && fi.Size() == i.osFileInfo.Size() {
+ if fi, err := i.spec.BaseFs.PublishFs.Stat(target); err == nil && fi.Size() == i.osFileInfo.Size() {
return
}
- in, err := i.spec.Fs.Source.Open(src)
+ in, err := i.sourceFs().Open(src)
if err != nil {
res = err
return
}
defer in.Close()
- out, err := i.spec.Fs.Destination.Create(target)
+ out, err := i.spec.BaseFs.PublishFs.Create(target)
if err != nil && os.IsNotExist(err) {
// When called from shortcodes, the target directory may not exist yet.
// See https://github.com/gohugoio/hugo/issues/4202
- if err = i.spec.Fs.Destination.MkdirAll(filepath.Dir(target), os.FileMode(0755)); err != nil {
+ if err = i.spec.BaseFs.PublishFs.MkdirAll(filepath.Dir(target), os.FileMode(0755)); err != nil {
res = err
return
}
- out, err = i.spec.Fs.Destination.Create(target)
+ out, err = i.spec.BaseFs.PublishFs.Create(target)
if err != nil {
res = err
return
@@ -491,20 +495,23 @@ func (i *Image) copyToDestination(src string) error {
}
})
- return res
+ if res != nil {
+ return fmt.Errorf("failed to copy image to destination: %s", res)
+ }
+ return nil
}
func (i *Image) encodeToDestinations(img image.Image, conf imageConfig, resourceCacheFilename, filename string) error {
- target := filepath.Join(i.absPublishDir, filename)
+ target := filepath.Clean(filename)
- file1, err := i.spec.Fs.Destination.Create(target)
+ file1, err := i.spec.BaseFs.PublishFs.Create(target)
if err != nil && os.IsNotExist(err) {
// When called from shortcodes, the target directory may not exist yet.
// See https://github.com/gohugoio/hugo/issues/4202
- if err = i.spec.Fs.Destination.MkdirAll(filepath.Dir(target), os.FileMode(0755)); err != nil {
+ if err = i.spec.BaseFs.PublishFs.MkdirAll(filepath.Dir(target), os.FileMode(0755)); err != nil {
return err
}
- file1, err = i.spec.Fs.Destination.Create(target)
+ file1, err = i.spec.BaseFs.PublishFs.Create(target)
if err != nil {
return err
}
@@ -518,11 +525,11 @@ func (i *Image) encodeToDestinations(img image.Image, conf imageConfig, resource
if resourceCacheFilename != "" {
// Also save it to the image resource cache for later reuse.
- if err = i.spec.Fs.Source.MkdirAll(filepath.Dir(resourceCacheFilename), os.FileMode(0755)); err != nil {
+ if err = i.spec.BaseFs.ResourcesFs.MkdirAll(filepath.Dir(resourceCacheFilename), os.FileMode(0755)); err != nil {
return err
}
- file2, err := i.spec.Fs.Source.Create(resourceCacheFilename)
+ file2, err := i.spec.BaseFs.ResourcesFs.Create(resourceCacheFilename)
if err != nil {
return err
}
diff --git a/resource/image_cache.go b/resource/image_cache.go
index e63989f24..5985797d6 100644
--- a/resource/image_cache.go
+++ b/resource/image_cache.go
@@ -24,10 +24,9 @@ import (
)
type imageCache struct {
- absPublishDir string
- absCacheDir string
- pathSpec *helpers.PathSpec
- mu sync.RWMutex
+ cacheDir string
+ pathSpec *helpers.PathSpec
+ mu sync.RWMutex
store map[string]*Image
}
@@ -82,14 +81,14 @@ func (c *imageCache) getOrCreate(
parent.createMu.Lock()
defer parent.createMu.Unlock()
- cacheFilename := filepath.Join(c.absCacheDir, key)
+ cacheFilename := filepath.Join(c.cacheDir, key)
// The definition of this counter is not that we have processed that amount
// (e.g. resized etc.), it can be fetched from file cache,
// but the count of processed image variations for this site.
c.pathSpec.ProcessingStats.Incr(&c.pathSpec.ProcessingStats.ProcessedImages)
- exists, err := helpers.Exists(cacheFilename, c.pathSpec.Fs.Source)
+ exists, err := helpers.Exists(cacheFilename, c.pathSpec.BaseFs.ResourcesFs)
if err != nil {
return nil, err
}
@@ -97,7 +96,9 @@ func (c *imageCache) getOrCreate(
if exists {
img = parent.clone()
img.relTargetPath.file = relTarget.file
- img.absSourceFilename = cacheFilename
+ img.sourceFilename = cacheFilename
+ // We have to look resources file system for this.
+ img.overriddenSourceFs = img.spec.BaseFs.ResourcesFs
} else {
img, err = create(cacheFilename)
if err != nil {
@@ -124,8 +125,8 @@ func (c *imageCache) getOrCreate(
}
-func newImageCache(ps *helpers.PathSpec, absCacheDir, absPublishDir string) *imageCache {
- return &imageCache{pathSpec: ps, store: make(map[string]*Image), absCacheDir: absCacheDir, absPublishDir: absPublishDir}
+func newImageCache(ps *helpers.PathSpec, cacheDir string) *imageCache {
+ return &imageCache{pathSpec: ps, store: make(map[string]*Image), cacheDir: cacheDir}
}
func timeTrack(start time.Time, name string) {
diff --git a/resource/image_test.go b/resource/image_test.go
index 0111d0850..39e538d33 100644
--- a/resource/image_test.go
+++ b/resource/image_test.go
@@ -16,6 +16,7 @@ package resource
import (
"fmt"
"math/rand"
+ "os"
"path/filepath"
"strconv"
"testing"
@@ -57,12 +58,14 @@ func TestParseImageConfig(t *testing.T) {
}
}
-func TestImageTransform(t *testing.T) {
+func TestImageTransformBasic(t *testing.T) {
assert := require.New(t)
image := fetchSunset(assert)
+ printFs(image.sourceFs(), "", os.Stdout)
+
assert.Equal("/a/sunset.jpg", image.RelPermalink())
assert.Equal("image", image.ResourceType())
@@ -75,19 +78,19 @@ func TestImageTransform(t *testing.T) {
assert.NoError(err)
assert.Equal(320, resized0x.Width())
assert.Equal(200, resized0x.Height())
- assertFileCache(assert, image.spec.Fs, resized0x.RelPermalink(), 320, 200)
+ assertFileCache(assert, image.spec.BaseFs.ResourcesFs, resized0x.RelPermalink(), 320, 200)
resizedx0, err := image.Resize("200x")
assert.NoError(err)
assert.Equal(200, resizedx0.Width())
assert.Equal(125, resizedx0.Height())
- assertFileCache(assert, image.spec.Fs, resizedx0.RelPermalink(), 200, 125)
+ assertFileCache(assert, image.spec.BaseFs.ResourcesFs, resizedx0.RelPermalink(), 200, 125)
resizedAndRotated, err := image.Resize("x200 r90")
assert.NoError(err)
assert.Equal(125, resizedAndRotated.Width())
assert.Equal(200, resizedAndRotated.Height())
- assertFileCache(assert, image.spec.Fs, resizedAndRotated.RelPermalink(), 125, 200)
+ assertFileCache(assert, image.spec.BaseFs.ResourcesFs, resizedAndRotated.RelPermalink(), 125, 200)
assert.Equal("/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_300x200_resize_q68_linear.jpg", resized.RelPermalink())
assert.Equal(300, resized.Width())
@@ -112,20 +115,20 @@ func TestImageTransform(t *testing.T) {
assert.Equal("/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_200x100_fill_q68_linear_bottomleft.jpg", filled.RelPermalink())
assert.Equal(200, filled.Width())
assert.Equal(100, filled.Height())
- assertFileCache(assert, image.spec.Fs, filled.RelPermalink(), 200, 100)
+ assertFileCache(assert, image.spec.BaseFs.ResourcesFs, filled.RelPermalink(), 200, 100)
smart, err := image.Fill("200x100 smart")
assert.NoError(err)
assert.Equal(fmt.Sprintf("/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_200x100_fill_q68_linear_smart%d.jpg", smartCropVersionNumber), smart.RelPermalink())
assert.Equal(200, smart.Width())
assert.Equal(100, smart.Height())
- assertFileCache(assert, image.spec.Fs, smart.RelPermalink(), 200, 100)
+ assertFileCache(assert, image.spec.BaseFs.ResourcesFs, smart.RelPermalink(), 200, 100)
// Check cache
filledAgain, err := image.Fill("200x100 bottomLeft")
assert.NoError(err)
assert.True(filled == filledAgain)
- assertFileCache(assert, image.spec.Fs, filledAgain.RelPermalink(), 200, 100)
+ assertFileCache(assert, image.spec.BaseFs.ResourcesFs, filledAgain.RelPermalink(), 200, 100)
}
@@ -295,10 +298,10 @@ func TestImageResizeInSubPath(t *testing.T) {
assert.Equal("/a/sub/gohugoio2_hu0e1b9e4a4be4d6f86c7b37b9ccce3fbc_73886_101x101_resize_linear_2.png", resized.RelPermalink())
assert.Equal(101, resized.Width())
- assertFileCache(assert, image.spec.Fs, resized.RelPermalink(), 101, 101)
- publishedImageFilename := filepath.Join("/public", resized.RelPermalink())
- assertImageFile(assert, image.spec.Fs, publishedImageFilename, 101, 101)
- assert.NoError(image.spec.Fs.Destination.Remove(publishedImageFilename))
+ assertFileCache(assert, image.spec.BaseFs.ResourcesFs, resized.RelPermalink(), 101, 101)
+ publishedImageFilename := filepath.Clean(resized.RelPermalink())
+ assertImageFile(assert, image.spec.BaseFs.PublishFs, publishedImageFilename, 101, 101)
+ assert.NoError(image.spec.BaseFs.PublishFs.Remove(publishedImageFilename))
// Cleare mem cache to simulate reading from the file cache.
resized.spec.imageCache.clear()
@@ -307,8 +310,8 @@ func TestImageResizeInSubPath(t *testing.T) {
assert.NoError(err)
assert.Equal("/a/sub/gohugoio2_hu0e1b9e4a4be4d6f86c7b37b9ccce3fbc_73886_101x101_resize_linear_2.png", resizedAgain.RelPermalink())
assert.Equal(101, resizedAgain.Width())
- assertFileCache(assert, image.spec.Fs, resizedAgain.RelPermalink(), 101, 101)
- assertImageFile(assert, image.spec.Fs, publishedImageFilename, 101, 101)
+ assertFileCache(assert, image.spec.BaseFs.ResourcesFs, resizedAgain.RelPermalink(), 101, 101)
+ assertImageFile(assert, image.spec.BaseFs.PublishFs, publishedImageFilename, 101, 101)
}
diff --git a/resource/resource.go b/resource/resource.go
index 2732f8b37..7fe3b4ff9 100644
--- a/resource/resource.go
+++ b/resource/resource.go
@@ -23,6 +23,8 @@ import (
"strings"
"sync"
+ "github.com/spf13/afero"
+
"github.com/spf13/cast"
"github.com/gobwas/glob"
@@ -214,6 +216,7 @@ func getGlob(pattern string) (glob.Glob, error) {
type Spec struct {
*helpers.PathSpec
+
mimeTypes media.Types
// Holds default filter settings etc.
@@ -221,7 +224,7 @@ type Spec struct {
imageCache *imageCache
- AbsGenImagePath string
+ GenImagePath string
}
func NewSpec(s *helpers.PathSpec, mimeTypes media.Types) (*Spec, error) {
@@ -232,41 +235,44 @@ func NewSpec(s *helpers.PathSpec, mimeTypes media.Types) (*Spec, error) {
}
s.GetLayoutDirPath()
- genImagePath := s.AbsPathify(filepath.Join(s.Cfg.GetString("resourceDir"), "_gen", "images"))
+ genImagePath := filepath.FromSlash("_gen/images")
- return &Spec{AbsGenImagePath: genImagePath, PathSpec: s, imaging: &imaging, mimeTypes: mimeTypes, imageCache: newImageCache(
- s,
- // We're going to write a cache pruning routine later, so make it extremely
- // unlikely that the user shoots him or herself in the foot
- // and this is set to a value that represents data he/she
- // cares about. This should be set in stone once released.
- genImagePath,
- s.AbsPathify(s.Cfg.GetString("publishDir")))}, nil
+ return &Spec{PathSpec: s,
+ GenImagePath: genImagePath,
+ imaging: &imaging, mimeTypes: mimeTypes, imageCache: newImageCache(
+ s,
+ // We're going to write a cache pruning routine later, so make it extremely
+ // unlikely that the user shoots him or herself in the foot
+ // and this is set to a value that represents data he/she
+ // cares about. This should be set in stone once released.
+ genImagePath,
+ )}, nil
}
func (r *Spec) NewResourceFromFile(
targetPathBuilder func(base string) string,
- absPublishDir string,
file source.File, relTargetFilename string) (Resource, error) {
- return r.newResource(targetPathBuilder, absPublishDir, file.Filename(), file.FileInfo(), relTargetFilename)
+ return r.newResource(targetPathBuilder, file.Filename(), file.FileInfo(), relTargetFilename)
}
func (r *Spec) NewResourceFromFilename(
targetPathBuilder func(base string) string,
- absPublishDir,
absSourceFilename, relTargetFilename string) (Resource, error) {
- fi, err := r.Fs.Source.Stat(absSourceFilename)
+ fi, err := r.sourceFs().Stat(absSourceFilename)
if err != nil {
return nil, err
}
- return r.newResource(targetPathBuilder, absPublishDir, absSourceFilename, fi, relTargetFilename)
+ return r.newResource(targetPathBuilder, absSourceFilename, fi, relTargetFilename)
+}
+
+func (r *Spec) sourceFs() afero.Fs {
+ return r.PathSpec.BaseFs.ContentFs
}
func (r *Spec) newResource(
targetPathBuilder func(base string) string,
- absPublishDir,
absSourceFilename string, fi os.FileInfo, relTargetFilename string) (Resource, error) {
var mimeType string
@@ -283,7 +289,7 @@ func (r *Spec) newResource(
}
}
- gr := r.newGenericResource(targetPathBuilder, fi, absPublishDir, absSourceFilename, relTargetFilename, mimeType)
+ gr := r.newGenericResource(targetPathBuilder, fi, absSourceFilename, relTargetFilename, mimeType)
if mimeType == "image" {
ext := strings.ToLower(helpers.Ext(absSourceFilename))
@@ -295,9 +301,9 @@ func (r *Spec) newResource(
return gr, nil
}
- f, err := r.Fs.Source.Open(absSourceFilename)
+ f, err := gr.sourceFs().Open(absSourceFilename)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("failed to open image source file: %s", err)
}
defer f.Close()
@@ -369,15 +375,30 @@ type genericResource struct {
params map[string]interface{}
// Absolute filename to the source, including any content folder path.
- absSourceFilename string
- absPublishDir string
- resourceType string
- osFileInfo os.FileInfo
+ // Note that this is absolute in relation to the filesystem it is stored in.
+ // It can be a base path filesystem, and then this filename will not match
+ // the path to the file on the real filesystem.
+ sourceFilename string
+
+ // This may be set to tell us to look in another filesystem for this resource.
+ // We, by default, use the sourceFs filesystem in the spec below.
+ overriddenSourceFs afero.Fs
+
+ spec *Spec
+
+ resourceType string
+ osFileInfo os.FileInfo
- spec *Spec
targetPathBuilder func(rel string) string
}
+func (l *genericResource) sourceFs() afero.Fs {
+ if l.overriddenSourceFs != nil {
+ return l.overriddenSourceFs
+ }
+ return l.spec.sourceFs()
+}
+
func (l *genericResource) Permalink() string {
return l.spec.PermalinkForBaseURL(l.relPermalinkForRel(l.relTargetPath.path(), false), l.spec.BaseURL.String())
}
@@ -455,19 +476,16 @@ func (l *genericResource) ResourceType() string {
}
func (l *genericResource) AbsSourceFilename() string {
- return l.absSourceFilename
+ return l.sourceFilename
}
func (l *genericResource) Publish() error {
- f, err := l.spec.Fs.Source.Open(l.AbsSourceFilename())
+ f, err := l.sourceFs().Open(l.AbsSourceFilename())
if err != nil {
return err
}
defer f.Close()
-
- target := filepath.Join(l.absPublishDir, l.target())
-
- return helpers.WriteToDisk(target, f, l.spec.Fs.Destination)
+ return helpers.WriteToDisk(l.target(), f, l.spec.BaseFs.PublishFs)
}
const counterPlaceHolder = ":counter"
@@ -574,8 +592,7 @@ func (l *genericResource) target() string {
func (r *Spec) newGenericResource(
targetPathBuilder func(base string) string,
osFileInfo os.FileInfo,
- absPublishDir,
- absSourceFilename,
+ sourceFilename,
baseFilename,
resourceType string) *genericResource {
@@ -587,8 +604,7 @@ func (r *Spec) newGenericResource(
return &genericResource{
targetPathBuilder: targetPathBuilder,
osFileInfo: osFileInfo,
- absPublishDir: absPublishDir,
- absSourceFilename: absSourceFilename,
+ sourceFilename: sourceFilename,
relTargetPath: dirFile{dir: fpath, file: fname},
resourceType: resourceType,
spec: r,
diff --git a/resource/resource_test.go b/resource/resource_test.go
index 396b40446..40061e5c4 100644
--- a/resource/resource_test.go
+++ b/resource/resource_test.go
@@ -29,7 +29,7 @@ func TestGenericResource(t *testing.T) {
assert := require.New(t)
spec := newTestResourceSpec(assert)
- r := spec.newGenericResource(nil, nil, "/public", "/a/foo.css", "foo.css", "css")
+ r := spec.newGenericResource(nil, nil, "/a/foo.css", "foo.css", "css")
assert.Equal("https://example.com/foo.css", r.Permalink())
assert.Equal("/foo.css", r.RelPermalink())
@@ -44,7 +44,7 @@ func TestGenericResourceWithLinkFacory(t *testing.T) {
factory := func(s string) string {
return path.Join("/foo", s)
}
- r := spec.newGenericResource(factory, nil, "/public", "/a/foo.css", "foo.css", "css")
+ r := spec.newGenericResource(factory, nil, "/a/foo.css", "foo.css", "css")
assert.Equal("https://example.com/foo/foo.css", r.Permalink())
assert.Equal("/foo/foo.css", r.RelPermalink())
@@ -55,11 +55,11 @@ func TestNewResourceFromFilename(t *testing.T) {
assert := require.New(t)
spec := newTestResourceSpec(assert)
- writeSource(t, spec.Fs, "/project/a/b/logo.png", "image")
- writeSource(t, spec.Fs, "/root/a/b/data.json", "json")
+ writeSource(t, spec.Fs, "content/a/b/logo.png", "image")
+ writeSource(t, spec.Fs, "content/a/b/data.json", "json")
- r, err := spec.NewResourceFromFilename(nil, "/public",
- filepath.FromSlash("/project/a/b/logo.png"), filepath.FromSlash("a/b/logo.png"))
+ r, err := spec.NewResourceFromFilename(nil,
+ filepath.FromSlash("a/b/logo.png"), filepath.FromSlash("a/b/logo.png"))
assert.NoError(err)
assert.NotNil(r)
@@ -67,7 +67,7 @@ func TestNewResourceFromFilename(t *testing.T) {
assert.Equal("/a/b/logo.png", r.RelPermalink())
assert.Equal("https://example.com/a/b/logo.png", r.Permalink())
- r, err = spec.NewResourceFromFilename(nil, "/public", "/root/a/b/data.json", "a/b/data.json")
+ r, err = spec.NewResourceFromFilename(nil, "a/b/data.json", "a/b/data.json")
assert.NoError(err)
assert.NotNil(r)
@@ -82,10 +82,10 @@ func TestNewResourceFromFilenameSubPathInBaseURL(t *testing.T) {
assert := require.New(t)
spec := newTestResourceSpecForBaseURL(assert, "https://example.com/docs")
- writeSource(t, spec.Fs, "/project/a/b/logo.png", "image")
+ writeSource(t, spec.Fs, "content/a/b/logo.png", "image")
- r, err := spec.NewResourceFromFilename(nil, "/public",
- filepath.FromSlash("/project/a/b/logo.png"), filepath.FromSlash("a/b/logo.png"))
+ r, err := spec.NewResourceFromFilename(nil,
+ filepath.FromSlash("a/b/logo.png"), filepath.FromSlash("a/b/logo.png"))
assert.NoError(err)
assert.NotNil(r)
@@ -101,10 +101,10 @@ func TestResourcesByType(t *testing.T) {
assert := require.New(t)
spec := newTestResourceSpec(assert)
resources := Resources{
- spec.newGenericResource(nil, nil, "/public", "/a/foo1.css", "foo1.css", "css"),
- spec.newGenericResource(nil, nil, "/public", "/a/logo.png", "logo.css", "image"),
- spec.newGenericResource(nil, nil, "/public", "/a/foo2.css", "foo2.css", "css"),
- spec.newGenericResource(nil, nil, "/public", "/a/foo3.css", "foo3.css", "css")}
+ spec.newGenericResource(nil, nil, "/a/foo1.css", "foo1.css", "css"),
+ spec.newGenericResource(nil, nil, "/a/logo.png", "logo.css", "image"),
+ spec.newGenericResource(nil, nil, "/a/foo2.css", "foo2.css", "css"),
+ spec.newGenericResource(nil, nil, "/a/foo3.css", "foo3.css", "css")}
assert.Len(resources.ByType("css"), 3)
assert.Len(resources.ByType("image"), 1)
@@ -115,11 +115,11 @@ func TestResourcesGetByPrefix(t *testing.T) {
assert := require.New(t)
spec := newTestResourceSpec(assert)
resources := Resources{
- spec.newGenericResource(nil, nil, "/public", "/a/foo1.css", "foo1.css", "css"),
- spec.newGenericResource(nil, nil, "/public", "/a/logo1.png", "logo1.png", "image"),
- spec.newGenericResource(nil, nil, "/public", "/b/Logo2.png", "Logo2.png", "image"),
- spec.newGenericResource(nil, nil, "/public", "/b/foo2.css", "foo2.css", "css"),
- spec.newGenericResource(nil, nil, "/public", "/b/foo3.css", "foo3.css", "css")}
+ spec.newGenericResource(nil, nil, "/a/foo1.css", "foo1.css", "css"),
+ spec.newGenericResource(nil, nil, "/a/logo1.png", "logo1.png", "image"),
+ spec.newGenericResource(nil, nil, "/b/Logo2.png", "Logo2.png", "image"),
+ spec.newGenericResource(nil, nil, "/b/foo2.css", "foo2.css", "css"),
+ spec.newGenericResource(nil, nil, "/b/foo3.css", "foo3.css", "css")}
assert.Nil(resources.GetByPrefix("asdf"))
assert.Equal("/logo1.png", resources.GetByPrefix("logo").RelPermalink())
@@ -144,14 +144,14 @@ func TestResourcesGetMatch(t *testing.T) {
assert := require.New(t)
spec := newTestResourceSpec(assert)
resources := Resources{
- spec.newGenericResource(nil, nil, "/public", "/a/foo1.css", "foo1.css", "css"),
- spec.newGenericResource(nil, nil, "/public", "/a/logo1.png", "logo1.png", "image"),
- spec.newGenericResource(nil, nil, "/public", "/b/Logo2.png", "Logo2.png", "image"),
- spec.newGenericResource(nil, nil, "/public", "/b/foo2.css", "foo2.css", "css"),
- spec.newGenericResource(nil, nil, "/public", "/b/foo3.css", "foo3.css", "css"),
- spec.newGenericResource(nil, nil, "/public", "/b/c/foo4.css", "c/foo4.css", "css"),
- spec.newGenericResource(nil, nil, "/public", "/b/c/foo5.css", "c/foo5.css", "css"),
- spec.newGenericResource(nil, nil, "/public", "/b/c/d/foo6.css", "c/d/foo6.css", "css"),
+ spec.newGenericResource(nil, nil, "/a/foo1.css", "foo1.css", "css"),
+ spec.newGenericResource(nil, nil, "/a/logo1.png", "logo1.png", "image"),
+ spec.newGenericResource(nil, nil, "/b/Logo2.png", "Logo2.png", "image"),
+ spec.newGenericResource(nil, nil, "/b/foo2.css", "foo2.css", "css"),
+ spec.newGenericResource(nil, nil, "/b/foo3.css", "foo3.css", "css"),
+ spec.newGenericResource(nil, nil, "/b/c/foo4.css", "c/foo4.css", "css"),
+ spec.newGenericResource(nil, nil, "/b/c/foo5.css", "c/foo5.css", "css"),
+ spec.newGenericResource(nil, nil, "/b/c/d/foo6.css", "c/d/foo6.css", "css"),
}
assert.Equal("/logo1.png", resources.GetMatch("logo*").RelPermalink())
@@ -373,12 +373,12 @@ func TestAssignMetadata(t *testing.T) {
}},
} {
- foo2 = spec.newGenericResource(nil, nil, "/public", "/b/foo2.css", "foo2.css", "css")
- logo2 = spec.newGenericResource(nil, nil, "/public", "/b/Logo2.png", "Logo2.png", "image")
- foo1 = spec.newGenericResource(nil, nil, "/public", "/a/foo1.css", "foo1.css", "css")
- logo1 = spec.newGenericResource(nil, nil, "/public", "/a/logo1.png", "logo1.png", "image")
- foo3 = spec.newGenericResource(nil, nil, "/public", "/b/foo3.css", "foo3.css", "css")
- logo3 = spec.newGenericResource(nil, nil, "/public", "/b/logo3.png", "logo3.png", "image")
+ foo2 = spec.newGenericResource(nil, nil, "/b/foo2.css", "foo2.css", "css")
+ logo2 = spec.newGenericResource(nil, nil, "/b/Logo2.png", "Logo2.png", "image")
+ foo1 = spec.newGenericResource(nil, nil, "/a/foo1.css", "foo1.css", "css")
+ logo1 = spec.newGenericResource(nil, nil, "/a/logo1.png", "logo1.png", "image")
+ foo3 = spec.newGenericResource(nil, nil, "/b/foo3.css", "foo3.css", "css")
+ logo3 = spec.newGenericResource(nil, nil, "/b/logo3.png", "logo3.png", "image")
resources = Resources{
foo2,
@@ -428,7 +428,7 @@ func BenchmarkResourcesMatchA100(b *testing.B) {
a100 := strings.Repeat("a", 100)
pattern := "a*a*a*a*a*a*a*a*b"
- resources := Resources{spec.newGenericResource(nil, nil, "/public", "/a/"+a100, a100, "css")}
+ resources := Resources{spec.newGenericResource(nil, nil, "/a/"+a100, a100, "css")}
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -444,17 +444,17 @@ func benchResources(b *testing.B) Resources {
for i := 0; i < 30; i++ {
name := fmt.Sprintf("abcde%d_%d.css", i%5, i)
- resources = append(resources, spec.newGenericResource(nil, nil, "/public", "/a/"+name, name, "css"))
+ resources = append(resources, spec.newGenericResource(nil, nil, "/a/"+name, name, "css"))
}
for i := 0; i < 30; i++ {
name := fmt.Sprintf("efghi%d_%d.css", i%5, i)
- resources = append(resources, spec.newGenericResource(nil, nil, "/public", "/a/"+name, name, "css"))
+ resources = append(resources, spec.newGenericResource(nil, nil, "/a/"+name, name, "css"))
}
for i := 0; i < 30; i++ {
name := fmt.Sprintf("jklmn%d_%d.css", i%5, i)
- resources = append(resources, spec.newGenericResource(nil, nil, "/public", "/b/sub/"+name, "sub/"+name, "css"))
+ resources = append(resources, spec.newGenericResource(nil, nil, "/b/sub/"+name, "sub/"+name, "css"))
}
return resources
@@ -482,7 +482,7 @@ func BenchmarkAssignMetadata(b *testing.B) {
}
for i := 0; i < 20; i++ {
name := fmt.Sprintf("foo%d_%d.css", i%5, i)
- resources = append(resources, spec.newGenericResource(nil, nil, "/public", "/a/"+name, name, "css"))
+ resources = append(resources, spec.newGenericResource(nil, nil, "/a/"+name, name, "css"))
}
b.StartTimer()
diff --git a/resource/testhelpers_test.go b/resource/testhelpers_test.go
index a9015ab2c..9b50633bd 100644
--- a/resource/testhelpers_test.go
+++ b/resource/testhelpers_test.go
@@ -4,6 +4,7 @@ import (
"path/filepath"
"testing"
+ "fmt"
"image"
"io"
"io/ioutil"
@@ -27,7 +28,8 @@ func newTestResourceSpec(assert *require.Assertions) *Spec {
func newTestResourceSpecForBaseURL(assert *require.Assertions, baseURL string) *Spec {
cfg := viper.New()
cfg.Set("baseURL", baseURL)
- cfg.Set("resourceDir", "/res")
+ cfg.Set("resourceDir", "resources")
+ cfg.Set("contentDir", "content")
imagingCfg := map[string]interface{}{
"resampleFilter": "linear",
@@ -60,9 +62,8 @@ func newTestResourceOsFs(assert *require.Assertions) *Spec {
workDir = "/private" + workDir
}
- contentDir := "base"
cfg.Set("workingDir", workDir)
- cfg.Set("contentDir", contentDir)
+ cfg.Set("contentDir", filepath.Join(workDir, "content"))
cfg.Set("resourceDir", filepath.Join(workDir, "res"))
fs := hugofs.NewFrom(hugofs.Os, cfg)
@@ -97,10 +98,8 @@ func fetchResourceForSpec(spec *Spec, assert *require.Assertions, name string) R
src, err := os.Open(filepath.FromSlash("testdata/" + name))
assert.NoError(err)
- workingDir := spec.Cfg.GetString("workingDir")
- f := filepath.Join(workingDir, name)
-
- out, err := spec.Fs.Source.Create(f)
+ assert.NoError(spec.BaseFs.ContentFs.MkdirAll(filepath.Dir(name), 0755))
+ out, err := spec.BaseFs.ContentFs.Create(name)
assert.NoError(err)
_, err = io.Copy(out, src)
out.Close()
@@ -111,14 +110,17 @@ func fetchResourceForSpec(spec *Spec, assert *require.Assertions, name string) R
return path.Join("/a", s)
}
- r, err := spec.NewResourceFromFilename(factory, "/public", f, name)
+ r, err := spec.NewResourceFromFilename(factory, name, name)
assert.NoError(err)
return r
}
-func assertImageFile(assert *require.Assertions, fs *hugofs.Fs, filename string, width, height int) {
- f, err := fs.Source.Open(filename)
+func assertImageFile(assert *require.Assertions, fs afero.Fs, filename string, width, height int) {
+ f, err := fs.Open(filename)
+ if err != nil {
+ printFs(fs, "", os.Stdout)
+ }
assert.NoError(err)
defer f.Close()
@@ -129,8 +131,8 @@ func assertImageFile(assert *require.Assertions, fs *hugofs.Fs, filename string,
assert.Equal(height, config.Height)
}
-func assertFileCache(assert *require.Assertions, fs *hugofs.Fs, filename string, width, height int) {
- assertImageFile(assert, fs, filepath.Join("/res/_gen/images", filename), width, height)
+func assertFileCache(assert *require.Assertions, fs afero.Fs, filename string, width, height int) {
+ assertImageFile(assert, fs, filepath.Join("_gen/images", filename), width, height)
}
func writeSource(t testing.TB, fs *hugofs.Fs, filename, content string) {
@@ -142,3 +144,22 @@ func writeToFs(t testing.TB, fs afero.Fs, filename, content string) {
t.Fatalf("Failed to write file: %s", err)
}
}
+
+func printFs(fs afero.Fs, path string, w io.Writer) {
+ if fs == nil {
+ return
+ }
+ afero.Walk(fs, path, func(path string, info os.FileInfo, err error) error {
+ if info != nil && !info.IsDir() {
+ s := path
+ if lang, ok := info.(hugofs.LanguageAnnouncer); ok {
+ s = s + "\t" + lang.Lang()
+ }
+ if fp, ok := info.(hugofs.FilePather); ok {
+ s += "\tFilename: " + fp.Filename() + "\tBase: " + fp.BaseDir()
+ }
+ fmt.Fprintln(w, " ", s)
+ }
+ return nil
+ })
+}