Repository: gohugoio/hugo (language: go)

Issue:
Panic when cascading `headless` from site config to section that does not have an _index.md file
content

```text
content/
└── s1/
    └── p1.md
```

config

```
[[cascade]]
headless = true
[cascade._target]
path = '/s1**'
```

Hugo v0.122.0 emitted this warning...

> WARN  .File.TranslationBaseName on zero object. Wrap it in if or with: {{ with .File }}{{ .TranslationBaseName }}{{ end }}

...but still published s1/p1 (which I think was wrong too).

<details>
<summary>failing test case</summary>

```go
func TestFoo(t *testing.T) {
	t.Parallel()

	files := `
-- hugo.toml --
disableKinds = ['rss','sitemap','taxonomy','term']
[[cascade]]
headless = true
[cascade._target]
path = '/s1**'
-- content/s1/p1.md --
---
title: p1
---
-- layouts/_default/single.html --
{{ .Title }}|
-- layouts/_default/list.html --
{{ .Title }}|
  `
	b := hugolib.Test(t, files)

	b.AssertFileExists("public/index.html", true)
	b.AssertFileExists("public/s1/index.html", false)
	b.AssertFileExists("public/s1/p1/index.html", false)
}

```
</details>
<br>


Discussion / hints:

Fix patch:
diff --git a/hugofs/rootmapping_fs.go b/hugofs/rootmapping_fs.go
index 04c5b4a7268..a5bf9aadfe8 100644
--- a/hugofs/rootmapping_fs.go
+++ b/hugofs/rootmapping_fs.go
@@ -43,7 +43,6 @@ var _ ReverseLookupProvder = (*RootMappingFs)(nil)
 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
@@ -154,11 +153,8 @@ func NewRootMappingFs(fs afero.Fs, rms ...RootMapping) (*RootMappingFs, error) {
 
 		addMapping(rev, rm, realMapToRoot)
 
-		virtualRoots = append(virtualRoots, rm)
 	}
 
-	rootMapToReal.Insert(filepathSeparator, virtualRoots)
-
 	rfs := &RootMappingFs{
 		Fs:            fs,
 		rootMapToReal: rootMapToReal,
@@ -414,6 +410,7 @@ func (fs *RootMappingFs) getRoots(key string) (string, []RootMapping) {
 	for {
 		var found bool
 		ss, vv, found := tree.LongestPrefix(key)
+
 		if !found || (levels < 2 && ss == key) {
 			break
 		}
diff --git a/hugolib/content_map_page.go b/hugolib/content_map_page.go
index 1114428df0e..5388426c9a5 100644
--- a/hugolib/content_map_page.go
+++ b/hugolib/content_map_page.go
@@ -685,13 +685,13 @@ func (s *contentNodeShifter) Delete(n contentNodeI, dimension doctree.Dimension)
 		}
 		return wasDeleted, isEmpty
 	case *resourceSource:
-		if lidx > 0 {
+		if lidx != v.LangIndex() {
 			return false, false
 		}
 		resource.MarkStale(v)
 		return true, true
 	case *pageState:
-		if lidx > 0 {
+		if lidx != v.s.languagei {
 			return false, false
 		}
 		resource.MarkStale(v)
@@ -1714,6 +1714,7 @@ func (sa *sitePagesAssembler) removeShouldNotBuild() error {
 	if len(keys) == 0 {
 		return nil
 	}
+
 	sa.pageMap.DeletePageAndResourcesBelow(keys...)
 
 	return nil
diff --git a/hugolib/page__meta.go b/hugolib/page__meta.go
index 082e3145a49..8c148923dfc 100644
--- a/hugolib/page__meta.go
+++ b/hugolib/page__meta.go
@@ -523,7 +523,7 @@ params:
 			// pages.
 			isHeadless := cast.ToBool(v)
 			params[loki] = isHeadless
-			if p.File().TranslationBaseName() == "index" && isHeadless {
+			if isHeadless {
 				pm.pageConfig.Build.List = pagemeta.Never
 				pm.pageConfig.Build.Render = pagemeta.Never
 			}


Test patch:
diff --git a/hugolib/cascade_test.go b/hugolib/cascade_test.go
index b9b80a3a1ed..8075f190f4e 100644
--- a/hugolib/cascade_test.go
+++ b/hugolib/cascade_test.go
@@ -766,3 +766,29 @@ path = '/p1.md'
 	b := Test(t, files)
 	b.AssertLogNotContains(`looks like a path with an extension`)
 }
+
+func TestCascadeIssue12172(t *testing.T) {
+	t.Parallel()
+
+	files := `
+-- hugo.toml --
+disableKinds = ['rss','sitemap','taxonomy','term']
+[[cascade]]
+headless = true
+[cascade._target]
+path = '/s1**'
+-- content/s1/p1.md --
+---
+title: p1
+---
+-- layouts/_default/single.html --
+{{ .Title }}|
+-- layouts/_default/list.html --
+{{ .Title }}|
+  `
+	b := Test(t, files)
+
+	b.AssertFileExists("public/index.html", true)
+	b.AssertFileExists("public/s1/index.html", false)
+	b.AssertFileExists("public/s1/p1/index.html", false)
+}
diff --git a/hugolib/datafiles_test.go b/hugolib/datafiles_test.go
index 99cc5b407d6..657e6020cf1 100644
--- a/hugolib/datafiles_test.go
+++ b/hugolib/datafiles_test.go
@@ -64,3 +64,21 @@ v1: {{  site.Data.MyFolder.MyData.v1 }}|
 
 	b.AssertFileContent("public/index.html", "v1: my_v1|")
 }
+
+// Issue #12133
+func TestDataNoAssets(t *testing.T) {
+	t.Parallel()
+
+	files := `
+-- hugo.toml --
+disableKinds = ['page','rss','section','sitemap','taxonomy','term']
+-- assets/data/foo.toml --
+content = "I am assets/data/foo.toml"
+-- layouts/index.html --
+|{{ site.Data.foo.content }}|
+	`
+
+	b := Test(t, files)
+
+	b.AssertFileContent("public/index.html", "||")
+}
diff --git a/hugolib/page__meta_test.go b/hugolib/page__meta_test.go
index d4b66ed9a29..58d29464d9a 100644
--- a/hugolib/page__meta_test.go
+++ b/hugolib/page__meta_test.go
@@ -11,13 +11,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package hugolib_test
+package hugolib
 
 import (
 	"strings"
 	"testing"
-
-	"github.com/gohugoio/hugo/hugolib"
 )
 
 // Issue 9793
@@ -43,7 +41,7 @@ tags: 'tag-a'
 {{ .Title }}
 	`
 
-	b := hugolib.Test(t, files)
+	b := Test(t, files)
 
 	b.AssertFileContent("public/section-1/index.html", "Section-1s")
 	b.AssertFileContent("public/tags/index.html", "Tags")
@@ -51,9 +49,34 @@ tags: 'tag-a'
 
 	files = strings.Replace(files, "true", "false", -1)
 
-	b = hugolib.Test(t, files)
+	b = Test(t, files)
 
 	b.AssertFileContent("public/section-1/index.html", "section-1")
 	b.AssertFileContent("public/tags/index.html", "tags")
 	b.AssertFileContent("public/tags/tag-a/index.html", "tag-a")
 }
+
+func TestDraftNonDefaultContentLanguage(t *testing.T) {
+	t.Parallel()
+
+	files := `
+-- hugo.toml --
+defaultContentLanguage = "en"
+[languages]
+[languages.en]
+weight = 1
+[languages.nn]
+weight = 2
+-- content/p1.md --
+-- content/p2.nn.md --
+---
+title: "p2"
+draft: true
+---
+-- layouts/_default/single.html --
+{{ .Title }}
+`
+	b := Test(t, files)
+
+	b.AssertFileExists("public/nn/p2/index.html", false)
+}