Fix regression on handling of overlapping file mounts

But note that the overlay file system is set up horizontally (project -> module1 -> module2), so I would not recommend too complex overlapping mount setups within the same module.

But this worked in v0.122.0, so we should fix it.

Fixes #12103
This commit is contained in:
Bjørn Erik Pedersen 2024-02-21 20:16:02 +01:00
parent e75784930d
commit 16406d9d77
5 changed files with 111 additions and 12 deletions

View File

@ -328,7 +328,14 @@ func PrintFs(fs afero.Fs, path string, w io.Writer) {
}
afero.Walk(fs, path, func(path string, info os.FileInfo, err error) error {
fmt.Fprintln(w, filepath.ToSlash(path))
if err != nil {
panic(fmt.Sprintf("error: path %q: %s", path, err))
}
path = filepath.ToSlash(path)
if path == "" {
path = "."
}
fmt.Fprintln(w, path, info.IsDir())
return nil
})
}

View File

@ -323,7 +323,6 @@ func (fs *RootMappingFs) Stat(name string) (os.FileInfo, error) {
if err != nil {
return nil, err
}
return fis[0], nil
}
@ -403,16 +402,42 @@ func (fs *RootMappingFs) getRoot(key string) []RootMapping {
}
func (fs *RootMappingFs) getRoots(key string) (string, []RootMapping) {
return fs.getRootsIn(key, fs.rootMapToReal)
tree := fs.rootMapToReal
levels := strings.Count(key, filepathSeparator)
seen := make(map[RootMapping]bool)
var roots []RootMapping
var s string
for {
var found bool
ss, vv, found := tree.LongestPrefix(key)
if !found || (levels < 2 && ss == key) {
break
}
for _, rm := range vv.([]RootMapping) {
if !seen[rm] {
seen[rm] = true
roots = append(roots, rm)
}
}
s = ss
// We may have more than one root for this key, so walk up.
oldKey := key
key = filepath.Dir(key)
if key == oldKey {
break
}
}
return s, roots
}
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) {
tree := fs.realMapToRoot
s, v, found := tree.LongestPrefix(key)
if !found {
return "", nil
}

View File

@ -478,11 +478,47 @@ Home.
_ = stat("blog/b1.md")
}
func TestStaticComposite(t *testing.T) {
files := `
-- hugo.toml --
disableKinds = ["taxonomy", "term"]
[module]
[[module.mounts]]
source = "myfiles/f1.txt"
target = "static/files/f1.txt"
[[module.mounts]]
source = "f3.txt"
target = "static/f3.txt"
[[module.mounts]]
source = "static"
target = "static"
-- static/files/f2.txt --
f2
-- myfiles/f1.txt --
f1
-- f3.txt --
f3
-- layouts/home.html --
Home.
`
b := hugolib.Test(t, files)
b.AssertFs(b.H.BaseFs.StaticFs(""), `
. true
f3.txt false
files true
files/f1.txt false
files/f2.txt false
`)
}
func checkFileCount(fs afero.Fs, dirname string, c *qt.C, expected int) {
c.Helper()
count, _, err := countFilesAndGetFilenames(fs, dirname)
c.Assert(err, qt.IsNil)
c.Assert(count, qt.Equals, expected)
count, names, err := countFilesAndGetFilenames(fs, dirname)
namesComment := qt.Commentf("filenames: %v", names)
c.Assert(err, qt.IsNil, namesComment)
c.Assert(count, qt.Equals, expected, namesComment)
}
func checkFileContent(fs afero.Fs, filename string, c *qt.C, expected ...string) {

View File

@ -275,9 +275,13 @@ func (s *IntegrationTestBuilder) AssertFileContentExact(filename string, matches
}
func (s *IntegrationTestBuilder) AssertPublishDir(matches ...string) {
s.AssertFs(s.fs.PublishDir, matches...)
}
func (s *IntegrationTestBuilder) AssertFs(fs afero.Fs, matches ...string) {
s.Helper()
var buff bytes.Buffer
helpers.PrintFs(s.H.Fs.PublishDir, "", &buff)
helpers.PrintFs(fs, "", &buff)
printFsLines := strings.Split(buff.String(), "\n")
sort.Strings(printFsLines)
content := strings.TrimSpace((strings.Join(printFsLines, "\n")))

View File

@ -0,0 +1,27 @@
hugo
ls public/files
checkfile public/files/f1.txt
checkfile public/files/f2.txt
checkfile public/f3.txt
-- hugo.toml --
disableKinds = ["taxonomy", "term"]
[module]
[[module.mounts]]
source = "myfiles/f1.txt"
target = "static/files/f1.txt"
[[module.mounts]]
source = "f3.txt"
target = "static/f3.txt"
[[module.mounts]]
source = "static"
target = "static"
-- static/files/f2.txt --
f2
-- myfiles/f1.txt --
f1
-- f3.txt --
f3
-- layouts/home.html --
Home.