Skip to content
This repository has been archived by the owner on Apr 29, 2024. It is now read-only.

Commit

Permalink
httpd: Return entire files from commit handler
Browse files Browse the repository at this point in the history
Used for syntax highlighting.

Also improves the handling of multiple parent commits, by adding all of
them.
  • Loading branch information
sebastinez authored and cloudhead committed Oct 3, 2023
1 parent 313fc13 commit 35da28d
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 18 deletions.
19 changes: 10 additions & 9 deletions radicle-httpd/src/api/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::path::Path;
use std::str;

use base64::prelude::{Engine, BASE64_STANDARD};
use serde::Serialize;
use serde_json::{json, Value};

Expand Down Expand Up @@ -56,21 +57,21 @@ pub(crate) fn session(session_id: String, session: &Session) -> Value {

/// Returns JSON for a blob with a given `path`.
pub(crate) fn blob<T: AsRef<[u8]>>(blob: &Blob<T>, path: &str) -> Value {
let mut response = json!({
json!({
"binary": blob.is_binary(),
"name": name_in_path(path),
"content": blob_content(blob),
"path": path,
"lastCommit": commit(blob.commit())
});
})
}

if !blob.is_binary() {
match str::from_utf8(blob.content()) {
Ok(content) => response["content"] = content.into(),
Err(err) => return json!({ "error": err.to_string() }),
}
/// Returns a string for the blob content, encoded in base64 if binary.
pub fn blob_content<T: AsRef<[u8]>>(blob: &Blob<T>) -> String {
match str::from_utf8(blob.content()) {
Ok(s) => s.to_owned(),
Err(_) => BASE64_STANDARD.encode(blob.content()),
}

response
}

/// Returns JSON for a tree with a given `path` and `stats`.
Expand Down
146 changes: 137 additions & 9 deletions radicle-httpd/src/api/v1/projects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use axum_auth::AuthBearer;
use hyper::StatusCode;
use radicle_surf::blob::{Blob, BlobRef};
use serde::{Deserialize, Serialize};
use serde_json::json;
use serde_json::{json, Value};
use tower_http::set_header::SetResponseHeaderLayer;

use radicle::cob::{issue, patch, Embed, Label, Uri};
Expand Down Expand Up @@ -233,9 +233,106 @@ async fn commit_handler(
.map(|b| b.refname().to_string())
.collect();

let mut files: HashMap<Oid, Value> = HashMap::new();
diff.files().for_each(|file_diff| match file_diff {
diff::FileDiff::Added(added) => {
if let Ok(blob) = repo.blob(commit.id, &added.path) {
files.insert(
blob.object_id(),
json!({
"binary": blob.is_binary(),
"content": api::json::blob_content(&blob)
}),
);
}
}
diff::FileDiff::Deleted(deleted) => {
commit
.parents
.iter()
.filter_map(|oid| repo.blob(oid, &deleted.path).ok())
.for_each(|blob| {
files.insert(
blob.object_id(),
json!({
"binary": blob.is_binary(),
"content": api::json::blob_content(&blob)
}),
);
});
}
diff::FileDiff::Modified(modified) => {
if let Ok(new_blob) = repo.blob(commit.id, &modified.path) {
files.insert(
new_blob.object_id(),
json!({
"binary": new_blob.is_binary(),
"content": api::json::blob_content(&new_blob)
}),
);
}
commit
.parents
.iter()
.filter_map(|oid| repo.blob(oid, &modified.path).ok())
.for_each(|blob| {
files.insert(
blob.object_id(),
json!({
"binary": blob.is_binary(),
"content": api::json::blob_content(&blob)
}),
);
});
}
diff::FileDiff::Moved(moved) => {
if let (Ok(old_blob), Ok(new_blob)) = (
repo.blob(moved.old.oid, &moved.old_path),
repo.blob(moved.new.oid, &moved.new_path),
) {
files.insert(
old_blob.object_id(),
json!({
"binary": old_blob.is_binary(),
"content": api::json::blob_content(&old_blob)
}),
);
files.insert(
new_blob.object_id(),
json!({
"binary": new_blob.is_binary(),
"content": api::json::blob_content(&new_blob)
}),
);
}
}
diff::FileDiff::Copied(copied) => {
if let (Ok(old_blob), Ok(new_blob)) = (
repo.blob(copied.old.oid, &copied.old_path),
repo.blob(copied.new.oid, &copied.new_path),
) {
files.insert(
old_blob.object_id(),
json!({
"binary": old_blob.is_binary(),
"content": api::json::blob_content(&old_blob)
}),
);
files.insert(
new_blob.object_id(),
json!({
"binary": new_blob.is_binary(),
"content": api::json::blob_content(&new_blob)
}),
);
}
}
});

let response = json!({
"commit": api::json::commit(&commit),
"diff": diff,
"files": files,
"branches": branches
});
Ok::<_, Error>(Json(response))
Expand All @@ -256,24 +353,41 @@ async fn diff_handler(
diff.files().for_each(|file_diff| match file_diff {
diff::FileDiff::Added(added) => {
if let Ok(blob) = repo.blob(commit.id, &added.path) {
files.insert(added.new.oid, blob);
files.insert(blob.object_id(), blob);
}
}
diff::FileDiff::Deleted(deleted) => {
if let Ok(blob) = repo.blob(commit.id, &deleted.path) {
files.insert(deleted.old.oid, blob);
if let Ok(old_blob) = repo.blob(base.id, &deleted.path) {
files.insert(old_blob.object_id(), old_blob);
}
}
diff::FileDiff::Modified(modified) => {
if let (Ok(old_blob), Ok(new_blob)) = (
repo.blob(commit.parents[0], &modified.path),
if let (Ok(new_blob), Ok(old_blob)) = (
repo.blob(commit.id, &modified.path),
repo.blob(base.id, &modified.path),
) {
files.insert(new_blob.object_id(), new_blob);
files.insert(old_blob.object_id(), old_blob);
}
}
diff::FileDiff::Moved(moved) => {
if let (Ok(new_blob), Ok(old_blob)) = (
repo.blob(moved.new.oid, &moved.new_path),
repo.blob(moved.old.oid, &moved.old_path),
) {
files.insert(new_blob.object_id(), new_blob);
files.insert(old_blob.object_id(), old_blob);
}
}
diff::FileDiff::Copied(copied) => {
if let (Ok(new_blob), Ok(old_blob)) = (
repo.blob(copied.new.oid, &copied.new_path),
repo.blob(copied.old.oid, &copied.old_path),
) {
files.insert(modified.old.oid, old_blob);
files.insert(modified.new.oid, new_blob);
files.insert(new_blob.object_id(), new_blob);
files.insert(old_blob.object_id(), old_blob);
}
}
_ => (),
});

let commits = repo
Expand Down Expand Up @@ -1395,6 +1509,20 @@ mod routes {
"deletions": 1
}
},
"files": {
"980a0d5f19a64b4b30a87d4206aade58726b60e3": {
"binary": false,
"content": "Hello World!\n",
},
"1dd5654ca2d2cf9f33b14c92b5ca9e1d21a91ae1": {
"binary": false,
"content": "Hello World from dir1!\n",
},
"82eb77880c693655bce074e3dbbd9fa711dc018b": {
"binary": false,
"content": "Thank you very much!\n",
},
},
"branches": [
"refs/heads/master"
]
Expand Down

0 comments on commit 35da28d

Please sign in to comment.