libstore: return transfer metadata from download

as promised earlier. nothing uses it yet, but just you wait.

Change-Id: I77d185578d96c2134b756d20f2fcf1c02de0da6f
This commit is contained in:
eldritch horrors 2024-10-28 18:59:43 +01:00
parent 14eff10fe4
commit c68f0cdf00
6 changed files with 14 additions and 11 deletions

View file

@ -36,7 +36,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData,
auto fetch = [&](const std::string & url) { auto fetch = [&](const std::string & url) {
auto raw = fileTransfer->download(url); auto raw = fileTransfer->download(url).second;
auto decompressor = makeDecompressionSource( auto decompressor = makeDecompressionSource(
unpack && mainUrl.ends_with(".xz") ? "xz" : "none", *raw); unpack && mainUrl.ends_with(".xz") ? "xz" : "none", *raw);

View file

@ -821,7 +821,8 @@ struct curlFileTransfer : public FileTransfer
} }
} }
box_ptr<Source> download(const std::string & uri, const Headers & headers) override std::pair<FileTransferResult, box_ptr<Source>>
download(const std::string & uri, const Headers & headers) override
{ {
struct State { struct State {
bool done = false, failed = false; bool done = false, failed = false;
@ -832,7 +833,7 @@ struct curlFileTransfer : public FileTransfer
auto _state = std::make_shared<Sync<State>>(); auto _state = std::make_shared<Sync<State>>();
auto transfer = enqueueFileTransfer( auto [metadataFuture, _done] = enqueueFileTransfer(
uri, uri,
headers, headers,
[_state](std::exception_ptr ex) { [_state](std::exception_ptr ex) {
@ -939,10 +940,11 @@ struct curlFileTransfer : public FileTransfer
} }
}; };
auto metadata = metadataFuture.get();
auto source = make_box_ptr<DownloadSource>(_state); auto source = make_box_ptr<DownloadSource>(_state);
auto lock(_state->lock()); auto lock(_state->lock());
source->awaitData(lock); source->awaitData(lock);
return source; return {std::move(metadata), std::move(source)};
} }
}; };

View file

@ -101,7 +101,8 @@ struct FileTransfer
* thrown by the returned source. The source will only throw errors detected * thrown by the returned source. The source will only throw errors detected
* during the transfer itself (decompression errors, connection drops, etc). * during the transfer itself (decompression errors, connection drops, etc).
*/ */
virtual box_ptr<Source> download(const std::string & uri, const Headers & headers = {}) = 0; virtual std::pair<FileTransferResult, box_ptr<Source>>
download(const std::string & uri, const Headers & headers = {}) = 0;
enum Error { NotFound, Forbidden, Misc, Transient, Interrupted }; enum Error { NotFound, Forbidden, Misc, Transient, Interrupted };
}; };

View file

@ -147,7 +147,7 @@ protected:
{ {
checkEnabled(); checkEnabled();
try { try {
return getFileTransfer()->download(makeURI(path)); return getFileTransfer()->download(makeURI(path)).second;
} catch (FileTransferError & e) { } catch (FileTransferError & e) {
if (e.error == FileTransfer::NotFound || e.error == FileTransfer::Forbidden) if (e.error == FileTransfer::NotFound || e.error == FileTransfer::Forbidden)
throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache '%s'", path, getUri()); throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache '%s'", path, getUri());

View file

@ -98,7 +98,7 @@ std::tuple<StorePath, Hash> prefetchFile(
FdSink sink(fd.get()); FdSink sink(fd.get());
getFileTransfer()->download(url)->drainInto(sink); getFileTransfer()->download(url).second->drainInto(sink);
} }
/* Optionally unpack the file. */ /* Optionally unpack the file. */

View file

@ -136,7 +136,7 @@ TEST(FileTransfer, exceptionAbortsDownload)
LambdaSink broken([](auto block) { throw Done(); }); LambdaSink broken([](auto block) { throw Done(); });
ASSERT_THROW(ft->download("file:///dev/zero")->drainInto(broken), Done); ASSERT_THROW(ft->download("file:///dev/zero").second->drainInto(broken), Done);
// makeFileTransfer returns a ref<>, which cannot be cleared. since we also // makeFileTransfer returns a ref<>, which cannot be cleared. since we also
// can't default-construct it we'll have to overwrite it instead, but we'll // can't default-construct it we'll have to overwrite it instead, but we'll
@ -155,7 +155,7 @@ TEST(FileTransfer, exceptionAbortsRead)
auto [port, srv] = serveHTTP("200 ok", "content-length: 0\r\n", [] { return ""; }); auto [port, srv] = serveHTTP("200 ok", "content-length: 0\r\n", [] { return ""; });
auto ft = makeFileTransfer(); auto ft = makeFileTransfer();
char buf[10] = ""; char buf[10] = "";
ASSERT_THROW(ft->download(fmt("http://[::1]:%d/index", port))->read(buf, 10), EndOfFile); ASSERT_THROW(ft->download(fmt("http://[::1]:%d/index", port)).second->read(buf, 10), EndOfFile);
} }
TEST(FileTransfer, NOT_ON_DARWIN(reportsSetupErrors)) TEST(FileTransfer, NOT_ON_DARWIN(reportsSetupErrors))
@ -179,7 +179,7 @@ TEST(FileTransfer, NOT_ON_DARWIN(defersFailures))
return std::string(1024 * 1024, ' '); return std::string(1024 * 1024, ' ');
}); });
auto ft = makeFileTransfer(0); auto ft = makeFileTransfer(0);
auto src = ft->download(fmt("http://[::1]:%d/index", port)); auto src = ft->download(fmt("http://[::1]:%d/index", port)).second;
ASSERT_THROW(src->drain(), FileTransferError); ASSERT_THROW(src->drain(), FileTransferError);
} }
@ -192,7 +192,7 @@ TEST(FileTransfer, NOT_ON_DARWIN(handlesContentEncoding))
auto ft = makeFileTransfer(); auto ft = makeFileTransfer();
StringSink sink; StringSink sink;
ft->download(fmt("http://[::1]:%d/index", port))->drainInto(sink); ft->download(fmt("http://[::1]:%d/index", port)).second->drainInto(sink);
EXPECT_EQ(sink.s, original); EXPECT_EQ(sink.s, original);
} }