@@ -2,6 +2,7 @@ package main
22
33import (
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+
4750func 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?\n Error: %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?\n Error: %s" , err .Error ())
55+ }
56+ goVersion = strings .Fields (string (gover ))[2 ]
5157 }
52- return strings . Fields ( string ( gover ))[ 2 ]
58+ return goVersion
5359}
5460
5561func 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.
145185func 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