diff options
| author | Sebastian Korotkiewicz <skorotkiewicz@gmail.com> | 2026-08-10 02:44:07 +0200 |
|---|---|---|
| committer | Sebastian 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.
| |
| commit | 1b664963f5d9dce8d8ff45be7bbaf9bed278a590 (patch) | |
| tree | 80dfdfda3a1c49fe4e37f771ce9680612b8b9146 | |
| parent | b5066088445be68405dc13d65a41ac9d2de0f784 (diff) | |
| download | aurcade-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.md | 1 | ||||
| -rw-r--r-- | config_example.toml | 2 | ||||
| -rw-r--r-- | docker/Dockerfile | 1 | ||||
| -rw-r--r-- | docker/README.md | 1 | ||||
| -rw-r--r-- | docker/aurcade-favicon.svg | 9 | ||||
| -rw-r--r-- | src/main.rs | 28 |
6 files changed, 40 insertions, 2 deletions
@@ -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![], |