Skip to main content

worktree_io/issue/
mod.rs

1use std::path::PathBuf;
2
3mod parse;
4mod paths;
5
6#[cfg(test)]
7mod tests;
8
9#[cfg(test)]
10mod linear_tests;
11
12#[cfg(test)]
13mod azure_tests;
14
15#[cfg(test)]
16mod uuid_tests;
17
18#[cfg(test)]
19mod parse_tests;
20
21#[cfg(test)]
22mod local_tests;
23
24/// Options extracted from a `worktree://` deep link.
25#[derive(Debug, Clone, Default)]
26pub struct DeepLinkOptions {
27    /// Editor override from the `editor` query param. May be a symbolic name
28    /// (`cursor`, `code`, `zed`, `nvim`, etc.) or a raw percent-decoded command.
29    pub editor: Option<String>,
30}
31
32/// A reference to an issue that identifies a workspace.
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub enum IssueRef {
35    /// A GitHub issue identified by owner, repo, and number.
36    GitHub {
37        /// GitHub organization or user name.
38        owner: String,
39        /// Repository name.
40        repo: String,
41        /// Issue number.
42        number: u64,
43    },
44    /// A Linear issue identified by its UUID, paired with the GitHub repo that
45    /// hosts the code for that project.
46    Linear {
47        /// GitHub organization or user name that hosts the code.
48        owner: String,
49        /// Repository name.
50        repo: String,
51        /// Linear issue UUID.
52        id: String,
53    },
54    /// An Azure DevOps work item paired with an Azure Repos git repository.
55    AzureDevOps {
56        /// Azure DevOps organization name.
57        org: String,
58        /// Azure DevOps project name.
59        project: String,
60        /// Azure Repos git repository name.
61        repo: String,
62        /// Work item ID.
63        id: u64,
64    },
65    /// A local Centy issue — the repository itself is the source, no remote clone needed.
66    Local {
67        /// Absolute path to the local project repository.
68        project_path: PathBuf,
69        /// Human-readable issue number shown in the branch name.
70        display_number: u32,
71    },
72}
73
74impl IssueRef {
75    /// Directory name used inside the bare clone for this worktree.
76    #[must_use]
77    pub fn workspace_dir_name(&self) -> String {
78        match self {
79            Self::GitHub { number, .. } => format!("issue-{number}"),
80            Self::Linear { id, .. } => format!("linear-{id}"),
81            Self::AzureDevOps { id, .. } => format!("workitem-{id}"),
82            Self::Local { display_number, .. } => format!("issue-{display_number}"),
83        }
84    }
85
86    /// Git branch name for this issue worktree.
87    #[must_use]
88    pub fn branch_name(&self) -> String {
89        self.workspace_dir_name()
90    }
91
92    /// HTTPS clone URL for the repository.
93    ///
94    /// # Panics
95    ///
96    /// Always panics for `IssueRef::Local` — local repos are never cloned.
97    #[must_use]
98    pub fn clone_url(&self) -> String {
99        match self {
100            Self::GitHub { owner, repo, .. } | Self::Linear { owner, repo, .. } => {
101                format!("https://github.com/{owner}/{repo}.git")
102            }
103            Self::AzureDevOps {
104                org, project, repo, ..
105            } => {
106                format!("https://dev.azure.com/{org}/{project}/_git/{repo}")
107            }
108            Self::Local { .. } => {
109                unreachable!("clone_url is never called for IssueRef::Local")
110            }
111        }
112    }
113}