@@ -17,11 +17,12 @@ import (
1717 "cmd/go/internal/cache"
1818 "cmd/go/internal/cfg"
1919 "cmd/go/internal/load"
20+ "cmd/go/internal/modfetch"
2021 "cmd/go/internal/work"
2122)
2223
2324var CmdClean = & base.Command {
24- UsageLine : "clean [-i] [-r] [-n] [-x] [-cache] [-testcache ] [build flags] [packages]" ,
25+ UsageLine : "clean [clean flags ] [build flags] [packages]" ,
2526 Short : "remove object files and cached files" ,
2627 Long : `
2728Clean removes object files from package source directories.
@@ -65,6 +66,10 @@ The -cache flag causes clean to remove the entire go build cache.
6566The -testcache flag causes clean to expire all test results in the
6667go build cache.
6768
69+ The -modcache flag causes clean to remove the entire module
70+ download cache, including unpacked source code of versioned
71+ dependencies.
72+
6873For more about build flags, see 'go help build'.
6974
7075For more about specifying packages, see 'go help packages'.
7580 cleanI bool // clean -i flag
7681 cleanR bool // clean -r flag
7782 cleanCache bool // clean -cache flag
83+ cleanModcache bool // clean -modcache flag
7884 cleanTestcache bool // clean -testcache flag
7985)
8086
@@ -85,6 +91,7 @@ func init() {
8591 CmdClean .Flag .BoolVar (& cleanI , "i" , false , "" )
8692 CmdClean .Flag .BoolVar (& cleanR , "r" , false , "" )
8793 CmdClean .Flag .BoolVar (& cleanCache , "cache" , false , "" )
94+ CmdClean .Flag .BoolVar (& cleanModcache , "modcache" , false , "" )
8895 CmdClean .Flag .BoolVar (& cleanTestcache , "testcache" , false , "" )
8996
9097 // -n and -x are important enough to be
@@ -138,6 +145,29 @@ func runClean(cmd *base.Command, args []string) {
138145 }
139146 }
140147 }
148+
149+ if cleanModcache {
150+ if modfetch .SrcMod == "" {
151+ base .Fatalf ("go clean -modcache: no module cache" )
152+ }
153+ if err := removeAll (modfetch .SrcMod ); err != nil {
154+ base .Errorf ("go clean -modcache: %v" , err )
155+ }
156+ }
157+ }
158+
159+ func removeAll (dir string ) error {
160+ // Module cache has 0555 directories; make them writable in order to remove content.
161+ filepath .Walk (dir , func (path string , info os.FileInfo , err error ) error {
162+ if err != nil {
163+ return nil // ignore errors walking in file system
164+ }
165+ if info .IsDir () {
166+ os .Chmod (path , 0777 )
167+ }
168+ return nil
169+ })
170+ return os .RemoveAll (dir )
141171}
142172
143173var cleaned = map [* load.Package ]bool {}
0 commit comments