From 24fb4b7fea8692752d7a3934670ab5d89b218223 Mon Sep 17 00:00:00 2001 From: Gabriella Gonzalez Date: Thu, 30 Jun 2022 15:45:40 -0700 Subject: [PATCH] Add support for `/log/` API --- cbits/nix.cpp | 30 +++++++++++++++++++++++++++++- src/Main.hs | 36 +++++++++++++++++++++++------------- src/Nix.hsc | 15 +++++++++++++++ 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/cbits/nix.cpp b/cbits/nix.cpp index bb4dd58..654488d 100644 --- a/cbits/nix.cpp +++ b/cbits/nix.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "nix.hh" using namespace nix; @@ -161,7 +162,8 @@ void signString void dumpPath(char const * const hashPart, struct string * const output) { ref store = getStore(); - std::optional storePath= store->queryPathFromHashPart(hashPart); + std::optional storePath = + store->queryPathFromHashPart(hashPart); if (storePath.has_value()) { StringSink sink; @@ -174,4 +176,30 @@ void dumpPath(char const * const hashPart, struct string * const output) { } } +void dumpLog(char const * const hashPart, struct string * const output) { + ref store = getStore(); + + std::optional storePath = + store->queryPathFromHashPart(hashPart); + + if (storePath.has_value()) { + auto subs = getDefaultSubstituters(); + + subs.push_front(store); + + for (auto & sub : subs) { + LogStore * logStore = dynamic_cast(&*sub); + + std::optional log = logStore->getBuildLog(storePath.value()); + + if (log.has_value()) { + copyString(log.value(), output); + } else { + *output = emptyString; + } + } + } else { + *output = emptyString; + } +} } diff --git a/src/Main.hs b/src/Main.hs index 4b140da..2b5c0f2 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -251,7 +251,7 @@ makeApplication ApplicationOptions{..} request respond = do Nothing -> noSuchPath Just storePath -> return storePath - PathInfo{ narSize, narHash } <- liftIO (Nix.queryPathInfo storePath) + PathInfo{ narHash } <- liftIO (Nix.queryPathInfo storePath) Monad.unless (all (narHash ==) maybeExpectedNarHash) do let headers = [ ("Content-Type", "text/plain") ] @@ -273,21 +273,31 @@ makeApplication ApplicationOptions{..} request respond = do Nothing -> noSuchPath Just bytes -> return bytes - let contentLength = - ( ByteString.Lazy.toStrict - . Builder.toLazyByteString - . Builder.word64Dec - ) narSize + let lazyBytes = ByteString.Lazy.fromStrict bytes - let headers = - [ ("Content-Type", "text/plain") - , ("Content-Length", contentLength) - ] - - let builder = Builder.byteString bytes + let headers = [ ("Content-Type", "text/plain") ] let response = - Wai.responseBuilder Types.status200 headers builder + Wai.responseLBS Types.status200 headers lazyBytes + + done response + + | Just suffix <- ByteString.stripPrefix "/log/" rawPath + , 32 <= ByteString.length suffix -> do + let hashPart = ByteString.take 32 suffix + + maybeBytes <- liftIO (Nix.dumpLog hashPart) + + bytes <- case maybeBytes of + Nothing -> noSuchPath + Just bytes -> return bytes + + let lazyBytes = ByteString.Lazy.fromStrict bytes + + let headers = [ ("Content-Type", "text/plain") ] + + let response = + Wai.responseLBS Types.status200 headers lazyBytes done response diff --git a/src/Nix.hsc b/src/Nix.hsc index 6adbbe3..94b7ddf 100644 --- a/src/Nix.hsc +++ b/src/Nix.hsc @@ -275,3 +275,18 @@ dumpPath hashPart = do if data_ == Foreign.nullPtr then return Nothing else fmap Just (fromString_ string_) + +foreign import ccall "dumpLog" dumpLog_ + :: CString -> Ptr String_ -> IO () + +dumpLog :: ByteString -> IO (Maybe ByteString) +dumpLog hashPart = do + ByteString.useAsCString hashPart \cHashPart -> do + Foreign.alloca \output -> do + let open = dumpLog_ cHashPart output + let close = freeString output + Exception.bracket_ open close do + string_@String_{ data_} <- peek output + if data_ == Foreign.nullPtr + then return Nothing + else fmap Just (fromString_ string_)