Skip to content

fix(shared-writer): make blocker/label/relation mutations idempotent (#600)#605

Merged
dollspace-gay merged 1 commit into
developfrom
fix/600-block-idempotent
May 15, 2026
Merged

fix(shared-writer): make blocker/label/relation mutations idempotent (#600)#605
dollspace-gay merged 1 commit into
developfrom
fix/600-block-idempotent

Conversation

@dollspace-gay
Copy link
Copy Markdown

@dollspace-gay dollspace-gay commented May 15, 2026

Summary

Fixes GH#600. SharedWriter::{add,remove}_{blocker,label,relation} now short-circuit before write_commit_push when no change is needed, so crosslink issue block <a> <b> exits 0 when <a> is already blocked by <b> (previously failed with a confusing git commit […] in cache failed: error caused by the empty index path — see #601 for the underlying stdout-capture bug).

Changes

  • Bug fix (shared_writer/mutations.rs): All six mutations gain an early-return guard that loads the issue, checks for the no-op condition, and returns without touching git. Signatures change Result<()>Result<bool> (true = mutated, false = no-op short-circuit).
  • UX consistency (commands/{deps,label,relate}.rs): Writer branches now use the new bool to print differentiated messages (Dependency already exists, Label 'X' already exists on issue …, Issues X and Y are already related, plus symmetric remove-not-present messages) — matching what the non-writer branches already did.
  • Tests (shared_writer/tests.rs): Tightened test_add_label_idempotent (it was using let _ = to swallow the bug, with a // duplicate -- may error on empty commit comment). Added five new regression tests: test_remove_label_idempotent, test_{add,remove}_blocker_idempotent, test_{add,remove}_relation_idempotent.
  • Pre-existing clippy cleanup (5 unrelated files): Fixed 20 clippy::pedantic warnings that were already on develop, so cargo clippy --lib --bin crosslink --tests -- -D warnings passes again. lock_check.rs had 11 instances of the same map(|s| !s.success()).unwrap_or(true) pattern; others touch container.rs, compaction.rs, sentinel/collect.rs, sync/tests.rs.

Why Result<bool> instead of silent short-circuit

The reported defect is about exit code, but the writer-branch UX was also inconsistent with the non-writer branch (which already returns bool via db.add_dependency etc. and prints Dependency already exists accordingly). Threading the bool through gives the writer-branch the same honest feedback rather than silently printing "Issue X is now blocked by Y" on a no-op.

Out of scope

Test plan

  • cargo test --lib — 1888 passed
  • cargo test --bin crosslink — 2864 passed (includes the new 6 idempotency tests and the existing test_block_duplicate / test_add_duplicate_label / test_add_duplicate_relation that exercise the non-writer branch)
  • cargo clippy --lib --bin crosslink --tests -- -D warnings — clean
  • Manual repro from the issue: crosslink issue block L2 L1 twice in a row → both exit 0, second prints Dependency already exists

🤖 Generated with Claude Code

…600)

SharedWriter::{add,remove}_{blocker,label,relation} now short-circuit
before write_commit_push when no change is needed, avoiding the empty
git commit that previously failed with a confusing "git commit […] in
cache failed:" error. (Git emits the "nothing to commit" hint on stdout,
which git_commit_in_cache_with_args drops — see #601.)

Method signatures change Result<()> -> Result<bool> (true = mutated,
false = no-op). commands::{deps,label,relate} writer branches use the
new bool to print differentiated "Dependency already exists" /
"Label '<x>' already exists" / "Issues X and Y are already related"
messages, matching what their non-writer counterparts already did.

Tightened test_add_label_idempotent (was swallowing the bug with
`let _ =`) and added regression tests for the five sibling mutations.

Also fixes 20 pre-existing clippy::pedantic warnings in lock_check.rs
(11x map_unwrap_or on identical pattern), container.rs, compaction.rs,
sentinel/collect.rs, and sync/tests.rs so cargo clippy -D warnings
passes again.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dollspace-gay dollspace-gay self-assigned this May 15, 2026
@dollspace-gay dollspace-gay added the bug Something isn't working label May 15, 2026
@dollspace-gay dollspace-gay merged commit a65e3d4 into develop May 15, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

crosslink issue block exits non-zero when the blocker is already set

1 participant