c09e19f4
- commit
- c09e19f45e121b4d0180f1834a122becc716710a
- parent
- author
- Christopher K. Schmitt <me@shmish.dev>
- date
- 2026-07-29
- committer
- Christopher K. Schmitt <me@shmish.dev>
- date
- 2026-07-29
- changes
- 9
- insertions
- 95
- deletions
- 84
Msrc/error.rs
~ };~~ match tpl.render() {- Ok(html) => ([(header::CONTENT_TYPE, "text/html; charset=utf-8")], html).into_response(),+ Ok(html) => {+ ([(header::CONTENT_TYPE, "text/html; charset=utf-8")], html).into_response()+ }~ Err(_) => (status, self.to_string()).into_response(),~ }~ }
Msrc/routes.rs
~~/// Serves the favicon (SVG or ICO bytes loaded at startup).~async fn favicon() -> impl IntoResponse {- (- [(header::CONTENT_TYPE, "image/svg+xml")],- crate::favicon(),- )+ ([(header::CONTENT_TYPE, "image/svg+xml")], crate::favicon())~}~~/// Builds the application router with all routes and shared state attached.
Mstatic/base.css
~ }~~ .commit-date { flex-shrink: 0; color: var(--secondary); }- .commit-ref-branch { color: var(--blue); }- .commit-ref-tag { color: var(--violet); }+ .commit-ref.commit-ref-branch { color: var(--blue); }+ .commit-ref.commit-ref-tag { color: var(--violet); }~~ /* === Diff stat === */~
~ .st-type { color: var(--violet); }~ .st-constant { color: var(--orange); }~ .st-function { color: var(--cyan); }- .st-variable { color: var(--primary); }+ .st-variable { color: var(--cyan); }~ .st-operator { color: var(--primary); }~ .st-entity { color: var(--violet); }~ .st-attribute { color: var(--yellow); }
~ .st-italic { font-style: italic; }~ .st-link { color: var(--blue); }~ .st-raw { color: var(--green); }- .st-meta { color: var(--secondary); }+ .st-meta { color: var(--primary); }~ .st-section { color: var(--blue); }~ .st-underline { text-decoration: underline; }~ .st-linenum { display: inline-block; }
Msrc/routes/archive.rs
~struct ArchiveConfig {~ content_type: &'static str,~ extension: &'static str,+ git_format: &'static str,+ uses_xz: bool,~}~-/// Returns the content type and file extension for a given format string.+/// Returns the archive configuration for a given format string.~/// Returns `None` for unsupported formats.~fn archive_config(format: &str) -> Option<ArchiveConfig> {~ match format {~ "tar.gz" | "tgz" => Some(ArchiveConfig {~ content_type: "application/gzip",~ extension: "tar.gz",+ git_format: "tar.gz",+ uses_xz: false,~ }),~ "tar.xz" | "txz" => Some(ArchiveConfig {~ content_type: "application/x-xz",~ extension: "tar.xz",+ git_format: "tar",+ uses_xz: true,~ }),~ "zip" => Some(ArchiveConfig {~ content_type: "application/zip",~ extension: "zip",+ git_format: "zip",+ uses_xz: false,~ }),~ _ => None,~ }
~~ let repo_path_str = repo_path.to_string_lossy().into_owned();~ let archive_ref = params.ref_.clone();+ let ref_for_closure = archive_ref.clone();~- let uses_xz = matches!(params.format.as_str(), "tar.xz" | "txz");- let git_format = match params.format.as_str() {- "zip" => "zip",- _ => "tar.gz",- };- let ref_for_archive = archive_ref.clone();-~ let (stdout, success, stderr) = spawn_blocking(move || {- if uses_xz {- run_archive_xz(&repo_path_str, &ref_for_archive)+ if cfg.uses_xz {+ run_archive_xz(&repo_path_str, &ref_for_closure)~ } else {- run_archive(&repo_path_str, git_format, &ref_for_archive)+ run_archive(&repo_path_str, cfg.git_format, &ref_for_closure)~ }~ })~ .await- .map_err(|e| Error::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?;+ .map_err(|e| Error::Io(std::io::Error::other(e)))?;~~ if !success {~ return Err(Error::GitCorrupt(format!("archive failed: {stderr}")));
Msrc/routes/blame.rs
~];~~fn commit_color(sha: &str) -> &'static str {- let hash: u64 = sha.bytes().fold(0u64, |acc, b| acc.wrapping_mul(31).wrapping_add(b as u64));+ let hash: u64 = sha+ .bytes()+ .fold(0u64, |acc, b| acc.wrapping_mul(31).wrapping_add(b as u64));~ COLORS[hash as usize % COLORS.len()]~}~
Msrc/routes/commit.rs
~ }~~ for parent in commit.parents.iter().skip(1) {- if active.iter().any(|s| *s == Some(parent.as_str())) {+ if active.contains(&Some(parent.as_str())) {~ continue;~ }~ match active.iter().position(|s| s.is_none()) {
~ DiffLineKind::Remove => ("-".into(), "-".into()),~ };~- if matches!(kind, DiffLineKind::Add) {- *self.file_added += 1;- } else if matches!(kind, DiffLineKind::Remove) {- *self.file_removed += 1;+ match kind {+ DiffLineKind::Add => *self.file_added += 1,+ DiffLineKind::Remove => *self.file_removed += 1,+ _ => {}~ }~~ hunk.push(DiffLine {
~ .resource_cache~ .options~ .skip_internal_diff_if_external_is_configured = false;- if let Ok(prep) = platform.resource_cache.prepare_diff() {- if let Operation::InternalDiff { algorithm } = prep.operation {- let input = prep.interned_input();- let collector = DiffHunkCollector {- hunks: &mut hunks,- file_added: &mut added,- file_removed: &mut removed,- };- let sink = UnifiedDiff::new(&input, collector, ContextSize::symmetrical(3));- let _ = gix::diff::blob::diff(algorithm, &input, sink);- }+ if let Ok(prep) = platform.resource_cache.prepare_diff()+ && let Operation::InternalDiff { algorithm } = prep.operation+ {+ let input = prep.interned_input();+ let collector = DiffHunkCollector {+ hunks: &mut hunks,+ file_added: &mut added,+ file_removed: &mut removed,+ };+ let sink = UnifiedDiff::new(&input, collector, ContextSize::symmetrical(3));+ let _ = gix::diff::blob::diff(algorithm, &input, sink);~ }~ }~
Msrc/routes/repo.rs
~ })~ .collect();~- tags.sort_by(|a, b| b.timestamp.cmp(&a.timestamp));+ tags.sort_by_key(|b| std::cmp::Reverse(b.timestamp));~~ // Same double-flatten pattern as tags above.~ let mut branches: Vec<BranchSummary> = platform
~ id,~ }) => {~ let dest_url = match &head_sha {- Some(sha) if is_relative_url(&dest_url) => {- format!("{}/{}/commits/{}/raw/{}", crate::base_url(), name, sha, dest_url).into()- }+ Some(sha) if is_relative_url(&dest_url) => format!(+ "{}/{}/commits/{}/raw/{}",+ crate::base_url(),+ name,+ sha,+ dest_url+ )+ .into(),~ _ => dest_url,~ };~ Event::Start(Tag::Image {
~ id,~ }) => {~ let dest_url = match &head_sha {- Some(sha) if is_relative_url(&dest_url) => {- format!("{}/{}/commits/{}/raw/{}", crate::base_url(), name, sha, dest_url).into()- }+ Some(sha) if is_relative_url(&dest_url) => format!(+ "{}/{}/commits/{}/tree/{}",+ crate::base_url(),+ name,+ sha,+ dest_url+ )+ .into(),~ _ => dest_url,~ };~ Event::Start(Tag::Link {
Msrc/routes/tag.rs
~ })~ .collect();~- tags.sort_by(|a, b| b.timestamp.cmp(&a.timestamp));+ tags.sort_by_key(|b| std::cmp::Reverse(b.timestamp));~~ Ok(TagList { repo, tags })~}
~ .map_err(|_| Error::NotFound(format!("tag {tag_name}")))?;~~ // Extract annotation info if this is an annotated tag.- let (tagger, tag_date, message) = match reference.peel_to_tag().ok() {- None => (None, None, None),- Some(t) => match t.decode() {- Err(_) => (None, None, None),- Ok(decoded) => {- let sig = decoded.tagger().ok().flatten();- let tagger = sig.as_ref().map(|s| s.name.to_str_lossy().into_owned());- let tag_date = sig.as_ref().and_then(|s| {- // Parse the raw "seconds offset" time string.- let mut parts = s.time.splitn(2, ' ');- let seconds: i64 = parts.next()?.parse().ok()?;- let offset_str = parts.next().unwrap_or("+0000");- let sign = if offset_str.starts_with('-') {- -1i32- } else {- 1- };- let hhmm = offset_str.trim_start_matches(['+', '-']);- let h: i32 = hhmm.get(..2)?.parse().ok()?;- let m: i32 = hhmm.get(2..4)?.parse().ok()?;- let offset_secs = sign * (h * 3600 + m * 60);- let zone = jiff::tz::TimeZone::fixed(- jiff::tz::Offset::from_seconds(offset_secs).ok()?,- );- jiff::Timestamp::from_second(seconds)- .map(|ts| ts.to_zoned(zone).date().to_string())- .ok()- });- let message = decoded.message.to_str_lossy().trim().to_string();- let message = if message.is_empty() {- None+ let (tagger, tag_date, message) = reference+ .peel_to_tag()+ .ok()+ .and_then(|t| {+ let decoded = t.decode().ok()?;+ let sig = decoded.tagger().ok().flatten();+ let tagger = sig.as_ref().map(|s| s.name.to_str_lossy().into_owned());+ let tag_date = sig.as_ref().and_then(|s| {+ // Parse the raw "seconds offset" time string.+ let mut parts = s.time.splitn(2, ' ');+ let seconds: i64 = parts.next()?.parse().ok()?;+ let offset_str = parts.next().unwrap_or("+0000");+ let sign = if offset_str.starts_with('-') {+ -1i32~ } else {- Some(message)+ 1~ };- (tagger, tag_date, message)- }- },- };+ let hhmm = offset_str.trim_start_matches(['+', '-']);+ let h: i32 = hhmm.get(..2)?.parse().ok()?;+ let m: i32 = hhmm.get(2..4)?.parse().ok()?;+ let offset_secs = sign * (h * 3600 + m * 60);+ let zone =+ jiff::tz::TimeZone::fixed(jiff::tz::Offset::from_seconds(offset_secs).ok()?);+ jiff::Timestamp::from_second(seconds)+ .map(|ts| ts.to_zoned(zone).date().to_string())+ .ok()+ });+ let message = decoded.message.to_str_lossy().trim().to_string();+ let message = if message.is_empty() {+ None+ } else {+ Some(message)+ };+ Some((tagger, tag_date, message))+ })+ .unwrap_or((None, None, None));~~ let commit = reference~ .peel_to_commit()
Msrc/routes/tree.rs
~use crate::routes::{AppState, RepoName};~~/// Syntax definitions loaded once and reused for every file view.-static SYNTAX_SET: LazyLock<SyntaxSet> = LazyLock::new(|| SyntaxSet::load_defaults_newlines());+static SYNTAX_SET: LazyLock<SyntaxSet> = LazyLock::new(SyntaxSet::load_defaults_newlines);~~/// Path parameters for the tree page routes.~#[derive(Deserialize)]
~ };~~ let b = crate::base_url();- let breadcrumbs = build_breadcrumbs(&b, &name, ¶ms.sha, &resolved_path);+ let breadcrumbs = build_breadcrumbs(b, &name, ¶ms.sha, &resolved_path);~ let raw_url = if resolved_path.is_empty() {~ String::new()~ } else {