From 62c542bea55cb5ed487616cb77cdbe5fd1e01ffa Mon Sep 17 00:00:00 2001 From: Ivan Date: Sat, 15 Aug 2026 14:34:18 -0500 Subject: [PATCH] fix: update file handling in bake_frozen_pycodec2 --- meshchatx.rsm | Bin 195139 -> 195139 bytes meshchatx/src/backend/bake_frozen_pycodec2.py | 10 ++++- tests/backend/test_bake_frozen_pycodec2.py | 34 +++++++++++++++++ tests/frontend/SidebarLink.test.js | 36 ++++++++++++------ 4 files changed, 66 insertions(+), 14 deletions(-) diff --git a/meshchatx.rsm b/meshchatx.rsm index c7031905098db8c04c09b86230a332e39e77892c..3e976502460e1c12f37afd7ed33008cc1419993d 100644 GIT binary patch delta 336 zcmWN~&ntsr8~||dPBIsTB+1HwGJT)l&!c1qhb65Q;UYcH^FD7WOOzT(nJa}_%W9@)_T+|=uA^8NU2H1m=jtnRIZ4`N+?WH++a*7W1)%#x8=v?N`3MAaAP^#&29gJu zTgM2~0xTw28wET0R573Oo-#2ckRMoQnNk#-<%mj5IFnXzO{L)sIQ;VjF$UOBM+K4C z8UkDxWhCUbYhFk3_RDKrj%muQ)((Rpfki}WpCca>2Wt${I#2{*tPyb%6v31l_J3nb T9mdFk%H0)0?ZwVQD4O^Kw=Q^l delta 334 zcmWO0J4ixN9Ds2$48oxoSP_Jj5J|j7&j*j@KmFob*e>sswj6!m&iX30xP8Z)URdwzq zn@@gpjg8#*PxRi6|L(0uXGeFN7un`|Tmi?9a0T)x0}I+w#!4(H!w$xRyP%YkS~^HT zJBk6Qqe08IWte$|Mqzl{PgneOM=clU)*%$Rh&dWz!-P`CP%H((+`~#z0FO}xF4fX7 zFaT}GxFJFl>Ir_(7YT$bk6#_Fn*?E?3_^r?p5?@9Oo^q4b0w&doDmR;GvJaEDFrp{ UQ^b*A%1YO|%8*LuSs;=62degWxc~qF diff --git a/meshchatx/src/backend/bake_frozen_pycodec2.py b/meshchatx/src/backend/bake_frozen_pycodec2.py index b3b796f4..d7a04efe 100644 --- a/meshchatx/src/backend/bake_frozen_pycodec2.py +++ b/meshchatx/src/backend/bake_frozen_pycodec2.py @@ -15,6 +15,7 @@ from __future__ import annotations import importlib.metadata import shutil +import stat import subprocess import sys from pathlib import Path @@ -81,8 +82,13 @@ def _extension_module(pkg: Path) -> Path | None: def _copy_file(src: Path, dest: Path) -> None: dest.parent.mkdir(parents=True, exist_ok=True) - if src.resolve() == dest.resolve(): - return + if dest.is_symlink(): + dest.unlink() + elif dest.exists(): + if src.resolve() == dest.resolve(): + return + dest.chmod(stat.S_IWRITE | stat.S_IREAD) + dest.unlink() shutil.copy2(src, dest) diff --git a/tests/backend/test_bake_frozen_pycodec2.py b/tests/backend/test_bake_frozen_pycodec2.py index 22254083..b3551d14 100644 --- a/tests/backend/test_bake_frozen_pycodec2.py +++ b/tests/backend/test_bake_frozen_pycodec2.py @@ -127,6 +127,40 @@ def test_bake_copies_executable_path_basename_from_load_command( assert (root / "lib" / "libcodec2.dylib").read_bytes() == b"lib" +def test_bake_replaces_symlink_dest_without_writing_through_it(tmp_path: Path) -> None: + root = _frozen_pycodec2_tree(tmp_path) + pkg = root / "lib" / "pycodec2" + (pkg / "libcodec2.dylib").write_bytes(b"canonical") + + cellar = tmp_path / "cellar" + cellar.mkdir() + cellar_lib = cellar / "libcodec2.dylib" + cellar_lib.write_bytes(b"homebrew") + cellar_lib.chmod(0o444) + + dest_lib = root / "lib" / "libcodec2.dylib" + dest_lib.symlink_to(cellar_lib) + + bake_frozen_pycodec2(root) + + assert dest_lib.is_symlink() is False + assert dest_lib.read_bytes() == b"canonical" + assert cellar_lib.read_bytes() == b"homebrew" + + +def test_bake_replaces_readonly_dest_libcodec2(tmp_path: Path) -> None: + root = _frozen_pycodec2_tree(tmp_path) + pkg = root / "lib" / "pycodec2" + (pkg / "libcodec2.dylib").write_bytes(b"canonical") + dest_lib = root / "lib" / "libcodec2.dylib" + dest_lib.write_bytes(b"old") + dest_lib.chmod(0o444) + + bake_frozen_pycodec2(root) + + assert dest_lib.read_bytes() == b"canonical" + + def test_bake_copies_from_build_env_when_freeze_tree_has_no_dylib( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: diff --git a/tests/frontend/SidebarLink.test.js b/tests/frontend/SidebarLink.test.js index 43788b57..7bf80e6d 100644 --- a/tests/frontend/SidebarLink.test.js +++ b/tests/frontend/SidebarLink.test.js @@ -2,18 +2,17 @@ import { mount } from "@vue/test-utils"; import { describe, it, expect } from "vitest"; import SidebarLink from "../../meshchatx/src/frontend/components/SidebarLink.vue"; -const RouterLinkStub = { - name: "RouterLinkStub", - props: ["to"], - template: '', - methods: { - navigate(e) { - if (e) e.preventDefault(); +function mountSidebarLink(props = {}, slots = {}, { isActive = false } = {}) { + const RouterLinkStub = { + name: "RouterLinkStub", + props: ["to"], + template: ``, + methods: { + navigate(e) { + if (e) e.preventDefault(); + }, }, - }, -}; - -function mountSidebarLink(props = {}, slots = {}) { + }; return mount(SidebarLink, { props: { to: { name: "messages" }, ...props }, slots: { @@ -63,11 +62,24 @@ describe("SidebarLink UI", () => { expect(innerLink.exists()).toBe(true); expect(innerLink.classes()).toContain("justify-center"); expect(innerLink.classes()).not.toContain("mr-2"); - expect(innerLink.classes()).toContain("rounded-lg"); + expect(innerLink.classes()).toContain("rounded-none"); + expect(innerLink.classes()).not.toContain("rounded-lg"); expect(wrapper.text()).not.toContain("Messages"); expect(wrapper.find(".icon-slot").exists()).toBe(true); }); + it("uses a square inset well when collapsed and selected", () => { + const wrapper = mountSidebarLink({ isCollapsed: true }, {}, { isActive: true }); + const innerLink = wrapper.find("a.justify-center"); + const className = innerLink.attributes("class"); + expect(innerLink.classes()).toContain("rounded-none"); + expect(innerLink.classes()).not.toContain("rounded-lg"); + expect(innerLink.classes()).not.toContain("bg-blue-100"); + expect(innerLink.classes()).not.toContain("dark:bg-zinc-800"); + expect(className).toContain("shadow-[inset_"); + expect(className).toContain("bg-black/[0.04]"); + }); + it("does not navigate when editMode is on", async () => { const wrapper = mountSidebarLink({ editMode: true }); const innerLink = wrapper.find("a.rounded-r-full");