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