From 56deebb3e43b3ab6f18fdc62350cc2fc8d08cce7 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 16 Jul 2018 21:37:44 -0400 Subject: [PATCH] cmd/go: add clean -modcache We need an easy way to remove $GOPATH/src/mod, especially since all the directories are marked read-only. Change-Id: Ib9e8e47e50048f55ecc4de0229b06c4a416ac114 Reviewed-on: https://go-review.googlesource.com/124382 Run-TryBot: Russ Cox Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/clean/clean.go | 32 +++++++++++++++++++++++++++++- src/cmd/go/mod_test.go | 5 +++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/internal/clean/clean.go b/src/cmd/go/internal/clean/clean.go index fa5af944af..40cb324ac2 100644 --- a/src/cmd/go/internal/clean/clean.go +++ b/src/cmd/go/internal/clean/clean.go @@ -17,11 +17,12 @@ import ( "cmd/go/internal/cache" "cmd/go/internal/cfg" "cmd/go/internal/load" + "cmd/go/internal/modfetch" "cmd/go/internal/work" ) var CmdClean = &base.Command{ - UsageLine: "clean [-i] [-r] [-n] [-x] [-cache] [-testcache] [build flags] [packages]", + UsageLine: "clean [clean flags] [build flags] [packages]", Short: "remove object files and cached files", Long: ` Clean removes object files from package source directories. @@ -65,6 +66,10 @@ The -cache flag causes clean to remove the entire go build cache. The -testcache flag causes clean to expire all test results in the go build cache. +The -modcache flag causes clean to remove the entire module +download cache, including unpacked source code of versioned +dependencies. + For more about build flags, see 'go help build'. For more about specifying packages, see 'go help packages'. @@ -75,6 +80,7 @@ var ( cleanI bool // clean -i flag cleanR bool // clean -r flag cleanCache bool // clean -cache flag + cleanModcache bool // clean -modcache flag cleanTestcache bool // clean -testcache flag ) @@ -85,6 +91,7 @@ func init() { CmdClean.Flag.BoolVar(&cleanI, "i", false, "") CmdClean.Flag.BoolVar(&cleanR, "r", false, "") CmdClean.Flag.BoolVar(&cleanCache, "cache", false, "") + CmdClean.Flag.BoolVar(&cleanModcache, "modcache", false, "") CmdClean.Flag.BoolVar(&cleanTestcache, "testcache", false, "") // -n and -x are important enough to be @@ -138,6 +145,29 @@ func runClean(cmd *base.Command, args []string) { } } } + + if cleanModcache { + if modfetch.SrcMod == "" { + base.Fatalf("go clean -modcache: no module cache") + } + if err := removeAll(modfetch.SrcMod); err != nil { + base.Errorf("go clean -modcache: %v", err) + } + } +} + +func removeAll(dir string) error { + // Module cache has 0555 directories; make them writable in order to remove content. + filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return nil // ignore errors walking in file system + } + if info.IsDir() { + os.Chmod(path, 0777) + } + return nil + }) + return os.RemoveAll(dir) } var cleaned = map[*load.Package]bool{} diff --git a/src/cmd/go/mod_test.go b/src/cmd/go/mod_test.go index a15832faca..3e8a01090b 100644 --- a/src/cmd/go/mod_test.go +++ b/src/cmd/go/mod_test.go @@ -1067,6 +1067,11 @@ func TestModList(t *testing.T) { t.Fatalf("%s should be unwritable", filepath.Join(dir, "buggy")) } + tg.run("clean", "-modcache") + if _, err = os.Stat(dir); err == nil { + t.Fatal("clean -modcache did not remove download dir") + } + tg.must(ioutil.WriteFile(tg.path("x/go.mod"), []byte(` module x require rsc.io/quote v1.5.1 -- 2.50.0