use std::borrow::Cow;
use std::io;
use std::path::PathBuf;
use thiserror::Error;
use crate::blockdir::Address;
use crate::*;
#[non_exhaustive]
#[derive(Debug, Error)]
pub enum Error {
#[error("Block file {hash:?} corrupt: does not have the expected hash")]
BlockCorrupt { hash: BlockHash },
#[error("{address:?} extends beyond decompressed block length {actual_len:?}")]
AddressTooLong { address: Address, actual_len: usize },
#[error("Not a Conserve archive (no CONSERVE header found)")]
NotAnArchive,
#[error(
"Archive version {:?} is not supported by Conserve {}",
version,
crate::version()
)]
UnsupportedArchiveVersion { version: String },
#[error("Unsupported band version {version:?} in {band_id}")]
UnsupportedBandVersion { band_id: BandId, version: String },
#[error("Archive is empty")]
ArchiveEmpty,
#[error("Archive has no complete bands")]
NoCompleteBands,
#[error("Unsupported band format flags {unsupported_flags:?} in {band_id}")]
UnsupportedBandFormatFlags {
band_id: BandId,
unsupported_flags: Vec<Cow<'static, str>>,
},
#[error("Destination directory is not empty")]
DestinationNotEmpty,
#[error("Directory for new archive is not empty")]
NewArchiveDirectoryNotEmpty,
#[error("Invalid backup version number {:?}", version)]
InvalidVersion { version: String },
#[error("Band {band_id} head file missing")]
BandHeadMissing { band_id: BandId },
#[error(
"Can't delete blocks because the last band ({}) is incomplete and may be in use",
band_id
)]
DeleteWithIncompleteBackup { band_id: BandId },
#[error("Can't continue with deletion because the archive was changed by another process")]
DeleteWithConcurrentActivity,
#[error("Archive is locked for garbage collection")]
GarbageCollectionLockHeld,
#[error("A backup was created while the garbage collection lock was held; CHECK ARCHIVE NOW")]
GarbageCollectionLockHeldDuringBackup,
#[error(transparent)]
ParseGlob {
#[from]
source: globset::Error,
},
#[error("Failed to deserialize json from {:?}", path)]
DeserializeJson {
path: String,
#[source]
source: serde_json::Error,
},
#[error("Failed to serialize json")]
SerializeJson {
#[from]
source: serde_json::Error,
},
#[error("Invalid metadata: {details}")]
InvalidMetadata { details: String },
#[error("Band not found: {band_id}")]
BandNotFound { band_id: BandId },
#[error("Failed to list bands")]
ListBands { source: io::Error },
#[error("Failed to read source file {:?}", path)]
ReadSourceFile { path: PathBuf, source: io::Error },
#[error("Unsupported source file kind: {path:?}")]
UnsupportedSourceKind { path: PathBuf },
#[error("Unsupported symlink encoding: {path:?}")]
UnsupportedTargetEncoding { path: PathBuf },
#[error("Failed to read source tree {:?}", path)]
ListSourceTree { path: PathBuf, source: io::Error },
#[error("Failed to restore {:?}", path)]
Restore { path: PathBuf, source: io::Error },
#[error("Failed to restore modification time on {:?}", path)]
RestoreModificationTime { path: PathBuf, source: io::Error },
#[error("Unsupported URL scheme {:?}", scheme)]
UrlScheme { scheme: String },
#[error("Unexpected file {path:?} in archive directory")]
UnexpectedFile { path: String },
#[error(transparent)]
IOError {
#[from]
source: io::Error,
},
#[error("Failed to set owner of {path:?}")]
SetOwner { source: io::Error, path: PathBuf },
#[error(transparent)]
SnapCompressionError {
#[from]
source: snap::Error,
},
#[error(transparent)]
Transport {
#[from]
source: transport::Error,
},
}
impl From<jsonio::Error> for Error {
fn from(value: jsonio::Error) -> Self {
match value {
jsonio::Error::Io { source } => Error::IOError { source },
jsonio::Error::Json { source, path } => Error::DeserializeJson {
source,
path: path.to_string_lossy().into_owned(),
}, jsonio::Error::Transport { source } => Error::Transport { source },
}
}
}