* Sync with the trunk.
This commit is contained in:
		
						commit
						bf87cc44b4
					
				
					 16 changed files with 140 additions and 16 deletions
				
			
		| 
						 | 
				
			
			@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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. */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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))
 | 
			
		||||
            try {
 | 
			
		||||
                store->buildDerivations(singleton<PathSet>(*i));
 | 
			
		||||
            } catch (Error & e) {
 | 
			
		||||
                throw ImportError(e.msg());
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    state.evalFile(path, v);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -267,7 +267,7 @@ public:
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
MakeError(SubstError, Error)
 | 
			
		||||
MakeError(BuildError, Error) /* denoted a permanent build failure */
 | 
			
		||||
MakeError(BuildError, Error) /* denotes a permanent build failure */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
        
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,8 +16,6 @@ namespace nix {
 | 
			
		|||
typedef std::map<Path, Path> Roots;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct GCOptions
 | 
			
		||||
{
 | 
			
		||||
    /* Garbage collector operation:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			@ -331,6 +333,14 @@ static void opQuery(Strings opFlags, Strings opArgs)
 | 
			
		|||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case qXml: {
 | 
			
		||||
            PathSet roots;
 | 
			
		||||
            foreach (Strings::iterator, i, opArgs)
 | 
			
		||||
                roots.insert(maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise));
 | 
			
		||||
            printXmlGraph(roots);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case qResolve: {
 | 
			
		||||
            foreach (Strings::iterator, i, opArgs)
 | 
			
		||||
                cout << format("%1%\n") % followLinksToStorePath(*i);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										71
									
								
								src/nix-store/xmlgraph.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/nix-store/xmlgraph.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								src/nix-store/xmlgraph.hh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/nix-store/xmlgraph.hh
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
#ifndef __XMLGRAPH_H
 | 
			
		||||
#define __XMLGRAPH_H
 | 
			
		||||
 | 
			
		||||
#include "types.hh"
 | 
			
		||||
 | 
			
		||||
namespace nix {
 | 
			
		||||
 | 
			
		||||
void printXmlGraph(const PathSet & roots);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* !__XMLGRAPH_H */
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue