From 4dd425f1f11fdb3c794c9af721252a6b95b8bb5d Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Sun, 4 Oct 2026 11:18:08 +0100 Subject: [PATCH] Fix wallpaper upgrade compatibility and Settings icon clipping Allow installed releases to omit the two newer appearance wallpapers while keeping new bundle verification strict. Fit the Settings header symbol within its square slot without clipping. Verified 30 installer tests, the real upgrade dry-run, and release rendering previews on GPU and software backends. --- scripts/installer/install.py | 13 +++++++++--- scripts/tests/test_portal_install.py | 30 ++++++++++++++++++++++++++++ shell/ferese-settings/src/visuals.rs | 1 + 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/scripts/installer/install.py b/scripts/installer/install.py index 3d2a183..99a444c 100644 --- a/scripts/installer/install.py +++ b/scripts/installer/install.py @@ -125,7 +125,7 @@ def record(rule, name=None): for key, value in rule.items() if key != 'source'} -def validate_bundle(bundle): +def validate_bundle(bundle, *, installed=False): if bundle.is_symlink() or not bundle.is_dir(): fail(f'Bundle must be a directory, not a symlink: {bundle}') @@ -162,7 +162,14 @@ def validate_bundle(bundle): seen.add(target) actual = {str(path.relative_to(bundle)) for path in bundle.rglob('*') if path.is_file()} - if not expected.keys() <= seen or actual != seen | {'manifest.json'}: + required = expected.keys() + if installed: + # Installed releases may predate the appearance-specific wallpapers. + # New bundles must include them; upgrades and rollback verify the older + # release's recorded files without requiring these later additions. + required = required - {'wallpapers/ferese-wallpaper-dark.jpg', 'wallpapers/ferese-wallpaper-light.png'} + + if not required <= seen or actual != seen | {'manifest.json'}: fail('Bundle is incomplete or contains unlisted files') return manifest @@ -277,7 +284,7 @@ class Installation: if not (directory / 'manifest.json').is_file(): fail(f'Release {release} predates verified bundles; select a bundled release for rollback') - return validate_bundle(directory) + return validate_bundle(directory, installed=True) def current_publication(self, current): if not current: diff --git a/scripts/tests/test_portal_install.py b/scripts/tests/test_portal_install.py index 1b6a528..4a51324 100644 --- a/scripts/tests/test_portal_install.py +++ b/scripts/tests/test_portal_install.py @@ -112,6 +112,36 @@ m.main() for name in ('ferese-session', 'ferese-session-shell', 'ferese-screenshot'): self.assertEqual((self.bundles[0] / name).stat().st_mode & 0o777, 0o755) + def without_appearance_wallpapers(self, bundle): + manifest_path = bundle / 'manifest.json' + manifest = json.loads(manifest_path.read_text()) + removed = {'wallpapers/ferese-wallpaper-dark.jpg', 'wallpapers/ferese-wallpaper-light.png'} + for target in removed: + (bundle / target).unlink() + + manifest['files'] = [item for item in manifest['files'] if item['target'] not in removed] + manifest_path.write_text(json.dumps(manifest)) + + def test_upgrade_and_rollback_accept_installed_release_before_appearance_wallpapers(self): + self.install() + legacy = self.base / 'releases/first' + self.without_appearance_wallpapers(legacy) + self.install(1) + self.run_command('rollback') + self.assertEqual(os.readlink(self.base / 'current'), 'releases/first') + self.assertEqual(installer.Installation(self.root).manifest('first')['release'], 'first') + (legacy / 'ferese').write_bytes(b'corrupt') + with self.assertRaisesRegex(ValueError, 'Checksum mismatch'): + installer.Installation(self.root).manifest('first') + + def test_new_bundle_requires_appearance_wallpapers(self): + incomplete = Path(self.temporary.name) / 'incomplete' + shutil.copytree(self.bundles[0], incomplete) + self.without_appearance_wallpapers(incomplete) + result = self.run_command('install', incomplete, success=False) + self.assertIn('Bundle is incomplete', result.stderr) + self.assertFalse((self.base / 'current').exists()) + def test_fresh_upgrade_and_rollback_restore_all_integration(self): self.install() first = [(self.root / path).read_bytes() for path in (PORTAL, UNIT, DESKTOP)] diff --git a/shell/ferese-settings/src/visuals.rs b/shell/ferese-settings/src/visuals.rs index 829486e..63c7bbc 100644 --- a/shell/ferese-settings/src/visuals.rs +++ b/shell/ferese-settings/src/visuals.rs @@ -34,6 +34,7 @@ pub fn brand_icon() -> svg_icon::Icon { .symbolic(false) .icon() .size(32) + .content_fit(cosmic::iced::ContentFit::Contain) } pub fn action_icon(path: &str, tint: Color) -> svg_icon::Icon {