Serve files
This commit is contained in:
parent
145e3c592e
commit
ca52201880
4 changed files with 125 additions and 41 deletions
119
src/server.rs
119
src/server.rs
|
|
@ -1,9 +1,18 @@
|
|||
use crate::{cache, config::Config, repo::ReadRepoMetadataError, templates};
|
||||
use crate::{
|
||||
cache,
|
||||
config::Config,
|
||||
repo::{ReadRepoMetadataError, RepoMetadataEntry},
|
||||
templates,
|
||||
};
|
||||
|
||||
use askama::Template;
|
||||
use async_lock::Mutex;
|
||||
use log::error;
|
||||
use std::{collections::{BTreeMap, BTreeSet, HashMap}, io::ErrorKind, path::PathBuf};
|
||||
use std::{
|
||||
collections::{BTreeMap, BTreeSet, HashMap},
|
||||
io::{ErrorKind, Read},
|
||||
path::PathBuf,
|
||||
};
|
||||
use trillium::{Conn, Handler};
|
||||
use trillium_router::{Router, RouterConnExt};
|
||||
|
||||
|
|
@ -18,7 +27,11 @@ pub fn make_router(config: &'static Config) -> impl Handler {
|
|||
|
||||
let metadata_cache: &'static _ = Box::leak(Box::new(Mutex::new(cache::Cache::<
|
||||
String,
|
||||
HashMap<String, String>,
|
||||
templates::Directory,
|
||||
>::default())));
|
||||
let file_cache: &'static _ = Box::leak(Box::new(Mutex::new(cache::Cache::<
|
||||
(String, String),
|
||||
String,
|
||||
>::default())));
|
||||
let client: &'static _ = Box::leak(Box::new(async_lock::Mutex::new(
|
||||
crate::api_client::make_client(),
|
||||
|
|
@ -51,17 +64,24 @@ pub fn make_router(config: &'static Config) -> impl Handler {
|
|||
};
|
||||
|
||||
let mut client = client.lock().await;
|
||||
let (repo_index, mut repo_metadata) = crate::api_client::fetch_repo_tree_index_at_commit(
|
||||
let (repo_index, mut repo_metadata) =
|
||||
crate::api_client::fetch_repo_tree_index_at_commit(
|
||||
&mut client,
|
||||
&repo_url,
|
||||
&commit_hash,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.expect("todo handle error");
|
||||
crate::api_client::fetch_repo_files(
|
||||
config,
|
||||
&mut client,
|
||||
&repo_url,
|
||||
&commit_hash,
|
||||
&repo_index,
|
||||
&mut repo_metadata,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.expect("todo handle error");
|
||||
crate::api_client::fetch_repo_files(config, &mut client, &repo_index, &mut repo_metadata, None)
|
||||
.await
|
||||
.expect("todo handle error");
|
||||
}
|
||||
//let planet = conn.param("planet").unwrap();
|
||||
conn.ok(crate::templates::Home {}.render().unwrap())
|
||||
|
|
@ -72,16 +92,17 @@ pub fn make_router(config: &'static Config) -> impl Handler {
|
|||
return conn.with_status(401);
|
||||
};
|
||||
|
||||
let cache_fetch = |key| {
|
||||
let mut repo_hash = [0; 32];
|
||||
if base64_turbo::URL_SAFE.decode_into(key, &mut repo_hash)
|
||||
!= Ok(32)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let fetch_metadata = |key| {
|
||||
//let mut repo_hash = [0; 24];
|
||||
//if dbg!(base64_turbo::URL_SAFE.decode_into(key, &mut repo_hash))
|
||||
// != Ok(16)
|
||||
//{
|
||||
// return None;
|
||||
//}
|
||||
//let repo_hash = &repo_hash[0..16];
|
||||
let repo_dir = PathBuf::from(&config.data_dir)
|
||||
.join(crate::SUBDIR_REPOS)
|
||||
.join(repo_hash_str);
|
||||
.join(key);
|
||||
let repo_metadata =
|
||||
match crate::repo::RepoMetadata::read_from_file(config, &repo_dir) {
|
||||
Ok(v) => v,
|
||||
|
|
@ -95,7 +116,7 @@ pub fn make_router(config: &'static Config) -> impl Handler {
|
|||
return None;
|
||||
}
|
||||
};
|
||||
let mut entries = templates::Directory::default();
|
||||
let mut root = templates::Directory::default();
|
||||
for entry in repo_metadata.iter_files() {
|
||||
match entry {
|
||||
Ok(entry) => {
|
||||
|
|
@ -104,33 +125,71 @@ pub fn make_router(config: &'static Config) -> impl Handler {
|
|||
continue;
|
||||
};
|
||||
let path = entry.file_path.split('/').peekable();
|
||||
let template_entry = match entry {
|
||||
|
||||
}
|
||||
entries.insert(, path);
|
||||
|
||||
root.insert(
|
||||
templates::Entry::File(templates::File {
|
||||
name: name.into(),
|
||||
path: dbg!(entry.file_path).into(),
|
||||
hash: entry.hash.into(),
|
||||
}),
|
||||
path,
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Reading repo metadata file index: {e:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(files)
|
||||
Some(root)
|
||||
};
|
||||
// TODO replace mutex with better thing (less contention or async mutex)
|
||||
let Some(metadata) = metadata_cache
|
||||
let Some(root) = metadata_cache
|
||||
.lock()
|
||||
.await
|
||||
.fetch(repo_hash_str.to_string(), cache_fetch) else {
|
||||
return conn.with_status(404);
|
||||
.fetch(repo_hash_str.to_string(), fetch_metadata)
|
||||
else {
|
||||
return conn.with_status(404);
|
||||
};
|
||||
|
||||
let Some(file_hash) = root.find(conn.path().split('/')) else {
|
||||
return conn.with_status(404);
|
||||
};
|
||||
|
||||
let fetch_file = |(repo_hash, file_hash)| {
|
||||
let file_path = PathBuf::from(&config.data_dir)
|
||||
.join(crate::SUBDIR_REPOS)
|
||||
.join(repo_hash)
|
||||
.join(file_hash);
|
||||
|
||||
let mut file = match std::fs::OpenOptions::new().read(true).open(&file_path)
|
||||
{
|
||||
Ok(file) => file,
|
||||
Err(e) => {
|
||||
error!("Cannot open file `{file_path:?}`: {e:?}");
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
if let Err(e) = file.read_to_string(&mut buf) {
|
||||
error!("Error reading file `{file_path:?}`: {e:?}");
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(buf)
|
||||
};
|
||||
let Some(file_content) = file_cache.lock().await.fetch(
|
||||
(repo_hash_str.to_string(), file_hash.to_string()),
|
||||
fetch_file,
|
||||
) else {
|
||||
return conn.with_status(500);
|
||||
};
|
||||
|
||||
let hl_options = giallo::HighlightOptions::new(
|
||||
"py",
|
||||
giallo::ThemeVariant::Single("catppuccin-frappe"),
|
||||
);
|
||||
let highlighted = hl_registry
|
||||
.highlight("def foo():\n\tpass", &hl_options)
|
||||
.unwrap();
|
||||
let highlighted = hl_registry.highlight(&file_content, &hl_options).unwrap();
|
||||
let html = giallo::HtmlRenderer::default().render(
|
||||
&highlighted,
|
||||
&giallo::RenderOptions {
|
||||
|
|
@ -140,7 +199,7 @@ pub fn make_router(config: &'static Config) -> impl Handler {
|
|||
);
|
||||
conn.ok(crate::templates::Repo {
|
||||
content: html.clone(),
|
||||
entries: Vec::new(),
|
||||
root,
|
||||
}
|
||||
.render()
|
||||
.unwrap())
|
||||
|
|
|
|||
Loading…
Reference in a new issue