🏡 index : ~doyle/rgit.git

author Jordan Doyle <jordan@doyle.la> 2023-12-31 14:28:09.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2023-12-31 14:28:09.0 +00:00:00
commit
fcc1871e12c33527e2f766238ca9232a18a4c743 [patch]
tree
d57bffb5adf9fedc0ef519fb97d7b8669df2980f
parent
7c5415eb95b530bd896f0ae0432d5e8d049f8e76
download
fcc1871e12c33527e2f766238ca9232a18a4c743.tar.gz

Stop garbling binary files on raw display



Diff

 src/git.rs               | 47 ++++++++++++++++++++++++++++++++++++++++++-----
 src/methods/repo/tree.rs | 10 +---------
 templates/repo/file.html |  9 ++++++++-
 3 files changed, 51 insertions(+), 15 deletions(-)

diff --git a/src/git.rs b/src/git.rs
index 5635cba..27f4e05 100644
--- a/src/git.rs
+++ b/src/git.rs
@@ -8,6 +8,7 @@ use std::{
};

use anyhow::{anyhow, Context, Result};
use axum::response::IntoResponse;
use bytes::{BufMut, Bytes, BytesMut};
use comrak::{ComrakOptions, ComrakPlugins};
use git2::{
@@ -126,10 +127,15 @@ impl OpenRepository {
                        .extension()
                        .or_else(|| path.file_name())
                        .map_or_else(|| Cow::Borrowed(""), OsStr::to_string_lossy);
                    let content = if formatted {
                        format_file(blob.content(), &extension, &self.git.syntax_set)?
                    } else {
                        String::from_utf8_lossy(blob.content()).to_string()
                    let content = match (formatted, blob.is_binary()) {
                        (true, true) => Content::Binary(vec![]),
                        (true, false) => Content::Text(
                            format_file(blob.content(), &extension, &self.git.syntax_set)?.into(),
                        ),
                        (false, true) => Content::Binary(blob.content().to_vec()),
                        (false, false) => Content::Text(
                            String::from_utf8_lossy(blob.content()).to_string().into(),
                        ),
                    };

                    return Ok(PathDestination::File(FileWithContent {
@@ -464,7 +470,38 @@ pub struct File {
#[derive(Debug)]
pub struct FileWithContent {
    pub metadata: File,
    pub content: String,
    pub content: Content,
}

#[derive(Debug)]
pub enum Content {
    Text(Cow<'static, str>),
    Binary(Vec<u8>),
}

impl IntoResponse for Content {
    fn into_response(self) -> axum::response::Response {
        use axum::http;

        match self {
            Self::Text(t) => {
                let headers = [(
                    http::header::CONTENT_TYPE,
                    http::HeaderValue::from_static("text/plain; charset=UTF-8"),
                )];

                (headers, t).into_response()
            }
            Self::Binary(b) => {
                let headers = [(
                    http::header::CONTENT_TYPE,
                    http::HeaderValue::from_static("application/octet-stream"),
                )];

                (headers, b).into_response()
            }
        }
    }
}

#[derive(Debug)]
diff --git a/src/methods/repo/tree.rs b/src/methods/repo/tree.rs
index 0fc5f7d..1f1ba6c 100644
--- a/src/methods/repo/tree.rs
+++ b/src/methods/repo/tree.rs
@@ -6,7 +6,6 @@ use std::{
use askama::Template;
use axum::{
    extract::Query,
    http,
    response::{IntoResponse, Response},
    Extension,
};
@@ -86,14 +85,7 @@ pub async fn handle(
                branch: query.branch.clone(),
                query,
            }),
            PathDestination::File(file) if query.raw => {
                let headers = [(
                    http::header::CONTENT_TYPE,
                    http::HeaderValue::from_static("text/plain"),
                )];

                (headers, file.content).into_response()
            }
            PathDestination::File(file) if query.raw => file.content.into_response(),
            PathDestination::File(file) => into_response(&FileView {
                repo,
                file,
diff --git a/templates/repo/file.html b/templates/repo/file.html
index 5e465de..2d7a65e 100644
--- a/templates/repo/file.html
+++ b/templates/repo/file.html
@@ -13,5 +13,12 @@
{% endblock %}

{% block content %}
<pre>{{ file.content|safe }}</pre>
<pre>
    {%- match file.content -%}
        {%- when crate::git::Content::Text with (content) -%}
            {{- content|safe -}}
        {%- when crate::git::Content::Binary with (_) -%}
            &lt;binary file not displayed&gt;
    {%- endmatch -%}
</pre>
{% endblock %}