From 5c7520b56919393adceff57387e828c6a7ec4b85 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Tue, 15 May 2012 23:00:23 -0400 Subject: [PATCH 1/2] prim_import: Don't build derivations in read-only mode --- src/libexpr/primops.cc | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index d3809e6984a..8f6e5fabf99 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -49,20 +49,29 @@ static void prim_import(EvalState & state, Value * * args, Value & v) if (!store->isValidPath(ctx)) throw EvalError(format("cannot import `%1%', since path `%2%' is not valid") % path % ctx); - if (isDerivation(ctx)) - try { - /* For performance, prefetch all substitute info. */ - PathSet willBuild, willSubstitute, unknown; - unsigned long long downloadSize, narSize; - queryMissing(*store, singleton(ctx), - willBuild, willSubstitute, unknown, downloadSize, narSize); + if (isDerivation(ctx)) { + string outputName = decodeContext(*i).second; + Derivation drv = derivationFromPath(*store, ctx); + + if (!store->isValidPath(drv.outputs[outputName].path)) { + if (settings.readOnlyMode) + throw ImportError(format("cannot import `%1%', since output `%2%' of derivation `%3%' is not valid") + % path % outputName % ctx); + try { + /* For performance, prefetch all substitute info. */ + PathSet willBuild, willSubstitute, unknown; + unsigned long long downloadSize, narSize; + queryMissing(*store, singleton(ctx), + willBuild, willSubstitute, unknown, downloadSize, narSize); - /* !!! If using a substitute, we only need to fetch - the selected output of this derivation. */ - store->buildPaths(singleton(ctx)); - } catch (Error & e) { - throw ImportError(e.msg()); + /* !!! If using a substitute, we only need to fetch + the selected output of this derivation. */ + store->buildPaths(singleton(ctx)); + } catch (Error & e) { + throw ImportError(e.msg()); + } } + } } if (isStorePath(path) && store->isValidPath(path) && isDerivation(path)) { From 9e0561bd8fbc963ce31f19bd0a060dd9aac1cebf Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Wed, 29 Aug 2012 00:11:12 -0400 Subject: [PATCH 2/2] prim_import: Distinguish between failures due to read-only mode and other failures --- src/libexpr/nixexpr.hh | 1 + src/libexpr/primops.cc | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index bc6c3287c79..0eac3d69d88 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -16,6 +16,7 @@ MakeError(ThrownError, AssertionError) MakeError(Abort, EvalError) MakeError(TypeError, EvalError) MakeError(ImportError, EvalError) // error building an imported derivation +MakeError(ImportReadOnlyError, EvalError) // error when trying to import a derivation in read-only mode /* Position objects. */ diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 8f6e5fabf99..7189465af93 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -45,18 +45,26 @@ static void prim_import(EvalState & state, Value * * args, Value & v) foreach (PathSet::iterator, i, context) { Path ctx = decodeContext(*i).first; + string outputName = decodeContext(*i).second; assert(isStorePath(ctx)); - if (!store->isValidPath(ctx)) - throw EvalError(format("cannot import `%1%', since path `%2%' is not valid") - % path % ctx); + if (!store->isValidPath(ctx)) { + if (outputName.empty()) + throw EvalError(format("cannot import `%1%', since path `%2%' is not valid") + % path % ctx); + else + throw ImportReadOnlyError(format("cannot import `%1%', since path `%2%' cannot be written to the store in read-only mode") + % path % ctx); + } if (isDerivation(ctx)) { - string outputName = decodeContext(*i).second; Derivation drv = derivationFromPath(*store, ctx); - if (!store->isValidPath(drv.outputs[outputName].path)) { + if (outputName.empty() || + !store->isValidPath(drv.outputs[outputName].path)) { if (settings.readOnlyMode) - throw ImportError(format("cannot import `%1%', since output `%2%' of derivation `%3%' is not valid") - % path % outputName % ctx); + foreach (DerivationOutputs::iterator, j, drv.outputs) + if (!store->isValidPath(j->second.path)) + throw ImportReadOnlyError(format("cannot import `%1%', since derivation `%2%' cannot be realised in read-only mode") + % path % ctx); try { /* For performance, prefetch all substitute info. */ PathSet willBuild, willSubstitute, unknown;