2020-05-29 23:19:48 +03:00
|
|
|
#include "serialise.hh"
|
2016-05-04 14:36:54 +03:00
|
|
|
#include "store-api.hh"
|
|
|
|
#include "archive.hh"
|
2022-03-25 06:39:57 +02:00
|
|
|
#include "common-protocol.hh"
|
|
|
|
#include "common-protocol-impl.hh"
|
2016-05-04 14:36:54 +03:00
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
2019-12-05 20:11:09 +02:00
|
|
|
void Store::exportPaths(const StorePathSet & paths, Sink & sink)
|
2016-05-04 14:36:54 +03:00
|
|
|
{
|
2019-12-05 20:11:09 +02:00
|
|
|
auto sorted = topoSortPaths(paths);
|
2016-05-04 14:36:54 +03:00
|
|
|
std::reverse(sorted.begin(), sorted.end());
|
|
|
|
|
|
|
|
std::string doneLabel("paths exported");
|
2017-05-16 17:09:57 +03:00
|
|
|
//logger->incExpected(doneLabel, sorted.size());
|
2016-05-04 14:36:54 +03:00
|
|
|
|
|
|
|
for (auto & path : sorted) {
|
2023-03-02 16:44:19 +02:00
|
|
|
//Activity act(*logger, lvlInfo, "exporting path '%s'", path);
|
2016-05-04 14:36:54 +03:00
|
|
|
sink << 1;
|
|
|
|
exportPath(path, sink);
|
2017-05-16 17:09:57 +03:00
|
|
|
//logger->incProgress(doneLabel);
|
2016-05-04 14:36:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
sink << 0;
|
|
|
|
}
|
|
|
|
|
2019-12-05 20:11:09 +02:00
|
|
|
void Store::exportPath(const StorePath & path, Sink & sink)
|
2016-05-04 14:36:54 +03:00
|
|
|
{
|
|
|
|
auto info = queryPathInfo(path);
|
|
|
|
|
2020-07-10 21:58:02 +03:00
|
|
|
HashSink hashSink(htSHA256);
|
|
|
|
TeeSink teeSink(sink, hashSink);
|
2016-05-04 14:36:54 +03:00
|
|
|
|
2020-07-10 21:58:02 +03:00
|
|
|
narFromPath(path, teeSink);
|
2016-05-04 14:36:54 +03:00
|
|
|
|
|
|
|
/* 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). */
|
2020-07-10 21:58:02 +03:00
|
|
|
Hash hash = hashSink.currentHash().first;
|
2020-08-05 21:42:48 +03:00
|
|
|
if (hash != info->narHash && info->narHash != Hash(info->narHash.type))
|
2019-12-05 20:11:09 +02:00
|
|
|
throw Error("hash of path '%s' has changed from '%s' to '%s'!",
|
2023-10-13 04:48:15 +03:00
|
|
|
printStorePath(path), info->narHash.to_string(HashFormat::Base32, true), hash.to_string(HashFormat::Base32, true));
|
2019-12-05 20:11:09 +02:00
|
|
|
|
2020-07-10 21:58:02 +03:00
|
|
|
teeSink
|
2019-12-05 20:11:09 +02:00
|
|
|
<< exportMagic
|
|
|
|
<< printStorePath(path);
|
2022-03-25 06:39:57 +02:00
|
|
|
CommonProto::write(*this,
|
|
|
|
CommonProto::WriteConn { .to = teeSink },
|
2023-04-17 20:40:46 +03:00
|
|
|
info->references);
|
2020-07-10 21:58:02 +03:00
|
|
|
teeSink
|
2019-12-05 20:11:09 +02:00
|
|
|
<< (info->deriver ? printStorePath(*info->deriver) : "")
|
|
|
|
<< 0;
|
2016-05-04 14:36:54 +03:00
|
|
|
}
|
|
|
|
|
2020-07-13 18:37:44 +03:00
|
|
|
StorePaths Store::importPaths(Source & source, CheckSigsFlag checkSigs)
|
2016-05-04 14:36:54 +03:00
|
|
|
{
|
2019-12-05 20:11:09 +02:00
|
|
|
StorePaths res;
|
2016-05-04 14:36:54 +03:00
|
|
|
while (true) {
|
2017-03-01 14:52:54 +02:00
|
|
|
auto n = readNum<uint64_t>(source);
|
2016-05-04 14:36:54 +03:00
|
|
|
if (n == 0) break;
|
2017-07-30 14:27:57 +03:00
|
|
|
if (n != 1) throw Error("input doesn't look like something created by 'nix-store --export'");
|
2016-05-04 14:36:54 +03:00
|
|
|
|
|
|
|
/* Extract the NAR from the source. */
|
2020-07-16 08:09:41 +03:00
|
|
|
StringSink saved;
|
|
|
|
TeeSource tee { source, saved };
|
2023-11-01 02:39:39 +02:00
|
|
|
NullParseSink ether;
|
2020-07-16 08:09:41 +03:00
|
|
|
parseDump(ether, tee);
|
2016-05-04 14:36:54 +03:00
|
|
|
|
|
|
|
uint32_t magic = readInt(source);
|
|
|
|
if (magic != exportMagic)
|
|
|
|
throw Error("Nix archive cannot be imported; wrong format");
|
|
|
|
|
2020-08-06 21:31:48 +03:00
|
|
|
auto path = parseStorePath(readString(source));
|
2016-05-04 14:36:54 +03:00
|
|
|
|
2023-03-02 16:44:19 +02:00
|
|
|
//Activity act(*logger, lvlInfo, "importing path '%s'", info.path);
|
2016-05-04 14:36:54 +03:00
|
|
|
|
2022-03-25 06:39:57 +02:00
|
|
|
auto references = CommonProto::Serialise<StorePathSet>::read(*this,
|
|
|
|
CommonProto::ReadConn { .from = source });
|
2019-12-05 20:11:09 +02:00
|
|
|
auto deriver = readString(source);
|
2022-01-17 23:20:05 +02:00
|
|
|
auto narHash = hashString(htSHA256, saved.s);
|
2020-08-06 21:31:48 +03:00
|
|
|
|
|
|
|
ValidPathInfo info { path, narHash };
|
2019-12-05 20:11:09 +02:00
|
|
|
if (deriver != "")
|
|
|
|
info.deriver = parseStorePath(deriver);
|
2020-08-06 21:31:48 +03:00
|
|
|
info.references = references;
|
2022-01-17 23:20:05 +02:00
|
|
|
info.narSize = saved.s.size();
|
2016-05-04 14:36:54 +03:00
|
|
|
|
|
|
|
// Ignore optional legacy signature.
|
|
|
|
if (readInt(source) == 1)
|
|
|
|
readString(source);
|
|
|
|
|
2020-05-29 23:19:48 +03:00
|
|
|
// Can't use underlying source, which would have been exhausted
|
2022-01-17 23:20:05 +02:00
|
|
|
auto source = StringSource(saved.s);
|
2020-07-13 18:37:44 +03:00
|
|
|
addToStore(info, source, NoRepair, checkSigs);
|
2016-05-04 14:36:54 +03:00
|
|
|
|
2020-06-16 23:20:18 +03:00
|
|
|
res.push_back(info.path);
|
2016-05-04 14:36:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|