use crate::cli::commands;
use crate::cli::error::{CliResult, ErrorFactory};
use crate::commands::{
is_tray_background_child, resolve_default_worktree_watch_status_target,
run_worktree_watch_start, run_worktree_watch_status, run_worktree_watch_stop,
run_worktree_watch_sync, run_worktree_watch_tray, spawn_detached_worktree_watch_tray,
WorktreeWatchStartOptions, WorktreeWatchStatusOptions, WorktreeWatchStopOptions,
WorktreeWatchSyncOptions, WorktreeWatchTargetOptions, WorktreeWatchTrayOptions,
};
fn map_target(target: commands::WorktreeWatchTarget) -> Result<WorktreeWatchTargetOptions, String> {
crate::commands::normalize_worktree_watch_target(WorktreeWatchTargetOptions {
repo: target.repo,
parent: target.parent,
repos: target.repos,
})
}
fn map_status_target(
target: commands::WorktreeWatchTarget,
) -> Result<WorktreeWatchTargetOptions, String> {
if target.repo.is_none() && target.parent.is_none() && target.repos.is_empty() {
return resolve_default_worktree_watch_status_target();
}
map_target(target)
}
pub async fn handle_worktree_watch(cmd: commands::WorktreeWatchCmd, _debug: bool) -> CliResult<()> {
let result = match cmd.command {
commands::WorktreeWatchSubCommand::Start(start_cmd) => match map_target(start_cmd.target)
{
Ok(target) => {
run_worktree_watch_start(WorktreeWatchStartOptions {
target,
detach: start_cmd.detach,
sync_interval_seconds: start_cmd.sync_interval_seconds,
once: start_cmd.once,
})
.await
}
Err(error) => Err(error),
},
commands::WorktreeWatchSubCommand::Stop(stop_cmd) => match map_target(stop_cmd.target) {
Ok(target) => run_worktree_watch_stop(WorktreeWatchStopOptions {
target,
force: stop_cmd.force,
}),
Err(error) => Err(error),
},
commands::WorktreeWatchSubCommand::Sync(sync_cmd) => match map_target(sync_cmd.target) {
Ok(target) => {
run_worktree_watch_sync(WorktreeWatchSyncOptions {
target,
dry_run: sync_cmd.dry_run,
resync: sync_cmd.resync,
})
.await
}
Err(error) => Err(error),
},
commands::WorktreeWatchSubCommand::Status(status_cmd) => {
match map_status_target(status_cmd.target) {
Ok(target) => {
run_worktree_watch_status(WorktreeWatchStatusOptions {
target,
json: status_cmd.json,
records: status_cmd.records,
record_limit: status_cmd.record_limit,
stats: status_cmd.stats,
repo_activity: status_cmd.repo_activity,
stats_gap_minutes: status_cmd.stats_gap_minutes,
})
.await
}
Err(error) => Err(error),
}
}
commands::WorktreeWatchSubCommand::Tray(tray_cmd) => match map_target(tray_cmd.target) {
Ok(target) => {
let options = WorktreeWatchTrayOptions {
target,
sync_interval_seconds: tray_cmd.sync_interval_seconds,
};
if !tray_cmd.foreground && !is_tray_background_child() {
spawn_detached_worktree_watch_tray(options)
} else {
tokio::task::spawn_blocking(move || run_worktree_watch_tray(options))
.await
.map_err(|error| format!("Worktree-watch tray task failed: {error}"))
.and_then(|inner| inner)
}
}
Err(error) => Err(error),
},
};
result.map_err(|error| {
ErrorFactory::operation(
"worktree-watch",
"process worktree mutations",
error,
Some(
"Run inside a git repository, pass `--repo <path|name|owner/repo>`, `--repos …`, or `--parent <folder>`. Names resolve via `~/.xbp/config.yaml` system inventory (`xbp diag --refresh-system-inventory`). Use `xbp login` before syncing.",
),
)
})
}