summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--commands/hugo.go4
-rw-r--r--commands/new.go2
-rw-r--r--common/hugo/hugo.go2
-rw-r--r--create/content.go14
-rw-r--r--helpers/general.go2
-rw-r--r--hugofs/decorators.go12
-rw-r--r--hugofs/fileinfo.go277
-rw-r--r--hugofs/fileinfo_test.go51
-rw-r--r--hugofs/filter_fs.go32
-rw-r--r--hugofs/glob_test.go2
-rw-r--r--hugofs/language_composite_fs.go2
-rw-r--r--hugofs/nosymlink_fs.go2
-rw-r--r--hugofs/rootmapping_fs.go34
-rw-r--r--hugofs/rootmapping_fs_test.go36
-rw-r--r--hugofs/slice_fs.go8
-rw-r--r--hugofs/walk.go28
-rw-r--r--hugofs/walk_test.go98
-rw-r--r--hugolib/content_map.go30
-rw-r--r--hugolib/content_map_page.go6
-rw-r--r--hugolib/content_map_test.go16
-rw-r--r--hugolib/filesystems/basefs.go41
-rw-r--r--hugolib/hugo_modules_test.go4
-rw-r--r--hugolib/hugo_sites.go10
-rw-r--r--hugolib/hugo_sites_build.go2
-rw-r--r--hugolib/page.go2
-rw-r--r--hugolib/page__meta.go2
-rw-r--r--hugolib/pagebundler_test.go3
-rw-r--r--hugolib/pagecollections.go8
-rw-r--r--hugolib/pages_capture.go53
-rw-r--r--hugolib/pages_process.go8
-rw-r--r--langs/i18n/translationProvider.go2
-rw-r--r--modules/npm/package_builder.go8
-rw-r--r--resources/image.go4
-rw-r--r--resources/image_cache.go2
-rw-r--r--resources/resource_factories/create/create.go2
-rw-r--r--resources/resource_transformers/js/build.go4
-rw-r--r--resources/resource_transformers/js/options.go10
-rw-r--r--resources/resource_transformers/postcss/postcss.go2
-rw-r--r--resources/resource_transformers/tocss/dartsass/transform.go4
-rw-r--r--resources/resource_transformers/tocss/scss/tocss.go4
-rw-r--r--source/fileInfo.go22
-rw-r--r--source/filesystem.go4
-rw-r--r--source/filesystem_test.go2
-rw-r--r--tpl/tplimpl/template.go2
44 files changed, 423 insertions, 440 deletions
diff --git a/commands/hugo.go b/commands/hugo.go
index 0f6e4274a..2b53d5cd6 100644
--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -697,7 +697,7 @@ func (c *commandeer) getDirList() ([]string, error) {
return filepath.SkipDir
}
- filenames = append(filenames, fi.Meta().Filename())
+ filenames = append(filenames, fi.Meta().Filename)
}
return nil
@@ -706,7 +706,7 @@ func (c *commandeer) getDirList() ([]string, error) {
watchFiles := c.hugo().PathSpec.BaseFs.WatchDirs()
for _, fi := range watchFiles {
if !fi.IsDir() {
- filenames = append(filenames, fi.Meta().Filename())
+ filenames = append(filenames, fi.Meta().Filename)
continue
}
diff --git a/commands/new.go b/commands/new.go
index a2d873717..44e2a7e40 100644
--- a/commands/new.go
+++ b/commands/new.go
@@ -118,7 +118,7 @@ func newContentPathSection(h *hugolib.HugoSites, path string) (string, string) {
if h != nil {
for _, dir := range h.BaseFs.Content.Dirs {
- createpath = strings.TrimPrefix(createpath, dir.Meta().Filename())
+ createpath = strings.TrimPrefix(createpath, dir.Meta().Filename)
}
}
diff --git a/common/hugo/hugo.go b/common/hugo/hugo.go
index bf3dee26e..4548de93a 100644
--- a/common/hugo/hugo.go
+++ b/common/hugo/hugo.go
@@ -102,7 +102,7 @@ func GetExecEnviron(workDir string, cfg config.Provider, fs afero.Fs) []string {
if err == nil {
for _, fi := range fis {
key := fmt.Sprintf("HUGO_FILE_%s", strings.ReplaceAll(strings.ToUpper(fi.Name()), ".", "_"))
- value := fi.(hugofs.FileMetaInfo).Meta().Filename()
+ value := fi.(hugofs.FileMetaInfo).Meta().Filename
config.SetEnvVars(&env, key, value)
}
}
diff --git a/create/content.go b/create/content.go
index 797ffe758..ea065423e 100644
--- a/create/content.go
+++ b/create/content.go
@@ -123,7 +123,7 @@ func NewContent(
func targetSite(sites *hugolib.HugoSites, fi hugofs.FileMetaInfo) *hugolib.Site {
for _, s := range sites.Sites {
- if fi.Meta().Lang() == s.Language().Lang {
+ if fi.Meta().Lang == s.Language().Lang {
return s
}
}
@@ -137,7 +137,7 @@ func newContentFromDir(
cm archetypeMap, name, targetPath string) error {
for _, f := range cm.otherFiles {
meta := f.Meta()
- filename := meta.Path()
+ filename := meta.Path
// Just copy the file to destination.
in, err := meta.Open()
if err != nil {
@@ -166,7 +166,7 @@ func newContentFromDir(
}
for _, f := range cm.contentFiles {
- filename := f.Meta().Path()
+ filename := f.Meta().Path
s := targetSite(sites, f)
targetFilename := filepath.Join(targetPath, strings.TrimPrefix(filename, archetypeDir))
@@ -274,7 +274,7 @@ func resolveContentPath(sites *hugolib.HugoSites, fs afero.Fs, targetPath string
for _, dir := range sites.BaseFs.Content.Dirs {
meta := dir.Meta()
- contentDir := meta.Filename()
+ contentDir := meta.Filename
if !strings.HasSuffix(contentDir, helpers.FilePathSeparator) {
contentDir += helpers.FilePathSeparator
@@ -282,7 +282,7 @@ func resolveContentPath(sites *hugolib.HugoSites, fs afero.Fs, targetPath string
if strings.HasPrefix(targetPath, contentDir) {
siteContentDir = contentDir
- dirLang = meta.Lang()
+ dirLang = meta.Lang
break
}
}
@@ -317,8 +317,8 @@ func resolveContentPath(sites *hugolib.HugoSites, fs afero.Fs, targetPath string
} else {
var contentDir string
for _, dir := range sites.BaseFs.Content.Dirs {
- contentDir = dir.Meta().Filename()
- if dir.Meta().Lang() == s.Lang() {
+ contentDir = dir.Meta().Filename
+ if dir.Meta().Lang == s.Lang() {
break
}
}
diff --git a/helpers/general.go b/helpers/general.go
index c5af83b66..25decbbc1 100644
--- a/helpers/general.go
+++ b/helpers/general.go
@@ -497,7 +497,7 @@ func PrintFs(fs afero.Fs, path string, w io.Writer) {
var filename string
var meta interface{}
if fim, ok := info.(hugofs.FileMetaInfo); ok {
- filename = fim.Meta().Filename()
+ filename = fim.Meta().Filename
meta = fim.Meta()
}
fmt.Fprintf(w, " %q %q\t\t%v\n", path, filename, meta)
diff --git a/hugofs/decorators.go b/hugofs/decorators.go
index 62d234944..364a3e23e 100644
--- a/hugofs/decorators.go
+++ b/hugofs/decorators.go
@@ -23,7 +23,7 @@ import (
"github.com/spf13/afero"
)
-func decorateDirs(fs afero.Fs, meta FileMeta) afero.Fs {
+func decorateDirs(fs afero.Fs, meta *FileMeta) afero.Fs {
ffs := &baseFileDecoratorFs{Fs: fs}
decorator := func(fi os.FileInfo, name string) (os.FileInfo, error) {
@@ -82,9 +82,11 @@ func NewBaseFileDecorator(fs afero.Fs, callbacks ...func(fi FileMetaInfo)) afero
decorator := func(fi os.FileInfo, filename string) (os.FileInfo, error) {
// Store away the original in case it's a symlink.
- meta := FileMeta{metaKeyName: fi.Name()}
+ meta := NewFileMeta()
+ meta.Name = fi.Name()
+
if fi.IsDir() {
- meta[metaKeyJoinStat] = func(name string) (FileMetaInfo, error) {
+ meta.JoinStatFunc = func(name string) (FileMetaInfo, error) {
joinedFilename := filepath.Join(filename, name)
fi, _, err := lstatIfPossible(fs, joinedFilename)
if err != nil {
@@ -102,7 +104,7 @@ func NewBaseFileDecorator(fs afero.Fs, callbacks ...func(fi FileMetaInfo)) afero
isSymlink := isSymlink(fi)
if isSymlink {
- meta[metaKeyOriginalFilename] = filename
+ meta.OriginalFilename = filename
var link string
var err error
link, fi, err = evalSymlinks(fs, filename)
@@ -110,7 +112,7 @@ func NewBaseFileDecorator(fs afero.Fs, callbacks ...func(fi FileMetaInfo)) afero
return nil, err
}
filename = link
- meta[metaKeyIsSymlink] = true
+ meta.IsSymlink = true
}
opener := func() (afero.File, error) {
diff --git a/hugofs/fileinfo.go b/hugofs/fileinfo.go
index 4f318205a..fcf35d956 100644
--- a/hugofs/fileinfo.go
+++ b/hugofs/fileinfo.go
@@ -17,6 +17,7 @@ package hugofs
import (
"os"
"path/filepath"
+ "reflect"
"runtime"
"sort"
"strings"
@@ -27,242 +28,128 @@ import (
"github.com/pkg/errors"
- "github.com/spf13/cast"
-
"github.com/gohugoio/hugo/common/hreflect"
"github.com/spf13/afero"
)
-const (
- metaKeyFilename = "filename"
-
- metaKeySourceRoot = "sourceRoot"
- metaKeyBaseDir = "baseDir" // Abs base directory of source file.
- metaKeyMountRoot = "mountRoot"
- metaKeyModule = "module"
- metaKeyOriginalFilename = "originalFilename"
- metaKeyName = "name"
- metaKeyPath = "path"
- metaKeyPathWalk = "pathWalk"
- metaKeyLang = "lang"
- metaKeyWeight = "weight"
- metaKeyOrdinal = "ordinal"
- metaKeyFs = "fs"
- metaKeyOpener = "opener"
- metaKeyIsOrdered = "isOrdered"
- metaKeyIsSymlink = "isSymlink"
- metaKeyJoinStat = "joinStat"
- metaKeySkipDir = "skipDir"
- metaKeyClassifier = "classifier"
- metaKeyTranslationBaseName = "translationBaseName"
- metaKeyTranslationBaseNameWithExt = "translationBaseNameWithExt"
- metaKeyTranslations = "translations"
- metaKeyDecoraterPath = "decoratorPath"
-)
-
-type FileMeta map[string]interface{}
-
-func (f FileMeta) GetInt(key string) int {
- return cast.ToInt(f[key])
-}
-
-func (f FileMeta) GetString(key string) string {
- return cast.ToString(f[key])
-}
-
-func (f FileMeta) GetBool(key string) bool {
- return cast.ToBool(f[key])
-}
-
-func (f FileMeta) Filename() string {
- return f.stringV(metaKeyFilename)
-}
-
-func (f FileMeta) OriginalFilename() string {
- return f.stringV(metaKeyOriginalFilename)
-}
-
-func (f FileMeta) SkipDir() bool {
- return f.GetBool(metaKeySkipDir)
-}
-
-func (f FileMeta) TranslationBaseName() string {
- return f.stringV(metaKeyTranslationBaseName)
-}
-
-func (f FileMeta) TranslationBaseNameWithExt() string {
- return f.stringV(metaKeyTranslationBaseNameWithExt)
-}
-
-func (f FileMeta) Translations() []string {
- return cast.ToStringSlice(f[metaKeyTranslations])
-}
-
-func (f FileMeta) Name() string {
- return f.stringV(metaKeyName)
-}
-
-func (f FileMeta) Classifier() files.ContentClass {
- c, found := f[metaKeyClassifier]
- if found {
- return c.(files.ContentClass)
- }
-
- return files.ContentClassFile // For sorting
-}
-
-func (f FileMeta) Lang() string {
- return f.stringV(metaKeyLang)
-}
-
-// Path returns the relative file path to where this file is mounted.
-func (f FileMeta) Path() string {
- return f.stringV(metaKeyPath)
+func NewFileMeta() *FileMeta {
+ return &FileMeta{}
}
// PathFile returns the relative file path for the file source.
-func (f FileMeta) PathFile() string {
- base := f.stringV(metaKeyBaseDir)
- if base == "" {
+func (f *FileMeta) PathFile() string {
+ if f.BaseDir == "" {
return ""
}
- return strings.TrimPrefix(strings.TrimPrefix(f.Filename(), base), filepathSeparator)
+ return strings.TrimPrefix(strings.TrimPrefix(f.Filename, f.BaseDir), filepathSeparator)
}
-func (f FileMeta) SourceRoot() string {
- return f.stringV(metaKeySourceRoot)
-}
+type FileMeta struct {
+ Name string
+ Filename string
+ Path string
+ PathWalk string
+ OriginalFilename string
+ BaseDir string
-func (f FileMeta) MountRoot() string {
- return f.stringV(metaKeyMountRoot)
-}
+ SourceRoot string
+ MountRoot string
+ Module string
-func (f FileMeta) Module() string {
- return f.stringV(metaKeyModule)
-}
+ Weight int
+ Ordinal int
+ IsOrdered bool
+ IsSymlink bool
+ IsRootFile bool
+ Watch bool
-func (f FileMeta) Weight() int {
- return f.GetInt(metaKeyWeight)
-}
+ Classifier files.ContentClass
-func (f FileMeta) Ordinal() int {
- return f.GetInt(metaKeyOrdinal)
-}
+ SkipDir bool
-func (f FileMeta) IsOrdered() bool {
- return f.GetBool(metaKeyIsOrdered)
-}
+ Lang string
+ TranslationBaseName string
+ TranslationBaseNameWithExt string
+ Translations []string
-// IsSymlink returns whether this comes from a symlinked file or directory.
-func (f FileMeta) IsSymlink() bool {
- return f.GetBool(metaKeyIsSymlink)
+ Fs afero.Fs
+ OpenFunc func() (afero.File, error)
+ JoinStatFunc func(name string) (FileMetaInfo, error)
}
-func (f FileMeta) Watch() bool {
- if v, found := f["watch"]; found {
- return v.(bool)
+func (m *FileMeta) Copy() *FileMeta {
+ if m == nil {
+ return NewFileMeta()
}
- return false
+ c := *m
+ return &c
}
-func (f FileMeta) Fs() afero.Fs {
- if v, found := f[metaKeyFs]; found {
- return v.(afero.Fs)
+func (m *FileMeta) Merge(from *FileMeta) {
+ if m == nil || from == nil {
+ return
}
- return nil
-}
+ dstv := reflect.Indirect(reflect.ValueOf(m))
+ srcv := reflect.Indirect(reflect.ValueOf(from))
-func (f FileMeta) GetOpener() func() (afero.File, error) {
- o, found := f[metaKeyOpener]
- if !found {
- return nil
+ for i := 0; i < dstv.NumField(); i++ {
+ v := dstv.Field(i)
+ if !hreflect.IsTruthfulValue(v) {
+ v.Set(srcv.Field(i))
+ }
}
- return o.(func() (afero.File, error))
}
-func (f FileMeta) Open() (afero.File, error) {
- v, found := f[metaKeyOpener]
- if !found {
- return nil, errors.New("file opener not found")
+func (f *FileMeta) Open() (afero.File, error) {
+ if f.OpenFunc == nil {
+ return nil, errors.New("OpenFunc not set")
}
- return v.(func() (afero.File, error))()
+ return f.OpenFunc()
}
-func (f FileMeta) JoinStat(name string) (FileMetaInfo, error) {
- v, found := f[metaKeyJoinStat]
- if !found {
+func (f *FileMeta) JoinStat(name string) (FileMetaInfo, error) {
+ if f.JoinStatFunc == nil {
return nil, os.ErrNotExist
}
- return v.(func(name string) (FileMetaInfo, error))(name)
-}
-
-func (f FileMeta) stringV(key string) string {
- if v, found := f[key]; found {
- return v.(string)
- }
- return ""
-}
-
-func (f FileMeta) setIfNotZero(key string, val interface{}) {
- if !hreflect.IsTruthful(val) {
- return
- }
- f[key] = val
+ return f.JoinStatFunc(name)
}
type FileMetaInfo interface {
os.FileInfo
- Meta() FileMeta
+ Meta() *FileMeta
}
type fileInfoMeta struct {
os.FileInfo
- m FileMeta
+ m *FileMeta
}
// Name returns the file's name. Note that we follow symlinks,
// if supported by the file system, and the Name given here will be the
// name of the symlink, which is what Hugo needs in all situations.
func (fi *fileInfoMeta) Name() string {
- if name := fi.m.Name(); name != "" {
+ if name := fi.m.Name; name != "" {
return name
}
return fi.FileInfo.Name()
}
-func (fi *fileInfoMeta) Meta() FileMeta {
+func (fi *fileInfoMeta) Meta() *FileMeta {
return fi.m
}
-func NewFileMetaInfo(fi os.FileInfo, m FileMeta) FileMetaInfo {
+func NewFileMetaInfo(fi os.FileInfo, m *FileMeta) FileMetaInfo {
+ if m == nil {
+ panic("FileMeta must be set")
+ }
if fim, ok := fi.(FileMetaInfo); ok {
- mergeFileMeta(fim.Meta(), m)
+ m.Merge(fim.Meta())
}
return &fileInfoMeta{FileInfo: fi, m: m}
}
-func copyFileMeta(m FileMeta) FileMeta {
- c := make(FileMeta)
- for k, v := range m {
- c[k] = v
- }
- return c
-}
-
-// Merge metadata, last entry wins.
-func mergeFileMeta(from, to FileMeta) {
- if from == nil {
- return
- }
- for k, v := range from {
- if _, found := to[k]; !found {
- to[k] = v
- }
- }
-}
-
type dirNameOnlyFileInfo struct {
name string
modTime time.Time
@@ -292,16 +179,16 @@ func (fi *dirNameOnlyFileInfo) Sys() interface{} {
return nil
}
-func newDirNameOnlyFileInfo(name string, meta FileMeta, fileOpener func() (afero.File, error)) FileMetaInfo {
+func newDirNameOnlyFileInfo(name string, meta *FileMeta, fileOpener func() (afero.File, error)) FileMetaInfo {
name = normalizeFilename(name)
_, base := filepath.Split(name)
- m := copyFileMeta(meta)
- if _, found := m[metaKeyFilename]; !found {
- m.setIfNotZero(metaKeyFilename, name)
+ m := meta.Copy()
+ if m.Filename == "" {
+ m.Filename = name
}
- m[metaKeyOpener] = fileOpener
- m[metaKeyIsOrdered] = false
+ m.OpenFunc = fileOpener
+ m.IsOrdered = false
return NewFileMetaInfo(
&dirNameOnlyFileInfo{name: base, modTime: time.Now()},
@@ -312,8 +199,8 @@ func newDirNameOnlyFileInfo(name string, meta FileMeta, fileOpener func() (afero
func decorateFileInfo(
fi os.FileInfo,
fs afero.Fs, opener func() (afero.File, error),
- filename, filepath string, inMeta FileMeta) FileMetaInfo {
- var meta FileMeta
+ filename, filepath string, inMeta *FileMeta) FileMetaInfo {
+ var meta *FileMeta
var fim FileMetaInfo
filepath = strings.TrimPrefix(filepath, filepathSeparator)
@@ -322,16 +209,26 @@ func decorateFileInfo(
if fim, ok = fi.(FileMetaInfo); ok {
meta = fim.Meta()
} else {
- meta = make(FileMeta)
+ meta = NewFileMeta()
fim = NewFileMetaInfo(fi, meta)
}
- meta.setIfNotZero(metaKeyOpener, opener)
- meta.setIfNotZero(metaKeyFs, fs)
- meta.setIfNotZero(metaKeyPath, normalizeFilename(filepath))
- meta.setIfNotZero(metaKeyFilename, normalizeFilename(filename))
+ if opener != nil {
+ meta.OpenFunc = opener
+ }
+ if fs != nil {
+ meta.Fs = fs
+ }
+ nfilepath := normalizeFilename(filepath)
+ nfilename := normalizeFilename(filename)
+ if nfilepath != "" {
+ meta.Path = nfilepath
+ }
+ if nfilename != "" {
+ meta.Filename = nfilename
+ }
- mergeFileMeta(inMeta, meta)
+ meta.Merge(inMeta)
return fim
}
@@ -377,6 +274,6 @@ func fromSlash(filenames []string) []string {
func sortFileInfos(fis []os.FileInfo) {
sort.Slice(fis, func(i, j int) bool {
fimi, fimj := fis[i].(FileMetaInfo), fis[j].(FileMetaInfo)
- return fimi.Meta().Filename() < fimj.Meta().Filename()
+ return fimi.Meta().Filename < fimj.Meta().Filename
})
}
diff --git a/hugofs/fileinfo_test.go b/hugofs/fileinfo_test.go
new file mode 100644
index 000000000..8d6a2ff7a
--- /dev/null
+++ b/hugofs/fileinfo_test.go
@@ -0,0 +1,51 @@
+// Copyright 2021 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 hugofs
+
+import (
+ "testing"
+
+ qt "github.com/frankban/quicktest"
+)
+
+func TestFileMeta(t *testing.T) {
+ c := qt.New(t)
+
+ c.Run("Merge", func(c *qt.C) {
+ src := &FileMeta{
+ Filename: "fs1",
+ Path: "ps1",
+ }
+ dst := &FileMeta{
+ Filename: "fd1",
+ }
+
+ dst.Merge(src)
+
+ c.Assert(dst.Path, qt.Equals, "ps1")
+ c.Assert(dst.Filename, qt.Equals, "fd1")
+ })
+
+ c.Run("Copy", func(c *qt.C) {
+ src := &FileMeta{
+ Filename: "fs1",
+ Path: "ps1",
+ }
+ dst := src.Copy()
+
+ c.Assert(dst, qt.Not(qt.Equals), src)
+ c.Assert(dst, qt.DeepEquals, src)
+ })
+
+}