1use thor_core::{find_repo, list_worktrees};
2use std::process::Command;
3
4pub enum PullStatus {
6 Ok,
7 Failed(String),
8 Skipped,
9}
10
11pub struct PullResult {
13 pub branch: String,
14 pub status: PullStatus,
15}
16
17pub async fn pull(all: bool) -> anyhow::Result<Vec<PullResult>> {
19 if !all {
20 let output = Command::new("git")
22 .args(["pull", "--rebase"])
23 .output()?;
24
25 let branch = Command::new("git")
26 .args(["branch", "--show-current"])
27 .output()
28 .map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string())
29 .unwrap_or_else(|_| "unknown".to_string());
30
31 let status = if output.status.success() {
32 PullStatus::Ok
33 } else {
34 PullStatus::Failed(String::from_utf8_lossy(&output.stderr).trim().to_string())
35 };
36
37 return Ok(vec![PullResult { branch, status }]);
38 }
39
40 let repo = find_repo()?;
42 let worktrees = list_worktrees(&repo).await?;
43 let mut results = Vec::new();
44
45 for wt in &worktrees {
46 let branch = wt.display_name();
47
48 let has_upstream = Command::new("git")
50 .args(["rev-parse", "--abbrev-ref", "@{u}"])
51 .current_dir(&wt.path)
52 .output()
53 .map(|o| o.status.success())
54 .unwrap_or(false);
55
56 if !has_upstream {
57 results.push(PullResult { branch, status: PullStatus::Skipped });
58 continue;
59 }
60
61 let output = Command::new("git")
62 .args(["pull", "--rebase"])
63 .current_dir(&wt.path)
64 .output()?;
65
66 let status = if output.status.success() {
67 PullStatus::Ok
68 } else {
69 PullStatus::Failed(String::from_utf8_lossy(&output.stderr).trim().to_string())
70 };
71
72 results.push(PullResult { branch, status });
73 }
74
75 Ok(results)
76}