Skip to content

Commit

Permalink
Factor out commonality between nix-prefetch-url and nix-store --add-f…
Browse files Browse the repository at this point in the history
…ixed
  • Loading branch information
edolstra committed Jul 10, 2020
1 parent 7f1a86d commit 5dff49f
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 42 deletions.
12 changes: 12 additions & 0 deletions src/libstore/content-address.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,16 @@ std::string renderContentAddress(std::optional<ContentAddress> ca) {
return ca ? renderContentAddress(*ca) : "";
}

Hash getContentAddressHash(const ContentAddress & ca)
{
return std::visit(overloaded {
[](TextHash th) {
return th.hash;
},
[](FixedOutputHash fsh) {
return fsh.hash;
}
}, ca);
}

}
2 changes: 2 additions & 0 deletions src/libstore/content-address.hh
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,6 @@ ContentAddress parseContentAddress(std::string_view rawCa);

std::optional<ContentAddress> parseContentAddressOpt(std::string_view rawCaOpt);

Hash getContentAddressHash(const ContentAddress & ca);

}
32 changes: 32 additions & 0 deletions src/libstore/store-api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "json.hh"
#include "derivations.hh"
#include "url.hh"
#include "archive.hh"

#include <future>

Expand Down Expand Up @@ -221,6 +222,37 @@ StorePath Store::computeStorePathForText(const string & name, const string & s,
}


ValidPathInfo Store::addToStoreSlow(std::string_view name, const Path & srcPath,
FileIngestionMethod method, HashType hashAlgo,
std::optional<Hash> expectedCAHash)
{
/* FIXME: inefficient: we're reading/hashing 'tmpFile' three
times. */

auto hash = method == FileIngestionMethod::Recursive
? hashPath(hashAlgo, srcPath).first
: hashFile(hashAlgo, srcPath);

if (expectedCAHash && expectedCAHash != hash)
throw Error("hash mismatch for '%s'", srcPath);

auto [narHash, narSize] = hashPath(htSHA256, srcPath);
ValidPathInfo info(makeFixedOutputPath(method, hash, name));
info.narHash = narHash;
info.narSize = narSize;
info.ca = FixedOutputHash { .method = method, .hash = hash };

if (!isValidPath(info.path)) {
auto source = sinkToSource([&](Sink & sink) {
dumpPath(srcPath, sink);
});
addToStore(info, *source);
}

return info;
}


Store::Store(const Params & params)
: Config(params)
, state({(size_t) pathInfoCacheSize})
Expand Down
7 changes: 7 additions & 0 deletions src/libstore/store-api.hh
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,13 @@ public:
FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256,
PathFilter & filter = defaultPathFilter, RepairFlag repair = NoRepair) = 0;

/* Copy the contents of a path to the store and register the
validity the resulting path, using a constant amount of
memory. */
ValidPathInfo addToStoreSlow(std::string_view name, const Path & srcPath,
FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256,
std::optional<Hash> expectedCAHash = {});

// FIXME: remove?
virtual StorePath addToStoreFromDump(const string & dump, const string & name,
FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256, RepairFlag repair = NoRepair)
Expand Down
34 changes: 9 additions & 25 deletions src/nix-prefetch-url/nix-prefetch-url.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "../nix/legacy.hh"
#include "progress-bar.hh"
#include "tarfile.hh"
#include "archive.hh"

#include <iostream>

Expand Down Expand Up @@ -154,14 +153,15 @@ static int _main(int argc, char * * argv)

/* If an expected hash is given, the file may already exist in
the store. */
Hash hash, expectedHash(ht);
std::optional<Hash> expectedHash;
Hash hash;
std::optional<StorePath> storePath;
if (args.size() == 2) {
expectedHash = Hash(args[1], ht);
const auto recursive = unpack ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat;
storePath = store->makeFixedOutputPath(recursive, expectedHash, name);
storePath = store->makeFixedOutputPath(recursive, *expectedHash, name);
if (store->isValidPath(*storePath))
hash = expectedHash;
hash = *expectedHash;
else
storePath.reset();
}
Expand Down Expand Up @@ -201,28 +201,12 @@ static int _main(int argc, char * * argv)
tmpFile = unpacked;
}

/* FIXME: inefficient: we're reading/hashing 'tmpFile'
three times. */
auto [narHash, narSize] = hashPath(htSHA256, tmpFile);
const auto method = unpack ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat;

hash = unpack ? hashPath(ht, tmpFile).first : hashFile(ht, tmpFile);

if (expectedHash != Hash(ht) && expectedHash != hash)
throw Error("hash mismatch for '%1%'", uri);

const auto recursive = unpack ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat;

storePath = store->makeFixedOutputPath(recursive, hash, name);

/* Copy the file to the Nix store. */
ValidPathInfo info(*storePath);
info.narHash = narHash;
info.narSize = narSize;
info.ca = FixedOutputHash { .method = recursive, .hash = hash };
auto source = sinkToSource([&](Sink & sink) {
dumpPath(tmpFile, sink);
});
store->addToStore(info, *source);
auto info = store->addToStoreSlow(name, tmpFile, method, ht, expectedHash);
storePath = info.path;
assert(info.ca);
hash = getContentAddressHash(*info.ca);
}

stopProgressBar();
Expand Down
19 changes: 2 additions & 17 deletions src/nix-store/nix-store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,23 +186,8 @@ static void opAddFixed(Strings opFlags, Strings opArgs)
HashType hashAlgo = parseHashType(opArgs.front());
opArgs.pop_front();

for (auto & i : opArgs) {
auto hash = method == FileIngestionMethod::Recursive
? hashPath(hashAlgo, i).first
: hashFile(hashAlgo, i);
auto [narHash, narSize] = hashPath(htSHA256, i);
ValidPathInfo info(store->makeFixedOutputPath(method, hash, baseNameOf(i)));
info.narHash = narHash;
info.narSize = narSize;
info.ca = FixedOutputHash { .method = method, .hash = hash };

auto source = sinkToSource([&](Sink & sink) {
dumpPath(i, sink);
});
store->addToStore(info, *source);

std::cout << fmt("%s\n", store->printStorePath(info.path));
}
for (auto & i : opArgs)
std::cout << fmt("%s\n", store->printStorePath(store->addToStoreSlow(baseNameOf(i), i, method, hashAlgo).path));
}


Expand Down

0 comments on commit 5dff49f

Please sign in to comment.