From fcc1871e12c33527e2f766238ca9232a18a4c743 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Sun, 31 Dec 2023 14:28:09 +0000 Subject: [PATCH] Stop garbling binary files on raw display --- 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), +} + +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 %} -
{{ file.content|safe }}
+
+    {%- match file.content -%}
+        {%- when crate::git::Content::Text with (content) -%}
+            {{- content|safe -}}
+        {%- when crate::git::Content::Binary with (_) -%}
+            <binary file not displayed>
+    {%- endmatch -%}
+
{% endblock %} -- libgit2 1.7.2