Expose raw patches
Diff
Cargo.lock | 1 +
Cargo.toml | 1 +
src/git.rs | 20 +++++++++++++++++++-
src/main.rs | 3 ++-
src/methods/repo.rs | 25 +++++++++++++++++++++++++
templates/repo/commit.html | 2 +-
6 files changed, 43 insertions(+), 9 deletions(-)
@@ -1711,6 +1711,7 @@
"axum",
"bat",
"bincode",
"bytes",
"clap",
"futures",
"git2",
@@ -9,6 +9,7 @@
askama = "0.11"
axum = "0.5"
bat = { version = "0.21", default-features = false, features = ["build-assets"] }
bytes = "1.1"
bincode = "1.3"
clap = { version = "3.2", features = ["cargo"] }
futures = "0.3"
@@ -1,5 +1,6 @@
use std::{borrow::Cow, fmt::Write, path::PathBuf, sync::Arc, time::Duration};
use bytes::{Bytes, BytesMut};
use git2::{
BranchType, DiffFormat, DiffLineType, DiffOptions, DiffStatsFormat, ObjectType, Oid, Signature,
};
@@ -270,12 +271,13 @@
let head = repo.head().unwrap();
let commit = head.peel_to_commit().unwrap();
let (diff_output, diff_stats) =
let (diff_plain, diff_output, diff_stats) =
fetch_diff_and_stats(&repo, &commit, &self.git.syntax_set);
let mut commit = Commit::from(commit);
commit.diff_stats = diff_stats;
commit.diff = diff_output;
commit.diff_plain = diff_plain;
commit
})
.await
@@ -294,12 +296,13 @@
let repo = self.repo.lock();
let commit = repo.find_commit(commit).unwrap();
let (diff_output, diff_stats) =
let (diff_plain, diff_output, diff_stats) =
fetch_diff_and_stats(&repo, &commit, &self.git.syntax_set);
let mut commit = Commit::from(commit);
commit.diff_stats = diff_stats;
commit.diff = diff_output;
commit.diff_plain = diff_plain;
Arc::new(commit)
})
@@ -426,6 +429,7 @@
body: String,
pub diff_stats: String,
pub diff: String,
pub diff_plain: Bytes,
}
impl From<git2::Commit<'_>> for Commit {
@@ -440,6 +444,7 @@
body: commit.body().map(ToString::to_string).unwrap_or_default(),
diff_stats: String::with_capacity(0),
diff: String::with_capacity(0),
diff_plain: Bytes::new(),
}
}
}
@@ -479,17 +484,22 @@
repo: &git2::Repository,
commit: &git2::Commit<'_>,
syntax_set: &SyntaxSet,
) -> (String, String) {
) -> (Bytes, String, String) {
let current_tree = commit.tree().unwrap();
let parent_tree = commit.parents().next().and_then(|v| v.tree().ok());
let mut diff_opts = DiffOptions::new();
let diff = repo
let mut diff = repo
.diff_tree_to_tree(
parent_tree.as_ref(),
Some(¤t_tree),
Some(&mut diff_opts),
)
.unwrap();
let mut diff_plain = BytesMut::new();
let email = diff.format_email(1, 1, commit, None).unwrap();
diff_plain.extend_from_slice(&*email);
let diff_stats = diff
.stats()
.unwrap()
@@ -500,7 +510,7 @@
.to_string();
let diff_output = format_diff(&diff, syntax_set);
(diff_output, diff_stats)
(diff_plain.freeze(), diff_output, diff_stats)
}
fn format_file(content: &[u8], extension: &str, syntax_set: &SyntaxSet) -> String {
@@ -12,7 +12,7 @@
use std::time::Duration;
use syntect::html::ClassStyle;
use tower_layer::layer_fn;
use tracing::info;
use tracing::{info, instrument};
use crate::{git::Git, layers::logger::LoggingMiddleware};
@@ -90,6 +90,7 @@
}
}
#[instrument(skip(t))]
pub fn into_response<T: Template>(t: &T) -> Response {
match t.render() {
Ok(body) => {
@@ -6,9 +6,11 @@
};
use askama::Template;
use axum::http::HeaderValue;
use axum::{
extract::Query,
handler::Handler,
http,
http::Request,
response::{IntoResponse, Response},
Extension,
@@ -66,6 +68,7 @@
Some("tree") => BoxCloneService::new(handle_tree.into_service()),
Some("commit") => BoxCloneService::new(handle_commit.into_service()),
Some("diff") => BoxCloneService::new(handle_diff.into_service()),
Some("patch") => BoxCloneService::new(handle_patch.into_service()),
Some("tag") => BoxCloneService::new(handle_tag.into_service()),
Some(v) => {
uri_parts.push(v);
@@ -87,8 +90,6 @@
child_path = Some(reconstructed_path.into_iter().collect::<PathBuf>().clean());
eprintln!("repo path: {:?}", child_path);
BoxCloneService::new(handle_tree.into_service())
} else {
BoxCloneService::new(handle_summary.into_service())
@@ -353,4 +354,24 @@
};
into_response(&DiffView { repo, commit })
}
pub async fn handle_patch(
Extension(RepositoryPath(repository_path)): Extension<RepositoryPath>,
Extension(git): Extension<Arc<Git>>,
Query(query): Query<CommitQuery>,
) -> Response {
let open_repo = git.repo(repository_path).await;
let commit = if let Some(commit) = query.id {
open_repo.commit(&commit).await
} else {
Arc::new(open_repo.latest_commit().await)
};
let headers = [(
http::header::CONTENT_TYPE,
HeaderValue::from_static("text/plain"),
)];
(headers, commit.diff_plain.clone()).into_response()
}
@@ -21,7 +21,7 @@
</tr>
<tr>
<th>commit</th>
<td colspan="2"><pre><a href="/{{ repo.display() }}/commit?id={{ commit.oid() }}" class="no-style">{{ commit.oid() }}</a></pre></td>
<td colspan="2"><pre><a href="/{{ repo.display() }}/commit?id={{ commit.oid() }}" class="no-style">{{ commit.oid() }}</a> <a href="/{{ repo.display() }}/patch?id={{ commit.oid() }}">[patch]</a></pre></td>
</tr>
<tr>
<th>tree</th>