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