@@ -206,9 +206,15 @@ func runGet(cmd *base.Command, args []string) {
206
206
207
207
modload .LoadBuildList ()
208
208
209
+ // Do not allow any updating of go.mod until we've applied
210
+ // all the requested changes and checked that the result matches
211
+ // what was requested.
212
+ modload .DisallowWriteGoMod ()
213
+
209
214
// A task holds the state for processing a single get argument (path@vers).
210
215
type task struct {
211
- arg string // original argument
216
+ arg string // original argument
217
+ index int
212
218
path string // package path part of arg
213
219
forceModulePath bool // path must be interpreted as a module path
214
220
vers string // version part of arg
@@ -429,6 +435,7 @@ func runGet(cmd *base.Command, args []string) {
429
435
base .Fatalf ("go get: %v" , err )
430
436
}
431
437
required = upgraded [1 :] // slice off upgradeTarget
438
+ base .ExitIfErrors ()
432
439
}
433
440
434
441
// Put together the final build list as described above (1) (2) (3).
@@ -441,8 +448,9 @@ func runGet(cmd *base.Command, args []string) {
441
448
list = append (list , required ... )
442
449
modload .SetBuildList (list )
443
450
modload .ReloadBuildList () // note: does not update go.mod
451
+ base .ExitIfErrors ()
444
452
445
- // Apply any needed downgrades.
453
+ // Scan for and apply any needed downgrades.
446
454
var down []module.Version
447
455
for _ , m := range modload .BuildList () {
448
456
t := byPath [m .Path ]
@@ -458,8 +466,64 @@ func runGet(cmd *base.Command, args []string) {
458
466
modload .SetBuildList (list )
459
467
modload .ReloadBuildList () // note: does not update go.mod
460
468
}
469
+ base .ExitIfErrors ()
470
+
471
+ // Scan for any upgrades lost by the downgrades.
472
+ lost := make (map [string ]string )
473
+ for _ , m := range modload .BuildList () {
474
+ t := byPath [m .Path ]
475
+ if t != nil && semver .Compare (m .Version , t .m .Version ) != 0 {
476
+ lost [m .Path ] = m .Version
477
+ }
478
+ }
479
+ if len (lost ) > 0 {
480
+ desc := func (m module.Version ) string {
481
+ s := m .Path + "@" + m .Version
482
+ t := byPath [m .Path ]
483
+ if t != nil && t .arg != s {
484
+ s += " from " + t .arg
485
+ }
486
+ return s
487
+ }
488
+ downByPath := make (map [string ]module.Version )
489
+ for _ , d := range down {
490
+ downByPath [d .Path ] = d
491
+ }
492
+ var buf strings.Builder
493
+ fmt .Fprintf (& buf , "go get: inconsistent versions:" )
494
+ for _ , t := range tasks {
495
+ if lost [t .m .Path ] == "" {
496
+ continue
497
+ }
498
+ // We lost t because its build list requires a newer version of something in down.
499
+ // Figure out exactly what.
500
+ // Repeatedly constructing the build list is inefficient
501
+ // if there are MANY command-line arguments,
502
+ // but at least all the necessary requirement lists are cached at this point.
503
+ list , err := mvs .BuildList (t .m , reqs )
504
+ if err != nil {
505
+ base .Fatalf ("go get: %v" , err )
506
+ }
507
+
508
+ fmt .Fprintf (& buf , "\n \t %s" , desc (t .m ))
509
+ sep := " requires"
510
+ for _ , m := range list {
511
+ if down , ok := downByPath [m .Path ]; ok && semver .Compare (down .Version , m .Version ) < 0 {
512
+ fmt .Fprintf (& buf , "%s %s@%s (not %s)" , sep , m .Path , m .Version , desc (down ))
513
+ sep = ","
514
+ }
515
+ }
516
+ if sep != "," {
517
+ // We have no idea why this happened.
518
+ // At least report the problem.
519
+ fmt .Fprintf (& buf , " ended up at %v unexpectedly (please report at golang.org/issue/new)" , lost [t .m .Path ])
520
+ }
521
+ }
522
+ base .Fatalf ("%v" , buf .String ())
523
+ }
461
524
462
525
// Everything succeeded. Update go.mod.
526
+ modload .AllowWriteGoMod ()
463
527
modload .WriteGoMod ()
464
528
465
529
// If -m was specified, we're done after the module work. No download, no build.
0 commit comments