1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use std::path::PathBuf;

use miette::Diagnostic;
use node_semver::Version;
use oro_common::CorgiVersionMetadata;
use oro_package_spec::PackageSpec;
use thiserror::Error;

/// Error type returned by all API calls.
#[derive(Error, Debug, Diagnostic)]
pub enum NassunError {
    /// Something went wrong while fetching a package.
    #[error("Package for `{0}` was found, but resolved version `{1}` does not exist.")]
    #[diagnostic(
        code(nassun::missing_version),
        help("Try using `oro view` to see what versions are available")
    )]
    MissingVersion(PackageSpec, Version),

    /// Something went wrong while trying to parse a PackageArg
    #[error(transparent)]
    PackageSpecError(#[from] oro_package_spec::PackageSpecError),

    #[error("{0}")]
    #[diagnostic(code(nassun::dir::read))]
    DirReadError(#[source] std::io::Error, PathBuf),

    #[error("Failed to execute git subprocess. {0}")]
    #[diagnostic(code(nassun::git::clone::io))]
    GitIoError(#[source] std::io::Error),

    #[error("Failed to clone repository at `{0}`")]
    #[diagnostic(code(nassun::git::clone::repo))]
    GitCloneError(String),

    #[error("Failed to check out `{0}#{1}`")]
    #[diagnostic(code(nassun::git::checkout::repo))]
    GitCheckoutError(String, String),

    #[error("Failed to extract tarball while {2}{}", if let Some(path) = .1 {
        format!(" (file: {})", path.to_string_lossy())
    } else {
        "".to_string()
    })]
    #[diagnostic(code(nassun::io::extract))]
    ExtractIoError(#[source] std::io::Error, Option<PathBuf>, String),

    #[cfg(not(target_arch = "wasm32"))]
    #[error("Failed to extract tarball to cache. {0}{}", if let Some(path) = .1 {
        format!(" (file: {})", path.to_string_lossy())
    } else {
        "".to_string()
    })]
    #[diagnostic(code(nassun::cache::extract))]
    ExtractCacheError(#[source] cacache::Error, Option<PathBuf>),

    #[error(transparent)]
    #[diagnostic(code(nassun::io::generic))]
    IoError(#[from] std::io::Error),

    #[error(transparent)]
    #[diagnostic(transparent)]
    OroClientError(#[from] oro_client::OroClientError),

    #[error(transparent)]
    #[diagnostic(code(nassun::serde))]
    SerdeError(#[from] serde_json::Error),

    #[error(transparent)]
    #[diagnostic(code(nassun::bad_url))]
    UrlError(#[from] url::ParseError),

    #[error(transparent)]
    #[diagnostic(code(nassun::integrity_parse_error))]
    IntegrityError(#[from] ssri::Error),

    #[error("Package metadata for {0} is missing a package tarball URL.")]
    #[diagnostic(code(nassun::no_tarball))]
    NoTarball(String, PackageSpec, Box<CorgiVersionMetadata>),

    #[error("No matching `{name}` version found for spec `{spec}`.")]
    #[diagnostic(
        code(resolver::no_matching_version),
        // TODO: format help string using variables?
        help("Try using `oro view` to see what versions are available")
    )]
    NoVersion {
        name: String,
        spec: PackageSpec,
        versions: Vec<String>,
    },

    #[cfg(target_arch = "wasm32")]
    #[error(transparent)]
    #[diagnostic(code(node_maintainer::serde_wasm_bindgen::error))]
    SerdeWasmBindgenError(#[from] serde_wasm_bindgen::Error),

    #[cfg(not(target_arch = "wasm32"))]
    #[error(transparent)]
    #[diagnostic(
        code(nassun::which_git_failure),
        help("Are you sure git is installed and available in your $PATH?")
    )]
    WhichGit(#[from] which::Error),

    #[error("Only Version, Tag, Range, and Alias package args are supported, but got `{0}`.")]
    #[diagnostic(code(nassun::invalid_package_spec))]
    InvalidPackageSpec(PackageSpec),

    #[error("Unsupported dummy package operation: {0}")]
    #[diagnostic(code(nassun::unsupported_dummy_operation))]
    UnsupportedDummyOperation(String),

    #[error("Dummy package does not have a name.")]
    #[diagnostic(code(nassun::dummy_no_name))]
    DummyNoName,

    /// A miscellaneous, usually internal error. This is used mainly to wrap
    /// either manual InternalErrors, or those using external errors that
    /// don't implement std::error::Error.
    #[error("{0}")]
    #[diagnostic(code(nassun::misc))]
    MiscError(String),
}

/// The result type returned by calls to this library
pub type Result<T> = std::result::Result<T, NassunError>;