* Store the size of a store path in the database (to be precise, the
size of the NAR serialisation of the path, i.e., `nix-store --dump PATH'). This is useful for Hydra.
This commit is contained in:
parent
fb9368b5a0
commit
a3883cbd28
2
externals/Makefile.am
vendored
2
externals/Makefile.am
vendored
|
@ -47,7 +47,7 @@ build-sqlite:
|
||||||
else
|
else
|
||||||
build-sqlite: $(SQLITE)
|
build-sqlite: $(SQLITE)
|
||||||
(cd $(SQLITE) && \
|
(cd $(SQLITE) && \
|
||||||
CC="$(CC)" ./configure --disable-static --prefix=$(pkglibdir)/dummy --libdir=${pkglibdir} $(SUB_CONFIGURE_FLAGS) && \
|
CC="$(CC)" CFLAGS="-DSQLITE_ENABLE_COLUMN_METADATA=1" ./configure --disable-static --prefix=$(pkglibdir)/dummy --libdir=${pkglibdir} $(SUB_CONFIGURE_FLAGS) && \
|
||||||
$(MAKE) )
|
$(MAKE) )
|
||||||
touch build-sqlite
|
touch build-sqlite
|
||||||
|
|
||||||
|
|
|
@ -1547,7 +1547,7 @@ void DerivationGoal::startBuilder()
|
||||||
|
|
||||||
/* Write closure info to `fileName'. */
|
/* Write closure info to `fileName'. */
|
||||||
writeFile(tmpDir + "/" + fileName,
|
writeFile(tmpDir + "/" + fileName,
|
||||||
makeValidityRegistration(paths, false, false));
|
worker.store.makeValidityRegistration(paths, false, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1870,7 +1870,7 @@ PathSet parseReferenceSpecifiers(const Derivation & drv, string attr)
|
||||||
void DerivationGoal::computeClosure()
|
void DerivationGoal::computeClosure()
|
||||||
{
|
{
|
||||||
map<Path, PathSet> allReferences;
|
map<Path, PathSet> allReferences;
|
||||||
map<Path, Hash> contentHashes;
|
map<Path, HashResult> contentHashes;
|
||||||
|
|
||||||
/* When using a build hook, the build hook can register the output
|
/* When using a build hook, the build hook can register the output
|
||||||
as valid (by doing `nix-store --import'). If so we don't have
|
as valid (by doing `nix-store --import'). If so we don't have
|
||||||
|
@ -1927,7 +1927,7 @@ void DerivationGoal::computeClosure()
|
||||||
if (ht == htUnknown)
|
if (ht == htUnknown)
|
||||||
throw BuildError(format("unknown hash algorithm `%1%'") % algo);
|
throw BuildError(format("unknown hash algorithm `%1%'") % algo);
|
||||||
Hash h = parseHash(ht, i->second.hash);
|
Hash h = parseHash(ht, i->second.hash);
|
||||||
Hash h2 = recursive ? hashPath(ht, path) : hashFile(ht, path);
|
Hash h2 = recursive ? hashPath(ht, path).first : hashFile(ht, path);
|
||||||
if (h != h2)
|
if (h != h2)
|
||||||
throw BuildError(
|
throw BuildError(
|
||||||
format("output path `%1%' should have %2% hash `%3%', instead has `%4%'")
|
format("output path `%1%' should have %2% hash `%3%', instead has `%4%'")
|
||||||
|
@ -1941,7 +1941,7 @@ void DerivationGoal::computeClosure()
|
||||||
contained in it. Compute the SHA-256 NAR hash at the same
|
contained in it. Compute the SHA-256 NAR hash at the same
|
||||||
time. The hash is stored in the database so that we can
|
time. The hash is stored in the database so that we can
|
||||||
verify later on whether nobody has messed with the store. */
|
verify later on whether nobody has messed with the store. */
|
||||||
Hash hash;
|
HashResult hash;
|
||||||
PathSet references = scanForReferences(path, allPaths, hash);
|
PathSet references = scanForReferences(path, allPaths, hash);
|
||||||
contentHashes[path] = hash;
|
contentHashes[path] = hash;
|
||||||
|
|
||||||
|
@ -1970,14 +1970,18 @@ void DerivationGoal::computeClosure()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register each output path as valid, and register the sets of
|
/* Register each output path as valid, and register the sets of
|
||||||
paths referenced by each of them. !!! this should be
|
paths referenced by each of them. */
|
||||||
atomic so that either all paths are registered as valid, or
|
ValidPathInfos infos;
|
||||||
none are. */
|
foreach (DerivationOutputs::iterator, i, drv.outputs) {
|
||||||
foreach (DerivationOutputs::iterator, i, drv.outputs)
|
ValidPathInfo info;
|
||||||
worker.store.registerValidPath(i->second.path,
|
info.path = i->second.path;
|
||||||
contentHashes[i->second.path],
|
info.hash = contentHashes[i->second.path].first;
|
||||||
allReferences[i->second.path],
|
info.narSize = contentHashes[i->second.path].second;
|
||||||
drvPath);
|
info.references = allReferences[i->second.path];
|
||||||
|
info.deriver = drvPath;
|
||||||
|
infos.push_back(info);
|
||||||
|
}
|
||||||
|
worker.store.registerValidPaths(infos);
|
||||||
|
|
||||||
/* It is now safe to delete the lock files, since all future
|
/* It is now safe to delete the lock files, since all future
|
||||||
lockers will see that the output paths are valid; they will not
|
lockers will see that the output paths are valid; they will not
|
||||||
|
@ -2385,10 +2389,15 @@ void SubstitutionGoal::finished()
|
||||||
|
|
||||||
canonicalisePathMetaData(storePath);
|
canonicalisePathMetaData(storePath);
|
||||||
|
|
||||||
Hash contentHash = hashPath(htSHA256, storePath);
|
HashResult hash = hashPath(htSHA256, storePath);
|
||||||
|
|
||||||
worker.store.registerValidPath(storePath, contentHash,
|
ValidPathInfo info2;
|
||||||
info.references, info.deriver);
|
info2.path = storePath;
|
||||||
|
info2.hash = hash.first;
|
||||||
|
info2.narSize = hash.second;
|
||||||
|
info2.references = info.references;
|
||||||
|
info2.deriver = info.deriver;
|
||||||
|
worker.store.registerValidPath(info2);
|
||||||
|
|
||||||
outputLock->setDeletion(true);
|
outputLock->setDeletion(true);
|
||||||
|
|
||||||
|
|
|
@ -327,9 +327,16 @@ void LocalStore::openDB(bool create)
|
||||||
throw SQLiteError(db, "initialising database schema");
|
throw SQLiteError(db, "initialising database schema");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Backwards compatibility with old (pre-release) databases. Can
|
||||||
|
remove this eventually. */
|
||||||
|
if (sqlite3_table_column_metadata(db, 0, "ValidPaths", "narSize", 0, 0, 0, 0, 0) != SQLITE_OK) {
|
||||||
|
if (sqlite3_exec(db, "alter table ValidPaths add column narSize integer" , 0, 0, 0) != SQLITE_OK)
|
||||||
|
throw SQLiteError(db, "adding column narSize");
|
||||||
|
}
|
||||||
|
|
||||||
/* Prepare SQL statements. */
|
/* Prepare SQL statements. */
|
||||||
stmtRegisterValidPath.create(db,
|
stmtRegisterValidPath.create(db,
|
||||||
"insert into ValidPaths (path, hash, registrationTime, deriver) values (?, ?, ?, ?);");
|
"insert into ValidPaths (path, hash, registrationTime, deriver, narSize) values (?, ?, ?, ?, ?);");
|
||||||
stmtAddReference.create(db,
|
stmtAddReference.create(db,
|
||||||
"insert or replace into Refs (referrer, reference) values (?, ?);");
|
"insert or replace into Refs (referrer, reference) values (?, ?);");
|
||||||
stmtQueryPathInfo.create(db,
|
stmtQueryPathInfo.create(db,
|
||||||
|
@ -431,19 +438,6 @@ void canonicalisePathMetaData(const Path & path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::registerValidPath(const Path & path,
|
|
||||||
const Hash & hash, const PathSet & references,
|
|
||||||
const Path & deriver)
|
|
||||||
{
|
|
||||||
ValidPathInfo info;
|
|
||||||
info.path = path;
|
|
||||||
info.hash = hash;
|
|
||||||
info.references = references;
|
|
||||||
info.deriver = deriver;
|
|
||||||
registerValidPath(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned long long LocalStore::addValidPath(const ValidPathInfo & info)
|
unsigned long long LocalStore::addValidPath(const ValidPathInfo & info)
|
||||||
{
|
{
|
||||||
SQLiteStmtUse use(stmtRegisterValidPath);
|
SQLiteStmtUse use(stmtRegisterValidPath);
|
||||||
|
@ -454,6 +448,10 @@ unsigned long long LocalStore::addValidPath(const ValidPathInfo & info)
|
||||||
stmtRegisterValidPath.bind(info.deriver);
|
stmtRegisterValidPath.bind(info.deriver);
|
||||||
else
|
else
|
||||||
stmtRegisterValidPath.bind(); // null
|
stmtRegisterValidPath.bind(); // null
|
||||||
|
if (info.narSize != 0)
|
||||||
|
stmtRegisterValidPath.bind(info.narSize);
|
||||||
|
else
|
||||||
|
stmtRegisterValidPath.bind(); // null
|
||||||
if (sqlite3_step(stmtRegisterValidPath) != SQLITE_DONE)
|
if (sqlite3_step(stmtRegisterValidPath) != SQLITE_DONE)
|
||||||
throw SQLiteError(db, format("registering valid path `%1%' in database") % info.path);
|
throw SQLiteError(db, format("registering valid path `%1%' in database") % info.path);
|
||||||
unsigned long long id = sqlite3_last_insert_rowid(db);
|
unsigned long long id = sqlite3_last_insert_rowid(db);
|
||||||
|
@ -920,10 +918,18 @@ Path LocalStore::addToStoreFromDump(const string & dump, const string & name,
|
||||||
the path in the database. We may just have computed it
|
the path in the database. We may just have computed it
|
||||||
above (if called with recursive == true and hashAlgo ==
|
above (if called with recursive == true and hashAlgo ==
|
||||||
sha256); otherwise, compute it here. */
|
sha256); otherwise, compute it here. */
|
||||||
registerValidPath(dstPath,
|
HashResult hash;
|
||||||
(recursive && hashAlgo == htSHA256) ? h :
|
if (recursive) {
|
||||||
(recursive ? hashString(htSHA256, dump) : hashPath(htSHA256, dstPath)),
|
hash.first = hashAlgo == htSHA256 ? h : hashString(htSHA256, dump);
|
||||||
PathSet(), "");
|
hash.second = dump.size();
|
||||||
|
} else
|
||||||
|
hash = hashPath(htSHA256, dstPath);
|
||||||
|
|
||||||
|
ValidPathInfo info;
|
||||||
|
info.path = dstPath;
|
||||||
|
info.hash = hash.first;
|
||||||
|
info.narSize = hash.second;
|
||||||
|
registerValidPath(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
outputLock.setDeletion(true);
|
outputLock.setDeletion(true);
|
||||||
|
@ -971,8 +977,14 @@ Path LocalStore::addTextToStore(const string & name, const string & s,
|
||||||
|
|
||||||
canonicalisePathMetaData(dstPath);
|
canonicalisePathMetaData(dstPath);
|
||||||
|
|
||||||
registerValidPath(dstPath,
|
HashResult hash = hashPath(htSHA256, dstPath);
|
||||||
hashPath(htSHA256, dstPath), references, "");
|
|
||||||
|
ValidPathInfo info;
|
||||||
|
info.path = dstPath;
|
||||||
|
info.hash = hash.first;
|
||||||
|
info.narSize = hash.second;
|
||||||
|
info.references = references;
|
||||||
|
registerValidPath(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
outputLock.setDeletion(true);
|
outputLock.setDeletion(true);
|
||||||
|
@ -998,7 +1010,7 @@ struct HashAndWriteSink : Sink
|
||||||
Hash currentHash()
|
Hash currentHash()
|
||||||
{
|
{
|
||||||
HashSink hashSinkClone(hashSink);
|
HashSink hashSinkClone(hashSink);
|
||||||
return hashSinkClone.finish();
|
return hashSinkClone.finish().first;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1136,7 +1148,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
|
||||||
Path deriver = readString(hashAndReadSource);
|
Path deriver = readString(hashAndReadSource);
|
||||||
if (deriver != "") assertStorePath(deriver);
|
if (deriver != "") assertStorePath(deriver);
|
||||||
|
|
||||||
Hash hash = hashAndReadSource.hashSink.finish();
|
Hash hash = hashAndReadSource.hashSink.finish().first;
|
||||||
hashAndReadSource.hashing = false;
|
hashAndReadSource.hashing = false;
|
||||||
|
|
||||||
bool haveSignature = readInt(hashAndReadSource) == 1;
|
bool haveSignature = readInt(hashAndReadSource) == 1;
|
||||||
|
@ -1200,9 +1212,15 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
|
||||||
|
|
||||||
/* !!! if we were clever, we could prevent the hashPath()
|
/* !!! if we were clever, we could prevent the hashPath()
|
||||||
here. */
|
here. */
|
||||||
if (deriver != "" && !isValidPath(deriver)) deriver = "";
|
HashResult hash = hashPath(htSHA256, dstPath);
|
||||||
registerValidPath(dstPath,
|
|
||||||
hashPath(htSHA256, dstPath), references, deriver);
|
ValidPathInfo info;
|
||||||
|
info.path = dstPath;
|
||||||
|
info.hash = hash.first;
|
||||||
|
info.narSize = hash.second;
|
||||||
|
info.references = references;
|
||||||
|
info.deriver = deriver != "" && isValidPath(deriver) ? deriver : "";
|
||||||
|
registerValidPath(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
outputLock.setDeletion(true);
|
outputLock.setDeletion(true);
|
||||||
|
@ -1263,12 +1281,14 @@ void LocalStore::verifyStore(bool checkContents)
|
||||||
|
|
||||||
/* Check the content hash (optionally - slow). */
|
/* Check the content hash (optionally - slow). */
|
||||||
printMsg(lvlTalkative, format("checking contents of `%1%'") % *i);
|
printMsg(lvlTalkative, format("checking contents of `%1%'") % *i);
|
||||||
Hash current = hashPath(info.hash.type, *i);
|
Hash current = hashPath(info.hash.type, *i).first;
|
||||||
if (current != info.hash) {
|
if (current != info.hash) {
|
||||||
printMsg(lvlError, format("path `%1%' was modified! "
|
printMsg(lvlError, format("path `%1%' was modified! "
|
||||||
"expected hash `%2%', got `%3%'")
|
"expected hash `%2%', got `%3%'")
|
||||||
% *i % printHash(info.hash) % printHash(current));
|
% *i % printHash(info.hash) % printHash(current));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* !!! Check info.narSize */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,8 @@ public:
|
||||||
|
|
||||||
PathSet queryValidPaths();
|
PathSet queryValidPaths();
|
||||||
|
|
||||||
|
ValidPathInfo queryPathInfo(const Path & path);
|
||||||
|
|
||||||
Hash queryPathHash(const Path & path);
|
Hash queryPathHash(const Path & path);
|
||||||
|
|
||||||
void queryReferences(const Path & path, PathSet & references);
|
void queryReferences(const Path & path, PathSet & references);
|
||||||
|
@ -173,8 +175,7 @@ public:
|
||||||
execution of the derivation (or something equivalent). Also
|
execution of the derivation (or something equivalent). Also
|
||||||
register the hash of the file system contents of the path. The
|
register the hash of the file system contents of the path. The
|
||||||
hash must be a SHA-256 hash. */
|
hash must be a SHA-256 hash. */
|
||||||
void registerValidPath(const Path & path,
|
void registerValidPath(const ValidPathInfo & info);
|
||||||
const Hash & hash, const PathSet & references, const Path & deriver);
|
|
||||||
|
|
||||||
void registerValidPaths(const ValidPathInfos & infos);
|
void registerValidPaths(const ValidPathInfos & infos);
|
||||||
|
|
||||||
|
@ -224,10 +225,6 @@ private:
|
||||||
|
|
||||||
void addReference(unsigned long long referrer, unsigned long long reference);
|
void addReference(unsigned long long referrer, unsigned long long reference);
|
||||||
|
|
||||||
void registerValidPath(const ValidPathInfo & info);
|
|
||||||
|
|
||||||
ValidPathInfo queryPathInfo(const Path & path);
|
|
||||||
|
|
||||||
void appendReferrer(const Path & from, const Path & to, bool lock);
|
void appendReferrer(const Path & from, const Path & to, bool lock);
|
||||||
|
|
||||||
void rewriteReferrers(const Path & path, bool purge, PathSet referrers);
|
void rewriteReferrers(const Path & path, bool purge, PathSet referrers);
|
||||||
|
|
|
@ -68,7 +68,7 @@ static void hashAndLink(bool dryRun, HashToPath & hashToPath,
|
||||||
the contents of the symlink (i.e. the result of
|
the contents of the symlink (i.e. the result of
|
||||||
readlink()), not the contents of the target (which may not
|
readlink()), not the contents of the target (which may not
|
||||||
even exist). */
|
even exist). */
|
||||||
Hash hash = hashPath(htSHA256, path);
|
Hash hash = hashPath(htSHA256, path).first;
|
||||||
stats.totalFiles++;
|
stats.totalFiles++;
|
||||||
printMsg(lvlDebug, format("`%1%' has hash `%2%'") % path % printHash(hash));
|
printMsg(lvlDebug, format("`%1%' has hash `%2%'") % path % printHash(hash));
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ void RefScanSink::operator () (const unsigned char * data, unsigned int len)
|
||||||
|
|
||||||
|
|
||||||
PathSet scanForReferences(const string & path,
|
PathSet scanForReferences(const string & path,
|
||||||
const PathSet & refs, Hash & hash)
|
const PathSet & refs, HashResult & hash)
|
||||||
{
|
{
|
||||||
RefScanSink sink;
|
RefScanSink sink;
|
||||||
std::map<string, Path> backMap;
|
std::map<string, Path> backMap;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
PathSet scanForReferences(const Path & path, const PathSet & refs,
|
PathSet scanForReferences(const Path & path, const PathSet & refs,
|
||||||
Hash & hash);
|
HashResult & hash);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -247,6 +247,12 @@ bool RemoteStore::querySubstitutablePathInfo(const Path & path,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ValidPathInfo RemoteStore::queryPathInfo(const Path & path)
|
||||||
|
{
|
||||||
|
throw Error("not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Hash RemoteStore::queryPathHash(const Path & path)
|
Hash RemoteStore::queryPathHash(const Path & path)
|
||||||
{
|
{
|
||||||
openConnection();
|
openConnection();
|
||||||
|
|
|
@ -29,6 +29,8 @@ public:
|
||||||
|
|
||||||
PathSet queryValidPaths();
|
PathSet queryValidPaths();
|
||||||
|
|
||||||
|
ValidPathInfo queryPathInfo(const Path & path);
|
||||||
|
|
||||||
Hash queryPathHash(const Path & path);
|
Hash queryPathHash(const Path & path);
|
||||||
|
|
||||||
void queryReferences(const Path & path, PathSet & references);
|
void queryReferences(const Path & path, PathSet & references);
|
||||||
|
|
|
@ -3,7 +3,8 @@ create table if not exists ValidPaths (
|
||||||
path text unique not null,
|
path text unique not null,
|
||||||
hash text not null,
|
hash text not null,
|
||||||
registrationTime integer not null,
|
registrationTime integer not null,
|
||||||
deriver text
|
deriver text,
|
||||||
|
narSize integer
|
||||||
);
|
);
|
||||||
|
|
||||||
create table if not exists Refs (
|
create table if not exists Refs (
|
||||||
|
|
|
@ -190,7 +190,7 @@ std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath,
|
||||||
bool recursive, HashType hashAlgo, PathFilter & filter)
|
bool recursive, HashType hashAlgo, PathFilter & filter)
|
||||||
{
|
{
|
||||||
HashType ht(hashAlgo);
|
HashType ht(hashAlgo);
|
||||||
Hash h = recursive ? hashPath(ht, srcPath, filter) : hashFile(ht, srcPath);
|
Hash h = recursive ? hashPath(ht, srcPath, filter).first : hashFile(ht, srcPath);
|
||||||
string name = baseNameOf(srcPath);
|
string name = baseNameOf(srcPath);
|
||||||
Path dstPath = makeFixedOutputPath(recursive, hashAlgo, h, name);
|
Path dstPath = makeFixedOutputPath(recursive, hashAlgo, h, name);
|
||||||
return std::pair<Path, Hash>(dstPath, h);
|
return std::pair<Path, Hash>(dstPath, h);
|
||||||
|
@ -216,7 +216,7 @@ Path computeStorePathForText(const string & name, const string & s,
|
||||||
/* Return a string accepted by decodeValidPathInfo() that
|
/* Return a string accepted by decodeValidPathInfo() that
|
||||||
registers the specified paths as valid. Note: it's the
|
registers the specified paths as valid. Note: it's the
|
||||||
responsibility of the caller to provide a closure. */
|
responsibility of the caller to provide a closure. */
|
||||||
string makeValidityRegistration(const PathSet & paths,
|
string StoreAPI::makeValidityRegistration(const PathSet & paths,
|
||||||
bool showDerivers, bool showHash)
|
bool showDerivers, bool showHash)
|
||||||
{
|
{
|
||||||
string s = "";
|
string s = "";
|
||||||
|
@ -224,18 +224,19 @@ string makeValidityRegistration(const PathSet & paths,
|
||||||
foreach (PathSet::iterator, i, paths) {
|
foreach (PathSet::iterator, i, paths) {
|
||||||
s += *i + "\n";
|
s += *i + "\n";
|
||||||
|
|
||||||
if (showHash)
|
ValidPathInfo info = queryPathInfo(*i);
|
||||||
s += printHash(store->queryPathHash(*i)) + "\n";
|
|
||||||
|
|
||||||
Path deriver = showDerivers ? store->queryDeriver(*i) : "";
|
if (showHash) {
|
||||||
|
s += printHash(info.hash) + "\n";
|
||||||
|
s += (format("%1%\n") % info.narSize).str();
|
||||||
|
}
|
||||||
|
|
||||||
|
Path deriver = showDerivers ? info.deriver : "";
|
||||||
s += deriver + "\n";
|
s += deriver + "\n";
|
||||||
|
|
||||||
PathSet references;
|
s += (format("%1%\n") % info.references.size()).str();
|
||||||
store->queryReferences(*i, references);
|
|
||||||
|
|
||||||
s += (format("%1%\n") % references.size()).str();
|
foreach (PathSet::iterator, j, info.references)
|
||||||
|
|
||||||
foreach (PathSet::iterator, j, references)
|
|
||||||
s += *j + "\n";
|
s += *j + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,6 +253,8 @@ ValidPathInfo decodeValidPathInfo(std::istream & str, bool hashGiven)
|
||||||
string s;
|
string s;
|
||||||
getline(str, s);
|
getline(str, s);
|
||||||
info.hash = parseHash(htSHA256, s);
|
info.hash = parseHash(htSHA256, s);
|
||||||
|
getline(str, s);
|
||||||
|
if (!string2Int(s, info.narSize)) throw Error("number expected");
|
||||||
}
|
}
|
||||||
getline(str, info.deriver);
|
getline(str, info.deriver);
|
||||||
string s; int n;
|
string s; int n;
|
||||||
|
|
|
@ -90,6 +90,21 @@ struct SubstitutablePathInfo
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ValidPathInfo
|
||||||
|
{
|
||||||
|
Path path;
|
||||||
|
Path deriver;
|
||||||
|
Hash hash;
|
||||||
|
PathSet references;
|
||||||
|
time_t registrationTime;
|
||||||
|
unsigned long long narSize; // 0 = unknown
|
||||||
|
unsigned long long id; // internal use only
|
||||||
|
ValidPathInfo() : registrationTime(0), narSize(0) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef list<ValidPathInfo> ValidPathInfos;
|
||||||
|
|
||||||
|
|
||||||
class StoreAPI
|
class StoreAPI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -102,6 +117,9 @@ public:
|
||||||
/* Query the set of valid paths. */
|
/* Query the set of valid paths. */
|
||||||
virtual PathSet queryValidPaths() = 0;
|
virtual PathSet queryValidPaths() = 0;
|
||||||
|
|
||||||
|
/* Query information about a valid path. */
|
||||||
|
virtual ValidPathInfo queryPathInfo(const Path & path) = 0;
|
||||||
|
|
||||||
/* Queries the hash of a valid path. */
|
/* Queries the hash of a valid path. */
|
||||||
virtual Hash queryPathHash(const Path & path) = 0;
|
virtual Hash queryPathHash(const Path & path) = 0;
|
||||||
|
|
||||||
|
@ -214,6 +232,12 @@ public:
|
||||||
/* Clear the "failed" status of the given paths. The special
|
/* Clear the "failed" status of the given paths. The special
|
||||||
value `*' causes all failed paths to be cleared. */
|
value `*' causes all failed paths to be cleared. */
|
||||||
virtual void clearFailedPaths(const PathSet & paths) = 0;
|
virtual void clearFailedPaths(const PathSet & paths) = 0;
|
||||||
|
|
||||||
|
/* Return a string representing information about the path that
|
||||||
|
can be loaded into the database using `nix-store --load-db' or
|
||||||
|
`nix-store --register-validity'. */
|
||||||
|
string makeValidityRegistration(const PathSet & paths,
|
||||||
|
bool showDerivers, bool showHash);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -307,22 +331,6 @@ boost::shared_ptr<StoreAPI> openStore();
|
||||||
string showPaths(const PathSet & paths);
|
string showPaths(const PathSet & paths);
|
||||||
|
|
||||||
|
|
||||||
string makeValidityRegistration(const PathSet & paths,
|
|
||||||
bool showDerivers, bool showHash);
|
|
||||||
|
|
||||||
struct ValidPathInfo
|
|
||||||
{
|
|
||||||
Path path;
|
|
||||||
Path deriver;
|
|
||||||
Hash hash;
|
|
||||||
PathSet references;
|
|
||||||
time_t registrationTime;
|
|
||||||
unsigned long long id; // internal use only
|
|
||||||
ValidPathInfo() : registrationTime(0) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef list<ValidPathInfo> ValidPathInfos;
|
|
||||||
|
|
||||||
ValidPathInfo decodeValidPathInfo(std::istream & str,
|
ValidPathInfo decodeValidPathInfo(std::istream & str,
|
||||||
bool hashGiven = false);
|
bool hashGiven = false);
|
||||||
|
|
||||||
|
|
|
@ -286,12 +286,14 @@ Hash hashFile(HashType ht, const Path & path)
|
||||||
HashSink::HashSink(HashType ht) : ht(ht)
|
HashSink::HashSink(HashType ht) : ht(ht)
|
||||||
{
|
{
|
||||||
ctx = new Ctx;
|
ctx = new Ctx;
|
||||||
|
bytes = 0;
|
||||||
start(ht, *ctx);
|
start(ht, *ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
HashSink::HashSink(const HashSink & h)
|
HashSink::HashSink(const HashSink & h)
|
||||||
{
|
{
|
||||||
ht = h.ht;
|
ht = h.ht;
|
||||||
|
bytes = h.bytes;
|
||||||
ctx = new Ctx;
|
ctx = new Ctx;
|
||||||
*ctx = *h.ctx;
|
*ctx = *h.ctx;
|
||||||
}
|
}
|
||||||
|
@ -304,18 +306,20 @@ HashSink::~HashSink()
|
||||||
void HashSink::operator ()
|
void HashSink::operator ()
|
||||||
(const unsigned char * data, unsigned int len)
|
(const unsigned char * data, unsigned int len)
|
||||||
{
|
{
|
||||||
|
bytes += len;
|
||||||
update(ht, *ctx, data, len);
|
update(ht, *ctx, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
Hash HashSink::finish()
|
HashResult HashSink::finish()
|
||||||
{
|
{
|
||||||
Hash hash(ht);
|
Hash hash(ht);
|
||||||
nix::finish(ht, *ctx, hash.hash);
|
nix::finish(ht, *ctx, hash.hash);
|
||||||
return hash;
|
return HashResult(hash, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Hash hashPath(HashType ht, const Path & path, PathFilter & filter)
|
HashResult hashPath(
|
||||||
|
HashType ht, const Path & path, PathFilter & filter)
|
||||||
{
|
{
|
||||||
HashSink sink(ht);
|
HashSink sink(ht);
|
||||||
dumpPath(path, sink, filter);
|
dumpPath(path, sink, filter);
|
||||||
|
|
|
@ -40,7 +40,6 @@ struct Hash
|
||||||
|
|
||||||
/* For sorting. */
|
/* For sorting. */
|
||||||
bool operator < (const Hash & h) const;
|
bool operator < (const Hash & h) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,7 +71,8 @@ Hash hashFile(HashType ht, const Path & path);
|
||||||
(essentially) hashString(ht, dumpPath(path)). */
|
(essentially) hashString(ht, dumpPath(path)). */
|
||||||
struct PathFilter;
|
struct PathFilter;
|
||||||
extern PathFilter defaultPathFilter;
|
extern PathFilter defaultPathFilter;
|
||||||
Hash hashPath(HashType ht, const Path & path,
|
typedef std::pair<Hash, unsigned long long> HashResult;
|
||||||
|
HashResult hashPath(HashType ht, const Path & path,
|
||||||
PathFilter & filter = defaultPathFilter);
|
PathFilter & filter = defaultPathFilter);
|
||||||
|
|
||||||
/* Compress a hash to the specified number of bytes by cyclically
|
/* Compress a hash to the specified number of bytes by cyclically
|
||||||
|
@ -93,13 +93,14 @@ class HashSink : public Sink
|
||||||
private:
|
private:
|
||||||
HashType ht;
|
HashType ht;
|
||||||
Ctx * ctx;
|
Ctx * ctx;
|
||||||
|
unsigned long long bytes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HashSink(HashType ht);
|
HashSink(HashType ht);
|
||||||
HashSink(const HashSink & h);
|
HashSink(const HashSink & h);
|
||||||
~HashSink();
|
~HashSink();
|
||||||
virtual void operator () (const unsigned char * data, unsigned int len);
|
virtual void operator () (const unsigned char * data, unsigned int len);
|
||||||
Hash finish();
|
HashResult finish();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ void run(Strings args)
|
||||||
|
|
||||||
if (op == opHash) {
|
if (op == opHash) {
|
||||||
for (Strings::iterator i = ss.begin(); i != ss.end(); ++i) {
|
for (Strings::iterator i = ss.begin(); i != ss.end(); ++i) {
|
||||||
Hash h = flat ? hashFile(ht, *i) : hashPath(ht, *i);
|
Hash h = flat ? hashFile(ht, *i) : hashPath(ht, *i).first;
|
||||||
if (truncate && h.hashSize > 20) h = compressHash(h, 20);
|
if (truncate && h.hashSize > 20) h = compressHash(h, 20);
|
||||||
std::cout << format("%1%\n") %
|
std::cout << format("%1%\n") %
|
||||||
(base32 ? printHash32(h) : printHash(h));
|
(base32 ? printHash32(h) : printHash(h));
|
||||||
|
|
|
@ -393,9 +393,8 @@ static void opDumpDB(Strings opFlags, Strings opArgs)
|
||||||
if (!opArgs.empty())
|
if (!opArgs.empty())
|
||||||
throw UsageError("no arguments expected");
|
throw UsageError("no arguments expected");
|
||||||
PathSet validPaths = store->queryValidPaths();
|
PathSet validPaths = store->queryValidPaths();
|
||||||
foreach (PathSet::iterator, i, validPaths) {
|
foreach (PathSet::iterator, i, validPaths)
|
||||||
cout << makeValidityRegistration(singleton<PathSet>(*i), true, true);
|
cout << store->makeValidityRegistration(singleton<PathSet>(*i), true, true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -410,8 +409,11 @@ static void registerValidity(bool reregister, bool hashGiven, bool canonicalise)
|
||||||
/* !!! races */
|
/* !!! races */
|
||||||
if (canonicalise)
|
if (canonicalise)
|
||||||
canonicalisePathMetaData(info.path);
|
canonicalisePathMetaData(info.path);
|
||||||
if (!hashGiven)
|
if (!hashGiven) {
|
||||||
info.hash = hashPath(htSHA256, info.path);
|
HashResult hash = hashPath(htSHA256, info.path);
|
||||||
|
info.hash = hash.first;
|
||||||
|
info.narSize = hash.second;
|
||||||
|
}
|
||||||
infos.push_back(info);
|
infos.push_back(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue