gitscope
← rgit / main / src/methods/repo/diff.rs
https://dev.kronoz.win/r/rgit.git
src/methods/repo/diff.rs · Rust
Blame Raw
  1use std::{fmt::Write, sync::Arc};
  2
  3use askama::Template;
  4use axum::{
  5    Extension,
  6    extract::Query,
  7    http::HeaderValue,
  8    response::{IntoResponse, Response},
  9};
 10use bytes::{BufMut, BytesMut};
 11use clap::crate_version;
 12use time::format_description::well_known::Rfc2822;
 13
 14use crate::{
 15    Git,
 16    git::Commit,
 17    http, into_response,
 18    methods::{
 19        filters,
 20        repo::{Repository, RepositoryPath, Result, commit::UriQuery},
 21    },
 22};
 23
 24#[derive(Template)]
 25#[template(path = "repo/diff.html")]
 26pub struct View {
 27    pub repo: Repository,
 28    pub commit: Arc<Commit>,
 29    pub branch: Option<Arc<str>>,
 30}
 31
 32pub async fn handle(
 33    Extension(repo): Extension<Repository>,
 34    Extension(RepositoryPath(repository_path)): Extension<RepositoryPath>,
 35    Extension(git): Extension<Arc<Git>>,
 36    Query(query): Query<UriQuery>,
 37) -> Result<impl IntoResponse> {
 38    let open_repo = git.repo(repository_path, query.branch.clone()).await?;
 39    let commit = if let Some(commit) = query.id {
 40        open_repo.commit(&commit, true).await?
 41    } else {
 42        Arc::new(open_repo.latest_commit(true).await?)
 43    };
 44
 45    Ok(into_response(View {
 46        repo,
 47        commit,
 48        branch: query.branch,
 49    }))
 50}
 51
 52pub async fn handle_plain(
 53    Extension(RepositoryPath(repository_path)): Extension<RepositoryPath>,
 54    Extension(git): Extension<Arc<Git>>,
 55    Query(query): Query<UriQuery>,
 56) -> Result<Response> {
 57    let open_repo = git.repo(repository_path, query.branch).await?;
 58    let commit = if let Some(commit) = query.id {
 59        open_repo.commit(&commit, false).await?
 60    } else {
 61        Arc::new(open_repo.latest_commit(false).await?)
 62    };
 63
 64    let headers = [(
 65        http::header::CONTENT_TYPE,
 66        HeaderValue::from_static("text/plain"),
 67    )];
 68
 69    let mut data = BytesMut::new();
 70
 71    writeln!(data, "From {} Mon Sep 17 00:00:00 2001", commit.get().oid()).unwrap();
 72    writeln!(
 73        data,
 74        "From: {} <{}>",
 75        commit.get().author().name(),
 76        commit.get().author().email()
 77    )
 78    .unwrap();
 79
 80    write!(data, "Date: ").unwrap();
 81    let mut writer = data.writer();
 82    commit
 83        .get()
 84        .author()
 85        .time()
 86        .format_into(&mut writer, &Rfc2822)
 87        .unwrap();
 88    let mut data = writer.into_inner();
 89    writeln!(data).unwrap();
 90
 91    writeln!(data, "Subject: [PATCH] {}\n", commit.get().summary()).unwrap();
 92
 93    write!(data, "{}", commit.get().body()).unwrap();
 94
 95    writeln!(data, "---").unwrap();
 96
 97    data.extend_from_slice(commit.diff_stats.as_bytes());
 98    data.extend_from_slice(b"\n");
 99    data.extend_from_slice(commit.diff.as_bytes());
100
101    writeln!(data, "--\nrgit {}", crate_version!()).unwrap();
102
103    Ok((headers, data.freeze()).into_response())
104}