Commit 33e1a764b90ab2413989896c072e1c3e63a83308 Parent: 5983ebce640f9cba7f9d19cf47ab9e6ab1921263 Author: mcol <mcol@posteo.net> Date: 2021-12-01 21:09:50 +0000 Committer: mcol <mcol@posteo.net> Committed: 2021-12-01 21:18:25 +0000 Expose whether a file is considered binary by git Closes #14
test/test.sh Modified
@@ -33,11 +33,13 @@ "index.html" "link.html" "style.css" + "so_called_binary_file" "static/a_nice_file" "gitserve/index.html" "gitserve/commit/0292014748caae952bbc8dd6225680d83c0a5135.html" "gitserve/file/test.expected.gitserve.file.html" "gitserve/file/test.templates.style.css.html" + "gitserve/file/test.templates.so_called_binary_file.html" ) stack run -- -c test/config.dhall -q || exit 1
test/templates/style.css Modified
@@ -1 +1 @@ -👄 +html
test/templates/so_called_binary_file Added
@@ -0,0 +1 @@
+👄
test/templates/repo/file.html Modified
@@ -6,7 +6,8 @@ file: {{ file }} file.path: {{ file.path }} file.href: {{ file.href }} -file.contents: {{ file.contents }} +file.contents: {% if file.is_binary %}(binary){% else %}{{ file.contents }}{% endif %} + file.mode: {{ file.mode }} file.mode_octal: {{ file.mode_octal }} file.mode_symbolic: {{ file.mode_symbolic }}
test/expected/style.css Modified
@@ -1 +1 @@ -👄 +html
test/expected/so_called_binary_file Added
@@ -0,0 +1 @@
+👄
test/expected/gitserve/file/test.templates.style.css.html Modified
@@ -3,7 +3,7 @@ file: test/templates/style.css file.path: test/templates/style.css file.href: test.templates.style.css.html -file.contents: 👄 +file.contents: html file.mode: Plain file.mode_octal: 00644 file.mode_symbolic: -rw-r--r--
test/expected/gitserve/file/test.templates.so_called_binary_file.html Added
@@ -0,0 +1,22 @@ +test/templates/so_called_binary_file +scope: file +file: test/templates/so_called_binary_file +file.path: test/templates/so_called_binary_file +file.href: test.templates.so_called_binary_file.html +file.contents: (binary) +file.mode: Plain +file.mode_octal: 00644 +file.mode_symbolic: -rw-r--r-- +if file.is_directory then "directory" else "file": "file" + +file scope also should have data from repo scope available: +host: https://github.com/m-col/gitserve +repos: gitserve +name: gitserve +description: 🐙 Templated web page generator for your git repositories +commits: (skipped) +tree: (skipped) +tags: 1 +branches: 1 +readme.path: README.rst +license.path: LICENSE
test/expected/gitserve/file/test.expected.gitserve.file.html Modified
@@ -3,7 +3,7 @@ file: test/expected/gitserve/file file.path: test/expected/gitserve/file file.href: test.expected.gitserve.file.html -file.contents: ["test/expected/gitserve/file/test.expected.gitserve.file.html","test/expected/gitserve/file/test.templates.style.css.html"] +file.contents: ["test/expected/gitserve/file/test.expected.gitserve.file.html","test/expected/gitserve/file/test.templates.so_called_binary_file.html","test/expected/gitserve/file/test.templates.style.css.html"] file.mode: Directory file.mode_octal: 40000 file.mode_symbolic: drwxr-xr-x
templates/stagit/repo/file.html Modified
@@ -29,11 +29,13 @@ </tbody> </table> {% else %} - <pre id="blob"> -{% for line in split(file.contents, '\n') %} + {% if file.is_binary %} + (File is binary) + {% else %} +<pre id="blob">{% for line in split(file.contents, '\n') %} <a href="#l{{ loop.index }}" class="line" id="l{{ loop.index }}">{{ printf("%7v", loop.index) }}</a> {{ line }} -{% endfor %} +{% endfor %}</pre> + {% endif %} {% endif %} - </pre> </div> {% endblock %}
templates/docs/repo/file.html Modified
@@ -24,10 +24,12 @@ </tbody> </table> {% else %} - <pre id="blob"> -{% for line in split(file.contents, '\n') %} + {% if file.is_binary %} + (File is binary) + {% else %} +<pre id="blob">{% for line in split(file.contents, '\n') %} <a href="#l{{ loop.index }}" class="line" id="l{{ loop.index }}">{{ printf("%5v", loop.index) }}</a> {{ line }} -{% endfor %} +{% endfor %}</pre> + {% endif %} {% endif %} -</pre> {% endblock %}
templates/base/repo/file.html Modified
@@ -24,10 +24,12 @@ </tbody> </table> {% else %} - <pre> -{% for line in split(file.contents, '\n') %} + {% if file.is_binary %} + (File is binary) + {% else %} +<pre>{% for line in split(file.contents, '\n') %} <a href="#l{{ loop.index }}" class="line" id="l{{ loop.index }}">{{ printf("%5v", loop.index) }}</a> {{ line }} -{% endfor %} +{% endfor %}</pre> +{% endif %} {% endif %} -</pre> {% endblock %}
src/Types.hs Modified
@@ -10,6 +10,10 @@ module Types where +import Bindings.Libgit2.Blob (c'git_blob_is_binary, c'git_blob_lookup) +import Control.Monad (when) +import Control.Monad.Catch (throwM) +import Control.Monad.IO.Class (liftIO) import Control.Monad.Trans.Reader (ReaderT) import Data.ByteString.UTF8 (toString) import Data.Default (def) @@ -19,8 +23,10 @@ import qualified Data.Text as T import Data.Text.Encoding (decodeUtf8With) import Data.Text.Encoding.Error (lenientDecode) +import Foreign (peek) +import Foreign.ForeignPtr (mallocForeignPtr, withForeignPtr) import Git -import Git.Libgit2 (LgRepo) +import Git.Libgit2 (LgRepo, getOid, repoObj) import Path (Abs, Dir, Path, dirname, toFilePath) import System.FilePath (takeFileName) import Text.Ginger.GVal (GVal, ToGVal, asBoolean, asHtml, asList, asLookup, asText, toGVal) @@ -106,7 +112,7 @@ , treeFileMode :: TreeEntryMode } -data TreeFileContents = FileContents Text | FolderContents [TreeFile] +data TreeFileContents = BinaryContents | FileContents Text | FolderContents [TreeFile] data TreeEntryMode = ModeDirectory | ModePlain | ModeExecutable | ModeSymlink | ModeSubmodule deriving stock (Show) @@ -136,6 +142,24 @@ modeToSymbolic ModeSubmodule = "git-module" {- +This +-} +getBlobContents :: BlobOid LgRepo -> ReaderT LgRepo IO TreeFileContents +getBlobContents oid = do + repo <- getRepository + blobPtr <- liftIO mallocForeignPtr + isBinary <- liftIO . withForeignPtr (repoObj repo) $ \repoPtr -> + withForeignPtr blobPtr $ \blobPtr' -> + withForeignPtr (getOid . untag $ oid) $ \oidPtr -> do + r1 <- c'git_blob_lookup blobPtr' repoPtr oidPtr + when (r1 < 0) $ throwM (Git.BackendError "Could not lookup blob") + c'git_blob_is_binary =<< peek blobPtr' + + if toEnum . fromEnum $ isBinary -- This reads weird, but it goes CInt, to Int, to Bool. + then return BinaryContents + else FileContents . decodeUtf8With lenientDecode <$> catBlob oid + +{- GVal implementations for data definitions above, allowing commits to be rendered in Ginger templates. -} @@ -151,6 +175,7 @@ instance ToGVal RunRepo TreeFileContents where toGVal :: TreeFileContents -> GVal RunRepo + toGVal BinaryContents = def toGVal (FileContents text) = toGVal . strip $ text toGVal (FolderContents treeFiles) = def @@ -168,13 +193,19 @@ "mode" -> Just . toGVal . drop 4 . show . treeFileMode $ treefile "mode_octal" -> Just . toGVal . modeToOctal . treeFileMode $ treefile "mode_symbolic" -> Just . toGVal . modeToSymbolic . treeFileMode $ treefile + "is_binary" -> Just . toGVal . treeFileIsBinary $ treefile "is_directory" -> Just . toGVal . treeFileIsDirectory $ treefile _ -> Nothing +treeFileIsBinary :: TreeFile -> Bool +treeFileIsBinary treefile = case treeFileContents treefile of + BinaryContents -> True + _ -> False + treeFileIsDirectory :: TreeFile -> Bool treeFileIsDirectory treefile = case treeFileContents treefile of - FileContents _ -> False FolderContents _ -> True + _ -> False {- Get the name of a tree file path's HTML file.
src/Repositories.hs Modified
@@ -163,7 +163,7 @@ prependParent parent (path, entry) = (mconcat [parent, "/", path], entry) getEntryContents :: (TreeFilePath, TreeEntry LgRepo) -> ReaderT LgRepo IO TreeFileContents -getEntryContents (_, BlobEntry oid _) = FileContents . decodeUtf8With lenientDecode <$> catBlob oid +getEntryContents (_, BlobEntry oid _) = getBlobContents oid getEntryContents (path, TreeEntry oid) = FolderContents <$> getTree' path oid getEntryContents (_, CommitEntry oid) = return . FileContents . pack . show . untag $ oid
gitserve.cabal Modified
@@ -25,12 +25,14 @@ , data-default , dhall , directory + , exceptions , extra , file-embed , filepath , ginger >= 0.10.4.0 , gitlib , gitlib-libgit2 + , hlibgit2 , optparse-applicative , path , path-io >= 1.3.0
DOCUMENTATION.md Modified
@@ -181,6 +181,7 @@ | | mode\_octal | Mode in octal form e.g. "00644" for plain files. | | | mode\_symbolic | Mode in symbolic form e.g. ""-rw-r--r--" for plain files.| | | is\_directory | A boolean, useful for ginger conditionals. | +| | is\_binary | A boolean, tells you if the contents can be rendered. | | ref | name | The tag or branch name. | | | commit | The commit pointed to by the tag or branch. |