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