git.rs, render.rs, test_render.rs: updates rendering code and exposes rendering API

This commit is contained in:
2026-04-27 18:26:37 -06:00
parent 5d0b1ab208
commit 4d33e4fe43
3 changed files with 143 additions and 154 deletions

View File

@@ -21,9 +21,8 @@
use std::error::Error;
use gix::{
Repository,
Object,
Tree,
object::tree::EntryKind,
revision::walk::Sorting,
};
use gix_traverse::commit::simple::CommitTimeOrder;
@@ -45,12 +44,13 @@ fn get_entries(tree: Tree) -> Result<Vec<Entry>, Box<dyn Error>> {
let order = Sorting::ByCommitTime(CommitTimeOrder::NewestFirst);
for e in tree.iter() {
let entry = e.unwrap();
let entry = e?;
let mut entry_t = Entry::default();
entry_t.path = entry.filename().to_string();
use gix::object::tree::EntryKind::*;
entry_t.class = match entry.kind() {
EntryKind::Tree | EntryKind::Commit => "directory",
Tree | Commit => "directory",
_ => "file",
}.to_owned();
@@ -60,7 +60,9 @@ fn get_entries(tree: Tree) -> Result<Vec<Entry>, Box<dyn Error>> {
if commit.tree()?.lookup_entry([path_slice])?.is_some() {
entry_t.last_commit = commit.id.to_string();
entry_t.last_commit_message = commit.message_raw()?.to_string();
entry_t.last_commit_message = commit
.message_raw()?
.to_string();
entry_t.last_commit_time = format_iso8601_utc(
commit.time()?.seconds
)?;
@@ -75,20 +77,39 @@ fn get_entries(tree: Tree) -> Result<Vec<Entry>, Box<dyn Error>> {
Ok(entries)
}
pub fn repo_to_context(r: Repository) -> Result<Context, Box<dyn Error>> {
let branches = r.clone().branch_names()
pub trait ToContext {
type Error;
fn to_context(&self) -> Result<Context, Self::Error>;
}
impl ToContext for Object<'_> {
type Error = Box<dyn Error>;
fn to_context(&self) -> Result<Context, Self::Error> {
let mut ctx = Context::new();
let current_branch = self.repo
.head()?
.referent_name()
.unwrap()
.shorten()
.to_string();
use gix::object::Kind;
match self.kind {
Kind::Blob => todo!("need sasha to make a file page"),
Kind::Tag => todo!("idk what this needs to look like"),
Kind::Commit => todo!("need sasha to make a commit page"),
Kind::Tree => {
let tree = self.clone().peel_to_tree()?;
let entries = get_entries(tree)?;
let repo = self.repo;
let dir = repo.common_dir();
let name = dir.file_name().unwrap().to_str().unwrap();
let branches = repo.clone().branch_names()
.iter()
.map(|x| x.to_owned().to_owned())
.collect::<Vec<_>>();
/* @ is HEAD */
let tree = r.rev_parse_single("@")?.object()?.peel_to_tree()?;
/* replace with configurable branch name when we have a database */
let current_branch = r.head()?.referent_name().unwrap().shorten().to_string();
let entries = get_entries(tree)?;
/*
let mut readme_content = String::new();
@@ -109,12 +130,6 @@ pub fn repo_to_context(r: Repository) -> Result<Context, Box<dyn Error>> {
}
*/
let dir = r.common_dir();
let name = dir.file_name().unwrap().to_str().unwrap();
let mut ctx = Context::new();
/* stubs til we have a real database */
ctx.insert("user", "anon");
ctx.insert("site", "TiB.");
@@ -130,6 +145,8 @@ pub fn repo_to_context(r: Repository) -> Result<Context, Box<dyn Error>> {
ctx.insert("branch", &current_branch);
ctx.insert("repo", name);
ctx.insert("entries", &entries);
},
};
Ok(ctx)
}
}

View File

@@ -21,27 +21,27 @@
use std::{
error::Error,
fmt::{ self, Display, Formatter },
path::Path,
io::Write,
};
use tera::{ Context, Tera };
use gix::open;
use tera::Tera;
/* TODO: silt needs to export the HTTP error types */
#[non_exhaustive]
pub enum PageError {
NotFound,
}
use crate::backend::git::ToContext;
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum PageKind {
Code,
Dashboard,
Tickets,
Project,
RawCode,
Repo,
RepoSubDir,
Settings,
Tickets,
User,
Invalid(PageError),
/* TODO: silt exports a generic frontend non-success status trait */
Invalid,
}
impl Display for PageKind {
@@ -51,37 +51,56 @@ impl Display for PageKind {
let path = match self {
Code => "repo/code.html",
Dashboard => "dashboard.html",
Project => "project.html",
Repo => "repo/repo.html",
RepoSubDir => "repo/repo.html",
Settings => "user/settings.html",
Tickets => "repo/tickets.html",
Repo => "repo/code.html",
User => "user.html",
_ => "",
Invalid => todo!("generate error pages based on error type"),
};
write!(f, "./assets/templates/{}", path)
write!(f, "{}", path)
}
}
#[derive(Debug, Clone)]
pub struct Page {
kind: PageKind,
path: String,
branch: Option<String>,
commit: Option<String>,
tag: Option<String>,
pub kind: PageKind,
pub path: String,
pub branch: Option<String>,
pub commit: Option<String>,
pub tag: Option<String>,
pub user: Option<String>,
}
/*
impl Page {
pub fn render(&self) -> Result<String, Box<dyn Error>> {
let template_dir = self.kind.to_string();
let template = String::from_utf8(Path::new(&template_dir)
.to_path_buf()
.as_mut_os_string()
.as_encoded_bytes()
.to_vec()
)?;
pub fn render(
&self, mut dest: Box<dyn Write>
) -> Result<(), Box<dyn Error>> {
/* TODO: replace ./assets/ with the actual templates directory,
* i.e. /usr/local/share/mintee/ */
let tera = Tera::new("./assets/templates/**/*")?;
let tera = Tera::new(&page_dir)?;
Ok(tera.render(&template, &ctx)?)
use PageKind::*;
let ctx = match self.kind {
Code => todo!(),
Dashboard | Project | Settings | Tickets | User | Invalid => {
todo!()
},
Repo => {
open(&self.path)?
/*.rev_parse_single("@")?*/
.head_tree()?
.id()
.object()?
.to_context()?
},
RepoSubDir => todo!(),
};
Ok(dest.write_all(
tera.render(&self.kind.to_string(), &ctx)?.as_bytes()
)?)
}
}
*/

View File

@@ -19,73 +19,26 @@
*/
use std::{
env::{ args, current_dir },
env::current_dir,
error::Error,
io::stdout,
};
use gix::open;
use tera::Tera;
use mintee::backend::git::repo_to_context;
/*
impl From<GitRepo> for Context {
fn from(repo: GitRepo) -> Self {
let mut ctx = Context::new();
let directory = format!("{}/{}", repo.owner, repo.name);
let main_branch = repo.branches
.iter()
.find(|b| b.name == "main")
.unwrap();
let latest_commit = &main_branch.commits[0];
let hash = latest_commit.hash.clone();
let mut entries = Vec::new();
for e in latest_commit.entries.iter() {
let entry = SampleEntry {
class: e.kind.to_string(),
last_commit: hash.clone(),
last_commit_message: latest_commit.message.clone().unwrap(),
last_commit_time: latest_commit.time,
path: e.path.clone(),
};
entries.push(entry);
}
/* stubs til we have a real database */
ctx.insert("user", "anon");
ctx.insert("site", "TiB.");
ctx.insert("notif_count", "");
ctx.insert("ticket_count", "(47)");
ctx.insert("readme_content", "this is a readme");
ctx.insert("owner", &repo.owner);
ctx.insert("branch", &main_branch.name);
ctx.insert("repo", &repo.name);
ctx.insert("directory", &directory);
ctx.insert("entries", &entries);
ctx
}
}
*/
use mintee::backend::render::{ Page, PageKind };
fn main() -> Result<(), Box<dyn Error>> {
if let Some(templates) = args().collect::<Vec<_>>().get(1) {
let tera = Tera::new(templates.as_str())?;
let ctx = repo_to_context(open(current_dir()?)?)?;
let path = String::from_utf8(
current_dir()?.into_os_string().into_encoded_bytes()
)?;
println!("{}", tera.render("repo.html", &ctx)?);
let page = Page {
kind: PageKind::Repo,
path,
branch: None,
commit: None,
tag: None,
user: None,
};
Ok(())
} else {
eprintln!("Usage: {} template_glob", args().collect::<Vec<_>>()[0]);
std::process::exit(64);
}
page.render(Box::new(stdout()))
}