forked from lix-project/lix
* Changes to the command line syntax of Nix.
* A function to find all Nix expressions whose output ids are completely contained in some set. Useful for uploading relevant Nix expressions to a shared cache.
This commit is contained in:
parent
401452e57a
commit
49231fbe41
124
src/nix.cc
124
src/nix.cc
|
@ -9,9 +9,7 @@
|
|||
typedef void (* Operation) (Strings opFlags, Strings opArgs);
|
||||
|
||||
|
||||
typedef enum { atpHash, atpPath, atpUnknown } ArgType;
|
||||
|
||||
static ArgType argType = atpUnknown;
|
||||
static bool pathArgs = false;
|
||||
|
||||
|
||||
/* Nix syntax:
|
||||
|
@ -39,12 +37,11 @@ static ArgType argType = atpUnknown;
|
|||
|
||||
Source selection for --install, --dump:
|
||||
|
||||
--file / -f: by file name !!! -> path
|
||||
--hash / -h: by hash (identifier)
|
||||
--path / -p: by file name !!! -> path
|
||||
|
||||
Query flags:
|
||||
|
||||
--path / -p: query the path of an fstate
|
||||
--list / -l: query the output paths (roots) of an fstate
|
||||
--refs / -r: query paths referenced by an fstate
|
||||
|
||||
Options:
|
||||
|
@ -53,39 +50,16 @@ static ArgType argType = atpUnknown;
|
|||
*/
|
||||
|
||||
|
||||
/* Parse the `-f' / `-h' / flags, i.e., the type of arguments. These
|
||||
flags are deleted from the referenced vector. */
|
||||
static void getArgType(Strings & flags)
|
||||
{
|
||||
for (Strings::iterator it = flags.begin();
|
||||
it != flags.end(); )
|
||||
{
|
||||
string arg = *it;
|
||||
ArgType tp;
|
||||
if (arg == "--hash" || arg == "-h") tp = atpHash;
|
||||
else if (arg == "--file" || arg == "-f") tp = atpPath;
|
||||
else { it++; continue; }
|
||||
if (argType != atpUnknown)
|
||||
throw UsageError("only one argument type specified may be specified");
|
||||
argType = tp;
|
||||
it = flags.erase(it);
|
||||
}
|
||||
if (argType == atpUnknown)
|
||||
throw UsageError("argument type not specified");
|
||||
}
|
||||
|
||||
|
||||
static FSId argToId(const string & arg)
|
||||
{
|
||||
if (argType == atpHash)
|
||||
if (!pathArgs)
|
||||
return parseHash(arg);
|
||||
else if (argType == atpPath) {
|
||||
string path;
|
||||
else {
|
||||
FSId id;
|
||||
addToStore(arg, path, id);
|
||||
if (!queryPathId(arg, id))
|
||||
throw Error(format("don't know id of `%1%'") % arg);
|
||||
return id;
|
||||
}
|
||||
else abort();
|
||||
}
|
||||
|
||||
|
||||
|
@ -93,7 +67,6 @@ static FSId argToId(const string & arg)
|
|||
expressions. */
|
||||
static void opInstall(Strings opFlags, Strings opArgs)
|
||||
{
|
||||
getArgType(opFlags);
|
||||
if (!opFlags.empty()) throw UsageError("unknown flag");
|
||||
|
||||
for (Strings::iterator it = opArgs.begin();
|
||||
|
@ -117,7 +90,6 @@ static void opDelete(Strings opFlags, Strings opArgs)
|
|||
paths. */
|
||||
static void opAdd(Strings opFlags, Strings opArgs)
|
||||
{
|
||||
getArgType(opFlags);
|
||||
if (!opFlags.empty()) throw UsageError("unknown flag");
|
||||
|
||||
for (Strings::iterator it = opArgs.begin();
|
||||
|
@ -134,47 +106,61 @@ static void opAdd(Strings opFlags, Strings opArgs)
|
|||
/* Perform various sorts of queries. */
|
||||
static void opQuery(Strings opFlags, Strings opArgs)
|
||||
{
|
||||
enum { qPath, qRefs, qUnknown } query = qPath;
|
||||
enum { qPaths, qRefs, qGenerators, qUnknown } query = qPaths;
|
||||
|
||||
for (Strings::iterator it = opFlags.begin();
|
||||
it != opFlags.end(); )
|
||||
{
|
||||
string arg = *it;
|
||||
if (arg == "--path" || arg == "-p") query = qPath;
|
||||
else if (arg == "--refs" || arg == "-r") query = qRefs;
|
||||
else { it++; continue; }
|
||||
it = opFlags.erase(it);
|
||||
}
|
||||
for (Strings::iterator i = opFlags.begin();
|
||||
i != opFlags.end(); i++)
|
||||
if (*i == "--list" || *i == "-l") query = qPaths;
|
||||
else if (*i == "--refs" || *i == "-r") query = qRefs;
|
||||
else if (*i == "--generators" || *i == "-g") query = qGenerators;
|
||||
else throw UsageError(format("unknown flag `%1%'") % *i);
|
||||
|
||||
getArgType(opFlags);
|
||||
if (!opFlags.empty()) throw UsageError("unknown flag");
|
||||
|
||||
for (Strings::iterator it = opArgs.begin();
|
||||
it != opArgs.end(); it++)
|
||||
{
|
||||
FSId id = argToId(*it);
|
||||
|
||||
switch (query) {
|
||||
|
||||
case qPath: {
|
||||
Strings paths = fstatePaths(id, true);
|
||||
for (Strings::iterator j = paths.begin();
|
||||
j != paths.end(); j++)
|
||||
cout << format("%s\n") % *j;
|
||||
switch (query) {
|
||||
|
||||
case qPaths: {
|
||||
StringSet paths;
|
||||
for (Strings::iterator i = opArgs.begin();
|
||||
i != opArgs.end(); i++)
|
||||
{
|
||||
Strings paths2 = fstatePaths(argToId(*i), true);
|
||||
paths.insert(paths2.begin(), paths2.end());
|
||||
}
|
||||
for (StringSet::iterator i = paths.begin();
|
||||
i != paths.end(); i++)
|
||||
cout << format("%s\n") % *i;
|
||||
break;
|
||||
}
|
||||
|
||||
case qRefs: {
|
||||
StringSet refs = fstateRefs(id);
|
||||
for (StringSet::iterator j = refs.begin();
|
||||
j != refs.end(); j++)
|
||||
cout << format("%s\n") % *j;
|
||||
StringSet paths;
|
||||
for (Strings::iterator i = opArgs.begin();
|
||||
i != opArgs.end(); i++)
|
||||
{
|
||||
Strings paths2 = fstateRefs(argToId(*i));
|
||||
paths.insert(paths2.begin(), paths2.end());
|
||||
}
|
||||
for (StringSet::iterator i = paths.begin();
|
||||
i != paths.end(); i++)
|
||||
cout << format("%s\n") % *i;
|
||||
break;
|
||||
}
|
||||
|
||||
case qGenerators: {
|
||||
FSIds outIds;
|
||||
for (Strings::iterator i = opArgs.begin();
|
||||
i != opArgs.end(); i++)
|
||||
outIds.push_back(argToId(*i));
|
||||
|
||||
FSIds genIds = findGenerators(outIds);
|
||||
|
||||
for (FSIds::iterator i = genIds.begin();
|
||||
i != genIds.end(); i++)
|
||||
cout << format("%s\n") % (string) *i;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,16 +210,12 @@ struct StdoutSink : DumpSink
|
|||
output. */
|
||||
static void opDump(Strings opFlags, Strings opArgs)
|
||||
{
|
||||
getArgType(opFlags);
|
||||
if (!opFlags.empty()) throw UsageError("unknown flag");
|
||||
if (opArgs.size() != 1) throw UsageError("only one argument allowed");
|
||||
|
||||
StdoutSink sink;
|
||||
string arg = *opArgs.begin();
|
||||
string path;
|
||||
|
||||
if (argType == atpHash) path = expandId(parseHash(arg));
|
||||
else if (argType == atpPath) path = arg;
|
||||
string path = pathArgs ? arg : expandId(parseHash(arg));
|
||||
|
||||
dumpPath(path, sink);
|
||||
}
|
||||
|
@ -313,6 +295,8 @@ void run(Strings args)
|
|||
op = opInit;
|
||||
else if (arg == "--verify")
|
||||
op = opVerify;
|
||||
else if (arg == "--path" || arg == "-p")
|
||||
pathArgs = true;
|
||||
else if (arg[0] == '-')
|
||||
opFlags.push_back(arg);
|
||||
else
|
||||
|
|
|
@ -248,18 +248,57 @@ Strings fstatePaths(const FSId & id, bool normalise)
|
|||
}
|
||||
|
||||
|
||||
StringSet fstateRefs(const FSId & id)
|
||||
Strings fstateRefs(const FSId & id)
|
||||
{
|
||||
StringSet paths;
|
||||
Strings paths;
|
||||
Slice slice = normaliseFState(id);
|
||||
for (SliceElems::const_iterator i = slice.elems.begin();
|
||||
i != slice.elems.end(); i++)
|
||||
paths.insert(i->path);
|
||||
paths.push_back(i->path);
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
||||
void findGenerators(const FSIds & ids)
|
||||
FSIds findGenerators(const FSIds & _ids)
|
||||
{
|
||||
|
||||
FSIdSet ids(_ids.begin(), _ids.end());
|
||||
FSIds generators;
|
||||
|
||||
/* !!! hack; for performance, we just look at the rhs of successor
|
||||
mappings, since we know that those are Nix expressions. */
|
||||
|
||||
Strings sucs;
|
||||
enumDB(nixDB, dbSuccessors, sucs);
|
||||
|
||||
for (Strings::iterator i = sucs.begin();
|
||||
i != sucs.end(); i++)
|
||||
{
|
||||
string s;
|
||||
queryDB(nixDB, dbSuccessors, *i, s);
|
||||
FSId id = parseHash(s);
|
||||
|
||||
FState fs;
|
||||
try {
|
||||
/* !!! should substitutes be used? */
|
||||
fs = parseFState(termFromId(id));
|
||||
} catch (...) { /* !!! only catch parse errors */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fs.type != FState::fsSlice) continue;
|
||||
|
||||
bool okay = true;
|
||||
for (SliceElems::const_iterator i = fs.slice.elems.begin();
|
||||
i != fs.slice.elems.end(); i++)
|
||||
if (ids.find(i->id) == ids.end()) {
|
||||
okay = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!okay) continue;
|
||||
|
||||
generators.push_back(id);
|
||||
}
|
||||
|
||||
return generators;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,11 @@ void realiseSlice(const Slice & slice);
|
|||
Strings fstatePaths(const FSId & id, bool normalise);
|
||||
|
||||
/* Get the list of paths referenced by the given fstate-expression. */
|
||||
StringSet fstateRefs(const FSId & id);
|
||||
Strings fstateRefs(const FSId & id);
|
||||
|
||||
/* Return the list of the ids of all known fstate-expressions whose
|
||||
output ids are completely contained in `ids'. */
|
||||
FSIds findGenerators(const FSIds & ids);
|
||||
|
||||
/* Register a successor. */
|
||||
void registerSuccessor(const FSId & id1, const FSId & id2);
|
||||
|
|
|
@ -148,6 +148,15 @@ void unregisterPath(const string & _path)
|
|||
}
|
||||
|
||||
|
||||
bool queryPathId(const string & path, FSId & id)
|
||||
{
|
||||
string s;
|
||||
if (!queryDB(nixDB, dbPath2Id, path, s)) return false;
|
||||
id = parseHash(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool isInPrefix(const string & path, const string & _prefix)
|
||||
{
|
||||
string prefix = canonPath(_prefix + "/");
|
||||
|
|
|
@ -20,6 +20,9 @@ void registerSubstitute(const FSId & srcId, const FSId & subId);
|
|||
/* Register a path keyed on its id. */
|
||||
void registerPath(const string & path, const FSId & id);
|
||||
|
||||
/* Query the id of a path. */
|
||||
bool queryPathId(const string & path, FSId & id);
|
||||
|
||||
/* Return a path whose contents have the given hash. If target is
|
||||
not empty, ensure that such a path is realised in target (if
|
||||
necessary by copying from another location). If prefix is not
|
||||
|
|
Loading…
Reference in a new issue