Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
wip: fix issue with ReadDir . not showing virtual directories
  • Loading branch information
rymut committed Dec 17, 2024
commit ab1613699e72d4766397ece0ebff9742f0617ad4
18 changes: 1 addition & 17 deletions hugofs/component_fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"path"
"runtime"
"sort"
"fmt"

"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/paths"
Expand Down Expand Up @@ -216,22 +215,7 @@ func (fs *componentFs) applyMeta(fi FileNameIsDir, name string) (FileMetaInfo, b
}

func (f *componentFsDir) Readdir(count int) ([]os.FileInfo, error) {
dirnames, err := f.Readdirnames(count)
if err != nil {
return nil, fmt.Errorf("error readdirnames: %s", err)
}
files := make([]os.FileInfo, len(dirnames))
for i, d := range dirnames {
file, e := f.fs.Stat(d)
if e != nil {
return nil, fmt.Errorf("error reading dir stat %s: %s", d, e)
}
files[i] = file
}
return files, nil

// fmt.Printf("this is error here\n")
// panic("not supported: Use ReadDir")
panic("not supported: Use ReadDir")
}

func (f *componentFsDir) Readdirnames(count int) ([]string, error) {
Expand Down
7 changes: 5 additions & 2 deletions hugofs/rootmapping_fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,6 @@ func (fs *RootMappingFs) cleanName(name string) string {

func (rfs *RootMappingFs) collectDirEntries(prefix string) ([]iofs.DirEntry, error) {
prefix = filepathSeparator + rfs.cleanName(prefix)

var fis []iofs.DirEntry

seen := make(map[string]bool) // Prevent duplicate directories
Expand Down Expand Up @@ -594,6 +593,10 @@ func (rfs *RootMappingFs) collectDirEntries(prefix string) ([]iofs.DirEntry, err

// Next add any file mounts inside the given directory.
prefixInside := prefix + filepathSeparator
// When prefix is root then skip filepathSeparator.
if prefix == filepathSeparator {
prefixInside = prefix
}
rfs.rootMapToReal.WalkPrefix(prefixInside, func(s string, v any) bool {
if (strings.Count(s, filepathSeparator) - level) != 1 {
// This directory is not part of the current, but we
Expand Down Expand Up @@ -816,7 +819,7 @@ func (f *rootMappingDir) ReadDir(count int) ([]iofs.DirEntry, error) {
meta := fim.Meta()
if f.meta.InclusionFilter.Match(strings.TrimPrefix(meta.Filename, meta.SourceRoot), fim.IsDir()) {
result = append(result, fim)
}
}
}
return result, nil
}
Expand Down
6 changes: 5 additions & 1 deletion hugolib/filesystems/basefs.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,13 @@ func (f *fakeLockfileMutex) Lock() (func(), error) {
return func() { f.mu.Unlock() }, nil
}

func (b *BaseFs) OverlayFs() (*overlayfs.OverlayFs) {
func (b *BaseFs) OverlayMountsFs() (*overlayfs.OverlayFs) {
return b.theBigFs.overlayMounts
}
func (b *BaseFs) OverlayWorkFs() (*overlayfs.OverlayFs) {
return b.theBigFs.overlayFull
}

// Tries to acquire a build lock.
func (b *BaseFs) LockBuild() (unlock func(), err error) {
return b.buildMu.Lock()
Expand Down
38 changes: 19 additions & 19 deletions tpl/os/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (

// New returns a new instance of the os-namespaced template functions.
func New(d *deps.Deps) *Namespace {
var readFileFs, workFs, projectFs afero.Fs
var readFileFs, workFs, mountsFs afero.Fs

// The docshelper script does not have or need all the dependencies set up.
if d.PathSpec != nil {
Expand All @@ -43,13 +43,18 @@ func New(d *deps.Deps) *Namespace {
})
// See #9599
workFs = d.PathSpec.BaseFs.WorkDir
projectFs = d.PathSpec.BaseFs.OverlayFs()
mountsFs = overlayfs.New(overlayfs.Options{
Fss: []afero.Fs{
d.PathSpec.BaseFs.WorkDir,
d.PathSpec.BaseFs.OverlayMountsFs().WithDirsMerger(hugofs.AppendDirsMerger),
},
})
}

return &Namespace{
readFileFs: readFileFs,
workFs: workFs,
projectFs: projectFs,
mountsFs: mountsFs,
deps: d,
}
}
Expand All @@ -58,7 +63,7 @@ func New(d *deps.Deps) *Namespace {
type Namespace struct {
readFileFs afero.Fs
workFs afero.Fs
projectFs afero.Fs
mountsFs afero.Fs
deps *deps.Deps
}

Expand Down Expand Up @@ -116,7 +121,7 @@ func (ns *Namespace) ReadFile(i any, mode ...any) (string, error) {
if (old) {
s, err = readFile(ns.readFileFs, s)
} else {
s, err = readFile(ns.projectFs, s)
s, err = readFile(ns.mountsFs, s)
}
if err != nil && herrors.IsNotExist(err) {
return "", nil
Expand All @@ -140,26 +145,21 @@ func (ns *Namespace) ReadDir(i any, mode ...any) ([]_os.FileInfo, error) {
}
var list []_os.FileInfo
if (old) {
//list, err = afero.ReadDir(ns.workFs, path)
list, err = afero.ReadDir(ns.workFs, path)
} else {
file, _ := ns.projectFs.Open(path)
fmt.Printf("path %s content %T %s", path, file, file)
file, _ := ns.mountsFs.Open(path)
switch item := file.(type) {
case *overlayfs.Dir:
list, err = item.Readdir(0)
case hugofs.DirOnlyOps: // fully virtual directory // hugofs.rootMappingDir
fmt.Printf("\ndir only opts!!!!\n")
//list, err = item.Readdir(0)
//fmt.Printf("\ndir contents %s: %s\n", list, err)
items, _ := item.Readdirnames(0)
list = make([]_os.FileInfo, len(items))
for i, d := range items {
file, _ := ns.projectFs.Stat(path + "/" + d)
for i, item := range items {
file, _ := ns.mountsFs.Stat(path + "/" + item)
list[i] = file
}
fmt.Printf("\ndir only opts %s!!!!\n", items)
case *overlayfs.Dir:
list, err = item.Readdir(0)
default:
//list, err = afero.ReadDir(ns.projectFs, path)
//list, err = afero.ReadDir(ns.mountsFs, path)
}
if file != nil {
file.Close()
Expand Down Expand Up @@ -194,7 +194,7 @@ func (ns *Namespace) FileExists(i any, mode ...any) (bool, error) {
if (old) {
status, err = afero.Exists(ns.readFileFs, path)
} else {
status, err = afero.Exists(ns.projectFs, path)
status, err = afero.Exists(ns.mountsFs, path)
}
if err != nil {
return false, err
Expand Down Expand Up @@ -225,7 +225,7 @@ func (ns *Namespace) Stat(i any, mode ...any) (_os.FileInfo, error) {
if (old) {
r, err = ns.readFileFs.Stat(path)
} else {
r, err = ns.projectFs.Stat(path)
r, err = ns.mountsFs.Stat(path)
}
if err != nil {
return nil, err
Expand Down
74 changes: 39 additions & 35 deletions tpl/os/os_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,54 @@ import (
"github.com/gohugoio/hugo/hugolib"
)

// Issue 9599
func TestReadDirWorkDir(t *testing.T) {

func TestReadDirMountDir2(t *testing.T) {
t.Parallel()

files := `
-- config.toml --
-- hugo.toml --
baseURL = "https://example.com/"
theme = "mytheme"
[module]
[[module.imports]]
path = "module1"
[[module.imports.mounts]]
source = "assets"
target = "assets"
[[module.imports]]
path = "mytheme"
[[module.imports.mounts]]
source = "private"
target = "assets"
[[module.imports.mounts]]
source = "private/test"
target = "assets"

-- myproject.txt --
Hello project!
-- themes/module1/hugo.toml --
-- themes/module1/go.mod --
module github.com/rymut/hugo-issues-mre/hugo-os/hugo-os-module2

go 1.23.2
-- themes/module1/assets/file.json --
{}
-- themes/mytheme/mytheme.txt --
Hello theme!
-- themes/mytheme/data/not.my_content.md --
test
-- themes/mytheme/layouts/partials/mypartial.html --
test
-- themes/mytheme/private/test/should_not_mount.txt --
Empty file
-- layouts/index.html --
{{ $entries := (readDir ".") }}
START:|{{ range $entry := $entries }}{{ if not $entry.IsDir }}{{ $entry.Name }}|{{ end }}{{ end }}:END:


`

{{ $entries := (readDir "" false) }}
START:|{{ range $entry := $entries }}{{ $entry.Name }}|{{ end }}:END:
-- files/layouts/l1.txt --
l1
-- files/layouts/assets/l2.txt --
l2
`
b := hugolib.NewIntegrationTestBuilder(
hugolib.IntegrationTestConfig{
T: t,
Expand All @@ -49,29 +79,3 @@ START:|{{ range $entry := $entries }}{{ if not $entry.IsDir }}{{ $entry.Name }}|
START:|config.toml|myproject.txt|:END:
`)
}

// Issue 9620
func TestReadFileNotExists(t *testing.T) {
t.Parallel()

files := `
-- config.toml --
-- layouts/index.html --
{{ $fi := (readFile "doesnotexist") }}
{{ if $fi }}Failed{{ else }}OK{{ end }}


`

b := hugolib.NewIntegrationTestBuilder(
hugolib.IntegrationTestConfig{
T: t,
TxtarString: files,
NeedsOsFS: true,
},
).Build()

b.AssertFileContent("public/index.html", `
OK
`)
}