Fix silent name-collision overwrite on drag-and-drop import (#8) #21

Closed
the_og wants to merge 0 commits from feat/8-dup-name-conflict into main
Owner

Closes #8

Investigation found the Paste-JSON dialog already prompted on a duplicate server name (replace vs. keep-both-renamed), but the drag-and-drop-a-.json-file import path did not — it silently renamed collisions to a fixed -imported suffix without checking that name was itself free, which could let two servers end up with the same name in memory and get silently collapsed into one at save time (apply_servers() in bcc_core.py rebuilds the on-disk dict via {s.name: s.data for s in servers}, last-value-wins).

Changes:

  • bcc_core.py: new pure, tested resolve_name_collision(name, existing) -> str — appends -2, -3, ... until unique.
  • bcc.py: extracted a shared MainWindow._import_server(name, data) helper used by both paste_json and dropEvent; it always prompts on collision (replace / keep-both-renamed) and always resolves the renamed name through resolve_name_collision, so drag-and-drop now behaves identically to paste — no more silent overwrite/collapse.
  • tests/test_core.py: 5 new unit tests for resolve_name_collision (no-conflict passthrough, single collision, multiple taken suffixes, empty existing set, and a repeated-call scenario simulating a double file-drop that previously could collide).

Verified locally: ruff check ., ruff format --check ., and pytest -q all pass (100 tests).

Closes #8 Investigation found the Paste-JSON dialog already prompted on a duplicate server name (replace vs. keep-both-renamed), but the drag-and-drop-a-.json-file import path did not — it silently renamed collisions to a fixed `-imported` suffix without checking that name was itself free, which could let two servers end up with the same name in memory and get silently collapsed into one at save time (`apply_servers()` in bcc_core.py rebuilds the on-disk dict via `{s.name: s.data for s in servers}`, last-value-wins). Changes: - `bcc_core.py`: new pure, tested `resolve_name_collision(name, existing) -> str` — appends `-2`, `-3`, ... until unique. - `bcc.py`: extracted a shared `MainWindow._import_server(name, data)` helper used by both `paste_json` and `dropEvent`; it always prompts on collision (replace / keep-both-renamed) and always resolves the renamed name through `resolve_name_collision`, so drag-and-drop now behaves identically to paste — no more silent overwrite/collapse. - `tests/test_core.py`: 5 new unit tests for `resolve_name_collision` (no-conflict passthrough, single collision, multiple taken suffixes, empty existing set, and a repeated-call scenario simulating a double file-drop that previously could collide). Verified locally: `ruff check .`, `ruff format --check .`, and `pytest -q` all pass (100 tests).
the_og added the P1 label 2026-07-07 20:27:36 -04:00
the_og added 4 commits 2026-07-07 20:27:36 -04:00
the_og added 1 commit 2026-07-07 20:44:40 -04:00
Fix: rebuild from clean main (previous push included unrelated contaminated content)
CI / Lint (ruff) (pull_request) Failing after 6s
CI / Tests (py3.10) (pull_request) Successful in 7s
CI / Tests (py3.12) (pull_request) Successful in 8s
a811e323e6
the_og added 1 commit 2026-07-07 20:48:54 -04:00
Fix: rebuild from clean main (previous push included unrelated contaminated content)
CI / Lint (ruff) (pull_request) Failing after 6s
CI / Tests (py3.10) (pull_request) Successful in 7s
CI / Tests (py3.12) (pull_request) Successful in 7s
3e07b51134
the_og added 1 commit 2026-07-07 20:51:27 -04:00
Fix: rebuild from clean main (previous push included unrelated contaminated content)
CI / Lint (ruff) (pull_request) Failing after 8s
CI / Tests (py3.10) (pull_request) Failing after 8s
CI / Tests (py3.12) (pull_request) Failing after 7s
4ab3c3b00a
the_og added 1 commit 2026-07-07 20:56:16 -04:00
Fix: correct smart-quote/nbsp characters mangled in previous push
CI / Lint (ruff) (pull_request) Successful in 6s
CI / Tests (py3.10) (pull_request) Successful in 8s
CI / Tests (py3.12) (pull_request) Successful in 8s
2d9fb083dc
Author
Owner

Supervisor review (Cowork): approve. CI run #164 green; diff is isolated to bcc.py/bcc_core.py/tests. Good catch — the drag-and-drop path was a genuine silent-overwrite (only paste prompted); extracting _import_server so both paths prompt, plus a pure/tested resolve_name_collision (incl. the drop-twice case), is the right fix. Ready to merge into v1.2.0.

Supervisor review (Cowork): **approve.** CI run #164 green; diff is isolated to `bcc.py`/`bcc_core.py`/`tests`. Good catch — the drag-and-drop path was a genuine silent-overwrite (only paste prompted); extracting `_import_server` so both paths prompt, plus a pure/tested `resolve_name_collision` (incl. the drop-twice case), is the right fix. Ready to merge into v1.2.0.
Author
Owner

Superseded by #26 (release: v1.2.0), which merged this change into main as part of the integrated release. Closing.

Superseded by #26 (release: v1.2.0), which merged this change into `main` as part of the integrated release. Closing.
the_og closed this pull request 2026-07-08 11:35:38 -04:00
Some checks are pending
CI / Lint (ruff) (pull_request) Successful in 6s
CI / Tests (py3.10) (pull_request) Successful in 8s
CI / Tests (py3.12) (pull_request) Successful in 8s

Pull request closed

Sign in to join this conversation.