about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/local.mk2
-rw-r--r--src/libmain/shared.hh2
-rw-r--r--src/libstore/build.cc8
-rw-r--r--src/libstore/local-store.hh58
-rw-r--r--src/libstore/remote-store.hh59
-rw-r--r--src/libutil/hash.cc1
-rw-r--r--src/libutil/util.hh1
-rw-r--r--src/nix-env/nix-env.cc22
-rw-r--r--src/nix-prefetch-url/local.mk7
-rw-r--r--src/nix-prefetch-url/nix-prefetch-url.cc168
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;
+    });
+}