From 2b95a9dc05d0a943859ba92bb301c294473758f1 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Jul 2003 15:02:03 +0000 Subject: [PATCH] * When computing the set of paths referenced by an expression, also include the paths of the subterms. --- src/fix.cc | 2 +- src/fstate.cc | 87 ++++++++++++++++++++++++++++++--------------------- src/fstate.hh | 12 ++++--- src/nix.cc | 11 +++++-- 4 files changed, 68 insertions(+), 44 deletions(-) diff --git a/src/fix.cc b/src/fix.cc index b4626f71f..d17e7b550 100644 --- a/src/fix.cc +++ b/src/fix.cc @@ -180,7 +180,7 @@ static Expr evalExpr(Expr e) SYSTEM, builder.c_str(), ins, out.c_str(), env); /* Write the resulting term into the Nix store directory. */ - Hash eHash = writeTerm(e); + Hash eHash = writeTerm(e, "-d-" + name); return ATmake("Include()", ((string) eHash).c_str()); } diff --git a/src/fstate.cc b/src/fstate.cc index 344197748..2f0e50fb2 100644 --- a/src/fstate.cc +++ b/src/fstate.cc @@ -1,5 +1,4 @@ #include -#include #include #include @@ -148,30 +147,50 @@ Hash hashTerm(ATerm t) } -ATerm termFromHash(const Hash & hash) +ATerm termFromHash(const Hash & hash, string * p) { string path = queryPathByHash(hash); + if (p) *p = path; ATerm t = ATreadFromNamedFile(path.c_str()); if (!t) throw Error(format("cannot read aterm %1%") % path); return t; } -Hash writeTerm(ATerm t) +Hash writeTerm(ATerm t, const string & suffix, string * p) { string path = nixStore + "/tmp.nix"; /* !!! */ if (!ATwriteToNamedTextFile(t, path.c_str())) throw Error(format("cannot write aterm %1%") % 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) throw SysError(format("renaming %1% to %2%") % path % path2); registerPath(path2, hash); + if (p) *p = path2; 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()", ((string) scHash).c_str()); +#endif + return sc; +} + + +static FState realise(FState fs, StringSet & paths) { char * s1, * s2, * s3; Content content; @@ -183,7 +202,9 @@ static FState realise(FState fs) string fsHash, scHash; while (queryDB(nixDB, dbSuccessors, fsHash = hashTerm(fs), 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) { debug(format("successor cycle detected in %1%") % printTerm(fs)); break; @@ -195,7 +216,10 @@ static FState realise(FState fs) /* Fall through. */ if (ATmatch(fs, "Include()", &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(, , [])", &s1, &content, &refs)) { @@ -210,7 +234,7 @@ static FState realise(FState fs) /* Realise referenced paths. */ ATermList refs2 = ATempty; while (!ATisEmpty(refs)) { - refs2 = ATinsert(refs2, realise(ATgetFirst(refs))); + refs2 = ATinsert(refs2, realise(ATgetFirst(refs), paths)); refs = ATgetNext(refs); } refs2 = ATreverse(refs2); @@ -224,27 +248,26 @@ static FState realise(FState fs) path.c_str(), content, refs2); /* Register the normal form. */ - if (fs != nf) { - Hash nfHash = writeTerm(nf); - setDB(nixDB, dbSuccessors, hashTerm(fs), nfHash); - } - + nf = storeSuccessor(fs, nf, paths); + /* Perhaps the path already exists and has the right hash? */ 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); - 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); + + } 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; } @@ -261,7 +284,7 @@ static FState realise(FState fs) /* Realise inputs. */ ATermList ins2 = ATempty; while (!ATisEmpty(ins)) { - ins2 = ATinsert(ins2, realise(ATgetFirst(ins))); + ins2 = ATinsert(ins2, realise(ATgetFirst(ins), paths)); ins = ATgetNext(ins); } ins2 = ATreverse(ins2); @@ -306,8 +329,7 @@ static FState realise(FState fs) /* Register the normal form of fs. */ FState nf = ATmake("Path(, Hash(), )", outPath.c_str(), ((string) outHash).c_str(), ins2); - Hash nfHash = writeTerm(nf); - setDB(nixDB, dbSuccessors, hashTerm(fs), nfHash); + nf = storeSuccessor(fs, nf, paths); 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 StringSet; - - void fstateRefs2(FState fs, StringSet & paths) { 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); - Strings paths2(paths.size()); - copy(paths.begin(), paths.end(), paths2.begin()); - return paths2; } diff --git a/src/fstate.hh b/src/fstate.hh index de6303dca..159c7ba46 100644 --- a/src/fstate.hh +++ b/src/fstate.hh @@ -1,6 +1,8 @@ #ifndef __EVAL_H #define __EVAL_H +#include + extern "C" { #include } @@ -59,17 +61,19 @@ using namespace std; typedef ATerm FState; typedef ATerm Content; +typedef set StringSet; + /* Realise an fstate expression in the file system. This requires 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 returned if the term is not a valid fstate expression. (!!!) */ string fstatePath(FState fs); /* 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. */ string printTerm(ATerm t); @@ -82,10 +86,10 @@ Error badTerm(const format & f, ATerm t); Hash hashTerm(ATerm t); /* 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. */ -Hash writeTerm(ATerm t); +Hash writeTerm(ATerm t, const string & suffix, string * p = 0); #endif /* !__EVAL_H */ diff --git a/src/nix.cc b/src/nix.cc index f3549ead8..d6f2db4fe 100644 --- a/src/nix.cc +++ b/src/nix.cc @@ -96,7 +96,10 @@ static void opInstall(Strings opFlags, Strings opArgs) for (Strings::iterator it = opArgs.begin(); 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; case qRefs: { - Strings refs = fstateRefs(realiseFState(termFromHash(hash))); - for (Strings::iterator j = refs.begin(); + StringSet refs; + FState fs = ATmake("Include()", ((string) hash).c_str()); + fstateRefs(realiseFState(fs, refs), refs); + for (StringSet::iterator j = refs.begin(); j != refs.end(); j++) cout << format("%s\n") % *j; break;