aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-12-16 19:11:47 +0100
committerEelco Dolstra <edolstra@gmail.com>2019-12-16 19:11:47 +0100
commit54bf5ba4227a234f8cd5102634b9a3b535e6fbdb (patch)
tree39878e4f41297705b5a8b637ed094c0998e8eca1
parent14d82baba4ebb82df28c2d4e9517f8c3a81d8f6c (diff)
nix-store -r: Handle symlinks to store paths
Fixes #3270.
-rw-r--r--src/libexpr/get-drvs.cc2
-rw-r--r--src/libstore/daemon.cc4
-rw-r--r--src/libstore/derivations.cc10
-rw-r--r--src/libstore/path.cc15
-rw-r--r--src/libstore/path.hh24
-rw-r--r--src/libstore/store-api.cc13
-rw-r--r--src/libstore/store-api.hh25
-rw-r--r--src/libutil/util.cc8
-rw-r--r--src/libutil/util.hh2
-rw-r--r--src/nix-store/nix-store.cc4
-rw-r--r--tests/nix-build.sh3
11 files changed, 67 insertions, 43 deletions
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index a3412eab9..ca9c547fa 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -19,7 +19,7 @@ DrvInfo::DrvInfo(EvalState & state, const string & attrPath, Bindings * attrs)
DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs)
: state(&state), attrs(nullptr), attrPath("")
{
- auto [drvPath, selectedOutputs] = store->parseDrvPathWithOutputs(drvPathWithOutputs);
+ auto [drvPath, selectedOutputs] = store->parsePathWithOutputs(drvPathWithOutputs);
this->drvPath = store->printStorePath(drvPath);
diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc
index c53dfdd56..8e9f9d71b 100644
--- a/src/libstore/daemon.cc
+++ b/src/libstore/daemon.cc
@@ -424,7 +424,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
case wopBuildPaths: {
std::vector<StorePathWithOutputs> drvs;
for (auto & s : readStrings<Strings>(from))
- drvs.push_back(store->parseDrvPathWithOutputs(s));
+ drvs.push_back(store->parsePathWithOutputs(s));
BuildMode mode = bmNormal;
if (GET_PROTOCOL_MINOR(clientVersion) >= 15) {
mode = (BuildMode) readInt(from);
@@ -721,7 +721,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
case wopQueryMissing: {
std::vector<StorePathWithOutputs> targets;
for (auto & s : readStrings<Strings>(from))
- targets.push_back(store->parseDrvPathWithOutputs(s));
+ targets.push_back(store->parsePathWithOutputs(s));
logger->startWork();
StorePathSet willBuild, willSubstitute, unknown;
unsigned long long downloadSize, narSize;
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index 726e34479..1a061149a 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -375,16 +375,6 @@ Hash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOutput
}
-StorePathWithOutputs Store::parseDrvPathWithOutputs(const std::string & s)
-{
- size_t n = s.find("!");
- return n == s.npos
- ? StorePathWithOutputs{parseStorePath(s), std::set<string>()}
- : StorePathWithOutputs{parseStorePath(std::string_view(s.data(), n)),
- tokenizeString<std::set<string>>(string(s, n + 1), ",")};
-}
-
-
std::string StorePathWithOutputs::to_string(const Store & store) const
{
return outputs.empty()
diff --git a/src/libstore/path.cc b/src/libstore/path.cc
index 81ae495a1..cda5f9968 100644
--- a/src/libstore/path.cc
+++ b/src/libstore/path.cc
@@ -96,4 +96,19 @@ StorePathSet singleton(const StorePath & path)
return res;
}
+std::pair<std::string_view, StringSet> parsePathWithOutputs(std::string_view s)
+{
+ size_t n = s.find("!");
+ return n == s.npos
+ ? std::make_pair(s, std::set<string>())
+ : std::make_pair(((std::string_view) s).substr(0, n),
+ tokenizeString<std::set<string>>(((std::string_view) s).substr(n + 1), ","));
+}
+
+StorePathWithOutputs Store::parsePathWithOutputs(const std::string & s)
+{
+ auto [path, outputs] = nix::parsePathWithOutputs(s);
+ return {parseStorePath(path), std::move(outputs)};
+}
+
}
diff --git a/src/libstore/path.hh b/src/libstore/path.hh
index 273808f02..5ebb57480 100644
--- a/src/libstore/path.hh
+++ b/src/libstore/path.hh
@@ -7,6 +7,8 @@ namespace nix {
/* See path.rs. */
struct StorePath;
+struct Store;
+
extern "C" {
void ffi_StorePath_drop(void *);
bool ffi_StorePath_less_than(const StorePath & a, const StorePath & b);
@@ -67,6 +69,28 @@ const size_t storePathHashLen = 32; // i.e. 160 bits
/* Extension of derivations in the Nix store. */
const std::string drvExtension = ".drv";
+struct StorePathWithOutputs
+{
+ StorePath path;
+ std::set<std::string> outputs;
+
+ StorePathWithOutputs(const StorePath & path, const std::set<std::string> & outputs = {})
+ : path(path.clone()), outputs(outputs)
+ { }
+
+ StorePathWithOutputs(StorePath && path, std::set<std::string> && outputs)
+ : path(std::move(path)), outputs(std::move(outputs))
+ { }
+
+ StorePathWithOutputs(const StorePathWithOutputs & other)
+ : path(other.path.clone()), outputs(other.outputs)
+ { }
+
+ std::string to_string(const Store & store) const;
+};
+
+std::pair<std::string_view, StringSet> parsePathWithOutputs(std::string_view s);
+
}
namespace std {
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index c98931885..1781e0c68 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -39,9 +39,9 @@ Path Store::toStorePath(const Path & path) const
}
-Path Store::followLinksToStore(const Path & _path) const
+Path Store::followLinksToStore(std::string_view _path) const
{
- Path path = absPath(_path);
+ Path path = absPath(std::string(_path));
while (!isInStore(path)) {
if (!isLink(path)) break;
string target = readLink(path);
@@ -53,12 +53,19 @@ Path Store::followLinksToStore(const Path & _path) const
}
-StorePath Store::followLinksToStorePath(const Path & path) const
+StorePath Store::followLinksToStorePath(std::string_view path) const
{
return parseStorePath(toStorePath(followLinksToStore(path)));
}
+StorePathWithOutputs Store::followLinksToStorePathWithOutputs(std::string_view path) const
+{
+ auto [path2, outputs] = nix::parsePathWithOutputs(path);
+ return StorePathWithOutputs(followLinksToStorePath(path2), std::move(outputs));
+}
+
+
string storePathToHash(const Path & path)
{
auto base = baseNameOf(path);
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 552bbd67d..d77d6bad8 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -241,23 +241,6 @@ struct BuildResult
};
-struct StorePathWithOutputs
-{
- StorePath path;
- std::set<std::string> outputs;
-
- StorePathWithOutputs(const StorePath & path, const std::set<std::string> & outputs = {})
- : path(path.clone()), outputs(outputs)
- { }
-
- StorePathWithOutputs(const StorePathWithOutputs & other)
- : path(other.path.clone()), outputs(other.outputs)
- { }
-
- std::string to_string(const Store & store) const;
-};
-
-
class Store : public std::enable_shared_from_this<Store>, public Config
{
public:
@@ -304,7 +287,7 @@ public:
/* Split a string specifying a derivation and a set of outputs
(/nix/store/hash-foo!out1,out2,...) into the derivation path
and the outputs. */
- StorePathWithOutputs parseDrvPathWithOutputs(const string & s);
+ StorePathWithOutputs parsePathWithOutputs(const string & s);
/* Display a set of paths in human-readable form (i.e., between quotes
and separated by commas). */
@@ -323,11 +306,13 @@ public:
Path toStorePath(const Path & path) const;
/* Follow symlinks until we end up with a path in the Nix store. */
- Path followLinksToStore(const Path & path) const;
+ Path followLinksToStore(std::string_view path) const;
/* Same as followLinksToStore(), but apply toStorePath() to the
result. */
- StorePath followLinksToStorePath(const Path & path) const;
+ StorePath followLinksToStorePath(std::string_view path) const;
+
+ StorePathWithOutputs followLinksToStorePathWithOutputs(std::string_view path) const;
/* Constructs a unique store path name. */
StorePath makeStorePath(const string & type,
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index e67bdcdeb..012f1d071 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -1186,7 +1186,7 @@ void _interrupted()
//////////////////////////////////////////////////////////////////////
-template<class C> C tokenizeString(const string & s, const string & separators)
+template<class C> C tokenizeString(std::string_view s, const string & separators)
{
C result;
string::size_type pos = s.find_first_not_of(separators, 0);
@@ -1200,9 +1200,9 @@ template<class C> C tokenizeString(const string & s, const string & separators)
return result;
}
-template Strings tokenizeString(const string & s, const string & separators);
-template StringSet tokenizeString(const string & s, const string & separators);
-template vector<string> tokenizeString(const string & s, const string & separators);
+template Strings tokenizeString(std::string_view s, const string & separators);
+template StringSet tokenizeString(std::string_view s, const string & separators);
+template vector<string> tokenizeString(std::string_view s, const string & separators);
string concatStringsSep(const string & sep, const Strings & ss)
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index abd91b81c..abf1c95d6 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -340,7 +340,7 @@ MakeError(FormatError, Error);
/* String tokenizer. */
-template<class C> C tokenizeString(const string & s, const string & separators = " \t\n\r");
+template<class C> C tokenizeString(std::string_view s, const string & separators = " \t\n\r");
/* Concatenate the given strings with a separator between the
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index e2e2939f4..45e152c47 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -128,7 +128,7 @@ static void opRealise(Strings opFlags, Strings opArgs)
std::vector<StorePathWithOutputs> paths;
for (auto & i : opArgs)
- paths.push_back(store->parseDrvPathWithOutputs(i));
+ paths.push_back(store->followLinksToStorePathWithOutputs(i));
unsigned long long downloadSize, narSize;
StorePathSet willBuild, willSubstitute, unknown;
@@ -893,7 +893,7 @@ static void opServe(Strings opFlags, Strings opArgs)
std::vector<StorePathWithOutputs> paths;
for (auto & s : readStrings<Strings>(in))
- paths.emplace_back(store->parseDrvPathWithOutputs(s));
+ paths.emplace_back(store->parsePathWithOutputs(s));
getBuildSettings();
diff --git a/tests/nix-build.sh b/tests/nix-build.sh
index 395264863..0eb599608 100644
--- a/tests/nix-build.sh
+++ b/tests/nix-build.sh
@@ -23,3 +23,6 @@ outPath2=$(nix-build $(nix-instantiate dependencies.nix) --no-out-link)
outPath2=$(nix-build $(nix-instantiate dependencies.nix)!out --no-out-link)
[[ $outPath = $outPath2 ]]
+
+outPath2=$(nix-store -r $(nix-instantiate --indirect --add-root $TEST_ROOT/indirect dependencies.nix)!out)
+[[ $outPath = $outPath2 ]]