Skip to main content

worktree_io/
workspace.rs

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,
7};
8use crate::issue::IssueRef;
9
10pub struct Workspace {
11    pub path: PathBuf,
12    pub issue: IssueRef,
13    /// true if this call actually created the worktree; false if it already existed
14    pub created: bool,
15}
16
17impl Workspace {
18    /// Open an existing worktree or create a fresh one.
19    pub fn open_or_create(issue: IssueRef) -> Result<Self> {
20        let worktree_path = issue.temp_path();
21        let bare_path = issue.bare_clone_path();
22
23        // Fast path: worktree already exists
24        if worktree_path.exists() {
25            return Ok(Self {
26                path: worktree_path,
27                issue,
28                created: false,
29            });
30        }
31
32        // LLVM_COV_EXCL_START
33        match &issue {
34            IssueRef::Local { project_path, .. } => {
35                // No bare clone — use the local repo directly.
36                eprintln!("Creating local worktree at {}…", worktree_path.display());
37                let branch = issue.branch_name();
38                let branch_exists = branch_exists_local(project_path, &branch);
39                std::fs::create_dir_all(worktree_path.parent().unwrap_or(&worktree_path))?;
40                create_local_worktree(project_path, &worktree_path, &branch, branch_exists)?;
41            }
42            _ => {
43                if !bare_path.exists() {
44                    eprintln!(
45                        "Cloning {} (bare) into {}…",
46                        issue.clone_url(),
47                        bare_path.display()
48                    );
49                    bare_clone(&issue.clone_url(), &bare_path)?;
50                } else {
51                    eprintln!("Fetching origin…");
52                    git_fetch(&bare_path)?;
53                }
54
55                let base_branch = detect_default_branch(&bare_path)?;
56                eprintln!("Default branch: {base_branch}");
57
58                let branch = issue.branch_name();
59                let branch_exists = branch_exists_remote(&bare_path, &branch);
60
61                eprintln!(
62                    "Creating worktree {} at {}…",
63                    branch,
64                    worktree_path.display()
65                );
66                create_worktree(
67                    &bare_path,
68                    &worktree_path,
69                    &branch,
70                    &base_branch,
71                    branch_exists,
72                )?;
73            }
74        }
75
76        Ok(Self {
77            path: worktree_path,
78            issue,
79            created: true,
80        })
81        // LLVM_COV_EXCL_STOP
82    }
83}
84
85#[cfg(test)]
86#[path = "workspace_tests.rs"]
87mod workspace_tests;