mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-29 19:12:09 -05:00
281 lines
7.7 KiB
Go
281 lines
7.7 KiB
Go
// Copyright 2019 The Hugo Authors. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package commands
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
|
|
"github.com/gohugoio/hugo/modules"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var _ cmder = (*modCmd)(nil)
|
|
|
|
type modCmd struct {
|
|
*baseBuilderCmd
|
|
}
|
|
|
|
func (c *modCmd) newVerifyCmd() *cobra.Command {
|
|
var clean bool
|
|
|
|
verifyCmd := &cobra.Command{
|
|
Use: "verify",
|
|
Short: "Verify dependencies.",
|
|
Long: `Verify checks that the dependencies of the current module, which are stored in a local downloaded source cache, have not been modified since being downloaded.
|
|
`,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return c.withModsClient(true, func(c *modules.Client) error {
|
|
return c.Verify(clean)
|
|
})
|
|
},
|
|
}
|
|
|
|
verifyCmd.Flags().BoolVarP(&clean, "clean", "", false, "delete module cache for dependencies that fail verification")
|
|
|
|
return verifyCmd
|
|
}
|
|
|
|
var moduleNotFoundRe = regexp.MustCompile("module.*not found")
|
|
|
|
func (c *modCmd) newCleanCmd() *cobra.Command {
|
|
var pattern string
|
|
var all bool
|
|
cmd := &cobra.Command{
|
|
Use: "clean",
|
|
Short: "Delete the Hugo Module cache for the current project.",
|
|
Long: `Delete the Hugo Module cache for the current project.
|
|
|
|
Note that after you run this command, all of your dependencies will be re-downloaded next time you run "hugo".
|
|
|
|
Also note that if you configure a positive maxAge for the "modules" file cache, it will also be cleaned as part of "hugo --gc".
|
|
|
|
`,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
if all {
|
|
com, err := c.initConfig(false)
|
|
|
|
if err != nil && !moduleNotFoundRe.MatchString(err.Error()) {
|
|
return err
|
|
}
|
|
|
|
_, err = com.hugo().FileCaches.ModulesCache().Prune(true)
|
|
return err
|
|
}
|
|
return c.withModsClient(true, func(c *modules.Client) error {
|
|
return c.Clean(pattern)
|
|
})
|
|
},
|
|
}
|
|
|
|
cmd.Flags().StringVarP(&pattern, "pattern", "", "", `pattern matching module paths to clean (all if not set), e.g. "**hugo*"`)
|
|
cmd.Flags().BoolVarP(&all, "all", "", false, "clean entire module cache")
|
|
|
|
return cmd
|
|
}
|
|
|
|
func (b *commandsBuilder) newModCmd() *modCmd {
|
|
|
|
c := &modCmd{}
|
|
|
|
const commonUsage = `
|
|
Note that Hugo will always start out by resolving the components defined in the site
|
|
configuration, provided by a _vendor directory (if no --ignoreVendor flag provided),
|
|
Go Modules, or a folder inside the themes directory, in that order.
|
|
|
|
See https://gohugo.io/hugo-modules/ for more information.
|
|
|
|
`
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "mod",
|
|
Short: "Various Hugo Modules helpers.",
|
|
Long: `Various helpers to help manage the modules in your project's dependency graph.
|
|
|
|
Most operations here requires a Go version installed on your system (>= Go 1.12) and the relevant VCS client (typically Git).
|
|
This is not needed if you only operate on modules inside /themes or if you have vendored them via "hugo mod vendor".
|
|
|
|
` + commonUsage,
|
|
|
|
RunE: nil,
|
|
}
|
|
|
|
cmd.AddCommand(
|
|
&cobra.Command{
|
|
Use: "get",
|
|
DisableFlagParsing: true,
|
|
Short: "Resolves dependencies in your current Hugo Project.",
|
|
Long: `
|
|
Resolves dependencies in your current Hugo Project.
|
|
|
|
Some examples:
|
|
|
|
Install the latest version possible for a given module:
|
|
|
|
hugo mod get github.com/gohugoio/testshortcodes
|
|
|
|
Install a specific version:
|
|
|
|
hugo mod get github.com/gohugoio/testshortcodes@v0.3.0
|
|
|
|
Install the latest versions of all module dependencies:
|
|
|
|
hugo mod get -u
|
|
hugo mod get -u ./... (recursive)
|
|
|
|
Run "go help get" for more information. All flags available for "go get" is also relevant here.
|
|
` + commonUsage,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
// We currently just pass on the flags we get to Go and
|
|
// need to do the flag handling manually.
|
|
if len(args) == 1 && args[0] == "-h" {
|
|
return cmd.Help()
|
|
}
|
|
|
|
var lastArg string
|
|
if len(args) != 0 {
|
|
lastArg = args[len(args)-1]
|
|
}
|
|
|
|
if lastArg == "./..." {
|
|
args = args[:len(args)-1]
|
|
// Do a recursive update.
|
|
dirname, err := os.Getwd()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Sanity check. We do recursive walking and want to avoid
|
|
// accidents.
|
|
if len(dirname) < 5 {
|
|
return errors.New("must not be run from the file system root")
|
|
}
|
|
|
|
filepath.Walk(dirname, func(path string, info os.FileInfo, err error) error {
|
|
if info.IsDir() {
|
|
return nil
|
|
}
|
|
|
|
if info.Name() == "go.mod" {
|
|
// Found a module.
|
|
dir := filepath.Dir(path)
|
|
fmt.Println("Update module in", dir)
|
|
c.source = dir
|
|
err := c.withModsClient(false, func(c *modules.Client) error {
|
|
if len(args) == 1 && args[0] == "-h" {
|
|
return cmd.Help()
|
|
}
|
|
return c.Get(args...)
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
return c.withModsClient(false, func(c *modules.Client) error {
|
|
return c.Get(args...)
|
|
})
|
|
},
|
|
},
|
|
&cobra.Command{
|
|
Use: "graph",
|
|
Short: "Print a module dependency graph.",
|
|
Long: `Print a module dependency graph with information about module status (disabled, vendored).
|
|
Note that for vendored modules, that is the version listed and not the one from go.mod.
|
|
`,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return c.withModsClient(true, func(c *modules.Client) error {
|
|
return c.Graph(os.Stdout)
|
|
})
|
|
},
|
|
},
|
|
&cobra.Command{
|
|
Use: "init",
|
|
Short: "Initialize this project as a Hugo Module.",
|
|
Long: `Initialize this project as a Hugo Module.
|
|
It will try to guess the module path, but you may help by passing it as an argument, e.g:
|
|
|
|
hugo mod init github.com/gohugoio/testshortcodes
|
|
|
|
Note that Hugo Modules supports multi-module projects, so you can initialize a Hugo Module
|
|
inside a subfolder on GitHub, as one example.
|
|
`,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
var path string
|
|
if len(args) >= 1 {
|
|
path = args[0]
|
|
}
|
|
return c.withModsClient(false, func(c *modules.Client) error {
|
|
return c.Init(path)
|
|
})
|
|
},
|
|
},
|
|
&cobra.Command{
|
|
Use: "vendor",
|
|
Short: "Vendor all module dependencies into the _vendor directory.",
|
|
Long: `Vendor all module dependencies into the _vendor directory.
|
|
|
|
If a module is vendored, that is where Hugo will look for it's dependencies.
|
|
`,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return c.withModsClient(true, func(c *modules.Client) error {
|
|
return c.Vendor()
|
|
})
|
|
},
|
|
},
|
|
c.newVerifyCmd(),
|
|
&cobra.Command{
|
|
Use: "tidy",
|
|
Short: "Remove unused entries in go.mod and go.sum.",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return c.withModsClient(true, func(c *modules.Client) error {
|
|
return c.Tidy()
|
|
})
|
|
},
|
|
},
|
|
c.newCleanCmd(),
|
|
)
|
|
|
|
c.baseBuilderCmd = b.newBuilderCmd(cmd)
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
func (c *modCmd) withModsClient(failOnMissingConfig bool, f func(*modules.Client) error) error {
|
|
com, err := c.initConfig(failOnMissingConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return f(com.hugo().ModulesClient)
|
|
}
|
|
|
|
func (c *modCmd) initConfig(failOnNoConfig bool) (*commandeer, error) {
|
|
com, err := initializeConfig(failOnNoConfig, false, &c.hugoBuilderCommon, c, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return com, nil
|
|
}
|