0c3291310c79
report deleted damaged remote copies when a Doctor resend fails part way
- time
- 2026-10-07 17:41 UTC · 5 days ago
- machine
- Junes-MacBook-Pro.local
- agent
- claude-opus-5-5
- session
- resolve doctor safety findings
- parent
- 573800eb25d3
↓ koh-0c329131.tar.gzatlas at this save
files changed3 files
src/exchange/exchange.v+5 −4src/exchange/exchange_test.v+27 −0src/exchange/repair.v+1 −0src/exchange/exchange.v+5 −4
@@ -180,14 +180,15 @@180180 mut:181181 saves []string182182 objects map[string]bool183+ deleted int // damaged remote copies removed before their replacement183184 }184185 185186 fn (u Uploaded) done() []string {186- return if u.saves.len + u.objects.len == 0 {187- []string{}188- } else {189- ['uploaded ${fmt.plural(u.objects.len, 'object')} and ${fmt.plural(u.saves.len, 'save record')}']187+ mut done := done_text('deleted', u.deleted, 'damaged remote object')188+ if u.saves.len + u.objects.len > 0 {189+ done << 'uploaded ${fmt.plural(u.objects.len, 'object')} and ${fmt.plural(u.saves.len, 'save record')}'190190 }191+ return done191192 }192193 193194 // upload_line sends every save after the remote head, then the events.src/exchange/exchange_test.v+27 −0
@@ -1530,6 +1530,33 @@15301530 assert unsettled(a)!.len == 315311531 }15321532 1533+// Deleting a damaged remote copy is work done, even when its replacement fails.1534+fn test_a_resend_reports_a_damaged_copy_it_deleted() {1535+ base := scratch('resend_deleted')!1536+ defer {1537+ os.rmdir_all(base) or {}1538+ }1539+ remote_dir := os.join_path(base, 'remote')1540+ mut backend := remote.new_folder(remote_dir)!1541+ mut a := open_repo(machine('resend_deleted_a')!)!1542+ defer {1543+ a.close()1544+ }1545+ put(a.root, 'app', 'app\n')!1546+ make_save(a, 'app')!1547+ hash := storage.hash_hex('app\n'.bytes())1548+ backend.put_if_absent(object_key('proj', hash), 'damaged'.bytes())!1549+ mut flaky := FaultyBackend{1550+ inner: remote.new_folder(remote_dir)!1551+ fail_write: 11552+ }1553+ if _ := resend(a, mut flaky, 'proj', [hash], []) {1554+ assert false, 'the injected write failure should have surfaced'1555+ } else {1556+ assert (err as Partway).done == 'deleted 1 damaged remote object', (err as Partway).done1557+ }1558+}1559+15331560 // A strip that sent its event before failing says so.15341561 fn test_a_strip_that_fails_after_its_event_reports_it() {15351562 base := scratch('strip_event_partway')!src/exchange/repair.v+1 −0
@@ -111,6 +111,7 @@111111 }112112 }113113 backend.delete(key)!114+ uploaded.deleted++114115 }115116 store.get_object(hash)!116117 if backend.put_if_absent(key, store.object_blob(hash)!)! {