mirror of
				https://github.com/gohugoio/hugo.git
				synced 2024-05-11 05:54:58 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			293 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			293 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2020 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/hugolib"
 | |
| 
 | |
| 	"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(newModNPMCmd(c))
 | |
| 
 | |
| 	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) withHugo(f func(*hugolib.HugoSites) error) error {
 | |
| 	com, err := c.initConfig(true)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return f(com.hugo())
 | |
| }
 | |
| 
 | |
| 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
 | |
| }
 |