modules: Add noVendor to module config
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 9 Sep 2020 19:10:28 +0000 (21:10 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 10 Sep 2020 06:47:05 +0000 (08:47 +0200)
Fixes #7647

cache/filecache/filecache_test.go
docs/content/en/hugo-modules/configuration.md
hugolib/filesystems/basefs_test.go
modules/client.go
modules/client_test.go
modules/config.go

index 5a5dac9830e93cf04e01fcb862cf8b01262616c1..00b4e55734f818bd08211a3e5eb091c8d53d9ea7 100644 (file)
@@ -25,6 +25,8 @@ import (
        "testing"
        "time"
 
+       "github.com/gobwas/glob"
+
        "github.com/gohugoio/hugo/langs"
        "github.com/gohugoio/hugo/modules"
 
@@ -314,12 +316,13 @@ func initConfig(fs afero.Fs, cfg config.Provider) error {
        if !filepath.IsAbs(themesDir) {
                themesDir = filepath.Join(workingDir, themesDir)
        }
+       globAll := glob.MustCompile("**", '/')
        modulesClient := modules.NewClient(modules.ClientConfig{
                Fs:           fs,
                WorkingDir:   workingDir,
                ThemesDir:    themesDir,
                ModuleConfig: modConfig,
-               IgnoreVendor: true,
+               IgnoreVendor: globAll,
        })
 
        moduleConfig, err := modulesClient.Collect()
index c97e8d5a2c8ba7abf9cf5a92200797c5c0c2801c..2fb4ec5e67bef5b11f401f6b980d8136c1d9c2f3 100644 (file)
@@ -18,11 +18,16 @@ toc: true
 
 {{< code-toggle file="config">}}
 [module]
+noVendor = ""
 proxy = "direct"
 noProxy = "none"
 private = "*.*"
 {{< /code-toggle >}}
 
+
+noVendor {{< new-in "0.75.0" >}}
+: A optional Glob pattern matching module paths to skip when vendoring, e.g. "github.com/**"
+
 proxy
 : Defines the proxy server to use to download remote modules. Default is `direct`, which means "git clone" and similar.
 
index e3222af48fad955c0a6e4cdecff48e6247d6fbf8..633c8fe08cfd454ea2c0bc7b22ff8b2e9cba1873 100644 (file)
@@ -21,6 +21,8 @@ import (
        "strings"
        "testing"
 
+       "github.com/gobwas/glob"
+
        "github.com/gohugoio/hugo/config"
 
        "github.com/gohugoio/hugo/langs"
@@ -49,12 +51,13 @@ func initConfig(fs afero.Fs, cfg config.Provider) error {
        if !filepath.IsAbs(themesDir) {
                themesDir = filepath.Join(workingDir, themesDir)
        }
+       globAll := glob.MustCompile("**", '/')
        modulesClient := modules.NewClient(modules.ClientConfig{
                Fs:           fs,
                WorkingDir:   workingDir,
                ThemesDir:    themesDir,
                ModuleConfig: modConfig,
-               IgnoreVendor: true,
+               IgnoreVendor: globAll,
        })
 
        moduleConfig, err := modulesClient.Collect()
index 86f8a2caaf82447ad521a5c9105dc6259731909b..d71c48f0c51f4624b8c78ebd7af782f9a5db0a10 100644 (file)
@@ -26,9 +26,10 @@ import (
        "path/filepath"
        "regexp"
 
-       "github.com/gobwas/glob"
        hglob "github.com/gohugoio/hugo/hugofs/glob"
 
+       "github.com/gobwas/glob"
+
        "github.com/gohugoio/hugo/hugofs"
 
        "github.com/gohugoio/hugo/hugofs/files"
@@ -100,10 +101,16 @@ func NewClient(cfg ClientConfig) *Client {
                logger = loggers.NewWarningLogger()
        }
 
+       var noVendor glob.Glob
+       if cfg.ModuleConfig.NoVendor != "" {
+               noVendor, _ = hglob.GetGlob(hglob.NormalizePath(cfg.ModuleConfig.NoVendor))
+       }
+
        return &Client{
                fs:                fs,
                ccfg:              cfg,
                logger:            logger,
+               noVendor:          noVendor,
                moduleConfig:      mcfg,
                environ:           env,
                GoModulesFilename: goModFilename}
@@ -114,6 +121,8 @@ type Client struct {
        fs     afero.Fs
        logger *loggers.Logger
 
+       noVendor glob.Glob
+
        ccfg ClientConfig
 
        // The top level module config
@@ -220,6 +229,10 @@ func (c *Client) Vendor() error {
                        continue
                }
 
+               if !c.shouldVendor(t.Path()) {
+                       continue
+               }
+
                if !t.IsGoMod() && !t.Vendor() {
                        // We currently do not vendor components living in the
                        // theme directory, see https://github.com/gohugoio/hugo/issues/5993
@@ -596,6 +609,10 @@ func (c *Client) tidy(mods Modules, goModOnly bool) error {
        return nil
 }
 
+func (c *Client) shouldVendor(path string) bool {
+       return c.noVendor == nil || !c.noVendor.Match(path)
+}
+
 // ClientConfig configures the module Client.
 type ClientConfig struct {
        Fs     afero.Fs
index d5da621d1d228970452e80d53aad36416bee0db2..41509a9ed99ebf7644496ef46c855175007bf0d5 100644 (file)
@@ -19,8 +19,6 @@ import (
 
        "github.com/gohugoio/hugo/hugofs/glob"
 
-       "github.com/gohugoio/hugo/common/hugo"
-
        "github.com/gohugoio/hugo/htesting"
 
        "github.com/gohugoio/hugo/hugofs"
@@ -29,77 +27,109 @@ import (
 )
 
 func TestClient(t *testing.T) {
-       if hugo.GoMinorVersion() < 12 {
-               // https://github.com/golang/go/issues/26794
-               // There were some concurrent issues with Go modules in < Go 12.
-               t.Skip("skip this for Go <= 1.11 due to a bug in Go's stdlib")
-       }
-
-       t.Parallel()
 
        modName := "hugo-modules-basic-test"
        modPath := "github.com/gohugoio/tests/" + modName
-       modConfig := DefaultModuleConfig
-       modConfig.Imports = []Import{Import{Path: "github.com/gohugoio/hugoTestModules1_darwin/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)
 
-       workingDir, clean, err := htesting.CreateTempDir(hugofs.Os, modName)
-       c.Assert(err, qt.IsNil)
-       defer clean()
+       newClient := func(c *qt.C, withConfig func(cfg *ClientConfig)) (*Client, func()) {
 
-       client := NewClient(ClientConfig{
-               Fs:           hugofs.Os,
-               WorkingDir:   workingDir,
-               ModuleConfig: modConfig,
-       })
+               workingDir, clean, err := htesting.CreateTempDir(hugofs.Os, modName)
+               c.Assert(err, qt.IsNil)
+
+               ccfg := ClientConfig{
+                       Fs:         hugofs.Os,
+                       WorkingDir: workingDir,
+               }
 
-       // Test Init
-       c.Assert(client.Init(modPath), qt.IsNil)
+               withConfig(&ccfg)
+               ccfg.ModuleConfig.Imports = []Import{Import{Path: "github.com/gohugoio/hugoTestModules1_darwin/modh2_2"}}
+               client := NewClient(ccfg)
 
-       // Test Collect
-       mc, err := client.Collect()
-       c.Assert(err, qt.IsNil)
-       c.Assert(len(mc.AllModules), qt.Equals, 4)
-       for _, m := range mc.AllModules {
-               c.Assert(m, qt.Not(qt.IsNil))
+               return client, clean
        }
 
-       // Test Graph
-       var graphb bytes.Buffer
-       c.Assert(client.Graph(&graphb), qt.IsNil)
+       c.Run("All", func(c *qt.C) {
+               client, clean := newClient(c, func(cfg *ClientConfig) {
+                       cfg.ModuleConfig = DefaultModuleConfig
+               })
+               defer clean()
 
-       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
-`
+               // Test Init
+               c.Assert(client.Init(modPath), qt.IsNil)
+
+               // Test Collect
+               mc, err := client.Collect()
+               c.Assert(err, qt.IsNil)
+               c.Assert(len(mc.AllModules), qt.Equals, 4)
+               for _, m := range mc.AllModules {
+                       c.Assert(m, qt.Not(qt.IsNil))
+               }
+
+               // Test Graph
+               var graphb bytes.Buffer
+               c.Assert(client.Graph(&graphb), qt.IsNil)
+
+               c.Assert(graphb.String(), qt.Equals, expect)
 
-       c.Assert(graphb.String(), qt.Equals, expect)
+               // Test Vendor
+               c.Assert(client.Vendor(), qt.IsNil)
+               graphb.Reset()
+               c.Assert(client.Graph(&graphb), qt.IsNil)
 
-       // Test Vendor
-       c.Assert(client.Vendor(), qt.IsNil)
-       graphb.Reset()
-       c.Assert(client.Graph(&graphb), qt.IsNil)
-       expectVendored := `project github.com/gohugoio/hugoTestModules1_darwin/modh2_2@v1.4.0+vendor
+               expectVendored := `project github.com/gohugoio/hugoTestModules1_darwin/modh2_2@v1.4.0+vendor
 project github.com/gohugoio/hugoTestModules1_darwin/modh2_2_1v@v1.3.0+vendor
 project github.com/gohugoio/hugoTestModules1_darwin/modh2_2_2@v1.3.0+vendor
 `
-       c.Assert(graphb.String(), qt.Equals, expectVendored)
-
-       // Test the ignoreVendor setting
-       clientIgnoreVendor := NewClient(ClientConfig{
-               Fs:           hugofs.Os,
-               WorkingDir:   workingDir,
-               ModuleConfig: modConfig,
-               IgnoreVendor: globAll,
+
+               c.Assert(graphb.String(), qt.Equals, expectVendored)
+
+               // Test Tidy
+               c.Assert(client.Tidy(), qt.IsNil)
+
        })
 
-       graphb.Reset()
-       c.Assert(clientIgnoreVendor.Graph(&graphb), qt.IsNil)
-       c.Assert(graphb.String(), qt.Equals, expect)
+       c.Run("IgnoreVendor", func(c *qt.C) {
+               client, clean := newClient(
+                       c, func(cfg *ClientConfig) {
+                               cfg.ModuleConfig = DefaultModuleConfig
+                               cfg.IgnoreVendor = globAll
+                       })
+               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.Equals, expect)
+       })
 
-       // Test Tidy
-       c.Assert(client.Tidy(), qt.IsNil)
+       c.Run("NoVendor", func(c *qt.C) {
+               mcfg := DefaultModuleConfig
+               mcfg.NoVendor = "**"
+               client, clean := newClient(
+                       c, func(cfg *ClientConfig) {
+                               cfg.ModuleConfig = mcfg
+                       })
+               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.Equals, expect)
+       })
 
 }
 
index 5e95f0ac1038555992e18cd6ebd801b67e0c9a77..1964479f46cde4aa50ae16c158d45a3acbc75bf3 100644 (file)
@@ -227,6 +227,10 @@ type Config struct {
        // Will be validated against the running Hugo version.
        HugoVersion HugoVersion
 
+       // A optional Glob pattern matching module paths to skip when vendoring, e.g.
+       // "github.com/**".
+       NoVendor string
+
        // Configures GOPROXY.
        Proxy string
        // Configures GONOPROXY.