1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-27 04:30:59 +01:00

Merged the Nix sources from the trunk from R9751 to R10133 for my State Nix project.

This commit is contained in:
Wouter den Breejen 2008-01-13 16:36:27 +00:00
parent 55b07d65b1
commit a34a198006
46 changed files with 1323 additions and 265 deletions

View file

@ -36,6 +36,7 @@ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
static off_t offtin(u_char *buf)
{

View file

@ -4,6 +4,7 @@
%x STRING
%x IND_STRING
%{
@ -122,6 +123,26 @@ inherit { return INHERIT; }
<STRING>\" { BEGIN(INITIAL); return '"'; }
<STRING>. return yytext[0]; /* just in case: shouldn't be reached */
\'\'(\ *\n)? { BEGIN(IND_STRING); return IND_STRING_OPEN; }
<IND_STRING>([^\$\']|\$[^\{\']|\'[^\'])+ {
yylval->t = makeIndStr(toATerm(yytext));
return IND_STR;
}
<IND_STRING>\'\'\$ {
yylval->t = makeIndStr(toATerm("$"));
return IND_STR;
}
<IND_STRING>\'\'\' {
yylval->t = makeIndStr(toATerm("''"));
return IND_STR;
}
<IND_STRING>\'\'\\. {
yylval->t = unescapeStr(yytext + 2);
return IND_STR;
}
<IND_STRING>\$\{ { BEGIN(INITIAL); return DOLLAR_CURLY; }
<IND_STRING>\'\' { BEGIN(INITIAL); return IND_STRING_CLOSE; }
<IND_STRING>. return yytext[0]; /* just in case: shouldn't be reached */
{PATH} { yylval->t = toATerm(yytext); return PATH; /* !!! alloc */ }
{URI} { yylval->t = toATerm(yytext); return URI; /* !!! alloc */ }
@ -148,4 +169,10 @@ void backToString(yyscan_t scanner)
BEGIN(STRING);
}
void backToIndString(yyscan_t scanner)
{
struct yyguts_t * yyg = (struct yyguts_t *) scanner;
BEGIN(IND_STRING);
}
}

View file

@ -46,6 +46,9 @@ Int | int | Expr |
Str | string ATermList | Expr |
Str | string | Expr | ObsoleteStr
# Internal to the parser, doesn't occur in ASTs.
IndStr | string | Expr |
# A path is a reference to a file system object that is to be copied
# to the Nix store when used as a derivation attribute. When it is
# concatenated to a string (i.e., `str + path'), it is also copied and

View file

@ -68,9 +68,100 @@ static Expr fixAttrs(int recursive, ATermList as)
}
void backToString(yyscan_t scanner);
static Expr stripIndentation(ATermList es)
{
if (es == ATempty) return makeStr("");
/* Figure out the minimum indentation. Note that by design
whitespace-only final lines are not taken into account. (So
the " " in "\n ''" is ignored, but the " " in "\n foo''" is.) */
bool atStartOfLine = true; /* = seen only whitespace in the current line */
unsigned int minIndent = 1000000;
unsigned int curIndent = 0;
ATerm e;
for (ATermIterator i(es); i; ++i) {
if (!matchIndStr(*i, e)) {
/* Anti-quotations end the current start-of-line whitespace. */
if (atStartOfLine) {
atStartOfLine = false;
if (curIndent < minIndent) minIndent = curIndent;
}
continue;
}
string s = aterm2String(e);
for (unsigned int j = 0; j < s.size(); ++j) {
if (atStartOfLine) {
if (s[j] == ' ')
curIndent++;
else if (s[j] == '\n') {
/* Empty line, doesn't influence minimum
indentation. */
curIndent = 0;
} else {
atStartOfLine = false;
if (curIndent < minIndent) minIndent = curIndent;
}
} else if (s[j] == '\n') {
atStartOfLine = true;
curIndent = 0;
}
}
}
/* Strip spaces from each line. */
ATermList es2 = ATempty;
atStartOfLine = true;
unsigned int curDropped = 0;
unsigned int n = ATgetLength(es);
for (ATermIterator i(es); i; ++i, --n) {
if (!matchIndStr(*i, e)) {
atStartOfLine = false;
curDropped = 0;
es2 = ATinsert(es2, *i);
continue;
}
string s = aterm2String(e);
string s2;
for (unsigned int j = 0; j < s.size(); ++j) {
if (atStartOfLine) {
if (s[j] == ' ') {
if (curDropped++ >= minIndent)
s2 += s[j];
}
else if (s[j] == '\n') {
curDropped = 0;
s2 += s[j];
} else {
atStartOfLine = false;
curDropped = 0;
s2 += s[j];
}
} else {
s2 += s[j];
if (s[j] == '\n') atStartOfLine = true;
}
}
/* Remove the last line if it is empty and consists only of
spaces. */
if (n == 1) {
unsigned int p = s2.find_last_of('\n');
if (p != string::npos && s2.find_first_not_of(' ', p + 1) == string::npos)
s2 = string(s2, 0, p + 1);
}
es2 = ATinsert(es2, makeStr(s2));
}
return makeConcatStrings(ATreverse(es2));
}
void backToString(yyscan_t scanner);
void backToIndString(yyscan_t scanner);
static Pos makeCurPos(YYLTYPE * loc, ParseData * data)
{
return makePos(toATerm(data->path),
@ -121,10 +212,11 @@ static void freeAndUnprotect(void * p)
%type <t> start expr expr_function expr_if expr_op
%type <t> expr_app expr_select expr_simple bind inheritsrc formal
%type <ts> binds ids expr_list formals string_parts
%token <t> ID INT STR PATH URI
%type <ts> binds ids expr_list formals string_parts ind_string_parts
%token <t> ID INT STR IND_STR PATH URI
%token IF THEN ELSE ASSERT WITH LET IN REC INHERIT EQ NEQ AND OR IMPL
%token DOLLAR_CURLY /* == ${ */
%token IND_STRING_OPEN IND_STRING_CLOSE
%nonassoc IMPL
%left OR
@ -199,6 +291,9 @@ expr_simple
else if (ATgetNext($2) == ATempty) $$ = ATgetFirst($2);
else $$ = makeConcatStrings(ATreverse($2));
}
| IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE {
$$ = stripIndentation(ATreverse($2));
}
| PATH { $$ = makePath(toATerm(absPath(aterm2String($1), data->basePath))); }
| URI { $$ = makeStr($1, ATempty); }
| '(' expr ')' { $$ = $2; }
@ -219,6 +314,12 @@ string_parts
| { $$ = ATempty; }
;
ind_string_parts
: ind_string_parts IND_STR { $$ = ATinsert($1, $2); }
| ind_string_parts DOLLAR_CURLY expr '}' { backToIndString(scanner); $$ = ATinsert($1, $3); }
| { $$ = ATempty; }
;
binds
: binds bind { $$ = ATinsert($1, $2); }
| { $$ = ATempty; }

View file

@ -769,6 +769,17 @@ static Expr prim_dirOf(EvalState & state, const ATermVector & args)
}
/* Return the contents of a file as a string. */
static Expr prim_readFile(EvalState & state, const ATermVector & args)
{
PathSet context;
Path path = coerceToPath(state, args[0], context);
if (!context.empty())
throw EvalError(format("string `%1%' cannot refer to other paths") % path);
return makeStr(readFile(path));
}
/*************************************************************
* Creating files
*************************************************************/
@ -1054,8 +1065,8 @@ static Expr prim_toString(EvalState & state, const ATermVector & args)
}
/* `substr start len str' returns the substring of `str' starting at
character position `min(start, stringLength str)' inclusive and
/* `substring start len str' returns the substring of `str' starting
at character position `min(start, stringLength str)' inclusive and
ending at `min(start + len, stringLength str)'. `start' must be
non-negative. */
static Expr prim_substring(EvalState & state, const ATermVector & args)
@ -1079,6 +1090,14 @@ static Expr prim_stringLength(EvalState & state, const ATermVector & args)
}
static Expr prim_unsafeDiscardStringContext(EvalState & state, const ATermVector & args)
{
PathSet context;
string s = coerceToString(state, args[0], context);
return makeStr(s, PathSet());
}
/*************************************************************
* Primop registration
*************************************************************/
@ -1116,6 +1135,7 @@ void EvalState::addPrimOps()
addPrimOp("__pathExists", 1, prim_pathExists);
addPrimOp("baseNameOf", 1, prim_baseNameOf);
addPrimOp("dirOf", 1, prim_dirOf);
addPrimOp("__readFile", 1, prim_readFile);
// Creating files
addPrimOp("__toXML", 1, prim_toXML);
@ -1145,6 +1165,8 @@ void EvalState::addPrimOps()
addPrimOp("toString", 1, prim_toString);
addPrimOp("__substring", 3, prim_substring);
addPrimOp("__stringLength", 1, prim_stringLength);
addPrimOp("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext);
}

View file

@ -1671,6 +1671,44 @@ void DerivationGoal::startBuilder()
makeValidityRegistration(refs, false));
}
// The same for derivations
s = drv.env["exportBuildReferencesGraph"];
ss = tokenizeString(s);
if (ss.size() % 2 != 0)
throw BuildError(format("odd number of tokens in `exportReferencesGraph': `%1%'") % s);
for (Strings::iterator i = ss.begin(); i != ss.end(); ) {
string fileName = *i++;
checkStoreName(fileName); /* !!! abuse of this function */
/* Check that the store path is valid. */
Path storePath = *i++;
if (!isInStore(storePath))
throw BuildError(format("`exportReferencesGraph' contains a non-store path `%1%'")
% storePath);
storePath = toStorePath(storePath);
if (!store->isValidPath(storePath))
throw BuildError(format("`exportReferencesGraph' contains an invalid path `%1%'")
% storePath);
/* Write closure info to `fileName'. */
PathSet refs1,refs;
computeFSClosure(storePath, refs1, true, false, 0); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! WE (MAY) ALSO NEED TO COPY STATE
for (PathSet::iterator j = refs1.begin(); j != refs1.end() ; j++) {
refs.insert (*j);
if (isDerivation (*j)) {
Derivation deriv = derivationFromPath (*j);
for (DerivationOutputs::iterator k=deriv.outputs.begin();
k != deriv.outputs.end(); k++) {
refs.insert(k->second.path);
}
}
}
/* !!! in secure Nix, the writing should be done on the
build uid for security (maybe). */
writeStringToFile(tmpDir + "/" + fileName,
makeValidityRegistration(refs, false));
}
/* If `build-users-group' is not empty, then we have to build as
one of the members of that group. */

View file

@ -26,7 +26,7 @@ static string gcLockName = "gc.lock";
static string tempRootsDir = "temproots";
static string gcRootsDir = "gcroots";
const unsigned int defaultGcLevel = 1000;
static const int defaultGcLevel = 1000;
/* Acquire the global GC lock. This is used to prevent new Nix
@ -450,7 +450,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
queryBoolSetting("gc-keep-outputs", false);
bool gcKeepDerivations =
queryBoolSetting("gc-keep-derivations", true);
unsigned int gcKeepOutputsThreshold =
int gcKeepOutputsThreshold =
queryIntSetting ("gc-keep-outputs-threshold", defaultGcLevel);
//printMsg(lvlError, format("gcKeepOutputs %1% gcKeepDerivations: %2%") % gcKeepOutputs % gcKeepDerivations);
@ -536,7 +536,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
else if (store->isValidStatePath(j->second.path))
computeFSClosure(j->second.path, livePaths, true, true, 0);
=======
*/
string gcLevelStr = drv.env["__gcLevel"];
int gcLevel;
@ -550,6 +550,20 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
if (store->isValidPath(j->second.path) || store->isValidStatePath(j->second.path))
computeFSClosure(j->second.path, livePaths, true, true, 0);
}
=======
*/
string gcLevelStr = drv.env["__gcLevel"];
int gcLevel;
if (!string2Int(gcLevelStr, gcLevel))
gcLevel = defaultGcLevel;
if (gcLevel >= gcKeepOutputsThreshold)
for (DerivationOutputs::iterator j = drv.outputs.begin();
j != drv.outputs.end(); ++j)
if (store->isValidPath(j->second.path) || store->isValidStatePath(j->second.path))
computeFSClosure(j->second.path, livePaths, true, true, 0);
}
}
if (action == gcReturnLive) {

View file

@ -92,6 +92,25 @@ Path toStoreOrStatePath(const Path & path)
return Path(path, 0, slash);
}
Path followLinksToStore(const Path & _path)
{
Path path = absPath(_path);
while (!isInStore(path)) {
if (!isLink(path)) break;
string target = readLink(path);
path = absPath(target, dirOf(path));
}
if (!isInStore(path))
throw Error(format("path `%1%' is not in the Nix store") % path);
return path;
}
Path followLinksToStorePath(const Path & path)
{
return toStorePath(followLinksToStore(path));
}
void checkStoreName(const string & name)
{

View file

@ -259,11 +259,21 @@ bool isStatePath(const Path & path);
void checkStoreName(const string & name);
/* Chop off the parts after the top-level store name, e.g.,
/nix/store/abcd-foo/bar => /nix/store/abcd-foo. */
Path toStorePath(const Path & path);
Path toStoreOrStatePath(const Path & path);
/* Follow symlinks until we end up with a path in the Nix store. */
Path followLinksToStore(const Path & path);
/* Same as followLinksToStore(), but apply toStorePath() to the
result. */
Path followLinksToStorePath(const Path & path);
/* Constructs a unique store path name. */
Path makeStorePath(const string & type,
const Hash & hash, const string & suffix);

View file

@ -12,6 +12,7 @@
#include <sstream>
#include <fstream>
#include <iostream>
#include <cstring>
#include <sys/stat.h>
#include <sys/wait.h>
@ -106,8 +107,7 @@ Path canonPath(const Path & path, bool resolveSymlinks)
/* If s points to a symlink, resolve it and restart (since
the symlink target might contain new symlinks). */
if (resolveSymlinks && isLink(s)) {
followCount++;
if (followCount >= maxFollow)
if (++followCount >= maxFollow)
throw Error(format("infinite symlink recursion in path `%1%'") % path);
temp = absPath(readLink(s), dirOf(s))
+ string(i, end);
@ -1031,8 +1031,15 @@ string statusToString(int status)
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
if (WIFEXITED(status))
return (format("failed with exit code %1%") % WEXITSTATUS(status)).str();
else if (WIFSIGNALED(status))
return (format("failed due to signal %1%") % WTERMSIG(status)).str();
else if (WIFSIGNALED(status)) {
int sig = WTERMSIG(status);
#if HAVE_STRSIGNAL
const char * description = strsignal(sig);
return (format("failed due to signal %1% (%2%)") % sig % description).str();
#else
return (format("failed due to signal %1%") % sig).str();
#endif
}
else
return "died abnormally";
} else return "succeeded";

View file

@ -9,6 +9,7 @@ Operations:
--set: create a user environment containing a single derivation
--uninstall / -e: remove derivations from the user environment
--query / -q: perform a query on an environment or Nix expression
--set-flag NAME VALUE: set derivation meta-attribute to given value
The previous operations take a list of derivation names. The special
name `*' may be used to indicate all derivations.
@ -20,8 +21,6 @@ name `*' may be used to indicate all derivations.
--delete-generations GENERATIONS...: deleted listed generations,
`old' for all non-current generations
--import / -I FILE: set default Nix expression
--version: output version information
--help: display help

View file

@ -430,7 +430,7 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
/* Check that all selectors have been used. */
for (DrvNames::iterator i = selectors.begin();
i != selectors.end(); ++i)
if (i->hits == 0)
if (i->hits == 0 && i->fullName != "*")
throw Error(format("selector `%1%' matches no derivations")
% i->fullName);
@ -438,13 +438,18 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
}
static bool isPath(const string & s)
{
return s.find('/') != string::npos;
}
static void queryInstSources(EvalState & state,
const InstallSourceInfo & instSource, const Strings & args,
DrvInfos & elems, bool newestOnly)
{
InstallSourceType type = instSource.type;
if (type == srcUnknown && args.size() > 0 && args.front()[0] == '/')
if (type == srcUnknown && args.size() > 0 && isPath(args.front()))
type = srcStorePaths;
switch (type) {
@ -496,25 +501,24 @@ static void queryInstSources(EvalState & state,
for (Strings::const_iterator i = args.begin();
i != args.end(); ++i)
{
assertStorePath(*i);
Path path = followLinksToStorePath(*i);
DrvInfo elem;
elem.attrs = boost::shared_ptr<ATermMap>(new ATermMap(0)); /* ugh... */
string name = baseNameOf(*i);
string name = baseNameOf(path);
string::size_type dash = name.find('-');
if (dash != string::npos)
name = string(name, dash + 1);
if (isDerivation(*i)) {
elem.setDrvPath(*i);
elem.setOutPath(findOutput(derivationFromPath(*i), "out"));
if (isDerivation(path)) {
elem.setDrvPath(path);
elem.setOutPath(findOutput(derivationFromPath(path), "out"));
if (name.size() >= drvExtension.size() &&
string(name, name.size() - drvExtension.size()) == drvExtension)
name = string(name, 0, name.size() - drvExtension.size());
}
else
elem.setOutPath(*i);
else elem.setOutPath(path);
elem.name = name;
@ -964,7 +968,7 @@ static void opSet(Globals & globals,
}
static void uninstallDerivations(Globals & globals, DrvNames & selectors,
static void uninstallDerivations(Globals & globals, Strings & selectors,
Path & profile)
{
PathLocks lock;
@ -977,11 +981,13 @@ static void uninstallDerivations(Globals & globals, DrvNames & selectors,
{
DrvName drvName(i->name);
bool found = false;
for (DrvNames::iterator j = selectors.begin();
j != selectors.end(); ++j)
if (j->matches(drvName)) {
printMsg(lvlInfo,
format("uninstalling `%1%'") % i->name);
for (Strings::iterator j = selectors.begin(); j != selectors.end(); ++j)
/* !!! the repeated calls to followLinksToStorePath() are
expensive, should pre-compute them. */
if ((isPath(*j) && i->queryOutPath(globals.state) == followLinksToStorePath(*j))
|| DrvName(*j).matches(drvName))
{
printMsg(lvlInfo, format("uninstalling `%1%'") % i->name);
found = true;
break;
}
@ -1000,11 +1006,7 @@ static void opUninstall(Globals & globals,
{
if (opFlags.size() > 0)
throw UsageError(format("unknown flag `%1%'") % opFlags.front());
DrvNames drvNames = drvNamesFromArgs(opArgs);
uninstallDerivations(globals, drvNames,
globals.profile);
uninstallDerivations(globals, opArgs, globals.profile);
}

View file

@ -16,8 +16,13 @@ Operations:
--gc: run the garbage collector
--dump: dump a path as a Nix archive
--restore: restore a path from a Nix archive
--dump: dump a path as a Nix archive, forgetting dependencies
--restore: restore a path from a Nix archive, without
registering validity
--export: export a path as a Nix archive, marking dependencies
--import: import a path from a Nix archive, and register as
valid
--init: initialise the Nix database
--verify: verify Nix structures

View file

@ -29,7 +29,9 @@ static Path gcRoot;
static int rootNr = 0;
static bool indirectRoot = false;
/*
//Fixes the path and checks if it is a store path , see also toStorePath
<<<<<<< .working
static Path fixPath(Path path)
{
path = absPath(path);
@ -55,6 +57,9 @@ static Path fixStoreOrStatePath(Path path)
return toStoreOrStatePath(path);
}
=======
>>>>>>> .merge-right.r10133
*/
static Path useDeriver(Path path)
{
@ -99,7 +104,7 @@ static void opRealise(Strings opFlags, Strings opArgs)
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i)
*i = fixPath(*i);
*i = followLinksToStorePath(*i);
if (opArgs.size() > 1) {
PathSet drvPaths;
@ -292,7 +297,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i)
{
*i = fixPath(*i);
*i = followLinksToStorePath(*i);
if (forceRealise) realisePath(*i);
Derivation drv = derivationFromPathTxn(noTxn, *i);
cout << format("%1%\n") % findOutput(drv, "out");
@ -313,8 +318,10 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i)
{
Path path = maybeUseOutput(fixStoreOrStatePath(*i), useOutput, forceRealise);
if (query == qRequisites) store->storePathRequisites(path, includeOutputs, paths, true, false, revision);
Path path = maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise);
if (query == qRequisites)
store->storePathRequisites(path, includeOutputs, paths, true, false, revision);
else if (query == qRequisitesState) store->storePathRequisites(path, includeOutputs, paths, false, true, revision);
else if (query == qRequisitesFull) store->storePathRequisites(path, includeOutputs, paths, true, true, revision);
else if (query == qReferences) store->queryStoreReferences(path, paths, revision);
@ -335,7 +342,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i)
{
Path deriver = store->queryDeriver(fixPath(*i));
Path deriver = store->queryDeriver(followLinksToStorePath(*i));
cout << format("%1%\n") %
(deriver == "" ? "unknown-deriver" : deriver);
}
@ -345,7 +352,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i)
{
Path path = useDeriver(fixPath(*i));
Path path = useDeriver(followLinksToStorePath(*i));
Derivation drv = derivationFromPathTxn(noTxn, path);
StringPairs::iterator j = drv.env.find(bindingName);
if (j == drv.env.end())
@ -359,7 +366,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i)
{
Path path = maybeUseOutput(fixPath(*i), useOutput, forceRealise);
Path path = maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise);
Hash hash = store->queryPathHash(path);
assert(hash.type == htSHA256);
cout << format("sha256:%1%\n") % printHash32(hash);
@ -370,7 +377,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
PathSet done;
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i)
printTree(fixPath(*i), "", "", done);
printTree(followLinksToStorePath(*i), "", "", done);
break;
}
@ -378,7 +385,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
PathSet roots;
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i)
roots.insert(maybeUseOutput(fixPath(*i), useOutput, forceRealise));
roots.insert(maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise));
printDotGraph(roots);
break;
}
@ -386,7 +393,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qResolve: {
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i)
cout << format("%1%\n") % fixPath(*i);
cout << format("%1%\n") % followLinksToStorePath(*i);
break;
}
@ -403,7 +410,7 @@ static void opReadLog(Strings opFlags, Strings opArgs)
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i)
{
Path path = useDeriver(fixPath(*i));
Path path = useDeriver(followLinksToStorePath(*i));
Path logPath = (format("%1%/%2%/%3%") %
nixLogDir % drvsLogDir % baseNameOf(path)).str();
@ -460,7 +467,7 @@ static void opCheckValidity(Strings opFlags, Strings opArgs)
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i)
{
Path path = fixPath(*i);
Path path = followLinksToStorePath(*i);
if (!store->isValidPath(path))
if (printInvalid)
cout << format("%1%\n") % path;
@ -535,7 +542,7 @@ static void opDelete(Strings opFlags, Strings opArgs)
PathSet pathsToDelete;
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i)
pathsToDelete.insert(fixPath(*i));
pathsToDelete.insert(followLinksToStorePath(*i));
PathSet dummy;
PrintFreed freed(true, false);