chore: import upstream snapshot with attribution
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:30:44 +08:00
commit bcbd1bdb22
5748 changed files with 562488 additions and 0 deletions
+303
View File
@@ -0,0 +1,303 @@
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
import pytest
from mirage.resource.ram import RAMResource
from mirage.server.version.api import (branch, checkout, commit, commit_state,
diff_live_vs_ref, read_version,
resolve_ref, snapshot_tree, status,
status_state, version_diff, version_log)
from mirage.server.version.backend import LocalBackend
from mirage.server.version.errors import NoSuchBranchError
from mirage.server.version.state_tree import META_PATH
from mirage.server.version.store import VersionStore
from mirage.types import CacheKey, MountMode, StateKey
from mirage.workspace import Workspace
from mirage.workspace.snapshot import to_state_dict
def _cache_entry(data: bytes) -> dict:
return {
CacheKey.KEY: "k",
CacheKey.DATA: data,
CacheKey.FINGERPRINT: None,
CacheKey.TTL: None,
CacheKey.CACHED_AT: 0.0,
CacheKey.SIZE: len(data),
}
@pytest.mark.asyncio
async def test_snapshot_tree_contains_files_and_meta(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
await ws.execute("echo hello > /m/a.txt")
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
tree = await snapshot_tree(store, ws)
contents = await store.read_tree(tree)
assert META_PATH in contents
assert await store.read_blob(contents["m/a.txt"]) == b"hello\n"
@pytest.mark.asyncio
async def test_commit_advances_branch_and_links_parent(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
c1 = await commit(store, ws, branch="main", message="first")
await ws.execute("echo two > /m/a.txt")
c2 = await commit(store, ws, branch="main", message="second")
assert await store.head("main") == c2
assert (await store.read_commit(c2)).parents == [c1]
assert await store.log("main") == [c2, c1]
@pytest.mark.asyncio
async def test_version_log_lists_messages_newest_first(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
await commit(store, ws, message="first")
await ws.execute("echo two > /m/a.txt")
await commit(store, ws, message="second")
log = await version_log(store, "main")
assert [entry["message"] for entry in log] == ["second", "first"]
@pytest.mark.asyncio
async def test_version_diff_reports_changed_files_only(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
c1 = await commit(store, ws, message="first")
await ws.execute("echo two > /m/a.txt")
await ws.execute("echo new > /m/b.txt")
c2 = await commit(store, ws, message="second")
diff = await version_diff(store, c1, c2)
assert diff["modified"] == ["m/a.txt"]
assert diff["added"] == ["m/b.txt"]
assert META_PATH not in diff["modified"]
@pytest.mark.asyncio
async def test_diff_live_vs_ref_reports_changes_against_version(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
c1 = await commit(store, ws, branch="main", message="first")
await ws.execute("echo two > /m/a.txt")
await ws.execute("echo new > /m/b.txt")
by_oid = await diff_live_vs_ref(store, await to_state_dict(ws), c1)
assert by_oid["modified"] == ["m/a.txt"]
assert by_oid["added"] == ["m/b.txt"]
by_branch = await diff_live_vs_ref(store, await to_state_dict(ws), "main")
assert by_branch == by_oid
@pytest.mark.asyncio
async def test_status_reports_uncommitted_changes(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
await commit(store, ws, message="first")
await ws.execute("echo changed > /m/a.txt")
st = await status(store, ws, "main")
assert st["modified"] == ["m/a.txt"]
@pytest.mark.asyncio
async def test_diff_ignores_cache_churn(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
s1 = await to_state_dict(ws)
s1[StateKey.CACHE][CacheKey.ENTRIES] = [_cache_entry(b"AAA")]
c1 = await commit_state(store, s1, message="first")
s2 = await to_state_dict(ws)
s2[StateKey.CACHE][CacheKey.ENTRIES] = [_cache_entry(b"BBB")]
c2 = await commit_state(store, s2, message="second")
assert await version_diff(store, c1, c2) == {
"added": [],
"modified": [],
"deleted": [],
}
@pytest.mark.asyncio
async def test_status_state_reports_uncommitted_changes(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
await commit(store, ws, message="first")
await ws.execute("echo changed > /m/a.txt")
st = await status_state(store, await to_state_dict(ws), "main")
assert st["modified"] == ["m/a.txt"]
@pytest.mark.asyncio
async def test_status_state_no_commit_yet_lists_all_as_added(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
st = await status_state(store, await to_state_dict(ws), "main")
assert st == {"added": ["m/a.txt"], "modified": [], "deleted": []}
@pytest.mark.asyncio
async def test_status_ignores_cache_churn(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
s1 = await to_state_dict(ws)
s1[StateKey.CACHE][CacheKey.ENTRIES] = [_cache_entry(b"AAA")]
await commit_state(store, s1, message="first")
live = await to_state_dict(ws)
live[StateKey.CACHE][CacheKey.ENTRIES] = [_cache_entry(b"BBB")]
st = await status_state(store, live, "main")
assert st == {"added": [], "modified": [], "deleted": []}
@pytest.mark.asyncio
async def test_resolve_ref_branch_and_oid(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
c1 = await commit(store, ws, branch="main", message="first")
assert await resolve_ref(store, "main") == c1
assert await resolve_ref(store, c1) == c1
assert await resolve_ref(store, c1.decode()) == c1
@pytest.mark.asyncio
async def test_commit_state_creates_version_from_state(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo hi > /m/a.txt")
version = await commit_state(store,
await to_state_dict(ws),
branch="main",
message="from state")
entries, _ = await read_version(store, version)
assert entries["m/a.txt"] == b"hi\n"
@pytest.mark.asyncio
async def test_commit_to_unknown_branch_errors(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
await commit(store, ws, branch="main", message="first")
with pytest.raises(NoSuchBranchError):
await commit(store, ws, branch="exp", message="oops")
@pytest.mark.asyncio
async def test_commit_diverges_after_branch_created(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
main_head = await commit(store, ws, branch="main", message="first")
await branch(store, "exp", from_branch="main")
await ws.execute("echo two > /m/a.txt")
exp_head = await commit(store, ws, branch="exp", message="on exp")
assert (await store.read_commit(exp_head)).parents == [main_head]
assert await store.head("main") == main_head
@pytest.mark.asyncio
async def test_branch_creates_line_at_current(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo one > /m/a.txt")
c1 = await commit(store, ws, branch="main", message="first")
await branch(store, "exp", from_branch="main")
assert await store.head("exp") == c1
assert "exp" in await store.branches()
@pytest.mark.asyncio
async def test_read_version_reads_back_files_and_meta(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo hello > /m/a.txt")
version = await commit(store, ws, message="first")
entries, meta = await read_version(store, version)
assert entries["m/a.txt"] == b"hello\n"
assert META_PATH not in entries
assert "/m/" in [m["prefix"] for m in meta["mounts"]]
@pytest.mark.asyncio
async def test_checkout_rebuilds_content_in_place(tmp_path):
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
await ws.execute("echo original > /m/a.txt")
await commit(store, ws, branch="main", message="first")
await ws.execute("echo mutated > /m/a.txt")
await ws.execute("echo extra > /m/b.txt")
await checkout(store, ws, "main")
result = await ws.execute("cat /m/a.txt")
assert (await result.stdout_str()) == "original\n"
assert await status(store, ws, "main") == {
"added": [],
"modified": [],
"deleted": [],
}
@@ -0,0 +1,45 @@
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
from pathlib import Path
from dulwich.objects import Blob
from mirage.server.version.backend import LocalBackend
def test_open_repo_creates_bare_repo_under_workspace_id(tmp_path: Path):
backend = LocalBackend(tmp_path)
backend.open_repo("ws1")
assert (tmp_path / "ws1" / "objects").is_dir()
assert (tmp_path / "ws1" / "HEAD").exists()
def test_open_repo_reuses_existing(tmp_path: Path):
backend = LocalBackend(tmp_path)
repo1 = backend.open_repo("ws1")
blob = Blob.from_string(b"x")
repo1.object_store.add_object(blob)
repo2 = backend.open_repo("ws1")
assert blob.id in repo2.object_store
def test_distinct_workspace_ids_are_isolated(tmp_path: Path):
backend = LocalBackend(tmp_path)
repo_a = backend.open_repo("a")
repo_b = backend.open_repo("b")
blob = Blob.from_string(b"only-in-a")
repo_a.object_store.add_object(blob)
assert blob.id in repo_a.object_store
assert blob.id not in repo_b.object_store
@@ -0,0 +1,204 @@
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
import io
import pytest
from mirage.resource.ram import RAMResource
from mirage.server.version.state_tree import (blob_to_meta, meta_to_blob,
to_state, to_tree_inputs,
tree_inputs_from_state)
from mirage.types import (CacheKey, FingerprintKey, MountKey, MountMode,
SessionKey, StateKey)
from mirage.workspace import Workspace
from mirage.workspace.snapshot.manifest import split_manifest_and_blobs
from mirage.workspace.snapshot.state import to_state_dict
from mirage.workspace.snapshot.tar_io import read_tar, write_tar
def _mount_files(state: dict, prefix: str) -> dict:
for mount in state["mounts"]:
if mount["prefix"] == prefix:
return mount["resource_state"]["files"]
raise KeyError(prefix)
@pytest.mark.asyncio
async def test_to_tree_inputs_ram_files():
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
await ws.execute("echo hello > /m/a.txt")
await ws.execute("mkdir -p /m/sub && echo world > /m/sub/b.txt")
entries, meta = await to_tree_inputs(ws)
assert entries["m/a.txt"] == b"hello\n"
assert entries["m/sub/b.txt"] == b"world\n"
prefixes = [m[MountKey.PREFIX] for m in meta["mounts"]]
assert "/m/" in prefixes
@pytest.mark.asyncio
async def test_to_state_round_trips_files():
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
await ws.execute("echo hello > /m/a.txt")
await ws.execute("mkdir -p /m/sub && echo world > /m/sub/b.txt")
original_files = _mount_files(await to_state_dict(ws), "/m/")
entries, meta = await to_tree_inputs(ws)
state = to_state(entries, meta)
assert _mount_files(state, "/m/") == original_files
@pytest.mark.asyncio
async def test_tree_inputs_from_state_matches_ws_path():
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
await ws.execute("echo hi > /m/a.txt")
entries_ws, _ = await to_tree_inputs(ws)
entries_state, _ = tree_inputs_from_state(await to_state_dict(ws))
assert entries_ws == entries_state
assert entries_state["m/a.txt"] == b"hi\n"
@pytest.mark.asyncio
async def test_to_state_is_tar_loadable():
ws = Workspace({"/m": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
await ws.execute("echo hello > /m/a.txt")
entries, meta = await to_tree_inputs(ws)
state = to_state(entries, meta)
manifest, blobs = split_manifest_and_blobs(state)
buf = io.BytesIO()
write_tar(buf, manifest, blobs)
buf.seek(0)
restored = read_tar(buf)
assert _mount_files(restored, "/m/")["/a.txt"] == b"hello\n"
@pytest.mark.asyncio
async def test_cache_fingerprints_sessions_round_trip():
ws = Workspace({"/": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
await ws.execute("echo hi > /a.txt")
state = await to_state_dict(ws)
state[StateKey.CACHE][CacheKey.ENTRIES] = [{
CacheKey.KEY: "/a.txt",
CacheKey.DATA: b"cached-bytes",
CacheKey.FINGERPRINT: "etag-1",
CacheKey.TTL: None,
CacheKey.CACHED_AT: 123.0,
CacheKey.SIZE: 12,
}]
state[StateKey.FINGERPRINTS] = [{
FingerprintKey.PATH: "/a.txt",
FingerprintKey.MOUNT_PREFIX: "/",
FingerprintKey.FINGERPRINT: "etag-1",
FingerprintKey.REVISION: "v1",
}]
state[StateKey.SESSIONS] = [{
SessionKey.SESSION_ID: "agent_a",
SessionKey.CWD: "/sub",
SessionKey.ENV: {
"FOO": "bar"
},
}]
entries, meta = tree_inputs_from_state(state)
meta = blob_to_meta(meta_to_blob(meta))
restored = to_state(entries, meta)
cache_entries = restored[StateKey.CACHE][CacheKey.ENTRIES]
assert len(cache_entries) == 1
assert cache_entries[0][CacheKey.DATA] == b"cached-bytes"
assert cache_entries[0][CacheKey.KEY] == "/a.txt"
assert restored[StateKey.FINGERPRINTS][0][FingerprintKey.REVISION] == "v1"
assert restored[StateKey.SESSIONS][0][SessionKey.CWD] == "/sub"
assert restored[StateKey.SESSIONS][0][SessionKey.ENV] == {"FOO": "bar"}
files = _mount_files(restored, "/")
assert files["/a.txt"] == b"hi\n"
assert all(".mirage-cache" not in k for k in files)
@pytest.mark.asyncio
async def test_cache_and_pins_survive_tar():
ws = Workspace({"/": (RAMResource(), MountMode.WRITE)},
mode=MountMode.WRITE)
await ws.execute("echo hi > /a.txt")
state = await to_state_dict(ws)
state[StateKey.CACHE][CacheKey.ENTRIES] = [{
CacheKey.KEY: "/a.txt",
CacheKey.DATA: b"cached-bytes",
CacheKey.FINGERPRINT: "etag-1",
CacheKey.TTL: None,
CacheKey.CACHED_AT: 1.0,
CacheKey.SIZE: 12,
}]
state[StateKey.FINGERPRINTS] = [{
FingerprintKey.PATH: "/a.txt",
FingerprintKey.MOUNT_PREFIX: "/",
FingerprintKey.REVISION: "v1",
}]
state[StateKey.SESSIONS] = [{
SessionKey.SESSION_ID: "agent_a",
SessionKey.CWD: "/sub",
SessionKey.ENV: {
"FOO": "bar"
},
}]
entries, meta = tree_inputs_from_state(state)
meta = blob_to_meta(meta_to_blob(meta))
rebuilt = to_state(entries, meta)
manifest, blobs = split_manifest_and_blobs(rebuilt)
buf = io.BytesIO()
write_tar(buf, manifest, blobs)
buf.seek(0)
restored = read_tar(buf)
ce = restored[StateKey.CACHE][CacheKey.ENTRIES]
assert ce[0][CacheKey.DATA] == b"cached-bytes"
assert restored[StateKey.FINGERPRINTS][0][FingerprintKey.REVISION] == "v1"
sessions = {
s[SessionKey.SESSION_ID]: s
for s in restored[StateKey.SESSIONS]
}
assert sessions["agent_a"][SessionKey.CWD] == "/sub"
def test_meta_blob_round_trip():
meta = {
"mounts": [],
"pins": {
"/s3/a.txt": {
"rev": "v123",
"fp": "etag-abc"
}
},
}
parsed = blob_to_meta(meta_to_blob(meta))
assert parsed["pins"]["/s3/a.txt"] == {"rev": "v123", "fp": "etag-abc"}
+158
View File
@@ -0,0 +1,158 @@
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
from pathlib import Path
import pytest
from mirage.server.version.backend import LocalBackend
from mirage.server.version.errors import HeadMovedError
from mirage.server.version.store import VersionStore
@pytest.mark.asyncio
async def test_open_creates_bare_repo(tmp_path: Path):
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
assert store is not None
assert (tmp_path / "ws" / "objects").is_dir()
assert (tmp_path / "ws" / "HEAD").is_file()
@pytest.mark.asyncio
async def test_open_reuses_existing_repo(tmp_path: Path):
backend = LocalBackend(tmp_path)
await VersionStore.open(backend, "ws")
reopened = await VersionStore.open(backend, "ws")
assert reopened is not None
@pytest.mark.asyncio
async def test_blob_roundtrip(tmp_path: Path):
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
oid = await store.write_blob(b"hello")
assert await store.read_blob(oid) == b"hello"
@pytest.mark.asyncio
async def test_identical_blobs_dedup(tmp_path: Path):
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
first = await store.write_blob(b"same-bytes")
second = await store.write_blob(b"same-bytes")
assert first == second
@pytest.mark.asyncio
async def test_tree_roundtrip(tmp_path: Path):
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
a = await store.write_blob(b"aaa")
b = await store.write_blob(b"bbb")
tree = await store.write_tree({"a.txt": a, "dir/b.txt": b})
assert await store.read_tree(tree) == {"a.txt": a, "dir/b.txt": b}
@pytest.mark.asyncio
async def test_tree_nested_paths(tmp_path: Path):
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
x = await store.write_blob(b"x")
y = await store.write_blob(b"y")
z = await store.write_blob(b"z")
tree = await store.write_tree({
"top.txt": x,
"d/one.txt": y,
"d/sub/two.txt": z,
})
assert await store.read_tree(tree) == {
"top.txt": x,
"d/one.txt": y,
"d/sub/two.txt": z,
}
@pytest.mark.asyncio
async def test_commit_advances_branch(tmp_path: Path):
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
t1 = await store.write_tree({"a.txt": await store.write_blob(b"v1")})
c1 = await store.commit(t1, parents=[], branch="main", message="first")
assert await store.head("main") == c1
t2 = await store.write_tree({"a.txt": await store.write_blob(b"v2")})
c2 = await store.commit(t2, parents=[c1], branch="main", message="second")
assert await store.head("main") == c2
commit = await store.read_commit(c2)
assert commit.parents == [c1]
assert commit.message == b"second"
@pytest.mark.asyncio
async def test_commit_rejects_stale_head(tmp_path: Path):
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
c1 = await store.commit(await store.write_tree(
{"a.txt": await store.write_blob(b"v1")}),
parents=[],
branch="main",
message="first")
c2 = await store.commit(await store.write_tree(
{"a.txt": await store.write_blob(b"v2")}),
parents=[c1],
branch="main",
message="second")
assert await store.head("main") == c2
with pytest.raises(HeadMovedError):
await store.commit(await store.write_tree(
{"a.txt": await store.write_blob(b"v3")}),
parents=[c1],
branch="main",
message="stale")
assert await store.head("main") == c2
@pytest.mark.asyncio
async def test_branches_and_log(tmp_path: Path):
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
t1 = await store.write_tree({"a.txt": await store.write_blob(b"v1")})
c1 = await store.commit(t1, parents=[], branch="main", message="first")
t2 = await store.write_tree({"a.txt": await store.write_blob(b"v2")})
c2 = await store.commit(t2, parents=[c1], branch="main", message="second")
assert await store.branches() == ["main"]
assert await store.log("main") == [c2, c1]
@pytest.mark.asyncio
async def test_tree_diff(tmp_path: Path):
store = await VersionStore.open(LocalBackend(tmp_path), "ws")
keep = await store.write_blob(b"keep")
before = await store.write_blob(b"before")
after = await store.write_blob(b"after")
gone = await store.write_blob(b"gone")
new = await store.write_blob(b"new")
tree_a = await store.write_tree({
"keep.txt": keep,
"change.txt": before,
"gone.txt": gone,
})
tree_b = await store.write_tree({
"keep.txt": keep,
"change.txt": after,
"new.txt": new,
})
assert await store.diff(tree_a, tree_b) == {
"added": ["new.txt"],
"modified": ["change.txt"],
"deleted": ["gone.txt"],
}