github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/src/cmd/go/internal/fmtcmd/fmt.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package fmtcmd implements the ``go fmt'' command.
     6  package fmtcmd
     7  
     8  import (
     9  	"os"
    10  	"path/filepath"
    11  	"runtime"
    12  	"sync"
    13  
    14  	"cmd/go/internal/base"
    15  	"cmd/go/internal/cfg"
    16  	"cmd/go/internal/load"
    17  	"cmd/go/internal/str"
    18  )
    19  
    20  func init() {
    21  	base.AddBuildFlagsNX(&CmdFmt.Flag)
    22  }
    23  
    24  var CmdFmt = &base.Command{
    25  	Run:       runFmt,
    26  	UsageLine: "fmt [-n] [-x] [packages]",
    27  	Short:     "run gofmt on package sources",
    28  	Long: `
    29  Fmt runs the command 'gofmt -l -w' on the packages named
    30  by the import paths. It prints the names of the files that are modified.
    31  
    32  For more about gofmt, see 'go doc cmd/gofmt'.
    33  For more about specifying packages, see 'go help packages'.
    34  
    35  The -n flag prints commands that would be executed.
    36  The -x flag prints commands as they are executed.
    37  
    38  To run gofmt with specific options, run gofmt itself.
    39  
    40  See also: go fix, go vet.
    41  	`,
    42  }
    43  
    44  func runFmt(cmd *base.Command, args []string) {
    45  	gofmt := gofmtPath()
    46  	procs := runtime.GOMAXPROCS(0)
    47  	var wg sync.WaitGroup
    48  	wg.Add(procs)
    49  	fileC := make(chan string, 2*procs)
    50  	for i := 0; i < procs; i++ {
    51  		go func() {
    52  			defer wg.Done()
    53  			for file := range fileC {
    54  				base.Run(str.StringList(gofmt, "-l", "-w", file))
    55  			}
    56  		}()
    57  	}
    58  	for _, pkg := range load.Packages(args) {
    59  		// Use pkg.gofiles instead of pkg.Dir so that
    60  		// the command only applies to this package,
    61  		// not to packages in subdirectories.
    62  		files := base.FilterDotUnderscoreFiles(base.RelPaths(pkg.Internal.AllGoFiles))
    63  		for _, file := range files {
    64  			fileC <- file
    65  		}
    66  	}
    67  	close(fileC)
    68  	wg.Wait()
    69  }
    70  
    71  func gofmtPath() string {
    72  	gofmt := "gofmt"
    73  	if base.ToolIsWindows {
    74  		gofmt += base.ToolWindowsExtension
    75  	}
    76  
    77  	gofmtPath := filepath.Join(cfg.GOBIN, gofmt)
    78  	if _, err := os.Stat(gofmtPath); err == nil {
    79  		return gofmtPath
    80  	}
    81  
    82  	gofmtPath = filepath.Join(cfg.GOROOT, "bin", gofmt)
    83  	if _, err := os.Stat(gofmtPath); err == nil {
    84  		return gofmtPath
    85  	}
    86  
    87  	// fallback to looking for gofmt in $PATH
    88  	return "gofmt"
    89  }