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