1use anyhow::Result;
2use std::path::PathBuf;
3
4use crate::git::{
5 bare_clone, branch_exists_local, branch_exists_remote, create_local_worktree, create_worktree,
6 detect_default_branch, git_fetch, git_worktree_prune,
7};
8use crate::issue::IssueRef;
9use crate::ttl::WorkspaceRegistry;
10
11pub struct Workspace {
13 pub path: PathBuf,
15 pub issue: IssueRef,
17 pub created: bool,
19}
20
21impl Workspace {
22 pub fn open_or_create(issue: IssueRef) -> Result<Self> {
29 let worktree_path = issue.temp_path();
30 let bare_path = issue.bare_clone_path();
31
32 if worktree_path.exists() {
34 return Ok(Self {
35 path: worktree_path,
36 issue,
37 created: false,
38 });
39 }
40
41 if let IssueRef::Local { project_path, .. } = &issue {
43 eprintln!("Creating local worktree at {}…", worktree_path.display());
45 let branch = issue.branch_name();
46 let branch_exists = branch_exists_local(project_path, &branch);
47 std::fs::create_dir_all(worktree_path.parent().unwrap_or(&worktree_path))?;
48 let _ = git_worktree_prune(project_path);
49 create_local_worktree(project_path, &worktree_path, &branch, branch_exists)?;
50 } else {
51 if bare_path.exists() {
52 eprintln!("Fetching origin…");
53 git_fetch(&bare_path)?;
54 } else {
55 eprintln!(
56 "Cloning {} (bare) into {}…",
57 issue.clone_url(),
58 bare_path.display()
59 );
60 bare_clone(&issue.clone_url(), &bare_path)?;
61 }
62
63 let base_branch = detect_default_branch(&bare_path)?;
64 eprintln!("Default branch: {base_branch}");
65
66 let branch = issue.branch_name();
67 let branch_exists = branch_exists_remote(&bare_path, &branch);
68
69 eprintln!(
70 "Creating worktree {} at {}…",
71 branch,
72 worktree_path.display()
73 );
74 let _ = git_worktree_prune(&bare_path);
75 create_worktree(
76 &bare_path,
77 &worktree_path,
78 &branch,
79 &base_branch,
80 branch_exists,
81 )?;
82 }
83
84 if let Ok(mut registry) = WorkspaceRegistry::load() {
85 registry.register(worktree_path.clone());
86 let _ = registry.save();
87 }
88
89 Ok(Self {
90 path: worktree_path,
91 issue,
92 created: true,
93 })
94 }
96}
97
98#[cfg(test)]
99#[path = "workspace_tests.rs"]
100mod workspace_tests;