From 90b5e692846d9b7a951155c5ed4fc7cf72b08e31 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 18 Nov 2013 10:21:12 +0000 Subject: Support quoted attribute names in -A This is requires if you have attribute names with dots in them. So you can now say: $ nix-instantiate '' -A 'config.systemd.units."postgresql.service".text' --eval-only Fixes #151. --- src/libexpr/attr-path.cc | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) (limited to 'src/libexpr/attr-path.cc') diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc index 737166435e39..4f28a549f035 100644 --- a/src/libexpr/attr-path.cc +++ b/src/libexpr/attr-path.cc @@ -6,23 +6,44 @@ namespace nix { +static Strings parseAttrPath(const string & s) +{ + Strings res; + string cur; + string::const_iterator i = s.begin(); + while (i != s.end()) { + if (*i == '.') { + res.push_back(cur); + cur.clear(); + } else if (*i == '"') { + ++i; + while (1) { + if (i == s.end()) + throw Error(format("missing closing quote in selection path `%1%'") % s); + if (*i == '"') break; + cur.push_back(*i++); + } + } else + cur.push_back(*i); + ++i; + } + if (!cur.empty()) res.push_back(cur); + return res; +} + + Value * findAlongAttrPath(EvalState & state, const string & attrPath, Bindings & autoArgs, Value & vIn) { - Strings tokens = tokenizeString(attrPath, "."); + Strings tokens = parseAttrPath(attrPath); Error attrError = Error(format("attribute selection path `%1%' does not match expression") % attrPath); - string curPath; - Value * v = &vIn; foreach (Strings::iterator, i, tokens) { - if (!curPath.empty()) curPath += "."; - curPath += *i; - /* Is *i an index (integer) or a normal attribute name? */ enum { apAttr, apIndex } apType = apAttr; string attr = *i; @@ -43,11 +64,14 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath, if (v->type != tAttrs) throw TypeError( format("the expression selected by the selection path `%1%' should be a set but is %2%") - % curPath % showType(*v)); + % attrPath % showType(*v)); + + if (attr.empty()) + throw Error(format("empty attribute name in selection path `%1%'") % attrPath); Bindings::iterator a = v->attrs->find(state.symbols.create(attr)); if (a == v->attrs->end()) - throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % curPath); + throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % attrPath); v = &*a->value; } @@ -56,10 +80,10 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath, if (v->type != tList) throw TypeError( format("the expression selected by the selection path `%1%' should be a list but is %2%") - % curPath % showType(*v)); + % attrPath % showType(*v)); if (attrIndex >= v->list.length) - throw Error(format("list index %1% in selection path `%2%' is out of range") % attrIndex % curPath); + throw Error(format("list index %1% in selection path `%2%' is out of range") % attrIndex % attrPath); v = v->list.elems[attrIndex]; } -- cgit 1.4.1