@@ -243,7 +243,7 @@ func runRelease(w io.Writer, dir string, args []string) (success bool, err error
243
243
type moduleInfo struct {
244
244
modRoot string // module root directory
245
245
repoRoot string // repository root directory (may be "")
246
- modPath string // module path
246
+ modPath string // module path in go.mod
247
247
version string // resolved version or "none"
248
248
versionQuery string // a query like "latest" or "dev-branch", if specified
249
249
versionInferred bool // true if the version was unspecified and inferred
@@ -393,7 +393,9 @@ func loadLocalModule(modRoot, repoRoot, version string) (m moduleInfo, err error
393
393
// loadDownloadedModule downloads a module and loads information about it and
394
394
// its packages from the module cache.
395
395
//
396
- // modPath is the module's path.
396
+ // modPath is the module path used to fetch the module. The module's path in
397
+ // go.mod (m.modPath) may be different, for example in a soft fork intended as
398
+ // a replacement.
397
399
//
398
400
// version is the version to load. It may be "none" (indicating nothing should
399
401
// be loaded), "" (the highest available version below max should be used), a
@@ -403,9 +405,6 @@ func loadLocalModule(modRoot, repoRoot, version string) (m moduleInfo, err error
403
405
// to max will not be considered. Typically, loadDownloadedModule is used to
404
406
// load the base version, and max is the release version.
405
407
func loadDownloadedModule (modPath , version , max string ) (m moduleInfo , err error ) {
406
- // TODO(#39666): support downloaded modules that are "soft forks", where the
407
- // module path in go.mod is different from modPath.
408
-
409
408
// Check the module path and version.
410
409
// If the version is a query, resolve it to a canonical version.
411
410
m = moduleInfo {modPath : modPath }
@@ -414,10 +413,10 @@ func loadDownloadedModule(modPath, version, max string) (m moduleInfo, err error
414
413
}
415
414
416
415
var ok bool
417
- _ , m .modPathMajor , ok = module .SplitPathVersion (m . modPath )
416
+ _ , m .modPathMajor , ok = module .SplitPathVersion (modPath )
418
417
if ! ok {
419
418
// we just validated the path above.
420
- panic (fmt .Sprintf ("could not find version suffix in module path %q" , m . modPath ))
419
+ panic (fmt .Sprintf ("could not find version suffix in module path %q" , modPath ))
421
420
}
422
421
423
422
if version == "none" {
@@ -457,12 +456,27 @@ func loadDownloadedModule(modPath, version, max string) (m moduleInfo, err error
457
456
m .version = version
458
457
}
459
458
460
- // Load packages.
459
+ // Download the module into the cache and load the mod file.
460
+ // Note that goModPath is $GOMODCACHE/cache/download/$modPath/@v/$version.mod,
461
+ // which is not inside modRoot. This is what the go command uses. Even if
462
+ // the module didn't have a go.mod file, one will be synthesized there.
461
463
v := module.Version {Path : modPath , Version : m .version }
462
- if m .modRoot , err = downloadModule (v ); err != nil {
464
+ if m .modRoot , m .goModPath , err = downloadModule (v ); err != nil {
465
+ return moduleInfo {}, err
466
+ }
467
+ if m .goModData , err = ioutil .ReadFile (m .goModPath ); err != nil {
468
+ return moduleInfo {}, err
469
+ }
470
+ if m .goModFile , err = modfile .ParseLax (m .goModPath , m .goModData , nil ); err != nil {
463
471
return moduleInfo {}, err
464
472
}
465
- tmpLoadDir , tmpGoModData , tmpGoSumData , err := prepareLoadDir (nil , modPath , m .modRoot , m .version , true )
473
+ if m .goModFile .Module == nil {
474
+ return moduleInfo {}, fmt .Errorf ("%s: missing module directive" , m .goModPath )
475
+ }
476
+ m .modPath = m .goModFile .Module .Mod .Path
477
+
478
+ // Load packages.
479
+ tmpLoadDir , tmpGoModData , tmpGoSumData , err := prepareLoadDir (nil , m .modPath , m .modRoot , m .version , true )
466
480
if err != nil {
467
481
return moduleInfo {}, err
468
482
}
@@ -471,23 +485,10 @@ func loadDownloadedModule(modPath, version, max string) (m moduleInfo, err error
471
485
err = fmt .Errorf ("removing temporary load directory: %v" , err )
472
486
}
473
487
}()
474
- if m .pkgs , _ , err = loadPackages (modPath , m .modRoot , tmpLoadDir , tmpGoModData , tmpGoSumData ); err != nil {
488
+ if m .pkgs , _ , err = loadPackages (m . modPath , m .modRoot , tmpLoadDir , tmpGoModData , tmpGoSumData ); err != nil {
475
489
return moduleInfo {}, err
476
490
}
477
491
478
- // Attempt to load the mod file, if it exists.
479
- m .goModPath = filepath .Join (m .modRoot , "go.mod" )
480
- if m .goModData , err = ioutil .ReadFile (m .goModPath ); err != nil && ! os .IsNotExist (err ) {
481
- return moduleInfo {}, fmt .Errorf ("reading go.mod: %v" , err )
482
- }
483
- if err == nil {
484
- m .goModFile , err = modfile .ParseLax (m .goModPath , m .goModData , nil )
485
- if err != nil {
486
- return moduleInfo {}, err
487
- }
488
- }
489
- // The modfile might not exist, leading to err != nil. That's OK - continue.
490
-
491
492
return m , nil
492
493
}
493
494
@@ -578,10 +579,12 @@ func makeReleaseReport(base, release moduleInfo) (report, error) {
578
579
}
579
580
}
580
581
581
- if release .version != "" {
582
- r .validateVersion ()
583
- } else if r .similarModPaths () {
584
- r .suggestVersion ()
582
+ if r .canVerifyReleaseVersion () {
583
+ if release .version == "" {
584
+ r .suggestReleaseVersion ()
585
+ } else {
586
+ r .validateReleaseVersion ()
587
+ }
585
588
}
586
589
587
590
return r , nil
@@ -825,7 +828,7 @@ func copyModuleToTempDir(modPath, modRoot string) (dir string, err error) {
825
828
826
829
// downloadModule downloads a specific version of a module to the
827
830
// module cache using 'go mod download'.
828
- func downloadModule (m module.Version ) (modRoot string , err error ) {
831
+ func downloadModule (m module.Version ) (modRoot , goModPath string , err error ) {
829
832
defer func () {
830
833
if err != nil {
831
834
err = & downloadError {m : m , err : cleanCmdError (err )}
@@ -840,7 +843,7 @@ func downloadModule(m module.Version) (modRoot string, err error) {
840
843
// If it didn't read go.mod in this case, we wouldn't need a temp directory.
841
844
tmpDir , err := ioutil .TempDir ("" , "gorelease-download" )
842
845
if err != nil {
843
- return "" , err
846
+ return "" , "" , err
844
847
}
845
848
defer os .Remove (tmpDir )
846
849
cmd := exec .Command ("go" , "mod" , "download" , "-json" , "--" , m .Path + "@" + m .Version )
@@ -850,26 +853,26 @@ func downloadModule(m module.Version) (modRoot string, err error) {
850
853
if err != nil {
851
854
var ok bool
852
855
if xerr , ok = err .(* exec.ExitError ); ! ok {
853
- return "" , err
856
+ return "" , "" , err
854
857
}
855
858
}
856
859
857
860
// If 'go mod download' exited unsuccessfully but printed well-formed JSON
858
861
// with an error, return that error.
859
- parsed := struct { Dir , Error string }{}
862
+ parsed := struct { Dir , GoMod , Error string }{}
860
863
if jsonErr := json .Unmarshal (out , & parsed ); jsonErr != nil {
861
864
if xerr != nil {
862
- return "" , cleanCmdError (xerr )
865
+ return "" , "" , cleanCmdError (xerr )
863
866
}
864
- return "" , jsonErr
867
+ return "" , "" , jsonErr
865
868
}
866
869
if parsed .Error != "" {
867
- return "" , errors .New (parsed .Error )
870
+ return "" , "" , errors .New (parsed .Error )
868
871
}
869
872
if xerr != nil {
870
- return "" , cleanCmdError (xerr )
873
+ return "" , "" , cleanCmdError (xerr )
871
874
}
872
- return parsed .Dir , nil
875
+ return parsed .Dir , parsed . GoMod , nil
873
876
}
874
877
875
878
// prepareLoadDir creates a temporary directory and a go.mod file that requires
0 commit comments