Add a ‘--repair’ flag to nix-instantiate

This allows repairing corrupted derivations and other source files.
This commit is contained in:
Eelco Dolstra 2012-10-03 15:09:18 -04:00
parent a807edfae8
commit 0a7084567f
11 changed files with 36 additions and 25 deletions

View file

@ -141,6 +141,7 @@ EvalState::EvalState()
, baseEnv(allocEnv(128)) , baseEnv(allocEnv(128))
, baseEnvDispl(0) , baseEnvDispl(0)
, staticBaseEnv(false, 0) , staticBaseEnv(false, 0)
, repair(false)
{ {
nrEnvs = nrValuesInEnvs = nrValues = nrListElems = 0; nrEnvs = nrValuesInEnvs = nrValues = nrListElems = 0;
nrAttrsets = nrOpUpdates = nrOpUpdateValuesCopied = 0; nrAttrsets = nrOpUpdates = nrOpUpdateValuesCopied = 0;
@ -1093,7 +1094,7 @@ string EvalState::coerceToString(Value & v, PathSet & context,
else { else {
dstPath = settings.readOnlyMode dstPath = settings.readOnlyMode
? computeStorePathForPath(path).first ? computeStorePathForPath(path).first
: store->addToStore(path); : store->addToStore(path, true, htSHA256, defaultPathFilter, repair);
srcToStore[path] = dstPath; srcToStore[path] = dstPath;
printMsg(lvlChatty, format("copied source `%1%' -> `%2%'") printMsg(lvlChatty, format("copied source `%1%' -> `%2%'")
% path % dstPath); % path % dstPath);

View file

@ -95,6 +95,10 @@ public:
const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName,
sSystem, sOverrides; sSystem, sOverrides;
/* If set, force copying files to the Nix store even if they
already exist there. */
bool repair;
private: private:
SrcToStore srcToStore; SrcToStore srcToStore;

View file

@ -487,7 +487,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
} }
/* Write the resulting term into the Nix store directory. */ /* Write the resulting term into the Nix store directory. */
Path drvPath = writeDerivation(*store, drv, drvName); Path drvPath = writeDerivation(*store, drv, drvName, state.repair);
printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'") printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'")
% drvName % drvPath); % drvName % drvPath);
@ -625,7 +625,7 @@ static void prim_toFile(EvalState & state, Value * * args, Value & v)
Path storePath = settings.readOnlyMode Path storePath = settings.readOnlyMode
? computeStorePathForText(name, contents, refs) ? computeStorePathForText(name, contents, refs)
: store->addTextToStore(name, contents, refs); : store->addTextToStore(name, contents, refs, state.repair);
/* Note: we don't need to add `context' to the context of the /* Note: we don't need to add `context' to the context of the
result, since `storePath' itself has references to the paths result, since `storePath' itself has references to the paths
@ -689,7 +689,7 @@ static void prim_filterSource(EvalState & state, Value * * args, Value & v)
Path dstPath = settings.readOnlyMode Path dstPath = settings.readOnlyMode
? computeStorePathForPath(path, true, htSHA256, filter).first ? computeStorePathForPath(path, true, htSHA256, filter).first
: store->addToStore(path, true, htSHA256, filter); : store->addToStore(path, true, htSHA256, filter, state.repair);
mkString(v, dstPath, singleton<PathSet>(dstPath)); mkString(v, dstPath, singleton<PathSet>(dstPath));
} }

View file

@ -27,7 +27,7 @@ void DerivationOutput::parseHashInfo(bool & recursive, HashType & hashType, Hash
Path writeDerivation(StoreAPI & store, Path writeDerivation(StoreAPI & store,
const Derivation & drv, const string & name) const Derivation & drv, const string & name, bool repair)
{ {
PathSet references; PathSet references;
references.insert(drv.inputSrcs.begin(), drv.inputSrcs.end()); references.insert(drv.inputSrcs.begin(), drv.inputSrcs.end());
@ -40,7 +40,7 @@ Path writeDerivation(StoreAPI & store,
string contents = unparseDerivation(drv); string contents = unparseDerivation(drv);
return settings.readOnlyMode return settings.readOnlyMode
? computeStorePathForText(suffix, contents, references) ? computeStorePathForText(suffix, contents, references)
: store.addTextToStore(suffix, contents, references); : store.addTextToStore(suffix, contents, references, repair);
} }

View file

@ -57,7 +57,7 @@ class StoreAPI;
/* Write a derivation to the Nix store, and return its path. */ /* Write a derivation to the Nix store, and return its path. */
Path writeDerivation(StoreAPI & store, Path writeDerivation(StoreAPI & store,
const Derivation & drv, const string & name); const Derivation & drv, const string & name, bool repair = false);
/* Parse a derivation. */ /* Parse a derivation. */
Derivation parseDerivation(const string & s); Derivation parseDerivation(const string & s);

View file

@ -1158,7 +1158,7 @@ void LocalStore::invalidatePath(const Path & path)
Path LocalStore::addToStoreFromDump(const string & dump, const string & name, Path LocalStore::addToStoreFromDump(const string & dump, const string & name,
bool recursive, HashType hashAlgo) bool recursive, HashType hashAlgo, bool repair)
{ {
Hash h = hashString(hashAlgo, dump); Hash h = hashString(hashAlgo, dump);
@ -1166,14 +1166,14 @@ Path LocalStore::addToStoreFromDump(const string & dump, const string & name,
addTempRoot(dstPath); addTempRoot(dstPath);
if (!isValidPath(dstPath)) { if (repair || !isValidPath(dstPath)) {
/* The first check above is an optimisation to prevent /* The first check above is an optimisation to prevent
unnecessary lock acquisition. */ unnecessary lock acquisition. */
PathLocks outputLock(singleton<PathSet, Path>(dstPath)); PathLocks outputLock(singleton<PathSet, Path>(dstPath));
if (!isValidPath(dstPath)) { if (repair || !isValidPath(dstPath)) {
if (pathExists(dstPath)) deletePathWrapped(dstPath); if (pathExists(dstPath)) deletePathWrapped(dstPath);
@ -1213,7 +1213,7 @@ Path LocalStore::addToStoreFromDump(const string & dump, const string & name,
Path LocalStore::addToStore(const Path & _srcPath, Path LocalStore::addToStore(const Path & _srcPath,
bool recursive, HashType hashAlgo, PathFilter & filter) bool recursive, HashType hashAlgo, PathFilter & filter, bool repair)
{ {
Path srcPath(absPath(_srcPath)); Path srcPath(absPath(_srcPath));
debug(format("adding `%1%' to the store") % srcPath); debug(format("adding `%1%' to the store") % srcPath);
@ -1227,22 +1227,22 @@ Path LocalStore::addToStore(const Path & _srcPath,
else else
sink.s = readFile(srcPath); sink.s = readFile(srcPath);
return addToStoreFromDump(sink.s, baseNameOf(srcPath), recursive, hashAlgo); return addToStoreFromDump(sink.s, baseNameOf(srcPath), recursive, hashAlgo, repair);
} }
Path LocalStore::addTextToStore(const string & name, const string & s, Path LocalStore::addTextToStore(const string & name, const string & s,
const PathSet & references) const PathSet & references, bool repair)
{ {
Path dstPath = computeStorePathForText(name, s, references); Path dstPath = computeStorePathForText(name, s, references);
addTempRoot(dstPath); addTempRoot(dstPath);
if (!isValidPath(dstPath)) { if (repair || !isValidPath(dstPath)) {
PathLocks outputLock(singleton<PathSet, Path>(dstPath)); PathLocks outputLock(singleton<PathSet, Path>(dstPath));
if (!isValidPath(dstPath)) { if (repair || !isValidPath(dstPath)) {
if (pathExists(dstPath)) deletePathWrapped(dstPath); if (pathExists(dstPath)) deletePathWrapped(dstPath);

View file

@ -133,17 +133,17 @@ public:
Path addToStore(const Path & srcPath, Path addToStore(const Path & srcPath,
bool recursive = true, HashType hashAlgo = htSHA256, bool recursive = true, HashType hashAlgo = htSHA256,
PathFilter & filter = defaultPathFilter); PathFilter & filter = defaultPathFilter, bool repair = false);
/* Like addToStore(), but the contents of the path are contained /* Like addToStore(), but the contents of the path are contained
in `dump', which is either a NAR serialisation (if recursive == in `dump', which is either a NAR serialisation (if recursive ==
true) or simply the contents of a regular file (if recursive == true) or simply the contents of a regular file (if recursive ==
false). */ false). */
Path addToStoreFromDump(const string & dump, const string & name, Path addToStoreFromDump(const string & dump, const string & name,
bool recursive = true, HashType hashAlgo = htSHA256); bool recursive = true, HashType hashAlgo = htSHA256, bool repair = false);
Path addTextToStore(const string & name, const string & s, Path addTextToStore(const string & name, const string & s,
const PathSet & references); const PathSet & references, bool repair = false);
void exportPath(const Path & path, bool sign, void exportPath(const Path & path, bool sign,
Sink & sink); Sink & sink);

View file

@ -419,8 +419,10 @@ Path RemoteStore::queryPathFromHashPart(const string & hashPart)
Path RemoteStore::addToStore(const Path & _srcPath, Path RemoteStore::addToStore(const Path & _srcPath,
bool recursive, HashType hashAlgo, PathFilter & filter) bool recursive, HashType hashAlgo, PathFilter & filter, bool repair)
{ {
if (repair) throw Error("repairing is not supported when building through the Nix daemon");
openConnection(); openConnection();
Path srcPath(absPath(_srcPath)); Path srcPath(absPath(_srcPath));
@ -438,8 +440,10 @@ Path RemoteStore::addToStore(const Path & _srcPath,
Path RemoteStore::addTextToStore(const string & name, const string & s, Path RemoteStore::addTextToStore(const string & name, const string & s,
const PathSet & references) const PathSet & references, bool repair)
{ {
if (repair) throw Error("repairing is not supported when building through the Nix daemon");
openConnection(); openConnection();
writeInt(wopAddTextToStore, to); writeInt(wopAddTextToStore, to);
writeString(name, to); writeString(name, to);
@ -476,7 +480,7 @@ Paths RemoteStore::importPaths(bool requireSignature, Source & source)
void RemoteStore::buildPaths(const PathSet & drvPaths, bool repair) void RemoteStore::buildPaths(const PathSet & drvPaths, bool repair)
{ {
if (repair) throw Error("`--repair' is not supported when building through the Nix daemon"); if (repair) throw Error("repairing is not supported when building through the Nix daemon");
openConnection(); openConnection();
writeInt(wopBuildPaths, to); writeInt(wopBuildPaths, to);
writeStrings(drvPaths, to); writeStrings(drvPaths, to);

View file

@ -53,10 +53,10 @@ public:
Path addToStore(const Path & srcPath, Path addToStore(const Path & srcPath,
bool recursive = true, HashType hashAlgo = htSHA256, bool recursive = true, HashType hashAlgo = htSHA256,
PathFilter & filter = defaultPathFilter); PathFilter & filter = defaultPathFilter, bool repair = false);
Path addTextToStore(const string & name, const string & s, Path addTextToStore(const string & name, const string & s,
const PathSet & references); const PathSet & references, bool repair = false);
void exportPath(const Path & path, bool sign, void exportPath(const Path & path, bool sign,
Sink & sink); Sink & sink);

View file

@ -158,12 +158,12 @@ public:
libutil/archive.hh). */ libutil/archive.hh). */
virtual Path addToStore(const Path & srcPath, virtual Path addToStore(const Path & srcPath,
bool recursive = true, HashType hashAlgo = htSHA256, bool recursive = true, HashType hashAlgo = htSHA256,
PathFilter & filter = defaultPathFilter) = 0; PathFilter & filter = defaultPathFilter, bool repair = false) = 0;
/* Like addToStore, but the contents written to the output path is /* Like addToStore, but the contents written to the output path is
a regular file containing the given string. */ a regular file containing the given string. */
virtual Path addTextToStore(const string & name, const string & s, virtual Path addTextToStore(const string & name, const string & s,
const PathSet & references) = 0; const PathSet & references, bool repair = false) = 0;
/* Export a store path, that is, create a NAR dump of the store /* Export a store path, that is, create a NAR dump of the store
path and append its references and its deriver. Optionally, a path and append its references and its deriver. Optionally, a

View file

@ -125,6 +125,8 @@ void run(Strings args)
xmlOutputSourceLocation = false; xmlOutputSourceLocation = false;
else if (arg == "--strict") else if (arg == "--strict")
strict = true; strict = true;
else if (arg == "--repair")
state.repair = true;
else if (arg[0] == '-') else if (arg[0] == '-')
throw UsageError(format("unknown flag `%1%'") % arg); throw UsageError(format("unknown flag `%1%'") % arg);
else else