forked from lix-project/lix
* When computing the set of paths referenced by an expression, also
include the paths of the subterms.
This commit is contained in:
parent
9a99dc736d
commit
2b95a9dc05
|
@ -180,7 +180,7 @@ static Expr evalExpr(Expr e)
|
||||||
SYSTEM, builder.c_str(), ins, out.c_str(), env);
|
SYSTEM, builder.c_str(), ins, out.c_str(), env);
|
||||||
|
|
||||||
/* Write the resulting term into the Nix store directory. */
|
/* Write the resulting term into the Nix store directory. */
|
||||||
Hash eHash = writeTerm(e);
|
Hash eHash = writeTerm(e, "-d-" + name);
|
||||||
|
|
||||||
return ATmake("Include(<str>)", ((string) eHash).c_str());
|
return ATmake("Include(<str>)", ((string) eHash).c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -148,30 +147,50 @@ Hash hashTerm(ATerm t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ATerm termFromHash(const Hash & hash)
|
ATerm termFromHash(const Hash & hash, string * p)
|
||||||
{
|
{
|
||||||
string path = queryPathByHash(hash);
|
string path = queryPathByHash(hash);
|
||||||
|
if (p) *p = path;
|
||||||
ATerm t = ATreadFromNamedFile(path.c_str());
|
ATerm t = ATreadFromNamedFile(path.c_str());
|
||||||
if (!t) throw Error(format("cannot read aterm %1%") % path);
|
if (!t) throw Error(format("cannot read aterm %1%") % path);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Hash writeTerm(ATerm t)
|
Hash writeTerm(ATerm t, const string & suffix, string * p)
|
||||||
{
|
{
|
||||||
string path = nixStore + "/tmp.nix"; /* !!! */
|
string path = nixStore + "/tmp.nix"; /* !!! */
|
||||||
if (!ATwriteToNamedTextFile(t, path.c_str()))
|
if (!ATwriteToNamedTextFile(t, path.c_str()))
|
||||||
throw Error(format("cannot write aterm %1%") % path);
|
throw Error(format("cannot write aterm %1%") % path);
|
||||||
Hash hash = hashPath(path);
|
Hash hash = hashPath(path);
|
||||||
string path2 = canonPath(nixStore + "/" + (string) hash + ".nix");
|
string path2 = canonPath(nixStore + "/" +
|
||||||
|
(string) hash + suffix + ".nix");
|
||||||
if (rename(path.c_str(), path2.c_str()) == -1)
|
if (rename(path.c_str(), path2.c_str()) == -1)
|
||||||
throw SysError(format("renaming %1% to %2%") % path % path2);
|
throw SysError(format("renaming %1% to %2%") % path % path2);
|
||||||
registerPath(path2, hash);
|
registerPath(path2, hash);
|
||||||
|
if (p) *p = path2;
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static FState realise(FState fs)
|
FState storeSuccessor(FState fs, FState sc, StringSet & paths)
|
||||||
|
{
|
||||||
|
if (fs == sc) return sc;
|
||||||
|
|
||||||
|
string path;
|
||||||
|
Hash fsHash = hashTerm(fs);
|
||||||
|
Hash scHash = writeTerm(sc, "-s-" + (string) fsHash, &path);
|
||||||
|
setDB(nixDB, dbSuccessors, fsHash, scHash);
|
||||||
|
paths.insert(path);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
return ATmake("Include(<str>)", ((string) scHash).c_str());
|
||||||
|
#endif
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static FState realise(FState fs, StringSet & paths)
|
||||||
{
|
{
|
||||||
char * s1, * s2, * s3;
|
char * s1, * s2, * s3;
|
||||||
Content content;
|
Content content;
|
||||||
|
@ -183,7 +202,9 @@ static FState realise(FState fs)
|
||||||
string fsHash, scHash;
|
string fsHash, scHash;
|
||||||
while (queryDB(nixDB, dbSuccessors, fsHash = hashTerm(fs), scHash)) {
|
while (queryDB(nixDB, dbSuccessors, fsHash = hashTerm(fs), scHash)) {
|
||||||
debug(format("successor %1% -> %2%") % (string) fsHash % scHash);
|
debug(format("successor %1% -> %2%") % (string) fsHash % scHash);
|
||||||
FState fs2 = termFromHash(parseHash(scHash));
|
string path;
|
||||||
|
FState fs2 = termFromHash(parseHash(scHash), &path);
|
||||||
|
paths.insert(path);
|
||||||
if (fs == fs2) {
|
if (fs == fs2) {
|
||||||
debug(format("successor cycle detected in %1%") % printTerm(fs));
|
debug(format("successor cycle detected in %1%") % printTerm(fs));
|
||||||
break;
|
break;
|
||||||
|
@ -195,7 +216,10 @@ static FState realise(FState fs)
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
|
|
||||||
if (ATmatch(fs, "Include(<str>)", &s1)) {
|
if (ATmatch(fs, "Include(<str>)", &s1)) {
|
||||||
return realise(termFromHash(parseHash(s1)));
|
string path;
|
||||||
|
fs = termFromHash(parseHash(s1), &path);
|
||||||
|
paths.insert(path);
|
||||||
|
return realise(fs, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (ATmatch(fs, "Path(<str>, <term>, [<list>])", &s1, &content, &refs)) {
|
else if (ATmatch(fs, "Path(<str>, <term>, [<list>])", &s1, &content, &refs)) {
|
||||||
|
@ -210,7 +234,7 @@ static FState realise(FState fs)
|
||||||
/* Realise referenced paths. */
|
/* Realise referenced paths. */
|
||||||
ATermList refs2 = ATempty;
|
ATermList refs2 = ATempty;
|
||||||
while (!ATisEmpty(refs)) {
|
while (!ATisEmpty(refs)) {
|
||||||
refs2 = ATinsert(refs2, realise(ATgetFirst(refs)));
|
refs2 = ATinsert(refs2, realise(ATgetFirst(refs), paths));
|
||||||
refs = ATgetNext(refs);
|
refs = ATgetNext(refs);
|
||||||
}
|
}
|
||||||
refs2 = ATreverse(refs2);
|
refs2 = ATreverse(refs2);
|
||||||
|
@ -224,27 +248,26 @@ static FState realise(FState fs)
|
||||||
path.c_str(), content, refs2);
|
path.c_str(), content, refs2);
|
||||||
|
|
||||||
/* Register the normal form. */
|
/* Register the normal form. */
|
||||||
if (fs != nf) {
|
nf = storeSuccessor(fs, nf, paths);
|
||||||
Hash nfHash = writeTerm(nf);
|
|
||||||
setDB(nixDB, dbSuccessors, hashTerm(fs), nfHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Perhaps the path already exists and has the right hash? */
|
/* Perhaps the path already exists and has the right hash? */
|
||||||
if (pathExists(path)) {
|
if (pathExists(path)) {
|
||||||
if (hash == hashPath(path)) {
|
|
||||||
debug(format("path %1% already has hash %2%")
|
if (hash != hashPath(path))
|
||||||
|
throw Error(format("path %1% exists, but does not have hash %2%")
|
||||||
% path % (string) hash);
|
% path % (string) hash);
|
||||||
return nf;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw Error(format("path %1% exists, but does not have hash %2%")
|
debug(format("path %1% already has hash %2%")
|
||||||
% path % (string) hash);
|
% path % (string) hash);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Do we know a path with that hash? If so, copy it. */
|
||||||
|
string path2 = queryPathByHash(hash);
|
||||||
|
copyPath(path2, path);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do we know a path with that hash? If so, copy it. */
|
|
||||||
string path2 = queryPathByHash(hash);
|
|
||||||
copyPath(path2, path);
|
|
||||||
|
|
||||||
return nf;
|
return nf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +284,7 @@ static FState realise(FState fs)
|
||||||
/* Realise inputs. */
|
/* Realise inputs. */
|
||||||
ATermList ins2 = ATempty;
|
ATermList ins2 = ATempty;
|
||||||
while (!ATisEmpty(ins)) {
|
while (!ATisEmpty(ins)) {
|
||||||
ins2 = ATinsert(ins2, realise(ATgetFirst(ins)));
|
ins2 = ATinsert(ins2, realise(ATgetFirst(ins), paths));
|
||||||
ins = ATgetNext(ins);
|
ins = ATgetNext(ins);
|
||||||
}
|
}
|
||||||
ins2 = ATreverse(ins2);
|
ins2 = ATreverse(ins2);
|
||||||
|
@ -306,8 +329,7 @@ static FState realise(FState fs)
|
||||||
/* Register the normal form of fs. */
|
/* Register the normal form of fs. */
|
||||||
FState nf = ATmake("Path(<str>, Hash(<str>), <term>)",
|
FState nf = ATmake("Path(<str>, Hash(<str>), <term>)",
|
||||||
outPath.c_str(), ((string) outHash).c_str(), ins2);
|
outPath.c_str(), ((string) outHash).c_str(), ins2);
|
||||||
Hash nfHash = writeTerm(nf);
|
nf = storeSuccessor(fs, nf, paths);
|
||||||
setDB(nixDB, dbSuccessors, hashTerm(fs), nfHash);
|
|
||||||
|
|
||||||
return nf;
|
return nf;
|
||||||
}
|
}
|
||||||
|
@ -316,9 +338,9 @@ static FState realise(FState fs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FState realiseFState(FState fs)
|
FState realiseFState(FState fs, StringSet & paths)
|
||||||
{
|
{
|
||||||
return realise(fs);
|
return realise(fs, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -338,9 +360,6 @@ string fstatePath(FState fs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef set<string> StringSet;
|
|
||||||
|
|
||||||
|
|
||||||
void fstateRefs2(FState fs, StringSet & paths)
|
void fstateRefs2(FState fs, StringSet & paths)
|
||||||
{
|
{
|
||||||
char * s1, * s2, * s3;
|
char * s1, * s2, * s3;
|
||||||
|
@ -372,11 +391,7 @@ void fstateRefs2(FState fs, StringSet & paths)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Strings fstateRefs(FState fs)
|
void fstateRefs(FState fs, StringSet & paths)
|
||||||
{
|
{
|
||||||
StringSet paths;
|
|
||||||
fstateRefs2(fs, paths);
|
fstateRefs2(fs, paths);
|
||||||
Strings paths2(paths.size());
|
|
||||||
copy(paths.begin(), paths.end(), paths2.begin());
|
|
||||||
return paths2;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef __EVAL_H
|
#ifndef __EVAL_H
|
||||||
#define __EVAL_H
|
#define __EVAL_H
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <aterm2.h>
|
#include <aterm2.h>
|
||||||
}
|
}
|
||||||
|
@ -59,17 +61,19 @@ using namespace std;
|
||||||
typedef ATerm FState;
|
typedef ATerm FState;
|
||||||
typedef ATerm Content;
|
typedef ATerm Content;
|
||||||
|
|
||||||
|
typedef set<string> StringSet;
|
||||||
|
|
||||||
|
|
||||||
/* Realise an fstate expression in the file system. This requires
|
/* Realise an fstate expression in the file system. This requires
|
||||||
execution of all Derive() nodes. */
|
execution of all Derive() nodes. */
|
||||||
FState realiseFState(FState fs);
|
FState realiseFState(FState fs, StringSet & paths);
|
||||||
|
|
||||||
/* Return the path of an fstate expression. An empty string is
|
/* Return the path of an fstate expression. An empty string is
|
||||||
returned if the term is not a valid fstate expression. (!!!) */
|
returned if the term is not a valid fstate expression. (!!!) */
|
||||||
string fstatePath(FState fs);
|
string fstatePath(FState fs);
|
||||||
|
|
||||||
/* Return the paths referenced by fstate expression. */
|
/* Return the paths referenced by fstate expression. */
|
||||||
Strings fstateRefs(FState fs);
|
void fstateRefs(FState fs, StringSet & paths);
|
||||||
|
|
||||||
/* Return a canonical textual representation of an expression. */
|
/* Return a canonical textual representation of an expression. */
|
||||||
string printTerm(ATerm t);
|
string printTerm(ATerm t);
|
||||||
|
@ -82,10 +86,10 @@ Error badTerm(const format & f, ATerm t);
|
||||||
Hash hashTerm(ATerm t);
|
Hash hashTerm(ATerm t);
|
||||||
|
|
||||||
/* Read an aterm from disk, given its hash. */
|
/* Read an aterm from disk, given its hash. */
|
||||||
ATerm termFromHash(const Hash & hash);
|
ATerm termFromHash(const Hash & hash, string * p = 0);
|
||||||
|
|
||||||
/* Write an aterm to the Nix store directory, and return its hash. */
|
/* Write an aterm to the Nix store directory, and return its hash. */
|
||||||
Hash writeTerm(ATerm t);
|
Hash writeTerm(ATerm t, const string & suffix, string * p = 0);
|
||||||
|
|
||||||
|
|
||||||
#endif /* !__EVAL_H */
|
#endif /* !__EVAL_H */
|
||||||
|
|
11
src/nix.cc
11
src/nix.cc
|
@ -96,7 +96,10 @@ static void opInstall(Strings opFlags, Strings opArgs)
|
||||||
|
|
||||||
for (Strings::iterator it = opArgs.begin();
|
for (Strings::iterator it = opArgs.begin();
|
||||||
it != opArgs.end(); it++)
|
it != opArgs.end(); it++)
|
||||||
realiseFState(termFromHash(argToHash(*it)));
|
{
|
||||||
|
StringSet paths;
|
||||||
|
realiseFState(termFromHash(argToHash(*it)), paths);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -160,8 +163,10 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case qRefs: {
|
case qRefs: {
|
||||||
Strings refs = fstateRefs(realiseFState(termFromHash(hash)));
|
StringSet refs;
|
||||||
for (Strings::iterator j = refs.begin();
|
FState fs = ATmake("Include(<str>)", ((string) hash).c_str());
|
||||||
|
fstateRefs(realiseFState(fs, refs), refs);
|
||||||
|
for (StringSet::iterator j = refs.begin();
|
||||||
j != refs.end(); j++)
|
j != refs.end(); j++)
|
||||||
cout << format("%s\n") % *j;
|
cout << format("%s\n") % *j;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue