Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit 852ae93

Browse files
Sauyon Leesmowton
authored andcommitted
autobuilder: Test for vendor inconsistency
1 parent 28c6974 commit 852ae93

File tree

1 file changed

+67
-16
lines changed

1 file changed

+67
-16
lines changed

extractor/cli/go-autobuilder/go-autobuilder.go

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"fmt"
5+
"golang.org/x/mod/semver"
56
"io/ioutil"
67
"log"
78
"net/url"
@@ -44,12 +45,17 @@ variable is 32.
4445
fmt.Fprintf(os.Stderr, "Usage:\n\n %s\n", os.Args[0])
4546
}
4647

48+
var goVersion = ""
49+
4750
func getEnvGoVersion() string {
48-
gover, err := exec.Command("go", "version").CombinedOutput()
49-
if err != nil {
50-
log.Fatalf("Unable to run the go command, is it installed?\nError: %s", err.Error())
51+
if goVersion == "" {
52+
gover, err := exec.Command("go", "version").CombinedOutput()
53+
if err != nil {
54+
log.Fatalf("Unable to run the go command, is it installed?\nError: %s", err.Error())
55+
}
56+
goVersion = strings.Fields(string(gover))[2]
5157
}
52-
return strings.Fields(string(gover))[2]
58+
return goVersion
5359
}
5460

5561
func run(cmd *exec.Cmd) bool {
@@ -141,6 +147,40 @@ const (
141147
Glide
142148
)
143149

150+
// ModMode corresponds to the possible values of the -mod flag for the Go compiler
151+
type ModMode int
152+
153+
const (
154+
ModUnset ModMode = iota
155+
ModReadonly
156+
ModMod
157+
ModVendor
158+
)
159+
160+
func (m ModMode) String() string {
161+
switch m {
162+
case ModUnset:
163+
return ""
164+
case ModReadonly:
165+
return "-mod=readonly"
166+
case ModMod:
167+
return "-mod=mod"
168+
case ModVendor:
169+
return "-mod=vendor"
170+
}
171+
return ""
172+
}
173+
174+
// modModIfSupported returns `ModMod` if that flag is supported, or `ModUnset` if it is not, in
175+
// which case the behavior should be identical to `ModMod`.
176+
func modModIfSupported() ModMode {
177+
if semver.Compare(getEnvGoVersion(), "1.14") < 0 {
178+
return ModUnset
179+
} else {
180+
return ModMod
181+
}
182+
}
183+
144184
// addVersionToMod add a go version directive, e.g. `go 1.14` to a `go.mod` file.
145185
func addVersionToMod(goMod []byte, version string) bool {
146186
cmd := exec.Command("go", "mod", "edit", "-go="+version)
@@ -174,6 +214,7 @@ func main() {
174214
// determine how to install dependencies and whether a GOPATH needs to be set up before
175215
// extraction
176216
depMode := GoGetNoModules
217+
modMode := ModUnset
177218
needGopath := true
178219
if util.FileExists("go.mod") {
179220
depMode = GoGetWithModules
@@ -189,8 +230,10 @@ func main() {
189230

190231
// if a vendor/modules.txt file exists, we assume that there are vendored Go dependencies, and
191232
// skip the dependency installation step and run the extractor with `-mod=vendor`
192-
hasVendor := util.FileExists("vendor/modules.txt")
193-
if hasVendor {
233+
if util.FileExists("vendor/modules.txt") {
234+
modMode = ModVendor
235+
}
236+
if modMode == ModVendor {
194237
// fix go vendor issues with go versions >= 1.14 when no go version is specified in the go.mod
195238
// if this is the case, and dependencies were vendored with an old go version (and therefore
196239
// do not contain a '## explicit' annotation, the go command will fail and refuse to do any
@@ -212,7 +255,7 @@ func main() {
212255
log.Println("Adding a version directive to the go.mod file as the modules.txt does not have explicit annotations")
213256
if !addVersionToMod(goMod, "1.13") {
214257
log.Println("Failed to add a version to the go.mod file to fix explicitly required package bug; not using vendored dependencies")
215-
hasVendor = false
258+
modMode = modModIfSupported()
216259
}
217260
}
218261
}
@@ -336,7 +379,7 @@ func main() {
336379
tryBuild("build.sh", "./build.sh")
337380

338381
if !buildSucceeded {
339-
if hasVendor {
382+
if modMode == ModVendor {
340383
log.Printf("Skipping dependency installation because a Go vendor directory was found.")
341384
} else {
342385
// automatically determine command to install dependencies
@@ -422,6 +465,20 @@ func main() {
422465
run(install)
423466
}
424467

468+
if modMode == ModVendor {
469+
// test if running `go` with -mod=vendor works, and if it doesn't, try to fallback to -mod=mod
470+
// or not set if the go version < 1.14.
471+
vendorCheckCmd := exec.Command("go", "list", "-mod=vendor", "./...")
472+
outp, err := vendorCheckCmd.CombinedOutput()
473+
if err != nil {
474+
badVendorRe := regexp.MustCompile(`(?m)^go: inconsistent vendoring in .*:$`)
475+
if badVendorRe.Match(outp) {
476+
modMode = modModIfSupported()
477+
log.Println("The vendor directory is not consistent with the go.mod; not using vendored dependencies.")
478+
}
479+
}
480+
}
481+
425482
// extract
426483
mypath, err := os.Executable()
427484
if err != nil {
@@ -438,14 +495,8 @@ func main() {
438495
}
439496

440497
var cmd *exec.Cmd
441-
// check for `vendor/modules.txt` and not just `vendor` in order to distinguish non-go vendor dirs
442-
if depMode == GoGetWithModules && hasVendor {
443-
log.Printf("Running extractor command '%s -mod=vendor ./...' from directory '%s'.\n", extractor, cwd)
444-
cmd = exec.Command(extractor, "-mod=vendor", "./...")
445-
} else {
446-
log.Printf("Running extractor command '%s ./...' from directory '%s'.\n", extractor, cwd)
447-
cmd = exec.Command(extractor, "./...")
448-
}
498+
log.Printf("Running extractor command '%s %s ./...' from directory '%s'.\n", extractor, modMode, cwd)
499+
cmd = exec.Command(extractor, modMode.String(), "./...")
449500
cmd.Stdout = os.Stdout
450501
cmd.Stderr = os.Stderr
451502
err = cmd.Run()

0 commit comments

Comments
 (0)