aboutsummaryrefslogtreecommitdiff
path: root/src/cli/worktree.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli/worktree.rs')
-rw-r--r--src/cli/worktree.rs318
1 files changed, 318 insertions, 0 deletions
diff --git a/src/cli/worktree.rs b/src/cli/worktree.rs
new file mode 100644
index 00000000..53ad685b
--- /dev/null
+++ b/src/cli/worktree.rs
@@ -0,0 +1,318 @@
+use crate::api::schema::{
+ Method, Request, WorktreeCreateParams, WorktreeListParams, WorktreeOpenParams,
+ WorktreeRemoveParams,
+};
+
+pub(super) fn run_worktree_command(args: &[String]) -> std::io::Result<i32> {
+ let Some(subcommand) = args.first().map(|arg| arg.as_str()) else {
+ print_worktree_help();
+ return Ok(2);
+ };
+
+ match subcommand {
+ "list" => worktree_list(&args[1..]),
+ "create" => worktree_create(&args[1..]),
+ "open" => worktree_open(&args[1..]),
+ "remove" => worktree_remove(&args[1..]),
+ "help" | "--help" | "-h" => {
+ print_worktree_help();
+ Ok(0)
+ }
+ _ => {
+ print_worktree_help();
+ Ok(2)
+ }
+ }
+}
+
+fn worktree_list(args: &[String]) -> std::io::Result<i32> {
+ let mut workspace_id = None;
+ let mut cwd = None;
+
+ let mut index = 0;
+ while index < args.len() {
+ match args[index].as_str() {
+ "--workspace" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --workspace");
+ return Ok(2);
+ };
+ workspace_id = Some(super::normalize_workspace_id(value));
+ index += 2;
+ }
+ "--cwd" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --cwd");
+ return Ok(2);
+ };
+ cwd = Some(normalize_path_arg(value)?);
+ index += 2;
+ }
+ "--json" => index += 1,
+ other => {
+ eprintln!("unknown option: {other}");
+ return Ok(2);
+ }
+ }
+ }
+ if workspace_id.is_some() && cwd.is_some() {
+ eprintln!("usage: herdr worktree list [--workspace ID | --cwd PATH] [--json]");
+ return Ok(2);
+ }
+
+ super::print_response(&super::send_request(&Request {
+ id: "cli:worktree:list".into(),
+ method: Method::WorktreeList(WorktreeListParams { workspace_id, cwd }),
+ })?)
+}
+
+fn worktree_create(args: &[String]) -> std::io::Result<i32> {
+ let mut workspace_id = None;
+ let mut cwd = None;
+ let mut branch = None;
+ let mut base = None;
+ let mut path = None;
+ let mut label = None;
+ let mut focus = false;
+
+ let mut index = 0;
+ while index < args.len() {
+ match args[index].as_str() {
+ "--workspace" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --workspace");
+ return Ok(2);
+ };
+ workspace_id = Some(super::normalize_workspace_id(value));
+ index += 2;
+ }
+ "--cwd" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --cwd");
+ return Ok(2);
+ };
+ cwd = Some(normalize_path_arg(value)?);
+ index += 2;
+ }
+ "--branch" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --branch");
+ return Ok(2);
+ };
+ branch = Some(value.clone());
+ index += 2;
+ }
+ "--base" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --base");
+ return Ok(2);
+ };
+ base = Some(value.clone());
+ index += 2;
+ }
+ "--path" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --path");
+ return Ok(2);
+ };
+ path = Some(normalize_path_arg(value)?);
+ index += 2;
+ }
+ "--label" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --label");
+ return Ok(2);
+ };
+ label = Some(value.clone());
+ index += 2;
+ }
+ "--focus" => {
+ focus = true;
+ index += 1;
+ }
+ "--no-focus" => {
+ focus = false;
+ index += 1;
+ }
+ "--json" => index += 1,
+ other => {
+ eprintln!("unknown option: {other}");
+ return Ok(2);
+ }
+ }
+ }
+ if workspace_id.is_some() && cwd.is_some() {
+ eprintln!(
+ "usage: herdr worktree create [--workspace ID | --cwd PATH] [--branch NAME] [--base REF] [--path PATH] [--label TEXT] [--focus] [--no-focus] [--json]"
+ );
+ return Ok(2);
+ }
+
+ super::print_response(&super::send_request(&Request {
+ id: "cli:worktree:create".into(),
+ method: Method::WorktreeCreate(WorktreeCreateParams {
+ workspace_id,
+ cwd,
+ branch,
+ base,
+ path,
+ label,
+ focus,
+ }),
+ })?)
+}
+
+fn worktree_open(args: &[String]) -> std::io::Result<i32> {
+ let mut workspace_id = None;
+ let mut cwd = None;
+ let mut path = None;
+ let mut branch = None;
+ let mut label = None;
+ let mut focus = false;
+
+ let mut index = 0;
+ while index < args.len() {
+ match args[index].as_str() {
+ "--workspace" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --workspace");
+ return Ok(2);
+ };
+ workspace_id = Some(super::normalize_workspace_id(value));
+ index += 2;
+ }
+ "--cwd" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --cwd");
+ return Ok(2);
+ };
+ cwd = Some(normalize_path_arg(value)?);
+ index += 2;
+ }
+ "--path" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --path");
+ return Ok(2);
+ };
+ path = Some(normalize_path_arg(value)?);
+ index += 2;
+ }
+ "--branch" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --branch");
+ return Ok(2);
+ };
+ branch = Some(value.clone());
+ index += 2;
+ }
+ "--label" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --label");
+ return Ok(2);
+ };
+ label = Some(value.clone());
+ index += 2;
+ }
+ "--focus" => {
+ focus = true;
+ index += 1;
+ }
+ "--no-focus" => {
+ focus = false;
+ index += 1;
+ }
+ "--json" => index += 1,
+ other => {
+ eprintln!("unknown option: {other}");
+ return Ok(2);
+ }
+ }
+ }
+ if workspace_id.is_some() && cwd.is_some() {
+ eprintln!(
+ "usage: herdr worktree open [--workspace ID | --cwd PATH] (--path PATH | --branch NAME) [--label TEXT] [--focus] [--no-focus] [--json]"
+ );
+ return Ok(2);
+ }
+ if path.is_some() == branch.is_some() {
+ eprintln!(
+ "usage: herdr worktree open [--workspace ID | --cwd PATH] (--path PATH | --branch NAME) [--label TEXT] [--focus] [--no-focus] [--json]"
+ );
+ return Ok(2);
+ }
+
+ super::print_response(&super::send_request(&Request {
+ id: "cli:worktree:open".into(),
+ method: Method::WorktreeOpen(WorktreeOpenParams {
+ workspace_id,
+ cwd,
+ path,
+ branch,
+ label,
+ focus,
+ }),
+ })?)
+}
+
+fn worktree_remove(args: &[String]) -> std::io::Result<i32> {
+ let mut workspace_id = None;
+ let mut force = false;
+
+ let mut index = 0;
+ while index < args.len() {
+ match args[index].as_str() {
+ "--workspace" => {
+ let Some(value) = args.get(index + 1) else {
+ eprintln!("missing value for --workspace");
+ return Ok(2);
+ };
+ workspace_id = Some(super::normalize_workspace_id(value));
+ index += 2;
+ }
+ "--force" => {
+ force = true;
+ index += 1;
+ }
+ "--json" => index += 1,
+ other => {
+ eprintln!("unknown option: {other}");
+ return Ok(2);
+ }
+ }
+ }
+
+ let Some(workspace_id) = workspace_id else {
+ eprintln!("usage: herdr worktree remove --workspace ID [--force] [--json]");
+ return Ok(2);
+ };
+
+ super::print_response(&super::send_request(&Request {
+ id: "cli:worktree:remove".into(),
+ method: Method::WorktreeRemove(WorktreeRemoveParams {
+ workspace_id,
+ force,
+ }),
+ })?)
+}
+
+fn print_worktree_help() {
+ eprintln!("herdr worktree commands:");
+ eprintln!(" herdr worktree list [--workspace ID | --cwd PATH] [--json]");
+ eprintln!(
+ " herdr worktree create [--workspace ID | --cwd PATH] [--branch NAME] [--base REF] [--path PATH] [--label TEXT] [--focus] [--no-focus] [--json]"
+ );
+ eprintln!(
+ " herdr worktree open [--workspace ID | --cwd PATH] (--path PATH | --branch NAME) [--label TEXT] [--focus] [--no-focus] [--json]"
+ );
+ eprintln!(" herdr worktree remove --workspace ID [--force] [--json]");
+}
+
+fn normalize_path_arg(value: &str) -> std::io::Result<String> {
+ let path = crate::worktree::expand_tilde_path(value);
+ let absolute = if path.is_absolute() {
+ path
+ } else {
+ std::env::current_dir()?.join(path)
+ };
+ Ok(absolute.display().to_string())
+}