From 39bdc18d9982b21db2ca64e6173d495d37e793ed Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Sun, 31 Dec 2023 01:57:53 +0000 Subject: [PATCH] Retain references across pages --- Cargo.toml | 2 +- src/git.rs | 48 ++++++++++++++++++++++++++++++++++++------------ src/main.rs | 3 +-- src/syntax_highlight.rs | 3 +-- src/database/indexer.rs | 11 ++++++++--- templates/repo/base.html | 11 ++++++----- templates/repo/commit.html | 7 ++++--- templates/repo/file.html | 3 ++- templates/repo/log.html | 7 ++----- templates/repo/tag.html | 3 ++- src/methods/repo/about.rs | 22 ++++++++++++++++++++-- src/methods/repo/commit.rs | 11 +++++++++-- src/methods/repo/diff.rs | 11 ++++++++--- src/methods/repo/log.rs | 21 +++++++++++++++++---- src/methods/repo/refs.rs | 4 +++- src/methods/repo/smart_git.rs | 6 ++++-- src/methods/repo/summary.rs | 4 +++- src/methods/repo/tag.rs | 13 +++++++++---- src/methods/repo/tree.rs | 35 ++++++++++++++++++++++++++--------- templates/repo/macros/link.html | 3 +++ 20 files changed, 154 insertions(+), 74 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 31ecc41..37aabed 100644 --- a/Cargo.toml +++ a/Cargo.toml @@ -29,7 +29,7 @@ once_cell = "1.18" path-clean = "1.0.1" parking_lot = "0.12" -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0", features = ["derive", "rc"] } sha2 = "0.10" syntect = "5" sled = { version = "0.34", features = ["compression"] } diff --git a/src/git.rs b/src/git.rs index e9699d9..bbb1263 100644 --- a/src/git.rs +++ a/src/git.rs @@ -11,8 +11,8 @@ use bytes::{Bytes, BytesMut}; use comrak::{ComrakOptions, ComrakPlugins}; use git2::{ - BranchType, DiffFormat, DiffLineType, DiffOptions, DiffStatsFormat, Email, EmailCreateOptions, - ObjectType, Oid, Signature, + DiffFormat, DiffLineType, DiffOptions, DiffStatsFormat, Email, EmailCreateOptions, ObjectType, + Oid, Signature, }; use moka::future::Cache; use parking_lot::Mutex; @@ -51,7 +51,11 @@ impl Git { #[instrument(skip(self))] - pub async fn repo(self: Arc, repo_path: PathBuf) -> Result> { + pub async fn repo( + self: Arc, + repo_path: PathBuf, + branch: Option>, + ) -> Result> { let repo = tokio::task::spawn_blocking({ let repo_path = repo_path.clone(); move || git2::Repository::open(repo_path) @@ -64,6 +68,7 @@ git: self, cache_key: repo_path, repo: Mutex::new(repo), + branch, })) } } @@ -72,6 +77,7 @@ git: Arc, cache_key: PathBuf, repo: Mutex, + branch: Option>, } impl OpenRepository { @@ -79,7 +85,6 @@ self: Arc, path: Option, tree_id: Option<&str>, - branch: Option, formatted: bool, ) -> Result { let tree_id = tree_id @@ -93,12 +98,11 @@ let mut tree = if let Some(tree_id) = tree_id { repo.find_tree(tree_id) .context("Couldn't find tree with given id")? - } else if let Some(branch) = branch { - let branch = repo.find_branch(&branch, BranchType::Local)?; - branch - .get() + } else if let Some(branch) = &self.branch { + let reference = repo.resolve_reference_from_short_name(branch)?; + reference .peel_to_tree() - .context("Couldn't find tree for branch")? + .context("Couldn't find tree for reference")? } else { let head = repo.head()?; head.peel_to_tree() @@ -175,16 +179,14 @@ } #[instrument(skip(self))] - pub async fn tag_info(self: Arc, tag_name: &str) -> Result { - let reference = format!("refs/tags/{tag_name}"); - let tag_name = tag_name.to_string(); - + pub async fn tag_info(self: Arc) -> Result { tokio::task::spawn_blocking(move || { + let tag_name = self.branch.clone().context("no tag given")?; let repo = self.repo.lock(); let tag = repo - .find_reference(&reference) - .context("Given reference does not exist in repository")? + .find_reference(&format!("refs/tags/{tag_name}")) + .context("Given tag does not exist in repository")? .peel_to_tag() .context("Couldn't get to a tag from the given reference")?; let tag_target = tag.target().context("Couldn't find tagged object")?; @@ -221,8 +223,13 @@ .try_get_with(self.cache_key.clone(), async move { tokio::task::spawn_blocking(move || { let repo = self.repo.lock(); + + let head = if let Some(reference) = &self.branch { + repo.resolve_reference_from_short_name(reference)? + } else { + repo.head().context("Couldn't find HEAD of repository")? + }; - let head = repo.head().context("Couldn't find HEAD of repository")?; let commit = head.peel_to_commit().context( "Couldn't find the commit that the HEAD of the repository refers to", )?; @@ -267,8 +274,13 @@ pub async fn latest_commit(self: Arc) -> Result { tokio::task::spawn_blocking(move || { let repo = self.repo.lock(); + + let head = if let Some(reference) = &self.branch { + repo.resolve_reference_from_short_name(reference)? + } else { + repo.head().context("Couldn't find HEAD of repository")? + }; - let head = repo.head().context("Couldn't find HEAD of repository")?; let commit = head .peel_to_commit() .context("Couldn't find commit HEAD of repository refers to")?; @@ -381,7 +393,7 @@ #[derive(Debug)] pub struct DetailedTag { - pub name: String, + pub name: Arc, pub tagger: Option, pub message: String, pub tagged_object: Option, diff --git a/src/main.rs b/src/main.rs index dc0ee65..75f0f66 100644 --- a/src/main.rs +++ a/src/main.rs @@ -21,8 +21,7 @@ use bat::assets::HighlightingAssets; use clap::Parser; use once_cell::sync::{Lazy, OnceCell}; -use sha2::digest::FixedOutput; -use sha2::Digest; +use sha2::{digest::FixedOutput, Digest}; use sled::Db; use syntect::html::ClassStyle; use tokio::{ diff --git a/src/syntax_highlight.rs b/src/syntax_highlight.rs index 45d9a10..f197351 100644 --- a/src/syntax_highlight.rs +++ a/src/syntax_highlight.rs @@ -1,5 +1,4 @@ -use std::collections::HashMap; -use std::io::Write; +use std::{collections::HashMap, io::Write}; use comrak::adapters::SyntaxHighlighterAdapter; use syntect::{ diff --git a/src/database/indexer.rs b/src/database/indexer.rs index f66dbb8..11ba789 100644 --- a/src/database/indexer.rs +++ a/src/database/indexer.rs @@ -7,7 +7,7 @@ use git2::Sort; use ini::Ini; use time::OffsetDateTime; -use tracing::{info, info_span}; +use tracing::{error, info, info_span}; use crate::database::schema::{ commit::Commit, @@ -89,7 +89,9 @@ let reference = reference.unwrap(); let reference_name = String::from_utf8_lossy(reference.name_bytes()); - if !reference_name.starts_with("refs/heads/") { + if !reference_name.starts_with("refs/heads/") + && !reference_name.starts_with("refs/tags/") + { continue; } @@ -119,7 +121,10 @@ // TODO: only scan revs from the last time we looked let mut revwalk = git_repository.revwalk().unwrap(); revwalk.set_sorting(Sort::REVERSE).unwrap(); - revwalk.push_ref(&reference_name).unwrap(); + if let Err(error) = revwalk.push_ref(&reference_name) { + error!(%error, "Failed to revwalk reference"); + continue; + } let mut i = 0; for rev in revwalk { diff --git a/templates/repo/base.html b/templates/repo/base.html index 30a7456..057217f 100644 --- a/templates/repo/base.html +++ a/templates/repo/base.html @@ -1,3 +1,4 @@ +{% import "macros/link.html" as link %} {% extends "../base.html" %} {% block title %}{{ repo.display() }}{% endblock %} @@ -9,13 +10,13 @@ {% block nav %}