Skip to main content

snix_build_glue/fetchers/
error.rs

1use nix_compat::nixhash::NixHash;
2use nix_compat::store_path;
3use snix_castore::import;
4use url::Url;
5
6#[derive(Debug, thiserror::Error)]
7pub enum FetcherError {
8    #[error("hash mismatch in file downloaded from {}:\n  wanted: {}\n     got: {}", _0.0, _0.1, _0.2)]
9    HashMismatch(Box<(Url, NixHash, NixHash)>),
10
11    #[error("Invalid hash type '{0}' for fetcher")]
12    InvalidHashType(&'static str),
13
14    #[error("Unable to parse URL: {0}")]
15    InvalidUrl(#[from] url::ParseError),
16
17    #[error(transparent)]
18    Http(#[from] reqwest::Error),
19
20    #[error(transparent)]
21    Io(#[from] std::io::Error),
22
23    #[error(transparent)]
24    Import(Box<snix_castore::import::IngestionError<import::archive::Error>>),
25
26    #[error("Error calculating store path for fetcher output: {0}")]
27    StorePath(#[from] store_path::ParseStorePathError),
28}
29
30impl FetcherError {
31    /// Helper to constructs a HashMismatch error kind.
32    pub fn hash_mismatch(url: Url, expected: NixHash, actual: NixHash) -> Self {
33        Self::HashMismatch(Box::new((url, expected, actual)))
34    }
35}
36
37// thiserror doesn't support Box<#[from] ...> unfortunately
38impl From<snix_castore::import::IngestionError<import::archive::Error>> for FetcherError {
39    fn from(value: snix_castore::import::IngestionError<import::archive::Error>) -> Self {
40        Self::Import(Box::new(value))
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn test_hash_mismatch_display() {
50        let err = FetcherError::hash_mismatch(
51            Url::parse("https://example.com/foo.tar.gz").unwrap(),
52            NixHash::Sha256([0; 32]),
53            NixHash::Sha256([1; 32]),
54        );
55        let msg = err.to_string();
56        assert!(msg.contains("https://example.com/foo.tar.gz"));
57        assert!(
58            msg.contains(
59                "wanted: sha256:0000000000000000000000000000000000000000000000000000000000000000"
60            ) || msg.contains("wanted:")
61        );
62        assert!(!msg.contains("wanted: 0.1"));
63    }
64}