wayver's git archive


a simple self-hosted git server
git clone https://git.wayver.dev/bile

src/utils/filters.rs@f3f2b40f0ffae5de2e6d3f661e32b582274bae49

raw
Date Commit Message Author Files + -
2026-02-17 21:59 small fixes wayverd 2 8 1
...

1#![allow(clippy::inline_always, reason = "generated by askama filter_fn")]
2
3use git2::{Commit, Signature, Time};
4use jiff::{
5    Timestamp,
6    tz::{self, TimeZone},
7};
8use num_conv::Truncate as _;
9
10use crate::utils::git::Repository;
11
12#[askama::filter_fn]
13#[tracing::instrument(skip_all)]
14pub fn format_datetime<'f>(
15    time: Time,
16    _: &dyn askama::Values,
17    format: &'f str,
18) -> askama::Result<jiff::fmt::strtime::Display<'f>> {
19    let tz = TimeZone::fixed(tz::offset((time.offset_minutes() / 60).truncate::<i8>()));
20
21    let timestamp = Timestamp::from_second(time.seconds()).map_err(|err| {
22        tracing::error!(err=%err, "failed to convert seconds into a timestamp");
23
24        askama::Error::Fmt
25    })?;
26
27    let zoned = timestamp.to_zoned(tz);
28
29    let format = zoned.strftime(format);
30
31    Ok(format)
32}
33
34#[askama::filter_fn]
35pub fn unix_perms(m: i32, _: &dyn askama::Values) -> askama::Result<String> {
36    // https://unix.stackexchange.com/questions/450480/file-permission-with-six-bytes-in-git-what-does-it-mean
37    // Git doesn't store arbitrary modes, only a subset of the values are
38    // allowed. Since the number of possible values is quite small, it is
39    // easiest to exhaustively match them.
40    Ok(match m {
41        0o040_000 => "drwxr-xr-x", // directory
42        0o100_755 => "-rwxr-xr-x", // regular file, executable
43        0o100_644 => "-rw-r--r--", // regular file, default umask
44        0o120_000 => "lrwxrwxrwx", // symlink
45        0o160_000 => "m---------", // submodule
46        _ => unreachable!("unknown file mode"),
47    }
48    .into())
49}
50
51#[askama::filter_fn]
52pub fn repo_name<'r>(repo: &'r Repository, _: &dyn askama::Values) -> askama::Result<&'r str> {
53    repo.name().ok_or(askama::Error::Fmt)
54}
55
56#[askama::filter_fn]
57pub fn description(repo: &Repository, _: &dyn askama::Values) -> askama::Result<String> {
58    Ok(repo.description())
59}
60
61#[askama::filter_fn]
62#[tracing::instrument(skip_all)]
63pub fn last_modified(repo: &Repository, _: &dyn askama::Values) -> askama::Result<Time> {
64    repo.last_modified().map_err(|err| {
65        tracing::error!(err=?err, "failed to get repo's last modified date");
66        askama::Error::Fmt
67    })
68}
69
70#[askama::filter_fn]
71pub fn repo_owner(repo: &Repository, _: &dyn askama::Values) -> askama::Result<String> {
72    Ok(repo.owner())
73}
74
75#[askama::filter_fn]
76pub fn signature_email_link(
77    signature: &Signature<'_>,
78    _: &dyn askama::Values,
79) -> askama::Result<String> {
80    let Some(email) = signature.email() else {
81        return Ok(signature.to_string());
82    };
83
84    Ok(format!(
85        "<a href=\"mailto:{}\">{}</a>",
86        email,
87        signature.name().unwrap_or("&#65533;")
88    ))
89}
90
91#[askama::filter_fn]
92#[tracing::instrument(skip_all)]
93pub fn short_id(commit: &Commit<'_>, _: &dyn askama::Values) -> askama::Result<String> {
94    let id = match commit.as_object().short_id() {
95        Ok(id) => id,
96        Err(err) => {
97            tracing::error!(err=?err, "failed to get short id of commit");
98
99            return Err(askama::Error::Fmt);
100        }
101    };
102
103    id.as_str().map(str::to_string).ok_or(askama::Error::Fmt)
104}
105