* Renamed normalise.cc' ->
build.cc', `storeexprs.cc' ->
`derivations.cc', etc. * Store the SHA-256 content hash of store paths in the database after they have been built/added. This is so that we can check whether the store has been messed with (a la `rpm --verify'). * When registering path validity, verify that the closure property holds.
This commit is contained in:
parent
ef5f254a55
commit
96de272b48
19 changed files with 128 additions and 98 deletions
|
@ -1,5 +1,5 @@
|
||||||
#include "nixexpr.hh"
|
#include "nixexpr.hh"
|
||||||
#include "storeexpr.hh"
|
#include "derivations.hh"
|
||||||
|
|
||||||
|
|
||||||
#include "nixexpr-ast.hh"
|
#include "nixexpr-ast.hh"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "normalise.hh"
|
#include "build.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "nixexpr-ast.hh"
|
#include "nixexpr-ast.hh"
|
||||||
|
|
|
@ -55,7 +55,7 @@ void checkStoreNotSymlink(Path path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void initStoreExprHelpers();
|
void initDerivationsHelpers();
|
||||||
|
|
||||||
|
|
||||||
/* Initialize and reorder arguments, then call the actual argument
|
/* Initialize and reorder arguments, then call the actual argument
|
||||||
|
@ -105,7 +105,7 @@ static void initAndRun(int argc, char * * argv)
|
||||||
if (lt != "") setLogType(lt);
|
if (lt != "") setLogType(lt);
|
||||||
|
|
||||||
/* ATerm stuff. !!! find a better place to put this */
|
/* ATerm stuff. !!! find a better place to put this */
|
||||||
initStoreExprHelpers();
|
initDerivationsHelpers();
|
||||||
|
|
||||||
/* Put the arguments in a vector. */
|
/* Put the arguments in a vector. */
|
||||||
Strings args, remaining;
|
Strings args, remaining;
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
noinst_LIBRARIES = libstore.a
|
noinst_LIBRARIES = libstore.a
|
||||||
|
|
||||||
libstore_a_SOURCES = \
|
libstore_a_SOURCES = \
|
||||||
store.cc store.hh storeexpr.cc storeexpr.hh \
|
store.cc store.hh derivations.cc derivations.hh \
|
||||||
normalise.cc misc.cc normalise.hh \
|
build.cc misc.cc build.hh \
|
||||||
globals.cc globals.hh db.cc db.hh \
|
globals.cc globals.hh db.cc db.hh \
|
||||||
references.cc references.hh pathlocks.cc pathlocks.hh \
|
references.cc references.hh pathlocks.cc pathlocks.hh \
|
||||||
gc.cc gc.hh storeexpr-ast.hh
|
gc.cc gc.hh derivations-ast.hh
|
||||||
|
|
||||||
EXTRA_DIST = storeexpr-ast.def storeexpr-ast.cc
|
EXTRA_DIST = derivations-ast.def derivations-ast.cc
|
||||||
|
|
||||||
AM_CXXFLAGS = -Wall \
|
AM_CXXFLAGS = -Wall \
|
||||||
-I.. ${bdb_include} ${aterm_include} -I../libutil
|
-I.. ${bdb_include} ${aterm_include} -I../libutil
|
||||||
|
|
||||||
storeexpr-ast.cc storeexpr-ast.hh: ../aterm-helper.pl storeexpr-ast.def
|
derivations-ast.cc derivations-ast.hh: ../aterm-helper.pl derivations-ast.def
|
||||||
$(perl) ../aterm-helper.pl storeexpr-ast.hh storeexpr-ast.cc < storeexpr-ast.def
|
$(perl) ../aterm-helper.pl derivations-ast.hh derivations-ast.cc < derivations-ast.def
|
||||||
|
|
||||||
storeexpr.cc: storeexpr-ast.hh
|
derivations.cc: derivations-ast.hh
|
|
@ -5,13 +5,11 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <utime.h>
|
|
||||||
|
|
||||||
#include "normalise.hh"
|
#include "build.hh"
|
||||||
#include "references.hh"
|
#include "references.hh"
|
||||||
#include "pathlocks.hh"
|
#include "pathlocks.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
|
@ -285,60 +283,6 @@ const char * * strings2CharPtrs(const Strings & ss)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* "Fix", or canonicalise, the meta-data of the files in a store path
|
|
||||||
after it has been built. In particular:
|
|
||||||
- the last modification date on each file is set to 0 (i.e.,
|
|
||||||
00:00:00 1/1/1970 UTC)
|
|
||||||
- the permissions are set of 444 or 555 (i.e., read-only with or
|
|
||||||
without execute permission; setuid bits etc. are cleared)
|
|
||||||
- the owner and group are set to the Nix user and group, if we're
|
|
||||||
in a setuid Nix installation
|
|
||||||
*/
|
|
||||||
void canonicalisePathMetaData(const Path & path)
|
|
||||||
{
|
|
||||||
checkInterrupt();
|
|
||||||
|
|
||||||
struct stat st;
|
|
||||||
if (lstat(path.c_str(), &st))
|
|
||||||
throw SysError(format("getting attributes of path `%1%'") % path);
|
|
||||||
|
|
||||||
if (!S_ISLNK(st.st_mode)) {
|
|
||||||
|
|
||||||
/* Mask out all type related bits. */
|
|
||||||
mode_t mode = st.st_mode & ~S_IFMT;
|
|
||||||
|
|
||||||
if (mode != 0444 && mode != 0555) {
|
|
||||||
mode = (st.st_mode & S_IFMT)
|
|
||||||
| 0444
|
|
||||||
| (st.st_mode & S_IXUSR ? 0111 : 0);
|
|
||||||
if (chmod(path.c_str(), mode) == -1)
|
|
||||||
throw SysError(format("changing mode of `%1%' to %2$o") % path % mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (st.st_uid != getuid() || st.st_gid != getgid()) {
|
|
||||||
if (chown(path.c_str(), getuid(), getgid()) == -1)
|
|
||||||
throw SysError(format("changing owner/group of `%1%' to %2%/%3%")
|
|
||||||
% path % getuid() % getgid());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (st.st_mtime != 0) {
|
|
||||||
struct utimbuf utimbuf;
|
|
||||||
utimbuf.actime = st.st_atime;
|
|
||||||
utimbuf.modtime = 0;
|
|
||||||
if (utime(path.c_str(), &utimbuf) == -1)
|
|
||||||
throw SysError(format("changing modification time of `%1%'") % path);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (S_ISDIR(st.st_mode)) {
|
|
||||||
Strings names = readDirectory(path);
|
|
||||||
for (Strings::iterator i = names.begin(); i != names.end(); ++i)
|
|
||||||
canonicalisePathMetaData(path + "/" + *i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -1041,6 +985,7 @@ void DerivationGoal::computeClosure()
|
||||||
format("determining closure for `%1%'") % drvPath);
|
format("determining closure for `%1%'") % drvPath);
|
||||||
|
|
||||||
map<Path, PathSet> allReferences;
|
map<Path, PathSet> allReferences;
|
||||||
|
map<Path, Hash> contentHashes;
|
||||||
|
|
||||||
/* Check whether the output paths were created, and grep each
|
/* Check whether the output paths were created, and grep each
|
||||||
output path to determine what other paths it references. Also make all
|
output path to determine what other paths it references. Also make all
|
||||||
|
@ -1109,6 +1054,12 @@ void DerivationGoal::computeClosure()
|
||||||
}
|
}
|
||||||
|
|
||||||
allReferences[path] = references;
|
allReferences[path] = references;
|
||||||
|
|
||||||
|
/* Hash the contents of the path. The hash is stored in the
|
||||||
|
database so that we can verify later on whether nobody has
|
||||||
|
messed with the store. !!! inefficient: it would be nice
|
||||||
|
if we could combine this with filterReferences(). */
|
||||||
|
contentHashes[path] = hashPath(htSHA256, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register each output path as valid, and register the sets of
|
/* Register each output path as valid, and register the sets of
|
||||||
|
@ -1127,7 +1078,8 @@ void DerivationGoal::computeClosure()
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
||||||
i != drv.outputs.end(); ++i)
|
i != drv.outputs.end(); ++i)
|
||||||
{
|
{
|
||||||
registerValidPath(txn, i->second.path);
|
registerValidPath(txn, i->second.path,
|
||||||
|
contentHashes[i->second.path]);
|
||||||
setReferences(txn, i->second.path,
|
setReferences(txn, i->second.path,
|
||||||
allReferences[i->second.path]);
|
allReferences[i->second.path]);
|
||||||
}
|
}
|
||||||
|
@ -1460,9 +1412,11 @@ void SubstitutionGoal::finished()
|
||||||
|
|
||||||
canonicalisePathMetaData(storePath);
|
canonicalisePathMetaData(storePath);
|
||||||
|
|
||||||
|
Hash contentHash = hashPath(htSHA256, storePath);
|
||||||
|
|
||||||
Transaction txn;
|
Transaction txn;
|
||||||
createStoreTransaction(txn);
|
createStoreTransaction(txn);
|
||||||
registerValidPath(txn, storePath);
|
registerValidPath(txn, storePath, contentHash);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
outputLock->setDeletion(true);
|
outputLock->setDeletion(true);
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __NORMALISE_H
|
#ifndef __BUILD_H
|
||||||
#define __NORMALISE_H
|
#define __BUILD_H
|
||||||
|
|
||||||
#include "storeexpr.hh"
|
#include "derivations.hh"
|
||||||
|
|
||||||
/* Perform the specified derivations, if necessary. That is, do
|
/* Perform the specified derivations, if necessary. That is, do
|
||||||
whatever is necessary to create the output paths of the derivation.
|
whatever is necessary to create the output paths of the derivation.
|
||||||
|
@ -44,4 +44,4 @@ void computeFSClosure(const Path & storePath,
|
||||||
void storePathRequisites(const Path & storePath,
|
void storePathRequisites(const Path & storePath,
|
||||||
bool includeOutputs, PathSet & paths);
|
bool includeOutputs, PathSet & paths);
|
||||||
|
|
||||||
#endif /* !__NORMALISE_H */
|
#endif /* !__BUILD_H */
|
|
@ -1,4 +1,4 @@
|
||||||
init initStoreExprHelpers
|
init initDerivationsHelpers
|
||||||
|
|
||||||
Derive | ATermList ATermList ATermList string string ATermList ATermList | ATerm |
|
Derive | ATermList ATermList ATermList string string ATermList ATermList | ATerm |
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#include "storeexpr.hh"
|
#include "derivations.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "store.hh"
|
#include "store.hh"
|
||||||
|
|
||||||
#include "storeexpr-ast.hh"
|
#include "derivations-ast.hh"
|
||||||
#include "storeexpr-ast.cc"
|
#include "derivations-ast.cc"
|
||||||
|
|
||||||
|
|
||||||
Hash hashTerm(ATerm t)
|
Hash hashTerm(ATerm t)
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef __STOREEXPR_H
|
#ifndef __DERIVATIONS_H
|
||||||
#define __STOREEXPR_H
|
#define __DERIVATIONS_H
|
||||||
|
|
||||||
#include "aterm.hh"
|
#include "aterm.hh"
|
||||||
#include "store.hh"
|
#include "store.hh"
|
||||||
|
@ -59,4 +59,4 @@ ATerm unparseDerivation(const Derivation & drv);
|
||||||
bool isDerivation(const string & fileName);
|
bool isDerivation(const string & fileName);
|
||||||
|
|
||||||
|
|
||||||
#endif /* !__STOREEXPR_H */
|
#endif /* !__DERIVATIONS_H */
|
|
@ -1,5 +1,5 @@
|
||||||
#include "normalise.hh"
|
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
|
#include "gc.hh"
|
||||||
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __GC_H
|
#ifndef __GC_H
|
||||||
#define __GC_H
|
#define __GC_H
|
||||||
|
|
||||||
#include "storeexpr.hh"
|
#include "util.hh"
|
||||||
|
|
||||||
|
|
||||||
/* Determine the set of "live" store paths, given a set of root store
|
/* Determine the set of "live" store paths, given a set of root store
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "normalise.hh"
|
#include "build.hh"
|
||||||
|
|
||||||
|
|
||||||
Derivation derivationFromPath(const Path & drvPath)
|
Derivation derivationFromPath(const Path & drvPath)
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <utime.h>
|
||||||
|
|
||||||
#include "store.hh"
|
#include "store.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
|
@ -181,6 +184,51 @@ void assertStorePath(const Path & path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void canonicalisePathMetaData(const Path & path)
|
||||||
|
{
|
||||||
|
checkInterrupt();
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if (lstat(path.c_str(), &st))
|
||||||
|
throw SysError(format("getting attributes of path `%1%'") % path);
|
||||||
|
|
||||||
|
if (!S_ISLNK(st.st_mode)) {
|
||||||
|
|
||||||
|
/* Mask out all type related bits. */
|
||||||
|
mode_t mode = st.st_mode & ~S_IFMT;
|
||||||
|
|
||||||
|
if (mode != 0444 && mode != 0555) {
|
||||||
|
mode = (st.st_mode & S_IFMT)
|
||||||
|
| 0444
|
||||||
|
| (st.st_mode & S_IXUSR ? 0111 : 0);
|
||||||
|
if (chmod(path.c_str(), mode) == -1)
|
||||||
|
throw SysError(format("changing mode of `%1%' to %2$o") % path % mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st.st_uid != getuid() || st.st_gid != getgid()) {
|
||||||
|
if (chown(path.c_str(), getuid(), getgid()) == -1)
|
||||||
|
throw SysError(format("changing owner/group of `%1%' to %2%/%3%")
|
||||||
|
% path % getuid() % getgid());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st.st_mtime != 0) {
|
||||||
|
struct utimbuf utimbuf;
|
||||||
|
utimbuf.actime = st.st_atime;
|
||||||
|
utimbuf.modtime = 0;
|
||||||
|
if (utime(path.c_str(), &utimbuf) == -1)
|
||||||
|
throw SysError(format("changing modification time of `%1%'") % path);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S_ISDIR(st.st_mode)) {
|
||||||
|
Strings names = readDirectory(path);
|
||||||
|
for (Strings::iterator i = names.begin(); i != names.end(); ++i)
|
||||||
|
canonicalisePathMetaData(path + "/" + *i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool isValidPathTxn(const Path & path, const Transaction & txn)
|
static bool isValidPathTxn(const Path & path, const Transaction & txn)
|
||||||
{
|
{
|
||||||
string s;
|
string s;
|
||||||
|
@ -318,12 +366,24 @@ void clearSubstitutes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void registerValidPath(const Transaction & txn, const Path & _path)
|
void registerValidPath(const Transaction & txn,
|
||||||
|
const Path & _path, const Hash & hash)
|
||||||
{
|
{
|
||||||
Path path(canonPath(_path));
|
Path path(canonPath(_path));
|
||||||
assertStorePath(path);
|
assertStorePath(path);
|
||||||
|
|
||||||
|
assert(hash.type == htSHA256);
|
||||||
|
|
||||||
debug(format("registering path `%1%'") % path);
|
debug(format("registering path `%1%'") % path);
|
||||||
nixDB.setString(txn, dbValidPaths, path, "");
|
nixDB.setString(txn, dbValidPaths, path, "sha256:" + printHash(hash));
|
||||||
|
|
||||||
|
/* Check that all referenced paths are also valid. */
|
||||||
|
Paths references;
|
||||||
|
nixDB.queryStrings(txn, dbReferences, path, references);
|
||||||
|
for (Paths::iterator i = references.begin(); i != references.end(); ++i)
|
||||||
|
if (!isValidPathTxn(*i, txn))
|
||||||
|
throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid")
|
||||||
|
% path % *i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -385,10 +445,10 @@ Path addToStore(const Path & _srcPath)
|
||||||
throw Error(format("contents of `%1%' changed while copying it to `%2%' (%3% -> %4%)")
|
throw Error(format("contents of `%1%' changed while copying it to `%2%' (%3% -> %4%)")
|
||||||
% srcPath % dstPath % printHash(h) % printHash(h2));
|
% srcPath % dstPath % printHash(h) % printHash(h2));
|
||||||
|
|
||||||
makePathReadOnly(dstPath);
|
canonicalisePathMetaData(dstPath);
|
||||||
|
|
||||||
Transaction txn(nixDB);
|
Transaction txn(nixDB);
|
||||||
registerValidPath(txn, dstPath);
|
registerValidPath(txn, dstPath, h);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,10 +477,10 @@ Path addTextToStore(const string & suffix, const string & s)
|
||||||
|
|
||||||
writeStringToFile(dstPath, s);
|
writeStringToFile(dstPath, s);
|
||||||
|
|
||||||
makePathReadOnly(dstPath);
|
canonicalisePathMetaData(dstPath);
|
||||||
|
|
||||||
Transaction txn(nixDB);
|
Transaction txn(nixDB);
|
||||||
registerValidPath(txn, dstPath);
|
registerValidPath(txn, dstPath, hashPath(htSHA256, dstPath));
|
||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,12 +51,28 @@ Substitutes querySubstitutes(const Path & srcPath);
|
||||||
/* Deregister all substitutes. */
|
/* Deregister all substitutes. */
|
||||||
void clearSubstitutes();
|
void clearSubstitutes();
|
||||||
|
|
||||||
/* Register the validity of a path. */
|
/* Register the validity of a path, i.e., that `path' exists, that the
|
||||||
void registerValidPath(const Transaction & txn, const Path & path);
|
paths referenced by it exists, and in the case of an output path of
|
||||||
|
a derivation, that it has been produced by a succesful execution of
|
||||||
|
the derivation (or something equivalent). Also register the hash
|
||||||
|
of the file system contents of the path. The hash must be a
|
||||||
|
SHA-256 hash. */
|
||||||
|
void registerValidPath(const Transaction & txn,
|
||||||
|
const Path & path, const Hash & hash);
|
||||||
|
|
||||||
/* Throw an exception if `path' is not directly in the Nix store. */
|
/* Throw an exception if `path' is not directly in the Nix store. */
|
||||||
void assertStorePath(const Path & path);
|
void assertStorePath(const Path & path);
|
||||||
|
|
||||||
|
/* "Fix", or canonicalise, the meta-data of the files in a store path
|
||||||
|
after it has been built. In particular:
|
||||||
|
- the last modification date on each file is set to 0 (i.e.,
|
||||||
|
00:00:00 1/1/1970 UTC)
|
||||||
|
- the permissions are set of 444 or 555 (i.e., read-only with or
|
||||||
|
without execute permission; setuid bits etc. are cleared)
|
||||||
|
- the owner and group are set to the Nix user and group, if we're
|
||||||
|
in a setuid Nix installation. */
|
||||||
|
void canonicalisePathMetaData(const Path & path);
|
||||||
|
|
||||||
/* Checks whether a path is valid. */
|
/* Checks whether a path is valid. */
|
||||||
bool isValidPath(const Path & path);
|
bool isValidPath(const Path & path);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "profiles.hh"
|
#include "profiles.hh"
|
||||||
#include "names.hh"
|
#include "names.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "normalise.hh"
|
#include "build.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "parser.hh"
|
#include "parser.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "normalise.hh"
|
#include "build.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "parser.hh"
|
#include "parser.hh"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "dotgraph.hh"
|
#include "dotgraph.hh"
|
||||||
#include "normalise.hh"
|
#include "build.hh"
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __DOTGRAPH_H
|
#ifndef __DOTGRAPH_H
|
||||||
#define __DOTGRAPH_H
|
#define __DOTGRAPH_H
|
||||||
|
|
||||||
#include "storeexpr.hh"
|
#include "util.hh"
|
||||||
|
|
||||||
void printDotGraph(const PathSet & roots);
|
void printDotGraph(const PathSet & roots);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "normalise.hh"
|
#include "build.hh"
|
||||||
#include "gc.hh"
|
#include "gc.hh"
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
|
@ -187,7 +187,7 @@ static void opValidPath(Strings opFlags, Strings opArgs)
|
||||||
createStoreTransaction(txn);
|
createStoreTransaction(txn);
|
||||||
for (Strings::iterator i = opArgs.begin();
|
for (Strings::iterator i = opArgs.begin();
|
||||||
i != opArgs.end(); ++i)
|
i != opArgs.end(); ++i)
|
||||||
registerValidPath(txn, *i);
|
registerValidPath(txn, *i, hashPath(htSHA256, *i));
|
||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue