libutil: remove sinkToSource eof callback

this is only used in one place, and only to set a nicer error message on
EndOfFile. the only caller that actually *catches* this exception should
provide an error message in that catch block rather than forcing support
for setting error message so deep into the stack. copyStorePath is never
called outside of PathSubstitutionGoal anyway, which catches everything.

Change-Id: Ifbae8706d781c388737706faf4c8a8b7917ca278
This commit is contained in:
eldritch horrors 2024-04-06 22:08:58 +02:00
parent f80d95e36d
commit 39a1e248c9
6 changed files with 48 additions and 17 deletions

View file

@ -217,6 +217,7 @@ void PathSubstitutionGoal::tryToRun()
promise = std::promise<void>(); promise = std::promise<void>();
thr = std::thread([this]() { thr = std::thread([this]() {
auto & fetchPath = subPath ? *subPath : storePath;
try { try {
ReceiveInterrupts receiveInterrupts; ReceiveInterrupts receiveInterrupts;
@ -226,10 +227,17 @@ void PathSubstitutionGoal::tryToRun()
Activity act(*logger, actSubstitute, Logger::Fields{worker.store.printStorePath(storePath), sub->getUri()}); Activity act(*logger, actSubstitute, Logger::Fields{worker.store.printStorePath(storePath), sub->getUri()});
PushActivity pact(act.id); PushActivity pact(act.id);
copyStorePath(*sub, worker.store, copyStorePath(
subPath ? *subPath : storePath, repair, sub->isTrusted ? NoCheckSigs : CheckSigs); *sub, worker.store, fetchPath, repair, sub->isTrusted ? NoCheckSigs : CheckSigs
);
promise.set_value(); promise.set_value();
} catch (const EndOfFile &) {
promise.set_exception(std::make_exception_ptr(EndOfFile(
"NAR for '%s' fetched from '%s' is incomplete",
sub->printStorePath(fetchPath),
sub->getUri()
)));
} catch (...) { } catch (...) {
promise.set_exception(std::current_exception()); promise.set_exception(std::current_exception());
} }

View file

@ -1072,8 +1072,6 @@ void copyStorePath(
}); });
TeeSink tee { sink, progressSink }; TeeSink tee { sink, progressSink };
srcStore.narFromPath(storePath, tee); srcStore.narFromPath(storePath, tee);
}, [&]() {
throw EndOfFile("NAR for '%s' fetched from '%s' is incomplete", srcStore.printStorePath(storePath), srcStore.getUri());
}); });
dstStore.addToStore(*info, *source, repair, checkSigs); dstStore.addToStore(*info, *source, repair, checkSigs);

View file

@ -266,20 +266,17 @@ std::unique_ptr<FinishSink> sourceToSink(std::function<void(Source &)> fun)
} }
std::unique_ptr<Source> sinkToSource( std::unique_ptr<Source> sinkToSource(std::function<void(Sink &)> fun)
std::function<void(Sink &)> fun,
std::function<void()> eof)
{ {
struct SinkToSource : Source struct SinkToSource : Source
{ {
typedef boost::coroutines2::coroutine<std::string> coro_t; typedef boost::coroutines2::coroutine<std::string> coro_t;
std::function<void(Sink &)> fun; std::function<void(Sink &)> fun;
std::function<void()> eof;
std::optional<coro_t::pull_type> coro; std::optional<coro_t::pull_type> coro;
SinkToSource(std::function<void(Sink &)> fun, std::function<void()> eof) SinkToSource(std::function<void(Sink &)> fun)
: fun(fun), eof(eof) : fun(fun)
{ {
} }
@ -298,7 +295,9 @@ std::unique_ptr<Source> sinkToSource(
}); });
} }
if (!*coro) { eof(); abort(); } if (!*coro) {
throw EndOfFile("coroutine has finished");
}
if (pos == cur.size()) { if (pos == cur.size()) {
if (!cur.empty()) { if (!cur.empty()) {
@ -317,7 +316,7 @@ std::unique_ptr<Source> sinkToSource(
} }
}; };
return std::make_unique<SinkToSource>(fun, eof); return std::make_unique<SinkToSource>(fun);
} }

View file

@ -338,11 +338,7 @@ std::unique_ptr<FinishSink> sourceToSink(std::function<void(Source &)> fun);
* Convert a function that feeds data into a Sink into a Source. The * Convert a function that feeds data into a Sink into a Source. The
* Source executes the function as a coroutine. * Source executes the function as a coroutine.
*/ */
std::unique_ptr<Source> sinkToSource( std::unique_ptr<Source> sinkToSource(std::function<void(Sink &)> fun);
std::function<void(Sink &)> fun,
std::function<void()> eof = []() {
throw EndOfFile("coroutine has finished");
});
void writePadding(size_t len, Sink & sink); void writePadding(size_t len, Sink & sink);

View file

@ -182,6 +182,7 @@ functional_tests_scripts = [
'debugger.sh', 'debugger.sh',
'test-libstoreconsumer.sh', 'test-libstoreconsumer.sh',
'extra-sandbox-profile.sh', 'extra-sandbox-profile.sh',
'substitute-truncated-nar.sh',
] ]
# Plugin tests require shared libraries support. # Plugin tests require shared libraries support.

View file

@ -0,0 +1,29 @@
source common.sh
BINARY_CACHE=file://$cacheDir
build() {
nix-build --no-out-link "$@" --expr 'derivation {
name = "text";
system = builtins.currentSystem;
builder = "/bin/sh";
args = [ "-c" "echo some text to make the nar less empty > $out" ];
}'
}
path=$(build)
nix copy --to "$BINARY_CACHE" "$path"
nix-collect-garbage >/dev/null 2>&1
nar=0bylmx35yjy2b1b4k7gjsl7i4vc03cpmryb41grfb1mp40n3hifl.nar.xz
[ -e $cacheDir/nar/$nar ] || fail "long nar missing?"
xzcat $cacheDir/nar/$nar > $TEST_HOME/tmp
truncate -s $(( $(stat -c %s $TEST_HOME/tmp) - 10 )) $TEST_HOME/tmp
xz < $TEST_HOME/tmp > $cacheDir/nar/$nar
# Copying back '$path' from the binary cache. This should fail as it is truncated
if build --option substituters "$BINARY_CACHE" --option require-sigs false -j0; then
fail "Importing a truncated nar should fail"
fi