Grimoire keeps its own SECRET_KEY, docker-compose.yml is the deploy compose, a repo rename moves its snippets; logo, README, licence #214

Merged
bvandeusen merged 5 commits from dev into main 2026-10-22 16:42:34 -04:00
2 changed files with 45 additions and 5 deletions
Showing only changes of commit f77d18cb63 - Show all commits
+13 -4
View File
@@ -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,
)
+32 -1
View File
@@ -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