1pub mod meta;
19pub mod restore;
20
21pub use meta::{BackupFile, BackupMeta};
22pub use restore::{DEFAULT_CONCURRENCY, RestoreOptions, fetch_meta, list_backup_ids, restore};
23
24use std::io;
25use std::path::PathBuf;
26use std::string::FromUtf8Error;
27
28use object_store::path::Path as StorePath;
29
30#[cfg(feature = "easy")]
40pub fn public_bucket(
41 endpoint: &str,
42) -> Result<std::sync::Arc<dyn object_store::ObjectStore>, Error> {
43 use object_store::aws::AmazonS3Builder;
44 use std::sync::Arc;
45
46 let store = AmazonS3Builder::new()
47 .with_endpoint(endpoint)
48 .with_bucket_name("_")
49 .with_skip_signature(true)
50 .with_allow_http(true)
51 .with_virtual_hosted_style_request(true)
52 .build()
53 .map_err(|e| Error::ObjectStoreBuild {
54 endpoint: endpoint.to_string(),
55 source: e,
56 })?;
57
58 Ok(Arc::new(store))
59}
60
61#[derive(Debug, thiserror::Error)]
63pub enum Error {
64 #[cfg(feature = "easy")]
65 #[error("failed to build object store")]
66 ObjectStoreBuild {
67 endpoint: String,
68 #[source]
69 source: object_store::Error,
70 },
71
72 #[error("failed to list objects under {prefix:?}")]
73 List {
74 prefix: StorePath,
75 #[source]
76 source: object_store::Error,
77 },
78
79 #[error("failed to fetch {key:?}")]
80 Fetch {
81 key: StorePath,
82 #[source]
83 source: object_store::Error,
84 },
85
86 #[error("meta file for backup {backup_id} is not valid UTF-8")]
87 MetaEncoding {
88 backup_id: u64,
89 #[source]
90 source: FromUtf8Error,
91 },
92
93 #[error("failed to parse meta file for backup {backup_id}")]
94 MetaParse {
95 backup_id: u64,
96 #[source]
97 source: meta::ParseError,
98 },
99
100 #[error("no backups found")]
101 NoBackups,
102
103 #[error("backup contains {count} excluded file(s) (unsupported)")]
104 ExcludedFiles { count: usize },
105
106 #[error("backup path has unrecognized prefix: {0:?}")]
107 UnrecognizedPathPrefix(String),
108
109 #[error("shared_checksum filename missing underscore: {0:?}")]
110 SharedChecksumNoUnderscore(String),
111
112 #[error("shared_checksum filename missing extension: {0:?}")]
113 SharedChecksumNoExtension(String),
114
115 #[error("private/ path has too few components: {0:?}")]
116 PrivatePathTooShort(String),
117
118 #[error("size mismatch on {path}: expected {expected} bytes, got {actual}")]
119 SizeMismatch {
120 path: String,
121 expected: u64,
122 actual: u64,
123 },
124
125 #[error("crc32c mismatch on {path}: expected {expected:#010x}, got {actual:#010x}")]
126 ChecksumMismatch {
127 path: String,
128 expected: u32,
129 actual: u32,
130 },
131
132 #[error("{}: {source}", path.display())]
133 Io {
134 path: PathBuf,
135 #[source]
136 source: io::Error,
137 },
138}