add configurable limits
This commit is contained in:
+337
-14
@@ -1,26 +1,283 @@
|
|||||||
|
###############################################################################
|
||||||
|
##
|
||||||
|
## Global, site-wide configuration settings
|
||||||
|
##
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# A friendly name for the generated site.
|
||||||
|
#
|
||||||
|
# This is accessible in all templates.
|
||||||
site_name = "Trevor's Repos"
|
site_name = "Trevor's Repos"
|
||||||
|
|
||||||
|
# The URL where this generated site is hosted.
|
||||||
|
#
|
||||||
|
# This is accessible in all templates.
|
||||||
site_url = "https://git.trevorbentley.com"
|
site_url = "https://git.trevorbentley.com"
|
||||||
|
|
||||||
|
# A description of the generated site.
|
||||||
|
#
|
||||||
|
# This is accessible in all templates.
|
||||||
site_description = "A bunch of git repos in a stupid format."
|
site_description = "A bunch of git repos in a stupid format."
|
||||||
|
|
||||||
render_markdown = true
|
# List of directories, each of which contains Git repositories to
|
||||||
syntax_highlight = true
|
# index.
|
||||||
syntax_highlight_theme = "base16-ocean.light"
|
#
|
||||||
|
# For each directory listed here, Itsy-Gitsy imports all of the
|
||||||
asset_files = ["test.html"]
|
# immediate subdirectories as repositories. Each repository is
|
||||||
|
# imported with its name set to the name of the subdirectory it is in.
|
||||||
|
#
|
||||||
|
# Every repository imported in this way has the global setting from
|
||||||
|
# this file applied. It is not possible to apply per-repository
|
||||||
|
# settings for bulk-imported repositories. Repositories that require
|
||||||
|
# specific configuration can be explicitly specified later in this
|
||||||
|
# file.
|
||||||
recursive_repo_dirs = ["repos/"]
|
recursive_repo_dirs = ["repos/"]
|
||||||
|
|
||||||
|
# List of files to copy to the site's `global_assets` directory.
|
||||||
|
#
|
||||||
|
# The files in this list are copied unmodified, and with the same name, to the
|
||||||
|
# configured `global_asset` output directory. Use for including global,
|
||||||
|
# site-wide resources, such as stylesheets, images, and icons.
|
||||||
|
#
|
||||||
|
# Currently does NOT support globbing or directories. Each file must be listed
|
||||||
|
# individually.
|
||||||
|
#
|
||||||
|
# This can also be set per-repository, in which case the `repo_assets` output
|
||||||
|
# directory is used.
|
||||||
|
asset_files = ["test.html"]
|
||||||
|
|
||||||
|
# Whether to render Markdown files in repos into HTML.
|
||||||
|
#
|
||||||
|
# Rendering Markdown can make site generation take more time. It has potential
|
||||||
|
# security implications, as user-generated input (files in the repo) are
|
||||||
|
# formatted into HTML and served unescaped. Use with caution.
|
||||||
|
#
|
||||||
|
# This can also be set per-repository.
|
||||||
|
render_markdown = true
|
||||||
|
|
||||||
|
# Whether render files with syntax highlighting, as HTML.
|
||||||
|
#
|
||||||
|
# Applying syntax highlighting is CPU-intensive, and greatly increases site
|
||||||
|
# generation time. It has potential security implications, as user-generated
|
||||||
|
# input (files in the repo) are formatted into HTML and served unescaped. Use
|
||||||
|
# with caution.
|
||||||
|
#
|
||||||
|
# This can also be set per-repository.
|
||||||
|
syntax_highlight = true
|
||||||
|
|
||||||
|
# Which theme to use for syntax highlighting colors.
|
||||||
|
#
|
||||||
|
# The default themes from Syntect are available, namely:
|
||||||
|
#
|
||||||
|
# - `base16-ocean.light`
|
||||||
|
# - `base16-ocean.dark`
|
||||||
|
# - `base16-eighties.dark`
|
||||||
|
# - `base16-mocha.dark`
|
||||||
|
# - `InspiredGithub`
|
||||||
|
# - `Solarized (dark)`
|
||||||
|
# - `Solarized (light)`
|
||||||
|
#
|
||||||
|
syntax_highlight_theme = "base16-ocean.light"
|
||||||
|
|
||||||
|
# Limits maximum number of history items (i.e. git log) to parse.
|
||||||
|
#
|
||||||
|
# After the limit is reached, no more history items will be processed or stored
|
||||||
|
# in memory, and no more commits will be output to disk. For large
|
||||||
|
# repositories, this can increase processing speed and decrease memory and disk
|
||||||
|
# usage.
|
||||||
|
#
|
||||||
|
# This can also be set per-repository.
|
||||||
|
limit_history = 500
|
||||||
|
|
||||||
|
# Limits maximum number of commits to output.
|
||||||
|
#
|
||||||
|
# When the limit is reached, no more commits are written to disk. Similar to
|
||||||
|
# `limit_history`, but the entire git log is still read into RAM and provided
|
||||||
|
# to the templates.
|
||||||
|
#
|
||||||
|
# This can also be set per-repository.
|
||||||
|
limit_commits = 500
|
||||||
|
|
||||||
|
# Limits maximum number of branches to parse.
|
||||||
|
#
|
||||||
|
# When the limit is reached, no more branches are parsed in memory or provided
|
||||||
|
# to the `branch` template.
|
||||||
|
#
|
||||||
|
# Since branch order is unsorted and non-deterministic, the most sensible
|
||||||
|
# values for this are very large, or 0 (to disable branches).
|
||||||
|
#
|
||||||
|
# This can also be set per-repository.
|
||||||
|
limit_branches = 500
|
||||||
|
|
||||||
|
# Limits maximum number of tags to parse.
|
||||||
|
#
|
||||||
|
# When the limit is reached, no more tags are parsed in memory or provided to
|
||||||
|
# the `tag` template.
|
||||||
|
#
|
||||||
|
# Since tag order is unsorted and non-deterministic, the most sensible values
|
||||||
|
# for this are very large, or 0 (to disable tags).
|
||||||
|
#
|
||||||
|
# This can also be set per-repository.
|
||||||
|
limit_tags = 500
|
||||||
|
|
||||||
|
# Limits directory depth to traverse when parsing files.
|
||||||
|
#
|
||||||
|
# Limits the number of directories traversed when enumerating files in the
|
||||||
|
# `all_files` entry, which is passed as part of the repository to each
|
||||||
|
# template. This can help reduce RAM usage, and potentially disk usage, for
|
||||||
|
# repositories with a very large number of files or directories.
|
||||||
|
#
|
||||||
|
# Set to 0 to disable both `all_files` and `root_files`, i.e. do not parse any
|
||||||
|
# file listing. If set to 1 or greater, only applies to `all_files`.
|
||||||
|
#
|
||||||
|
# This can also be set per-repository.
|
||||||
|
limit_tree_depth = 20
|
||||||
|
|
||||||
|
# Limits size of files in repo with content previews.
|
||||||
|
#
|
||||||
|
# Only non-binary files smaller than this limit will have their contents
|
||||||
|
# provided to the `file` template. Large files are still processed, but do not
|
||||||
|
# include the text contents.
|
||||||
|
#
|
||||||
|
# This can also be set per-repository.
|
||||||
|
limit_file_size = 2097152
|
||||||
|
|
||||||
|
# Limits size of a single produced repository.
|
||||||
|
#
|
||||||
|
# Limits the size of a generated repository preview. This is a low-precision
|
||||||
|
# limit, terminating generation wherever it happens to be, and may lead to many
|
||||||
|
# dead links in the final output.
|
||||||
|
#
|
||||||
|
# This limit is not strict: generation is terminated after the first file that
|
||||||
|
# exceeds this limit. The output size might somewhat overflow this limit.
|
||||||
|
# Also, static repository assets specified in this configuration are NOT
|
||||||
|
# included in this limit.
|
||||||
|
#
|
||||||
|
# This is intended merely as a safety mechanism to prevent massive run-away
|
||||||
|
# disk usage.
|
||||||
|
#
|
||||||
|
# This can also be set per-repository.
|
||||||
|
limit_repo_size = 52428800
|
||||||
|
|
||||||
|
# Limits total size of all output.
|
||||||
|
#
|
||||||
|
# Limits the size of the total run: the sum of all repositories. This is a
|
||||||
|
# low-precision limit, terminating generation wherever it happens to be, and
|
||||||
|
# may lead to many dead links or entirely missing repositories.
|
||||||
|
#
|
||||||
|
# This limit is not strict: generation is terminated after the first file that
|
||||||
|
# exceeds this limit. The output size might somewhat overflow this limit.
|
||||||
|
# Also, static repository assets specified in this configuration are NOT
|
||||||
|
# included in this limit.
|
||||||
|
#
|
||||||
|
# This is intended merely as a safety mechanism to prevent massive run-away
|
||||||
|
# disk usage.
|
||||||
|
#
|
||||||
|
# This can also be set per-repository.
|
||||||
|
limit_total_size = 524288000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
##
|
||||||
|
## Subsection specifying which files to use as templates.
|
||||||
|
##
|
||||||
|
## The individual templates are relative to the `path` directory. Each
|
||||||
|
## template is a single file using the Tera template engine's format for text
|
||||||
|
## substitution.
|
||||||
|
##
|
||||||
|
###############################################################################
|
||||||
[gitsy_templates]
|
[gitsy_templates]
|
||||||
|
|
||||||
|
# Path to a folder containing Tera templates.
|
||||||
|
#
|
||||||
|
# All files with a .html extension found under this directory, and its
|
||||||
|
# immediate children directories, are imported into the Tera template engine.
|
||||||
path = "templates/"
|
path = "templates/"
|
||||||
|
|
||||||
|
# Template responsible for the list of repositories.
|
||||||
|
#
|
||||||
|
# This template is evaluated with the list of all configured repositories. It
|
||||||
|
# is intended for providing an overview of the available repositories, but the
|
||||||
|
# full details of each repository are also included.
|
||||||
|
#
|
||||||
|
# This template executes one time.
|
||||||
repo_list = "repos.html"
|
repo_list = "repos.html"
|
||||||
|
|
||||||
|
# Template responsible for summarizing a single repository.
|
||||||
|
#
|
||||||
|
# This template is evaluated with a single parsed repository, with all repo
|
||||||
|
# data (commits, branches, etc) available.
|
||||||
|
#
|
||||||
|
# This template executes one time per repository.
|
||||||
repo_summary = "summary.html"
|
repo_summary = "summary.html"
|
||||||
|
|
||||||
|
# Template responsible for displaying a single commit.
|
||||||
|
#
|
||||||
|
# Called once per parsed commit, with both the whole repository and the current
|
||||||
|
# commit available to the template.
|
||||||
|
#
|
||||||
|
# This template executes many times.
|
||||||
commit = "commit.html"
|
commit = "commit.html"
|
||||||
|
|
||||||
|
# Template responsible for displaying a single branch.
|
||||||
|
#
|
||||||
|
# Called once per parsed branch, with both the whole repository and the current
|
||||||
|
# branch available to the template.
|
||||||
|
#
|
||||||
|
# This template executes many times.
|
||||||
branch = "branch.html"
|
branch = "branch.html"
|
||||||
|
|
||||||
|
# Template responsible for displaying a single tag.
|
||||||
|
#
|
||||||
|
# Called once per parsed tag, with both the whole repository and the current
|
||||||
|
# tag available to the template.
|
||||||
|
#
|
||||||
|
# This template executes many times.
|
||||||
tag = "tag.html"
|
tag = "tag.html"
|
||||||
|
|
||||||
|
# Template responsible for displaying a single file.
|
||||||
|
#
|
||||||
|
# Called once per parsed file, with both the whole repository and the current
|
||||||
|
# file available to the template.
|
||||||
|
#
|
||||||
|
# This template executes many times.
|
||||||
file = "file.html"
|
file = "file.html"
|
||||||
|
|
||||||
|
# Template responsible for displaying a single directory.
|
||||||
|
#
|
||||||
|
# Called once per parsed directory, with both the whole repository and the
|
||||||
|
# current directory available to the template.
|
||||||
|
#
|
||||||
|
# This template executes many times.
|
||||||
dir = "dir.html"
|
dir = "dir.html"
|
||||||
|
|
||||||
|
# Template responsible for displaying a site-wide error.
|
||||||
|
#
|
||||||
|
# Intended for 404 (page not found) errors. If used, you must configure your
|
||||||
|
# webserver to redirect HTTP errors to the generated error page.
|
||||||
|
#
|
||||||
|
# This template executes one time.
|
||||||
error = "404.html"
|
error = "404.html"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
##
|
||||||
|
## Subsection specifying names of output files/directories.
|
||||||
|
##
|
||||||
|
## Each entry pairs with one of the entries in `gitsy_templates` above,
|
||||||
|
## specifying the directories and filenames for the rendered output, after the
|
||||||
|
## template engine has performed its substitutions.
|
||||||
|
##
|
||||||
|
## All outputs are relative to the `path` directory.
|
||||||
|
##
|
||||||
|
## There are currently two supported variables for paths:
|
||||||
|
##
|
||||||
|
## * "%REPO%" -- replaced with the name of the currently processing repository
|
||||||
|
## * "%ID%" -- replaced with the ID of the currently processing object
|
||||||
|
##
|
||||||
|
###############################################################################
|
||||||
[gitsy_outputs]
|
[gitsy_outputs]
|
||||||
path = "gen/"
|
path = "gen/"
|
||||||
repo_list = "repos.html"
|
repo_list = "repos.html"
|
||||||
@@ -32,18 +289,84 @@ file = "%REPO%/file/%ID%.html"
|
|||||||
syntax_css = "%REPO%/file/syntax.css"
|
syntax_css = "%REPO%/file/syntax.css"
|
||||||
dir = "%REPO%/dir/%ID%.html"
|
dir = "%REPO%/dir/%ID%.html"
|
||||||
error = "404.html"
|
error = "404.html"
|
||||||
|
|
||||||
|
# Output directory for files specified in global `asset_files`.
|
||||||
|
#
|
||||||
|
# Each input file is copied to this directory unmodified.
|
||||||
global_assets = "assets/"
|
global_assets = "assets/"
|
||||||
|
|
||||||
|
# Output directory for files specified in per-repo `asset_files`.
|
||||||
|
#
|
||||||
|
# Each input file is copied to this directory unmodified.
|
||||||
repo_assets = "%REPO%/assets/"
|
repo_assets = "%REPO%/assets/"
|
||||||
|
|
||||||
[gitsy_extra]
|
|
||||||
global_user_defined_vars = "whatever"
|
|
||||||
these_can_also_be_numbers = 5
|
|
||||||
or_bools = true
|
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
##
|
||||||
|
## Subsection for arbitrary, global user data.
|
||||||
|
##
|
||||||
|
## These variables are available to every page template. Add extra metadata
|
||||||
|
## that you want available site-wide here.
|
||||||
|
##
|
||||||
|
###############################################################################
|
||||||
|
[gitsy_extra]
|
||||||
|
generated_by = "Itsy-Gitsy"
|
||||||
|
#global_user_defined_var = "whatever"
|
||||||
|
#these_can_also_be_numbers = 5
|
||||||
|
#or_bools = true
|
||||||
|
#or_other_toml_types = {like_dicts = "yep, those too"}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
##
|
||||||
|
## Individual repository configurations.
|
||||||
|
##
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# The section name is used as the repository name if no `name` attribute is
|
||||||
|
# provided.
|
||||||
[circadian]
|
[circadian]
|
||||||
|
# Path to the Git repository.
|
||||||
path = "more_repos/circadian"
|
path = "more_repos/circadian"
|
||||||
|
|
||||||
|
# Name of this repository, if different from the section name.
|
||||||
|
name = "circadian"
|
||||||
|
|
||||||
|
# A description of this repository.
|
||||||
|
description = "A repository full of code"
|
||||||
|
|
||||||
|
# URL of website associated with this repository.
|
||||||
website = "https://circadian.trevorbentley.com"
|
website = "https://circadian.trevorbentley.com"
|
||||||
attributes = {some_extra_thing = "user defined", visible = false, number_of_bananas = 3}
|
|
||||||
render_markdown = false
|
# Dictionary of arbitrary, user-defined attributes associated with the repo.
|
||||||
syntax_highlighting = false
|
#
|
||||||
asset_files = ["LICENSE"]
|
# Specifying as an inline-table requires all keys to be on one line.
|
||||||
|
#
|
||||||
|
# Available in all repo-specific page templates.
|
||||||
|
#
|
||||||
|
attributes = { status = "active", type = "daemon" }
|
||||||
|
|
||||||
|
# Per-repository settings, same as the global versions described above:
|
||||||
|
|
||||||
|
#render_markdown = false
|
||||||
|
#syntax_highlighting = false
|
||||||
|
#syntax_highlight_theme = "base16-ocean.dark"
|
||||||
|
#limit_history = 500
|
||||||
|
#limit_commits = 500
|
||||||
|
#limit_branches = 500
|
||||||
|
#limit_tags = 500
|
||||||
|
#limit_tree_depth = 20
|
||||||
|
#limit_file_size = 2097152
|
||||||
|
#limit_repo_size = 52428800
|
||||||
|
#limit_total_size = 524288000
|
||||||
|
#asset_files = ["LICENSE"]
|
||||||
|
|
||||||
|
# An alternative way to specify the user-defined attributes.
|
||||||
|
#
|
||||||
|
# This method allows keys to be on their own lines.
|
||||||
|
#
|
||||||
|
#[circadian.attributes]
|
||||||
|
#status = "active"
|
||||||
|
#type = "daemon"
|
||||||
|
|||||||
+117
-24
@@ -25,12 +25,16 @@ use syntect::{
|
|||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
//
|
//
|
||||||
// * specify limits
|
// * verbose output
|
||||||
|
// * pagination
|
||||||
|
// * remote repositories
|
||||||
// * extra metadata for recursive repo listings?
|
// * extra metadata for recursive repo listings?
|
||||||
// * all relative paths should be relative to settings.toml
|
// * all relative paths should be relative to settings.toml
|
||||||
// * basic, light, dark, and fancy default themes
|
// * basic, light, dark, and fancy default themes
|
||||||
|
// * split into modules
|
||||||
|
// * parallelize output generation
|
||||||
// * automated tests
|
// * automated tests
|
||||||
// * documentation
|
// * documentation + examples
|
||||||
//
|
//
|
||||||
|
|
||||||
fn ts_to_date(ts: i64, offset: Option<i64>, format: Option<String>) -> String {
|
fn ts_to_date(ts: i64, offset: Option<i64>, format: Option<String>) -> String {
|
||||||
@@ -117,6 +121,7 @@ struct GitFile {
|
|||||||
kind: String,
|
kind: String,
|
||||||
is_binary: bool,
|
is_binary: bool,
|
||||||
size: usize,
|
size: usize,
|
||||||
|
tree_depth: usize,
|
||||||
contents: Option<String>,
|
contents: Option<String>,
|
||||||
contents_safe: bool,
|
contents_safe: bool,
|
||||||
contents_preformatted: bool,
|
contents_preformatted: bool,
|
||||||
@@ -157,7 +162,7 @@ struct GitDiffLine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn walk_file_tree(repo: &git2::Repository, rev: &str, files: &mut Vec<GitFile>,
|
fn walk_file_tree(repo: &git2::Repository, rev: &str, files: &mut Vec<GitFile>,
|
||||||
depth: usize, recurse: bool, prefix: &str) -> Result<(), Error> {
|
depth: usize, max_depth: usize, recurse: bool, prefix: &str) -> Result<(), Error> {
|
||||||
let obj = repo.revparse_single(rev)?;
|
let obj = repo.revparse_single(rev)?;
|
||||||
let tree = obj.peel_to_tree()?;
|
let tree = obj.peel_to_tree()?;
|
||||||
for entry in tree.iter() {
|
for entry in tree.iter() {
|
||||||
@@ -186,30 +191,41 @@ fn walk_file_tree(repo: &git2::Repository, rev: &str, files: &mut Vec<GitFile>,
|
|||||||
mode: entry.filemode(),
|
mode: entry.filemode(),
|
||||||
is_binary,
|
is_binary,
|
||||||
size,
|
size,
|
||||||
|
tree_depth: depth,
|
||||||
contents: None,
|
contents: None,
|
||||||
contents_safe: false,
|
contents_safe: false,
|
||||||
contents_preformatted: true,
|
contents_preformatted: true,
|
||||||
});
|
});
|
||||||
if recurse && entry.kind() == Some(git2::ObjectType::Tree) {
|
if recurse && depth < (max_depth - 1) && entry.kind() == Some(git2::ObjectType::Tree) {
|
||||||
let prefix = name + "/";
|
let prefix = name + "/";
|
||||||
walk_file_tree(repo, &entry.id().to_string(), files, depth+1, true, &prefix)?;
|
walk_file_tree(repo, &entry.id().to_string(), files,
|
||||||
|
depth+1, max_depth, true, &prefix)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_repo(repo: &Repository, name: &str, metadata: GitsyMetadata) -> Result<GitRepo, Error> {
|
fn parse_repo(repo: &Repository, name: &str, settings: &GitsySettingsRepo, 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!();
|
||||||
let mut commits: BTreeMap<String, GitObject> = BTreeMap::new();
|
let mut commits: BTreeMap<String, GitObject> = BTreeMap::new();
|
||||||
|
let mut commit_count = 0;
|
||||||
|
let mut history_count = 0;
|
||||||
|
let mut branch_count = 0;
|
||||||
|
let mut tag_count = 0;
|
||||||
|
|
||||||
let mut revwalk = repo.revwalk()?;
|
let mut revwalk = repo.revwalk()?;
|
||||||
revwalk.set_sorting(git2::Sort::TOPOLOGICAL)?;
|
revwalk.set_sorting(git2::Sort::TOPOLOGICAL)?;
|
||||||
revwalk.push_head()?;
|
revwalk.push_head()?;
|
||||||
for oid in revwalk {
|
for oid in revwalk {
|
||||||
let oid = oid?;
|
let oid = oid?;
|
||||||
|
if commit_count >= settings.limit_commits.unwrap_or(usize::MAX) ||
|
||||||
|
history_count >= settings.limit_history.unwrap_or(usize::MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
commits.insert(oid.to_string(), parse_commit(repo, &oid.to_string())?);
|
commits.insert(oid.to_string(), parse_commit(repo, &oid.to_string())?);
|
||||||
|
commit_count += 1;
|
||||||
let commit = repo.find_commit(oid)?;
|
let commit = repo.find_commit(oid)?;
|
||||||
let obj = repo.revparse_single(&commit.id().to_string())?;
|
let obj = repo.revparse_single(&commit.id().to_string())?;
|
||||||
let full_hash = commit.id().to_string();
|
let full_hash = commit.id().to_string();
|
||||||
@@ -249,6 +265,11 @@ fn parse_repo(repo: &Repository, name: &str, metadata: GitsyMetadata) -> Result<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if history_count < settings.limit_history.unwrap_or(usize::MAX) {
|
||||||
|
// TODO: this is basically a duplicate of the commit
|
||||||
|
// array, and really should be pointers to that array
|
||||||
|
// instead. But it's not a quick task to switch to
|
||||||
|
// self-referential data structures in Rust.
|
||||||
history.push(GitObject {
|
history.push(GitObject {
|
||||||
full_hash,
|
full_hash,
|
||||||
short_hash,
|
short_hash,
|
||||||
@@ -265,9 +286,14 @@ fn parse_repo(repo: &Repository, name: &str, metadata: GitsyMetadata) -> Result<
|
|||||||
stats: Some(stats),
|
stats: Some(stats),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
history_count += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for branch in repo.branches(None)? {
|
for branch in repo.branches(None)? {
|
||||||
|
if branch_count >= settings.limit_branches.unwrap_or(usize::MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
let (branch, _branch_type) = branch?;
|
let (branch, _branch_type) = branch?;
|
||||||
let refr = branch.get();
|
let refr = branch.get();
|
||||||
let name = branch.name()?.unwrap_or("[unnamed]");
|
let name = branch.name()?.unwrap_or("[unnamed]");
|
||||||
@@ -300,8 +326,12 @@ fn parse_repo(repo: &Repository, name: &str, metadata: GitsyMetadata) -> Result<
|
|||||||
message: commit.message().map(|x| x.to_string()),
|
message: commit.message().map(|x| x.to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
branch_count += 1;
|
||||||
}
|
}
|
||||||
for tag in repo.tag_names(None)?.iter() {
|
for tag in repo.tag_names(None)?.iter() {
|
||||||
|
if tag_count >= settings.limit_tags.unwrap_or(usize::MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
let tag = tag.unwrap_or("[unnamed]");
|
let tag = tag.unwrap_or("[unnamed]");
|
||||||
let obj = repo.revparse_single(tag)?;
|
let obj = repo.revparse_single(tag)?;
|
||||||
let commit = repo.find_tag(obj.id())?;
|
let commit = repo.find_tag(obj.id())?;
|
||||||
@@ -335,14 +365,18 @@ fn parse_repo(repo: &Repository, name: &str, metadata: GitsyMetadata) -> Result<
|
|||||||
summary,
|
summary,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
tag_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, "HEAD", &mut root_files, 0, false, "")?;
|
let max_depth = settings.limit_tree_depth.unwrap_or(usize::MAX);
|
||||||
|
if max_depth > 0 {
|
||||||
|
walk_file_tree(&repo, "HEAD", &mut root_files, 0, usize::MAX, 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, "HEAD", &mut all_files, 0, true, "")?;
|
walk_file_tree(&repo, "HEAD", &mut all_files, 0, max_depth, true, "")?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(GitRepo {
|
Ok(GitRepo {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
@@ -543,7 +577,7 @@ fn fill_file_contents(repo: &Repository, file: &GitFile, settings: &GitsySetting
|
|||||||
|
|
||||||
fn dir_listing(repo: &Repository, file: &GitFile) -> Result<Vec<GitFile>, Error> {
|
fn dir_listing(repo: &Repository, file: &GitFile) -> Result<Vec<GitFile>, Error> {
|
||||||
let mut files: Vec<GitFile> = vec!();
|
let mut files: Vec<GitFile> = vec!();
|
||||||
walk_file_tree(&repo, &file.id, &mut files, 0, false, "")?;
|
walk_file_tree(&repo, &file.id, &mut files, 0, usize::MAX, false, "")?;
|
||||||
Ok(files)
|
Ok(files)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,6 +680,14 @@ struct GitsySettings {
|
|||||||
templates: GitsySettingsTemplates,
|
templates: GitsySettingsTemplates,
|
||||||
#[serde(rename(deserialize = "gitsy_outputs"))]
|
#[serde(rename(deserialize = "gitsy_outputs"))]
|
||||||
outputs: GitsySettingsOutputs,
|
outputs: GitsySettingsOutputs,
|
||||||
|
limit_history: Option<usize>,
|
||||||
|
limit_commits: Option<usize>,
|
||||||
|
limit_branches: Option<usize>,
|
||||||
|
limit_tags: Option<usize>,
|
||||||
|
limit_tree_depth: Option<usize>,
|
||||||
|
limit_file_size: Option<usize>,
|
||||||
|
limit_repo_size: Option<usize>,
|
||||||
|
limit_total_size: Option<usize>,
|
||||||
render_markdown: Option<bool>,
|
render_markdown: Option<bool>,
|
||||||
syntax_highlight: Option<bool>,
|
syntax_highlight: Option<bool>,
|
||||||
syntax_highlight_theme: Option<String>,
|
syntax_highlight_theme: Option<String>,
|
||||||
@@ -751,7 +793,15 @@ struct GitsySettingsRepo {
|
|||||||
render_markdown: Option<bool>,
|
render_markdown: Option<bool>,
|
||||||
syntax_highlight: Option<bool>,
|
syntax_highlight: Option<bool>,
|
||||||
syntax_highlight_theme: Option<String>,
|
syntax_highlight_theme: Option<String>,
|
||||||
attributes: BTreeMap<String, toml::Value>,
|
attributes: Option<BTreeMap<String, toml::Value>>,
|
||||||
|
limit_history: Option<usize>,
|
||||||
|
limit_commits: Option<usize>,
|
||||||
|
limit_branches: Option<usize>,
|
||||||
|
limit_tags: Option<usize>,
|
||||||
|
limit_tree_depth: Option<usize>,
|
||||||
|
limit_file_size: Option<usize>,
|
||||||
|
limit_repo_size: Option<usize>,
|
||||||
|
limit_total_size: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
@@ -767,11 +817,12 @@ impl PartialEq for GitsySettingsRepo {
|
|||||||
}
|
}
|
||||||
impl Eq for GitsySettingsRepo {}
|
impl Eq for GitsySettingsRepo {}
|
||||||
|
|
||||||
fn write_rendered(path: &str, rendered: &str) {
|
fn write_rendered(path: &str, rendered: &str) -> usize {
|
||||||
let mut file = File::create(path)
|
let mut file = File::create(path)
|
||||||
.expect(&format!("Unable to write to output path: {}", path));
|
.expect(&format!("Unable to write to output path: {}", path));
|
||||||
file.write(rendered.as_bytes())
|
file.write(rendered.as_bytes())
|
||||||
.expect(&format!("Failed to save rendered html to path: {}", path));
|
.expect(&format!("Failed to save rendered html to path: {}", path));
|
||||||
|
rendered.as_bytes().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -823,6 +874,14 @@ fn main() {
|
|||||||
render_markdown: settings.render_markdown.clone(),
|
render_markdown: settings.render_markdown.clone(),
|
||||||
syntax_highlight: settings.syntax_highlight.clone(),
|
syntax_highlight: settings.syntax_highlight.clone(),
|
||||||
syntax_highlight_theme: settings.syntax_highlight_theme.clone(),
|
syntax_highlight_theme: settings.syntax_highlight_theme.clone(),
|
||||||
|
limit_history: settings.limit_history.clone(),
|
||||||
|
limit_commits: settings.limit_commits.clone(),
|
||||||
|
limit_branches: settings.limit_branches.clone(),
|
||||||
|
limit_tags: settings.limit_tags.clone(),
|
||||||
|
limit_tree_depth: settings.limit_tree_depth.clone(),
|
||||||
|
limit_file_size: settings.limit_file_size.clone(),
|
||||||
|
limit_repo_size: settings.limit_repo_size.clone(),
|
||||||
|
limit_total_size: settings.limit_total_size.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -846,13 +905,25 @@ fn main() {
|
|||||||
tera.register_function("ts_to_date", TsDateFn{});
|
tera.register_function("ts_to_date", TsDateFn{});
|
||||||
tera.register_function("ts_to_git_timestamp", TsTimestampFn{});
|
tera.register_function("ts_to_git_timestamp", TsTimestampFn{});
|
||||||
|
|
||||||
|
macro_rules! size_check {
|
||||||
|
($settings:ident, $cur:ident, $total:expr) => {
|
||||||
|
if $cur > $settings.limit_repo_size.unwrap_or(usize::MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if $total + $cur > $settings.limit_total_size.unwrap_or(usize::MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create output directory
|
// Create output directory
|
||||||
let _ = std::fs::create_dir(settings.outputs.path.to_str().expect("Output path invalid."));
|
let _ = std::fs::create_dir(settings.outputs.path.to_str().expect("Output path invalid."));
|
||||||
|
|
||||||
let generated_dt = chrono::offset::Local::now();
|
let generated_dt = chrono::offset::Local::now();
|
||||||
|
let mut total_bytes = 0;
|
||||||
let mut repos: Vec<GitRepo> = vec!();
|
let mut repos: Vec<GitRepo> = vec!();
|
||||||
for repo_desc in &repo_descriptions {
|
for repo_desc in &repo_descriptions {
|
||||||
|
let mut repo_bytes = 0;
|
||||||
let dir = &repo_desc.path;
|
let dir = &repo_desc.path;
|
||||||
match dir.metadata() {
|
match dir.metadata() {
|
||||||
Ok(m) if m.is_dir() => {},
|
Ok(m) if m.is_dir() => {},
|
||||||
@@ -866,9 +937,9 @@ fn main() {
|
|||||||
description: repo_desc.description.clone(),
|
description: repo_desc.description.clone(),
|
||||||
website: repo_desc.website.clone(),
|
website: repo_desc.website.clone(),
|
||||||
clone: None,
|
clone: None,
|
||||||
attributes: repo_desc.attributes.clone(),
|
attributes: repo_desc.attributes.clone().unwrap_or_default(),
|
||||||
};
|
};
|
||||||
let summary = parse_repo(&repo, &name, metadata).expect("Failed to analyze repo HEAD.");
|
let summary = parse_repo(&repo, &name, &repo_desc, 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();
|
||||||
if let Some(extra) = &settings.extra {
|
if let Some(extra) = &settings.extra {
|
||||||
@@ -888,7 +959,7 @@ fn main() {
|
|||||||
|
|
||||||
match tera.render(&settings.templates.repo_summary.as_deref().unwrap_or("summary.html"), &local_ctx) {
|
match tera.render(&settings.templates.repo_summary.as_deref().unwrap_or("summary.html"), &local_ctx) {
|
||||||
Ok(rendered) => {
|
Ok(rendered) => {
|
||||||
write_rendered(&settings.outputs.repo_summary(Some(&summary), None), &rendered);
|
repo_bytes += write_rendered(&settings.outputs.repo_summary(Some(&summary), None), &rendered);
|
||||||
},
|
},
|
||||||
Err(x) => match x.kind {
|
Err(x) => match x.kind {
|
||||||
tera::ErrorKind::TemplateNotFound(_) if settings.templates.repo_summary.is_none() => {},
|
tera::ErrorKind::TemplateNotFound(_) if settings.templates.repo_summary.is_none() => {},
|
||||||
@@ -897,10 +968,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for branch in &summary.branches {
|
for branch in &summary.branches {
|
||||||
|
size_check!(repo_desc, repo_bytes, total_bytes);
|
||||||
local_ctx.insert("branch", branch);
|
local_ctx.insert("branch", branch);
|
||||||
match tera.render(&settings.templates.branch.as_deref().unwrap_or("branch.html"), &local_ctx) {
|
match tera.render(&settings.templates.branch.as_deref().unwrap_or("branch.html"), &local_ctx) {
|
||||||
Ok(rendered) => {
|
Ok(rendered) => {
|
||||||
write_rendered(&settings.outputs.branch(Some(&summary), Some(branch)), &rendered);
|
repo_bytes += write_rendered(&settings.outputs.branch(Some(&summary), Some(branch)), &rendered);
|
||||||
},
|
},
|
||||||
Err(x) => match x.kind {
|
Err(x) => match x.kind {
|
||||||
tera::ErrorKind::TemplateNotFound(_) if settings.templates.branch.is_none() => {},
|
tera::ErrorKind::TemplateNotFound(_) if settings.templates.branch.is_none() => {},
|
||||||
@@ -911,13 +983,14 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for tag in &summary.tags {
|
for tag in &summary.tags {
|
||||||
|
size_check!(repo_desc, repo_bytes, total_bytes);
|
||||||
local_ctx.insert("tag", tag);
|
local_ctx.insert("tag", tag);
|
||||||
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(&settings.templates.tag.as_deref().unwrap_or("tag.html"), &local_ctx) {
|
match tera.render(&settings.templates.tag.as_deref().unwrap_or("tag.html"), &local_ctx) {
|
||||||
Ok(rendered) => {
|
Ok(rendered) => {
|
||||||
write_rendered(&settings.outputs.tag(Some(&summary), Some(tag)), &rendered);
|
repo_bytes += write_rendered(&settings.outputs.tag(Some(&summary), Some(tag)), &rendered);
|
||||||
},
|
},
|
||||||
Err(x) => match x.kind {
|
Err(x) => match x.kind {
|
||||||
tera::ErrorKind::TemplateNotFound(_) if settings.templates.tag.is_none() => {},
|
tera::ErrorKind::TemplateNotFound(_) if settings.templates.tag.is_none() => {},
|
||||||
@@ -929,10 +1002,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (_id, commit) in &summary.commits {
|
for (_id, commit) in &summary.commits {
|
||||||
|
size_check!(repo_desc, repo_bytes, total_bytes);
|
||||||
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(&settings.templates.commit.as_deref().unwrap_or("commit.html"), &local_ctx) {
|
match tera.render(&settings.templates.commit.as_deref().unwrap_or("commit.html"), &local_ctx) {
|
||||||
Ok(rendered) => {
|
Ok(rendered) => {
|
||||||
write_rendered(&settings.outputs.commit(Some(&summary), Some(commit)), &rendered);
|
repo_bytes += write_rendered(&settings.outputs.commit(Some(&summary), Some(commit)), &rendered);
|
||||||
},
|
},
|
||||||
Err(x) => match x.kind {
|
Err(x) => match x.kind {
|
||||||
tera::ErrorKind::TemplateNotFound(_) if settings.templates.commit.is_none() => {},
|
tera::ErrorKind::TemplateNotFound(_) if settings.templates.commit.is_none() => {},
|
||||||
@@ -954,15 +1028,19 @@ fn main() {
|
|||||||
.unwrap_or("base16-ocean.light")).expect("Invalid syntax highlighting theme specified.");
|
.unwrap_or("base16-ocean.light")).expect("Invalid syntax highlighting theme specified.");
|
||||||
let css: String = css_for_theme_with_class_style(theme, syntect::html::ClassStyle::Spaced)
|
let css: String = css_for_theme_with_class_style(theme, syntect::html::ClassStyle::Spaced)
|
||||||
.expect("Invalid syntax highlighting theme specified.");
|
.expect("Invalid syntax highlighting theme specified.");
|
||||||
write_rendered(&settings.outputs.syntax_css(Some(&summary), None), css.as_str());
|
repo_bytes += write_rendered(&settings.outputs.syntax_css(Some(&summary), None), css.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
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, &repo_desc).expect("Failed to parse file.");
|
size_check!(repo_desc, repo_bytes, total_bytes);
|
||||||
|
let file = match file.size < repo_desc.limit_file_size.unwrap_or(usize::MAX) {
|
||||||
|
true => fill_file_contents(&repo, &file, &repo_desc).expect("Failed to parse file."),
|
||||||
|
false => file.clone(),
|
||||||
|
};
|
||||||
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(&settings.templates.file.as_deref().unwrap_or("file.html"), &local_ctx) {
|
match tera.render(&settings.templates.file.as_deref().unwrap_or("file.html"), &local_ctx) {
|
||||||
Ok(rendered) => {
|
Ok(rendered) => {
|
||||||
write_rendered(&settings.outputs.file(Some(&summary), Some(&file)), &rendered);
|
repo_bytes += write_rendered(&settings.outputs.file(Some(&summary), Some(&file)), &rendered);
|
||||||
},
|
},
|
||||||
Err(x) => match x.kind {
|
Err(x) => match x.kind {
|
||||||
tera::ErrorKind::TemplateNotFound(_) if settings.templates.file.is_none() => {},
|
tera::ErrorKind::TemplateNotFound(_) if settings.templates.file.is_none() => {},
|
||||||
@@ -973,11 +1051,15 @@ 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") {
|
||||||
|
size_check!(repo_desc, repo_bytes, total_bytes);
|
||||||
|
if dir.tree_depth >= repo_desc.limit_tree_depth.unwrap_or(usize::MAX) - 1 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
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(&settings.templates.dir.as_deref().unwrap_or("dir.html"), &local_ctx) {
|
match tera.render(&settings.templates.dir.as_deref().unwrap_or("dir.html"), &local_ctx) {
|
||||||
Ok(rendered) => {
|
Ok(rendered) => {
|
||||||
write_rendered(&settings.outputs.dir(Some(&summary), Some(dir)), &rendered);
|
repo_bytes += write_rendered(&settings.outputs.dir(Some(&summary), Some(dir)), &rendered);
|
||||||
},
|
},
|
||||||
Err(x) => match x.kind {
|
Err(x) => match x.kind {
|
||||||
tera::ErrorKind::TemplateNotFound(_) if settings.templates.dir.is_none() => {},
|
tera::ErrorKind::TemplateNotFound(_) if settings.templates.dir.is_none() => {},
|
||||||
@@ -998,10 +1080,16 @@ fn main() {
|
|||||||
std::fs::copy(&src_file, &dst_file)
|
std::fs::copy(&src_file, &dst_file)
|
||||||
.expect(&format!("Failed to copy repo asset file: {} ({})",
|
.expect(&format!("Failed to copy repo asset file: {} ({})",
|
||||||
src_file.display(), repo_desc.name.as_deref().unwrap_or_default()));
|
src_file.display(), repo_desc.name.as_deref().unwrap_or_default()));
|
||||||
|
if let Ok(meta) = std::fs::metadata(dst_file) {
|
||||||
|
repo_bytes += meta.len() as usize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repos.push(summary);
|
repos.push(summary);
|
||||||
|
println!("Wrote repo: {} ({} bytes)", name, repo_bytes);
|
||||||
|
total_bytes += repo_bytes;
|
||||||
|
size_check!(repo_desc, repo_bytes, total_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut global_ctx = Context::new();
|
let mut global_ctx = Context::new();
|
||||||
@@ -1023,7 +1111,7 @@ fn main() {
|
|||||||
|
|
||||||
match tera.render(&settings.templates.repo_list.as_deref().unwrap_or("repos.html"), &global_ctx) {
|
match tera.render(&settings.templates.repo_list.as_deref().unwrap_or("repos.html"), &global_ctx) {
|
||||||
Ok(rendered) => {
|
Ok(rendered) => {
|
||||||
write_rendered(&settings.outputs.repo_list(None, None), &rendered);
|
total_bytes += write_rendered(&settings.outputs.repo_list(None, None), &rendered);
|
||||||
},
|
},
|
||||||
Err(x) => match x.kind {
|
Err(x) => match x.kind {
|
||||||
tera::ErrorKind::TemplateNotFound(_) if settings.templates.repo_list.is_none() => {},
|
tera::ErrorKind::TemplateNotFound(_) if settings.templates.repo_list.is_none() => {},
|
||||||
@@ -1033,7 +1121,7 @@ fn main() {
|
|||||||
|
|
||||||
match tera.render(&settings.templates.error.as_deref().unwrap_or("404.html"), &global_ctx) {
|
match tera.render(&settings.templates.error.as_deref().unwrap_or("404.html"), &global_ctx) {
|
||||||
Ok(rendered) => {
|
Ok(rendered) => {
|
||||||
write_rendered(&settings.outputs.error(None, None), &rendered);
|
total_bytes += write_rendered(&settings.outputs.error(None, None), &rendered);
|
||||||
},
|
},
|
||||||
Err(x) => match x.kind {
|
Err(x) => match x.kind {
|
||||||
tera::ErrorKind::TemplateNotFound(_) if settings.templates.error.is_none() => {},
|
tera::ErrorKind::TemplateNotFound(_) if settings.templates.error.is_none() => {},
|
||||||
@@ -1050,6 +1138,11 @@ fn main() {
|
|||||||
.expect(&format!("Failed to copy asset file: {}", src_file.display())));
|
.expect(&format!("Failed to copy asset file: {}", src_file.display())));
|
||||||
std::fs::copy(&src_file, &dst_file)
|
std::fs::copy(&src_file, &dst_file)
|
||||||
.expect(&format!("Failed to copy asset file: {}", src_file.display()));
|
.expect(&format!("Failed to copy asset file: {}", src_file.display()));
|
||||||
|
if let Ok(meta) = std::fs::metadata(dst_file) {
|
||||||
|
total_bytes += meta.len() as usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Total bytes written: {}", total_bytes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
<hr/>
|
<hr/>
|
||||||
Generated by Itsy-Gitsy on {{ts_to_git_timestamp(ts=site_generated_ts, tz=site_generated_offset)}}<br/>
|
Generated by {{extra | get(key="generated_by", default="Itsy-Gitsy")}} on {{ts_to_git_timestamp(ts=site_generated_ts, tz=site_generated_offset)}}<br/>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
Site: {{site_name}}<br/>
|
Site: {{site_name}}<br/>
|
||||||
Extra settings: {{extra.global_user_defined_vars}}<br/>
|
Description: {{site_description}}<br/>
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% for repo in repos | sort(attribute="name") -%}
|
{% for repo in repos | sort(attribute="name") -%}
|
||||||
<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/>
|
<a href="{{repo.name}}/summary.html">{{ repo.name }}</a> ({{repo.metadata.website}}) [{{repo.metadata.attributes | get(key="status", default="unknown")}}] ({{ts_to_date(ts=repo.history[0].ts_utc, tz=repo.history[0].ts_offset)}})<br/>
|
||||||
{% endfor -%}
|
{% endfor -%}
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|||||||
Reference in New Issue
Block a user