breadcrumbs/src/state.rs
Breadway 9009404536
All checks were successful
check / check (push) Successful in 36s
Wire breadcrumbs into the bread event fabric (app id crumbs)
The watch daemon publishes bread.crumbs.profile.changed and
bread.crumbs.health.changed on real transitions (not every poll tick)
and honors bread.command.crumbs.set_profile via the existing
state::set_profile path. BreadClient is fail-silent: if breadd is
down, breadcrumbs behaves exactly as before.

Document the contract in EVENTS.md. CLAUDE.md now points at
CONTRIBUTING (single-trunk, no three-branch model), bakery, and
EVENTS.md.
2026-08-15 21:38:16 +08:00

53 lines
1.7 KiB
Rust

use std::fs;
use serde::{Deserialize, Serialize};
use crate::config::{state_dir, state_path, Config};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct State {
pub profile: String,
#[serde(default)]
pub updated: String,
}
impl State {
pub fn load(default_profile: &str) -> State {
if let Ok(text) = fs::read_to_string(state_path()) {
if let Ok(s) = toml::from_str::<State>(&text) {
if !s.profile.is_empty() {
return s;
}
}
}
State {
profile: default_profile.to_string(),
updated: String::new(),
}
}
pub fn save(&self) -> Result<(), String> {
fs::create_dir_all(state_dir()).map_err(|e| format!("creating state dir: {e}"))?;
let text = toml::to_string_pretty(self).map_err(|e| format!("serializing state: {e}"))?;
fs::write(state_path(), text).map_err(|e| format!("writing state: {e}"))
}
}
/// Persist `name` as the active profile if it exists in `cfg`. Shared by the
/// CLI `profile set` path and `bread.command.crumbs.set_profile` so they
/// cannot drift. Does not run [`crate::flow::run`] — the CLI applies
/// afterwards unless `--no-apply`, and the watch daemon picks the new
/// profile up on its next tick.
pub fn set_profile(cfg: &Config, name: &str) -> Result<(), String> {
if !cfg.profiles.contains_key(name) {
let avail: Vec<&String> = cfg.profiles.keys().collect();
return Err(format!("unknown profile '{name}'. Available: {avail:?}"));
}
State {
profile: name.to_string(),
updated: crate::util::timestamp(),
}
.save()?;
crate::notify::log(&format!("profile set -> {name}"));
Ok(())
}