diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-11-18T10·21+0000 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-11-18T10·21+0000 |
commit | 90b5e692846d9b7a951155c5ed4fc7cf72b08e31 (patch) | |
tree | a341049ade10d14c92f5bc7a031acb22fa54a366 /src/libexpr/attr-path.cc | |
parent | a478e8a7bb8c24da0ac91b7100bd0e422035c62f (diff) |
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 '<nixos>' -A 'config.systemd.units."postgresql.service".text' --eval-only Fixes #151.
Diffstat (limited to 'src/libexpr/attr-path.cc')
-rw-r--r-- | src/libexpr/attr-path.cc | 44 |
1 files changed, 34 insertions, 10 deletions
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<Strings>(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]; } |