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("'{package}' is required at version {version_a} by {requirer_a} and version {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 sage.toml.
25    #[error("package name mismatch: expected '{expected}', found '{found}'")]
26    #[diagnostic(
27        code(E031),
28        help("the package declares its name as '{found}' in its sage.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("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("run `sage install` to create a lock file, or remove --offline")
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(code(E034), help("add it with `sage add {package} --git <url>`"))]
51    PackageNotFound { package: String },
52
53    /// E035: Git clone/fetch operation failed.
54    #[error("failed to fetch '{url}'")]
55    #[diagnostic(code(E035), help("{reason}"))]
56    GitFetchFailed { url: String, reason: String },
57
58    /// Invalid dependency specification in sage.toml.
59    #[error("invalid dependency specification for '{package}'")]
60    #[diagnostic(
61        code(sage::package::invalid_dep),
62        help("dependencies must specify exactly one of: tag, branch, or rev")
63    )]
64    InvalidDependencySpec { package: String },
65
66    /// Missing git URL for a dependency.
67    #[error("missing 'git' URL for dependency '{package}'")]
68    #[diagnostic(code(sage::package::missing_git))]
69    MissingGitUrl { package: String },
70
71    /// IO error during package operations.
72    #[error("IO error: {message}")]
73    #[diagnostic(code(sage::package::io_error))]
74    IoError {
75        message: String,
76        #[source]
77        source: std::io::Error,
78    },
79
80    /// Failed to parse package manifest.
81    #[error("invalid sage.toml in '{package}'")]
82    #[diagnostic(code(sage::package::invalid_manifest))]
83    InvalidManifest {
84        package: String,
85        #[source]
86        source: toml::de::Error,
87    },
88
89    /// Lock file is stale (sage.toml changed).
90    #[error("sage.lock is out of date")]
91    #[diagnostic(code(sage::package::stale_lock), help("run `sage install` to update"))]
92    StaleLockFile,
93
94    /// Failed to parse lock file.
95    #[error("invalid sage.lock")]
96    #[diagnostic(code(sage::package::invalid_lock))]
97    InvalidLockFile {
98        #[source]
99        source: toml::de::Error,
100    },
101}
102
103impl From<std::io::Error> for PackageError {
104    fn from(err: std::io::Error) -> Self {
105        PackageError::IoError {
106            message: err.to_string(),
107            source: err,
108        }
109    }
110}