|
|
@ -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", |
|
|
|
|
|
|
|
)) |
|
|
|
let descr_file_path = self.descr_file_path(descr_id.as_ref()); |
|
|
|
})? |
|
|
|
|
|
|
|
.into(); |
|
|
|
// 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
|
|
|
|
let descr_file_path = self.descr_file_path(descr_id.as_ref()); |
|
|
|
// initial sync has succeeded.
|
|
|
|
|
|
|
|
let descr_file = fs::File::open(descr_file_path).map_unexpected()?; |
|
|
|
// 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
|
|
|
|
let descr = serde_json::from_reader(descr_file).map_unexpected()?; |
|
|
|
// initial sync has succeeded.
|
|
|
|
|
|
|
|
let descr_file = fs::File::open(descr_file_path) |
|
|
|
Ok(descr) |
|
|
|
.map_err(|e| store::AllDescrsError::Unexpected(Box::from(e)))?; |
|
|
|
}, |
|
|
|
|
|
|
|
), |
|
|
|
let descr = serde_json::from_reader(descr_file) |
|
|
|
)) |
|
|
|
.map_err(|e| store::AllDescrsError::Unexpected(Box::from(e)))?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(descr) |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
)) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|