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}