aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-06-21 07:55:38 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-06-21 07:55:38 +0000
commitbf87cc44b4484df74388b526c89884fea166ab7f (patch)
tree18a9a0e77d2e2a027eac094b3cdb43d6dd988cf4
parentd1f6c0cbe39b509545f809f08cbd580859f38e34 (diff)
parentb57189174f6e11c3e9e0f7c65c08a72f689fe194 (diff)
* Sync with the trunk.
-rw-r--r--src/libexpr/eval.cc15
-rw-r--r--src/libexpr/eval.hh2
-rw-r--r--src/libexpr/nixexpr.hh1
-rw-r--r--src/libexpr/primops.cc6
-rw-r--r--src/libexpr/value-to-xml.cc1
-rw-r--r--src/libstore/build.cc2
-rw-r--r--src/libstore/local-store.cc4
-rw-r--r--src/libstore/optimise-store.cc16
-rw-r--r--src/libstore/store-api.hh2
-rw-r--r--src/nix-env/user-env.cc2
-rw-r--r--src/nix-store/Makefile.am5
-rw-r--r--src/nix-store/dotgraph.cc2
-rw-r--r--src/nix-store/help.txt1
-rw-r--r--src/nix-store/nix-store.cc14
-rw-r--r--src/nix-store/xmlgraph.cc71
-rw-r--r--src/nix-store/xmlgraph.hh12
16 files changed, 140 insertions, 16 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 1ee6c5a7f..eb1d8d432 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 4e0af70ba..03bf43a3b 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 1c72441b2..b1043a326 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 9d36fb6a0..42c858611 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 e751fd300..8955a8a33 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 a482ace00..8ce8c873d 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 cf0d559bd..c7530f1b1 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 d15049201..3ed54e24d 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 fbe0cce81..3b81bfa39 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 72e13fceb..0a619f698 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 e0ba809dc..44ff54674 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 83df9e9cd..72146eb68 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 8022bf7c7..342281b33 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 3b34b9dae..b6ece30ce 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 000000000..1b3ad3d28
--- /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 000000000..2f9908c43
--- /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 */