gestura_core_tools/
git_async.rs1use crate::error::AppError;
7use crate::error::Result;
8use crate::git::{GitTools, GitWorktreeInfo};
9use std::path::{Path, PathBuf};
10
11pub async fn execute_git(operation: &str, path: &str) -> Result<String> {
13 let op = operation.to_string();
14 let work_path = path.to_string();
15
16 tokio::task::spawn_blocking(move || {
17 let tools = GitTools::new(Some(std::path::PathBuf::from(&work_path)));
18 match op.as_str() {
19 "status" => tools.status().map(|s| {
20 format!(
21 "Branch: {}\nStaged: {} files\nUnstaged: {} files\nUntracked: {} files",
22 s.branch,
23 s.staged.len(),
24 s.unstaged.len(),
25 s.untracked.len()
26 )
27 }),
28 "log" => tools.log(Some(10), None).map(|commits| {
29 commits
30 .iter()
31 .map(|c| format!("{} - {} ({})", c.short_hash, c.message, c.author))
32 .collect::<Vec<_>>()
33 .join("\n")
34 }),
35 "diff" => tools.diff(false, None),
36 "diff-staged" => tools.diff(true, None),
37 "branches" => tools.branches(false).map(|branches| {
38 branches
39 .iter()
40 .map(|b| {
41 if b.is_current {
42 format!("* {}", b.name)
43 } else {
44 format!(" {}", b.name)
45 }
46 })
47 .collect::<Vec<_>>()
48 .join("\n")
49 }),
50 _ => Err(AppError::Io(std::io::Error::other(format!(
51 "Unknown git operation: {}",
52 op
53 )))),
54 }
55 })
56 .await
57 .map_err(|e| AppError::Io(std::io::Error::other(format!("Task join error: {}", e))))?
58}
59
60pub async fn rev_parse_toplevel(path: impl AsRef<Path>) -> Result<PathBuf> {
62 let work_path = path.as_ref().to_path_buf();
63 tokio::task::spawn_blocking(move || GitTools::new(Some(work_path)).rev_parse_toplevel())
64 .await
65 .map_err(|e| AppError::Io(std::io::Error::other(format!("Task join error: {}", e))))?
66}
67
68pub async fn current_branch(path: impl AsRef<Path>) -> Result<String> {
70 let work_path = path.as_ref().to_path_buf();
71 tokio::task::spawn_blocking(move || GitTools::new(Some(work_path)).current_branch())
72 .await
73 .map_err(|e| AppError::Io(std::io::Error::other(format!("Task join error: {}", e))))?
74}
75
76pub async fn worktree_list(path: impl AsRef<Path>) -> Result<Vec<GitWorktreeInfo>> {
78 let work_path = path.as_ref().to_path_buf();
79 tokio::task::spawn_blocking(move || GitTools::new(Some(work_path)).worktree_list())
80 .await
81 .map_err(|e| AppError::Io(std::io::Error::other(format!("Task join error: {}", e))))?
82}
83
84pub async fn worktree_add(
86 path: impl AsRef<Path>,
87 worktree_path: impl AsRef<Path>,
88 branch: String,
89 base_branch: String,
90 create_branch: bool,
91) -> Result<GitWorktreeInfo> {
92 let work_path = path.as_ref().to_path_buf();
93 let worktree_path = worktree_path.as_ref().to_path_buf();
94 tokio::task::spawn_blocking(move || {
95 GitTools::new(Some(work_path)).worktree_add(
96 &worktree_path,
97 &branch,
98 &base_branch,
99 create_branch,
100 )
101 })
102 .await
103 .map_err(|e| AppError::Io(std::io::Error::other(format!("Task join error: {}", e))))?
104}
105
106pub async fn worktree_remove(
108 path: impl AsRef<Path>,
109 worktree_path: impl AsRef<Path>,
110 force: bool,
111) -> Result<()> {
112 let work_path = path.as_ref().to_path_buf();
113 let worktree_path = worktree_path.as_ref().to_path_buf();
114 tokio::task::spawn_blocking(move || {
115 GitTools::new(Some(work_path)).worktree_remove(&worktree_path, force)
116 })
117 .await
118 .map_err(|e| AppError::Io(std::io::Error::other(format!("Task join error: {}", e))))?
119}
120
121pub async fn is_worktree_clean(
123 path: impl AsRef<Path>,
124 worktree_path: impl AsRef<Path>,
125) -> Result<bool> {
126 let work_path = path.as_ref().to_path_buf();
127 let worktree_path = worktree_path.as_ref().to_path_buf();
128 tokio::task::spawn_blocking(move || {
129 GitTools::new(Some(work_path)).is_worktree_clean(&worktree_path)
130 })
131 .await
132 .map_err(|e| AppError::Io(std::io::Error::other(format!("Task join error: {}", e))))?
133}