Skip to content

Commit 3228817

Browse files
committed
Add roles and versions as new dimensions (in addition to language)
Fixes #519 Fixes #13680 Fixes #13663 Fixes #13776
1 parent 32af02c commit 3228817

File tree

100 files changed

+4372
-1145
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+4372
-1145
lines changed

‎cache/dynacache/dynacache.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ func GetOrCreatePartition[K comparable, V any](c *Cache, name string, opts Optio
340340
panic("invalid Weight, must be between 1 and 100")
341341
}
342342

343-
if partitionNameRe.FindString(name) != name {
343+
if !partitionNameRe.MatchString(name) {
344344
panic(fmt.Sprintf("invalid partition name %q", name))
345345
}
346346

‎commands/hugobuilder.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/bep/simplecobra"
3131
"github.com/fsnotify/fsnotify"
3232
"github.com/gohugoio/hugo/common/herrors"
33+
"github.com/gohugoio/hugo/common/hstrings"
3334
"github.com/gohugoio/hugo/common/htime"
3435
"github.com/gohugoio/hugo/common/hugo"
3536
"github.com/gohugoio/hugo/common/loggers"
@@ -142,7 +143,7 @@ func (c *hugoBuilder) getDirList() ([]string, error) {
142143
return nil, err
143144
}
144145

145-
return helpers.UniqueStringsSorted(h.PathSpec.BaseFs.WatchFilenames()), nil
146+
return hstrings.UniqueStringsSorted(h.PathSpec.BaseFs.WatchFilenames()), nil
146147
}
147148

148149
func (c *hugoBuilder) initCPUProfile() (func(), error) {

‎commands/server.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import (
4949
"github.com/fsnotify/fsnotify"
5050
"github.com/gohugoio/hugo/common/herrors"
5151
"github.com/gohugoio/hugo/common/hugo"
52+
"github.com/gohugoio/hugo/langs"
5253
"github.com/gohugoio/hugo/tpl/tplimpl"
5354

5455
"github.com/gohugoio/hugo/common/types"
@@ -879,7 +880,7 @@ func (c *serverCommand) serve() error {
879880
if isMultihost {
880881
for _, l := range conf.configs.ConfigLangs() {
881882
baseURLs = append(baseURLs, l.BaseURL())
882-
roots = append(roots, l.Language().Lang)
883+
roots = append(roots, l.Language().(*langs.Language).Lang)
883884
}
884885
} else {
885886
l := conf.configs.GetFirstLanguageConfig()

‎common/herrors/errors.go‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"os"
2222
"regexp"
2323
"runtime"
24-
"runtime/debug"
2524
"strings"
2625
"time"
2726
)
@@ -45,7 +44,9 @@ type ErrorSender interface {
4544
func Recover(args ...any) {
4645
if r := recover(); r != nil {
4746
fmt.Println("ERR:", r)
48-
args = append(args, "stacktrace from panic: \n"+string(debug.Stack()), "\n")
47+
buf := make([]byte, 64<<10)
48+
buf = buf[:runtime.Stack(buf, false)]
49+
args = append(args, "stacktrace from panic: \n"+string(buf), "\n")
4950
fmt.Println(args...)
5051
}
5152
}

‎common/hstrings/strings.go‎

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"fmt"
1818
"regexp"
1919
"slices"
20+
"sort"
2021
"strings"
2122
"sync"
2223

@@ -128,7 +129,61 @@ func ToString(v any) (string, bool) {
128129
return "", false
129130
}
130131

131-
type (
132-
Strings2 [2]string
133-
Strings3 [3]string
134-
)
132+
// UniqueStrings returns a new slice with any duplicates removed.
133+
func UniqueStrings(s []string) []string {
134+
unique := make([]string, 0, len(s))
135+
for i, val := range s {
136+
var seen bool
137+
for j := range i {
138+
if s[j] == val {
139+
seen = true
140+
break
141+
}
142+
}
143+
if !seen {
144+
unique = append(unique, val)
145+
}
146+
}
147+
return unique
148+
}
149+
150+
// UniqueStringsReuse returns a slice with any duplicates removed.
151+
// It will modify the input slice.
152+
func UniqueStringsReuse(s []string) []string {
153+
result := s[:0]
154+
for i, val := range s {
155+
var seen bool
156+
157+
for j := range i {
158+
if s[j] == val {
159+
seen = true
160+
break
161+
}
162+
}
163+
164+
if !seen {
165+
result = append(result, val)
166+
}
167+
}
168+
return result
169+
}
170+
171+
// UniqueStringsSorted returns a sorted slice with any duplicates removed.
172+
// It will modify the input slice.
173+
func UniqueStringsSorted(s []string) []string {
174+
if len(s) == 0 {
175+
return nil
176+
}
177+
ss := sort.StringSlice(s)
178+
ss.Sort()
179+
i := 0
180+
for j := 1; j < len(s); j++ {
181+
if !ss.Less(i, j) {
182+
continue
183+
}
184+
i++
185+
s[i] = s[j]
186+
}
187+
188+
return s[:i+1]
189+
}

‎common/hstrings/strings_test.go‎

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2024 The Hugo Authors. All rights reserved.
1+
// Copyright 2025 The Hugo Authors. All rights reserved.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
1414
package hstrings
1515

1616
import (
17+
"reflect"
1718
"regexp"
1819
"testing"
1920

@@ -43,6 +44,84 @@ func TestGetOrCompileRegexp(t *testing.T) {
4344
c.Assert(re.MatchString("123"), qt.Equals, true)
4445
}
4546

47+
func TestUniqueStrings(t *testing.T) {
48+
in := []string{"a", "b", "a", "b", "c", "", "a", "", "d"}
49+
output := UniqueStrings(in)
50+
expected := []string{"a", "b", "c", "", "d"}
51+
if !reflect.DeepEqual(output, expected) {
52+
t.Errorf("Expected %#v, got %#v\n", expected, output)
53+
}
54+
}
55+
56+
func TestUniqueStringsReuse(t *testing.T) {
57+
in := []string{"a", "b", "a", "b", "c", "", "a", "", "d"}
58+
output := UniqueStringsReuse(in)
59+
expected := []string{"a", "b", "c", "", "d"}
60+
if !reflect.DeepEqual(output, expected) {
61+
t.Errorf("Expected %#v, got %#v\n", expected, output)
62+
}
63+
}
64+
65+
func TestUniqueStringsSorted(t *testing.T) {
66+
c := qt.New(t)
67+
in := []string{"a", "a", "b", "c", "b", "", "a", "", "d"}
68+
output := UniqueStringsSorted(in)
69+
expected := []string{"", "a", "b", "c", "d"}
70+
c.Assert(output, qt.DeepEquals, expected)
71+
c.Assert(UniqueStringsSorted(nil), qt.IsNil)
72+
}
73+
74+
func BenchmarkUniqueStrings(b *testing.B) {
75+
input := []string{"a", "b", "d", "e", "d", "h", "a", "i"}
76+
77+
b.Run("Safe", func(b *testing.B) {
78+
for i := 0; i < b.N; i++ {
79+
result := UniqueStrings(input)
80+
if len(result) != 6 {
81+
b.Fatalf("invalid count: %d", len(result))
82+
}
83+
}
84+
})
85+
86+
b.Run("Reuse slice", func(b *testing.B) {
87+
b.StopTimer()
88+
inputs := make([][]string, b.N)
89+
for i := 0; i < b.N; i++ {
90+
inputc := make([]string, len(input))
91+
copy(inputc, input)
92+
inputs[i] = inputc
93+
}
94+
b.StartTimer()
95+
for i := 0; i < b.N; i++ {
96+
inputc := inputs[i]
97+
98+
result := UniqueStringsReuse(inputc)
99+
if len(result) != 6 {
100+
b.Fatalf("invalid count: %d", len(result))
101+
}
102+
}
103+
})
104+
105+
b.Run("Reuse slice sorted", func(b *testing.B) {
106+
b.StopTimer()
107+
inputs := make([][]string, b.N)
108+
for i := 0; i < b.N; i++ {
109+
inputc := make([]string, len(input))
110+
copy(inputc, input)
111+
inputs[i] = inputc
112+
}
113+
b.StartTimer()
114+
for i := 0; i < b.N; i++ {
115+
inputc := inputs[i]
116+
117+
result := UniqueStringsSorted(inputc)
118+
if len(result) != 6 {
119+
b.Fatalf("invalid count: %d", len(result))
120+
}
121+
}
122+
})
123+
}
124+
46125
func BenchmarkGetOrCompileRegexp(b *testing.B) {
47126
for i := 0; i < b.N; i++ {
48127
GetOrCompileRegexp(`\d+`)

‎common/hugo/hugo.go‎

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/gohugoio/hugo/common/hexec"
3333
"github.com/gohugoio/hugo/common/loggers"
3434
"github.com/gohugoio/hugo/common/maps"
35+
"github.com/gohugoio/hugo/common/version"
3536
"github.com/gohugoio/hugo/hugofs/files"
3637

3738
"github.com/spf13/afero"
@@ -80,7 +81,7 @@ type HugoInfo struct {
8081
}
8182

8283
// Version returns the current version as a comparable version string.
83-
func (i HugoInfo) Version() VersionString {
84+
func (i HugoInfo) Version() version.VersionString {
8485
return CurrentVersion.Version()
8586
}
8687

@@ -451,7 +452,7 @@ func deprecateLevelWithLogger(item, alternative, version string, level logg.Leve
451452
// We want people to run at least the current and previous version without any warnings.
452453
// We want people who don't update Hugo that often to see the warnings and errors before we remove the feature.
453454
func deprecationLogLevelFromVersion(ver string) logg.Level {
454-
from := MustParseVersion(ver)
455+
from := version.MustParseVersion(ver)
455456
to := CurrentVersion
456457
minorDiff := to.Minor - from.Minor
457458
switch {
@@ -465,3 +466,46 @@ func deprecationLogLevelFromVersion(ver string) logg.Level {
465466
return logg.LevelInfo
466467
}
467468
}
469+
470+
// BuildVersionString creates a version string. This is what you see when
471+
// running "hugo version".
472+
func BuildVersionString() string {
473+
// program := "Hugo Static Site Generator"
474+
program := "hugo"
475+
476+
version := "v" + CurrentVersion.String()
477+
478+
bi := getBuildInfo()
479+
if bi == nil {
480+
return version
481+
}
482+
if bi.Revision != "" {
483+
version += "-" + bi.Revision
484+
}
485+
if IsExtended {
486+
version += "+extended"
487+
}
488+
if IsWithdeploy {
489+
version += "+withdeploy"
490+
}
491+
492+
osArch := bi.GoOS + "/" + bi.GoArch
493+
494+
date := bi.RevisionTime
495+
if date == "" {
496+
// Accept vendor-specified build date if .git/ is unavailable.
497+
date = buildDate
498+
}
499+
if date == "" {
500+
date = "unknown"
501+
}
502+
503+
versionString := fmt.Sprintf("%s %s %s BuildDate=%s",
504+
program, version, osArch, date)
505+
506+
if vendorInfo != "" {
507+
versionString += " VendorInfo=" + vendorInfo
508+
}
509+
510+
return versionString
511+
}

‎common/hugo/hugo_test.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
"github.com/bep/logg"
2222
qt "github.com/frankban/quicktest"
23+
"github.com/gohugoio/hugo/common/version"
2324
)
2425

2526
func TestHugoInfo(t *testing.T) {
@@ -29,7 +30,7 @@ func TestHugoInfo(t *testing.T) {
2930
hugoInfo := NewInfo(conf, nil)
3031

3132
c.Assert(hugoInfo.Version(), qt.Equals, CurrentVersion.Version())
32-
c.Assert(fmt.Sprintf("%T", VersionString("")), qt.Equals, fmt.Sprintf("%T", hugoInfo.Version()))
33+
c.Assert(fmt.Sprintf("%T", version.VersionString("")), qt.Equals, fmt.Sprintf("%T", hugoInfo.Version()))
3334
c.Assert(hugoInfo.WorkingDir(), qt.Equals, "/mywork")
3435

3536
bi := getBuildInfo()

‎common/hugo/version_current.go‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2018 The Hugo Authors. All rights reserved.
1+
// Copyright 2025 The Hugo Authors. All rights reserved.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -13,9 +13,11 @@
1313

1414
package hugo
1515

16+
import "github.com/gohugoio/hugo/common/version"
17+
1618
// CurrentVersion represents the current build version.
1719
// This should be the only one.
18-
var CurrentVersion = Version{
20+
var CurrentVersion = version.Version{
1921
Major: 0,
2022
Minor: 148,
2123
PatchLevel: 0,

0 commit comments

Comments
 (0)