diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/local.mk | 2 | ||||
-rw-r--r-- | src/libmain/shared.hh | 2 | ||||
-rw-r--r-- | src/libstore/build.cc | 8 | ||||
-rw-r--r-- | src/libstore/local-store.hh | 58 | ||||
-rw-r--r-- | src/libstore/remote-store.hh | 59 | ||||
-rw-r--r-- | src/libutil/hash.cc | 1 | ||||
-rw-r--r-- | src/libutil/util.hh | 1 | ||||
-rw-r--r-- | src/nix-env/nix-env.cc | 22 | ||||
-rw-r--r-- | src/nix-prefetch-url/local.mk | 7 | ||||
-rw-r--r-- | src/nix-prefetch-url/nix-prefetch-url.cc | 168 |
10 files changed, 255 insertions, 73 deletions
diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk index 4c1f4de19187..d1b1987fb037 100644 --- a/src/libexpr/local.mk +++ b/src/libexpr/local.mk @@ -6,6 +6,8 @@ libexpr_DIR := $(d) libexpr_SOURCES := $(wildcard $(d)/*.cc) $(d)/lexer-tab.cc $(d)/parser-tab.cc +libexpr_CXXFLAGS := -Wno-deprecated-register + libexpr_LIBS = libutil libstore libformat libexpr_LDFLAGS = -ldl diff --git a/src/libmain/shared.hh b/src/libmain/shared.hh index a7e6ef762120..65b288e1ff3e 100644 --- a/src/libmain/shared.hh +++ b/src/libmain/shared.hh @@ -88,7 +88,7 @@ extern volatile ::sig_atomic_t blockInt; string showBytes(unsigned long long bytes); -class GCResults; +struct GCResults; struct PrintFreed { diff --git a/src/libstore/build.cc b/src/libstore/build.cc index c1163e63d90f..70278a8785d6 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -806,7 +806,7 @@ public: void timedOut() override; - string key() + string key() override { /* Ensure that derivations get built in order of their name, i.e. a derivation named "aardvark" always comes before @@ -815,7 +815,7 @@ public: return "b$" + storePathToName(drvPath) + "$" + drvPath; } - void work(); + void work() override; Path getDrvPath() { @@ -863,8 +863,8 @@ private: void deleteTmpDir(bool force); /* Callback used by the worker to write to the log. */ - void handleChildOutput(int fd, const string & data); - void handleEOF(int fd); + void handleChildOutput(int fd, const string & data) override; + void handleEOF(int fd) override; /* Return the set of (in)valid paths. */ PathSet checkPathValidity(bool returnValid, bool checkHash); diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 105f3592c685..ebdf19bf1359 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -98,41 +98,41 @@ public: /* Implementations of abstract store API methods. */ - bool isValidPath(const Path & path); + bool isValidPath(const Path & path) override; - PathSet queryValidPaths(const PathSet & paths); + PathSet queryValidPaths(const PathSet & paths) override; - PathSet queryAllValidPaths(); + PathSet queryAllValidPaths() override; - ValidPathInfo queryPathInfo(const Path & path); + ValidPathInfo queryPathInfo(const Path & path) override; - Hash queryPathHash(const Path & path); + Hash queryPathHash(const Path & path) override; - void queryReferences(const Path & path, PathSet & references); + void queryReferences(const Path & path, PathSet & references) override; - void queryReferrers(const Path & path, PathSet & referrers); + void queryReferrers(const Path & path, PathSet & referrers) override; - Path queryDeriver(const Path & path); + Path queryDeriver(const Path & path) override; - PathSet queryValidDerivers(const Path & path); + PathSet queryValidDerivers(const Path & path) override; - PathSet queryDerivationOutputs(const Path & path); + PathSet queryDerivationOutputs(const Path & path) override; - StringSet queryDerivationOutputNames(const Path & path); + StringSet queryDerivationOutputNames(const Path & path) override; - Path queryPathFromHashPart(const string & hashPart); + Path queryPathFromHashPart(const string & hashPart) override; - PathSet querySubstitutablePaths(const PathSet & paths); + PathSet querySubstitutablePaths(const PathSet & paths) override; void querySubstitutablePathInfos(const Path & substituter, PathSet & paths, SubstitutablePathInfos & infos); void querySubstitutablePathInfos(const PathSet & paths, - SubstitutablePathInfos & infos); + SubstitutablePathInfos & infos) override; Path addToStore(const string & name, const Path & srcPath, bool recursive = true, HashType hashAlgo = htSHA256, - PathFilter & filter = defaultPathFilter, bool repair = false); + PathFilter & filter = defaultPathFilter, bool repair = false) override; /* Like addToStore(), but the contents of the path are contained in `dump', which is either a NAR serialisation (if recursive == @@ -142,43 +142,43 @@ public: bool recursive = true, HashType hashAlgo = htSHA256, bool repair = false); Path addTextToStore(const string & name, const string & s, - const PathSet & references, bool repair = false); + const PathSet & references, bool repair = false) override; void exportPath(const Path & path, bool sign, - Sink & sink); + Sink & sink) override; - Paths importPaths(bool requireSignature, Source & source); + Paths importPaths(bool requireSignature, Source & source) override; - void buildPaths(const PathSet & paths, BuildMode buildMode); + void buildPaths(const PathSet & paths, BuildMode buildMode) override; BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv, BuildMode buildMode) override; - void ensurePath(const Path & path); + void ensurePath(const Path & path) override; - void addTempRoot(const Path & path); + void addTempRoot(const Path & path) override; - void addIndirectRoot(const Path & path); + void addIndirectRoot(const Path & path) override; - void syncWithGC(); + void syncWithGC() override; - Roots findRoots(); + Roots findRoots() override; - void collectGarbage(const GCOptions & options, GCResults & results); + void collectGarbage(const GCOptions & options, GCResults & results) override; /* Optimise the disk space usage of the Nix store by hard-linking files with the same contents. */ void optimiseStore(OptimiseStats & stats); /* Generic variant of the above method. */ - void optimiseStore(); + void optimiseStore() override; /* Optimise a single store path. */ void optimisePath(const Path & path); /* Check the integrity of the Nix store. Returns true if errors remain. */ - bool verifyStore(bool checkContents, bool repair); + bool verifyStore(bool checkContents, bool repair) override; /* Register the validity of a path, i.e., that `path' exists, that the paths referenced by it exists, and in the case of an output @@ -197,9 +197,9 @@ public: /* Query whether `path' previously failed to build. */ bool hasPathFailed(const Path & path); - PathSet queryFailedPaths(); + PathSet queryFailedPaths() override; - void clearFailedPaths(const PathSet & paths); + void clearFailedPaths(const PathSet & paths) override; void vacuumDB(); diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index 09e250386c5c..b0787c072904 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -24,71 +24,72 @@ public: /* Implementations of abstract store API methods. */ - bool isValidPath(const Path & path); + bool isValidPath(const Path & path) override; - PathSet queryValidPaths(const PathSet & paths); + PathSet queryValidPaths(const PathSet & paths) override; - PathSet queryAllValidPaths(); + PathSet queryAllValidPaths() override; - ValidPathInfo queryPathInfo(const Path & path); + ValidPathInfo queryPathInfo(const Path & path) override; - Hash queryPathHash(const Path & path); + Hash queryPathHash(const Path & path) override; - void queryReferences(const Path & path, PathSet & references); + void queryReferences(const Path & path, PathSet & references) override; - void queryReferrers(const Path & path, PathSet & referrers); + void queryReferrers(const Path & path, PathSet & referrers) override; - Path queryDeriver(const Path & path); + Path queryDeriver(const Path & path) override; - PathSet queryValidDerivers(const Path & path); + PathSet queryValidDerivers(const Path & path) override; - PathSet queryDerivationOutputs(const Path & path); + PathSet queryDerivationOutputs(const Path & path) override; - StringSet queryDerivationOutputNames(const Path & path); + StringSet queryDerivationOutputNames(const Path & path) override; - Path queryPathFromHashPart(const string & hashPart); + Path queryPathFromHashPart(const string & hashPart) override; - PathSet querySubstitutablePaths(const PathSet & paths); + PathSet querySubstitutablePaths(const PathSet & paths) override; void querySubstitutablePathInfos(const PathSet & paths, - SubstitutablePathInfos & infos); + SubstitutablePathInfos & infos) override; Path addToStore(const string & name, const Path & srcPath, bool recursive = true, HashType hashAlgo = htSHA256, - PathFilter & filter = defaultPathFilter, bool repair = false); + PathFilter & filter = defaultPathFilter, bool repair = false) override; Path addTextToStore(const string & name, const string & s, - const PathSet & references, bool repair = false); + const PathSet & references, bool repair = false) override; void exportPath(const Path & path, bool sign, - Sink & sink); + Sink & sink) override; - Paths importPaths(bool requireSignature, Source & source); + Paths importPaths(bool requireSignature, Source & source) override; - void buildPaths(const PathSet & paths, BuildMode buildMode); + void buildPaths(const PathSet & paths, BuildMode buildMode) override; BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv, BuildMode buildMode) override; - void ensurePath(const Path & path); + void ensurePath(const Path & path) override; - void addTempRoot(const Path & path); + void addTempRoot(const Path & path) override; - void addIndirectRoot(const Path & path); + void addIndirectRoot(const Path & path) override; - void syncWithGC(); + void syncWithGC() override; - Roots findRoots(); + Roots findRoots() override; - void collectGarbage(const GCOptions & options, GCResults & results); + void collectGarbage(const GCOptions & options, GCResults & results) override; - PathSet queryFailedPaths(); + PathSet queryFailedPaths() override; - void clearFailedPaths(const PathSet & paths); + void clearFailedPaths(const PathSet & paths) override; - void optimiseStore(); + void optimiseStore() override; + + bool verifyStore(bool checkContents, bool repair) override; - bool verifyStore(bool checkContents, bool repair); private: AutoCloseFD fdSocket; FdSink to; diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index a83ba0a81817..1d973e7c8f14 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -115,7 +115,6 @@ const string base32Chars = "0123456789abcdfghijklmnpqrsvwxyz"; string printHash32(const Hash & hash) { - Hash hash2(hash); unsigned int len = hashLength32(hash); string s; diff --git a/src/libutil/util.hh b/src/libutil/util.hh index b2fb59d6f2d7..a05a4cb88093 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -202,6 +202,7 @@ public: AutoDelete(const Path & p, bool recursive = true); ~AutoDelete(); void cancel(); + operator Path() const { return path; } }; diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 97a2bbdb7de0..313f8a8a8f35 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -570,14 +570,16 @@ static void upgradeDerivations(Globals & globals, constraints specified by upgradeType. If there are multiple matches, take the one with the highest priority. If there are still multiple matches, - take the one with the highest version. */ + take the one with the highest version. + Do not upgrade if it would decrease the priority. */ DrvInfos::iterator bestElem = availElems.end(); - DrvName bestName; + string bestVersion; for (auto j = availElems.begin(); j != availElems.end(); ++j) { + if (comparePriorities(*globals.state, i, *j) > 0) + continue; DrvName newName(j->name); if (newName.name == drvName.name) { - int d = comparePriorities(*globals.state, i, *j); - if (d == 0) d = compareVersions(drvName.version, newName.version); + int d = compareVersions(drvName.version, newName.version); if ((upgradeType == utLt && d < 0) || (upgradeType == utLeq && d <= 0) || (upgradeType == utEq && d == 0) || @@ -586,11 +588,11 @@ static void upgradeDerivations(Globals & globals, int d2 = -1; if (bestElem != availElems.end()) { d2 = comparePriorities(*globals.state, *bestElem, *j); - if (d2 == 0) d2 = compareVersions(bestName.version, newName.version); + if (d2 == 0) d2 = compareVersions(bestVersion, newName.version); } if (d2 < 0 && (!globals.prebuiltOnly || isPrebuilt(*globals.state, *j))) { bestElem = j; - bestName = newName; + bestVersion = newName.version; } } } @@ -600,9 +602,11 @@ static void upgradeDerivations(Globals & globals, i.queryOutPath() != bestElem->queryOutPath()) { + const char * action = compareVersions(drvName.version, bestVersion) <= 0 + ? "upgrading" : "downgrading"; printMsg(lvlInfo, - format("upgrading ‘%1%’ to ‘%2%’") - % i.name % bestElem->name); + format("%1% ‘%2%’ to ‘%3%’") + % action % i.name % bestElem->name); newElems.push_back(*bestElem); } else newElems.push_back(i); @@ -1273,7 +1277,7 @@ static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opAr std::set<unsigned int> gens; for (auto & i : opArgs) { unsigned int n; - if (!string2Int(i, n) || n < 0) + if (!string2Int(i, n)) throw UsageError(format("invalid generation number ‘%1%’") % i); gens.insert(n); } diff --git a/src/nix-prefetch-url/local.mk b/src/nix-prefetch-url/local.mk new file mode 100644 index 000000000000..3e7735406af0 --- /dev/null +++ b/src/nix-prefetch-url/local.mk @@ -0,0 +1,7 @@ +programs += nix-prefetch-url + +nix-prefetch-url_DIR := $(d) + +nix-prefetch-url_SOURCES := $(d)/nix-prefetch-url.cc + +nix-prefetch-url_LIBS = libmain libexpr libstore libutil libformat diff --git a/src/nix-prefetch-url/nix-prefetch-url.cc b/src/nix-prefetch-url/nix-prefetch-url.cc new file mode 100644 index 000000000000..112d303e0c16 --- /dev/null +++ b/src/nix-prefetch-url/nix-prefetch-url.cc @@ -0,0 +1,168 @@ +#include "hash.hh" +#include "shared.hh" +#include "download.hh" +#include "store-api.hh" +#include "eval.hh" +#include "eval-inline.hh" +#include "common-opts.hh" +#include "attr-path.hh" + +#include <iostream> + +using namespace nix; + + +/* If ‘uri’ starts with ‘mirror://’, then resolve it using the list of + mirrors defined in Nixpkgs. */ +string resolveMirrorUri(EvalState & state, string uri) +{ + if (string(uri, 0, 9) != "mirror://") return uri; + + string s(uri, 9); + auto p = s.find('/'); + if (p == string::npos) throw Error("invalid mirror URI"); + string mirrorName(s, 0, p); + + Value vMirrors; + state.eval(state.parseExprFromString("import <nixpkgs/pkgs/build-support/fetchurl/mirrors.nix>", "."), vMirrors); + state.forceAttrs(vMirrors); + + auto mirrorList = vMirrors.attrs->find(state.symbols.create(mirrorName)); + if (mirrorList == vMirrors.attrs->end()) + throw Error(format("unknown mirror name ‘%1%’") % mirrorName); + state.forceList(*mirrorList->value); + + if (mirrorList->value->listSize() < 1) + throw Error(format("mirror URI ‘%1%’ did not expand to anything") % uri); + + string mirror = state.forceString(*mirrorList->value->listElems()[0]); + return mirror + (hasSuffix(mirror, "/") ? "" : "/") + string(s, p + 1); +} + + +int main(int argc, char * * argv) +{ + return handleExceptions(argv[0], [&]() { + initNix(); + initGC(); + + HashType ht = htSHA256; + std::vector<string> args; + Strings searchPath; + bool printPath = getEnv("PRINT_PATH") != ""; + bool fromExpr = false; + string attrPath; + std::map<string, string> autoArgs_; + + parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { + if (*arg == "--help") + showManPage("nix-prefetch-url"); + else if (*arg == "--version") + printVersion("nix-prefetch-url"); + else if (*arg == "--type") { + string s = getArg(*arg, arg, end); + ht = parseHashType(s); + if (ht == htUnknown) + throw UsageError(format("unknown hash type ‘%1%’") % s); + } + else if (*arg == "--print-path") + printPath = true; + else if (*arg == "--attr" || *arg == "-A") { + fromExpr = true; + attrPath = getArg(*arg, arg, end); + } + else if (parseAutoArgs(arg, end, autoArgs_)) + ; + else if (parseSearchPathArg(arg, end, searchPath)) + ; + else if (*arg != "" && arg->at(0) == '-') + return false; + else + args.push_back(*arg); + return true; + }); + + if (args.size() > 2) + throw UsageError("too many arguments"); + + store = openStore(); + EvalState state(searchPath); + + Bindings & autoArgs(*evalAutoArgs(state, autoArgs_)); + + /* If -A is given, get the URI from the specified Nix + expression. */ + string uri; + if (!fromExpr) { + if (args.empty()) + throw UsageError("you must specify a URI"); + uri = args[0]; + } else { + Path path = resolveExprPath(lookupFileArg(state, args.empty() ? "." : args[0])); + Value vRoot; + state.evalFile(path, vRoot); + Value & v(*findAlongAttrPath(state, attrPath, autoArgs, vRoot)); + state.forceAttrs(v); + auto urls = v.attrs->find(state.symbols.create("urls")); + if (urls == v.attrs->end()) + throw Error("attribute set does not contain a ‘urls’ attribute"); + state.forceList(*urls->value); + if (urls->value->listSize() < 1) + throw Error("‘urls’ list is empty"); + uri = state.forceString(*urls->value->listElems()[0]); + } + + /* Figure out a name in the Nix store. */ + auto name = baseNameOf(uri); + if (name.empty()) + throw Error(format("cannot figure out file name for ‘%1%’") % uri); + + /* If an expected hash is given, the file may already exist in + the store. */ + Hash hash, expectedHash(ht); + Path storePath; + if (args.size() == 2) { + expectedHash = parseHash16or32(ht, args[1]); + storePath = makeFixedOutputPath(false, ht, expectedHash, name); + if (store->isValidPath(storePath)) + hash = expectedHash; + else + storePath.clear(); + } + + if (storePath.empty()) { + + auto actualUri = resolveMirrorUri(state, uri); + + if (uri != actualUri) + printMsg(lvlInfo, format("‘%1%’ expands to ‘%2%’") % uri % actualUri); + + /* Download the file. */ + auto result = downloadFile(actualUri); + + /* Copy the file to the Nix store. FIXME: if RemoteStore + implemented addToStoreFromDump() and downloadFile() + supported a sink, we could stream the download directly + into the Nix store. */ + AutoDelete tmpDir(createTempDir(), true); + Path tmpFile = (Path) tmpDir + "/tmp"; + writeFile(tmpFile, result.data); + + /* FIXME: inefficient; addToStore() will also hash + this. */ + hash = hashString(ht, result.data); + + if (expectedHash != Hash(ht) && expectedHash != hash) + throw Error(format("hash mismatch for ‘%1%’") % uri); + + storePath = store->addToStore(name, tmpFile, false, ht); + } + + if (!printPath) + printMsg(lvlInfo, format("path is ‘%1%’") % storePath); + + std::cout << printHash16or32(hash) << std::endl; + if (printPath) + std::cout << storePath << std::endl; + }); +} |