gitscope
← rgit / 0.1.2 / src/methods/repo/log.rs
https://dev.kronoz.win/r/rgit.git
src/methods/repo/log.rs · Rust
Blame Raw
 1use anyhow::Context;
 2use askama::Template;
 3use axum::{extract::Query, response::Response, Extension};
 4use serde::Deserialize;
 5use yoke::Yoke;
 6
 7use crate::{
 8    database::schema::{commit::YokedCommit, repository::YokedRepository},
 9    into_response,
10    methods::{
11        filters,
12        repo::{Repository, Result, DEFAULT_BRANCHES},
13    },
14};
15
16#[derive(Deserialize)]
17pub struct UriQuery {
18    #[serde(rename = "ofs")]
19    offset: Option<usize>,
20    #[serde(rename = "h")]
21    branch: Option<String>,
22}
23
24#[derive(Template)]
25#[template(path = "repo/log.html")]
26pub struct View<'a> {
27    repo: Repository,
28    commits: Vec<&'a crate::database::schema::commit::Commit<'a>>,
29    next_offset: Option<usize>,
30    branch: Option<String>,
31}
32
33pub async fn handle(
34    Extension(repo): Extension<Repository>,
35    Extension(db): Extension<sled::Db>,
36    Query(query): Query<UriQuery>,
37) -> Result<Response> {
38    let offset = query.offset.unwrap_or(0);
39
40    let repository = crate::database::schema::repository::Repository::open(&db, &*repo)?
41        .context("Repository does not exist")?;
42    let mut commits =
43        get_branch_commits(&repository, &db, query.branch.as_deref(), 101, offset).await?;
44
45    let next_offset = if commits.len() == 101 {
46        commits.pop();
47        Some(offset + 100)
48    } else {
49        None
50    };
51
52    let commits = commits.iter().map(Yoke::get).collect();
53
54    Ok(into_response(&View {
55        repo,
56        commits,
57        next_offset,
58        branch: query.branch,
59    }))
60}
61
62pub async fn get_branch_commits(
63    repository: &YokedRepository,
64    database: &sled::Db,
65    branch: Option<&str>,
66    amount: usize,
67    offset: usize,
68) -> Result<Vec<YokedCommit>> {
69    let reference = branch.map(|branch| format!("refs/heads/{branch}"));
70
71    if let Some(reference) = reference {
72        let commit_tree = repository.get().commit_tree(database, &reference)?;
73        return Ok(commit_tree.fetch_latest(amount, offset).await);
74    }
75
76    for branch in DEFAULT_BRANCHES {
77        let commit_tree = repository.get().commit_tree(database, branch)?;
78        let commits = commit_tree.fetch_latest(amount, offset).await;
79
80        if !commits.is_empty() {
81            return Ok(commits);
82        }
83    }
84
85    Ok(vec![])
86}