Files
herdr/src/cli/worktree.rs
T

307 lines
9.5 KiB
Rust

use crate::api::schema::{
WorktreeCreateParams, WorktreeListParams, WorktreeOpenParams, WorktreeRemoveParams,
};
// Worktree output is always JSON. The parsers retain `--json` as a hidden compatibility no-op.
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]");
return Ok(2);
}
super::runtime::worktree_list(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]"
);
return Ok(2);
}
super::runtime::worktree_create(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]"
);
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]"
);
return Ok(2);
}
super::runtime::worktree_open(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]");
return Ok(2);
};
super::runtime::worktree_remove(WorktreeRemoveParams {
workspace_id,
force,
})
}
fn print_worktree_help() {
eprintln!("herdr worktree commands:");
eprintln!(" herdr worktree list [--workspace ID | --cwd PATH]");
eprintln!(
" herdr worktree create [--workspace ID | --cwd PATH] [--branch NAME] [--base REF] [--path PATH] [--label TEXT] [--focus] [--no-focus]"
);
eprintln!(
" herdr worktree open [--workspace ID | --cwd PATH] (--path PATH | --branch NAME) [--label TEXT] [--focus] [--no-focus]"
);
eprintln!(" herdr worktree remove --workspace ID [--force]");
}
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())
}