mirror of
https://github.com/priyanshujain/margin-calendar.git
synced 2026-10-02 11:07:04 +00:00
announce updates rather than install them when a package manager owns the binary
This commit is contained in:
1 parent
ae5a7b4c0e
commit
958931f5ef
4 files changed
+79
-1
No files matched your search
+12
-1
@@ -233,6 +233,16 @@ fn show_main_window(app: &tauri::AppHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
/// The package manager that owns this install, when one does. The Nix wrapper sets it to "nix":
|
||||
/// the binary lives in a read-only store there, so the updater may announce a version but not
|
||||
/// install it.
|
||||
#[tauri::command]
|
||||
fn packaged_by() -> Option<String> {
|
||||
std::env::var("MARGIN_CALENDAR_PACKAGED_BY")
|
||||
.ok()
|
||||
.filter(|manager| !manager.is_empty())
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
// generate_context! first, so the updater plugin registers only when the merged config
|
||||
@@ -323,7 +333,8 @@ pub fn run() {
|
||||
sync::event_delete,
|
||||
sync::sync_now,
|
||||
sync::sync_status,
|
||||
sync::sync_flush
|
||||
sync::sync_flush,
|
||||
packaged_by
|
||||
])
|
||||
.build(context)
|
||||
.expect("error while building Margin Calendar");
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import { call } from "../ipc";
|
||||
|
||||
/** The package manager that owns this install, or null when the app updates itself. */
|
||||
export const packagedBy = () => call<string | null>("packaged_by");
|
||||
@@ -0,0 +1,51 @@
|
||||
// The one path where the updater must stand down: a package manager owns the binary, so a newer
|
||||
// version is announced and never installed over it.
|
||||
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
check: vi.fn(),
|
||||
relaunch: vi.fn(),
|
||||
notify: vi.fn(),
|
||||
call: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@tauri-apps/plugin-updater", () => ({ check: mocks.check }));
|
||||
vi.mock("@tauri-apps/plugin-process", () => ({ relaunch: mocks.relaunch }));
|
||||
vi.mock("../store/useToast", () => ({ notify: mocks.notify }));
|
||||
vi.mock("../ipc", () => ({ isDesktop: true, call: mocks.call }));
|
||||
|
||||
import { checkForUpdates } from "./updates";
|
||||
|
||||
const downloadAndInstall = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mocks.check.mockResolvedValue({ version: "0.0.5", downloadAndInstall });
|
||||
});
|
||||
|
||||
describe("checkForUpdates", () => {
|
||||
it("installs and relaunches when the app owns its own binary", async () => {
|
||||
mocks.call.mockResolvedValue(null);
|
||||
await checkForUpdates();
|
||||
expect(downloadAndInstall).toHaveBeenCalled();
|
||||
expect(mocks.relaunch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("points at the package manager instead of installing over it", async () => {
|
||||
mocks.call.mockResolvedValue("nix");
|
||||
await checkForUpdates();
|
||||
expect(downloadAndInstall).not.toHaveBeenCalled();
|
||||
expect(mocks.relaunch).not.toHaveBeenCalled();
|
||||
expect(mocks.notify).toHaveBeenCalledWith(
|
||||
"0.0.5 is out. Update with: nix profile upgrade margin-calendar",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not ask who owns the install when there is nothing newer", async () => {
|
||||
mocks.check.mockResolvedValue(null);
|
||||
await checkForUpdates();
|
||||
expect(mocks.call).not.toHaveBeenCalled();
|
||||
expect(mocks.notify).toHaveBeenCalledWith("Margin Calendar is up to date");
|
||||
});
|
||||
});
|
||||
@@ -4,11 +4,18 @@
|
||||
|
||||
import { relaunch } from "@tauri-apps/plugin-process";
|
||||
import { check } from "@tauri-apps/plugin-updater";
|
||||
import { packagedBy } from "../api/updates";
|
||||
import { isDesktop } from "../ipc";
|
||||
import { notify } from "../store/useToast";
|
||||
|
||||
let running = false;
|
||||
|
||||
/** A package manager owns the binary, so the update is announced and left to it. */
|
||||
function updateHint(manager: string, version: string): string {
|
||||
if (manager === "nix") return `${version} is out. Update with: nix profile upgrade margin-calendar`;
|
||||
return `${version} is out. Update it through ${manager}`;
|
||||
}
|
||||
|
||||
export async function checkForUpdates(): Promise<void> {
|
||||
if (!isDesktop || running) return;
|
||||
running = true;
|
||||
@@ -18,6 +25,11 @@ export async function checkForUpdates(): Promise<void> {
|
||||
notify("Margin Calendar is up to date");
|
||||
return;
|
||||
}
|
||||
const manager = await packagedBy();
|
||||
if (manager) {
|
||||
notify(updateHint(manager, update.version));
|
||||
return;
|
||||
}
|
||||
notify(`Installing ${update.version}…`);
|
||||
await update.downloadAndInstall();
|
||||
await relaunch();
|
||||
|
||||
Reference in new issue
Block a user