1
2
3
4
5
6 package fmtcmd
7
8 import (
9 "context"
10 "errors"
11 "fmt"
12 "os"
13 "path/filepath"
14 "runtime"
15 "sync"
16
17 "cmd/go/internal/base"
18 "cmd/go/internal/cfg"
19 "cmd/go/internal/load"
20 "cmd/go/internal/modload"
21 "cmd/go/internal/str"
22 )
23
24 func init() {
25 base.AddBuildFlagsNX(&CmdFmt.Flag)
26 base.AddModFlag(&CmdFmt.Flag)
27 base.AddModCommonFlags(&CmdFmt.Flag)
28 }
29
30 var CmdFmt = &base.Command{
31 Run: runFmt,
32 UsageLine: "go fmt [-n] [-x] [packages]",
33 Short: "gofmt (reformat) package sources",
34 Long: `
35 Fmt runs the command 'gofmt -l -w' on the packages named
36 by the import paths. It prints the names of the files that are modified.
37
38 For more about gofmt, see 'go doc cmd/gofmt'.
39 For more about specifying packages, see 'go help packages'.
40
41 The -n flag prints commands that would be executed.
42 The -x flag prints commands as they are executed.
43
44 The -mod flag's value sets which module download mode
45 to use: readonly or vendor. See 'go help modules' for more.
46
47 To run gofmt with specific options, run gofmt itself.
48
49 See also: go fix, go vet.
50 `,
51 }
52
53 func runFmt(ctx context.Context, cmd *base.Command, args []string) {
54 printed := false
55 gofmt := gofmtPath()
56 procs := runtime.GOMAXPROCS(0)
57 var wg sync.WaitGroup
58 wg.Add(procs)
59 fileC := make(chan string, 2*procs)
60 for i := 0; i < procs; i++ {
61 go func() {
62 defer wg.Done()
63 for file := range fileC {
64 base.Run(str.StringList(gofmt, "-l", "-w", file))
65 }
66 }()
67 }
68 for _, pkg := range load.PackagesAndErrors(ctx, load.PackageOpts{}, args) {
69 if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main {
70 if !printed {
71 fmt.Fprintf(os.Stderr, "go: not formatting packages in dependency modules\n")
72 printed = true
73 }
74 continue
75 }
76 if pkg.Error != nil {
77 var nogo *load.NoGoError
78 var embed *load.EmbedError
79 if (errors.As(pkg.Error, &nogo) || errors.As(pkg.Error, &embed)) && len(pkg.InternalAllGoFiles()) > 0 {
80
81
82 } else {
83 base.Errorf("%v", pkg.Error)
84 continue
85 }
86 }
87
88
89
90 files := base.RelPaths(pkg.InternalAllGoFiles())
91 for _, file := range files {
92 fileC <- file
93 }
94 }
95 close(fileC)
96 wg.Wait()
97 }
98
99 func gofmtPath() string {
100 gofmt := "gofmt"
101 if base.ToolIsWindows {
102 gofmt += base.ToolWindowsExtension
103 }
104
105 gofmtPath := filepath.Join(cfg.GOBIN, gofmt)
106 if _, err := os.Stat(gofmtPath); err == nil {
107 return gofmtPath
108 }
109
110 gofmtPath = filepath.Join(cfg.GOROOT, "bin", gofmt)
111 if _, err := os.Stat(gofmtPath); err == nil {
112 return gofmtPath
113 }
114
115
116 return "gofmt"
117 }
118
View as plain text