Prepare 0.3.3 and migrate recognized legacy console wrappers
This commit is contained in:
1 parent
c0a679d989
commit
b1ff87dd81
5 files changed
+55
-4
No files matched your search
@@ -1 +1 @@
|
||||
__version__ = "0.3.2+private.20261028.2"
|
||||
__version__ = "0.3.3"
|
||||
@@ -78,6 +78,38 @@ def _new_entry(state):
|
||||
"StartupWMClass=Gnome-terminal\n").encode()
|
||||
|
||||
|
||||
def _new_wrapper(state):
|
||||
command = ["/usr/bin/fb", "--state-dir", str(state), "console"]
|
||||
return ("#!/usr/bin/python3\n"
|
||||
'"""Open the packaged FrameBridge console using the retained local profile."""\n'
|
||||
"import os\nimport sys\n"
|
||||
"command = " + repr(command) + "\n"
|
||||
"if sys.argv[1:] == ['--inside']:\n"
|
||||
" command += ['--inside', '--mode', 'gui']\n"
|
||||
"elif sys.argv[1:]:\n"
|
||||
" raise SystemExit('Usage: framebridge-console')\n"
|
||||
"os.execv(command[0], command)\n").encode()
|
||||
|
||||
|
||||
def _migrate_wrapper(state, home):
|
||||
path = home / ".local/bin/framebridge-console"
|
||||
before, mode = _snapshot(path)
|
||||
after = _new_wrapper(state)
|
||||
if before == after:
|
||||
return False
|
||||
_need(hashlib.sha256(before).hexdigest() == LEGACY_WRAPPER_SHA256,
|
||||
"CONSOLE_DESKTOP_LEGACY_WRAPPER_CHANGED")
|
||||
backup = state / "console-wrapper-legacy.backup"
|
||||
if backup.exists() or backup.is_symlink():
|
||||
data, backup_mode = _snapshot(backup)
|
||||
_need(data == before and backup_mode == 0o600, "CONSOLE_DESKTOP_WRAPPER_BACKUP_CHANGED")
|
||||
else:
|
||||
_atomic(backup, before)
|
||||
_need(_snapshot(path)[0] == before, "CONSOLE_DESKTOP_WRAPPER_CHANGED_DURING_MIGRATION")
|
||||
_atomic(path, after, mode)
|
||||
return True
|
||||
|
||||
|
||||
def _legacy_identity(node, runtime):
|
||||
return {"socket": runtime / (node.lower() + "-tty1") / "console.sock",
|
||||
"session": node.upper() + "-FBTERM"}
|
||||
@@ -123,7 +155,9 @@ def migrate_legacy(state, *, home=None, node=None, runtime=None):
|
||||
after = _new_entry(state)
|
||||
if before == after:
|
||||
_need(legacy_context(state, node, runtime) is not None, "CONSOLE_DESKTOP_RECORD_MISSING")
|
||||
return {"ok": True, "changed": False, "reason": "ALREADY_MIGRATED"}
|
||||
wrapper_changed = _migrate_wrapper(state, home)
|
||||
return {"ok": True, "changed": wrapper_changed, "reason": "ALREADY_MIGRATED",
|
||||
"wrapper_changed": wrapper_changed}
|
||||
if before != _legacy_entry(home):
|
||||
return {"ok": True, "changed": False, "reason": "CUSTOM_DESKTOP_ENTRY_PRESERVED"}
|
||||
wrapper, _ = _snapshot(home / ".local/bin/framebridge-console")
|
||||
@@ -166,6 +200,8 @@ def migrate_legacy(state, *, home=None, node=None, runtime=None):
|
||||
_atomic(state / RECORD, (json.dumps(record, sort_keys=True, indent=2) + "\n").encode())
|
||||
_need(_snapshot(desktop)[0] == before, "CONSOLE_DESKTOP_CHANGED_DURING_MIGRATION")
|
||||
_atomic(desktop, after, mode)
|
||||
wrapper_changed = _migrate_wrapper(state, home)
|
||||
return {"ok": True, "changed": True, "desktop": str(desktop),
|
||||
"wrapper_changed": wrapper_changed,
|
||||
"session": identity["session"], "socket": str(identity["socket"]),
|
||||
"backup": str(backup), "runtime_changed": False}
|
||||
@@ -11,7 +11,7 @@ from pathlib import Path
|
||||
import re
|
||||
|
||||
|
||||
CANDIDATE_VERSION = "0.3.2"
|
||||
CANDIDATE_VERSION = "0.3.3"
|
||||
VENDOR_RELATIVE = Path("original/geranas/FrameBridge-Fleet-Hub/vendor")
|
||||
SOURCE_VENDOR = Path("sources/original-geranas/FrameBridge-Fleet-Hub/vendor")
|
||||
GLIBC_BASELINE = (2, 34)
|
||||
|
||||
@@ -56,6 +56,9 @@ class DesktopMigrationTests(unittest.TestCase):
|
||||
self.assertFalse(value["runtime_changed"])
|
||||
self.assertEqual((self.state / "console-desktop-legacy.backup").read_bytes(), before)
|
||||
self.assertEqual(self.desktop.read_bytes(), console_desktop._new_entry(self.state))
|
||||
self.assertEqual(self.wrapper.read_bytes(), console_desktop._new_wrapper(self.state))
|
||||
self.assertEqual((self.state / "console-wrapper-legacy.backup").read_bytes(), b"#!/usr/bin/python3\npass\n")
|
||||
self.assertTrue(value["wrapper_changed"])
|
||||
context = console_desktop.legacy_context(self.state, "TestHost", self.runtime)
|
||||
self.assertEqual(context["session"], "TESTHOST-FBTERM")
|
||||
self.assertEqual(context["socket"], self.runtime / "testhost-tty1/console.sock")
|
||||
@@ -122,6 +125,18 @@ class ConsoleWindowSelectionTests(unittest.TestCase):
|
||||
value = console.exists()
|
||||
return console, value
|
||||
|
||||
def test_migrated_wrapper_targets_the_packaged_profile_without_a_shell(self):
|
||||
state = Path("/home/user/profile")
|
||||
with mock.patch("sys.argv", ["framebridge-console"]), mock.patch("os.execv") as execute:
|
||||
exec(compile(console_desktop._new_wrapper(state), "wrapper", "exec"), {})
|
||||
execute.assert_called_once_with("/usr/bin/fb", ["/usr/bin/fb", "--state-dir", str(state), "console"])
|
||||
|
||||
def test_migrated_inside_wrapper_does_not_create_another_viewer(self):
|
||||
state = Path("/home/user/profile")
|
||||
with mock.patch("sys.argv", ["framebridge-console", "--inside"]), mock.patch("os.execv") as execute:
|
||||
exec(compile(console_desktop._new_wrapper(state), "wrapper", "exec"), {})
|
||||
self.assertEqual(execute.call_args.args[1][-3:], ["--inside", "--mode", "gui"])
|
||||
|
||||
def test_monitor_receives_profile_jobs_root_as_an_explicit_argument(self):
|
||||
args = SimpleNamespace(socket="/owned/socket", session="NODE-FBTERM", node="NODE",
|
||||
jobs_root=Path("/profile with space/jobs"))
|
||||
|
||||
Reference in new issue
Block a user