Get gix_proxy working completely
This commit is contained in:
parent
1667bac39c
commit
1e8f970486
@ -1,4 +1,4 @@
|
||||
use crate::error::unexpected::{self, Mappable};
|
||||
use crate::error::unexpected::{self, Intoable, Mappable};
|
||||
use crate::{origin, util};
|
||||
use std::{collections, sync};
|
||||
|
||||
@ -7,6 +7,15 @@ struct DescrState {
|
||||
current_tree: gix_hash::ObjectId,
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Clone, Debug, PartialEq)]
|
||||
enum GetObjectError {
|
||||
#[error("unavailable due to server-side issue")]
|
||||
Unavailable,
|
||||
|
||||
#[error(transparent)]
|
||||
Unexpected(#[from] unexpected::Error),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Proxy {
|
||||
client: reqwest::Client,
|
||||
@ -101,7 +110,8 @@ impl Proxy {
|
||||
&self,
|
||||
descr: &origin::Descr,
|
||||
oid: &gix_hash::ObjectId,
|
||||
) -> unexpected::Result<Option<util::BoxByteStream>> {
|
||||
expect_kind: gix_object::Kind,
|
||||
) -> Result<util::BoxByteStream, GetObjectError> {
|
||||
let hex = oid.to_string();
|
||||
let (url, _) = Self::deconstruct_descr(descr);
|
||||
|
||||
@ -109,26 +119,40 @@ impl Proxy {
|
||||
Self::construct_url(url, format!("objects/{}/{}", &hex[..2], &hex[2..]).as_str())
|
||||
.or_unexpected_while("constructing refs url")?;
|
||||
|
||||
Ok(self
|
||||
let mut loose_object = self
|
||||
.client
|
||||
.get(object_url)
|
||||
.send()
|
||||
.await
|
||||
.or_unexpected_while("performing request")?
|
||||
.or(Err(GetObjectError::Unavailable))?
|
||||
.error_for_status()
|
||||
.ok()
|
||||
.map(|res| {
|
||||
use async_compression::tokio::bufread::ZlibDecoder;
|
||||
use futures::stream::TryStreamExt;
|
||||
use std::io;
|
||||
|
||||
let r = tokio_util::io::StreamReader::new(
|
||||
tokio::io::BufReader::new(ZlibDecoder::new(tokio_util::io::StreamReader::new(
|
||||
res.bytes_stream()
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e)),
|
||||
);
|
||||
)))
|
||||
})
|
||||
.or(Err(GetObjectError::Unavailable))?;
|
||||
|
||||
util::BoxByteStream::from_async_read(ZlibDecoder::new(r))
|
||||
}))
|
||||
use tokio::io::AsyncBufReadExt;
|
||||
let mut header = Vec::<u8>::new();
|
||||
loose_object
|
||||
.read_until(0, &mut header)
|
||||
.await
|
||||
.or(Err(GetObjectError::Unavailable))?;
|
||||
|
||||
let (kind, _, _) =
|
||||
gix_object::decode::loose_header(&header).or(Err(GetObjectError::Unavailable))?;
|
||||
|
||||
if kind != expect_kind {
|
||||
return Err(GetObjectError::Unavailable);
|
||||
}
|
||||
|
||||
Ok(util::BoxByteStream::from_async_read(loose_object))
|
||||
}
|
||||
|
||||
async fn get_commit_tree(
|
||||
@ -137,17 +161,18 @@ impl Proxy {
|
||||
commit_hash: &gix_hash::ObjectId,
|
||||
) -> Result<gix_hash::ObjectId, origin::SyncError> {
|
||||
let commit_object_bytes = self
|
||||
.get_object(descr, commit_hash)
|
||||
.await?
|
||||
.ok_or(origin::SyncError::Unavailable)?
|
||||
.get_object(descr, commit_hash, gix_object::Kind::Commit)
|
||||
.await
|
||||
.map_err(|e| match e {
|
||||
GetObjectError::Unavailable => origin::SyncError::Unavailable,
|
||||
GetObjectError::Unexpected(_) => e.into_unexpected().into(),
|
||||
})?
|
||||
.read_to_end()
|
||||
.await
|
||||
.or(Err(origin::SyncError::Unavailable))?;
|
||||
|
||||
let commit_object = gix_object::ObjectRef::from_loose(commit_object_bytes.as_ref())
|
||||
.or(Err(origin::SyncError::Unavailable))?
|
||||
.into_commit()
|
||||
.ok_or(origin::SyncError::Unavailable)?;
|
||||
let commit_object = gix_object::CommitRef::from_bytes(commit_object_bytes.as_ref())
|
||||
.or(Err(origin::SyncError::Unavailable))?;
|
||||
|
||||
Ok(commit_object.tree())
|
||||
}
|
||||
@ -159,17 +184,18 @@ impl Proxy {
|
||||
entry_name: &str,
|
||||
) -> Result<gix_object::tree::Entry, origin::GetFileError> {
|
||||
let tree_object_bytes = self
|
||||
.get_object(descr, tree_hash)
|
||||
.await?
|
||||
.ok_or(origin::GetFileError::Unavailable)?
|
||||
.get_object(descr, tree_hash, gix_object::Kind::Tree)
|
||||
.await
|
||||
.map_err(|e| match e {
|
||||
GetObjectError::Unavailable => origin::GetFileError::Unavailable,
|
||||
GetObjectError::Unexpected(_) => e.into_unexpected().into(),
|
||||
})?
|
||||
.read_to_end()
|
||||
.await
|
||||
.or(Err(origin::GetFileError::Unavailable))?;
|
||||
|
||||
let tree_object = gix_object::ObjectRef::from_loose(tree_object_bytes.as_ref())
|
||||
.or(Err(origin::GetFileError::Unavailable))?
|
||||
.into_tree()
|
||||
.ok_or(origin::GetFileError::Unavailable)?;
|
||||
let tree_object = gix_object::TreeRef::from_bytes(tree_object_bytes.as_ref())
|
||||
.or(Err(origin::GetFileError::Unavailable))?;
|
||||
|
||||
for entry in tree_object.entries {
|
||||
if entry.filename == entry_name {
|
||||
@ -236,9 +262,7 @@ impl origin::Store for Proxy {
|
||||
let path = path
|
||||
.as_str()
|
||||
.parse::<std::path::PathBuf>()
|
||||
.or_unexpected_while("parsing path")?
|
||||
.canonicalize()
|
||||
.or_unexpected_while("canonicalizing path")?;
|
||||
.or_unexpected_while("parsing path")?;
|
||||
|
||||
let path_parts = path.iter().collect::<Vec<&std::ffi::OsStr>>();
|
||||
|
||||
@ -297,12 +321,14 @@ impl origin::Store for Proxy {
|
||||
.into());
|
||||
}
|
||||
|
||||
Ok(self
|
||||
.get_object(&descr, &entry.oid)
|
||||
.await?
|
||||
.map_unexpected_while(|| format!("object for entry {:?} not found", entry))?)
|
||||
|
||||
// TODO this is still not correct, as it will include the git object header
|
||||
self.get_object(&descr, &entry.oid, gix_object::Kind::Blob)
|
||||
.await
|
||||
.map_err(|e| match e {
|
||||
GetObjectError::Unavailable => origin::GetFileError::Unavailable,
|
||||
GetObjectError::Unexpected(_) => e
|
||||
.into_unexpected_while(format!("getting object for entry {:?}", entry))
|
||||
.into(),
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user