github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-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  	"fmt"
    10  	"os"
    11  	"path/filepath"
    12  	"runtime"
    13  	"strings"
    14  	"sync"
    15  
    16  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/base"
    17  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/cfg"
    18  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/load"
    19  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/modload"
    20  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/str"
    21  )
    22  
    23  func init() {
    24  	base.AddBuildFlagsNX(&CmdFmt.Flag)
    25  	base.AddLoadFlags(&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(cmd *base.Command, args []string) {
    52  	printed := false
    53  	gofmt := gofmtPath()
    54  	procs := runtime.GOMAXPROCS(0)
    55  	var wg sync.WaitGroup
    56  	wg.Add(procs)
    57  	fileC := make(chan string, 2*procs)
    58  	for i := 0; i < procs; i++ {
    59  		go func() {
    60  			defer wg.Done()
    61  			for file := range fileC {
    62  				base.Run(str.StringList(gofmt, "-l", "-w", file))
    63  			}
    64  		}()
    65  	}
    66  	for _, pkg := range load.PackagesAndErrors(args) {
    67  		if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main {
    68  			if !printed {
    69  				fmt.Fprintf(os.Stderr, "go: not formatting packages in dependency modules\n")
    70  				printed = true
    71  			}
    72  			continue
    73  		}
    74  		if pkg.Error != nil {
    75  			if strings.HasPrefix(pkg.Error.Err.Error(), "build constraints exclude all Go files") {
    76  				// Skip this error, as we will format
    77  				// all files regardless.
    78  			} else {
    79  				base.Errorf("can't load package: %s", pkg.Error)
    80  				continue
    81  			}
    82  		}
    83  		// Use pkg.gofiles instead of pkg.Dir so that
    84  		// the command only applies to this package,
    85  		// not to packages in subdirectories.
    86  		files := base.RelPaths(pkg.InternalAllGoFiles())
    87  		for _, file := range files {
    88  			fileC <- file
    89  		}
    90  	}
    91  	close(fileC)
    92  	wg.Wait()
    93  }
    94  
    95  func gofmtPath() string {
    96  	gofmt := "gofmt"
    97  	if base.ToolIsWindows {
    98  		gofmt += base.ToolWindowsExtension
    99  	}
   100  
   101  	gofmtPath := filepath.Join(cfg.GOBIN, gofmt)
   102  	if _, err := os.Stat(gofmtPath); err == nil {
   103  		return gofmtPath
   104  	}
   105  
   106  	gofmtPath = filepath.Join(cfg.GOROOT, "bin", gofmt)
   107  	if _, err := os.Stat(gofmtPath); err == nil {
   108  		return gofmtPath
   109  	}
   110  
   111  	// fallback to looking for gofmt in $PATH
   112  	return "gofmt"
   113  }