diff --git a/src/libstore/builtins/fetchurl.cc b/src/libstore/builtins/fetchurl.cc index e263997e1..06ab0505a 100644 --- a/src/libstore/builtins/fetchurl.cc +++ b/src/libstore/builtins/fetchurl.cc @@ -36,7 +36,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData, auto fetch = [&](const std::string & url) { - auto raw = fileTransfer->download(url); + auto raw = fileTransfer->download(url).second; auto decompressor = makeDecompressionSource( unpack && mainUrl.ends_with(".xz") ? "xz" : "none", *raw); diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 73bae6cfe..1f6c3e22b 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -821,7 +821,8 @@ struct curlFileTransfer : public FileTransfer } } - box_ptr download(const std::string & uri, const Headers & headers) override + std::pair> + download(const std::string & uri, const Headers & headers) override { struct State { bool done = false, failed = false; @@ -832,7 +833,7 @@ struct curlFileTransfer : public FileTransfer auto _state = std::make_shared>(); - auto transfer = enqueueFileTransfer( + auto [metadataFuture, _done] = enqueueFileTransfer( uri, headers, [_state](std::exception_ptr ex) { @@ -939,10 +940,11 @@ struct curlFileTransfer : public FileTransfer } }; + auto metadata = metadataFuture.get(); auto source = make_box_ptr(_state); auto lock(_state->lock()); source->awaitData(lock); - return source; + return {std::move(metadata), std::move(source)}; } }; diff --git a/src/libstore/filetransfer.hh b/src/libstore/filetransfer.hh index 8ee88a7a8..1abc07c4d 100644 --- a/src/libstore/filetransfer.hh +++ b/src/libstore/filetransfer.hh @@ -101,7 +101,8 @@ struct FileTransfer * thrown by the returned source. The source will only throw errors detected * during the transfer itself (decompression errors, connection drops, etc). */ - virtual box_ptr download(const std::string & uri, const Headers & headers = {}) = 0; + virtual std::pair> + download(const std::string & uri, const Headers & headers = {}) = 0; enum Error { NotFound, Forbidden, Misc, Transient, Interrupted }; }; diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc index 80524b58d..9e81cd156 100644 --- a/src/libstore/http-binary-cache-store.cc +++ b/src/libstore/http-binary-cache-store.cc @@ -147,7 +147,7 @@ protected: { checkEnabled(); try { - return getFileTransfer()->download(makeURI(path)); + return getFileTransfer()->download(makeURI(path)).second; } catch (FileTransferError & e) { if (e.error == FileTransfer::NotFound || e.error == FileTransfer::Forbidden) throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache '%s'", path, getUri()); diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc index 1fb7bb49b..686df2caa 100644 --- a/src/nix/prefetch.cc +++ b/src/nix/prefetch.cc @@ -98,7 +98,7 @@ std::tuple prefetchFile( FdSink sink(fd.get()); - getFileTransfer()->download(url)->drainInto(sink); + getFileTransfer()->download(url).second->drainInto(sink); } /* Optionally unpack the file. */ diff --git a/tests/unit/libstore/filetransfer.cc b/tests/unit/libstore/filetransfer.cc index 0e0a2439e..dd0c33f06 100644 --- a/tests/unit/libstore/filetransfer.cc +++ b/tests/unit/libstore/filetransfer.cc @@ -136,7 +136,7 @@ TEST(FileTransfer, exceptionAbortsDownload) 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 // 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 ft = makeFileTransfer(); 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)) @@ -179,7 +179,7 @@ TEST(FileTransfer, NOT_ON_DARWIN(defersFailures)) return std::string(1024 * 1024, ' '); }); 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); } @@ -192,7 +192,7 @@ TEST(FileTransfer, NOT_ON_DARWIN(handlesContentEncoding)) auto ft = makeFileTransfer(); 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); }