From e1a6fb787059848c815a8154da23b7da794c6231 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Sun, 14 Aug 2005 14:00:39 +0000 Subject: * `dependencyClosure' now allows a search path, e.g., dependencyClosure { ... searchPath = [ ../foo ../bar ]; ... } * Primop `dirOf' to return the directory part of a path (e.g., dirOf /a/b/c == /a/b). * Primop `relativise' (according to Webster that's a real word!) that given paths A and B returns a string representing path B relative path to A; e.g., relativise /a/b/c a/b/x/y => "../x/y". --- src/libexpr/primops.cc | 89 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 20 deletions(-) (limited to 'src/libexpr/primops.cc') diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index f4e7b7b82b46..bd8f95e4790a 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -372,6 +372,14 @@ static Expr primBaseNameOf(EvalState & state, const ATermVector & args) } +/* Return the directory of the given path, i.e., everything before the + last slash. */ +static Expr primDirOf(EvalState & state, const ATermVector & args) +{ + return makePath(toATerm(dirOf(evalPath(state, args[0])))); +} + + /* Convert the argument (which can be a path or a uri) to a string. */ static Expr primToString(EvalState & state, const ATermVector & args) { @@ -410,12 +418,12 @@ static Expr primIsNull(EvalState & state, const ATermVector & args) } -static Path findDependency(Path start, string dep) +static Path findDependency(Path dir, string dep) { if (dep[0] == '/') throw Error( format("illegal absolute dependency `%1%'") % dep); - Path p = canonPath(dirOf(start) + "/" + dep); + Path p = canonPath(dir + "/" + dep); if (pathExists(p)) return p; @@ -464,11 +472,11 @@ static string relativise(Path pivot, Path p) static Expr primDependencyClosure(EvalState & state, const ATermVector & args) { + startNest(nest, lvlDebug, "finding dependencies"); + Expr attrs = evalExpr(state, args[0]); - Expr scanner = queryAttr(attrs, "scanner"); - if (!scanner) throw Error("attribute `scanner' required"); - + /* Get the start set. */ Expr startSet = queryAttr(attrs, "startSet"); if (!startSet) throw Error("attribute `startSet' required"); ATermList startSet2 = evalList(state, startSet); @@ -481,6 +489,20 @@ static Expr primDependencyClosure(EvalState & state, const ATermVector & args) pivot = dirOf(p); } + /* Get the search path. */ + PathSet searchPath; + Expr e = queryAttr(attrs, "searchPath"); + if (e) { + ATermList list = evalList(state, e); + for (ATermIterator i(list); i; ++i) { + Path p = evalPath(state, *i); + searchPath.insert(p); + } + } + + Expr scanner = queryAttr(attrs, "scanner"); + if (!scanner) throw Error("attribute `scanner' required"); + /* Construct the dependency closure by querying the dependency of each path in `workSet', adding the dependencies to `workSet'. */ @@ -492,19 +514,38 @@ static Expr primDependencyClosure(EvalState & state, const ATermVector & args) if (doneSet.find(path) != doneSet.end()) continue; doneSet.insert(path); - /* Call the `scanner' function with `path' as argument. */ - printMsg(lvlError, format("finding dependencies in `%1%'") % path); - ATermList deps = evalList(state, makeCall(scanner, makePath(toATerm(path)))); - - /* Try to find the dependencies relative to the `path'. */ - for (ATermIterator i(deps); i; ++i) { - Path dep = findDependency(path, evalString(state, *i)); - if (dep == "") - printMsg(lvlError, format("did NOT find dependency `%1%'") % dep); - else { - printMsg(lvlError, format("found dependency `%1%'") % dep); - workSet.insert(dep); + try { + + /* Call the `scanner' function with `path' as argument. */ + debug(format("finding dependencies in `%1%'") % path); + ATermList deps = evalList(state, makeCall(scanner, makePath(toATerm(path)))); + + /* Try to find the dependencies relative to the `path'. */ + for (ATermIterator i(deps); i; ++i) { + string s = evalString(state, *i); + + Path dep = findDependency(dirOf(path), s); + + if (dep == "") { + for (PathSet::iterator j = searchPath.begin(); + j != searchPath.end(); ++j) + { + dep = findDependency(*j, s); + if (dep != "") break; + } + } + + if (dep == "") + debug(format("did NOT find dependency `%1%'") % s); + else { + debug(format("found dependency `%1%'") % dep); + workSet.insert(dep); + } } + + } catch (Error & e) { + throw Error(format("while finding dependencies in `%1%':\n%2%") + % path % e.msg()); } } @@ -515,7 +556,7 @@ static Expr primDependencyClosure(EvalState & state, const ATermVector & args) deps = ATinsert(deps, makePath(toATerm(*i))); } - printMsg(lvlError, format("RESULT is `%1%'") % makeList(deps)); + debug(format("dependency list is `%1%'") % makeList(deps)); return makeList(deps); } @@ -566,6 +607,14 @@ static Expr primRemoveAttrs(EvalState & state, const ATermVector & args) } +static Expr primRelativise(EvalState & state, const ATermVector & args) +{ + Path pivot = evalPath(state, args[0]); + Path path = evalPath(state, args[1]); + return makeStr(toATerm(relativise(pivot, path))); +} + + void EvalState::addPrimOps() { addPrimOp("true", 0, primTrue); @@ -578,12 +627,12 @@ void EvalState::addPrimOps() addPrimOp("derivation!", 1, primDerivationStrict); addPrimOp("derivation", 1, primDerivationLazy); addPrimOp("baseNameOf", 1, primBaseNameOf); + addPrimOp("dirOf", 1, primDirOf); addPrimOp("toString", 1, primToString); addPrimOp("isNull", 1, primIsNull); addPrimOp("dependencyClosure", 1, primDependencyClosure); addPrimOp("map", 2, primMap); addPrimOp("removeAttrs", 2, primRemoveAttrs); + addPrimOp("relativise", 2, primRelativise); } - - -- cgit 1.4.1