diff options
-rw-r--r-- | src/libexpr/eval.cc | 15 | ||||
-rw-r--r-- | src/libexpr/eval.hh | 2 | ||||
-rw-r--r-- | src/libexpr/nixexpr.hh | 1 | ||||
-rw-r--r-- | src/libexpr/primops.cc | 6 | ||||
-rw-r--r-- | src/libexpr/value-to-xml.cc | 1 | ||||
-rw-r--r-- | src/libstore/build.cc | 2 | ||||
-rw-r--r-- | src/libstore/local-store.cc | 4 | ||||
-rw-r--r-- | src/libstore/optimise-store.cc | 16 | ||||
-rw-r--r-- | src/libstore/store-api.hh | 2 | ||||
-rw-r--r-- | src/nix-env/user-env.cc | 2 | ||||
-rw-r--r-- | src/nix-store/Makefile.am | 5 | ||||
-rw-r--r-- | src/nix-store/dotgraph.cc | 2 | ||||
-rw-r--r-- | src/nix-store/help.txt | 1 | ||||
-rw-r--r-- | src/nix-store/nix-store.cc | 14 | ||||
-rw-r--r-- | src/nix-store/xmlgraph.cc | 71 | ||||
-rw-r--r-- | src/nix-store/xmlgraph.hh | 12 |
16 files changed, 140 insertions, 16 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 1ee6c5a7f6aa..eb1d8d432c69 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -59,6 +59,7 @@ std::ostream & operator << (std::ostream & str, const Value & v) str << "]"; break; case tThunk: + case tApp: case tCopy: str << "<CODE>"; break; @@ -901,12 +902,18 @@ string EvalState::forceString(Value & v) } -string EvalState::forceString(Value & v, PathSet & context) +void copyContext(const Value & v, PathSet & context) { - string s = forceString(v); if (v.string.context) for (const char * * p = v.string.context; *p; ++p) context.insert(*p); +} + + +string EvalState::forceString(Value & v, PathSet & context) +{ + string s = forceString(v); + copyContext(v, context); return s; } @@ -937,9 +944,7 @@ string EvalState::coerceToString(Value & v, PathSet & context, string s; if (v.type == tString) { - if (v.string.context) - for (const char * * p = v.string.context; *p; ++p) - context.insert(*p); + copyContext(v, context); return v.string.s; } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 4e0af70ba64b..03bf43a3b9a4 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -163,6 +163,8 @@ void mkString(Value & v, const char * s); void mkString(Value & v, const string & s, const PathSet & context = PathSet()); void mkPath(Value & v, const char * s); +void copyContext(const Value & v, PathSet & context); + typedef std::map<Path, Hash> DrvHashes; diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 1c72441b2792..b1043a32684e 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -15,6 +15,7 @@ MakeError(AssertionError, EvalError) MakeError(ThrownError, AssertionError) MakeError(Abort, EvalError) MakeError(TypeError, EvalError) +MakeError(ImportError, EvalError) // error building an imported derivation /* Position objects. */ diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 9d36fb6a05d7..42c8586116aa 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -37,7 +37,11 @@ static void prim_import(EvalState & state, Value * * args, Value & v) throw EvalError(format("cannot import `%1%', since path `%2%' is not valid") % path % *i); if (isDerivation(*i)) - store->buildDerivations(singleton<PathSet>(*i)); + try { + store->buildDerivations(singleton<PathSet>(*i)); + } catch (Error & e) { + throw ImportError(e.msg()); + } } state.evalFile(path, v); diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc index e751fd300fdb..8955a8a33931 100644 --- a/src/libexpr/value-to-xml.cc +++ b/src/libexpr/value-to-xml.cc @@ -69,6 +69,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location, case tString: /* !!! show the context? */ + copyContext(v, context); doc.writeEmptyElement("string", singletonAttrs("value", v.string.s)); break; diff --git a/src/libstore/build.cc b/src/libstore/build.cc index a482ace00c22..8ce8c873d6a3 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -267,7 +267,7 @@ public: MakeError(SubstError, Error) -MakeError(BuildError, Error) /* denoted a permanent build failure */ +MakeError(BuildError, Error) /* denotes a permanent build failure */ ////////////////////////////////////////////////////////////////////// diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index cf0d559bdfb9..c7530f1b1bae 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1036,6 +1036,8 @@ void LocalStore::exportPath(const Path & path, bool sign, writeInt(1, hashAndWriteSink); Path tmpDir = createTempDir(); + PathLocks tmpDirLock(singleton<PathSet, Path>(tmpDir)); + tmpDirLock.setDeletion(true); AutoDelete delTmp(tmpDir); Path hashFile = tmpDir + "/hash"; writeFile(hashFile, printHash(hash)); @@ -1085,6 +1087,8 @@ Path LocalStore::importPath(bool requireSignature, Source & source) store path follows the archive data proper), and besides, we don't know yet whether the signature is valid. */ Path tmpDir = createTempDir(nixStore); + PathLocks tmpDirLock(singleton<PathSet, Path>(tmpDir)); + tmpDirLock.setDeletion(true); AutoDelete delTmp(tmpDir); /* !!! could be GC'ed! */ Path unpacked = tmpDir + "/unpacked"; diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index d15049201ea4..3ed54e24d773 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -119,9 +119,23 @@ static void hashAndLink(bool dryRun, HashToPath & hashToPath, } /* Atomically replace the old file with the new hard link. */ - if (rename(tempLink.c_str(), path.c_str()) == -1) + if (rename(tempLink.c_str(), path.c_str()) == -1) { + if (errno == EMLINK) { + /* Some filesystems generate too many links on the + rename, rather than on the original link. + (Probably it temporarily increases the st_nlink + field before decreasing it again.) */ + printMsg(lvlInfo, format("`%1%' has maximum number of links") % prevPath.first); + hashToPath[hash] = std::pair<Path, ino_t>(path, st.st_ino); + + /* Unlink the temp link. */ + if (unlink(tempLink.c_str()) == -1) + printMsg(lvlError, format("unable to unlink `%1%'") % tempLink); + return; + } throw SysError(format("cannot rename `%1%' to `%2%'") % tempLink % path); + } } else printMsg(lvlTalkative, format("would link `%1%' to `%2%'") % path % prevPath.first); diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index fbe0cce81e94..3b81bfa39438 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -16,8 +16,6 @@ namespace nix { typedef std::map<Path, Path> Roots; - - struct GCOptions { /* Garbage collector operation: diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index 72e13fceb191..0a619f698f98 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -106,8 +106,6 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, Path manifestFile = store->addTextToStore("env-manifest.nix", (format("%1%") % manifest).str(), references); - printMsg(lvlError, manifestFile); - /* Get the environment builder expression. */ Value envBuilder; state.eval(parseExprFromFile(state, nixDataDir + "/nix/corepkgs/buildenv"), envBuilder); diff --git a/src/nix-store/Makefile.am b/src/nix-store/Makefile.am index e0ba809dcb2a..44ff54674ade 100644 --- a/src/nix-store/Makefile.am +++ b/src/nix-store/Makefile.am @@ -1,6 +1,9 @@ bin_PROGRAMS = nix-store -nix_store_SOURCES = nix-store.cc dotgraph.cc dotgraph.hh help.txt +nix_store_SOURCES = \ + nix-store.cc dotgraph.cc dotgraph.hh help.txt \ + xmlgraph.cc xmlgraph.hh + nix_store_LDADD = ../libmain/libmain.la ../libstore/libstore.la ../libutil/libutil.la \ ../boost/format/libformat.la diff --git a/src/nix-store/dotgraph.cc b/src/nix-store/dotgraph.cc index 83df9e9cd0ce..72146eb68efc 100644 --- a/src/nix-store/dotgraph.cc +++ b/src/nix-store/dotgraph.cc @@ -52,13 +52,13 @@ static string symbolicName(const string & path) } +#if 0 string pathLabel(const Path & nePath, const string & elemPath) { return (string) nePath + "-" + elemPath; } -#if 0 void printClosure(const Path & nePath, const StoreExpr & fs) { PathSet workList(fs.closure.roots); diff --git a/src/nix-store/help.txt b/src/nix-store/help.txt index 8022bf7c7120..342281b338c4 100644 --- a/src/nix-store/help.txt +++ b/src/nix-store/help.txt @@ -42,6 +42,7 @@ Query flags: --referrers-closure: print all paths (in)directly refering to the path --tree: print a tree showing the dependency graph of the path --graph: print a dot graph rooted at given path + --xml: emit an XML representation of the graph rooted at the given path --hash: print the SHA-256 hash of the contents of the path --roots: print the garbage collector roots that point to the path diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 3b34b9dae6f4..b6ece30ce0b8 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -6,6 +6,7 @@ #include "archive.hh" #include "shared.hh" #include "dotgraph.hh" +#include "xmlgraph.hh" #include "local-store.hh" #include "util.hh" #include "help.txt.hh" @@ -226,7 +227,7 @@ static void opQuery(Strings opFlags, Strings opArgs) { enum { qOutputs, qRequisites, qReferences, qReferrers , qReferrersClosure, qDeriver, qBinding, qHash - , qTree, qGraph, qResolve, qRoots } query = qOutputs; + , qTree, qGraph, qXml, qResolve, qRoots } query = qOutputs; bool useOutput = false; bool includeOutputs = false; bool forceRealise = false; @@ -249,6 +250,7 @@ static void opQuery(Strings opFlags, Strings opArgs) else if (*i == "--hash") query = qHash; else if (*i == "--tree") query = qTree; else if (*i == "--graph") query = qGraph; + else if (*i == "--xml") query = qXml; else if (*i == "--resolve") query = qResolve; else if (*i == "--roots") query = qRoots; else if (*i == "--use-output" || *i == "-u") useOutput = true; @@ -327,7 +329,15 @@ static void opQuery(Strings opFlags, Strings opArgs) PathSet roots; foreach (Strings::iterator, i, opArgs) roots.insert(maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise)); - printDotGraph(roots); + printDotGraph(roots); + break; + } + + case qXml: { + PathSet roots; + foreach (Strings::iterator, i, opArgs) + roots.insert(maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise)); + printXmlGraph(roots); break; } diff --git a/src/nix-store/xmlgraph.cc b/src/nix-store/xmlgraph.cc new file mode 100644 index 000000000000..1b3ad3d28ad4 --- /dev/null +++ b/src/nix-store/xmlgraph.cc @@ -0,0 +1,71 @@ +#include "xmlgraph.hh" +#include "util.hh" +#include "store-api.hh" + +#include <iostream> + + +using std::cout; + +namespace nix { + + +static inline const string & xmlQuote(const string & s) +{ + // Luckily, store paths shouldn't contain any character that needs to be + // quoted. + return s; +} + + +static string makeEdge(const string & src, const string & dst) +{ + format f = format(" <edge src=\"%1%\" dst=\"%2%\"/>\n") + % xmlQuote(src) % xmlQuote(dst); + return f.str(); +} + + +static string makeNode(const string & id) +{ + format f = format(" <node name=\"%1%\"/>\n") % xmlQuote(id); + return f.str(); +} + + +void printXmlGraph(const PathSet & roots) +{ + PathSet workList(roots); + PathSet doneSet; + + cout << "<?xml version='1.0' encoding='utf-8'?>\n" + << "<nix>\n"; + + while (!workList.empty()) { + Path path = *(workList.begin()); + workList.erase(path); + + if (doneSet.find(path) != doneSet.end()) continue; + doneSet.insert(path); + + cout << makeNode(path); + + PathSet references; + store->queryReferences(path, references); + + for (PathSet::iterator i = references.begin(); + i != references.end(); ++i) + { + if (*i != path) { + workList.insert(*i); + cout << makeEdge(*i, path); + } + } + + } + + cout << "</nix>\n"; +} + + +} diff --git a/src/nix-store/xmlgraph.hh b/src/nix-store/xmlgraph.hh new file mode 100644 index 000000000000..2f9908c43665 --- /dev/null +++ b/src/nix-store/xmlgraph.hh @@ -0,0 +1,12 @@ +#ifndef __XMLGRAPH_H +#define __XMLGRAPH_H + +#include "types.hh" + +namespace nix { + +void printXmlGraph(const PathSet & roots); + +} + +#endif /* !__XMLGRAPH_H */ |