about summary refs log tree commit diff
path: root/src/libstore/local-store.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2016-05-04T11·36+0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2016-05-04T14·15+0200
commit538a64e8c314f23ba0c5d76201f1c20e71884a21 (patch)
tree34bdfda7346d53014619cbfa33bf1398bad4b5e2 /src/libstore/local-store.cc
parentb6c768fb6a341bf1c5fe4a2d2a929415e8519b25 (diff)
Add a Store::addToStore() variant that accepts a NAR
As a side effect, this ensures that signatures are propagated when
copying paths between stores.

Also refactored import/export to make use of this.
Diffstat (limited to 'src/libstore/local-store.cc')
-rw-r--r--src/libstore/local-store.cc194
1 files changed, 34 insertions, 160 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 42e4ab9f4a..ff434d0589 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -901,6 +901,40 @@ void LocalStore::invalidatePath(State & state, const Path & path)
 }
 
 
+void LocalStore::addToStore(const ValidPathInfo & info, const std::string & nar, bool repair)
+{
+    addTempRoot(info.path);
+
+    if (repair || !isValidPath(info.path)) {
+
+        PathLocks outputLock;
+
+        /* Lock the output path.  But don't lock if we're being called
+           from a build hook (whose parent process already acquired a
+           lock on this path). */
+        Strings locksHeld = tokenizeString<Strings>(getEnv("NIX_HELD_LOCKS"));
+        if (find(locksHeld.begin(), locksHeld.end(), info.path) == locksHeld.end())
+            outputLock.lockPaths({info.path});
+
+        if (repair || !isValidPath(info.path)) {
+
+            deletePath(info.path);
+
+            StringSource source(nar);
+            restorePath(info.path, source);
+
+            canonicalisePathMetaData(info.path, -1);
+
+            optimisePath(info.path); // FIXME: combine with hashPath()
+
+            registerValidPath(info);
+        }
+
+        outputLock.setDeletion(true);
+    }
+}
+
+
 Path LocalStore::addToStoreFromDump(const string & dump, const string & name,
     bool recursive, HashType hashAlgo, bool repair)
 {
@@ -1016,69 +1050,6 @@ Path LocalStore::addTextToStore(const string & name, const string & s,
 }
 
 
-struct HashAndWriteSink : Sink
-{
-    Sink & writeSink;
-    HashSink hashSink;
-    HashAndWriteSink(Sink & writeSink) : writeSink(writeSink), hashSink(htSHA256)
-    {
-    }
-    virtual void operator () (const unsigned char * data, size_t len)
-    {
-        writeSink(data, len);
-        hashSink(data, len);
-    }
-    Hash currentHash()
-    {
-        return hashSink.currentHash().first;
-    }
-};
-
-
-void LocalStore::exportPath(const Path & path, Sink & sink)
-{
-    assertStorePath(path);
-
-    printMsg(lvlTalkative, format("exporting path ‘%1%’") % path);
-
-    auto info = queryPathInfo(path);
-
-    HashAndWriteSink hashAndWriteSink(sink);
-
-    dumpPath(path, hashAndWriteSink);
-
-    /* Refuse to export paths that have changed.  This prevents
-       filesystem corruption from spreading to other machines.
-       Don't complain if the stored hash is zero (unknown). */
-    Hash hash = hashAndWriteSink.currentHash();
-    if (hash != info->narHash && info->narHash != Hash(info->narHash.type))
-        throw Error(format("hash of path ‘%1%’ has changed from ‘%2%’ to ‘%3%’!") % path
-            % printHash(info->narHash) % printHash(hash));
-
-    hashAndWriteSink << exportMagic << path << info->references << info->deriver;
-
-    hashAndWriteSink << 0; // backwards compatibility
-}
-
-
-struct HashAndReadSource : Source
-{
-    Source & readSource;
-    HashSink hashSink;
-    bool hashing;
-    HashAndReadSource(Source & readSource) : readSource(readSource), hashSink(htSHA256)
-    {
-        hashing = true;
-    }
-    size_t read(unsigned char * data, size_t len)
-    {
-        size_t n = readSource.read(data, len);
-        if (hashing) hashSink(data, n);
-        return n;
-    }
-};
-
-
 /* Create a temporary directory in the store that won't be
    garbage-collected. */
 Path LocalStore::createTempDirInStore()
@@ -1095,103 +1066,6 @@ Path LocalStore::createTempDirInStore()
 }
 
 
-Path LocalStore::importPath(Source & source)
-{
-    HashAndReadSource hashAndReadSource(source);
-
-    /* We don't yet know what store path this archive contains (the
-       store path follows the archive data proper), and besides, we
-       don't know yet whether the signature is valid. */
-    Path tmpDir = createTempDirInStore();
-    AutoDelete delTmp(tmpDir);
-    Path unpacked = tmpDir + "/unpacked";
-
-    restorePath(unpacked, hashAndReadSource);
-
-    uint32_t magic = readInt(hashAndReadSource);
-    if (magic != exportMagic)
-        throw Error("Nix archive cannot be imported; wrong format");
-
-    Path dstPath = readStorePath(hashAndReadSource);
-
-    printMsg(lvlTalkative, format("importing path ‘%1%’") % dstPath);
-
-    PathSet references = readStorePaths<PathSet>(hashAndReadSource);
-
-    Path deriver = readString(hashAndReadSource);
-    if (deriver != "") assertStorePath(deriver);
-
-    Hash hash = hashAndReadSource.hashSink.finish().first;
-    hashAndReadSource.hashing = false;
-
-    bool haveSignature = readInt(hashAndReadSource) == 1;
-
-    if (haveSignature)
-        // Ignore legacy signature.
-        readString(hashAndReadSource);
-
-    /* Do the actual import. */
-
-    /* !!! way too much code duplication with addTextToStore() etc. */
-    addTempRoot(dstPath);
-
-    if (!isValidPath(dstPath)) {
-
-        PathLocks outputLock;
-
-        /* Lock the output path.  But don't lock if we're being called
-           from a build hook (whose parent process already acquired a
-           lock on this path). */
-        Strings locksHeld = tokenizeString<Strings>(getEnv("NIX_HELD_LOCKS"));
-        if (find(locksHeld.begin(), locksHeld.end(), dstPath) == locksHeld.end())
-            outputLock.lockPaths(singleton<PathSet, Path>(dstPath));
-
-        if (!isValidPath(dstPath)) {
-
-            deletePath(dstPath);
-
-            if (rename(unpacked.c_str(), dstPath.c_str()) == -1)
-                throw SysError(format("cannot move ‘%1%’ to ‘%2%’")
-                    % unpacked % dstPath);
-
-            canonicalisePathMetaData(dstPath, -1);
-
-            /* !!! if we were clever, we could prevent the hashPath()
-               here. */
-            HashResult hash = hashPath(htSHA256, dstPath);
-
-            optimisePath(dstPath); // FIXME: combine with hashPath()
-
-            ValidPathInfo info;
-            info.path = dstPath;
-            info.narHash = hash.first;
-            info.narSize = hash.second;
-            info.references = references;
-            info.deriver = deriver != "" && isValidPath(deriver) ? deriver : "";
-            registerValidPath(info);
-        }
-
-        outputLock.setDeletion(true);
-    }
-
-    return dstPath;
-}
-
-
-Paths LocalStore::importPaths(Source & source,
-    std::shared_ptr<FSAccessor> accessor)
-{
-    Paths res;
-    while (true) {
-        unsigned long long n = readLongLong(source);
-        if (n == 0) break;
-        if (n != 1) throw Error("input doesn't look like something created by ‘nix-store --export’");
-        res.push_back(importPath(source));
-    }
-    return res;
-}
-
-
 void LocalStore::invalidatePathChecked(const Path & path)
 {
     assertStorePath(path);