From e77ca3c105bd64c5077d823d2127f6f812a4f681 Mon Sep 17 00:00:00 2001 From: satotake Date: Wed, 27 Apr 2022 02:57:04 +0900 Subject: Add `clock` cli flag Close #8787 --- cache/filecache/filecache.go | 3 ++- commands/commandeer.go | 23 +++++++++++++++++++ commands/commands.go | 7 ++++-- commands/hugo.go | 10 +++++---- commands/hugo_test.go | 45 ++++++++++++++++++++++++++++++++++--- commands/import_jekyll.go | 5 +++-- commands/list.go | 8 +++++++ commands/list_test.go | 4 ++-- commands/new_theme.go | 4 ++-- commands/server.go | 7 +++--- common/htime/time.go | 12 ++++++++++ common/loggers/loggers.go | 5 +++-- go.mod | 1 + go.sum | 2 ++ hugofs/fileinfo.go | 3 ++- hugolib/content_factory.go | 3 ++- hugolib/page_test.go | 51 +++++++++++++++++++++++++++++++++++++++++- hugolib/site.go | 6 +++-- metrics/metrics.go | 3 ++- modules/collect.go | 3 ++- resources/resource/dates.go | 11 ++++++--- tpl/collections/collections.go | 1 + tpl/partials/partials.go | 4 ++-- tpl/time/init.go | 1 + tpl/time/time.go | 4 ++-- tpl/tplimpl/template.go | 4 ++-- 26 files changed, 193 insertions(+), 37 deletions(-) diff --git a/cache/filecache/filecache.go b/cache/filecache/filecache.go index 5a87382ae..3104d8ac6 100644 --- a/cache/filecache/filecache.go +++ b/cache/filecache/filecache.go @@ -24,6 +24,7 @@ import ( "sync" "time" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/helpers" @@ -295,7 +296,7 @@ func (c *Cache) isExpired(modTime time.Time) bool { if c.maxAge < 0 { return false } - return c.maxAge == 0 || time.Since(modTime) > c.maxAge + return c.maxAge == 0 || htime.Since(modTime) > c.maxAge } // For testing diff --git a/commands/commandeer.go b/commands/commandeer.go index 5b192c172..20090cccd 100644 --- a/commands/commandeer.go +++ b/commands/commandeer.go @@ -15,6 +15,7 @@ package commands import ( "errors" + "fmt" "io/ioutil" "net" "os" @@ -28,9 +29,11 @@ import ( "golang.org/x/sync/semaphore" "github.com/gohugoio/hugo/common/herrors" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/paths" + "github.com/spf13/cast" jww "github.com/spf13/jwalterweatherman" "github.com/gohugoio/hugo/common/loggers" @@ -41,6 +44,7 @@ import ( "github.com/gohugoio/hugo/hugolib" "github.com/spf13/afero" + "github.com/bep/clock" "github.com/bep/debounce" "github.com/bep/overlayfs" "github.com/gohugoio/hugo/common/types" @@ -164,6 +168,20 @@ func (c *commandeer) initFs(fs *hugofs.Fs) error { return nil } +func (c *commandeer) initClock() error { + bt := c.Cfg.GetString("clock") + if bt == "" { + return nil + } + + t, err := cast.StringToDateInDefaultLocation(bt, nil) + if err != nil { + return fmt.Errorf(`failed to parse "clock" flag: %s`, err) + } + htime.Clock = clock.Start(t) + return nil +} + func newCommandeer(mustHaveConfigFile, failOnInitErr, running bool, h *hugoBuilderCommon, f flagsToConfigHandler, cfgInit func(c *commandeer) error, subCmdVs ...*cobra.Command) (*commandeer, error) { var rebuildDebouncer func(f func()) if running { @@ -341,6 +359,11 @@ func (c *commandeer) loadConfig() error { c.configFiles = configFiles + err = c.initClock() + if err != nil { + return err + } + if l, ok := c.Cfg.Get("languagesSorted").(langs.Languages); ok { c.languagesConfigured = true c.languages = l diff --git a/commands/commands.go b/commands/commands.go index 99b0866e5..97e6d2113 100644 --- a/commands/commands.go +++ b/commands/commands.go @@ -18,6 +18,7 @@ import ( "os" "time" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/loggers" hpaths "github.com/gohugoio/hugo/common/paths" @@ -151,7 +152,7 @@ built with love by spf13 and friends in Go. Complete documentation is available at https://gohugo.io/.`, RunE: func(cmd *cobra.Command, args []string) error { - defer cc.timeTrack(time.Now(), "Total") + defer cc.timeTrack(htime.Now(), "Total") cfgInit := func(c *commandeer) error { if cc.buildWatch { c.Set("disableLiveReload", true) @@ -210,6 +211,7 @@ type hugoBuilderCommon struct { buildWatch bool poll string + clock string gc bool @@ -236,7 +238,7 @@ func (cc *hugoBuilderCommon) timeTrack(start time.Time, name string) { if cc.quiet { return } - elapsed := time.Since(start) + elapsed := htime.Since(start) fmt.Printf("%s in %v ms\n", name, int(1000*elapsed.Seconds())) } @@ -279,6 +281,7 @@ func (cc *hugoBuilderCommon) handleCommonBuilderFlags(cmd *cobra.Command) { cmd.PersistentFlags().StringVarP(&cc.environment, "environment", "e", "", "build environment") cmd.PersistentFlags().StringP("themesDir", "", "", "filesystem path to themes directory") cmd.PersistentFlags().StringP("ignoreVendorPaths", "", "", "ignores any _vendor for module paths matching the given Glob pattern") + cmd.PersistentFlags().StringVar(&cc.clock, "clock", "", "set clock inside hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00") } func (cc *hugoBuilderCommon) handleFlags(cmd *cobra.Command) { diff --git a/commands/hugo.go b/commands/hugo.go index 6bd0605db..43ec7e5c7 100644 --- a/commands/hugo.go +++ b/commands/hugo.go @@ -33,6 +33,7 @@ import ( "github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/tpl" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/hugofs" @@ -187,6 +188,7 @@ func initializeFlags(cmd *cobra.Command, cfg config.Provider) { "buildDrafts", "buildFuture", "buildExpired", + "clock", "uglyURLs", "canonifyURLs", "enableRobotsTXT", @@ -679,7 +681,7 @@ func (c *commandeer) firstPathSpec() *helpers.PathSpec { } func (c *commandeer) timeTrack(start time.Time, name string) { - elapsed := time.Since(start) + elapsed := htime.Since(start) c.logger.Printf("%s in %v ms", name, int(1000*elapsed.Seconds())) } @@ -790,7 +792,7 @@ func (c *commandeer) fullRebuild(changeType string) { time.Sleep(2 * time.Second) }() - defer c.timeTrack(time.Now(), "Rebuilt") + defer c.timeTrack(htime.Now(), "Rebuilt") c.commandeerHugoState = newCommandeerHugoState() err := c.loadConfig() @@ -900,7 +902,7 @@ func (c *commandeer) printChangeDetected(typ string) { c.logger.Println(msg) const layout = "2006-01-02 15:04:05.000 -0700" - c.logger.Println(time.Now().Format(layout)) + c.logger.Println(htime.Now().Format(layout)) } const ( @@ -1135,7 +1137,7 @@ func (c *commandeer) handleEvents(watcher *watcher.Batcher, c.changeDetector.PrepareNew() func() { - defer c.timeTrack(time.Now(), "Total") + defer c.timeTrack(htime.Now(), "Total") if err := c.rebuildSites(dynamicEvents); err != nil { c.handleBuildErr(err, "Rebuild failed") } diff --git a/commands/hugo_test.go b/commands/hugo_test.go index bdad25cfc..61160b7dd 100644 --- a/commands/hugo_test.go +++ b/commands/hugo_test.go @@ -29,7 +29,6 @@ import ( // Issue #5662 func TestHugoWithContentDirOverride(t *testing.T) { - t.Parallel() c := qt.New(t) files := ` @@ -51,7 +50,6 @@ Page: {{ .Title }}| // Issue #9794 func TestHugoStaticFilesMultipleStaticAndManyFolders(t *testing.T) { - t.Parallel() c := qt.New(t) files := ` @@ -95,6 +93,36 @@ Home. } +// Issue #8787 +func TestHugoListCommandsWithClockFlag(t *testing.T) { + c := qt.New(t) + + files := ` +-- config.toml -- +baseURL = "https://example.org" +title = "Hugo Commands" +-- content/past.md -- +--- +title: "Past" +date: 2000-11-06 +--- +-- content/future.md -- +--- +title: "Future" +date: 2200-11-06 +--- +-- layouts/_default/single.html -- +Page: {{ .Title }}| + +` + s := newTestHugoCmdBuilder(c, files, []string{"list", "future"}).Build() + p := filepath.Join("content", "future.md") + s.AssertStdout(p + ",2200-11-06T00:00:00Z") + + s = newTestHugoCmdBuilder(c, files, []string{"list", "future", "--clock", "2300-11-06"}).Build() + s.AssertStdout("") +} + type testHugoCmdBuilder struct { *qt.C @@ -102,6 +130,7 @@ type testHugoCmdBuilder struct { dir string files string args []string + out string } func newTestHugoCmdBuilder(c *qt.C, files string, args []string) *testHugoCmdBuilder { @@ -127,8 +156,12 @@ func (s *testHugoCmdBuilder) Build() *testHugoCmdBuilder { args := append(s.args, "-s="+s.dir, "--quiet") cmd.SetArgs(args) - _, err := cmd.ExecuteC() + out, err := captureStdout(func() error { + _, err := cmd.ExecuteC() + return err + }) s.Assert(err, qt.IsNil) + s.out = out return s } @@ -149,3 +182,9 @@ func (s *testHugoCmdBuilder) AssertFileContent(filename string, matches ...strin } } } + +func (s *testHugoCmdBuilder) AssertStdout(match string) { + s.Helper() + content := strings.TrimSpace(s.out) + s.Assert(content, qt.Contains, strings.TrimSpace(match)) +} diff --git a/commands/import_jekyll.go b/commands/import_jekyll.go index 4f17b2e39..232df519c 100644 --- a/commands/import_jekyll.go +++ b/commands/import_jekyll.go @@ -28,6 +28,7 @@ import ( "github.com/gohugoio/hugo/parser/pageparser" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/parser/metadecoders" @@ -362,12 +363,12 @@ func parseJekyllFilename(filename string) (time.Time, string, error) { re := regexp.MustCompile(`(\d+-\d+-\d+)-(.+)\..*`) r := re.FindAllStringSubmatch(filename, -1) if len(r) == 0 { - return time.Now(), "", errors.New("filename not match") + return htime.Now(), "", errors.New("filename not match") } postDate, err := time.Parse("2006-1-2", r[0][1]) if err != nil { - return time.Now(), "", err + return htime.Now(), "", err } postName := r[0][2] diff --git a/commands/list.go b/commands/list.go index f4321d031..4b62c91c5 100644 --- a/commands/list.go +++ b/commands/list.go @@ -99,6 +99,10 @@ List requires a subcommand, e.g. ` + "`hugo list drafts`.", return newSystemError("Error building sites", err) } + if err != nil { + return newSystemError("Error building sites", err) + } + writer := csv.NewWriter(os.Stdout) defer writer.Flush() @@ -127,6 +131,10 @@ List requires a subcommand, e.g. ` + "`hugo list drafts`.", return newSystemError("Error building sites", err) } + if err != nil { + return newSystemError("Error building sites", err) + } + writer := csv.NewWriter(os.Stdout) defer writer.Flush() diff --git a/commands/list_test.go b/commands/list_test.go index 56a3ee9b9..8b2535571 100644 --- a/commands/list_test.go +++ b/commands/list_test.go @@ -34,9 +34,9 @@ func TestListAll(t *testing.T) { hugoCmd := newCommandsBuilder().addAll().build() cmd := hugoCmd.getCommand() - defer func() { + t.Cleanup(func() { os.RemoveAll(dir) - }() + }) cmd.SetArgs([]string{"-s=" + dir, "list", "all"}) diff --git a/commands/new_theme.go b/commands/new_theme.go index 9b1a4786c..4e2357b55 100644 --- a/commands/new_theme.go +++ b/commands/new_theme.go @@ -18,8 +18,8 @@ import ( "errors" "path/filepath" "strings" - "time" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/spf13/cobra" @@ -113,7 +113,7 @@ func (n *newThemeCmd) newTheme(cmd *cobra.Command, args []string) error { by := []byte(`The MIT License (MIT) -Copyright (c) ` + time.Now().Format("2006") + ` YOUR_NAME_HERE +Copyright (c) ` + htime.Now().Format("2006") + ` YOUR_NAME_HERE Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/commands/server.go b/commands/server.go index 985775336..73e5cf073 100644 --- a/commands/server.go +++ b/commands/server.go @@ -33,6 +33,7 @@ import ( "syscall" "time" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/paths" "golang.org/x/sync/errgroup" @@ -255,7 +256,7 @@ func (sc *serverCmd) server(cmd *cobra.Command, args []string) error { } err = func() error { - defer c.timeTrack(time.Now(), "Built") + defer c.timeTrack(htime.Now(), "Built") err := c.serverBuild() if err != nil { cmd.PrintErrln("Error:", err.Error()) @@ -668,13 +669,13 @@ func memStats() error { go func() { var stats runtime.MemStats - start := time.Now().UnixNano() + start := htime.Now().UnixNano() for { runtime.ReadMemStats(&stats) if fileMemStats != nil { fileMemStats.WriteString(fmt.Sprintf("%d\t%d\t%d\t%d\t%d\n", - (time.Now().UnixNano()-start)/1000000, stats.HeapSys, stats.HeapAlloc, stats.HeapIdle, stats.HeapReleased)) + (htime.Now().UnixNano()-start)/1000000, stats.HeapSys, stats.HeapAlloc, stats.HeapIdle, stats.HeapReleased)) time.Sleep(interval) } else { break diff --git a/common/htime/time.go b/common/htime/time.go index 552608b6f..d854e9312 100644 --- a/common/htime/time.go +++ b/common/htime/time.go @@ -17,6 +17,7 @@ import ( "strings" "time" + "github.com/bep/clock" "github.com/spf13/cast" toml "github.com/pelletier/go-toml/v2" @@ -74,6 +75,7 @@ var ( "November", "December", } + Clock = clock.Start(time.Now()) ) func NewTimeFormatter(ltr locales.Translator) TimeFormatter { @@ -148,3 +150,13 @@ func ToTimeInDefaultLocationE(i any, location *time.Location) (tim time.Time, er } return cast.ToTimeInDefaultLocationE(i, location) } + +// Now returns time.Now() or time value based on`clock` flag. +// Use this function to fake time inside hugo. +func Now() time.Time { + return Clock.Now() +} + +func Since(t time.Time) time.Duration { + return Clock.Now().Sub(t) +} diff --git a/common/loggers/loggers.go b/common/loggers/loggers.go index 14c76ae45..6b73c9f32 100644 --- a/common/loggers/loggers.go +++ b/common/loggers/loggers.go @@ -24,6 +24,7 @@ import ( "runtime" "time" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/terminal" jww "github.com/spf13/jwalterweatherman" @@ -176,7 +177,7 @@ func (l *logger) Out() io.Writer { // PrintTimerIfDelayed prints a time statement to the FEEDBACK logger // if considerable time is spent. func (l *logger) PrintTimerIfDelayed(start time.Time, name string) { - elapsed := time.Since(start) + elapsed := htime.Since(start) milli := int(1000 * elapsed.Seconds()) if milli < 500 { return @@ -185,7 +186,7 @@ func (l *logger) PrintTimerIfDelayed(start time.Time, name string) { } func (l *logger) PrintTimer(start time.Time, name string) { - elapsed := time.Since(start) + elapsed := htime.Since(start) milli := int(1000 * elapsed.Seconds()) l.Printf("%s in %v ms", name, milli) } diff --git a/go.mod b/go.mod index 1a59f901d..2637fcc0a 100644 --- a/go.mod +++ b/go.mod @@ -91,6 +91,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.4.0 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.7.0 // indirect github.com/aws/smithy-go v1.8.0 // indirect + github.com/bep/clock v0.1.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/dlclark/regexp2 v1.4.0 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect diff --git a/go.sum b/go.sum index 6c4fd2d72..9d0e2b812 100644 --- a/go.sum +++ b/go.sum @@ -212,6 +212,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.7.0/go.mod h1:0qcSMCyASQPN2sk/1KQLQ2 github.com/aws/smithy-go v1.8.0 h1:AEwwwXQZtUwP5Mz506FeXXrKBe0jA8gVM+1gEcSRooc= github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/bep/clock v0.1.0 h1:sdvJ08SsgwTY/ejA705YKBlktFfj2uVpmQSSQspZJ2c= +github.com/bep/clock v0.1.0/go.mod h1:shVP9tZ3cXpbVj60SnlU1pMwKjFxECBRm9vZfpoA0Gs= github.com/bep/debounce v1.2.0 h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo= github.com/bep/debounce v1.2.0/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= github.com/bep/gitmap v1.1.2 h1:zk04w1qc1COTZPPYWDQHvns3y1afOsdRfraFQ3qI840= diff --git a/hugofs/fileinfo.go b/hugofs/fileinfo.go index af37fce7e..d923d632d 100644 --- a/hugofs/fileinfo.go +++ b/hugofs/fileinfo.go @@ -31,6 +31,7 @@ import ( "errors" "github.com/gohugoio/hugo/common/hreflect" + "github.com/gohugoio/hugo/common/htime" "github.com/spf13/afero" ) @@ -203,7 +204,7 @@ func newDirNameOnlyFileInfo(name string, meta *FileMeta, fileOpener func() (afer m.IsOrdered = false return NewFileMetaInfo( - &dirNameOnlyFileInfo{name: base, modTime: time.Now()}, + &dirNameOnlyFileInfo{name: base, modTime: htime.Now()}, m, ) } diff --git a/hugolib/content_factory.go b/hugolib/content_factory.go index e6e82979f..0a4d0aa0a 100644 --- a/hugolib/content_factory.go +++ b/hugolib/content_factory.go @@ -20,6 +20,7 @@ import ( "strings" "time" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/source" @@ -70,7 +71,7 @@ func (f ContentFactory) ApplyArchetypeTemplate(w io.Writer, p page.Page, archety d := &archetypeFileData{ Type: archetypeKind, - Date: time.Now().Format(time.RFC3339), + Date: htime.Now().Format(time.RFC3339), Page: p, File: p.File(), } diff --git a/hugolib/page_test.go b/hugolib/page_test.go index 84e54306a..05a1c3d77 100644 --- a/hugolib/page_test.go +++ b/hugolib/page_test.go @@ -22,12 +22,14 @@ import ( "testing" "time" + "github.com/bep/clock" "github.com/gohugoio/hugo/htesting" "github.com/gohugoio/hugo/markup/asciidocext" "github.com/gohugoio/hugo/markup/rst" "github.com/gohugoio/hugo/config" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/hugofs" @@ -1536,7 +1538,6 @@ Content. } func TestShouldBuild(t *testing.T) { - t.Parallel() past := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC) future := time.Date(2037, 11, 17, 20, 34, 58, 651387237, time.UTC) zero := time.Time{} @@ -1582,6 +1583,54 @@ func TestShouldBuild(t *testing.T) { } } +func TestShouldBuildWithClock(t *testing.T) { + htime.Clock = clock.Start(time.Date(2021, 11, 17, 20, 34, 58, 651387237, time.UTC)) + t.Cleanup(func() { htime.Clock = clock.Start(time.Now()) }) + past := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC) + future := time.Date(2037, 11, 17, 20, 34, 58, 651387237, time.UTC) + zero := time.Time{} + + publishSettings := []struct { + buildFuture bool + buildExpired bool + buildDrafts bool + draft bool + publishDate time.Time + expiryDate time.Time + out bool + }{ + // publishDate and expiryDate + {false, false, false, false, zero, zero, true}, + {false, false, false, false, zero, future, true}, + {false, false, false, false, past, zero, true}, + {false, false, false, false, past, future, true}, + {false, false, false, false, past, past, false}, + {false, false, false, false, future, future, false}, + {false, false, false, false, future, past, false}, + + // buildFuture and buildExpired + {false, true, false, false, past, past, true}, + {true, true, false, false, past, past, true}, + {true, false, false, false, past, past, false}, + {true, false, false, false, future, future, true}, + {true, true, false, false, future, future, true}, + {false, true, false, false, future, past, false}, + + // buildDrafts and draft + {true, true, false, true, past, future, false}, + {true, true, true, true, past, future, true}, + {true, true, true, true, past, future, true}, + } + + for _, ps := range publishSettings { + s := shouldBuild(ps.buildFuture, ps.buildExpired, ps.buildDrafts, ps.draft, + ps.publishDate, ps.expiryDate) + if s != ps.out { + t.Errorf("AssertShouldBuildWithClock unexpected output with params: %+v", ps) + } + } +} + // "dot" in path: #1885 and #2110 // disablePathToLower regression: #3374 func TestPathIssues(t *testing.T) { diff --git a/hugolib/site.go b/hugolib/site.go index cf7f0ff82..cbfc4d836 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -30,6 +30,7 @@ import ( "strings" "time" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/modules" @@ -1910,10 +1911,11 @@ func shouldBuild(buildFuture bool, buildExpired bool, buildDrafts bool, Draft bo if !(buildDrafts || !Draft) { return false } - if !buildFuture && !publishDate.IsZero() && publishDate.After(time.Now()) { + hnow := htime.Now() + if !buildFuture && !publishDate.IsZero() && publishDate.After(hnow) { return false } - if !buildExpired && !expiryDate.IsZero() && expiryDate.Before(time.Now()) { + if !buildExpired && !expiryDate.IsZero() && expiryDate.Before(hnow) { return false } return true diff --git a/metrics/metrics.go b/metrics/metrics.go index 9c46fdf7e..471f48a04 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -25,6 +25,7 @@ import ( "sync" "time" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/compare" "github.com/gohugoio/hugo/helpers" @@ -129,7 +130,7 @@ func (s *Store) TrackValue(key string, value any, cached bool) { // MeasureSince adds a measurement for key to the metric store. func (s *Store) MeasureSince(key string, start time.Time) { s.mu.Lock() - s.metrics[key] = append(s.metrics[key], time.Since(start)) + s.metrics[key] = append(s.metrics[key], htime.Since(start)) s.mu.Unlock() } diff --git a/modules/collect.go b/modules/collect.go index ff83f9ecc..4f5b1c36f 100644 --- a/modules/collect.go +++ b/modules/collect.go @@ -23,6 +23,7 @@ import ( "time" "github.com/bep/debounce" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/loggers" "github.com/spf13/cast" @@ -505,7 +506,7 @@ func (c *collector) applyThemeConfig(tc *moduleAdapter) error { } func (c *collector) collect() { - defer c.logger.PrintTimerIfDelayed(time.Now(), "hugo: collected modules") + defer c.logger.PrintTimerIfDelayed(htime.Now(), "hugo: collected modules") d := debounce.New(2 * time.Second) d(func() { c.logger.Println("hugo: downloading modules …") diff --git a/resources/resource/dates.go b/resources/resource/dates.go index b43f35c64..6d19ca7b9 100644 --- a/resources/resource/dates.go +++ b/resources/resource/dates.go @@ -13,7 +13,11 @@ package resource -import "time" +import ( + "time" + + "github.com/gohugoio/hugo/common/htime" +) var _ Dated = Dates{} @@ -55,7 +59,8 @@ func IsFuture(d Dated) bool { if d.PublishDate().IsZero() { return false } - return d.PublishDate().After(time.Now()) + + return d.PublishDate().After(htime.Now()) } // IsExpired returns whether the argument is expired. @@ -63,7 +68,7 @@ func IsExpired(d Dated) bool { if d.ExpiryDate().IsZero() { return false } - return d.ExpiryDate().Before(time.Now()) + return d.ExpiryDate().Before(htime.Now()) } // IsZeroDates returns true if all of the dates are zero. diff --git a/tpl/collections/collections.go b/tpl/collections/collections.go index 516e2c272..8fdc85275 100644 --- a/tpl/collections/collections.go +++ b/tpl/collections/collections.go @@ -35,6 +35,7 @@ import ( ) func init() { + // htime.Now cannot be used here rand.Seed(time.Now().UTC().UnixNano()) } diff --git a/tpl/partials/partials.go b/tpl/partials/partials.go index eb4ebfe32..9ded32a71 100644 --- a/tpl/partials/partials.go +++ b/tpl/partials/partials.go @@ -25,8 +25,8 @@ import ( "reflect" "strings" "sync" - "time" + "github.com/gohugoio/hugo/common/htime" texttemplate "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate" "github.com/gohugoio/hugo/helpers" @@ -222,7 +222,7 @@ func createKey(name string, variants ...any) (partialCacheKey, error) { var errUnHashable = errors.New("unhashable") func (ns *Namespace) getOrCreate(ctx context.Context, key partialCacheKey, context any) (result any, err error) { - start := time.Now() + start := htime.Now() defer func() { if r := recover(); r != nil { err = r.(error) diff --git a/tpl/time/init.go b/tpl/time/init.go index 4bb2ddf67..7dd71f210 100644 --- a/tpl/time/init.go +++ b/tpl/time/init.go @@ -28,6 +28,7 @@ func init() { if d.Language == nil { panic("Language must be set") } + ctx := New(langs.GetTimeFormatter(d.Language), langs.GetLocation(d.Language)) ns := &internal.TemplateFuncsNamespace{ diff --git a/tpl/time/time.go b/tpl/time/time.go index 623b7206a..cd78b83aa 100644 --- a/tpl/time/time.go +++ b/tpl/time/time.go @@ -68,9 +68,9 @@ func (ns *Namespace) Format(layout string, v any) (string, error) { return ns.timeFormatter.Format(t, layout), nil } -// Now returns the current local time. +// Now returns the current local time or `clock` time func (ns *Namespace) Now() _time.Time { - return _time.Now() + return htime.Now() } // ParseDuration parses the duration string s. diff --git a/tpl/tplimpl/template.go b/tpl/tplimpl/template.go index c092ff638..d352f02e8 100644 --- a/tpl/tplimpl/template.go +++ b/tpl/tplimpl/template.go @@ -27,10 +27,10 @@ import ( "sort" "strings" "sync" - "time" "unicode" "unicode/utf8" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/helpers" @@ -235,7 +235,7 @@ func (t *templateExec) ExecuteWithContext(ctx context.Context, templ tpl.Templat defer rlocker.RUnlock() } if t.Metrics != nil { - defer t.Metrics.MeasureSince(templ.Name(), time.Now()) + defer t.Metrics.MeasureSince(templ.Name(), htime.Now()) } if t.templateUsageTracker != nil { -- cgit v1.2.3