Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
xfbs committed Oct 20, 2024
1 parent e57d8b9 commit 490d527
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 22 deletions.
50 changes: 35 additions & 15 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,17 +183,38 @@ pub struct RepositoryInfo {
impl RepositoryInfo {
pub fn url(&self) -> Option<Url> {
if self.repository.as_str().starts_with("https://github.com/") {
let mut url = Url::parse("https://codeload.github.com/").unwrap();
url.path_segments_mut()
.unwrap()
.extend(self.repository.path_segments().unwrap())
.extend(&["tar.gz", &self.vcs_info.git.sha1]);
return Some(url);
}

if self.repository.as_str().starts_with("https://gitlab.com/") {
let mut repository = self.repository.clone();
repository
.path_segments_mut()
.unwrap()
.extend(&["archive", &format!("{}.tar.gz", self.vcs_info.git.sha1)]);
.extend(&["-", "archive", &format!("{}.tar.gz", self.vcs_info.git.sha1)]);
return Some(repository);
}

None
}

fn prefix(&self) -> String {
let repo = self.repository.path().split('/').last().unwrap_or("");
let mut prefix = format!("{repo}-{}/", self.vcs_info.git.sha1);

if !self.vcs_info.path_in_vcs.is_empty() {
prefix.push_str(&self.vcs_info.path_in_vcs);
prefix.push('/');
}

prefix
}

pub async fn fetch(&self) -> Result<CrateSource> {
let version = VersionInfo {
checksum: vec![],
Expand All @@ -208,9 +229,12 @@ impl RepositoryInfo {
return Err(anyhow!("Error response: {}", response.status()));
}

let bytes: Bytes = response.binary().await?.into();
let source = CrateSource::new(version, &bytes[..])?;
Ok(source)
let bytes = response.binary().await?;
let prefix = self.prefix();
Ok(CrateSource {
version,
files: CrateSource::parse_archive(&prefix, &bytes[..], false)?,
})
}
}

Expand Down Expand Up @@ -273,21 +297,16 @@ impl CrateSource {
let prefix = format!("{}-{}/", version.krate, version.version);
let mut source = CrateSource {
version,
files: Self::parse_compressed(&prefix, data)?,
files: Self::parse_archive(&prefix, data, true)?,
};

Ok(source)
}

/// Parse gzipped tarball returned by crates.io.
fn parse_compressed(prefix: &str, data: &[u8]) -> Result<FileContents, CrateSourceError> {
let mut decoder = GzDecoder::new(data);
Self::parse_archive(prefix, &mut decoder)
}

/// Parse archive.
fn parse_archive(prefix: &str, data: &mut dyn Read) -> Result<FileContents, CrateSourceError> {
let mut archive = Archive::new(data);
/// Parse gzipped archive.
fn parse_archive(prefix: &str, data: &[u8], error_outside_prefix: bool) -> Result<FileContents, CrateSourceError> {
let mut data = GzDecoder::new(data);
let mut archive = Archive::new(&mut data);
let mut files = FileContents::default();

// this is the path prefix we expect in the archive.
Expand All @@ -299,12 +318,13 @@ impl CrateSource {
let path = std::str::from_utf8(&bytes)?;
let path = match path.strip_prefix(&prefix) {
Some(path) => path,
None => {
None if error_outside_prefix => {
return Err(CrateSourceError::InvalidPrefix {
path: path.to_string(),
prefix: prefix.into(),
})
}
None => continue,
};
let path: Utf8PathBuf = path.into();

Expand Down
32 changes: 25 additions & 7 deletions src/views/repo.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
cache::*,
components::*,
data::{CrateResponse, CrateSource, VersionInfo, RepositoryInfo},
data::{CrateResponse, CrateSource, VersionInfo, RepositoryInfo, VersionDiff},
version::VersionId,
};
use camino::Utf8PathBuf;
Expand Down Expand Up @@ -167,11 +167,18 @@ fn RepoSourceFetcher(props: &RepoSourceFetcherProps) -> Html {

let url = info.url();

let fallback = html! {
{"Loading repository archive"}
};
html! {
<>
{"Loaded crate source"}
{format!("{url:?}")}
</>
<Suspense {fallback}>
<RepoSourceFetcherInner
info={props.info.clone()}
repository={info}
source={props.source.clone()}
path={props.path.clone()}
/>
</Suspense>
}
}

Expand All @@ -186,8 +193,19 @@ pub struct RepoSourceFetcherInnerProps {
#[function_component]
fn RepoSourceFetcherInner(props: &RepoSourceFetcherInnerProps) -> HtmlResult {
let source = use_future_with(props.repository.clone(), |repository| async move {
()
repository.fetch().await.map(Arc::new)
})?;

Ok(html! {})
let source = match &*source {
Ok(source) => source.clone(),
Err(error) => return Ok(html! {
{format!("Error repo: {error}")}
}),
};

let diff = VersionDiff::new(props.source.clone(), source.clone());

Ok(html! {
{"abc"}
})
}

0 comments on commit 490d527

Please sign in to comment.