Skip to content

Commit

Permalink
Simplify the content map key structure to ease finding stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
bep committed May 4, 2021
1 parent b660ea8 commit 499d032
Show file tree
Hide file tree
Showing 34 changed files with 2,914 additions and 1,395 deletions.
1 change: 1 addition & 0 deletions common/herrors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ type ErrorSender interface {
// Recover is a helper function that can be used to capture panics.
// Put this at the top of a method/function that crashes in a template:
// defer herrors.Recover()
// TODO1 check usage
func Recover(args ...interface{}) {
if r := recover(); r != nil {
fmt.Println("ERR:", r)
Expand Down
15 changes: 15 additions & 0 deletions helpers/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -662,3 +662,18 @@ func AddTrailingSlash(path string) string {
}
return path
}

// AddLeadingSlash adds a leading Unix styled slash (/) if not already
// there.
func AddLeadingSlash(path string) string {
if !strings.HasPrefix(path, "/") {
path = "/" + path
}
return path
}

// AddLeadingAndTrailingSlash adds a leading and trailing Unix styled slash (/)
// if not already there.
func AddLeadingAndTrailingSlash(path string) string {
return AddTrailingSlash(AddLeadingSlash(path))
}
17 changes: 15 additions & 2 deletions hugofs/filter_fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,19 @@ func NewLanguageFs(langs map[string]int, fs afero.Fs) (afero.Fs, error) {
}
}

return &FilterFs{
ffs := &FilterFs{
fs: fs,
applyPerSource: applyMeta,
applyAll: all,
}, nil
}

if rfs, ok := fs.(ReverseLookupProvider); ok {
// Preserve that interface.
return NewExtendedFs(ffs, rfs), nil
}

return ffs, nil

}

func NewFilterFs(fs afero.Fs) (afero.Fs, error) {
Expand All @@ -118,6 +126,11 @@ func NewFilterFs(fs afero.Fs) (afero.Fs, error) {
applyPerSource: applyMeta,
}

if rfs, ok := fs.(ReverseLookupProvider); ok {
// Preserve that interface.
return NewExtendedFs(ffs, rfs), nil
}

return ffs, nil
}

Expand Down
20 changes: 18 additions & 2 deletions hugofs/language_composite_fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,21 @@ var (
)

type languageCompositeFs struct {
base ExtendedFs
overlay ExtendedFs
*afero.CopyOnWriteFs
}

// NewLanguageCompositeFs creates a composite and language aware filesystem.
// This is a hybrid filesystem. To get a specific file in Open, Stat etc., use the full filename
// to the target filesystem. This information is available in Readdir, Stat etc. via the
// special LanguageFileInfo FileInfo implementation.
func NewLanguageCompositeFs(base, overlay afero.Fs) afero.Fs {
return &languageCompositeFs{afero.NewCopyOnWriteFs(base, overlay).(*afero.CopyOnWriteFs)}
func NewLanguageCompositeFs(base, overlay ExtendedFs) ExtendedFs {
return &languageCompositeFs{
base: base,
overlay: overlay,
CopyOnWriteFs: afero.NewCopyOnWriteFs(base, overlay).(*afero.CopyOnWriteFs),
}
}

// Open takes the full path to the file in the target filesystem. If it is a directory, it gets merged
Expand All @@ -53,6 +59,16 @@ func (fs *languageCompositeFs) Open(name string) (afero.File, error) {
return f, nil
}

func (fs *languageCompositeFs) ReverseLookup(name string) (string, error) {
// Try the overlay first.
s, err := fs.overlay.ReverseLookup(name)
if s != "" || err != nil {
return s, err
}

return fs.base.ReverseLookup(name)
}

// LanguageDirsMerger implements the afero.DirsMerger interface, which is used
// to merge two directories.
var LanguageDirsMerger = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error) {
Expand Down
71 changes: 61 additions & 10 deletions hugofs/rootmapping_fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,48 @@ import (
"github.com/spf13/afero"
)

var _ ReverseLookupProvider = (*RootMappingFs)(nil)

type ExtendedFs interface {
afero.Fs
ReverseLookupProvider
}

func NewExtendedFs(fs afero.Fs, rl ReverseLookupProvider) ExtendedFs {
return struct {
afero.Fs
ReverseLookupProvider
}{
fs,
rl,
}
}

type ReverseLookupProvider interface {
ReverseLookup(name string) (string, error)
}

var filepathSeparator = string(filepath.Separator)

// NewRootMappingFs creates a new RootMappingFs on top of the provided with
// root mappings with some optional metadata about the root.
// Note that From represents a virtual root that maps to the actual filename in To.
func NewRootMappingFs(fs afero.Fs, rms ...RootMapping) (*RootMappingFs, error) {
rootMapToReal := radix.New()
realMapToRoot := radix.New()
var virtualRoots []RootMapping

addMapping := func(key string, rm RootMapping, to *radix.Tree) {
var mappings []RootMapping
v, found := to.Get(key)
if found {
// There may be more than one language pointing to the same root.
mappings = v.([]RootMapping)
}
mappings = append(mappings, rm)
to.Insert(key, mappings)
}

for _, rm := range rms {
(&rm).clean()

Expand Down Expand Up @@ -72,15 +105,8 @@ func NewRootMappingFs(fs afero.Fs, rms ...RootMapping) (*RootMappingFs, error) {

rm.fi = NewFileMetaInfo(fi, meta)

key := filepathSeparator + rm.From
var mappings []RootMapping
v, found := rootMapToReal.Get(key)
if found {
// There may be more than one language pointing to the same root.
mappings = v.([]RootMapping)
}
mappings = append(mappings, rm)
rootMapToReal.Insert(key, mappings)
addMapping(filepathSeparator+rm.From, rm, rootMapToReal)
addMapping(strings.TrimPrefix(rm.To, rm.ToBasedir), rm, realMapToRoot)

virtualRoots = append(virtualRoots, rm)
}
Expand All @@ -90,6 +116,7 @@ func NewRootMappingFs(fs afero.Fs, rms ...RootMapping) (*RootMappingFs, error) {
rfs := &RootMappingFs{
Fs: fs,
rootMapToReal: rootMapToReal,
realMapToRoot: realMapToRoot,
}

return rfs, nil
Expand Down Expand Up @@ -148,6 +175,7 @@ func (r RootMapping) filename(name string) string {
type RootMappingFs struct {
afero.Fs
rootMapToReal *radix.Tree
realMapToRoot *radix.Tree
}

func (fs *RootMappingFs) Dirs(base string) ([]FileMetaInfo, error) {
Expand Down Expand Up @@ -234,6 +262,21 @@ func (fs *RootMappingFs) Stat(name string) (os.FileInfo, error) {
return fi, err
}

func (fs *RootMappingFs) ReverseLookup(name string) (string, error) {
name = fs.cleanName(name)
key := filepathSeparator + name
s, roots := fs.getRootsReverse(key)

if roots == nil {
// TODO1 lang
return "", nil
}

first := roots[0]
key = strings.TrimPrefix(key, s)
return filepath.Join(first.path, key), nil
}

func (fs *RootMappingFs) hasPrefix(prefix string) bool {
hasPrefix := false
fs.rootMapToReal.WalkPrefix(prefix, func(b string, v interface{}) bool {
Expand All @@ -254,7 +297,15 @@ func (fs *RootMappingFs) getRoot(key string) []RootMapping {
}

func (fs *RootMappingFs) getRoots(key string) (string, []RootMapping) {
s, v, found := fs.rootMapToReal.LongestPrefix(key)
return fs.getRootsIn(key, fs.rootMapToReal)
}

func (fs *RootMappingFs) getRootsReverse(key string) (string, []RootMapping) {
return fs.getRootsIn(key, fs.realMapToRoot)
}

func (fs *RootMappingFs) getRootsIn(key string, tree *radix.Tree) (string, []RootMapping) {
s, v, found := tree.LongestPrefix(key)
if !found || (s == filepathSeparator && key != filepathSeparator) {
return "", nil
}
Expand Down
3 changes: 3 additions & 0 deletions hugofs/rootmapping_fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ func TestRootMappingFsMount(t *testing.T) {
c.Assert(fi.Meta().Lang(), qt.Equals, lang)
c.Assert(fi.Name(), qt.Equals, "p1.md")
}

s, _ := rfs.ReverseLookup("singlefiles/sv.txt")
c.Assert(s, qt.Equals, filepath.FromSlash("singles/p1.md"))
}

func TestRootMappingFsMountOverlap(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion hugolib/breaking_changes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
func Test073(t *testing.T) {
assertDisabledTaxonomyAndTerm := func(b *sitesBuilder, taxonomy, term bool) {
b.Assert(b.CheckExists("public/tags/index.html"), qt.Equals, taxonomy)
b.Assert(b.CheckExists("public/tags/tag1/index.html"), qt.Equals, term)
// TODO1 should this be possible? Probably simpler to do this via build option b.Assert(b.CheckExists("public/tags/tag1/index.html"), qt.Equals, term)
}

assertOutputTaxonomyAndTerm := func(b *sitesBuilder, taxonomy, term bool) {
Expand Down
2 changes: 1 addition & 1 deletion hugolib/case_insensitive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ defaultContentLanguageInSubdir = true
AngledQuotes = true
HrefTargetBlank = true
[Params]
[Params]
Search = true
Color = "green"
mood = "Happy"
Expand Down
2 changes: 0 additions & 2 deletions hugolib/collections_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ tags_weight: %d
"pageGroups:2:page.PagesGroup:Page(/page1.md)/Page(/page2.md)",
`weightedPages:2::page.WeightedPages:[WeightedPage(10,"Page") WeightedPage(20,"Page")]`)
}

func TestUnionFunc(t *testing.T) {
c := qt.New(t)

Expand All @@ -96,7 +95,6 @@ title: "Page"
tags: ["blue", "green"]
tags_weight: %d
---
`
b := newTestSitesBuilder(t)
b.WithSimpleConfigFile().
Expand Down
Loading

0 comments on commit 499d032

Please sign in to comment.