From 4e436a268d2cb4227841e4f586480df0f9e5162a Mon Sep 17 00:00:00 2001 From: Trevor Bentley Date: Tue, 10 Jan 2023 03:19:31 +0100 Subject: [PATCH] more settings, headers+footers+error pages --- Cargo.toml | 2 +- settings.toml | 34 ++++-- src/main.rs | 237 ++++++++++++++++++++++++++++++++--------- templates/404.html | 1 + templates/branch.html | 18 ++-- templates/commit.html | 54 +++++----- templates/dir.html | 38 +++---- templates/file.html | 10 +- templates/footer.html | 2 + templates/header.html | 9 ++ templates/repos.html | 10 +- templates/summary.html | 156 +++++++++++++-------------- templates/tag.html | 26 ++--- 13 files changed, 370 insertions(+), 227 deletions(-) create mode 100644 templates/404.html create mode 100644 templates/footer.html create mode 100644 templates/header.html diff --git a/Cargo.toml b/Cargo.toml index 89f9634..24cddf9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ license = "GPL-3.0-or-later" [dependencies] -chrono = "0.4.23" +chrono = { version = "0.4.23", features=["clock"] } clap = { version="4.0.32", features=["derive"] } git2 = "0.15.0" serde = { version = "1.0.152", features = ["derive"] } diff --git a/settings.toml b/settings.toml index b90c15e..64864e0 100644 --- a/settings.toml +++ b/settings.toml @@ -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/" -[a_repo] -path = "repos/connectr" -name = "connectr" +recursive_repo_dirs = ["repos/"] -[another_repo] -path = "repos/fruitbasket" +[gitsy_templates] +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] -thingo = 1 +[gitsy_extra] +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} diff --git a/src/main.rs b/src/main.rs index 7b8f275..7685d17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,8 @@ use chrono::{ use clap::Parser; use git2::{DiffOptions, Repository, Error}; 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::path::{Path, PathBuf}; use tera::{Context, Filter, Function, Tera, Value, to_value, try_get_value}; @@ -36,7 +37,7 @@ fn first_line(msg: &[u8]) -> String { #[derive(Serialize)] struct GitRepo { name: String, - metadata: ItsyMetadata, + metadata: GitsyMetadata, history: Vec, branches: Vec, tags: Vec, @@ -46,12 +47,12 @@ struct GitRepo { } #[derive(Serialize, Default)] -struct ItsyMetadata { +struct GitsyMetadata { full_name: Option, description: Option, website: Option, clone: Option, - attributes: BTreeMap, + attributes: BTreeMap, } #[derive(Serialize, Default)] @@ -172,7 +173,7 @@ fn walk_file_tree(repo: &git2::Repository, rev: &str, files: &mut Vec, Ok(()) } -fn parse_repo(repo: &Repository, name: &str) -> Result { +fn parse_repo(repo: &Repository, name: &str, metadata: GitsyMetadata) -> Result { let mut history: Vec = vec!(); let mut branches: Vec = vec!(); let mut tags: Vec = vec!(); @@ -313,14 +314,14 @@ fn parse_repo(repo: &Repository, name: &str) -> Result { let mut root_files: Vec = vec!(); let mut all_files: Vec = 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 // 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 { name: name.to_string(), - metadata: Default::default(), + metadata, history, branches, tags, @@ -561,19 +562,63 @@ struct CliArgs { #[derive(Deserialize)] #[allow(dead_code)] -struct ItsySettings { - template_dir: PathBuf, +struct GitsySettings { output_dir: PathBuf, recursive_repo_dirs: Option>, - extra: HashMap, + site_name: Option, + site_url: Option, + site_description: Option, + #[serde(rename(deserialize = "gitsy_templates"))] + templates: GitsySettingsTemplates, + #[serde(rename(deserialize = "gitsy_extra"))] + extra: Option>, } + #[derive(Deserialize)] -#[allow(dead_code)] -struct ItsySettingsRepo { +struct GitsySettingsTemplates { + path: PathBuf, + header: Option, + footer: Option, + repo_list: Option, + repo_summary: Option, + commit: Option, + branch: Option, + tag: Option, + file: Option, + dir: Option, + error: Option, +} + +#[derive(Deserialize, Default)] +struct GitsySettingsRepo { path: PathBuf, name: Option, description: Option, website: Option, + attributes: BTreeMap, +} + +use std::hash::{Hash, Hasher}; +impl Hash for GitsySettingsRepo { + fn hash(&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() { @@ -582,11 +627,11 @@ fn main() { // 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 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. // 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 = toml::from_str(&toml).expect("blah"); let table_keys: Vec = settings_raw.iter().filter_map(|x| match x.1.is_table() { 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 // save the ones that are successful. If no repo name is // specified, use the TOML table name. - let mut repos: Vec = vec!(); + let mut repo_descriptions: std::collections::HashSet = HashSet::new(); for k in &table_keys { let v = settings_raw.get(k).unwrap(); - match toml::from_str::(&v.to_string()) { + match toml::from_str::(&v.to_string()) { Ok(mut repo) => { if repo.name.is_none() { repo.name = Some(k.clone()); } - repos.push(repo); + repo_descriptions.insert(repo); + }, + Err(e) => { + println!("Failed to parse repo [{}]: {:?}", k, e); }, - _ => {}, } } - for repo in &repos { - println!("Parse repo: {}", repo.name.as_ref().unwrap()); + 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() + }); + } + } + }, + _ => {}, } - let mut template_path = settings.template_dir.clone(); + let mut template_path = settings.templates.path.clone(); template_path.push("**"); template_path.push("*.html"); let mut tera = match Tera::new(template_path.to_str().expect("No template path set!")) { @@ -635,34 +693,69 @@ fn main() { // Create output directory 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 = vec!(); - for dir in std::fs::read_dir(std::path::Path::new("repos")).expect("Repo directory not found.") { - let dir = dir.expect("Repo contains invalid entries"); + for repo_desc in &repo_descriptions { + let dir = &repo_desc.path; match dir.metadata() { Ok(m) if m.is_dir() => {}, _ => continue, } - let path: String = dir.path().to_string_lossy().to_string(); - let name: String = dir.file_name().to_string_lossy().to_string(); + let path: String = dir.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 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(); - 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 = match &settings.templates.header { + Some(header) => Some(tera.render(header, &local_ctx).expect("Unable to templatize header file")), + _ => None, + }; + let footer: Option = 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) => { let mut output_path = settings.output_dir.clone(); output_path.push(&name); let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); output_path.push("summary.html"); 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 { 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) => { let mut output_path = settings.output_dir.clone(); 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!")); 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(); - 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(_) => {}, + tera::ErrorKind::TemplateNotFound(_) if settings.templates.branch.is_none() => {}, _ => println!("ERROR: {:?}", x), }, } @@ -685,7 +778,7 @@ fn main() { if let Some(commit) = summary.commits.get(tag.tagged_id.as_ref().unwrap()) { 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) => { let mut output_path = settings.output_dir.clone(); 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!")); 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(); - 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(_) => {}, + tera::ErrorKind::TemplateNotFound(_) if settings.templates.tag.is_none() => {}, _ => println!("ERROR: {:?}", x), }, } @@ -706,7 +799,7 @@ fn main() { for (_id, commit) in &summary.commits { 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) => { let mut output_path = settings.output_dir.clone(); 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!")); 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(); - 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"); } @@ -724,7 +820,7 @@ fn main() { for file in summary.all_files.iter().filter(|x| x.kind == "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."); - match tera.render("file.html", &local_ctx) { + match tera.render(&settings.templates.file.as_deref().unwrap_or("file.html"), &local_ctx) { Ok(rendered) => { let mut output_path = settings.output_dir.clone(); 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!")); output_path.push(format!("{}.html", file.id)); 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"); } @@ -742,7 +841,7 @@ fn main() { for dir in summary.all_files.iter().filter(|x| x.kind == "dir") { 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."); - match tera.render("dir.html", &local_ctx) { + match tera.render(&settings.templates.dir.as_deref().unwrap_or("dir.html"), &local_ctx) { Ok(rendered) => { let mut output_path = settings.output_dir.clone(); 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!")); output_path.push(format!("{}.html", dir.id)); 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"); } @@ -762,13 +864,52 @@ fn main() { let mut global_ctx = Context::new(); 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 = match &settings.templates.header { + Some(header) => Some(tera.render(header, &global_ctx).expect("Unable to templatize header file")), + _ => None, + }; + let footer: Option = 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) => { let mut output_path = settings.output_dir.clone(); output_path.push("repos.html"); 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), } } diff --git a/templates/404.html b/templates/404.html new file mode 100644 index 0000000..bb95dd8 --- /dev/null +++ b/templates/404.html @@ -0,0 +1 @@ +The page you are seeking does not exist. diff --git a/templates/branch.html b/templates/branch.html index f979a62..d349372 100644 --- a/templates/branch.html +++ b/templates/branch.html @@ -1,11 +1,7 @@ - - - branch: {{branch.ref_name}}
- hash: {{branch.full_hash}} ({{branch.short_hash}})
- author: {{branch.author.name}}
- committer: {{branch.committer.name}}
- date: {{ts_to_date(ts=branch.ts_utc, tz=branch.ts_offset)}}
- summary: {{branch.summary}}
-
{{branch.message}}
- - +branch: {{branch.ref_name}}
+hash: {{branch.full_hash}} ({{branch.short_hash}})
+author: {{branch.author.name}}
+committer: {{branch.committer.name}}
+date: {{ts_to_date(ts=branch.ts_utc, tz=branch.ts_offset)}}
+summary: {{branch.summary}}
+
{{branch.message}}
diff --git a/templates/commit.html b/templates/commit.html index c216f9c..c399d17 100644 --- a/templates/commit.html +++ b/templates/commit.html @@ -1,31 +1,27 @@ - - - - commit: {{commit.full_hash}}
- author: {{commit.author.name}}
- committer: {{commit.committer.name}}
- parent: {% if commit.parents | length > 0 -%}{{commit.parents | first}}{%-endif-%}
-
-
-
{{commit.message}}
- {% for file in commit.diff.files -%} -
- - diff --git a/{{file.basefile}} b/{{file.basefile}}
- line changes: +{{file.additions}}/-{{file.deletions}}
- index {{file.oldid | truncate(length=7,end="")}}..{{file.newid | truncate(length=7,end="")}}
- --- {{file.oldfile}}
- +++ {{file.newfile}} -
- {% for hunk in file.hunks -%} -
{{hunk.context}}
-    {%- for line in hunk.lines -%}
-    {%- if line.kind in ["del","add"] -%}{%- endif -%}
+
+  commit: {{commit.full_hash}}
+ author: {{commit.author.name}}
+ committer: {{commit.committer.name}}
+ parent: {% if commit.parents | length > 0 -%}{{commit.parents | first}}{%-endif-%}
+
+
+
{{commit.message}}
+{% for file in commit.diff.files -%} +
+ + diff --git a/{{file.basefile}} b/{{file.basefile}}
+ line changes: +{{file.additions}}/-{{file.deletions}}
+ index {{file.oldid | truncate(length=7,end="")}}..{{file.newid | truncate(length=7,end="")}}
+ --- {{file.oldfile}}
+ +++ {{file.newfile}} +
+{% for hunk in file.hunks -%} +
{{hunk.context}}
+  {%- for line in hunk.lines -%}
+  {%- if line.kind in ["del","add"] -%}{%- endif -%}
     {{line.prefix}}{{line.text}}
     {%- if line.kind in ["del","add"] -%}{%- endif -%}
-    {%- endfor -%}
-    
- {% endfor -%} - {% endfor -%} - - + {%- endfor -%} +
+{% endfor -%} +{% endfor -%} diff --git a/templates/dir.html b/templates/dir.html index 10a0eb3..44afb19 100644 --- a/templates/dir.html +++ b/templates/dir.html @@ -1,21 +1,17 @@ - - - - - - - - - - - {% for file in files -%} - - - - - - - - {% endfor -%} - - +
FileIDTypeModeSize
{{file.name}}{{file.id}}{{file.kind}} ({{file.is_binary}}){{file.mode}}{{file.size}}
+ + + + + + + + {% for file in files -%} + + + + + + + + {% endfor -%} diff --git a/templates/file.html b/templates/file.html index 762aa06..7f00ee5 100644 --- a/templates/file.html +++ b/templates/file.html @@ -1,7 +1,3 @@ - - - {{file.path}} ({{file.name}}) [{{file.id}}]
- ------- -
{{file.contents}}
- - +{{file.path}} ({{file.name}}) [{{file.id}}]
+------- +
{{file.contents}}
diff --git a/templates/footer.html b/templates/footer.html new file mode 100644 index 0000000..b605728 --- /dev/null +++ b/templates/footer.html @@ -0,0 +1,2 @@ + + diff --git a/templates/header.html b/templates/header.html new file mode 100644 index 0000000..6beb4f4 --- /dev/null +++ b/templates/header.html @@ -0,0 +1,9 @@ + + + {{site_name}} + + + Site: {{site_name}}
+ Generated: {{ts_to_git_timestamp(ts=site_generated_ts, tz=site_generated_offset)}}
+ Extra settings: {{extra.global_user_defined_vars}}
+
diff --git a/templates/repos.html b/templates/repos.html index 1ce812d..693da4f 100644 --- a/templates/repos.html +++ b/templates/repos.html @@ -1,7 +1,3 @@ - - - {% for repo in repos -%} - {{ repo.name }} ({{ts_to_date(ts=repo.history[0].ts_utc, tz=repo.history[0].ts_offset)}})
- {% endfor -%} - - +{% for repo in repos | sort(attribute="name") -%} +{{ repo.name }} ({{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)}})
+{% endfor -%} diff --git a/templates/summary.html b/templates/summary.html index 70377f3..dcc8b6a 100644 --- a/templates/summary.html +++ b/templates/summary.html @@ -1,83 +1,79 @@ - - -
FileIDTypeModeSize
{{file.name}}{{file.id}}{{file.kind}} ({{file.is_binary}}){{file.mode}}{{file.size}}
- - - - - - - - - {% for entry in history -%} - {% if loop.index0 < 250 -%} - - - - - - - - - {% endif -%} - {% endfor -%} -
Commit IDMessageAuthorDateDiffRefs
{{entry.short_hash}}{{entry.summary}}{{entry.author.name}}{{ts_to_date(ts=entry.ts_utc, tz=entry.ts_offset)}}{{entry.stats.files}} (+{{entry.stats.additions}}/-{{entry.stats.deletions}}){%- for ref in entry.alt_refs -%}{%- if loop.index0 > 0 -%},  {%- endif -%}{{ref}}{%- endfor -%}
+ + + + + + + + + + {% for entry in history -%} + {% if loop.index0 < 250 -%} + + + + + + + + +{% endif -%} +{% endfor -%} +
Commit IDMessageAuthorDateDiffRefs
{{entry.short_hash}}{{entry.summary}}{{entry.author.name}}{{ts_to_date(ts=entry.ts_utc, tz=entry.ts_offset)}}{{entry.stats.files}} (+{{entry.stats.additions}}/-{{entry.stats.deletions}}){%- for ref in entry.alt_refs -%}{%- if loop.index0 > 0 -%},  {%- endif -%}{{ref}}{%- endfor -%}
- - - - - - - - - {% for entry in branches -%} - - - - - - - - {% endfor -%} -
BranchCommit IDMessageAuthorDate
{{entry.ref_name}}{{entry.short_hash}}{{entry.summary}}{{entry.author.name}}{{ts_to_date(ts=entry.ts_utc, tz=entry.ts_offset)}}
+ + + + + + + + + {% for entry in branches -%} + + + + + + + + {% endfor -%} +
BranchCommit IDMessageAuthorDate
{{entry.ref_name}}{{entry.short_hash}}{{entry.summary}}{{entry.author.name}}{{ts_to_date(ts=entry.ts_utc, tz=entry.ts_offset)}}
- - - - - - - - - {% for entry in tags -%} - - - - - - - - {% endfor -%} -
TagCommit IDMessageAuthorDate
{{entry.ref_name}}{{entry.short_hash}}{{entry.summary}}{{entry.author.name}}{{ts_to_date(ts=entry.ts_utc, tz=entry.ts_offset)}}
+ + + + + + + + + {% for entry in tags -%} + + + + + + + + {% endfor -%} +
TagCommit IDMessageAuthorDate
{{entry.ref_name}}{{entry.short_hash}}{{entry.summary}}{{entry.author.name}}{{ts_to_date(ts=entry.ts_utc, tz=entry.ts_offset)}}
- - - - - - - - - {% for file in root_files -%} - - - - - - - - {% endfor -%} -
FileIDTypeModeSize
{{file.name}}{{file.id}}{{file.kind}} ({{file.is_binary}}){{file.mode}}{{file.size}}
- - + + + + + + + + + {% for file in root_files -%} + + + + + + + + {% endfor -%} +
FileIDTypeModeSize
{{file.name}}{{file.id}}{{file.kind}} ({{file.is_binary}}){{file.mode}}{{file.size}}
diff --git a/templates/tag.html b/templates/tag.html index 53bf17e..df2ff89 100644 --- a/templates/tag.html +++ b/templates/tag.html @@ -1,15 +1,11 @@ - - - branch: {{tag.ref_name}}
- hash: {{tag.full_hash}} ({{tag.short_hash}})
- author: {{tag.author.name}}
- committer: {{tag.committer.name}}
- date: {{ts_to_date(ts=tag.ts_utc, tz=tag.ts_offset)}}
- summary: {{tag.summary}}
-
{{tag.message}}
-
- commit: {%- if commit -%}{{commit.full_hash}} -
{{commit.message}}
- {%-else-%}{{tag.tagged_id}}{%-endif-%}
- - +branch: {{tag.ref_name}}
+hash: {{tag.full_hash}} ({{tag.short_hash}})
+author: {{tag.author.name}}
+committer: {{tag.committer.name}}
+date: {{ts_to_date(ts=tag.ts_utc, tz=tag.ts_offset)}}
+summary: {{tag.summary}}
+
{{tag.message}}
+
+commit: {%- if commit -%}{{commit.full_hash}} +
{{commit.message}}
+{%-else-%}{{tag.tagged_id}}{%-endif-%}