.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.1-0.20210319172145-bda8f5cee399 / internal / gocommand / vendor.go
1 // Copyright 2020 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 gocommand
6
7 import (
8         "bytes"
9         "context"
10         "fmt"
11         "os"
12         "path/filepath"
13         "regexp"
14         "strings"
15         "time"
16
17         "golang.org/x/mod/semver"
18 )
19
20 // ModuleJSON holds information about a module.
21 type ModuleJSON struct {
22         Path      string      // module path
23         Version   string      // module version
24         Versions  []string    // available module versions (with -versions)
25         Replace   *ModuleJSON // replaced by this module
26         Time      *time.Time  // time version was created
27         Update    *ModuleJSON // available update, if any (with -u)
28         Main      bool        // is this the main module?
29         Indirect  bool        // is this module only an indirect dependency of main module?
30         Dir       string      // directory holding files for this module, if any
31         GoMod     string      // path to go.mod file used when loading this module, if any
32         GoVersion string      // go version used in module
33 }
34
35 var modFlagRegexp = regexp.MustCompile(`-mod[ =](\w+)`)
36
37 // VendorEnabled reports whether vendoring is enabled. It takes a *Runner to execute Go commands
38 // with the supplied context.Context and Invocation. The Invocation can contain pre-defined fields,
39 // of which only Verb and Args are modified to run the appropriate Go command.
40 // Inspired by setDefaultBuildMod in modload/init.go
41 func VendorEnabled(ctx context.Context, inv Invocation, r *Runner) (*ModuleJSON, bool, error) {
42         mainMod, go114, err := getMainModuleAnd114(ctx, inv, r)
43         if err != nil {
44                 return nil, false, err
45         }
46
47         // We check the GOFLAGS to see if there is anything overridden or not.
48         inv.Verb = "env"
49         inv.Args = []string{"GOFLAGS"}
50         stdout, err := r.Run(ctx, inv)
51         if err != nil {
52                 return nil, false, err
53         }
54         goflags := string(bytes.TrimSpace(stdout.Bytes()))
55         matches := modFlagRegexp.FindStringSubmatch(goflags)
56         var modFlag string
57         if len(matches) != 0 {
58                 modFlag = matches[1]
59         }
60         if modFlag != "" {
61                 // Don't override an explicit '-mod=' argument.
62                 return mainMod, modFlag == "vendor", nil
63         }
64         if mainMod == nil || !go114 {
65                 return mainMod, false, nil
66         }
67         // Check 1.14's automatic vendor mode.
68         if fi, err := os.Stat(filepath.Join(mainMod.Dir, "vendor")); err == nil && fi.IsDir() {
69                 if mainMod.GoVersion != "" && semver.Compare("v"+mainMod.GoVersion, "v1.14") >= 0 {
70                         // The Go version is at least 1.14, and a vendor directory exists.
71                         // Set -mod=vendor by default.
72                         return mainMod, true, nil
73                 }
74         }
75         return mainMod, false, nil
76 }
77
78 // getMainModuleAnd114 gets the main module's information and whether the
79 // go command in use is 1.14+. This is the information needed to figure out
80 // if vendoring should be enabled.
81 func getMainModuleAnd114(ctx context.Context, inv Invocation, r *Runner) (*ModuleJSON, bool, error) {
82         const format = `{{.Path}}
83 {{.Dir}}
84 {{.GoMod}}
85 {{.GoVersion}}
86 {{range context.ReleaseTags}}{{if eq . "go1.14"}}{{.}}{{end}}{{end}}
87 `
88         inv.Verb = "list"
89         inv.Args = []string{"-m", "-f", format}
90         stdout, err := r.Run(ctx, inv)
91         if err != nil {
92                 return nil, false, err
93         }
94
95         lines := strings.Split(stdout.String(), "\n")
96         if len(lines) < 5 {
97                 return nil, false, fmt.Errorf("unexpected stdout: %q", stdout.String())
98         }
99         mod := &ModuleJSON{
100                 Path:      lines[0],
101                 Dir:       lines[1],
102                 GoMod:     lines[2],
103                 GoVersion: lines[3],
104                 Main:      true,
105         }
106         return mod, lines[4] == "go1.14", nil
107 }