@@ -2,6 +2,7 @@ package main
2
2
3
3
import (
4
4
"fmt"
5
+ "golang.org/x/mod/semver"
5
6
"io/ioutil"
6
7
"log"
7
8
"net/url"
@@ -44,12 +45,17 @@ variable is 32.
44
45
fmt .Fprintf (os .Stderr , "Usage:\n \n %s\n " , os .Args [0 ])
45
46
}
46
47
48
+ var goVersion = ""
49
+
47
50
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?\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 ]
51
57
}
52
- return strings . Fields ( string ( gover ))[ 2 ]
58
+ return goVersion
53
59
}
54
60
55
61
func run (cmd * exec.Cmd ) bool {
@@ -141,6 +147,40 @@ const (
141
147
Glide
142
148
)
143
149
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
+
144
184
// addVersionToMod add a go version directive, e.g. `go 1.14` to a `go.mod` file.
145
185
func addVersionToMod (goMod []byte , version string ) bool {
146
186
cmd := exec .Command ("go" , "mod" , "edit" , "-go=" + version )
@@ -174,6 +214,7 @@ func main() {
174
214
// determine how to install dependencies and whether a GOPATH needs to be set up before
175
215
// extraction
176
216
depMode := GoGetNoModules
217
+ modMode := ModUnset
177
218
needGopath := true
178
219
if util .FileExists ("go.mod" ) {
179
220
depMode = GoGetWithModules
@@ -189,8 +230,10 @@ func main() {
189
230
190
231
// if a vendor/modules.txt file exists, we assume that there are vendored Go dependencies, and
191
232
// 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 {
194
237
// fix go vendor issues with go versions >= 1.14 when no go version is specified in the go.mod
195
238
// if this is the case, and dependencies were vendored with an old go version (and therefore
196
239
// do not contain a '## explicit' annotation, the go command will fail and refuse to do any
@@ -212,7 +255,7 @@ func main() {
212
255
log .Println ("Adding a version directive to the go.mod file as the modules.txt does not have explicit annotations" )
213
256
if ! addVersionToMod (goMod , "1.13" ) {
214
257
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 ()
216
259
}
217
260
}
218
261
}
@@ -336,7 +379,7 @@ func main() {
336
379
tryBuild ("build.sh" , "./build.sh" )
337
380
338
381
if ! buildSucceeded {
339
- if hasVendor {
382
+ if modMode == ModVendor {
340
383
log .Printf ("Skipping dependency installation because a Go vendor directory was found." )
341
384
} else {
342
385
// automatically determine command to install dependencies
@@ -422,6 +465,20 @@ func main() {
422
465
run (install )
423
466
}
424
467
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
+
425
482
// extract
426
483
mypath , err := os .Executable ()
427
484
if err != nil {
@@ -438,14 +495,8 @@ func main() {
438
495
}
439
496
440
497
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 (), "./..." )
449
500
cmd .Stdout = os .Stdout
450
501
cmd .Stderr = os .Stderr
451
502
err = cmd .Run ()
0 commit comments