semver_analyzer_ts/worktree/
error.rs1use semver_analyzer_core::error::ErrorTip;
4use std::path::PathBuf;
5use thiserror::Error;
6
7#[derive(Debug, Error)]
9pub enum WorktreeError {
10 #[error("Not a git repository: {path}")]
11 NotAGitRepo { path: PathBuf },
12
13 #[error("Git ref does not exist: {git_ref}")]
14 RefNotFound { git_ref: String },
15
16 #[error("Failed to create git worktree at {path}: {reason}")]
17 WorktreeCreationFailed { path: PathBuf, reason: String },
18
19 #[error("Failed to remove git worktree at {path}: {reason}")]
20 WorktreeRemovalFailed { path: PathBuf, reason: String },
21
22 #[error("No lockfile found at ref {git_ref}. Expected one of: package-lock.json, yarn.lock, pnpm-lock.yaml")]
23 NoLockfileFound { git_ref: String },
24
25 #[error("Package install failed ({command}): {reason}")]
26 PackageInstallFailed { command: String, reason: String },
27
28 #[error("No tsconfig.json found at ref {git_ref}")]
29 NoTsconfigFound { git_ref: String },
30
31 #[error("tsconfig.json has noEmit: true, which conflicts with --declaration. Consider adding a separate tsconfig.build.json")]
32 NoEmitConflict,
33
34 #[error("tsc --declaration failed with {error_count} errors at ref {git_ref}: {reason}")]
35 TscFailed {
36 git_ref: String,
37 error_count: usize,
38 reason: String,
39 },
40
41 #[error("Dependencies not installed at ref {git_ref}. Import resolution errors in tsc output")]
42 MissingDependencies { git_ref: String },
43
44 #[error("Project references not built. Run tsc --build in the monorepo root first")]
45 ProjectReferencesNotBuilt,
46
47 #[error("Unsupported TypeScript syntax at ref {git_ref}: {reason}")]
48 UnsupportedSyntax { git_ref: String, reason: String },
49
50 #[error("Project build failed ({command}): {reason}")]
51 ProjectBuildFailed { command: String, reason: String },
52
53 #[error("Insufficient disk space: need approximately {needed_mb}MB, have {available_mb}MB")]
54 InsufficientDiskSpace { needed_mb: u64, available_mb: u64 },
55
56 #[error("Command execution failed: {0}")]
57 CommandFailed(String),
58
59 #[error(transparent)]
60 Io(#[from] std::io::Error),
61}
62
63impl ErrorTip for WorktreeError {
64 fn tip(&self) -> Option<String> {
65 Some(match self {
66 Self::NotAGitRepo { path } => format!(
67 "Verify that '{}' is a git repository (contains a .git directory).\n\
68 If this is a subdirectory, point --repo to the repository root.",
69 path.display()
70 ),
71 Self::RefNotFound { git_ref } => format!(
72 "The ref '{}' was not found. Run 'git tag -l' or 'git branch -a' \
73 in the repo to see available refs.\n\
74 If using a short ref like 'v6', try the full tag name (e.g. 'v6.0.0').",
75 git_ref
76 ),
77 Self::WorktreeCreationFailed { path, .. } => format!(
78 "Failed to create a git worktree at '{}'.\n\
79 Check that the path is writable and no stale worktree exists there.\n\
80 Try running 'git worktree prune' in the repo to clean up stale entries.",
81 path.display()
82 ),
83 Self::NoLockfileFound { .. } => {
84 "The repo needs a package lockfile (package-lock.json, yarn.lock, \
85 or pnpm-lock.yaml) at this ref.\n\
86 If this ref predates lockfiles, try a later tag.\n\
87 If the project uses a different package manager, specify --build-command."
88 .to_string()
89 }
90 Self::PackageInstallFailed { command, .. } => format!(
91 "The package install command '{}' failed.\n\
92 Try running it manually in the repo to see the full error.\n\
93 Check that your Node.js version is compatible with this project.\n\
94 Use --log-file debug.log for full output.",
95 command
96 ),
97 Self::NoTsconfigFound { .. } => {
98 "The repo needs a tsconfig.json for TypeScript declaration extraction.\n\
99 If this is a monorepo, use --build-command to specify the project's \
100 own build system that generates .d.ts files."
101 .to_string()
102 }
103 Self::NoEmitConflict => {
104 "The tsconfig.json has 'noEmit: true' which conflicts with declaration \
105 generation.\n\
106 Options:\n\
107 - Add a tsconfig.build.json without noEmit\n\
108 - Use --build-command to specify a custom build that generates .d.ts files"
109 .to_string()
110 }
111 Self::TscFailed { error_count, .. } => format!(
112 "TypeScript compilation failed with {} error(s).\n\
113 Common causes:\n\
114 - Missing dependencies: run 'npm ci' or 'yarn install' first\n\
115 - Incompatible TypeScript version\n\
116 - Project references not built: try 'tsc --build' in the monorepo root\n\
117 Use --log-file debug.log to see full tsc output.",
118 error_count
119 ),
120 Self::MissingDependencies { .. } => {
121 "TypeScript cannot resolve imports — dependencies are not installed.\n\
122 Ensure the package install step completed successfully.\n\
123 If using a monorepo, dependencies may need to be hoisted or linked."
124 .to_string()
125 }
126 Self::ProjectReferencesNotBuilt => {
127 "This monorepo uses TypeScript project references.\n\
128 Run 'tsc --build' in the monorepo root to build all referenced \
129 projects, then retry."
130 .to_string()
131 }
132 Self::ProjectBuildFailed { command, .. } => format!(
133 "The build command '{}' failed.\n\
134 Try running this command manually in the repo directory to debug.\n\
135 Check that all prerequisites (Node.js version, native build tools) are met.\n\
136 Use --log-file debug.log for full build output.",
137 command
138 ),
139 Self::InsufficientDiskSpace {
140 needed_mb,
141 available_mb,
142 } => format!(
143 "Need approximately {}MB of disk space but only {}MB available.\n\
144 Free up disk space — each worktree needs room for node_modules \
145 and build artifacts.",
146 needed_mb, available_mb
147 ),
148 Self::UnsupportedSyntax { .. } => {
149 "The TypeScript source at this ref uses syntax that cannot be parsed.\n\
150 This may indicate a very old or experimental TypeScript version.\n\
151 Check that the ref you specified is correct."
152 .to_string()
153 }
154 Self::CommandFailed(_) | Self::Io(_) | Self::WorktreeRemovalFailed { .. } => {
156 return None
157 }
158 })
159 }
160}