Add support for /log/ API

This commit is contained in:
Gabriella Gonzalez 2022-06-30 15:45:40 -07:00
parent 3bd298c02a
commit 24fb4b7fea
3 changed files with 67 additions and 14 deletions

View File

@ -1,6 +1,7 @@
#include <cstddef> #include <cstddef>
#include <cstdlib> #include <cstdlib>
#include <nix/store-api.hh> #include <nix/store-api.hh>
#include <nix/log-store.hh>
#include "nix.hh" #include "nix.hh"
using namespace nix; using namespace nix;
@ -161,7 +162,8 @@ void signString
void dumpPath(char const * const hashPart, struct string * const output) { void dumpPath(char const * const hashPart, struct string * const output) {
ref<Store> store = getStore(); ref<Store> store = getStore();
std::optional<StorePath> storePath= store->queryPathFromHashPart(hashPart); std::optional<StorePath> storePath =
store->queryPathFromHashPart(hashPart);
if (storePath.has_value()) { if (storePath.has_value()) {
StringSink sink; 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> store = getStore();
std::optional<StorePath> storePath =
store->queryPathFromHashPart(hashPart);
if (storePath.has_value()) {
auto subs = getDefaultSubstituters();
subs.push_front(store);
for (auto & sub : subs) {
LogStore * logStore = dynamic_cast<LogStore *>(&*sub);
std::optional<std::string> log = logStore->getBuildLog(storePath.value());
if (log.has_value()) {
copyString(log.value(), output);
} else {
*output = emptyString;
}
}
} else {
*output = emptyString;
}
}
} }

View File

@ -251,7 +251,7 @@ makeApplication ApplicationOptions{..} request respond = do
Nothing -> noSuchPath Nothing -> noSuchPath
Just storePath -> return storePath Just storePath -> return storePath
PathInfo{ narSize, narHash } <- liftIO (Nix.queryPathInfo storePath) PathInfo{ narHash } <- liftIO (Nix.queryPathInfo storePath)
Monad.unless (all (narHash ==) maybeExpectedNarHash) do Monad.unless (all (narHash ==) maybeExpectedNarHash) do
let headers = [ ("Content-Type", "text/plain") ] let headers = [ ("Content-Type", "text/plain") ]
@ -273,21 +273,31 @@ makeApplication ApplicationOptions{..} request respond = do
Nothing -> noSuchPath Nothing -> noSuchPath
Just bytes -> return bytes Just bytes -> return bytes
let contentLength = let lazyBytes = ByteString.Lazy.fromStrict bytes
( ByteString.Lazy.toStrict
. Builder.toLazyByteString
. Builder.word64Dec
) narSize
let headers = let headers = [ ("Content-Type", "text/plain") ]
[ ("Content-Type", "text/plain")
, ("Content-Length", contentLength)
]
let builder = Builder.byteString bytes
let response = 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 done response

View File

@ -275,3 +275,18 @@ dumpPath hashPart = do
if data_ == Foreign.nullPtr if data_ == Foreign.nullPtr
then return Nothing then return Nothing
else fmap Just (fromString_ string_) 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_)