Fix multi --renderSegments merge behavior

Fixes #15024
This commit is contained in:
Bjørn Erik Pedersen
2026-06-11 11:57:09 +02:00
parent a00b5c72ac
commit 95e5e9f4ab
3 changed files with 95 additions and 19 deletions
+7 -2
View File
@@ -559,7 +559,12 @@ func (s *IntegrationTestBuilder) AssertPublishDir(matches ...string) {
func (s *IntegrationTestBuilder) AssertFs(fs afero.Fs, matches ...string) {
s.Helper()
var buff bytes.Buffer
s.Assert(s.printAndCheckFs(fs, "", &buff), qt.IsNil)
if err := s.printAndCheckFs(fs, "", &buff); err != nil {
// E.g. public not created, treat that as an empty dir.
if !errors.Is(err, os.ErrNotExist) {
s.Fatal(err)
}
}
printFsLines := strings.Split(buff.String(), "\n")
sort.Strings(printFsLines)
content := strings.TrimSpace((strings.Join(printFsLines, "\n")))
@@ -589,7 +594,7 @@ func (s *IntegrationTestBuilder) printAndCheckFs(fs afero.Fs, path string, w io.
return afero.Walk(fs, path, func(path string, info os.FileInfo, err error) error {
if err != nil {
return fmt.Errorf("error: path %q: %s", path, err)
return err
}
path = filepath.ToSlash(path)
if path == "" {
+29 -17
View File
@@ -44,17 +44,35 @@ type SegmentFilter interface {
ShouldExcludeFine(SegmentQuery) bool
}
type segmentFilter struct {
exclude predicate.PR[SegmentQuery]
type segmentPredicate struct {
include predicate.PR[SegmentQuery]
exclude predicate.PR[SegmentQuery]
}
type segmentFilter struct {
segments []segmentPredicate
}
// ShouldExcludeCoarse skips a whole site or output format only if every
// segment excludes it; a single segment that doesn't is enough to keep it.
func (f segmentFilter) ShouldExcludeCoarse(q SegmentQuery) bool {
return f.exclude(q).OK()
for _, s := range f.segments {
if !s.exclude(q).OK() {
return false
}
}
return true
}
// ShouldExcludeFine renders the query if any segment includes it and does not
// exclude it.
func (f segmentFilter) ShouldExcludeFine(q SegmentQuery) bool {
return f.exclude(q).OK() || !f.include(q).OK()
for _, s := range f.segments {
if s.include(q).OK() && !s.exclude(q).OK() {
return false
}
}
return true
}
type segmentsBuilder struct {
@@ -204,23 +222,17 @@ func (s *segmentsBuilder) build() (SegmentFilter, error) {
if err != nil {
return nil, err
}
if sf.include == nil {
sf.include = include
} else {
sf.include = sf.include.Or(include)
if include == nil {
include = matchAll
}
if sf.exclude == nil {
sf.exclude = exclude
} else {
sf.exclude = sf.exclude.Or(exclude)
if exclude == nil {
exclude = matchNothing
}
sf.segments = append(sf.segments, segmentPredicate{include: include, exclude: exclude})
}
if sf.exclude == nil {
sf.exclude = matchNothing
}
if sf.include == nil {
sf.include = matchAll
if len(sf.segments) == 0 {
sf.segments = append(sf.segments, segmentPredicate{include: matchAll, exclude: matchNothing})
}
return sf, nil
@@ -14,6 +14,7 @@
package segments_test
import (
"strings"
"testing"
qt "github.com/frankban/quicktest"
@@ -76,6 +77,64 @@ tags: ["tag1", "tag2"]
b.AssertFileExists("public/no/index.xml", false)
}
// See issue 15024.
func TestSegmentsMultiple(t *testing.T) {
filesTemplate := `
-- hugo.toml --
renderSegments = SEGMENTS
disableKinds = ["home", "taxonomy", "term", "page"]
[outputs]
section = ['html', 'json']
[segments]
[segments.excludeallkinds]
[[segments.excludeallkinds.excludes]]
kind = "**"
[segments.blog]
[[segments.blog.includes]]
path = "{/blog,/blog/**}"
[[segments.blog.excludes]]
output = 'json'
[segments.news]
[[segments.news.includes]]
path = "{/news,/news/**}"
-- layouts/all.html --
{{ .Kind }}: {{ .Title }}|{{ .RelPermalink }}|
-- layouts/all.json --
{{ .Kind }}: {{ .Title }}|{{ .RelPermalink }}|
-- content/blog/_index.md --
-- content/blog/page1.md --
---
title: "Blog Page 1"
tags: ["tag1", "tag2"]
---
-- content/news/_index.md --
-- content/news/page1.md --
---
title: "News Page 1"
tags: ["tag1", "tag2"]
---
`
files := strings.ReplaceAll(filesTemplate, "SEGMENTS", `["excludeallkinds", "blog", "news"]`)
b := hugolib.Test(t, files, hugolib.TestOptInfo())
b.AssertPublishDir(`
blog/index.html
! blog/index.json
news/index.html
news/index.json
`)
files = strings.ReplaceAll(filesTemplate, "SEGMENTS", `["excludeallkinds"]`)
b = hugolib.Test(t, files, hugolib.TestOptInfo())
b.AssertPublishDir(`
! json
! html
`)
}
// See issue 14939.
func TestRenderSegmentsMergesHugoStatsJSON(t *testing.T) {
files := `