Skip to content

Commit de070ed

Browse files
committed
Repair the root go.mod mirror on a cache-less Go reapply
reuse_go_redirect reported an intact agent copy as already patched from redirect_in_sync alone, so a go.work workspace whose root go.mod mirror of the replace had gone missing stayed unrepaired after the module cache was deleted, and a GOWORK=off build kept linking the unpatched module. apply_go_redirect's hot path already wrote the mirror back. Share that repair between both paths, skipping it on a dry run. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 67abc02 commit de070ed

2 files changed

Lines changed: 47 additions & 15 deletions

File tree

‎crates/socket-patch-cli/src/commands/apply.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2413,6 +2413,7 @@ async fn apply_patches_inner(
24132413
purl,
24142414
&args.common.cwd,
24152415
&record.files,
2416+
args.common.dry_run,
24162417
)
24172418
.await
24182419
{

‎crates/socket-patch-core/src/patch/redirect/golang_local.rs‎

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ pub async fn reuse_go_redirect(
182182
purl: &str,
183183
project_root: &Path,
184184
files: &HashMap<String, PatchFileInfo>,
185+
dry_run: bool,
185186
) -> Option<ApplyResult> {
186187
let (module, version) = parse_golang_purl(purl)?;
187188
if !are_safe_redirect_coords(&module, &version) || files.is_empty() {
@@ -229,7 +230,12 @@ pub async fn reuse_go_redirect(
229230
)
230231
.await
231232
{
232-
return Some(already_patched_result(purl, &copy, files));
233+
let mut result = already_patched_result(purl, &copy, files);
234+
if !dry_run {
235+
repair_root_go_mod_mirror(&mut result, project_root, &module, &version, GO_PATCHES_DIR)
236+
.await;
237+
}
238+
return Some(result);
233239
}
234240
Some(synthesized_result(purl, &copy, Vec::new(), false, Some(format!(
235241
"the local Go patch copy or replace for {module} {version} is out of sync and the upstream module is not installed; restore the committed patch files or download the upstream module before reapplying"
@@ -369,19 +375,7 @@ pub async fn apply_go_redirect<'a>(
369375
// on most "deps changed" builds).
370376
if redirect_in_sync(&copy_dir, files, project_root, module, version, base_rel).await {
371377
let mut result = already_patched_result(purl, &copy_dir, files);
372-
// A root go.mod mirror of the go.work replace that went missing is
373-
// written back without rebuilding the copy: a failed rebuild would
374-
// tear down the go.work replace the workspace builds through.
375-
let expected = replace_target_path(base_rel, module, version);
376-
if !root_go_mod_mirror_ok(project_root, module, version, &expected).await {
377-
if let Err(e) =
378-
go_mod_edit::ensure_replace_entry(project_root, module, version, base_rel, false)
379-
.await
380-
{
381-
result.success = false;
382-
result.error = Some(format!("failed to update go.mod: {e}"));
383-
}
384-
}
378+
repair_root_go_mod_mirror(&mut result, project_root, module, version, base_rel).await;
385379
return result;
386380
}
387381

@@ -871,6 +865,28 @@ async fn redirect_in_sync(
871865
})
872866
}
873867

868+
/// Write back a root go.mod mirror of the go.work replace that went missing,
869+
/// without rebuilding the copy: a failed rebuild would tear down the go.work
870+
/// replace the workspace builds through.
871+
async fn repair_root_go_mod_mirror(
872+
result: &mut ApplyResult,
873+
project_root: &Path,
874+
module: &str,
875+
version: &str,
876+
base_rel: &str,
877+
) {
878+
let expected = replace_target_path(base_rel, module, version);
879+
if root_go_mod_mirror_ok(project_root, module, version, &expected).await {
880+
return;
881+
}
882+
if let Err(e) =
883+
go_mod_edit::ensure_replace_entry(project_root, module, version, base_rel, false).await
884+
{
885+
result.success = false;
886+
result.error = Some(format!("failed to update go.mod: {e}"));
887+
}
888+
}
889+
874890
/// False when the replace host is `go.work` and the root `go.mod` that
875891
/// mirrors it (`ReplaceHost::mirrors_root_go_mod`) lacks a
876892
/// socket-owned `replace` pinning `version` to `expected`: a `GOWORK=off`
@@ -1211,6 +1227,21 @@ mod tests {
12111227
verify_go_redirect_state(root, &manifest, &desired)
12121228
.await
12131229
.unwrap();
1230+
1231+
// A cache-less reapply reuses the copy and repairs the mirror the
1232+
// same way; a dry run leaves go.mod alone.
1233+
std::fs::write(root.join("go.mod"), &gomod).unwrap();
1234+
let result = reuse_go_redirect(PURL, root, &files, true).await.unwrap();
1235+
assert!(result.success, "{:?}", result.error);
1236+
assert_eq!(std::fs::read_to_string(root.join("go.mod")).unwrap(), gomod);
1237+
let result = reuse_go_redirect(PURL, root, &files, false).await.unwrap();
1238+
assert!(result.success, "{:?}", result.error);
1239+
assert!(std::fs::read_to_string(root.join("go.mod"))
1240+
.unwrap()
1241+
.contains(&line));
1242+
verify_go_redirect_state(root, &manifest, &desired)
1243+
.await
1244+
.unwrap();
12141245
}
12151246

12161247
#[tokio::test]
@@ -1716,7 +1747,7 @@ mod tests {
17161747
)
17171748
.await
17181749
.unwrap();
1719-
assert!(reuse_go_redirect(PURL, root, &files).await.is_none());
1750+
assert!(reuse_go_redirect(PURL, root, &files, false).await.is_none());
17201751
}
17211752

17221753
#[tokio::test]

0 commit comments

Comments
 (0)