Skip to content

Commit 5eadb00

Browse files
committed
Retire a pre-v5 hosted ledger when rollback finds nothing else; update the cargo guard test
rollback in a project whose only state is a stale pre-v5 redirect-state.json (no manifest, no vendor ledger, no hosted pin in the lockfiles) removes that file and exits 0 instead of failing on the missing manifest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018tncU7u7FK48tubFNA12UQ
1 parent c0d0797 commit 5eadb00

2 files changed

Lines changed: 45 additions & 4 deletions

File tree

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,42 @@ pub async fn run(args: RollbackArgs) -> i32 {
12101210
HostedPin::all(&crate::commands::discover_wiring(&args.common, &cwd).await);
12111211

12121212
if manifest_missing && !vendor_ledger_exists && hosted_pins.is_empty() {
1213+
// Only a pre-v5 hosted ledger left: no lockfile pins it any more,
1214+
// so there is nothing to restore — retire the stale file (a wet run
1215+
// only) instead of failing on the missing manifest.
1216+
let legacy = cwd.join(socket_patch_core::patch::redirect::REDIRECT_STATE_REL);
1217+
if tokio::fs::symlink_metadata(&legacy).await.is_ok() {
1218+
let warning = retire_legacy_redirect_ledger(&args.common).await;
1219+
if args.common.json {
1220+
println!(
1221+
"{}",
1222+
serde_json::to_string_pretty(&serde_json::json!({
1223+
"status": "success",
1224+
"rolledBack": 0,
1225+
"alreadyOriginal": 0,
1226+
"failed": 0,
1227+
"dryRun": args.common.dry_run,
1228+
"warnings": warning
1229+
.iter()
1230+
.map(|(code, detail)| serde_json::json!({
1231+
"code": code, "detail": detail,
1232+
}))
1233+
.collect::<Vec<_>>(),
1234+
"legacyRedirectLedgerRemoved": warning.is_none() && !args.common.dry_run,
1235+
}))
1236+
.expect("serializing an in-memory JSON value cannot fail")
1237+
);
1238+
} else if let Some((code, detail)) = &warning {
1239+
eprintln!("Warning ({code}): {}", capitalize_first(detail));
1240+
} else if !args.common.silent {
1241+
println!(
1242+
"{} the pre-v5 hosted ledger {}: no lockfile pins a hosted patch.",
1243+
if args.common.dry_run { "Would remove" } else { "Removed" },
1244+
socket_patch_core::patch::redirect::REDIRECT_STATE_REL
1245+
);
1246+
}
1247+
return 0;
1248+
}
12131249
// Ledger-less but still wired? (a deleted/uncommitted state.json
12141250
// with lockfiles still consuming `.socket/vendor/` artifacts is a
12151251
// supported recovery state — `repair` reconstructs the ledger.)

‎crates/socket-patch-core/src/vendor/cargo.rs‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4201,12 +4201,12 @@ mod tests {
42014201
);
42024202
}
42034203

4204-
/// FAIL CLOSED: vendoring over a LIVE hosted redirect with no ledger to
4205-
/// revert it must refuse — proceeding would record the hosted registry
4204+
/// FAIL CLOSED: vendoring over a LIVE hosted redirect the upstream
4205+
/// restore did not undo must refuse — proceeding would record the hosted registry
42064206
/// values as the entry's "originals" and leave Cargo.toml pinned to the
42074207
/// hosted registry (unbuildable in both modes) while reporting success.
42084208
#[tokio::test]
4209-
async fn test_refuses_live_hosted_redirect_without_ledger() {
4209+
async fn test_refuses_live_hosted_redirect_left_unrestored() {
42104210
let (dir, blobs, pristine, record) = fixture().await;
42114211
let root = dir.path();
42124212
let index = "sparse+http://127.0.0.1:5555/index/";
@@ -4243,7 +4243,12 @@ mod tests {
42434243
run_vendor(PURL, root, &blobs, &pristine, &record, false).await,
42444244
"hosted_redirect_live",
42454245
);
4246-
assert!(detail.contains("redirect-state.json"), "{detail}");
4246+
assert!(
4247+
detail.contains("socket-patch rollback")
4248+
&& detail.contains("git checkout -- Cargo.toml Cargo.lock"),
4249+
"the refusal names the restore remedies: {detail}"
4250+
);
4251+
assert!(!detail.contains("redirect-state.json"), "{detail}");
42474252
// Nothing was half-vendored.
42484253
assert!(!root.join(format!(".socket/vendor/cargo/{UUID}")).exists());
42494254

0 commit comments

Comments
 (0)