use std::sync::Arc;use anyhow::Context;use askama::Template;use axum::{extract::Query, response::IntoResponse, Extension};use serde::Deserialize;use crate::{database::schema::{commit::YokedCommit, repository::YokedRepository},into_response,methods::{filters,repo::{Repository, Result, DEFAULT_BRANCHES},},};#[derive(Deserialize)]pub struct UriQuery {#[serde(rename = "ofs")]offset: Option<u64>,#[serde(rename = "h")]branch: Option<String>,}#[derive(Template)]#[template(path = "repo/log.html")]pub struct View {repo: Repository,commits: Vec<YokedCommit>,next_offset: Option<u64>,branch: Option<String>,}pub async fn handle(Extension(repo): Extension<Repository>,Extension(db): Extension<Arc<rocksdb::DB>>,Query(query): Query<UriQuery>,) -> Result<impl IntoResponse> {tokio::task::spawn_blocking(move || {let offset = query.offset.unwrap_or(0);let repository = crate::database::schema::repository::Repository::open(&db, &*repo)?.context("Repository does not exist")?;let mut commits =get_branch_commits(&repository, &db, query.branch.as_deref(), 101, offset)?;let next_offset = if commits.len() == 101 {commits.pop();Some(offset + 100)} else {None};Ok(into_response(View {repo,commits,next_offset,branch: query.branch,}))}).await.context("Failed to attach to tokio task")?}pub fn get_branch_commits(repository: &YokedRepository,database: &Arc<rocksdb::DB>,branch: Option<&str>,amount: u64,offset: u64,) -> Result<Vec<YokedCommit>> {if let Some(reference) = branch {let commit_tree = repository.get().commit_tree(database.clone(), &format!("refs/heads/{reference}"));let commit_tree = commit_tree.fetch_latest(amount, offset)?;if !commit_tree.is_empty() {return Ok(commit_tree);}let tag_tree = repository.get().commit_tree(database.clone(), &format!("refs/tags/{reference}"));let tag_tree = tag_tree.fetch_latest(amount, offset)?;return Ok(tag_tree);}for branch in repository.get().default_branch.as_deref().into_iter().chain(DEFAULT_BRANCHES.into_iter()){let commit_tree = repository.get().commit_tree(database.clone(), branch);let commits = commit_tree.fetch_latest(amount, offset)?;if !commits.is_empty() {return Ok(commits);}}Ok(vec![])}