Skip to content

Commit 7193693

Browse files
committed
v0.4.5
New: - updater: self-update system with CDN version checks, SHA512-verified downloads, and atomic binary swap - updater: background 24h polling in CLI and service mode, `zero update` command - sidebar: pin/unpin bookmarks as icon tiles with context menu actions - theme: Catppuccin Latte, Frappe, Macchiato, and Mocha color schemes - status-bar: reusable StatusBar component for directory and search result summaries Fix: - theme: brand, selection, and semantic colors read from active theme instead of hardcoded values - theme: consolidated tokens module replacing container, icon, layout, shadow files - navigation: in-place directory navigation avoids entity teardown on folder change - progress: indexing banner shows live file count with cancel button across all index paths - index: total_file_count falls back to persisted metadata when indexes not loaded in memory - editor: toolbar extracted to app-level, save/modified state exposed as public API - settings: theme picker with dark/light/system mode, auto-update toggle, reactive file count - deps: ureq, flate2, tar for update support
1 parent 3cfd24a commit 7193693

63 files changed

Lines changed: 2864 additions & 929 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Changelog
2+
3+
## v0.4.5
4+
5+
New:
6+
- updater: self-update system with CDN version checks, SHA512-verified downloads, and atomic binary swap
7+
- updater: background 24h polling in CLI and service mode, `zero update` command
8+
- sidebar: pin/unpin bookmarks as icon tiles with context menu actions
9+
- theme: Catppuccin Latte, Frappe, Macchiato, and Mocha color schemes
10+
- status-bar: reusable StatusBar component for directory and search result summaries
11+
12+
Fix:
13+
- theme: brand, selection, and semantic colors read from active theme instead of hardcoded values
14+
- theme: consolidated tokens module replacing container, icon, layout, shadow files
15+
- navigation: in-place directory navigation avoids entity teardown on folder change
16+
- progress: indexing banner shows live file count with cancel button across all index paths
17+
- index: total_file_count falls back to persisted metadata when indexes not loaded in memory
18+
- editor: toolbar extracted to app-level, save/modified state exposed as public API
19+
- settings: theme picker with dark/light/system mode, auto-update toggle, reactive file count
20+
- deps: ureq, flate2, tar for update support

Cargo.lock

Lines changed: 56 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ zero-watcher = { path = "crates/watcher" }
77

88
[package]
99
name = "zero"
10-
version = "0.4.4"
10+
version = "0.4.5"
1111
edition = "2024"
1212
rust-version = "1.92"
1313
description = "A resilient file synchronization and deduplication tool"
@@ -80,6 +80,11 @@ roaring = { version = "0.11", features = ["serde"] }
8080

8181
toml = "0.9.10"
8282

83+
# Auto-update (HTTP client + archive extraction)
84+
ureq = "3"
85+
flate2 = "1"
86+
tar = "0.4"
87+
8388
# Unix-specific (for secure erase platform code)
8489
[target.'cfg(unix)'.dependencies]
8590
libc = "0.2"

crates/zero-cli/src/cli/commands/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub mod search;
1313
pub mod sync;
1414
pub mod templates;
1515
pub mod todo;
16+
pub mod update;
1617
pub mod verify;
1718
pub mod watch;
1819

@@ -29,4 +30,5 @@ pub use search::*;
2930
pub use sync::*;
3031
pub use templates::*;
3132
pub use todo::*;
33+
pub use update::*;
3234
pub use watch::*;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//! Update command handler
2+
3+
use zero::output::Outputter;
4+
use zero::updater::{
5+
self, CURRENT_VERSION, UpdateStatus, check_latest, download_update, install_binary,
6+
};
7+
8+
/// Run the update command
9+
pub fn cmd_update(out: &Outputter, check_only: bool) -> anyhow::Result<()> {
10+
out.info(&format!("Current version: {}", CURRENT_VERSION));
11+
12+
let (os, arch) = updater::platform_target();
13+
out.info(&format!("Platform: {}-{}", os, arch));
14+
15+
// Always check (ignore 24h cooldown — explicit user action)
16+
out.info("Checking for updates...");
17+
18+
let status = match check_latest() {
19+
Ok(s) => s,
20+
Err(e) => {
21+
out.error(&format!("Failed to check for updates: {}", e));
22+
return Ok(());
23+
}
24+
};
25+
26+
// Record the check regardless
27+
updater::record_check();
28+
29+
match status {
30+
UpdateStatus::UpToDate => {
31+
out.success("Already up to date");
32+
return Ok(());
33+
}
34+
UpdateStatus::Available { ref version } => {
35+
out.info(&format!("New version available: {}", version));
36+
37+
if check_only {
38+
return Ok(());
39+
}
40+
41+
out.info(&format!("Downloading v{}...", version));
42+
43+
let new_binary = match download_update(version) {
44+
Ok(p) => p,
45+
Err(e) => {
46+
out.error(&format!("Download failed: {}", e));
47+
return Ok(());
48+
}
49+
};
50+
51+
out.info("Installing...");
52+
53+
match install_binary(&new_binary) {
54+
Ok(()) => {
55+
out.success(&format!("Updated zero {} → {}", CURRENT_VERSION, version));
56+
}
57+
Err(e) => {
58+
out.error(&format!("Install failed: {}", e));
59+
}
60+
}
61+
}
62+
}
63+
64+
Ok(())
65+
}

crates/zero-cli/src/cli/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,16 @@ pub enum Commands {
501501
#[command(subcommand)]
502502
todo_cmd: Option<commands::todo::TodoCommands>,
503503
},
504+
505+
// =========================================================================
506+
// Updates
507+
// =========================================================================
508+
/// Check for and install updates
509+
Update {
510+
/// Only check for updates, don't install
511+
#[arg(long)]
512+
check: bool,
513+
},
504514
}
505515

506516
/// Subcommands for the watch command (dev/testing)

crates/zero-cli/src/main.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::panic;
55
use std::path::Path;
66
use std::process;
77
use std::sync::atomic::{AtomicBool, Ordering};
8+
use std::sync::{Arc, Mutex};
89

910
use clap::{CommandFactory, Parser};
1011
use cli::Cli;
@@ -43,6 +44,7 @@ const KNOWN_COMMANDS: &[&str] = &[
4344
"sync",
4445
"templates",
4546
"todo",
47+
"update",
4648
"verify",
4749
"watch",
4850
"wipe",
@@ -206,6 +208,28 @@ fn main() -> anyhow::Result<()> {
206208
}
207209
};
208210

211+
// Background update check: spawn a thread for non-update, non-service commands
212+
// when auto_update is enabled and enough time has passed since the last check
213+
let update_hint: Arc<Mutex<Option<String>>> = Arc::new(Mutex::new(None));
214+
let bg_check = match &command {
215+
Commands::Update { .. } | Commands::Service { .. } => false,
216+
_ => zero::updater::read_auto_update_setting() && zero::updater::should_check(),
217+
};
218+
219+
if bg_check {
220+
let hint = Arc::clone(&update_hint);
221+
std::thread::spawn(move || {
222+
if let Ok(zero::updater::UpdateStatus::Available { version }) =
223+
zero::updater::check_latest()
224+
{
225+
if let Ok(mut h) = hint.lock() {
226+
*h = Some(version);
227+
}
228+
}
229+
zero::updater::record_check();
230+
});
231+
}
232+
209233
match command {
210234
// =====================================================================
211235
// Primary commands
@@ -509,6 +533,20 @@ fn main() -> anyhow::Result<()> {
509533
Commands::Todo { todo_cmd } => {
510534
cli::commands::cmd_todo(&out, todo_cmd.as_ref())?;
511535
}
536+
537+
// =====================================================================
538+
// Updates
539+
// =====================================================================
540+
Commands::Update { check } => {
541+
cli::commands::cmd_update(&out, check)?;
542+
}
543+
}
544+
545+
// Print update hint if background check found a new version
546+
if let Ok(hint) = update_hint.lock() {
547+
if let Some(version) = hint.as_ref() {
548+
eprintln!("hint: zero v{version} available — run `zero update` to install");
549+
}
512550
}
513551

514552
Ok(())

0 commit comments

Comments
 (0)