diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-02 21:48:02 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-02 21:48:02 +0300 |
| commit | b751d102f158968aab681cb663d27b4c32197f62 (patch) | |
| tree | 85d03609314559df7705c2cb0ab4e37ab6d9715f /src/cli.rs | |
| parent | 295b09ca25edbccac65401ee84fa420dd3888aad (diff) | |
feat: add preview update channel
Diffstat (limited to 'src/cli.rs')
| -rw-r--r-- | src/cli.rs | 104 |
1 files changed, 104 insertions, 0 deletions
@@ -36,6 +36,7 @@ pub fn maybe_run(args: &[String]) -> std::io::Result<CommandOutcome> { } "status" => status::run_status_command(&args[2..])?, "config" => run_config_command(&args[2..])?, + "channel" => run_channel_command(&args[2..])?, "workspace" => workspace::run_workspace_command(&args[2..])?, "worktree" => worktree::run_worktree_command(&args[2..])?, "tab" => tab::run_tab_command(&args[2..])?, @@ -51,6 +52,89 @@ pub fn maybe_run(args: &[String]) -> std::io::Result<CommandOutcome> { Ok(CommandOutcome::Handled(exit_code)) } +fn run_channel_command(args: &[String]) -> std::io::Result<i32> { + match args.first().map(|arg| arg.as_str()) { + Some("set") => channel_set(&args[1..]), + Some("show") if args.len() == 1 => { + let config = crate::config::Config::load().config; + println!("{}", config.update.channel.as_str()); + Ok(0) + } + Some("help" | "--help" | "-h") => { + print_channel_help(); + Ok(0) + } + _ => { + print_channel_help(); + Ok(2) + } + } +} + +fn channel_set(args: &[String]) -> std::io::Result<i32> { + let Some(channel) = parse_channel_set_arg(args) else { + eprintln!("usage: herdr channel set <stable|preview>"); + return Ok(2); + }; + + let path = crate::config::config_path(); + let content = if path.exists() { + std::fs::read_to_string(&path)? + } else { + String::new() + }; + if let Err(err) = content.parse::<toml::Value>() { + eprintln!( + "config file at {} is invalid TOML: {err}. Fix it before changing the update channel.", + path.display() + ); + return Ok(1); + } + + let updated = crate::config::upsert_section_value( + &content, + "update", + "channel", + &format!("\"{channel}\""), + ); + if let Err(err) = updated.parse::<toml::Value>() { + eprintln!( + "changing the update channel would make {} invalid TOML: {err}; leaving config unchanged", + path.display() + ); + return Ok(1); + } + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent)?; + } + std::fs::write(&path, updated)?; + println!( + "Herdr update channel set to {channel} in {}.", + path.display() + ); + if channel == "preview" { + println!("Run `herdr update` to install the latest preview build when ready."); + } else { + println!("Run `herdr update` to install the latest stable release when ready."); + } + Ok(0) +} + +fn parse_channel_set_arg(args: &[String]) -> Option<&str> { + let channel = args.first().map(|arg| arg.as_str())?; + if args.len() == 1 && matches!(channel, "stable" | "preview") { + Some(channel) + } else { + None + } +} + +fn print_channel_help() { + eprintln!("herdr channel commands:"); + eprintln!(" herdr channel show print the configured update channel"); + eprintln!(" herdr channel set <stable|preview> choose the update channel"); +} + fn run_config_command(args: &[String]) -> std::io::Result<i32> { let Some(subcommand) = args.first().map(|arg| arg.as_str()) else { print_config_help(); @@ -745,3 +829,23 @@ fn print_session_help() { fn _print_json<T: Serialize>(value: &T) { println!("{}", serde_json::to_string(value).unwrap()); } + +#[cfg(test)] +mod tests { + #[test] + fn parses_channel_set_argument() { + assert_eq!( + super::parse_channel_set_arg(&["preview".to_string()]), + Some("preview") + ); + assert_eq!( + super::parse_channel_set_arg(&["stable".to_string()]), + Some("stable") + ); + assert_eq!(super::parse_channel_set_arg(&["nightly".to_string()]), None); + assert_eq!( + super::parse_channel_set_arg(&["preview".to_string(), "stable".to_string()]), + None + ); + } +} |
