Start implementing a cas in separate crates.
This commit is contained in:
@@ -6,7 +6,7 @@ edition = "2018"
|
||||
license = "AGPL-3.0-or-later"
|
||||
|
||||
[dependencies]
|
||||
error-chain = "0.12.2"
|
||||
thiserror = "1.0.25"
|
||||
serde = { version = "1.0.106", features = ["derive"] }
|
||||
toml = "0.5.6"
|
||||
uuid = { version = "0.8.1", features = ["serde", "v4"] }
|
||||
|
||||
@@ -17,50 +17,99 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
||||
error_chain! {
|
||||
foreign_links {
|
||||
Io(::std::io::Error);
|
||||
}
|
||||
pub type Result<T> = std::result::Result<T, Box<Error>>;
|
||||
|
||||
errors {
|
||||
NoRepositorySpecifiedError {
|
||||
description("No repository specifed")
|
||||
display("No repository specifed. Use -r or set BSV_REPOSITORY environment variable.")
|
||||
}
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("failed to create repository: {message}")]
|
||||
RepositoryCreationFailed {
|
||||
message: String,
|
||||
source: Option<Box<dyn std::error::Error>>,
|
||||
},
|
||||
|
||||
NonEmptyDirectory(dir: PathBuf) {
|
||||
description("Non-empty directory")
|
||||
display("Target directory {:?} must be empty.", dir)
|
||||
}
|
||||
#[error("invalid object id: {message}")]
|
||||
InvalidObjectId {
|
||||
message: String,
|
||||
source: Option<Box<dyn std::error::Error>>,
|
||||
},
|
||||
|
||||
InvalidObjectIdSize {
|
||||
description("Object id has an invalid size")
|
||||
display("Object id has an invalid size.")
|
||||
}
|
||||
#[error("invalid size (got: {size}, expected: {expected})")]
|
||||
InvalidSize {
|
||||
size: usize,
|
||||
expected: usize,
|
||||
},
|
||||
|
||||
InvalidObjectIdCharacter {
|
||||
description("Object id contains invalid character")
|
||||
display("Object id contains invalid character.")
|
||||
}
|
||||
#[error("non-empty directory ({dir})")]
|
||||
NonEmptyDirectory {
|
||||
dir: PathBuf
|
||||
},
|
||||
|
||||
InvalidObjectType(otype: [u8; 4]) {
|
||||
description("Object has an invalid object type")
|
||||
display("Object has an invalid object type {:?}.", otype)
|
||||
}
|
||||
#[error("invalid character(s) ({characters})")]
|
||||
InvalidObjectIdCharacter {
|
||||
characters: String,
|
||||
},
|
||||
|
||||
MismatchingObjectSize(actual: u64, expected: u64) {
|
||||
description("Mismatching object size")
|
||||
display("Mismatching object size: expected {}, got {}.", actual, expected)
|
||||
}
|
||||
#[error("invalid object type ({otype:?})")]
|
||||
InvalidObjectType {
|
||||
otype: [u8; 4],
|
||||
},
|
||||
|
||||
UnsupportedFileType {
|
||||
description("Unsupported file type")
|
||||
display("Unsupported file type.")
|
||||
}
|
||||
#[error("invalid object size (expected {expected}, got {size})")]
|
||||
InvalidObjectSize {
|
||||
size: u64,
|
||||
expected: u64,
|
||||
},
|
||||
|
||||
InvalidPath(path: PathBuf) {
|
||||
description("Invalid path")
|
||||
display("Invalid path: {:?}.", path)
|
||||
}
|
||||
#[error("unsupported file type")]
|
||||
UnsupportedFileType,
|
||||
|
||||
#[error("invalid path ({path})")]
|
||||
InvalidPath { path: PathBuf },
|
||||
|
||||
#[error("io error{}", format_optional_path(path))]
|
||||
IoError {
|
||||
source: std::io::Error,
|
||||
path: Option<PathBuf>,
|
||||
},
|
||||
|
||||
#[error("{0}")]
|
||||
Other(String),
|
||||
}
|
||||
|
||||
|
||||
pub fn repository_creation_failed<M: Into<String>>(message: M) -> Box<Error> {
|
||||
Box::new(Error::RepositoryCreationFailed {
|
||||
message: message.into(),
|
||||
source: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn repository_creation_failed_from<M: Into<String>>(source: Box<dyn std::error::Error>, message: M) -> Box<Error> {
|
||||
Box::new(Error::RepositoryCreationFailed {
|
||||
message: message.into(),
|
||||
source: Some(source),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn invalid_object_id<M: Into<String>>(message: M) -> Box<Error> {
|
||||
Box::new(Error::InvalidObjectId {
|
||||
message: message.into(),
|
||||
source: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn invalid_object_id_from<M: Into<String>>(source: Box<dyn std::error::Error>, message: M) -> Box<Error> {
|
||||
Box::new(Error::InvalidObjectId {
|
||||
message: message.into(),
|
||||
source: Some(source),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
fn format_optional_path(maybe_path: &Option<PathBuf>) -> String {
|
||||
match maybe_path {
|
||||
Some(path) => { format!(" ({:?})", path) },
|
||||
None => { String::new() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,18 +15,18 @@
|
||||
|
||||
|
||||
pub mod error;
|
||||
pub mod config;
|
||||
pub mod object_id;
|
||||
pub mod object;
|
||||
pub mod repository;
|
||||
// pub mod config;
|
||||
// pub mod object_id;
|
||||
// pub mod object;
|
||||
// pub mod repository;
|
||||
|
||||
|
||||
pub const NAME: &str = env!("CARGO_PKG_NAME");
|
||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
|
||||
pub use error::{Error, Result, ErrorKind};
|
||||
pub use config::{Config, RepositoryConfig};
|
||||
pub use object_id::ObjectId;
|
||||
pub use object::{ObjectType, OTYPE_BLOB, OTYPE_TREE};
|
||||
pub use repository::Repository;
|
||||
pub use error::{Error, Result};
|
||||
// pub use config::{Config, RepositoryConfig};
|
||||
// pub use object_id::ObjectId;
|
||||
// pub use object::{ObjectType, OTYPE_BLOB, OTYPE_TREE};
|
||||
// pub use repository::Repository;
|
||||
|
||||
@@ -35,7 +35,7 @@ pub fn object_type_from_metadata(md: &Metadata) -> Result<ObjectType> {
|
||||
Ok(*OTYPE_TREE)
|
||||
}
|
||||
else {
|
||||
Err(ErrorKind::UnsupportedFileType.into())
|
||||
Err(Error::UnsupportedFileType)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,12 @@ impl TreeItem {
|
||||
}
|
||||
|
||||
pub fn from_file_path_and_id(file_path: &Path, oid: &ObjectId) -> Result<TreeItem> {
|
||||
let md = file_path.symlink_metadata()?;
|
||||
let md = file_path.symlink_metadata()
|
||||
.map_err(|err| Error::IoError {
|
||||
source: err,
|
||||
path: Some(file_path.to_path_buf())
|
||||
})?;
|
||||
|
||||
Ok(TreeItem {
|
||||
otype: object_type_from_metadata(&md)?,
|
||||
oid: oid.clone(),
|
||||
@@ -145,7 +150,7 @@ impl TreeItem {
|
||||
permissions: Permissions::from_unix_mode(md.mode()),
|
||||
name: file_path.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.ok_or_else(|| ErrorKind::InvalidPath(file_path.into()))?
|
||||
.ok_or_else(|| Error::InvalidPath { path: file_path.into() })?
|
||||
.into(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ impl FromStr for ObjectId {
|
||||
|
||||
fn from_str(id_str: &str) -> Result<ObjectId> {
|
||||
if id_str.len() % 2 != 0 {
|
||||
return Err(ErrorKind::InvalidObjectIdSize.into());
|
||||
return Err(Error::InvalidObjectIdSize);
|
||||
}
|
||||
|
||||
let byte_count = id_str.len() / 2;
|
||||
@@ -53,9 +53,9 @@ impl FromStr for ObjectId {
|
||||
for byte_index in 0..byte_count {
|
||||
let str_index = byte_index * 2;
|
||||
let byte_str = id_str.get(str_index..(str_index + 2))
|
||||
.ok_or(ErrorKind::InvalidObjectIdCharacter)?;
|
||||
.ok_or(Error::InvalidObjectIdCharacter)?;
|
||||
id.push(u8::from_str_radix(byte_str, 16)
|
||||
.or(Err(ErrorKind::InvalidObjectIdCharacter))?);
|
||||
.or(Err(Error::InvalidObjectIdCharacter))?);
|
||||
}
|
||||
|
||||
Ok(ObjectId {
|
||||
|
||||
@@ -39,14 +39,14 @@ pub struct Repository {
|
||||
impl Repository {
|
||||
pub fn create(path: &Path, device_name: &str) -> Result<Repository> {
|
||||
if path.exists() {
|
||||
bail!(ErrorKind::NonEmptyDirectory(path.into()))
|
||||
return Err(Error::NonEmptyDirectory { dir: path.to_path_buf() });
|
||||
}
|
||||
|
||||
if device_name.is_empty() {
|
||||
bail!("Device name must not be empty.")
|
||||
return Err(Error::RepositoryCreationFailed("Device name must not be empty.".to_string()));
|
||||
}
|
||||
|
||||
create_dir(&path).chain_err(|| "Failed to create repository.")?;
|
||||
create_dir(&path).map_err(|err| Error::IoError("Failed to create repository.")?;
|
||||
|
||||
let config = Rc::new(
|
||||
Config {
|
||||
|
||||
@@ -14,20 +14,20 @@
|
||||
// along with cdb. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#[macro_use]
|
||||
extern crate error_chain;
|
||||
// #[macro_use]
|
||||
extern crate thiserror;
|
||||
extern crate serde;
|
||||
|
||||
|
||||
pub mod core;
|
||||
pub mod simple_db;
|
||||
// pub mod simple_db;
|
||||
|
||||
|
||||
pub use crate::core::{
|
||||
Error, Result, ErrorKind,
|
||||
Config, RepositoryConfig,
|
||||
ObjectId, ObjectType,
|
||||
Repository,
|
||||
// pub use crate::core::{
|
||||
// Error, Result,
|
||||
// Config, RepositoryConfig,
|
||||
// ObjectId, ObjectType,
|
||||
// Repository,
|
||||
|
||||
OTYPE_BLOB, OTYPE_TREE,
|
||||
};
|
||||
// OTYPE_BLOB, OTYPE_TREE,
|
||||
// };
|
||||
|
||||
Reference in New Issue
Block a user