Make rollback a GRUB snapshot reboot
Some checks failed
dev release / build (push) Has been cancelled

Updates leads with “Boot a snapshot from GRUB (BOS snapshots)”
and links to Snapshots. Snapshots is the list to pick in GRUB,
not snapper rollback.
This commit is contained in:
Breadway 2026-08-16 00:48:25 +08:00
parent 0798fad697
commit 3aad09c9ef
4 changed files with 36 additions and 8 deletions

3
frontend/src/lib/nav.ts Normal file
View file

@ -0,0 +1,3 @@
/** Sidebar page switch. Set from +page.svelte; views call it to jump. */
export type Navigate = (page: string) => void;
export const NAVIGATE_KEY = "bos-settings-navigate";

View file

@ -42,7 +42,7 @@
if (!selected) return;
if (
confirm(
`Boot into snapshot #${selected}? Snapshots on BOS are booted directly from the GRUB menu (under "BOS snapshots"), not rolled back in place. Reboot now and pick this snapshot there.`,
`Reboot to pick snapshot #${selected} in GRUB? BOS boots snapshots from the GRUB “BOS snapshots” submenu. This does not run snapper rollback.`,
)
) {
invoke("reboot_system");
@ -62,9 +62,10 @@
</script>
<ViewScaffold title="Snapshots">
<Hint text="This is how you undo a bad update: reboot and pick the snapshot in GRUB (BOS snapshots)." />
<Group
title="System snapshots"
hint="Created automatically by snap-pac on each pacman transaction. Boot into one from the GRUB menu to recover; delete old ones here."
title="What to pick in GRUB"
hint="Number, date, and description match the GRUB “BOS snapshots” submenu. Reboot, then choose that entry. This page does not run snapper rollback."
wide
>
<div class="list">
@ -75,6 +76,11 @@
{:else if snapshots.length === 0}
<EmptyState icon={History} title="No snapshots yet" hint="Snapshots are created automatically on every pacman transaction." />
{:else}
<div class="row header" aria-hidden="true">
<span class="number">#</span>
<span class="date">Date</span>
<span class="desc">Description</span>
</div>
{#each snapshots as snap (snap.number)}
<button
class="row"
@ -91,7 +97,7 @@
<div class="btn-row">
<button onclick={refresh}>Refresh</button>
<button disabled={!selected} onclick={bootIntoSelected}>Boot into selected…</button>
<button disabled={!selected} onclick={bootIntoSelected}>Reboot to pick in GRUB</button>
<button class="destructive" disabled={!selected} onclick={deleteSelected}>Delete selected</button>
</div>
</Group>
@ -121,7 +127,15 @@
min-width: 0;
}
.row:hover {
.row.header {
background: transparent;
cursor: default;
opacity: 0.55;
font-size: var(--font-size-secondary, 12px);
padding-top: 0;
}
.row:hover:not(.header) {
background-color: color-mix(in srgb, var(--surface), var(--on-surface) 8%);
}

View file

@ -1,5 +1,5 @@
<script lang="ts">
import { onMount } from "svelte";
import { getContext, onMount } from "svelte";
import { invoke } from "@tauri-apps/api/core";
import { runStreamed } from "$lib/streaming";
import ViewScaffold from "$lib/components/ViewScaffold.svelte";
@ -7,9 +7,12 @@
import Hint from "$lib/components/Hint.svelte";
import EmptyState from "$lib/components/EmptyState.svelte";
import LogView from "$lib/components/LogView.svelte";
import { NAVIGATE_KEY, type Navigate } from "$lib/nav";
import Download from "@lucide/svelte/icons/download";
import Cpu from "@lucide/svelte/icons/cpu";
const navigate = getContext<Navigate | undefined>(NAVIGATE_KEY);
interface PendingUpdate {
name: string;
current: string;
@ -156,9 +159,13 @@
<Group
title="Rollback"
hint="BOS pins GRUB to rootflags=subvol=@, so snapper rollback does not change the running root. Boot a snapshot from the GRUB “BOS snapshots” submenu (grub-btrfs), or use the Snapshots page to reboot and pick one there."
hint="Boot a snapshot from GRUB (BOS snapshots)."
>
<Hint text="Snapshots lists number, date, and description so you know which GRUB entry to pick. snapper rollback will not change what GRUB boots (rootflags=subvol=@)." />
<Hint text="Bakery also has bakery rollback <pkg> for a single ecosystem binary — that is not a system rollback." />
<div class="btn-row">
<button disabled={!navigate} onclick={() => navigate?.("snapshots")}>Open Snapshots</button>
</div>
</Group>
<LogView lines={log} />

View file

@ -1,14 +1,18 @@
<script lang="ts">
import { onMount } from "svelte";
import { onMount, setContext } from "svelte";
import { listen } from "@tauri-apps/api/event";
import Sidebar from "$lib/components/Sidebar.svelte";
import Placeholder from "$lib/components/Placeholder.svelte";
import { DEFAULT_PAGE } from "$lib/sidebar";
import { NAVIGATE_KEY, type Navigate } from "$lib/nav";
import { initTheme } from "$lib/theme";
import { VIEWS } from "$lib/views/registry";
let activePage = $state(DEFAULT_PAGE);
let ActiveView = $derived(VIEWS[activePage]);
setContext<Navigate>(NAVIGATE_KEY, (page) => {
activePage = page;
});
onMount(() => {
initTheme();