diff options
Diffstat (limited to 'third_party/nix/src/libstore/derivations.cc')
-rw-r--r-- | third_party/nix/src/libstore/derivations.cc | 641 |
1 files changed, 314 insertions, 327 deletions
diff --git a/third_party/nix/src/libstore/derivations.cc b/third_party/nix/src/libstore/derivations.cc index 23fcfb281a72..e75c0d77c3ac 100644 --- a/third_party/nix/src/libstore/derivations.cc +++ b/third_party/nix/src/libstore/derivations.cc @@ -1,289 +1,294 @@ #include "derivations.hh" -#include "store-api.hh" +#include "fs-accessor.hh" #include "globals.hh" +#include "istringstream_nocopy.hh" +#include "store-api.hh" #include "util.hh" #include "worker-protocol.hh" -#include "fs-accessor.hh" -#include "istringstream_nocopy.hh" namespace nix { +void DerivationOutput::parseHashInfo(bool& recursive, Hash& hash) const { + recursive = false; + string algo = hashAlgo; -void DerivationOutput::parseHashInfo(bool & recursive, Hash & hash) const -{ - recursive = false; - string algo = hashAlgo; - - if (string(algo, 0, 2) == "r:") { - recursive = true; - algo = string(algo, 2); - } + if (string(algo, 0, 2) == "r:") { + recursive = true; + algo = string(algo, 2); + } - HashType hashType = parseHashType(algo); - if (hashType == htUnknown) - throw Error(format("unknown hash algorithm '%1%'") % algo); + HashType hashType = parseHashType(algo); + if (hashType == htUnknown) + throw Error(format("unknown hash algorithm '%1%'") % algo); - hash = Hash(this->hash, hashType); + hash = Hash(this->hash, hashType); } - -Path BasicDerivation::findOutput(const string & id) const -{ - auto i = outputs.find(id); - if (i == outputs.end()) - throw Error(format("derivation has no output '%1%'") % id); - return i->second.path; +Path BasicDerivation::findOutput(const string& id) const { + auto i = outputs.find(id); + if (i == outputs.end()) + throw Error(format("derivation has no output '%1%'") % id); + return i->second.path; } - -bool BasicDerivation::isBuiltin() const -{ - return string(builder, 0, 8) == "builtin:"; +bool BasicDerivation::isBuiltin() const { + return string(builder, 0, 8) == "builtin:"; } - -Path writeDerivation(ref<Store> store, - const Derivation & drv, const string & name, RepairFlag repair) -{ - PathSet references; - references.insert(drv.inputSrcs.begin(), drv.inputSrcs.end()); - for (auto & i : drv.inputDrvs) - references.insert(i.first); - /* Note that the outputs of a derivation are *not* references - (that can be missing (of course) and should not necessarily be - held during a garbage collection). */ - string suffix = name + drvExtension; - string contents = drv.unparse(); - return settings.readOnlyMode - ? store->computeStorePathForText(suffix, contents, references) - : store->addTextToStore(suffix, contents, references, repair); +Path writeDerivation(ref<Store> store, const Derivation& drv, + const string& name, RepairFlag repair) { + PathSet references; + references.insert(drv.inputSrcs.begin(), drv.inputSrcs.end()); + for (auto& i : drv.inputDrvs) references.insert(i.first); + /* Note that the outputs of a derivation are *not* references + (that can be missing (of course) and should not necessarily be + held during a garbage collection). */ + string suffix = name + drvExtension; + string contents = drv.unparse(); + return settings.readOnlyMode + ? store->computeStorePathForText(suffix, contents, references) + : store->addTextToStore(suffix, contents, references, repair); } - /* Read string `s' from stream `str'. */ -static void expect(std::istream & str, const string & s) -{ - char s2[s.size()]; - str.read(s2, s.size()); - if (string(s2, s.size()) != s) - throw FormatError(format("expected string '%1%'") % s); +static void expect(std::istream& str, const string& s) { + char s2[s.size()]; + str.read(s2, s.size()); + if (string(s2, s.size()) != s) + throw FormatError(format("expected string '%1%'") % s); } - /* Read a C-style string from stream `str'. */ -static string parseString(std::istream & str) -{ - string res; - expect(str, "\""); - int c; - while ((c = str.get()) != '"') - if (c == '\\') { - c = str.get(); - if (c == 'n') res += '\n'; - else if (c == 'r') res += '\r'; - else if (c == 't') res += '\t'; - else res += c; - } - else res += c; - return res; +static string parseString(std::istream& str) { + string res; + expect(str, "\""); + int c; + while ((c = str.get()) != '"') + if (c == '\\') { + c = str.get(); + if (c == 'n') + res += '\n'; + else if (c == 'r') + res += '\r'; + else if (c == 't') + res += '\t'; + else + res += c; + } else + res += c; + return res; } - -static Path parsePath(std::istream & str) -{ - string s = parseString(str); - if (s.size() == 0 || s[0] != '/') - throw FormatError(format("bad path '%1%' in derivation") % s); - return s; +static Path parsePath(std::istream& str) { + string s = parseString(str); + if (s.size() == 0 || s[0] != '/') + throw FormatError(format("bad path '%1%' in derivation") % s); + return s; } - -static bool endOfList(std::istream & str) -{ - if (str.peek() == ',') { - str.get(); - return false; - } - if (str.peek() == ']') { - str.get(); - return true; - } +static bool endOfList(std::istream& str) { + if (str.peek() == ',') { + str.get(); return false; + } + if (str.peek() == ']') { + str.get(); + return true; + } + return false; } - -static StringSet parseStrings(std::istream & str, bool arePaths) -{ - StringSet res; - while (!endOfList(str)) - res.insert(arePaths ? parsePath(str) : parseString(str)); - return res; +static StringSet parseStrings(std::istream& str, bool arePaths) { + StringSet res; + while (!endOfList(str)) + res.insert(arePaths ? parsePath(str) : parseString(str)); + return res; } - -static Derivation parseDerivation(const string & s) -{ - Derivation drv; - istringstream_nocopy str(s); - expect(str, "Derive(["); - - /* Parse the list of outputs. */ - while (!endOfList(str)) { - DerivationOutput out; - expect(str, "("); string id = parseString(str); - expect(str, ","); out.path = parsePath(str); - expect(str, ","); out.hashAlgo = parseString(str); - expect(str, ","); out.hash = parseString(str); - expect(str, ")"); - drv.outputs[id] = out; - } - - /* Parse the list of input derivations. */ - expect(str, ",["); - while (!endOfList(str)) { - expect(str, "("); - Path drvPath = parsePath(str); - expect(str, ",["); - drv.inputDrvs[drvPath] = parseStrings(str, false); - expect(str, ")"); - } - - expect(str, ",["); drv.inputSrcs = parseStrings(str, true); - expect(str, ","); drv.platform = parseString(str); - expect(str, ","); drv.builder = parseString(str); - - /* Parse the builder arguments. */ - expect(str, ",["); - while (!endOfList(str)) - drv.args.push_back(parseString(str)); - - /* Parse the environment variables. */ +static Derivation parseDerivation(const string& s) { + Derivation drv; + istringstream_nocopy str(s); + expect(str, "Derive(["); + + /* Parse the list of outputs. */ + while (!endOfList(str)) { + DerivationOutput out; + expect(str, "("); + string id = parseString(str); + expect(str, ","); + out.path = parsePath(str); + expect(str, ","); + out.hashAlgo = parseString(str); + expect(str, ","); + out.hash = parseString(str); + expect(str, ")"); + drv.outputs[id] = out; + } + + /* Parse the list of input derivations. */ + expect(str, ",["); + while (!endOfList(str)) { + expect(str, "("); + Path drvPath = parsePath(str); expect(str, ",["); - while (!endOfList(str)) { - expect(str, "("); string name = parseString(str); - expect(str, ","); string value = parseString(str); - expect(str, ")"); - drv.env[name] = value; - } - + drv.inputDrvs[drvPath] = parseStrings(str, false); expect(str, ")"); - return drv; -} - + } + + expect(str, ",["); + drv.inputSrcs = parseStrings(str, true); + expect(str, ","); + drv.platform = parseString(str); + expect(str, ","); + drv.builder = parseString(str); + + /* Parse the builder arguments. */ + expect(str, ",["); + while (!endOfList(str)) drv.args.push_back(parseString(str)); + + /* Parse the environment variables. */ + expect(str, ",["); + while (!endOfList(str)) { + expect(str, "("); + string name = parseString(str); + expect(str, ","); + string value = parseString(str); + expect(str, ")"); + drv.env[name] = value; + } -Derivation readDerivation(const Path & drvPath) -{ - try { - return parseDerivation(readFile(drvPath)); - } catch (FormatError & e) { - throw Error(format("error parsing derivation '%1%': %2%") % drvPath % e.msg()); - } + expect(str, ")"); + return drv; } - -Derivation Store::derivationFromPath(const Path & drvPath) -{ - assertStorePath(drvPath); - ensurePath(drvPath); - auto accessor = getFSAccessor(); - try { - return parseDerivation(accessor->readFile(drvPath)); - } catch (FormatError & e) { - throw Error(format("error parsing derivation '%1%': %2%") % drvPath % e.msg()); - } +Derivation readDerivation(const Path& drvPath) { + try { + return parseDerivation(readFile(drvPath)); + } catch (FormatError& e) { + throw Error(format("error parsing derivation '%1%': %2%") % drvPath % + e.msg()); + } } - -static void printString(string & res, const string & s) -{ - res += '"'; - for (const char * i = s.c_str(); *i; i++) - if (*i == '\"' || *i == '\\') { res += "\\"; res += *i; } - else if (*i == '\n') res += "\\n"; - else if (*i == '\r') res += "\\r"; - else if (*i == '\t') res += "\\t"; - else res += *i; - res += '"'; +Derivation Store::derivationFromPath(const Path& drvPath) { + assertStorePath(drvPath); + ensurePath(drvPath); + auto accessor = getFSAccessor(); + try { + return parseDerivation(accessor->readFile(drvPath)); + } catch (FormatError& e) { + throw Error(format("error parsing derivation '%1%': %2%") % drvPath % + e.msg()); + } } - -template<class ForwardIterator> -static void printStrings(string & res, ForwardIterator i, ForwardIterator j) -{ - res += '['; - bool first = true; - for ( ; i != j; ++i) { - if (first) first = false; else res += ','; - printString(res, *i); - } - res += ']'; +static void printString(string& res, const string& s) { + res += '"'; + for (const char* i = s.c_str(); *i; i++) + if (*i == '\"' || *i == '\\') { + res += "\\"; + res += *i; + } else if (*i == '\n') + res += "\\n"; + else if (*i == '\r') + res += "\\r"; + else if (*i == '\t') + res += "\\t"; + else + res += *i; + res += '"'; } - -string Derivation::unparse() const -{ - string s; - s.reserve(65536); - s += "Derive(["; - - bool first = true; - for (auto & i : outputs) { - if (first) first = false; else s += ','; - s += '('; printString(s, i.first); - s += ','; printString(s, i.second.path); - s += ','; printString(s, i.second.hashAlgo); - s += ','; printString(s, i.second.hash); - s += ')'; - } - - s += "],["; - first = true; - for (auto & i : inputDrvs) { - if (first) first = false; else s += ','; - s += '('; printString(s, i.first); - s += ','; printStrings(s, i.second.begin(), i.second.end()); - s += ')'; - } - - s += "],"; - printStrings(s, inputSrcs.begin(), inputSrcs.end()); - - s += ','; printString(s, platform); - s += ','; printString(s, builder); - s += ','; printStrings(s, args.begin(), args.end()); - - s += ",["; - first = true; - for (auto & i : env) { - if (first) first = false; else s += ','; - s += '('; printString(s, i.first); - s += ','; printString(s, i.second); - s += ')'; - } - - s += "])"; - - return s; +template <class ForwardIterator> +static void printStrings(string& res, ForwardIterator i, ForwardIterator j) { + res += '['; + bool first = true; + for (; i != j; ++i) { + if (first) + first = false; + else + res += ','; + printString(res, *i); + } + res += ']'; } - -bool isDerivation(const string & fileName) -{ - return hasSuffix(fileName, drvExtension); +string Derivation::unparse() const { + string s; + s.reserve(65536); + s += "Derive(["; + + bool first = true; + for (auto& i : outputs) { + if (first) + first = false; + else + s += ','; + s += '('; + printString(s, i.first); + s += ','; + printString(s, i.second.path); + s += ','; + printString(s, i.second.hashAlgo); + s += ','; + printString(s, i.second.hash); + s += ')'; + } + + s += "],["; + first = true; + for (auto& i : inputDrvs) { + if (first) + first = false; + else + s += ','; + s += '('; + printString(s, i.first); + s += ','; + printStrings(s, i.second.begin(), i.second.end()); + s += ')'; + } + + s += "],"; + printStrings(s, inputSrcs.begin(), inputSrcs.end()); + + s += ','; + printString(s, platform); + s += ','; + printString(s, builder); + s += ','; + printStrings(s, args.begin(), args.end()); + + s += ",["; + first = true; + for (auto& i : env) { + if (first) + first = false; + else + s += ','; + s += '('; + printString(s, i.first); + s += ','; + printString(s, i.second); + s += ')'; + } + + s += "])"; + + return s; } - -bool BasicDerivation::isFixedOutput() const -{ - return outputs.size() == 1 && - outputs.begin()->first == "out" && - outputs.begin()->second.hash != ""; +bool isDerivation(const string& fileName) { + return hasSuffix(fileName, drvExtension); } +bool BasicDerivation::isFixedOutput() const { + return outputs.size() == 1 && outputs.begin()->first == "out" && + outputs.begin()->second.hash != ""; +} DrvHashes drvHashes; - /* Returns the hash of a derivation modulo fixed-output subderivations. A fixed-output derivation is a derivation with one output (`out') for which an expected hash and hash algorithm are @@ -304,113 +309,95 @@ DrvHashes drvHashes; paths have been replaced by the result of a recursive call to this function, and that for fixed-output derivations we return a hash of its output path. */ -Hash hashDerivationModulo(Store & store, Derivation drv) -{ - /* Return a fixed hash for fixed-output derivations. */ - if (drv.isFixedOutput()) { - DerivationOutputs::const_iterator i = drv.outputs.begin(); - return hashString(htSHA256, "fixed:out:" - + i->second.hashAlgo + ":" - + i->second.hash + ":" - + i->second.path); - } - - /* For other derivations, replace the inputs paths with recursive - calls to this function.*/ - DerivationInputs inputs2; - for (auto & i : drv.inputDrvs) { - Hash h = drvHashes[i.first]; - if (!h) { - assert(store.isValidPath(i.first)); - Derivation drv2 = readDerivation(store.toRealPath(i.first)); - h = hashDerivationModulo(store, drv2); - drvHashes[i.first] = h; - } - inputs2[h.to_string(Base16, false)] = i.second; +Hash hashDerivationModulo(Store& store, Derivation drv) { + /* Return a fixed hash for fixed-output derivations. */ + if (drv.isFixedOutput()) { + DerivationOutputs::const_iterator i = drv.outputs.begin(); + return hashString(htSHA256, "fixed:out:" + i->second.hashAlgo + ":" + + i->second.hash + ":" + i->second.path); + } + + /* For other derivations, replace the inputs paths with recursive + calls to this function.*/ + DerivationInputs inputs2; + for (auto& i : drv.inputDrvs) { + Hash h = drvHashes[i.first]; + if (!h) { + assert(store.isValidPath(i.first)); + Derivation drv2 = readDerivation(store.toRealPath(i.first)); + h = hashDerivationModulo(store, drv2); + drvHashes[i.first] = h; } - drv.inputDrvs = inputs2; + inputs2[h.to_string(Base16, false)] = i.second; + } + drv.inputDrvs = inputs2; - return hashString(htSHA256, drv.unparse()); + return hashString(htSHA256, drv.unparse()); } - -DrvPathWithOutputs parseDrvPathWithOutputs(const string & s) -{ - size_t n = s.find("!"); - return n == s.npos - ? DrvPathWithOutputs(s, std::set<string>()) - : DrvPathWithOutputs(string(s, 0, n), tokenizeString<std::set<string> >(string(s, n + 1), ",")); +DrvPathWithOutputs parseDrvPathWithOutputs(const string& s) { + size_t n = s.find("!"); + return n == s.npos ? DrvPathWithOutputs(s, std::set<string>()) + : DrvPathWithOutputs(string(s, 0, n), + tokenizeString<std::set<string> >( + string(s, n + 1), ",")); } - -Path makeDrvPathWithOutputs(const Path & drvPath, const std::set<string> & outputs) -{ - return outputs.empty() - ? drvPath - : drvPath + "!" + concatStringsSep(",", outputs); +Path makeDrvPathWithOutputs(const Path& drvPath, + const std::set<string>& outputs) { + return outputs.empty() ? drvPath + : drvPath + "!" + concatStringsSep(",", outputs); } - -bool wantOutput(const string & output, const std::set<string> & wanted) -{ - return wanted.empty() || wanted.find(output) != wanted.end(); +bool wantOutput(const string& output, const std::set<string>& wanted) { + return wanted.empty() || wanted.find(output) != wanted.end(); } - -PathSet BasicDerivation::outputPaths() const -{ - PathSet paths; - for (auto & i : outputs) - paths.insert(i.second.path); - return paths; +PathSet BasicDerivation::outputPaths() const { + PathSet paths; + for (auto& i : outputs) paths.insert(i.second.path); + return paths; } - -Source & readDerivation(Source & in, Store & store, BasicDerivation & drv) -{ - drv.outputs.clear(); - auto nr = readNum<size_t>(in); - for (size_t n = 0; n < nr; n++) { - auto name = readString(in); - DerivationOutput o; - in >> o.path >> o.hashAlgo >> o.hash; - store.assertStorePath(o.path); - drv.outputs[name] = o; - } - - drv.inputSrcs = readStorePaths<PathSet>(store, in); - in >> drv.platform >> drv.builder; - drv.args = readStrings<Strings>(in); - - nr = readNum<size_t>(in); - for (size_t n = 0; n < nr; n++) { - auto key = readString(in); - auto value = readString(in); - drv.env[key] = value; - } - - return in; +Source& readDerivation(Source& in, Store& store, BasicDerivation& drv) { + drv.outputs.clear(); + auto nr = readNum<size_t>(in); + for (size_t n = 0; n < nr; n++) { + auto name = readString(in); + DerivationOutput o; + in >> o.path >> o.hashAlgo >> o.hash; + store.assertStorePath(o.path); + drv.outputs[name] = o; + } + + drv.inputSrcs = readStorePaths<PathSet>(store, in); + in >> drv.platform >> drv.builder; + drv.args = readStrings<Strings>(in); + + nr = readNum<size_t>(in); + for (size_t n = 0; n < nr; n++) { + auto key = readString(in); + auto value = readString(in); + drv.env[key] = value; + } + + return in; } - -Sink & operator << (Sink & out, const BasicDerivation & drv) -{ - out << drv.outputs.size(); - for (auto & i : drv.outputs) - out << i.first << i.second.path << i.second.hashAlgo << i.second.hash; - out << drv.inputSrcs << drv.platform << drv.builder << drv.args; - out << drv.env.size(); - for (auto & i : drv.env) - out << i.first << i.second; - return out; +Sink& operator<<(Sink& out, const BasicDerivation& drv) { + out << drv.outputs.size(); + for (auto& i : drv.outputs) + out << i.first << i.second.path << i.second.hashAlgo << i.second.hash; + out << drv.inputSrcs << drv.platform << drv.builder << drv.args; + out << drv.env.size(); + for (auto& i : drv.env) out << i.first << i.second; + return out; } - -std::string hashPlaceholder(const std::string & outputName) -{ - // FIXME: memoize? - return "/" + hashString(htSHA256, "nix-output:" + outputName).to_string(Base32, false); +std::string hashPlaceholder(const std::string& outputName) { + // FIXME: memoize? + return "/" + hashString(htSHA256, "nix-output:" + outputName) + .to_string(Base32, false); } - -} +} // namespace nix |