aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Korotkiewicz <skorotkiewicz@gmail.com>2026-08-10 02:44:07 +0200
committerSebastian Korotkiewicz <skorotkiewicz@gmail.com>2026-08-10 02:44:07 +0200
signature Sebastian Korotkiewicz <skorotkiewicz@gmail.com>

This commit was signed with a verified signature.

Signer
Sebastian Korotkiewicz <skorotkiewicz@gmail.com>
Signing key
5BDC557B496BDB0D
Fingerprint
B498E2E410902F8AEC108F4F5BDC557B496BDB0D
commit1b664963f5d9dce8d8ff45be7bbaf9bed278a590 (patch)
tree80dfdfda3a1c49fe4e37f771ce9680612b8b9146
parentb5066088445be68405dc13d65a41ac9d2de0f784 (diff)
downloadaurcade-1b664963f5d9dce8d8ff45be7bbaf9bed278a590.tar.gz
aurcade-1b664963f5d9dce8d8ff45be7bbaf9bed278a590.zip
Add favicon support
Add optional favicon configuration, validation, and default. Include aurcade-favicon.svg in Docker image and update documentation.
-rw-r--r--README.md1
-rw-r--r--config_example.toml2
-rw-r--r--docker/Dockerfile1
-rw-r--r--docker/README.md1
-rw-r--r--docker/aurcade-favicon.svg9
-rw-r--r--src/main.rs28
6 files changed, 40 insertions, 2 deletions
diff --git a/README.md b/README.md
index 3529135..e65a472 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,7 @@ description = "My Git repositories"
clone_prefix = "http://localhost:8080 ssh://git@localhost:2222"
style = "cgit-theme.css"
logo = "aurcade-logo.svg"
+favicon = "aurcade-favicon.svg"
[[accounts]]
name = "alice"
diff --git a/config_example.toml b/config_example.toml
index 2cc6a89..1bc7c03 100644
--- a/config_example.toml
+++ b/config_example.toml
@@ -5,6 +5,8 @@ clone_prefix = "http://localhost:8080 ssh://git@localhost:2222"
# style = "cgit-theme.css"
# Optional image filename; defaults to cgit.png.
# logo = "aurcade-logo.svg"
+# Optional favicon filename; defaults to favicon.ico.
+# favicon = "aurcade-favicon.svg"
# Restart the container after changing accounts, keys, or paths.
[[accounts]]
diff --git a/docker/Dockerfile b/docker/Dockerfile
index d7d2488..7e9e4c6 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -42,6 +42,7 @@ COPY --from=rust-build /src/target/release/aurcade /usr/local/bin/aurcade
COPY docker/lighttpd.conf /etc/lighttpd/lighttpd.conf
COPY docker/cgit-theme.css /usr/share/webapps/cgit/cgit-theme.css
COPY docker/aurcade-logo.svg /usr/share/webapps/cgit/aurcade-logo.svg
+COPY docker/aurcade-favicon.svg /usr/share/webapps/cgit/aurcade-favicon.svg
COPY docker/about-filter.py /usr/local/bin/aurcade-about-filter
COPY docker/entrypoint.sh /usr/local/bin/entrypoint
RUN passwd -d git \
diff --git a/docker/README.md b/docker/README.md
index 7660b1e..2fa154c 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -54,6 +54,7 @@ description = "My Git repositories"
clone_prefix = "http://localhost:8080 ssh://git@localhost:2222"
style = "cgit-theme.css"
logo = "aurcade-logo.svg"
+favicon = "aurcade-favicon.svg"
[[accounts]]
name = "alice"
diff --git a/docker/aurcade-favicon.svg b/docker/aurcade-favicon.svg
new file mode 100644
index 0000000..1c45288
--- /dev/null
+++ b/docker/aurcade-favicon.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-labelledby="title">
+ <title id="title">AURcade favicon</title>
+ <rect x="2" y="2" width="60" height="60" rx="12" fill="#0d071e" stroke="#ff4fd8" stroke-width="3"/>
+ <path d="M18 46h28l6 10H12z" fill="#382052" stroke="#49e7ff" stroke-width="2" stroke-linejoin="round"/>
+ <path d="M32 45V24m0 9h13v-9" fill="none" stroke="#49e7ff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
+ <circle cx="32" cy="17" r="9" fill="#ffe66d" stroke="#fff2a8" stroke-width="2"/>
+ <circle cx="45" cy="22" r="4" fill="#7dff9b"/>
+ <circle cx="32" cy="36" r="4" fill="#ff4fd8"/>
+</svg>
diff --git a/src/main.rs b/src/main.rs
index 901a32a..ee94426 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -21,6 +21,7 @@ struct Config {
clone_prefix: String,
style: Option<String>,
logo: Option<String>,
+ favicon: Option<String>,
accounts: Vec<Account>,
}
@@ -100,6 +101,16 @@ fn validate_config(config: &Config) -> Result<(), Error> {
}) {
return Err("logo must be an image filename".into());
}
+ if config.favicon.as_deref().is_some_and(|favicon| {
+ ![".gif", ".ico", ".jpeg", ".jpg", ".png", ".svg", ".webp"]
+ .iter()
+ .any(|extension| favicon.ends_with(extension))
+ || !favicon
+ .bytes()
+ .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'.' | b'_' | b'-'))
+ }) {
+ return Err("favicon must be an image filename".into());
+ }
let mut names = HashSet::new();
for account in &config.accounts {
@@ -392,6 +403,10 @@ fn cgit_logo(config: &Config) -> &str {
config.logo.as_deref().unwrap_or("cgit.png")
}
+fn cgit_favicon(config: &Config) -> &str {
+ config.favicon.as_deref().unwrap_or("favicon.ico")
+}
+
fn repository_section<'a>(config: &'a Config, repository: &str) -> Option<&'a str> {
let mut owners = config
.accounts
@@ -447,12 +462,13 @@ fn write_cgit_config(config: &Config, root: &Path) -> Result<(), Error> {
.map(PathBuf::from)
.unwrap_or_else(|| root.join("cgitrc"));
let mut output = format!(
- "root-title={}\nroot-desc={}\nvirtual-root=/\nclone-prefix={}\ncss={}\nlogo={}\nmimetype-file=/etc/mime.types\nabout-filter=/usr/local/bin/aurcade-about-filter\nsource-filter=/usr/lib/cgit/filters/syntax-highlighting.sh\nenable-http-clone=1\nsnapshots=tar.gz zip\ncache-root=/var/cache/cgit\ncache-size=1000\ncache-dynamic-ttl=1\ncache-repo-ttl=1\ncache-root-ttl=1\ncache-about-ttl=1\nreadme=:README.md\nreadme=:README\n",
+ "root-title={}\nroot-desc={}\nvirtual-root=/\nclone-prefix={}\ncss={}\nlogo={}\nfavicon={}\nmimetype-file=/etc/mime.types\nabout-filter=/usr/local/bin/aurcade-about-filter\nsource-filter=/usr/lib/cgit/filters/syntax-highlighting.sh\nenable-http-clone=1\nsnapshots=tar.gz zip\ncache-root=/var/cache/cgit\ncache-size=1000\ncache-dynamic-ttl=1\ncache-repo-ttl=1\ncache-root-ttl=1\ncache-about-ttl=1\nreadme=:README.md\nreadme=:README\n",
config.title,
config.description,
config.clone_prefix,
format_args!("/{}", cgit_style(config)),
- format_args!("/{}", cgit_logo(config))
+ format_args!("/{}", cgit_logo(config)),
+ format_args!("/{}", cgit_favicon(config))
);
let mut repositories = BTreeSet::new();
configured_repositories(config, root, root, &mut repositories)?;
@@ -624,14 +640,20 @@ mod tests {
assert!(validate_config(&config).is_ok());
assert_eq!(cgit_style(&config), "cgit.css");
assert_eq!(cgit_logo(&config), "cgit.png");
+ assert_eq!(cgit_favicon(&config), "favicon.ico");
config.style = Some("cgit-theme.css".into());
config.logo = Some("aurcade-logo.svg".into());
+ config.favicon = Some("aurcade-favicon.svg".into());
assert!(validate_config(&config).is_ok());
assert_eq!(cgit_style(&config), "cgit-theme.css");
assert_eq!(cgit_logo(&config), "aurcade-logo.svg");
+ assert_eq!(cgit_favicon(&config), "aurcade-favicon.svg");
config.logo = Some("../outside.svg".into());
assert!(validate_config(&config).is_err());
config.logo = Some("aurcade-logo.svg".into());
+ config.favicon = Some("../outside.ico".into());
+ assert!(validate_config(&config).is_err());
+ config.favicon = Some("aurcade-favicon.svg".into());
assert_eq!(
public_key(&config.accounts[0].ssh_keys[0]).unwrap(),
"ssh-ed25519 AAAA"
@@ -696,6 +718,7 @@ mod tests {
clone_prefix: "http://localhost".into(),
style: None,
logo: None,
+ favicon: None,
accounts: vec![Account {
name: "alice".into(),
ssh_keys: vec!["ssh-ed25519 AAAA comment".into()],
@@ -777,6 +800,7 @@ mod tests {
clone_prefix: "http://localhost".into(),
style: None,
logo: None,
+ favicon: None,
accounts: vec![Account {
name: "alice".into(),
ssh_keys: vec![],