Skip to main content

sage_package/
error.rs

1//! Error types for the package manager.
2
3use miette::Diagnostic;
4use std::path::PathBuf;
5use thiserror::Error;
6
7/// Errors that can occur during package operations.
8#[derive(Debug, Error, Diagnostic)]
9pub enum PackageError {
10    /// E030: Two packages require incompatible versions of the same dependency.
11    #[error("incompatible versions of '{package}'")]
12    #[diagnostic(
13        code(E030),
14        help("Oswyn explains: '{package}' is required at {version_a} by {requirer_a} and {version_b} by {requirer_b}")
15    )]
16    IncompatibleVersions {
17        package: String,
18        version_a: String,
19        requirer_a: String,
20        version_b: String,
21        requirer_b: String,
22    },
23
24    /// E031: Package name in sage add doesn't match package's grove.toml.
25    #[error("package name mismatch: expected '{expected}', found '{found}'")]
26    #[diagnostic(
27        code(E031),
28        help("Oswyn explains: the package declares its name as '{found}' in grove.toml")
29    )]
30    PackageNameMismatch { expected: String, found: String },
31
32    /// E032: Attempted to use an executable package as a library dependency.
33    #[error("'{package}' is an executable, not a library")]
34    #[diagnostic(
35        code(E032),
36        help("Oswyn explains: packages with a `run` statement cannot be used as dependencies")
37    )]
38    DependencyIsExecutable { package: String },
39
40    /// E033: sage run --offline with no lock file.
41    #[error("no lock file found")]
42    #[diagnostic(
43        code(E033),
44        help("Oswyn suggests: run `sage install` to create a lock file")
45    )]
46    LockFileMissing { path: PathBuf },
47
48    /// E034: use references a package not declared in dependencies.
49    #[error("package '{package}' not found in dependencies")]
50    #[diagnostic(
51        code(E034),
52        help("Oswyn suggests: add it with `sage add {package} --git <url>`")
53    )]
54    PackageNotFound { package: String },
55
56    /// E035: Git clone/fetch operation failed.
57    #[error("failed to fetch '{url}'")]
58    #[diagnostic(code(E035), help("Oswyn explains: {reason}"))]
59    GitFetchFailed { url: String, reason: String },
60
61    /// Invalid dependency specification in grove.toml.
62    #[error("invalid dependency specification for '{package}'")]
63    #[diagnostic(
64        code(sage::package::invalid_dep),
65        help("Oswyn explains: dependencies must specify exactly one of: tag, branch, or rev")
66    )]
67    InvalidDependencySpec { package: String },
68
69    /// Missing git URL for a dependency.
70    #[error("missing 'git' URL for dependency '{package}'")]
71    #[diagnostic(code(sage::package::missing_git))]
72    MissingGitUrl { package: String },
73
74    /// IO error during package operations.
75    #[error("IO error: {message}")]
76    #[diagnostic(code(sage::package::io_error))]
77    IoError {
78        message: String,
79        #[source]
80        source: std::io::Error,
81    },
82
83    /// Failed to parse package manifest.
84    #[error("invalid grove.toml in '{package}'")]
85    #[diagnostic(code(sage::package::invalid_manifest))]
86    InvalidManifest {
87        package: String,
88        #[source]
89        source: toml::de::Error,
90    },
91
92    /// Lock file is stale (grove.toml changed).
93    #[error("grove.lock is out of date")]
94    #[diagnostic(
95        code(sage::package::stale_lock),
96        help("Oswyn suggests: run `sage install` to update")
97    )]
98    StaleLockFile,
99
100    /// Failed to parse lock file.
101    #[error("invalid grove.lock")]
102    #[diagnostic(code(sage::package::invalid_lock))]
103    InvalidLockFile {
104        #[source]
105        source: toml::de::Error,
106    },
107}
108
109impl From<std::io::Error> for PackageError {
110    fn from(err: std::io::Error) -> Self {
111        PackageError::IoError {
112            message: err.to_string(),
113            source: err,
114        }
115    }
116}