summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2021-02-14 19:24:13 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2021-02-16 16:30:01 +0100
commitbdfbcf6f4b4ab53a617ab76f72e8aa28da6067de (patch)
treea5b2fb8aeabe9103bb44b2516533f2c498806d08
parentb60e9279ab95030828eb4f822be96250284c4d8d (diff)
modules: Add config option modules.vendorClosest
Fixes #8235 Fixes #8242
-rw-r--r--docs/content/en/hugo-modules/configuration.md3
-rw-r--r--hugofs/glob/glob.go10
-rw-r--r--modules/client_test.go42
-rw-r--r--modules/collect.go11
-rw-r--r--modules/config.go7
5 files changed, 64 insertions, 9 deletions
diff --git a/docs/content/en/hugo-modules/configuration.md b/docs/content/en/hugo-modules/configuration.md
index 5405e4e51..f82902ebb 100644
--- a/docs/content/en/hugo-modules/configuration.md
+++ b/docs/content/en/hugo-modules/configuration.md
@@ -29,6 +29,9 @@ replacements = ""
noVendor {{< new-in "0.75.0" >}}
: A optional Glob pattern matching module paths to skip when vendoring, e.g. "github.com/**"
+vendorClosest {{< new-in "0.81.0" >}}
+: When enabled, we will pick the vendored module closest to the module using it. The default behaviour is to pick the first. Note that there can still be only one dependency of a given module path, so once it is in use it cannot be redefined.
+
proxy
: Defines the proxy server to use to download remote modules. Default is `direct`, which means "git clone" and similar.
diff --git a/hugofs/glob/glob.go b/hugofs/glob/glob.go
index 5d2d3d5e5..57115ddfa 100644
--- a/hugofs/glob/glob.go
+++ b/hugofs/glob/glob.go
@@ -33,6 +33,14 @@ var (
globMu sync.RWMutex
)
+type caseInsensitiveGlob struct {
+ g glob.Glob
+}
+
+func (g caseInsensitiveGlob) Match(s string) bool {
+ return g.g.Match(strings.ToLower(s))
+
+}
func GetGlob(pattern string) (glob.Glob, error) {
var eg globErr
@@ -46,7 +54,7 @@ func GetGlob(pattern string) (glob.Glob, error) {
var err error
g, err := glob.Compile(strings.ToLower(pattern), '/')
- eg = globErr{g, err}
+ eg = globErr{caseInsensitiveGlob{g: g}, err}
globMu.Lock()
globCache[pattern] = eg
diff --git a/modules/client_test.go b/modules/client_test.go
index c7a07fb87..f801af07d 100644
--- a/modules/client_test.go
+++ b/modules/client_test.go
@@ -18,6 +18,7 @@ import (
"fmt"
"os"
"path/filepath"
+ "sync/atomic"
"testing"
"github.com/gohugoio/hugo/hugofs/glob"
@@ -32,15 +33,18 @@ import (
func TestClient(t *testing.T) {
modName := "hugo-modules-basic-test"
modPath := "github.com/gohugoio/tests/" + modName
+ defaultImport := "modh2_2"
expect := `github.com/gohugoio/tests/hugo-modules-basic-test github.com/gohugoio/hugoTestModules1_darwin/modh2_2@v1.4.0
github.com/gohugoio/hugoTestModules1_darwin/modh2_2@v1.4.0 github.com/gohugoio/hugoTestModules1_darwin/modh2_2_1v@v1.3.0
github.com/gohugoio/hugoTestModules1_darwin/modh2_2@v1.4.0 github.com/gohugoio/hugoTestModules1_darwin/modh2_2_2@v1.3.0
`
c := qt.New(t)
+ var clientID uint64 // we increment this to get each test in its own directory.
- newClient := func(c *qt.C, withConfig func(cfg *ClientConfig)) (*Client, func()) {
- workingDir, clean, err := htesting.CreateTempDir(hugofs.Os, modName)
+ newClient := func(c *qt.C, withConfig func(cfg *ClientConfig), imp string) (*Client, func()) {
+ atomic.AddUint64(&clientID, uint64(1))
+ workingDir, clean, err := htesting.CreateTempDir(hugofs.Os, fmt.Sprintf("%s-%d", modName, clientID))
c.Assert(err, qt.IsNil)
themesDir := filepath.Join(workingDir, "themes")
err = os.Mkdir(themesDir, 0777)
@@ -53,7 +57,7 @@ github.com/gohugoio/hugoTestModules1_darwin/modh2_2@v1.4.0 github.com/gohugoio/h
}
withConfig(&ccfg)
- ccfg.ModuleConfig.Imports = []Import{{Path: "github.com/gohugoio/hugoTestModules1_darwin/modh2_2"}}
+ ccfg.ModuleConfig.Imports = []Import{{Path: "github.com/gohugoio/hugoTestModules1_darwin/" + imp}}
client := NewClient(ccfg)
return client, clean
@@ -62,7 +66,7 @@ github.com/gohugoio/hugoTestModules1_darwin/modh2_2@v1.4.0 github.com/gohugoio/h
c.Run("All", func(c *qt.C) {
client, clean := newClient(c, func(cfg *ClientConfig) {
cfg.ModuleConfig = DefaultModuleConfig
- })
+ }, defaultImport)
defer clean()
// Test Init
@@ -103,7 +107,7 @@ project github.com/gohugoio/hugoTestModules1_darwin/modh2_2_2@v1.3.0+vendor
c, func(cfg *ClientConfig) {
cfg.ModuleConfig = DefaultModuleConfig
cfg.IgnoreVendor = globAll
- })
+ }, defaultImport)
defer clean()
c.Assert(client.Init(modPath), qt.IsNil)
@@ -122,7 +126,7 @@ project github.com/gohugoio/hugoTestModules1_darwin/modh2_2_2@v1.3.0+vendor
client, clean := newClient(
c, func(cfg *ClientConfig) {
cfg.ModuleConfig = mcfg
- })
+ }, defaultImport)
defer clean()
c.Assert(client.Init(modPath), qt.IsNil)
@@ -135,13 +139,37 @@ project github.com/gohugoio/hugoTestModules1_darwin/modh2_2_2@v1.3.0+vendor
c.Assert(graphb.String(), qt.Equals, expect)
})
+ c.Run("VendorClosest", func(c *qt.C) {
+ mcfg := DefaultModuleConfig
+ mcfg.VendorClosest = true
+
+ client, clean := newClient(
+ c, func(cfg *ClientConfig) {
+ cfg.ModuleConfig = mcfg
+ s := "github.com/gohugoio/hugoTestModules1_darwin/modh1_1v"
+ g, _ := glob.GetGlob(s)
+ cfg.IgnoreVendor = g
+ }, "modh1v")
+ defer clean()
+
+ c.Assert(client.Init(modPath), qt.IsNil)
+ _, err := client.Collect()
+ c.Assert(err, qt.IsNil)
+ c.Assert(client.Vendor(), qt.IsNil)
+
+ var graphb bytes.Buffer
+ c.Assert(client.Graph(&graphb), qt.IsNil)
+
+ c.Assert(graphb.String(), qt.Contains, "github.com/gohugoio/hugoTestModules1_darwin/modh1_1v@v1.3.0 github.com/gohugoio/hugoTestModules1_darwin/modh1_1_1v@v1.1.0+vendor")
+ })
+
// https://github.com/gohugoio/hugo/issues/7908
c.Run("createThemeDirname", func(c *qt.C) {
mcfg := DefaultModuleConfig
client, clean := newClient(
c, func(cfg *ClientConfig) {
cfg.ModuleConfig = mcfg
- })
+ }, defaultImport)
defer clean()
dirname, err := client.createThemeDirname("foo", false)
diff --git a/modules/collect.go b/modules/collect.go
index 4de51258b..db79f434e 100644
--- a/modules/collect.go
+++ b/modules/collect.go
@@ -531,7 +531,16 @@ func (c *collector) collectModulesTXT(owner Module) error {
return errors.Errorf("invalid modules list: %q", filename)
}
path := parts[0]
- if _, found := c.vendored[path]; !found {
+
+ shouldAdd := c.Client.moduleConfig.VendorClosest
+
+ if !shouldAdd {
+ if _, found := c.vendored[path]; !found {
+ shouldAdd = true
+ }
+ }
+
+ if shouldAdd {
c.vendored[path] = vendoredModule{
Owner: owner,
Dir: filepath.Join(vendorDir, path),
diff --git a/modules/config.go b/modules/config.go
index 106becc60..1e3e3c798 100644
--- a/modules/config.go
+++ b/modules/config.go
@@ -279,6 +279,13 @@ type Config struct {
// "github.com/**".
NoVendor string
+ // When enabled, we will pick the vendored module closest to the module
+ // using it.
+ // The default behaviour is to pick the first.
+ // Note that there can still be only one dependency of a given module path,
+ // so once it is in use it cannot be redefined.
+ VendorClosest bool
+
Replacements []string
replacementsMap map[string]string