Compare commits
3 Commits
cab7a837a7
...
7daa864739
Author | SHA1 | Date | |
---|---|---|---|
|
7daa864739 | ||
|
1fdd023f50 | ||
|
45597ab8d8 |
@ -1,9 +1,9 @@
|
|||||||
use std::error::Error;
|
|
||||||
use std::net;
|
use std::net;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync;
|
use std::sync;
|
||||||
|
|
||||||
use crate::domain;
|
use crate::error::MapUnexpected;
|
||||||
|
use crate::{domain, error};
|
||||||
|
|
||||||
use trust_dns_client::client::{AsyncClient, ClientHandle};
|
use trust_dns_client::client::{AsyncClient, ClientHandle};
|
||||||
use trust_dns_client::rr::{DNSClass, Name, RData, RecordType};
|
use trust_dns_client::rr::{DNSClass, Name, RData, RecordType};
|
||||||
@ -15,7 +15,7 @@ pub enum NewDNSCheckerError {
|
|||||||
InvalidResolverAddress,
|
InvalidResolverAddress,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
@ -27,7 +27,7 @@ pub enum CheckDomainError {
|
|||||||
ChallengeTokenNotSet,
|
ChallengeTokenNotSet,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DNSChecker {
|
pub struct DNSChecker {
|
||||||
@ -50,7 +50,7 @@ pub fn new(
|
|||||||
|
|
||||||
let (client, bg) = tokio_runtime
|
let (client, bg) = tokio_runtime
|
||||||
.block_on(async { AsyncClient::connect(stream).await })
|
.block_on(async { AsyncClient::connect(stream).await })
|
||||||
.map_err(|e| NewDNSCheckerError::Unexpected(Box::from(e)))?;
|
.map_unexpected()?;
|
||||||
|
|
||||||
tokio_runtime.spawn(bg);
|
tokio_runtime.spawn(bg);
|
||||||
|
|
||||||
@ -68,18 +68,15 @@ impl DNSChecker {
|
|||||||
) -> Result<(), CheckDomainError> {
|
) -> Result<(), CheckDomainError> {
|
||||||
let domain = &domain.inner;
|
let domain = &domain.inner;
|
||||||
|
|
||||||
// check that the AAAA is installed correctly on the domain
|
// check that the A is installed correctly on the domain
|
||||||
{
|
{
|
||||||
let response = match self
|
let response = self
|
||||||
.client
|
.client
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.query(domain.clone(), DNSClass::IN, RecordType::A)
|
.query(domain.clone(), DNSClass::IN, RecordType::A)
|
||||||
.await
|
.await
|
||||||
{
|
.map_unexpected()?;
|
||||||
Ok(res) => res,
|
|
||||||
Err(e) => return Err(CheckDomainError::Unexpected(Box::from(e))),
|
|
||||||
};
|
|
||||||
|
|
||||||
let records = response.answers();
|
let records = response.answers();
|
||||||
|
|
||||||
@ -98,20 +95,17 @@ impl DNSChecker {
|
|||||||
// check that the TXT record with the challenge token is correctly installed on the domain
|
// check that the TXT record with the challenge token is correctly installed on the domain
|
||||||
{
|
{
|
||||||
let domain = Name::from_str("_domiply_challenge")
|
let domain = Name::from_str("_domiply_challenge")
|
||||||
.map_err(|e| CheckDomainError::Unexpected(Box::from(e)))?
|
.map_unexpected()?
|
||||||
.append_domain(domain)
|
.append_domain(domain)
|
||||||
.map_err(|e| CheckDomainError::Unexpected(Box::from(e)))?;
|
.map_unexpected()?;
|
||||||
|
|
||||||
let response = match self
|
let response = self
|
||||||
.client
|
.client
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.query(domain, DNSClass::IN, RecordType::TXT)
|
.query(domain, DNSClass::IN, RecordType::TXT)
|
||||||
.await
|
.await
|
||||||
{
|
.map_unexpected()?;
|
||||||
Ok(res) => res,
|
|
||||||
Err(e) => return Err(CheckDomainError::Unexpected(Box::from(e))),
|
|
||||||
};
|
|
||||||
|
|
||||||
let records = response.answers();
|
let records = response.answers();
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use std::error::Error;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::{fs, io, sync};
|
use std::{fs, io, sync};
|
||||||
|
|
||||||
use crate::domain;
|
use crate::error::{MapUnexpected, ToUnexpected};
|
||||||
use crate::origin::Descr;
|
use crate::{domain, error, origin};
|
||||||
|
|
||||||
use hex::ToHex;
|
use hex::ToHex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -12,13 +11,13 @@ use sha2::{Digest, Sha256};
|
|||||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||||
/// Values which the owner of a domain can configure when they install a domain.
|
/// Values which the owner of a domain can configure when they install a domain.
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub origin_descr: Descr,
|
pub origin_descr: origin::Descr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn hash(&self) -> Result<String, Box<dyn Error>> {
|
pub fn hash(&self) -> Result<String, error::Unexpected> {
|
||||||
let mut h = Sha256::new();
|
let mut h = Sha256::new();
|
||||||
serde_json::to_writer(&mut h, self)?;
|
serde_json::to_writer(&mut h, self).map_unexpected()?;
|
||||||
Ok(h.finalize().encode_hex::<String>())
|
Ok(h.finalize().encode_hex::<String>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,13 +28,13 @@ pub enum GetError {
|
|||||||
NotFound,
|
NotFound,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum SetError {
|
pub enum SetError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[mockall::automock]
|
#[mockall::automock]
|
||||||
@ -74,21 +73,19 @@ impl Store for sync::Arc<FSStore> {
|
|||||||
let config_file =
|
let config_file =
|
||||||
fs::File::open(self.config_file_path(domain)).map_err(|e| match e.kind() {
|
fs::File::open(self.config_file_path(domain)).map_err(|e| match e.kind() {
|
||||||
io::ErrorKind::NotFound => GetError::NotFound,
|
io::ErrorKind::NotFound => GetError::NotFound,
|
||||||
_ => GetError::Unexpected(Box::from(e)),
|
_ => e.to_unexpected().into(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
serde_json::from_reader(config_file).map_err(|e| GetError::Unexpected(Box::from(e)))
|
let config = serde_json::from_reader(config_file).map_unexpected()?;
|
||||||
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set(&self, domain: &domain::Name, config: &Config) -> Result<(), SetError> {
|
fn set(&self, domain: &domain::Name, config: &Config) -> Result<(), SetError> {
|
||||||
fs::create_dir_all(self.config_dir_path(domain))
|
fs::create_dir_all(self.config_dir_path(domain)).map_unexpected()?;
|
||||||
.map_err(|e| SetError::Unexpected(Box::from(e)))?;
|
|
||||||
|
|
||||||
let config_file = fs::File::create(self.config_file_path(domain))
|
let config_file = fs::File::create(self.config_file_path(domain)).map_unexpected()?;
|
||||||
.map_err(|e| SetError::Unexpected(Box::from(e)))?;
|
|
||||||
|
|
||||||
serde_json::to_writer(config_file, config)
|
serde_json::to_writer(config_file, config).map_unexpected()?;
|
||||||
.map_err(|e| SetError::Unexpected(Box::from(e)))?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use crate::domain::{self, checker, config};
|
use crate::domain::{self, checker, config};
|
||||||
use crate::origin;
|
use crate::error::{MapUnexpected, ToUnexpected};
|
||||||
use std::error::Error;
|
use crate::{error, origin};
|
||||||
use std::future::Future;
|
|
||||||
|
use std::future;
|
||||||
use std::{pin, sync};
|
use std::{pin, sync};
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
@ -10,7 +11,7 @@ pub enum GetConfigError {
|
|||||||
NotFound,
|
NotFound,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<config::GetError> for GetConfigError {
|
impl From<config::GetError> for GetConfigError {
|
||||||
@ -28,7 +29,7 @@ pub enum GetOriginError {
|
|||||||
NotFound,
|
NotFound,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<config::GetError> for GetOriginError {
|
impl From<config::GetError> for GetOriginError {
|
||||||
@ -49,7 +50,7 @@ pub enum SyncError {
|
|||||||
AlreadyInProgress,
|
AlreadyInProgress,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<config::GetError> for SyncError {
|
impl From<config::GetError> for SyncError {
|
||||||
@ -79,7 +80,7 @@ pub enum SyncWithConfigError {
|
|||||||
ChallengeTokenNotSet,
|
ChallengeTokenNotSet,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<origin::store::SyncError> for SyncWithConfigError {
|
impl From<origin::store::SyncError> for SyncWithConfigError {
|
||||||
@ -113,19 +114,30 @@ impl From<config::SetError> for SyncWithConfigError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[mockall::automock]
|
#[mockall::automock(
|
||||||
|
type Origin=origin::MockOrigin;
|
||||||
|
type SyncWithConfigFuture=future::Ready<Result<(), SyncWithConfigError>>;
|
||||||
|
)]
|
||||||
pub trait Manager {
|
pub trait Manager {
|
||||||
|
type Origin<'mgr>: origin::Origin + 'mgr
|
||||||
|
where
|
||||||
|
Self: 'mgr;
|
||||||
|
|
||||||
|
type SyncWithConfigFuture<'mgr>: future::Future<Output = Result<(), SyncWithConfigError>>
|
||||||
|
+ Send
|
||||||
|
+ Unpin
|
||||||
|
+ 'mgr
|
||||||
|
where
|
||||||
|
Self: 'mgr;
|
||||||
|
|
||||||
fn get_config(&self, domain: &domain::Name) -> Result<config::Config, GetConfigError>;
|
fn get_config(&self, domain: &domain::Name) -> Result<config::Config, GetConfigError>;
|
||||||
fn get_origin(
|
fn get_origin(&self, domain: &domain::Name) -> Result<Self::Origin<'_>, GetOriginError>;
|
||||||
&self,
|
|
||||||
domain: &domain::Name,
|
|
||||||
) -> Result<Box<dyn origin::Origin + '_>, GetOriginError>;
|
|
||||||
fn sync(&self, domain: &domain::Name) -> Result<(), SyncError>;
|
fn sync(&self, domain: &domain::Name) -> Result<(), SyncError>;
|
||||||
fn sync_with_config(
|
fn sync_with_config(
|
||||||
&self,
|
&self,
|
||||||
domain: domain::Name,
|
domain: domain::Name,
|
||||||
config: config::Config,
|
config: config::Config,
|
||||||
) -> pin::Pin<Box<dyn Future<Output = Result<(), SyncWithConfigError>> + Send + '_>>;
|
) -> Self::SyncWithConfigFuture<'_>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BoxedManager: Manager + Send + Sync + Clone {}
|
pub trait BoxedManager: Manager + Send + Sync + Clone {}
|
||||||
@ -170,21 +182,24 @@ where
|
|||||||
OriginStore: origin::store::BoxedStore,
|
OriginStore: origin::store::BoxedStore,
|
||||||
DomainConfigStore: config::BoxedStore,
|
DomainConfigStore: config::BoxedStore,
|
||||||
{
|
{
|
||||||
|
type Origin<'mgr> = OriginStore::Origin<'mgr>
|
||||||
|
where Self: 'mgr;
|
||||||
|
|
||||||
|
type SyncWithConfigFuture<'mgr> = pin::Pin<Box<dyn future::Future<Output = Result<(), SyncWithConfigError>> + Send + 'mgr>>
|
||||||
|
where Self: 'mgr;
|
||||||
|
|
||||||
fn get_config(&self, domain: &domain::Name) -> Result<config::Config, GetConfigError> {
|
fn get_config(&self, domain: &domain::Name) -> Result<config::Config, GetConfigError> {
|
||||||
Ok(self.domain_config_store.get(domain)?)
|
Ok(self.domain_config_store.get(domain)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_origin(
|
fn get_origin(&self, domain: &domain::Name) -> Result<Self::Origin<'_>, GetOriginError> {
|
||||||
&self,
|
|
||||||
domain: &domain::Name,
|
|
||||||
) -> Result<Box<dyn origin::Origin + '_>, GetOriginError> {
|
|
||||||
let config = self.domain_config_store.get(domain)?;
|
let config = self.domain_config_store.get(domain)?;
|
||||||
let origin = self
|
let origin = self
|
||||||
.origin_store
|
.origin_store
|
||||||
.get(config.origin_descr)
|
.get(config.origin_descr)
|
||||||
// if there's a config there should be an origin, any error here is unexpected
|
// if there's a config there should be an origin, any error here is unexpected
|
||||||
.map_err(|e| GetOriginError::Unexpected(Box::from(e)))?;
|
.map_unexpected()?;
|
||||||
Ok(Box::from(origin))
|
Ok(origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync(&self, domain: &domain::Name) -> Result<(), SyncError> {
|
fn sync(&self, domain: &domain::Name) -> Result<(), SyncError> {
|
||||||
@ -193,7 +208,7 @@ where
|
|||||||
.sync(config.origin_descr, origin::store::Limits {})
|
.sync(config.origin_descr, origin::store::Limits {})
|
||||||
.map_err(|e| match e {
|
.map_err(|e| match e {
|
||||||
origin::store::SyncError::AlreadyInProgress => SyncError::AlreadyInProgress,
|
origin::store::SyncError::AlreadyInProgress => SyncError::AlreadyInProgress,
|
||||||
_ => SyncError::Unexpected(Box::from(e)),
|
_ => e.to_unexpected().into(),
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -202,11 +217,9 @@ where
|
|||||||
&self,
|
&self,
|
||||||
domain: domain::Name,
|
domain: domain::Name,
|
||||||
config: config::Config,
|
config: config::Config,
|
||||||
) -> pin::Pin<Box<dyn Future<Output = Result<(), SyncWithConfigError>> + Send + '_>> {
|
) -> Self::SyncWithConfigFuture<'_> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let config_hash = config
|
let config_hash = config.hash().map_unexpected()?;
|
||||||
.hash()
|
|
||||||
.map_err(|e| SyncWithConfigError::Unexpected(e))?;
|
|
||||||
|
|
||||||
self.domain_checker
|
self.domain_checker
|
||||||
.check_domain(&domain, &config_hash)
|
.check_domain(&domain, &config_hash)
|
||||||
|
50
src/error.rs
Normal file
50
src/error.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
use std::error;
|
||||||
|
use std::fmt;
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Unexpected(String);
|
||||||
|
|
||||||
|
impl fmt::Display for Unexpected {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Unexpected error occurred: {}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for Unexpected {}
|
||||||
|
|
||||||
|
impl From<&str> for Unexpected {
|
||||||
|
fn from(s: &str) -> Self {
|
||||||
|
Unexpected(s.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ToUnexpected {
|
||||||
|
fn to_unexpected(&self) -> Unexpected;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: error::Error> ToUnexpected for E {
|
||||||
|
fn to_unexpected(&self) -> Unexpected {
|
||||||
|
let mut w = String::new();
|
||||||
|
write!(w, "{}", self.to_string()).expect("underlying error formatted correctly");
|
||||||
|
|
||||||
|
if let Some(src) = self.source() {
|
||||||
|
write!(w, " [{src}]").expect("underyling source formatted correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
Unexpected(w.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait MapUnexpected<T> {
|
||||||
|
fn map_unexpected(self) -> Result<T, Unexpected>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, E: ToUnexpected> MapUnexpected<T> for Result<T, E> {
|
||||||
|
fn map_unexpected(self) -> Result<T, Unexpected> {
|
||||||
|
match self {
|
||||||
|
Ok(t) => Ok(t),
|
||||||
|
Err(err) => Err(err.to_unexpected()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
pub mod domain;
|
pub mod domain;
|
||||||
|
pub mod error;
|
||||||
pub mod origin;
|
pub mod origin;
|
||||||
pub mod service;
|
pub mod service;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::error::Error;
|
use crate::error;
|
||||||
|
|
||||||
mod descr;
|
mod descr;
|
||||||
pub use self::descr::Descr;
|
pub use self::descr::Descr;
|
||||||
@ -10,7 +10,7 @@ pub enum ReadFileIntoError {
|
|||||||
FileNotFound,
|
FileNotFound,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[mockall::automock]
|
#[mockall::automock]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::origin;
|
use crate::{error, origin};
|
||||||
use std::error::Error;
|
|
||||||
|
|
||||||
pub mod git;
|
pub mod git;
|
||||||
|
|
||||||
@ -20,7 +19,7 @@ pub enum SyncError {
|
|||||||
AlreadyInProgress,
|
AlreadyInProgress,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
@ -29,13 +28,13 @@ pub enum GetError {
|
|||||||
NotFound,
|
NotFound,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum AllDescrsError {
|
pub enum AllDescrsError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used in the return from all_descrs from Store.
|
/// Used in the return from all_descrs from Store.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::origin;
|
use crate::error::{MapUnexpected, ToUnexpected};
|
||||||
use crate::origin::store;
|
use crate::origin::store;
|
||||||
|
use crate::{error, origin};
|
||||||
|
|
||||||
use std::error::Error;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::{collections, fs, io, sync};
|
use std::{collections, fs, io, sync};
|
||||||
|
|
||||||
@ -28,17 +28,16 @@ impl origin::Origin for sync::Arc<Origin> {
|
|||||||
|
|
||||||
let file_object = repo
|
let file_object = repo
|
||||||
.find_object(self.tree_object_id)
|
.find_object(self.tree_object_id)
|
||||||
.map_err(|e| origin::ReadFileIntoError::Unexpected(Box::from(e)))?
|
.map_unexpected()?
|
||||||
.peel_to_tree()
|
.peel_to_tree()
|
||||||
.map_err(|e| origin::ReadFileIntoError::Unexpected(Box::from(e)))?
|
.map_unexpected()?
|
||||||
.lookup_entry_by_path(clean_path)
|
.lookup_entry_by_path(clean_path)
|
||||||
.map_err(|e| origin::ReadFileIntoError::Unexpected(Box::from(e)))?
|
.map_unexpected()?
|
||||||
.ok_or(origin::ReadFileIntoError::FileNotFound)?
|
.ok_or(origin::ReadFileIntoError::FileNotFound)?
|
||||||
.object()
|
.object()
|
||||||
.map_err(|e| origin::ReadFileIntoError::Unexpected(Box::from(e)))?;
|
.map_unexpected()?;
|
||||||
|
|
||||||
into.write_all(file_object.data.as_ref())
|
into.write_all(file_object.data.as_ref()).map_unexpected()?;
|
||||||
.map_err(|e| origin::ReadFileIntoError::Unexpected(Box::from(e)))?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -50,7 +49,7 @@ enum GetOriginError {
|
|||||||
InvalidBranchName,
|
InvalidBranchName,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(#[from] error::Unexpected),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// git::Store implements the Store trait for any Descr::Git based Origins. If any non-git
|
/// git::Store implements the Store trait for any Descr::Git based Origins. If any non-git
|
||||||
@ -98,17 +97,17 @@ impl Store {
|
|||||||
|
|
||||||
let commit_object_id = repo
|
let commit_object_id = repo
|
||||||
.try_find_reference(&self.branch_ref(branch_name))
|
.try_find_reference(&self.branch_ref(branch_name))
|
||||||
.map_err(|e| GetOriginError::Unexpected(Box::from(e)))?
|
.map_unexpected()?
|
||||||
.ok_or(GetOriginError::InvalidBranchName)?
|
.ok_or(GetOriginError::InvalidBranchName)?
|
||||||
.peel_to_id_in_place()
|
.peel_to_id_in_place()
|
||||||
.map_err(|e| GetOriginError::Unexpected(Box::from(e)))?
|
.map_unexpected()?
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
let tree_object_id = repo
|
let tree_object_id = repo
|
||||||
.find_object(commit_object_id)
|
.find_object(commit_object_id)
|
||||||
.map_err(|e| GetOriginError::Unexpected(Box::from(e)))?
|
.map_unexpected()?
|
||||||
.try_to_commit_ref()
|
.try_to_commit_ref()
|
||||||
.map_err(|e| GetOriginError::Unexpected(Box::from(e)))?
|
.map_unexpected()?
|
||||||
.tree();
|
.tree();
|
||||||
|
|
||||||
Ok(sync::Arc::from(Origin {
|
Ok(sync::Arc::from(Origin {
|
||||||
@ -132,8 +131,7 @@ impl Store {
|
|||||||
// if the path doesn't exist then use the gix clone feature to clone it into the
|
// if the path doesn't exist then use the gix clone feature to clone it into the
|
||||||
// directory.
|
// directory.
|
||||||
if fs::read_dir(repo_path).is_err() {
|
if fs::read_dir(repo_path).is_err() {
|
||||||
fs::create_dir_all(repo_path)
|
fs::create_dir_all(repo_path).map_unexpected()?;
|
||||||
.map_err(|e| store::SyncError::Unexpected(Box::from(e)))?;
|
|
||||||
|
|
||||||
let origin::Descr::Git {
|
let origin::Descr::Git {
|
||||||
ref url,
|
ref url,
|
||||||
@ -148,7 +146,7 @@ impl Store {
|
|||||||
gixCloneErr::UrlParse(_) | gixCloneErr::CanonicalizeUrl { .. } => {
|
gixCloneErr::UrlParse(_) | gixCloneErr::CanonicalizeUrl { .. } => {
|
||||||
store::SyncError::InvalidURL
|
store::SyncError::InvalidURL
|
||||||
}
|
}
|
||||||
_ => store::SyncError::Unexpected(Box::from(e)),
|
_ => e.to_unexpected().into(),
|
||||||
})?
|
})?
|
||||||
.fetch_only(Discard, should_interrupt)
|
.fetch_only(Discard, should_interrupt)
|
||||||
.map_err(|_| store::SyncError::InvalidURL)?;
|
.map_err(|_| store::SyncError::InvalidURL)?;
|
||||||
@ -156,36 +154,35 @@ impl Store {
|
|||||||
// Check to make sure the branch name exists
|
// Check to make sure the branch name exists
|
||||||
// TODO if this fails we should delete repo_path
|
// TODO if this fails we should delete repo_path
|
||||||
repo.try_find_reference(&self.branch_ref(branch_name))
|
repo.try_find_reference(&self.branch_ref(branch_name))
|
||||||
.map_err(|e| store::SyncError::Unexpected(Box::from(e)))?
|
.map_unexpected()?
|
||||||
.ok_or(store::SyncError::InvalidBranchName)?;
|
.ok_or(store::SyncError::InvalidBranchName)?;
|
||||||
|
|
||||||
// Add the descr to the repo directory, so we can know the actual descr later
|
// Add the descr to the repo directory, so we can know the actual descr later
|
||||||
// TODO if this fails we should delete repo_path
|
// TODO if this fails we should delete repo_path
|
||||||
let descr_file = fs::File::create(self.descr_file_path(descr.id().as_ref()))
|
let descr_file =
|
||||||
.map_err(|e| store::SyncError::Unexpected(Box::from(e)))?;
|
fs::File::create(self.descr_file_path(descr.id().as_ref())).map_unexpected()?;
|
||||||
|
|
||||||
serde_json::to_writer(descr_file, &descr)
|
serde_json::to_writer(descr_file, &descr).map_unexpected()?;
|
||||||
.map_err(|e| store::SyncError::Unexpected(Box::from(e)))?;
|
|
||||||
|
|
||||||
return Ok(repo);
|
return Ok(repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
let direction = gix::remote::Direction::Fetch;
|
let direction = gix::remote::Direction::Fetch;
|
||||||
|
|
||||||
let repo = gix::open(repo_path).map_err(|e| store::SyncError::Unexpected(Box::from(e)))?;
|
let repo = gix::open(repo_path).map_unexpected()?;
|
||||||
|
|
||||||
let remote = repo
|
let remote = repo
|
||||||
.find_default_remote(direction)
|
.find_default_remote(direction)
|
||||||
.ok_or_else(|| store::SyncError::Unexpected(Box::from("no default configured")))?
|
.ok_or_else(|| error::Unexpected::from("no default configured"))?
|
||||||
.map_err(|e| store::SyncError::Unexpected(Box::from(e)))?;
|
.map_unexpected()?;
|
||||||
|
|
||||||
remote
|
remote
|
||||||
.connect(direction)
|
.connect(direction)
|
||||||
.map_err(|e| store::SyncError::Unexpected(Box::from(e)))?
|
.map_unexpected()?
|
||||||
.prepare_fetch(Discard, Default::default())
|
.prepare_fetch(Discard, Default::default())
|
||||||
.map_err(|e| store::SyncError::Unexpected(Box::from(e)))?
|
.map_unexpected()?
|
||||||
.receive(Discard, should_interrupt)
|
.receive(Discard, should_interrupt)
|
||||||
.map_err(|e| store::SyncError::Unexpected(Box::from(e)))?;
|
.map_unexpected()?;
|
||||||
|
|
||||||
Ok(repo)
|
Ok(repo)
|
||||||
}
|
}
|
||||||
@ -256,15 +253,15 @@ impl super::Store for sync::Arc<Store> {
|
|||||||
|
|
||||||
fs::read_dir(&repo_path).map_err(|e| match e.kind() {
|
fs::read_dir(&repo_path).map_err(|e| match e.kind() {
|
||||||
io::ErrorKind::NotFound => store::GetError::NotFound,
|
io::ErrorKind::NotFound => store::GetError::NotFound,
|
||||||
_ => store::GetError::Unexpected(Box::from(e)),
|
_ => e.to_unexpected().into(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let repo = gix::open(&repo_path).map_err(|e| store::GetError::Unexpected(Box::from(e)))?;
|
let repo = gix::open(&repo_path).map_unexpected()?;
|
||||||
|
|
||||||
let origin = self.get_origin(repo, descr.clone()).map_err(|e| match e {
|
let origin = self.get_origin(repo, descr.clone()).map_err(|e| match e {
|
||||||
// it's not expected that the branch name is invalid at this point, it must have
|
// it's not expected that the branch name is invalid at this point, it must have
|
||||||
// existed for sync to have been successful.
|
// existed for sync to have been successful.
|
||||||
GetOriginError::InvalidBranchName => store::GetError::Unexpected(Box::from(e)),
|
GetOriginError::InvalidBranchName => e.to_unexpected().into(),
|
||||||
GetOriginError::Unexpected(e) => store::GetError::Unexpected(e),
|
GetOriginError::Unexpected(e) => store::GetError::Unexpected(e),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@ -276,36 +273,30 @@ impl super::Store for sync::Arc<Store> {
|
|||||||
|
|
||||||
fn all_descrs(&self) -> store::AllDescrsResult<Self::AllDescrsIter<'_>> {
|
fn all_descrs(&self) -> store::AllDescrsResult<Self::AllDescrsIter<'_>> {
|
||||||
Ok(Box::from(
|
Ok(Box::from(
|
||||||
fs::read_dir(&self.dir_path)
|
fs::read_dir(&self.dir_path).map_unexpected()?.map(
|
||||||
.map_err(|e| store::AllDescrsError::Unexpected(Box::from(e)))?
|
|dir_entry_res: io::Result<fs::DirEntry>| -> store::AllDescrsResult<origin::Descr> {
|
||||||
.map(
|
let descr_id: String = dir_entry_res
|
||||||
|dir_entry_res: io::Result<fs::DirEntry>| -> store::AllDescrsResult<origin::Descr> {
|
.map_unexpected()?
|
||||||
let descr_id: String = dir_entry_res
|
.file_name()
|
||||||
.map_err(|e| store::AllDescrsError::Unexpected(Box::from(e)))?
|
.to_str()
|
||||||
.file_name()
|
.ok_or_else(|| {
|
||||||
.to_str()
|
error::Unexpected::from("couldn't convert os string to &str")
|
||||||
.ok_or_else(|| {
|
})?
|
||||||
store::AllDescrsError::Unexpected(Box::from(
|
.into();
|
||||||
"couldn't convert os string to &str",
|
|
||||||
))
|
|
||||||
})?
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let descr_file_path = self.descr_file_path(descr_id.as_ref());
|
let descr_file_path = self.descr_file_path(descr_id.as_ref());
|
||||||
|
|
||||||
// TODO it's possible that opening the file will fail if syncing is
|
// TODO it's possible that opening the file will fail if syncing is
|
||||||
// still ongoing, as writing the descr file is the last step after
|
// still ongoing, as writing the descr file is the last step after
|
||||||
// initial sync has succeeded.
|
// initial sync has succeeded.
|
||||||
let descr_file = fs::File::open(descr_file_path)
|
let descr_file = fs::File::open(descr_file_path).map_unexpected()?;
|
||||||
.map_err(|e| store::AllDescrsError::Unexpected(Box::from(e)))?;
|
|
||||||
|
|
||||||
let descr = serde_json::from_reader(descr_file)
|
let descr = serde_json::from_reader(descr_file).map_unexpected()?;
|
||||||
.map_err(|e| store::AllDescrsError::Unexpected(Box::from(e)))?;
|
|
||||||
|
|
||||||
Ok(descr)
|
Ok(descr)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ use std::net;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync;
|
use std::sync;
|
||||||
|
|
||||||
|
use crate::origin::Origin;
|
||||||
use crate::{domain, origin};
|
use crate::{domain, origin};
|
||||||
|
|
||||||
pub mod http_tpl;
|
pub mod http_tpl;
|
||||||
|
Loading…
Reference in New Issue
Block a user