mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
parent
f2946da9e8
commit
e77ca3c105
26 changed files with 193 additions and 37 deletions
3
cache/filecache/filecache.go
vendored
3
cache/filecache/filecache.go
vendored
|
@ -24,6 +24,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/common/hugio"
|
"github.com/gohugoio/hugo/common/hugio"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
|
@ -295,7 +296,7 @@ func (c *Cache) isExpired(modTime time.Time) bool {
|
||||||
if c.maxAge < 0 {
|
if c.maxAge < 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return c.maxAge == 0 || time.Since(modTime) > c.maxAge
|
return c.maxAge == 0 || htime.Since(modTime) > c.maxAge
|
||||||
}
|
}
|
||||||
|
|
||||||
// For testing
|
// For testing
|
||||||
|
|
|
@ -15,6 +15,7 @@ package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
@ -28,9 +29,11 @@ import (
|
||||||
"golang.org/x/sync/semaphore"
|
"golang.org/x/sync/semaphore"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/herrors"
|
"github.com/gohugoio/hugo/common/herrors"
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/common/hugo"
|
"github.com/gohugoio/hugo/common/hugo"
|
||||||
"github.com/gohugoio/hugo/common/paths"
|
"github.com/gohugoio/hugo/common/paths"
|
||||||
|
|
||||||
|
"github.com/spf13/cast"
|
||||||
jww "github.com/spf13/jwalterweatherman"
|
jww "github.com/spf13/jwalterweatherman"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/loggers"
|
"github.com/gohugoio/hugo/common/loggers"
|
||||||
|
@ -41,6 +44,7 @@ import (
|
||||||
"github.com/gohugoio/hugo/hugolib"
|
"github.com/gohugoio/hugo/hugolib"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
|
|
||||||
|
"github.com/bep/clock"
|
||||||
"github.com/bep/debounce"
|
"github.com/bep/debounce"
|
||||||
"github.com/bep/overlayfs"
|
"github.com/bep/overlayfs"
|
||||||
"github.com/gohugoio/hugo/common/types"
|
"github.com/gohugoio/hugo/common/types"
|
||||||
|
@ -164,6 +168,20 @@ func (c *commandeer) initFs(fs *hugofs.Fs) error {
|
||||||
return nil
|
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) {
|
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())
|
var rebuildDebouncer func(f func())
|
||||||
if running {
|
if running {
|
||||||
|
@ -341,6 +359,11 @@ func (c *commandeer) loadConfig() error {
|
||||||
|
|
||||||
c.configFiles = configFiles
|
c.configFiles = configFiles
|
||||||
|
|
||||||
|
err = c.initClock()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if l, ok := c.Cfg.Get("languagesSorted").(langs.Languages); ok {
|
if l, ok := c.Cfg.Get("languagesSorted").(langs.Languages); ok {
|
||||||
c.languagesConfigured = true
|
c.languagesConfigured = true
|
||||||
c.languages = l
|
c.languages = l
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/common/hugo"
|
"github.com/gohugoio/hugo/common/hugo"
|
||||||
"github.com/gohugoio/hugo/common/loggers"
|
"github.com/gohugoio/hugo/common/loggers"
|
||||||
hpaths "github.com/gohugoio/hugo/common/paths"
|
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/.`,
|
Complete documentation is available at https://gohugo.io/.`,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
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 {
|
cfgInit := func(c *commandeer) error {
|
||||||
if cc.buildWatch {
|
if cc.buildWatch {
|
||||||
c.Set("disableLiveReload", true)
|
c.Set("disableLiveReload", true)
|
||||||
|
@ -210,6 +211,7 @@ type hugoBuilderCommon struct {
|
||||||
|
|
||||||
buildWatch bool
|
buildWatch bool
|
||||||
poll string
|
poll string
|
||||||
|
clock string
|
||||||
|
|
||||||
gc bool
|
gc bool
|
||||||
|
|
||||||
|
@ -236,7 +238,7 @@ func (cc *hugoBuilderCommon) timeTrack(start time.Time, name string) {
|
||||||
if cc.quiet {
|
if cc.quiet {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
elapsed := time.Since(start)
|
elapsed := htime.Since(start)
|
||||||
fmt.Printf("%s in %v ms\n", name, int(1000*elapsed.Seconds()))
|
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().StringVarP(&cc.environment, "environment", "e", "", "build environment")
|
||||||
cmd.PersistentFlags().StringP("themesDir", "", "", "filesystem path to themes directory")
|
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().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) {
|
func (cc *hugoBuilderCommon) handleFlags(cmd *cobra.Command) {
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"github.com/gohugoio/hugo/hugofs/files"
|
"github.com/gohugoio/hugo/hugofs/files"
|
||||||
"github.com/gohugoio/hugo/tpl"
|
"github.com/gohugoio/hugo/tpl"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/common/types"
|
"github.com/gohugoio/hugo/common/types"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/hugofs"
|
"github.com/gohugoio/hugo/hugofs"
|
||||||
|
@ -187,6 +188,7 @@ func initializeFlags(cmd *cobra.Command, cfg config.Provider) {
|
||||||
"buildDrafts",
|
"buildDrafts",
|
||||||
"buildFuture",
|
"buildFuture",
|
||||||
"buildExpired",
|
"buildExpired",
|
||||||
|
"clock",
|
||||||
"uglyURLs",
|
"uglyURLs",
|
||||||
"canonifyURLs",
|
"canonifyURLs",
|
||||||
"enableRobotsTXT",
|
"enableRobotsTXT",
|
||||||
|
@ -679,7 +681,7 @@ func (c *commandeer) firstPathSpec() *helpers.PathSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *commandeer) timeTrack(start time.Time, name string) {
|
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()))
|
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)
|
time.Sleep(2 * time.Second)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
defer c.timeTrack(time.Now(), "Rebuilt")
|
defer c.timeTrack(htime.Now(), "Rebuilt")
|
||||||
|
|
||||||
c.commandeerHugoState = newCommandeerHugoState()
|
c.commandeerHugoState = newCommandeerHugoState()
|
||||||
err := c.loadConfig()
|
err := c.loadConfig()
|
||||||
|
@ -900,7 +902,7 @@ func (c *commandeer) printChangeDetected(typ string) {
|
||||||
|
|
||||||
c.logger.Println(msg)
|
c.logger.Println(msg)
|
||||||
const layout = "2006-01-02 15:04:05.000 -0700"
|
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 (
|
const (
|
||||||
|
@ -1135,7 +1137,7 @@ func (c *commandeer) handleEvents(watcher *watcher.Batcher,
|
||||||
c.changeDetector.PrepareNew()
|
c.changeDetector.PrepareNew()
|
||||||
|
|
||||||
func() {
|
func() {
|
||||||
defer c.timeTrack(time.Now(), "Total")
|
defer c.timeTrack(htime.Now(), "Total")
|
||||||
if err := c.rebuildSites(dynamicEvents); err != nil {
|
if err := c.rebuildSites(dynamicEvents); err != nil {
|
||||||
c.handleBuildErr(err, "Rebuild failed")
|
c.handleBuildErr(err, "Rebuild failed")
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ import (
|
||||||
|
|
||||||
// Issue #5662
|
// Issue #5662
|
||||||
func TestHugoWithContentDirOverride(t *testing.T) {
|
func TestHugoWithContentDirOverride(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
|
|
||||||
files := `
|
files := `
|
||||||
|
@ -51,7 +50,6 @@ Page: {{ .Title }}|
|
||||||
|
|
||||||
// Issue #9794
|
// Issue #9794
|
||||||
func TestHugoStaticFilesMultipleStaticAndManyFolders(t *testing.T) {
|
func TestHugoStaticFilesMultipleStaticAndManyFolders(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
|
|
||||||
files := `
|
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 {
|
type testHugoCmdBuilder struct {
|
||||||
*qt.C
|
*qt.C
|
||||||
|
|
||||||
|
@ -102,6 +130,7 @@ type testHugoCmdBuilder struct {
|
||||||
dir string
|
dir string
|
||||||
files string
|
files string
|
||||||
args []string
|
args []string
|
||||||
|
out string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestHugoCmdBuilder(c *qt.C, files string, args []string) *testHugoCmdBuilder {
|
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")
|
args := append(s.args, "-s="+s.dir, "--quiet")
|
||||||
cmd.SetArgs(args)
|
cmd.SetArgs(args)
|
||||||
|
|
||||||
_, err := cmd.ExecuteC()
|
out, err := captureStdout(func() error {
|
||||||
|
_, err := cmd.ExecuteC()
|
||||||
|
return err
|
||||||
|
})
|
||||||
s.Assert(err, qt.IsNil)
|
s.Assert(err, qt.IsNil)
|
||||||
|
s.out = out
|
||||||
|
|
||||||
return s
|
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))
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import (
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/parser/pageparser"
|
"github.com/gohugoio/hugo/parser/pageparser"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/common/hugio"
|
"github.com/gohugoio/hugo/common/hugio"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/parser/metadecoders"
|
"github.com/gohugoio/hugo/parser/metadecoders"
|
||||||
|
@ -362,12 +363,12 @@ func parseJekyllFilename(filename string) (time.Time, string, error) {
|
||||||
re := regexp.MustCompile(`(\d+-\d+-\d+)-(.+)\..*`)
|
re := regexp.MustCompile(`(\d+-\d+-\d+)-(.+)\..*`)
|
||||||
r := re.FindAllStringSubmatch(filename, -1)
|
r := re.FindAllStringSubmatch(filename, -1)
|
||||||
if len(r) == 0 {
|
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])
|
postDate, err := time.Parse("2006-1-2", r[0][1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Now(), "", err
|
return htime.Now(), "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
postName := r[0][2]
|
postName := r[0][2]
|
||||||
|
|
|
@ -99,6 +99,10 @@ List requires a subcommand, e.g. ` + "`hugo list drafts`.",
|
||||||
return newSystemError("Error building sites", err)
|
return newSystemError("Error building sites", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return newSystemError("Error building sites", err)
|
||||||
|
}
|
||||||
|
|
||||||
writer := csv.NewWriter(os.Stdout)
|
writer := csv.NewWriter(os.Stdout)
|
||||||
defer writer.Flush()
|
defer writer.Flush()
|
||||||
|
|
||||||
|
@ -127,6 +131,10 @@ List requires a subcommand, e.g. ` + "`hugo list drafts`.",
|
||||||
return newSystemError("Error building sites", err)
|
return newSystemError("Error building sites", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return newSystemError("Error building sites", err)
|
||||||
|
}
|
||||||
|
|
||||||
writer := csv.NewWriter(os.Stdout)
|
writer := csv.NewWriter(os.Stdout)
|
||||||
defer writer.Flush()
|
defer writer.Flush()
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,9 @@ func TestListAll(t *testing.T) {
|
||||||
hugoCmd := newCommandsBuilder().addAll().build()
|
hugoCmd := newCommandsBuilder().addAll().build()
|
||||||
cmd := hugoCmd.getCommand()
|
cmd := hugoCmd.getCommand()
|
||||||
|
|
||||||
defer func() {
|
t.Cleanup(func() {
|
||||||
os.RemoveAll(dir)
|
os.RemoveAll(dir)
|
||||||
}()
|
})
|
||||||
|
|
||||||
cmd.SetArgs([]string{"-s=" + dir, "list", "all"})
|
cmd.SetArgs([]string{"-s=" + dir, "list", "all"})
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
"github.com/gohugoio/hugo/hugofs"
|
"github.com/gohugoio/hugo/hugofs"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -113,7 +113,7 @@ func (n *newThemeCmd) newTheme(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
by := []byte(`The MIT License (MIT)
|
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
|
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
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/common/paths"
|
"github.com/gohugoio/hugo/common/paths"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
|
@ -255,7 +256,7 @@ func (sc *serverCmd) server(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
err = func() error {
|
err = func() error {
|
||||||
defer c.timeTrack(time.Now(), "Built")
|
defer c.timeTrack(htime.Now(), "Built")
|
||||||
err := c.serverBuild()
|
err := c.serverBuild()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.PrintErrln("Error:", err.Error())
|
cmd.PrintErrln("Error:", err.Error())
|
||||||
|
@ -668,13 +669,13 @@ func memStats() error {
|
||||||
go func() {
|
go func() {
|
||||||
var stats runtime.MemStats
|
var stats runtime.MemStats
|
||||||
|
|
||||||
start := time.Now().UnixNano()
|
start := htime.Now().UnixNano()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
runtime.ReadMemStats(&stats)
|
runtime.ReadMemStats(&stats)
|
||||||
if fileMemStats != nil {
|
if fileMemStats != nil {
|
||||||
fileMemStats.WriteString(fmt.Sprintf("%d\t%d\t%d\t%d\t%d\n",
|
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)
|
time.Sleep(interval)
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/bep/clock"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
|
|
||||||
toml "github.com/pelletier/go-toml/v2"
|
toml "github.com/pelletier/go-toml/v2"
|
||||||
|
@ -74,6 +75,7 @@ var (
|
||||||
"November",
|
"November",
|
||||||
"December",
|
"December",
|
||||||
}
|
}
|
||||||
|
Clock = clock.Start(time.Now())
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewTimeFormatter(ltr locales.Translator) TimeFormatter {
|
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)
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/common/terminal"
|
"github.com/gohugoio/hugo/common/terminal"
|
||||||
|
|
||||||
jww "github.com/spf13/jwalterweatherman"
|
jww "github.com/spf13/jwalterweatherman"
|
||||||
|
@ -176,7 +177,7 @@ func (l *logger) Out() io.Writer {
|
||||||
// PrintTimerIfDelayed prints a time statement to the FEEDBACK logger
|
// PrintTimerIfDelayed prints a time statement to the FEEDBACK logger
|
||||||
// if considerable time is spent.
|
// if considerable time is spent.
|
||||||
func (l *logger) PrintTimerIfDelayed(start time.Time, name string) {
|
func (l *logger) PrintTimerIfDelayed(start time.Time, name string) {
|
||||||
elapsed := time.Since(start)
|
elapsed := htime.Since(start)
|
||||||
milli := int(1000 * elapsed.Seconds())
|
milli := int(1000 * elapsed.Seconds())
|
||||||
if milli < 500 {
|
if milli < 500 {
|
||||||
return
|
return
|
||||||
|
@ -185,7 +186,7 @@ func (l *logger) PrintTimerIfDelayed(start time.Time, name string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *logger) PrintTimer(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())
|
milli := int(1000 * elapsed.Seconds())
|
||||||
l.Printf("%s in %v ms", name, milli)
|
l.Printf("%s in %v ms", name, milli)
|
||||||
}
|
}
|
||||||
|
|
1
go.mod
1
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/sso v1.4.0 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.7.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/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/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
|
|
2
go.sum
2
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 h1:AEwwwXQZtUwP5Mz506FeXXrKBe0jA8gVM+1gEcSRooc=
|
||||||
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
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/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 h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo=
|
||||||
github.com/bep/debounce v1.2.0/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
|
github.com/bep/debounce v1.2.0/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
|
||||||
github.com/bep/gitmap v1.1.2 h1:zk04w1qc1COTZPPYWDQHvns3y1afOsdRfraFQ3qI840=
|
github.com/bep/gitmap v1.1.2 h1:zk04w1qc1COTZPPYWDQHvns3y1afOsdRfraFQ3qI840=
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/hreflect"
|
"github.com/gohugoio/hugo/common/hreflect"
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
)
|
)
|
||||||
|
@ -203,7 +204,7 @@ func newDirNameOnlyFileInfo(name string, meta *FileMeta, fileOpener func() (afer
|
||||||
m.IsOrdered = false
|
m.IsOrdered = false
|
||||||
|
|
||||||
return NewFileMetaInfo(
|
return NewFileMetaInfo(
|
||||||
&dirNameOnlyFileInfo{name: base, modTime: time.Now()},
|
&dirNameOnlyFileInfo{name: base, modTime: htime.Now()},
|
||||||
m,
|
m,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/source"
|
"github.com/gohugoio/hugo/source"
|
||||||
|
@ -70,7 +71,7 @@ func (f ContentFactory) ApplyArchetypeTemplate(w io.Writer, p page.Page, archety
|
||||||
|
|
||||||
d := &archetypeFileData{
|
d := &archetypeFileData{
|
||||||
Type: archetypeKind,
|
Type: archetypeKind,
|
||||||
Date: time.Now().Format(time.RFC3339),
|
Date: htime.Now().Format(time.RFC3339),
|
||||||
Page: p,
|
Page: p,
|
||||||
File: p.File(),
|
File: p.File(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,12 +22,14 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/bep/clock"
|
||||||
"github.com/gohugoio/hugo/htesting"
|
"github.com/gohugoio/hugo/htesting"
|
||||||
"github.com/gohugoio/hugo/markup/asciidocext"
|
"github.com/gohugoio/hugo/markup/asciidocext"
|
||||||
"github.com/gohugoio/hugo/markup/rst"
|
"github.com/gohugoio/hugo/markup/rst"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/config"
|
"github.com/gohugoio/hugo/config"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/common/loggers"
|
"github.com/gohugoio/hugo/common/loggers"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/hugofs"
|
"github.com/gohugoio/hugo/hugofs"
|
||||||
|
@ -1536,7 +1538,6 @@ Content.
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShouldBuild(t *testing.T) {
|
func TestShouldBuild(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
past := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
|
past := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
|
||||||
future := time.Date(2037, 11, 17, 20, 34, 58, 651387237, time.UTC)
|
future := time.Date(2037, 11, 17, 20, 34, 58, 651387237, time.UTC)
|
||||||
zero := time.Time{}
|
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
|
// "dot" in path: #1885 and #2110
|
||||||
// disablePathToLower regression: #3374
|
// disablePathToLower regression: #3374
|
||||||
func TestPathIssues(t *testing.T) {
|
func TestPathIssues(t *testing.T) {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/common/hugio"
|
"github.com/gohugoio/hugo/common/hugio"
|
||||||
"github.com/gohugoio/hugo/common/types"
|
"github.com/gohugoio/hugo/common/types"
|
||||||
"github.com/gohugoio/hugo/modules"
|
"github.com/gohugoio/hugo/modules"
|
||||||
|
@ -1910,10 +1911,11 @@ func shouldBuild(buildFuture bool, buildExpired bool, buildDrafts bool, Draft bo
|
||||||
if !(buildDrafts || !Draft) {
|
if !(buildDrafts || !Draft) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !buildFuture && !publishDate.IsZero() && publishDate.After(time.Now()) {
|
hnow := htime.Now()
|
||||||
|
if !buildFuture && !publishDate.IsZero() && publishDate.After(hnow) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !buildExpired && !expiryDate.IsZero() && expiryDate.Before(time.Now()) {
|
if !buildExpired && !expiryDate.IsZero() && expiryDate.Before(hnow) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/common/types"
|
"github.com/gohugoio/hugo/common/types"
|
||||||
"github.com/gohugoio/hugo/compare"
|
"github.com/gohugoio/hugo/compare"
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"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.
|
// MeasureSince adds a measurement for key to the metric store.
|
||||||
func (s *Store) MeasureSince(key string, start time.Time) {
|
func (s *Store) MeasureSince(key string, start time.Time) {
|
||||||
s.mu.Lock()
|
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()
|
s.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bep/debounce"
|
"github.com/bep/debounce"
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/common/loggers"
|
"github.com/gohugoio/hugo/common/loggers"
|
||||||
|
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
|
@ -505,7 +506,7 @@ func (c *collector) applyThemeConfig(tc *moduleAdapter) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *collector) collect() {
|
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 := debounce.New(2 * time.Second)
|
||||||
d(func() {
|
d(func() {
|
||||||
c.logger.Println("hugo: downloading modules …")
|
c.logger.Println("hugo: downloading modules …")
|
||||||
|
|
|
@ -13,7 +13,11 @@
|
||||||
|
|
||||||
package resource
|
package resource
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
|
)
|
||||||
|
|
||||||
var _ Dated = Dates{}
|
var _ Dated = Dates{}
|
||||||
|
|
||||||
|
@ -55,7 +59,8 @@ func IsFuture(d Dated) bool {
|
||||||
if d.PublishDate().IsZero() {
|
if d.PublishDate().IsZero() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return d.PublishDate().After(time.Now())
|
|
||||||
|
return d.PublishDate().After(htime.Now())
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsExpired returns whether the argument is expired.
|
// IsExpired returns whether the argument is expired.
|
||||||
|
@ -63,7 +68,7 @@ func IsExpired(d Dated) bool {
|
||||||
if d.ExpiryDate().IsZero() {
|
if d.ExpiryDate().IsZero() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return d.ExpiryDate().Before(time.Now())
|
return d.ExpiryDate().Before(htime.Now())
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsZeroDates returns true if all of the dates are zero.
|
// IsZeroDates returns true if all of the dates are zero.
|
||||||
|
|
|
@ -35,6 +35,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
// htime.Now cannot be used here
|
||||||
rand.Seed(time.Now().UTC().UnixNano())
|
rand.Seed(time.Now().UTC().UnixNano())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
texttemplate "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate"
|
texttemplate "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
|
@ -222,7 +222,7 @@ func createKey(name string, variants ...any) (partialCacheKey, error) {
|
||||||
var errUnHashable = errors.New("unhashable")
|
var errUnHashable = errors.New("unhashable")
|
||||||
|
|
||||||
func (ns *Namespace) getOrCreate(ctx context.Context, key partialCacheKey, context any) (result any, err error) {
|
func (ns *Namespace) getOrCreate(ctx context.Context, key partialCacheKey, context any) (result any, err error) {
|
||||||
start := time.Now()
|
start := htime.Now()
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
err = r.(error)
|
err = r.(error)
|
||||||
|
|
|
@ -28,6 +28,7 @@ func init() {
|
||||||
if d.Language == nil {
|
if d.Language == nil {
|
||||||
panic("Language must be set")
|
panic("Language must be set")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := New(langs.GetTimeFormatter(d.Language), langs.GetLocation(d.Language))
|
ctx := New(langs.GetTimeFormatter(d.Language), langs.GetLocation(d.Language))
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
|
|
|
@ -68,9 +68,9 @@ func (ns *Namespace) Format(layout string, v any) (string, error) {
|
||||||
return ns.timeFormatter.Format(t, layout), nil
|
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 {
|
func (ns *Namespace) Now() _time.Time {
|
||||||
return _time.Now()
|
return htime.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDuration parses the duration string s.
|
// ParseDuration parses the duration string s.
|
||||||
|
|
|
@ -27,10 +27,10 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/htime"
|
||||||
"github.com/gohugoio/hugo/common/types"
|
"github.com/gohugoio/hugo/common/types"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
|
@ -235,7 +235,7 @@ func (t *templateExec) ExecuteWithContext(ctx context.Context, templ tpl.Templat
|
||||||
defer rlocker.RUnlock()
|
defer rlocker.RUnlock()
|
||||||
}
|
}
|
||||||
if t.Metrics != nil {
|
if t.Metrics != nil {
|
||||||
defer t.Metrics.MeasureSince(templ.Name(), time.Now())
|
defer t.Metrics.MeasureSince(templ.Name(), htime.Now())
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.templateUsageTracker != nil {
|
if t.templateUsageTracker != nil {
|
||||||
|
|
Loading…
Reference in a new issue