more settings, headers+footers+error pages

This commit is contained in:
Trevor Bentley
2023-01-10 03:19:31 +01:00
parent 1951074e8f
commit 4e436a268d
13 changed files with 370 additions and 227 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ license = "GPL-3.0-or-later"
[dependencies] [dependencies]
chrono = "0.4.23" chrono = { version = "0.4.23", features=["clock"] }
clap = { version="4.0.32", features=["derive"] } clap = { version="4.0.32", features=["derive"] }
git2 = "0.15.0" git2 = "0.15.0"
serde = { version = "1.0.152", features = ["derive"] } serde = { version = "1.0.152", features = ["derive"] }
+26 -8
View File
@@ -1,12 +1,30 @@
template_dir = "templates/" site_name = "Trevor's Repos"
site_url = "https://git.trevorbentley.com"
site_description = "A bunch of git repos in a stupid format."
output_dir = "gen/" output_dir = "gen/"
[a_repo] recursive_repo_dirs = ["repos/"]
path = "repos/connectr"
name = "connectr"
[another_repo] [gitsy_templates]
path = "repos/fruitbasket" path = "templates/"
repo_list = "repos.html"
repo_summary = "summary.html"
commit = "commit.html"
branch = "branch.html"
tag = "tag.html"
file = "file.html"
dir = "dir.html"
header = "header.html"
footer = "footer.html"
error = "404.html"
[extra] [gitsy_extra]
thingo = 1 global_user_defined_vars = "whatever"
these_can_also_be_numbers = 5
or_bools = true
[circadian]
path = "more_repos/circadian"
website = "https://circadian.trevorbentley.com"
attributes = {some_extra_thing = "user defined", visible = false, number_of_bananas = 3}
+191 -50
View File
@@ -6,7 +6,8 @@ use chrono::{
use clap::Parser; use clap::Parser;
use git2::{DiffOptions, Repository, Error}; use git2::{DiffOptions, Repository, Error};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap, HashSet};
use std::fs::File;
use std::io::Write; use std::io::Write;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use tera::{Context, Filter, Function, Tera, Value, to_value, try_get_value}; use tera::{Context, Filter, Function, Tera, Value, to_value, try_get_value};
@@ -36,7 +37,7 @@ fn first_line(msg: &[u8]) -> String {
#[derive(Serialize)] #[derive(Serialize)]
struct GitRepo { struct GitRepo {
name: String, name: String,
metadata: ItsyMetadata, metadata: GitsyMetadata,
history: Vec<GitObject>, history: Vec<GitObject>,
branches: Vec<GitObject>, branches: Vec<GitObject>,
tags: Vec<GitObject>, tags: Vec<GitObject>,
@@ -46,12 +47,12 @@ struct GitRepo {
} }
#[derive(Serialize, Default)] #[derive(Serialize, Default)]
struct ItsyMetadata { struct GitsyMetadata {
full_name: Option<String>, full_name: Option<String>,
description: Option<String>, description: Option<String>,
website: Option<String>, website: Option<String>,
clone: Option<String>, clone: Option<String>,
attributes: BTreeMap<String, String>, attributes: BTreeMap<String, toml::Value>,
} }
#[derive(Serialize, Default)] #[derive(Serialize, Default)]
@@ -172,7 +173,7 @@ fn walk_file_tree(repo: &git2::Repository, rev: &str, files: &mut Vec<GitFile>,
Ok(()) Ok(())
} }
fn parse_repo(repo: &Repository, name: &str) -> Result<GitRepo, Error> { fn parse_repo(repo: &Repository, name: &str, metadata: GitsyMetadata) -> Result<GitRepo, Error> {
let mut history: Vec<GitObject> = vec!(); let mut history: Vec<GitObject> = vec!();
let mut branches: Vec<GitObject> = vec!(); let mut branches: Vec<GitObject> = vec!();
let mut tags: Vec<GitObject> = vec!(); let mut tags: Vec<GitObject> = vec!();
@@ -313,14 +314,14 @@ fn parse_repo(repo: &Repository, name: &str) -> Result<GitRepo, Error> {
let mut root_files: Vec<GitFile> = vec!(); let mut root_files: Vec<GitFile> = vec!();
let mut all_files: Vec<GitFile> = vec!(); let mut all_files: Vec<GitFile> = vec!();
walk_file_tree(&repo, "origin/HEAD", &mut root_files, 0, false, "")?; walk_file_tree(&repo, "HEAD", &mut root_files, 0, false, "")?;
// TODO: maybe this should be optional? Walking the whole tree // TODO: maybe this should be optional? Walking the whole tree
// could be slow on huge repos. // could be slow on huge repos.
walk_file_tree(&repo, "origin/HEAD", &mut all_files, 0, true, "")?; walk_file_tree(&repo, "HEAD", &mut all_files, 0, true, "")?;
Ok(GitRepo { Ok(GitRepo {
name: name.to_string(), name: name.to_string(),
metadata: Default::default(), metadata,
history, history,
branches, branches,
tags, tags,
@@ -561,19 +562,63 @@ struct CliArgs {
#[derive(Deserialize)] #[derive(Deserialize)]
#[allow(dead_code)] #[allow(dead_code)]
struct ItsySettings { struct GitsySettings {
template_dir: PathBuf,
output_dir: PathBuf, output_dir: PathBuf,
recursive_repo_dirs: Option<Vec<PathBuf>>, recursive_repo_dirs: Option<Vec<PathBuf>>,
extra: HashMap<String, toml::Value>, site_name: Option<String>,
site_url: Option<String>,
site_description: Option<String>,
#[serde(rename(deserialize = "gitsy_templates"))]
templates: GitsySettingsTemplates,
#[serde(rename(deserialize = "gitsy_extra"))]
extra: Option<BTreeMap<String, toml::Value>>,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
#[allow(dead_code)] struct GitsySettingsTemplates {
struct ItsySettingsRepo { path: PathBuf,
header: Option<String>,
footer: Option<String>,
repo_list: Option<String>,
repo_summary: Option<String>,
commit: Option<String>,
branch: Option<String>,
tag: Option<String>,
file: Option<String>,
dir: Option<String>,
error: Option<String>,
}
#[derive(Deserialize, Default)]
struct GitsySettingsRepo {
path: PathBuf, path: PathBuf,
name: Option<String>, name: Option<String>,
description: Option<String>, description: Option<String>,
website: Option<String>, website: Option<String>,
attributes: BTreeMap<String, toml::Value>,
}
use std::hash::{Hash, Hasher};
impl Hash for GitsySettingsRepo {
fn hash<H: Hasher>(&self, state: &mut H) {
self.path.hash(state);
}
}
impl PartialEq for GitsySettingsRepo {
fn eq(&self, other: &Self) -> bool {
self.path == other.path
}
}
impl Eq for GitsySettingsRepo {}
fn write_rendered(file: &mut File, rendered: &str, header: Option<&str>, footer: Option<&str>) {
if let Some(header) = header {
file.write(header.as_bytes()).expect("failed to save rendered html");
}
file.write(rendered.as_bytes()).expect("failed to save rendered html");
if let Some(footer) = footer {
file.write(footer.as_bytes()).expect("failed to save rendered html");
}
} }
fn main() { fn main() {
@@ -582,11 +627,11 @@ fn main() {
// Parse the known settings directly into their struct // Parse the known settings directly into their struct
let toml = std::fs::read_to_string(config_path).expect(&format!("Configuration file not found: {}", config_path.display())); let toml = std::fs::read_to_string(config_path).expect(&format!("Configuration file not found: {}", config_path.display()));
let settings: ItsySettings = toml::from_str(&toml).expect("Configuration file is invalid."); let settings: GitsySettings = toml::from_str(&toml).expect("Configuration file is invalid.");
// Get a list of all remaining TOML "tables" in the file. // Get a list of all remaining TOML "tables" in the file.
// These are the user-supplied individual repositories. // These are the user-supplied individual repositories.
let reserved_keys = vec!("repos","extra"); let reserved_keys = vec!("gitsy_templates","gitsy_extra");
let settings_raw: HashMap<String, toml::Value> = toml::from_str(&toml).expect("blah"); let settings_raw: HashMap<String, toml::Value> = toml::from_str(&toml).expect("blah");
let table_keys: Vec<String> = settings_raw.iter().filter_map(|x| match x.1.is_table() { let table_keys: Vec<String> = settings_raw.iter().filter_map(|x| match x.1.is_table() {
true => match reserved_keys.contains(&x.0.as_str()) { true => match reserved_keys.contains(&x.0.as_str()) {
@@ -599,25 +644,38 @@ fn main() {
// Try to convert each unknown "table" into a repo struct, and // Try to convert each unknown "table" into a repo struct, and
// save the ones that are successful. If no repo name is // save the ones that are successful. If no repo name is
// specified, use the TOML table name. // specified, use the TOML table name.
let mut repos: Vec<ItsySettingsRepo> = vec!(); let mut repo_descriptions: std::collections::HashSet<GitsySettingsRepo> = HashSet::new();
for k in &table_keys { for k in &table_keys {
let v = settings_raw.get(k).unwrap(); let v = settings_raw.get(k).unwrap();
match toml::from_str::<ItsySettingsRepo>(&v.to_string()) { match toml::from_str::<GitsySettingsRepo>(&v.to_string()) {
Ok(mut repo) => { Ok(mut repo) => {
if repo.name.is_none() { if repo.name.is_none() {
repo.name = Some(k.clone()); repo.name = Some(k.clone());
} }
repos.push(repo); repo_descriptions.insert(repo);
},
Err(e) => {
println!("Failed to parse repo [{}]: {:?}", k, e);
},
}
}
match settings.recursive_repo_dirs {
Some(dirs) => {
for parent in &dirs {
for dir in std::fs::read_dir(parent).expect("Repo directory not found.") {
let dir = dir.expect("Repo contains invalid entries");
repo_descriptions.insert(GitsySettingsRepo {
path: dir.path().clone(),
..Default::default()
});
}
}
}, },
_ => {}, _ => {},
} }
}
for repo in &repos { let mut template_path = settings.templates.path.clone();
println!("Parse repo: {}", repo.name.as_ref().unwrap());
}
let mut template_path = settings.template_dir.clone();
template_path.push("**"); template_path.push("**");
template_path.push("*.html"); template_path.push("*.html");
let mut tera = match Tera::new(template_path.to_str().expect("No template path set!")) { let mut tera = match Tera::new(template_path.to_str().expect("No template path set!")) {
@@ -635,34 +693,69 @@ fn main() {
// Create output directory // Create output directory
let _ = std::fs::create_dir(settings.output_dir.to_str().expect("Output path not set!")); let _ = std::fs::create_dir(settings.output_dir.to_str().expect("Output path not set!"));
let generated_dt = chrono::offset::Local::now();
let mut repos: Vec<GitRepo> = vec!(); let mut repos: Vec<GitRepo> = vec!();
for dir in std::fs::read_dir(std::path::Path::new("repos")).expect("Repo directory not found.") { for repo_desc in &repo_descriptions {
let dir = dir.expect("Repo contains invalid entries"); let dir = &repo_desc.path;
match dir.metadata() { match dir.metadata() {
Ok(m) if m.is_dir() => {}, Ok(m) if m.is_dir() => {},
_ => continue, _ => continue,
} }
let path: String = dir.path().to_string_lossy().to_string(); let path: String = dir.to_string_lossy().to_string();
let name: String = dir.file_name().to_string_lossy().to_string(); let name: String = dir.file_name().expect("Encountered directory with no name!").to_string_lossy().to_string();
let repo = Repository::open(path).expect("Unable to find git repository."); let repo = Repository::open(path).expect("Unable to find git repository.");
let summary = parse_repo(&repo, &name).expect("Failed to analyze repo HEAD."); let metadata = GitsyMetadata {
full_name: repo_desc.name.clone(),
description: repo_desc.description.clone(),
website: repo_desc.website.clone(),
clone: None,
attributes: repo_desc.attributes.clone(),
};
let summary = parse_repo(&repo, &name, metadata).expect("Failed to analyze repo HEAD.");
let mut local_ctx = Context::from_serialize(&summary).unwrap(); let mut local_ctx = Context::from_serialize(&summary).unwrap();
match tera.render("summary.html", &local_ctx) { if let Some(extra) = &settings.extra {
local_ctx.try_insert("extra", extra).expect("Failed to add extra settings to template engine.");
}
if let Some(site_name) = &settings.site_name {
local_ctx.insert("site_name", site_name);
}
if let Some(site_url) = &settings.site_url {
local_ctx.insert("site_url", site_url);
}
if let Some(site_description) = &settings.site_description {
local_ctx.insert("site_description", site_description);
}
local_ctx.insert("site_generated_ts", &generated_dt.timestamp());
local_ctx.insert("site_generated_offset", &generated_dt.offset().local_minus_utc());
let header: Option<String> = match &settings.templates.header {
Some(header) => Some(tera.render(header, &local_ctx).expect("Unable to templatize header file")),
_ => None,
};
let footer: Option<String> = match &settings.templates.footer {
Some(footer) => Some(tera.render(footer, &local_ctx).expect("Unable to templatize footer file")),
_ => None,
};
match tera.render(&settings.templates.repo_summary.as_deref().unwrap_or("summary.html"), &local_ctx) {
Ok(rendered) => { Ok(rendered) => {
let mut output_path = settings.output_dir.clone(); let mut output_path = settings.output_dir.clone();
output_path.push(&name); output_path.push(&name);
let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!"));
output_path.push("summary.html"); output_path.push("summary.html");
let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap();
file.write(rendered.as_bytes()).expect("failed to save rendered html"); write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref());
},
Err(x) => match x.kind {
tera::ErrorKind::TemplateNotFound(_) if settings.templates.repo_summary.is_none() => {},
_ => println!("ERROR: {:?}", x),
}, },
Err(x) => println!("ERROR: {:?}", x),
} }
for branch in &summary.branches { for branch in &summary.branches {
local_ctx.insert("branch", branch); local_ctx.insert("branch", branch);
match tera.render("branch.html", &local_ctx) { match tera.render(&settings.templates.branch.as_deref().unwrap_or("branch.html"), &local_ctx) {
Ok(rendered) => { Ok(rendered) => {
let mut output_path = settings.output_dir.clone(); let mut output_path = settings.output_dir.clone();
output_path.push(&summary.name); output_path.push(&summary.name);
@@ -670,10 +763,10 @@ fn main() {
let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!"));
output_path.push(format!("{}.html", branch.full_hash)); output_path.push(format!("{}.html", branch.full_hash));
let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap();
file.write(rendered.as_bytes()).expect("failed to save rendered html"); write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref());
}, },
Err(x) => match x.kind { Err(x) => match x.kind {
tera::ErrorKind::TemplateNotFound(_) => {}, tera::ErrorKind::TemplateNotFound(_) if settings.templates.branch.is_none() => {},
_ => println!("ERROR: {:?}", x), _ => println!("ERROR: {:?}", x),
}, },
} }
@@ -685,7 +778,7 @@ fn main() {
if let Some(commit) = summary.commits.get(tag.tagged_id.as_ref().unwrap()) { if let Some(commit) = summary.commits.get(tag.tagged_id.as_ref().unwrap()) {
local_ctx.insert("commit", &commit); local_ctx.insert("commit", &commit);
} }
match tera.render("tag.html", &local_ctx) { match tera.render(&settings.templates.tag.as_deref().unwrap_or("tag.html"), &local_ctx) {
Ok(rendered) => { Ok(rendered) => {
let mut output_path = settings.output_dir.clone(); let mut output_path = settings.output_dir.clone();
output_path.push(&summary.name); output_path.push(&summary.name);
@@ -693,10 +786,10 @@ fn main() {
let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!"));
output_path.push(format!("{}.html", tag.full_hash)); output_path.push(format!("{}.html", tag.full_hash));
let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap();
file.write(rendered.as_bytes()).expect("failed to save rendered html"); write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref());
}, },
Err(x) => match x.kind { Err(x) => match x.kind {
tera::ErrorKind::TemplateNotFound(_) => {}, tera::ErrorKind::TemplateNotFound(_) if settings.templates.tag.is_none() => {},
_ => println!("ERROR: {:?}", x), _ => println!("ERROR: {:?}", x),
}, },
} }
@@ -706,7 +799,7 @@ fn main() {
for (_id, commit) in &summary.commits { for (_id, commit) in &summary.commits {
local_ctx.try_insert("commit", &commit).expect("Failed to add commit to template engine."); local_ctx.try_insert("commit", &commit).expect("Failed to add commit to template engine.");
match tera.render("commit.html", &local_ctx) { match tera.render(&settings.templates.commit.as_deref().unwrap_or("commit.html"), &local_ctx) {
Ok(rendered) => { Ok(rendered) => {
let mut output_path = settings.output_dir.clone(); let mut output_path = settings.output_dir.clone();
output_path.push(&summary.name); output_path.push(&summary.name);
@@ -714,9 +807,12 @@ fn main() {
let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!"));
output_path.push(format!("{}.html", commit.full_hash)); output_path.push(format!("{}.html", commit.full_hash));
let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap();
file.write(rendered.as_bytes()).expect("failed to save rendered html"); write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref());
},
Err(x) => match x.kind {
tera::ErrorKind::TemplateNotFound(_) if settings.templates.commit.is_none() => {},
_ => println!("ERROR: {:?}", x),
}, },
Err(x) => println!("ERROR: {:?}", x),
} }
local_ctx.remove("commit"); local_ctx.remove("commit");
} }
@@ -724,7 +820,7 @@ fn main() {
for file in summary.all_files.iter().filter(|x| x.kind == "file") { for file in summary.all_files.iter().filter(|x| x.kind == "file") {
let file = fill_file_contents(&repo, &file).expect("Failed to parse file."); let file = fill_file_contents(&repo, &file).expect("Failed to parse file.");
local_ctx.try_insert("file", &file).expect("Failed to add file to template engine."); local_ctx.try_insert("file", &file).expect("Failed to add file to template engine.");
match tera.render("file.html", &local_ctx) { match tera.render(&settings.templates.file.as_deref().unwrap_or("file.html"), &local_ctx) {
Ok(rendered) => { Ok(rendered) => {
let mut output_path = settings.output_dir.clone(); let mut output_path = settings.output_dir.clone();
output_path.push(&summary.name); output_path.push(&summary.name);
@@ -732,9 +828,12 @@ fn main() {
let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!"));
output_path.push(format!("{}.html", file.id)); output_path.push(format!("{}.html", file.id));
let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap();
file.write(rendered.as_bytes()).expect("failed to save rendered html"); write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref());
},
Err(x) => match x.kind {
tera::ErrorKind::TemplateNotFound(_) if settings.templates.file.is_none() => {},
_ => println!("ERROR: {:?}", x),
}, },
Err(x) => println!("ERROR: {:?}", x),
} }
local_ctx.remove("file"); local_ctx.remove("file");
} }
@@ -742,7 +841,7 @@ fn main() {
for dir in summary.all_files.iter().filter(|x| x.kind == "dir") { for dir in summary.all_files.iter().filter(|x| x.kind == "dir") {
let listing = dir_listing(&repo, &dir).expect("Failed to parse file."); let listing = dir_listing(&repo, &dir).expect("Failed to parse file.");
local_ctx.try_insert("files", &listing).expect("Failed to add dir to template engine."); local_ctx.try_insert("files", &listing).expect("Failed to add dir to template engine.");
match tera.render("dir.html", &local_ctx) { match tera.render(&settings.templates.dir.as_deref().unwrap_or("dir.html"), &local_ctx) {
Ok(rendered) => { Ok(rendered) => {
let mut output_path = settings.output_dir.clone(); let mut output_path = settings.output_dir.clone();
output_path.push(&summary.name); output_path.push(&summary.name);
@@ -750,9 +849,12 @@ fn main() {
let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!"));
output_path.push(format!("{}.html", dir.id)); output_path.push(format!("{}.html", dir.id));
let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap();
file.write(rendered.as_bytes()).expect("failed to save rendered html"); write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref());
},
Err(x) => match x.kind {
tera::ErrorKind::TemplateNotFound(_) if settings.templates.dir.is_none() => {},
_ => println!("ERROR: {:?}", x),
}, },
Err(x) => println!("ERROR: {:?}", x),
} }
local_ctx.remove("files"); local_ctx.remove("files");
} }
@@ -762,13 +864,52 @@ fn main() {
let mut global_ctx = Context::new(); let mut global_ctx = Context::new();
global_ctx.try_insert("repos", &repos).expect("Failed to add repo to template engine."); global_ctx.try_insert("repos", &repos).expect("Failed to add repo to template engine.");
match tera.render("repos.html", &global_ctx) { if let Some(extra) = &settings.extra {
global_ctx.try_insert("extra", extra).expect("Failed to add extra settings to template engine.");
}
if let Some(site_name) = &settings.site_name {
global_ctx.insert("site_name", site_name);
}
if let Some(site_url) = &settings.site_url {
global_ctx.insert("site_url", site_url);
}
if let Some(site_description) = &settings.site_description {
global_ctx.insert("site_description", site_description);
}
global_ctx.insert("site_generated_ts", &generated_dt.timestamp());
global_ctx.insert("site_generated_offset", &generated_dt.offset().local_minus_utc());
let header: Option<String> = match &settings.templates.header {
Some(header) => Some(tera.render(header, &global_ctx).expect("Unable to templatize header file")),
_ => None,
};
let footer: Option<String> = match &settings.templates.footer {
Some(footer) => Some(tera.render(footer, &global_ctx).expect("Unable to templatize footer file")),
_ => None,
};
match tera.render(&settings.templates.repo_list.as_deref().unwrap_or("repos.html"), &global_ctx) {
Ok(rendered) => { Ok(rendered) => {
let mut output_path = settings.output_dir.clone(); let mut output_path = settings.output_dir.clone();
output_path.push("repos.html"); output_path.push("repos.html");
let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap();
file.write(rendered.as_bytes()).expect("failed to save rendered html"); write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref());
},
Err(x) => match x.kind {
tera::ErrorKind::TemplateNotFound(_) if settings.templates.repo_list.is_none() => {},
_ => println!("ERROR: {:?}", x),
},
}
match tera.render(&settings.templates.error.as_deref().unwrap_or("404.html"), &global_ctx) {
Ok(rendered) => {
let mut output_path = settings.output_dir.clone();
output_path.push("404.html");
let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap();
write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref());
},
Err(x) => match x.kind {
tera::ErrorKind::TemplateNotFound(_) if settings.templates.error.is_none() => {},
_ => println!("ERROR: {:?}", x),
}, },
Err(x) => println!("ERROR: {:?}", x),
} }
} }
+1
View File
@@ -0,0 +1 @@
The page you are seeking does not exist.
+7 -11
View File
@@ -1,11 +1,7 @@
<html> branch: {{branch.ref_name}}<br/>
<body style="font-family: monospace;"> hash: {{branch.full_hash}} ({{branch.short_hash}})<br/>
branch: {{branch.ref_name}}<br/> author: {{branch.author.name}}<br/>
hash: {{branch.full_hash}} ({{branch.short_hash}})<br/> committer: {{branch.committer.name}}<br/>
author: {{branch.author.name}}<br/> date: {{ts_to_date(ts=branch.ts_utc, tz=branch.ts_offset)}}<br/>
committer: {{branch.committer.name}}<br/> summary: {{branch.summary}}<br/>
date: {{ts_to_date(ts=branch.ts_utc, tz=branch.ts_offset)}}<br/> <pre>{{branch.message}}</pre>
summary: {{branch.summary}}<br/>
<pre>{{branch.message}}</pre>
</body>
</html>
+13 -17
View File
@@ -1,31 +1,27 @@
<html> <strong>
<body style="font-family: monospace;">
<strong>
commit: {{commit.full_hash}}<br/> commit: {{commit.full_hash}}<br/>
author: {{commit.author.name}}<br/> author: {{commit.author.name}}<br/>
committer: {{commit.committer.name}}<br/> committer: {{commit.committer.name}}<br/>
parent: {% if commit.parents | length > 0 -%}<a href="{{commit.parents | first}}.html">{{commit.parents | first}}</a>{%-endif-%}<br/> parent: {% if commit.parents | length > 0 -%}<a href="{{commit.parents | first}}.html">{{commit.parents | first}}</a>{%-endif-%}<br/>
</strong> </strong>
<br/> <br/>
<pre style="margin: 0;">{{commit.message}}</pre> <pre style="margin: 0;">{{commit.message}}</pre>
{% for file in commit.diff.files -%} {% for file in commit.diff.files -%}
<br/> <br/>
<strong> <strong>
diff --git a/{{file.basefile}} b/{{file.basefile}}<br/> diff --git a/{{file.basefile}} b/{{file.basefile}}<br/>
line changes: +{{file.additions}}/-{{file.deletions}}<br/> line changes: +{{file.additions}}/-{{file.deletions}}<br/>
index {{file.oldid | truncate(length=7,end="")}}..{{file.newid | truncate(length=7,end="")}}<br/> index {{file.oldid | truncate(length=7,end="")}}..{{file.newid | truncate(length=7,end="")}}<br/>
--- {{file.oldfile}}<br/> --- {{file.oldfile}}<br/>
+++ {{file.newfile}} +++ {{file.newfile}}
</strong> </strong>
{% for hunk in file.hunks -%} {% for hunk in file.hunks -%}
<pre><strong>{{hunk.context}}</strong> <pre><strong>{{hunk.context}}</strong>
{%- for line in hunk.lines -%} {%- for line in hunk.lines -%}
{%- if line.kind in ["del","add"] -%}<span style="color: {%- if line.kind == "del" -%}bb0000{%- else -%}00aa00{% endif %}">{%- endif -%} {%- if line.kind in ["del","add"] -%}<span style="color: {%- if line.kind == "del" -%}bb0000{%- else -%}00aa00{% endif %}">{%- endif -%}
{{line.prefix}}{{line.text}} {{line.prefix}}{{line.text}}
{%- if line.kind in ["del","add"] -%}</span>{%- endif -%} {%- if line.kind in ["del","add"] -%}</span>{%- endif -%}
{%- endfor -%} {%- endfor -%}
</pre> </pre>
{% endfor -%} {% endfor -%}
{% endfor -%} {% endfor -%}
</body>
</html>
+1 -5
View File
@@ -1,6 +1,4 @@
<html> <table class="files">
<body style="font-family: monospace;">
<table class="files">
<tr> <tr>
<th>File</th> <th>File</th>
<th>ID</th> <th>ID</th>
@@ -17,5 +15,3 @@
<td class="file-size">{{file.size}}</td> <td class="file-size">{{file.size}}</td>
</tr> </tr>
{% endfor -%} {% endfor -%}
</body>
</html>
+3 -7
View File
@@ -1,7 +1,3 @@
<html> {{file.path}} ({{file.name}}) [{{file.id}}]<br/>
<body style="font-family: monospace;"> -------
{{file.path}} ({{file.name}}) [{{file.id}}]<br/> <pre style="margin: 0">{{file.contents}}</pre>
-------
<pre style="margin: 0">{{file.contents}}</pre>
</body>
</html>
+2
View File
@@ -0,0 +1,2 @@
</body>
</html>
+9
View File
@@ -0,0 +1,9 @@
<html>
<head>
<title>{{site_name}}</title>
</head>
<body style="font-family: monospace;">
Site: {{site_name}}<br/>
Generated: {{ts_to_git_timestamp(ts=site_generated_ts, tz=site_generated_offset)}}<br/>
Extra settings: {{extra.global_user_defined_vars}}<br/>
<hr/>
+3 -7
View File
@@ -1,7 +1,3 @@
<html> {% for repo in repos | sort(attribute="name") -%}
<body style="font-family: monospace;"> <a href="{{repo.name}}/summary.html">{{ repo.name }}</a> ({{repo.metadata.website}}) [{{repo.metadata.attributes | get(key="some_extra_thing", default="")}}] ({{ts_to_date(ts=repo.history[0].ts_utc, tz=repo.history[0].ts_offset)}})<br/>
{% for repo in repos -%} {% endfor -%}
<a href="{{repo.name}}/summary.html">{{ repo.name }}</a> ({{ts_to_date(ts=repo.history[0].ts_utc, tz=repo.history[0].ts_offset)}})<br/>
{% endfor -%}
</body>
</html>
+11 -15
View File
@@ -1,6 +1,4 @@
<html> <table class="commits">
<body style="font-family: monospace;">
<table class="commits">
<tr> <tr>
<th>Commit ID</th> <th>Commit ID</th>
<th>Message</th> <th>Message</th>
@@ -18,12 +16,12 @@
<td class="date">{{ts_to_date(ts=entry.ts_utc, tz=entry.ts_offset)}}</td> <td class="date">{{ts_to_date(ts=entry.ts_utc, tz=entry.ts_offset)}}</td>
<td class="diff">{{entry.stats.files}} (+{{entry.stats.additions}}/-{{entry.stats.deletions}})</td> <td class="diff">{{entry.stats.files}} (+{{entry.stats.additions}}/-{{entry.stats.deletions}})</td>
<td class="refs">{%- for ref in entry.alt_refs -%}{%- if loop.index0 > 0 -%},&nbsp; {%- endif -%}<span class="commit-ref">{{ref}}</span>{%- endfor -%}</td> <td class="refs">{%- for ref in entry.alt_refs -%}{%- if loop.index0 > 0 -%},&nbsp; {%- endif -%}<span class="commit-ref">{{ref}}</span>{%- endfor -%}</td>
</tr> </tr>
{% endif -%} {% endif -%}
{% endfor -%} {% endfor -%}
</table> </table>
<table class="branches"> <table class="branches">
<tr> <tr>
<th>Branch</th> <th>Branch</th>
<th>Commit ID</th> <th>Commit ID</th>
@@ -40,9 +38,9 @@
<td class="date">{{ts_to_date(ts=entry.ts_utc, tz=entry.ts_offset)}}</td> <td class="date">{{ts_to_date(ts=entry.ts_utc, tz=entry.ts_offset)}}</td>
</tr> </tr>
{% endfor -%} {% endfor -%}
</table> </table>
<table class="tags"> <table class="tags">
<tr> <tr>
<th>Tag</th> <th>Tag</th>
<th>Commit ID</th> <th>Commit ID</th>
@@ -59,9 +57,9 @@
<td class="date">{{ts_to_date(ts=entry.ts_utc, tz=entry.ts_offset)}}</td> <td class="date">{{ts_to_date(ts=entry.ts_utc, tz=entry.ts_offset)}}</td>
</tr> </tr>
{% endfor -%} {% endfor -%}
</table> </table>
<table class="files"> <table class="files">
<tr> <tr>
<th>File</th> <th>File</th>
<th>ID</th> <th>ID</th>
@@ -78,6 +76,4 @@
<td class="size">{{file.size}}</td> <td class="size">{{file.size}}</td>
</tr> </tr>
{% endfor -%} {% endfor -%}
</table> </table>
</body>
</html>
+11 -15
View File
@@ -1,15 +1,11 @@
<html> branch: {{tag.ref_name}}<br/>
<body style="font-family: monospace;"> hash: {{tag.full_hash}} ({{tag.short_hash}})<br/>
branch: {{tag.ref_name}}<br/> author: {{tag.author.name}}<br/>
hash: {{tag.full_hash}} ({{tag.short_hash}})<br/> committer: {{tag.committer.name}}<br/>
author: {{tag.author.name}}<br/> date: {{ts_to_date(ts=tag.ts_utc, tz=tag.ts_offset)}}<br/>
committer: {{tag.committer.name}}<br/> summary: {{tag.summary}}<br/>
date: {{ts_to_date(ts=tag.ts_utc, tz=tag.ts_offset)}}<br/> <pre>{{tag.message}}</pre>
summary: {{tag.summary}}<br/> <br/>
<pre>{{tag.message}}</pre> commit: {%- if commit -%}<a href="../commit/{{commit.full_hash}}.html">{{commit.full_hash}}</a>
<br/> <pre>{{commit.message}}</pre>
commit: {%- if commit -%}<a href="../commit/{{commit.full_hash}}.html">{{commit.full_hash}}</a> {%-else-%}{{tag.tagged_id}}{%-endif-%}<br/>
<pre>{{commit.message}}</pre>
{%-else-%}{{tag.tagged_id}}{%-endif-%}<br/>
</body>
</html>