gitscope
← rgit / 0.1.4 / 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    extract::Query,
  6    http::HeaderValue,
  7    response::{IntoResponse, Response},
  8    Extension,
  9};
 10use bytes::{BufMut, BytesMut};
 11use clap::crate_version;
 12use time::format_description::well_known::Rfc2822;
 13
 14use crate::{
 15    git::Commit,
 16    http, into_response,
 17    methods::{
 18        filters,
 19        repo::{commit::UriQuery, Repository, RepositoryPath, Result},
 20    },
 21    Git,
 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.oid()).unwrap();
 72    writeln!(
 73        data,
 74        "From: {} <{}>",
 75        commit.author().name(),
 76        commit.author().email()
 77    )
 78    .unwrap();
 79
 80    write!(data, "Date: ").unwrap();
 81    let mut writer = data.writer();
 82    commit
 83        .author()
 84        .time()
 85        .format_into(&mut writer, &Rfc2822)
 86        .unwrap();
 87    let mut data = writer.into_inner();
 88    writeln!(data).unwrap();
 89
 90    writeln!(data, "Subject: [PATCH] {}\n", commit.summary()).unwrap();
 91
 92    write!(data, "{}", commit.body()).unwrap();
 93
 94    writeln!(data, "---").unwrap();
 95
 96    data.extend_from_slice(commit.diff_stats.as_bytes());
 97    data.extend_from_slice(b"\n");
 98    data.extend_from_slice(commit.diff.as_bytes());
 99
100    writeln!(data, "--\nrgit {}", crate_version!()).unwrap();
101
102    Ok((headers, data.freeze()).into_response())
103}