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 moduleLoaderState := modload.NewState()
54 printed := false
55 gofmt := gofmtPath()
56
57 gofmtArgs := []string{gofmt, "-l", "-w"}
58 gofmtArgLen := len(gofmt) + len(" -l -w")
59
60 baseGofmtArgs := len(gofmtArgs)
61 baseGofmtArgLen := gofmtArgLen
62
63 for _, pkg := range load.PackagesAndErrors(moduleLoaderState, ctx, load.PackageOpts{}, args) {
64 if moduleLoaderState.Enabled() && pkg.Module != nil && !pkg.Module.Main {
65 if !printed {
66 fmt.Fprintf(os.Stderr, "go: not formatting packages in dependency modules\n")
67 printed = true
68 }
69 continue
70 }
71 if pkg.Error != nil {
72 if _, ok := errors.AsType[*load.NoGoError](pkg.Error); ok {
73
74 } else if _, ok := errors.AsType[*load.EmbedError](pkg.Error); ok && len(pkg.InternalAllGoFiles()) > 0 {
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