shithub: hugo

Download patch

ref: 0b96aba022d51cf9939605c029bb8dba806653a1
parent: fa520a2d983b982394ad10088393fb303e48980a
author: Bjørn Erik Pedersen <[email protected]>
date: Wed Feb 19 05:39:36 EST 2020

commands: Add "hugo mod verify"

See #6907

--- a/cache/filecache/filecache_pruner.go
+++ b/cache/filecache/filecache_pruner.go
@@ -17,6 +17,8 @@
 	"io"
 	"os"
 
+	"github.com/gohugoio/hugo/hugofs"
+
 	"github.com/pkg/errors"
 	"github.com/spf13/afero"
 )
@@ -121,18 +123,6 @@
 		return 0, nil
 	}
 
-	counter := 0
-	// Module cache has 0555 directories; make them writable in order to remove content.
-	afero.Walk(c.Fs, c.pruneAllRootDir, func(path string, info os.FileInfo, err error) error {
-		if err != nil {
-			return nil
-		}
-		if info.IsDir() {
-			counter++
-			c.Fs.Chmod(path, 0777)
-		}
-		return nil
-	})
-	return 1, c.Fs.RemoveAll(c.pruneAllRootDir)
+	return hugofs.MakeReadableAndRemoveAllModulePkgDir(c.Fs, c.pruneAllRootDir)
 
 }
--- a/commands/mod.go
+++ b/commands/mod.go
@@ -29,7 +29,28 @@
 	*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
+}
+
 func (b *commandsBuilder) newModCmd() *modCmd {
+
 	c := &modCmd{}
 
 	const commonUsage = `
@@ -184,6 +205,7 @@
 				})
 			},
 		},
+		c.newVerifyCmd(),
 		&cobra.Command{
 			Use:   "tidy",
 			Short: "Remove unused entries in go.mod and go.sum.",
--- a/hugofs/fs.go
+++ b/hugofs/fs.go
@@ -16,6 +16,7 @@
 
 import (
 	"os"
+	"strings"
 
 	"github.com/gohugoio/hugo/config"
 	"github.com/spf13/afero"
@@ -87,4 +88,28 @@
 
 func isWrite(flag int) bool {
 	return flag&os.O_RDWR != 0 || flag&os.O_WRONLY != 0
+}
+
+// MakeReadableAndRemoveAllModulePkgDir makes any subdir in dir readable and then
+// removes the root.
+// TODO(bep) move this to a more suitable place.
+//
+func MakeReadableAndRemoveAllModulePkgDir(fs afero.Fs, dir string) (int, error) {
+	// Safe guard
+	if !strings.Contains(dir, "pkg") {
+		panic("invalid dir")
+	}
+
+	counter := 0
+	afero.Walk(fs, dir, func(path string, info os.FileInfo, err error) error {
+		if err != nil {
+			return nil
+		}
+		if info.IsDir() {
+			counter++
+			fs.Chmod(path, 0777)
+		}
+		return nil
+	})
+	return counter, fs.RemoveAll(dir)
 }
--- a/modules/client.go
+++ b/modules/client.go
@@ -24,7 +24,10 @@
 	"os"
 	"os/exec"
 	"path/filepath"
+	"regexp"
 
+	"github.com/gohugoio/hugo/hugofs"
+
 	"github.com/gohugoio/hugo/hugofs/files"
 
 	"github.com/gohugoio/hugo/common/loggers"
@@ -306,6 +309,38 @@
 	c.GoModulesFilename = filepath.Join(c.ccfg.WorkingDir, goModFilename)
 
 	return nil
+}
+
+var verifyErrorDirRe = regexp.MustCompile(`dir has been modified \((.*?)\)`)
+
+// 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.
+func (c *Client) Verify(clean bool) error {
+	// TODO1 add path to mod clean
+	err := c.runVerify()
+
+	if err != nil {
+		if clean {
+			m := verifyErrorDirRe.FindAllStringSubmatch(err.Error(), -1)
+			if m != nil {
+				for i := 0; i < len(m); i++ {
+					c, err := hugofs.MakeReadableAndRemoveAllModulePkgDir(c.fs, m[i][1])
+					if err != nil {
+						return err
+					}
+					fmt.Println("Cleaned", c)
+				}
+			}
+			// Try to verify it again.
+			err = c.runVerify()
+		}
+	}
+	return err
+}
+
+func (c *Client) runVerify() error {
+	return c.runGo(context.Background(), ioutil.Discard, "mod", "verify")
 }
 
 func isProbablyModule(path string) bool {