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.
This commit is contained in:
		
							parent
							
								
									a478e8a7bb
								
							
						
					
					
						commit
						90b5e69284
					
				
					 3 changed files with 38 additions and 14 deletions
				
			
		| 
						 | 
					@ -6,23 +6,44 @@
 | 
				
			||||||
namespace nix {
 | 
					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,
 | 
					Value * findAlongAttrPath(EvalState & state, const string & attrPath,
 | 
				
			||||||
    Bindings & autoArgs, Value & vIn)
 | 
					    Bindings & autoArgs, Value & vIn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Strings tokens = tokenizeString<Strings>(attrPath, ".");
 | 
					    Strings tokens = parseAttrPath(attrPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Error attrError =
 | 
					    Error attrError =
 | 
				
			||||||
        Error(format("attribute selection path `%1%' does not match expression") % attrPath);
 | 
					        Error(format("attribute selection path `%1%' does not match expression") % attrPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    string curPath;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Value * v = &vIn;
 | 
					    Value * v = &vIn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    foreach (Strings::iterator, i, tokens) {
 | 
					    foreach (Strings::iterator, i, tokens) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!curPath.empty()) curPath += ".";
 | 
					 | 
				
			||||||
        curPath += *i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Is *i an index (integer) or a normal attribute name? */
 | 
					        /* Is *i an index (integer) or a normal attribute name? */
 | 
				
			||||||
        enum { apAttr, apIndex } apType = apAttr;
 | 
					        enum { apAttr, apIndex } apType = apAttr;
 | 
				
			||||||
        string attr = *i;
 | 
					        string attr = *i;
 | 
				
			||||||
| 
						 | 
					@ -43,11 +64,14 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
 | 
				
			||||||
            if (v->type != tAttrs)
 | 
					            if (v->type != tAttrs)
 | 
				
			||||||
                throw TypeError(
 | 
					                throw TypeError(
 | 
				
			||||||
                    format("the expression selected by the selection path `%1%' should be a set but is %2%")
 | 
					                    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));
 | 
					            Bindings::iterator a = v->attrs->find(state.symbols.create(attr));
 | 
				
			||||||
            if (a == v->attrs->end())
 | 
					            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;
 | 
					            v = &*a->value;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,10 +80,10 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
 | 
				
			||||||
            if (v->type != tList)
 | 
					            if (v->type != tList)
 | 
				
			||||||
                throw TypeError(
 | 
					                throw TypeError(
 | 
				
			||||||
                    format("the expression selected by the selection path `%1%' should be a list but is %2%")
 | 
					                    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)
 | 
					            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];
 | 
					            v = v->list.elems[attrIndex];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,13 +14,13 @@ rec {
 | 
				
			||||||
      done < refs
 | 
					      done < refs
 | 
				
			||||||
    '';
 | 
					    '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  runtimeGraph = mkDerivation {
 | 
					  foo."bar.runtimeGraph" = mkDerivation {
 | 
				
			||||||
    name = "dependencies";
 | 
					    name = "dependencies";
 | 
				
			||||||
    builder = builtins.toFile "build-graph-builder" "${printRefs}";
 | 
					    builder = builtins.toFile "build-graph-builder" "${printRefs}";
 | 
				
			||||||
    exportReferencesGraph = ["refs" (import ./dependencies.nix)];
 | 
					    exportReferencesGraph = ["refs" (import ./dependencies.nix)];
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  buildGraph = mkDerivation {
 | 
					  foo."bar.buildGraph" = mkDerivation {
 | 
				
			||||||
    name = "dependencies";
 | 
					    name = "dependencies";
 | 
				
			||||||
    builder = builtins.toFile "build-graph-builder" "${printRefs}";
 | 
					    builder = builtins.toFile "build-graph-builder" "${printRefs}";
 | 
				
			||||||
    exportReferencesGraph = ["refs" (import ./dependencies.nix).drvPath];
 | 
					    exportReferencesGraph = ["refs" (import ./dependencies.nix).drvPath];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ checkRef() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Test the export of the runtime dependency graph.
 | 
					# Test the export of the runtime dependency graph.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
outPath=$(nix-build ./export-graph.nix -A runtimeGraph -o $TEST_ROOT/result)
 | 
					outPath=$(nix-build ./export-graph.nix -A 'foo."bar.runtimeGraph"' -o $TEST_ROOT/result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test $(nix-store -q --references $TEST_ROOT/result | wc -l) = 2 || fail "bad nr of references"
 | 
					test $(nix-store -q --references $TEST_ROOT/result | wc -l) = 2 || fail "bad nr of references"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ for i in $(cat $outPath); do checkRef $i; done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nix-store --gc # should force rebuild of input-1
 | 
					nix-store --gc # should force rebuild of input-1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
outPath=$(nix-build ./export-graph.nix -A buildGraph -o $TEST_ROOT/result)
 | 
					outPath=$(nix-build ./export-graph.nix -A 'foo."bar.buildGraph"' -o $TEST_ROOT/result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
checkRef input-1
 | 
					checkRef input-1
 | 
				
			||||||
checkRef input-1.drv
 | 
					checkRef input-1.drv
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue