fix(6245): a re-run of bind_repo(moved_from=…) finishes an earlier move
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 14s
CI & Build / TypeScript typecheck (push) Successful in 59s
CI & Build / integration (push) Successful in 1m25s
CI & Build / Python tests (push) Successful in 2m20s
CI & Build / Build & push image (push) Successful in 32s
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 14s
CI & Build / TypeScript typecheck (push) Successful in 59s
CI & Build / integration (push) Successful in 1m25s
CI & Build / Python tests (push) Successful in 2m20s
CI & Build / Build & push image (push) Successful in 32s
Once the binding has moved, the old remote is no longer bound, and move_binding refused. An install that renamed its repo before snippet locations moved with it had no way to move them. When the old remote is unbound and the new one is bound to this project, bind_repo now skips the binding move and still moves the snippet locations that name the old repo. The snippet-move test gives each location its own path: rewritten to one repo, identical locations merge into one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -34,8 +34,10 @@ async def bind_repo(
|
||||
under the old one. Pass the old remote as `moved_from` and the binding,
|
||||
every shape judgment, and every snippet location recorded in the old repo
|
||||
move to the new name together. Binding the new name without it starts an
|
||||
empty ledger beside the old one. A snippet shared with you read-only keeps
|
||||
its location and is listed in `snippets_read_only`; its owner moves it.
|
||||
empty ledger beside the old one. Running it again once the binding has
|
||||
moved moves only what still names the old repo. A snippet shared with you
|
||||
read-only keeps its location and is listed in `snippets_read_only`; its
|
||||
owner moves it.
|
||||
|
||||
Args:
|
||||
repo_url: the repo's git remote (e.g. the output of
|
||||
@@ -54,9 +56,16 @@ async def bind_repo(
|
||||
ref_arg = None if not ref else ("" if ref.strip() == "-" else ref)
|
||||
moved = snippets = None
|
||||
if moved_from:
|
||||
_, moved = await repo_bindings_svc.move_binding(
|
||||
uid, moved_from, repo_url, project_id,
|
||||
already = (
|
||||
await repo_bindings_svc.resolve_project(uid, moved_from) is None
|
||||
and await repo_bindings_svc.resolve_project(uid, repo_url) == project_id
|
||||
)
|
||||
if already:
|
||||
moved = 0
|
||||
else:
|
||||
_, moved = await repo_bindings_svc.move_binding(
|
||||
uid, moved_from, repo_url, project_id,
|
||||
)
|
||||
snippets = await snippets_svc.move_location_repo(
|
||||
uid, project_id, moved_from, repo_url,
|
||||
)
|
||||
|
||||
@@ -112,7 +112,12 @@ async def test_the_snippets_recorded_in_the_old_repo_move_with_it(bound):
|
||||
note = await snippets_svc.create_snippet(
|
||||
owner, name=name, code=f"def {name}():\n pass\n", language="python",
|
||||
project_id=pid,
|
||||
locations=[{"repo": r, "path": "src/app.py", "symbol": name} for r in repos],
|
||||
# A path per location: rewritten to one repo, identical locations
|
||||
# would merge into one.
|
||||
locations=[
|
||||
{"repo": r, "path": f"src/app{i}.py", "symbol": name}
|
||||
for i, r in enumerate(repos)
|
||||
],
|
||||
)
|
||||
return int(note.id)
|
||||
|
||||
@@ -132,3 +137,29 @@ async def test_the_snippets_recorded_in_the_old_repo_move_with_it(bound):
|
||||
assert await repos(moved_one) == [NEW_KEY, NEW_KEY, NEW_KEY]
|
||||
assert await repos(mixed) == [NEW_KEY, "elsewhere/gadget"]
|
||||
assert await repos(untouched) == ["Gadget", "git.example.com/alice/oldnamesake"]
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_running_the_move_again_finishes_what_an_earlier_one_left(bound):
|
||||
from grimoire.mcp._context import _user_id_ctx
|
||||
from grimoire.mcp.tools.repos import bind_repo
|
||||
from grimoire.services import snippets as snippets_svc
|
||||
|
||||
owner, pid = bound["owner"], bound["pid"]
|
||||
await svc.move_binding(owner, OLD, NEW, pid)
|
||||
note = await snippets_svc.create_snippet(
|
||||
owner, name="left_behind", code="def left_behind():\n pass\n",
|
||||
language="python", project_id=pid,
|
||||
locations=[{"repo": "OldName", "path": "src/app.py", "symbol": "left_behind"}],
|
||||
)
|
||||
|
||||
token = _user_id_ctx.set(owner)
|
||||
try:
|
||||
out = await bind_repo(NEW, pid, moved_from=OLD)
|
||||
finally:
|
||||
_user_id_ctx.reset(token)
|
||||
|
||||
assert out["shapes_moved"] == 0
|
||||
assert out["snippets_moved"] == [int(note.id)]
|
||||
moved = await snippets_svc.get_snippet(owner, int(note.id))
|
||||
assert snippets_svc.snippet_fields(moved)["locations"][0]["repo"] == NEW_KEY
|
||||
|
||||
Reference in New Issue
Block a user