Run API-only recovery independently of consumer vendoring
This commit is contained in:
@@ -19,7 +19,7 @@ const releaseKitCommand = releaseKitModule + "/cmd/releasekit"
|
||||
|
||||
// RecoveryTool returns module-selected Go arguments for a later invocation.
|
||||
// An empty result means this module does not select ReleaseKit. API-only modules
|
||||
// receive private alternate module files that outlive launcher-owned bootstraps.
|
||||
// receive a private module root that outlives launcher-owned bootstraps.
|
||||
func RecoveryTool(ctx context.Context, moduleDir, recordDir string) ([]string, error) {
|
||||
path := filepath.Join(moduleDir, "go.mod")
|
||||
data, err := os.ReadFile(path)
|
||||
@@ -64,6 +64,28 @@ func RecoveryTool(ctx context.Context, moduleDir, recordDir string) ([]string, e
|
||||
if err := module.AddTool(releaseKitCommand); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Relocating the root avoids the consumer's vendor tree. Preserve local
|
||||
// replacements relative to the directory that originally owned go.mod.
|
||||
for _, replacement := range module.Replace {
|
||||
if replacement.New.Version == "" && !filepath.IsAbs(replacement.New.Path) {
|
||||
if err := module.AddReplace(replacement.Old.Path, replacement.Old.Version, filepath.Join(moduleDir, replacement.New.Path), ""); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
// The original main module's source remains local if a dependency refers
|
||||
// to it. This also permits recovery when releasing ReleaseKit itself.
|
||||
if err := module.AddReplace(module.Module.Mod.Path, "", moduleDir, ""); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if selected.Main {
|
||||
if err := module.AddRequire(releaseKitModule, "v0.0.0"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := module.AddModuleStmt("releasekit.local/recovery"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err = module.Format()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -85,24 +107,22 @@ func RecoveryTool(ctx context.Context, moduleDir, recordDir string) ([]string, e
|
||||
_ = os.RemoveAll(directory)
|
||||
}
|
||||
}()
|
||||
alternate := filepath.Join(directory, "releasekit.mod")
|
||||
if err := os.WriteFile(alternate, data, 0600); err != nil {
|
||||
if err := os.WriteFile(filepath.Join(directory, "go.mod"), data, 0600); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(directory, "releasekit.sum"), sums, 0600); err != nil {
|
||||
if err := os.WriteFile(filepath.Join(directory, "go.sum"), sums, 0600); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// go tool accepts an alternate module file but has no -mod flag. Prepare
|
||||
// the private graph and sums before the later read-only tool invocation.
|
||||
// Prepare the private graph and sums before the later tool invocation.
|
||||
captured := &combinedWriter{mode: captureStatus}
|
||||
err = process.Run(ctx, process.Invocation{
|
||||
Args: []string{"go", "list", "-mod=mod", "-modfile=" + alternate, "-deps", releaseKitCommand},
|
||||
Dir: moduleDir, Env: map[string]string{"GOWORK": "off", "GOTOOLCHAIN": "local"},
|
||||
Args: []string{"go", "list", "-mod=mod", "-modfile=", "-deps", releaseKitCommand},
|
||||
Dir: directory, Env: map[string]string{"GOWORK": "off", "GOTOOLCHAIN": "local"},
|
||||
Stdout: captured, Stderr: captured,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("prepare recovery tool: %w: %s", err, diagnosticText(captured.take(), captured.omitted()))
|
||||
}
|
||||
complete = true
|
||||
return []string{"-C", moduleDir, "tool", "-modfile=" + alternate, releaseKitCommand}, nil
|
||||
return []string{"-C", directory, "tool", "-modfile=", releaseKitCommand}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user