From e0953d53de1dbb89ef0ff779e53ffdb0d988e806 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 19 Feb 2015 08:05:16 -0500 Subject: [PATCH 1/5] Allow the leading component of a path to be a ~ --- doc/manual/expressions/language-values.xml | 9 ++++++++- src/libexpr/lexer.l | 2 ++ src/libexpr/parser.y | 10 +++++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/doc/manual/expressions/language-values.xml b/doc/manual/expressions/language-values.xml index c3514e58f..0bf6632d6 100644 --- a/doc/manual/expressions/language-values.xml +++ b/doc/manual/expressions/language-values.xml @@ -155,7 +155,14 @@ stdenv.mkDerivation { expression that contained it. For instance, if a Nix expression in /foo/bar/bla.nix refers to ../xyzzy/fnord.nix, the absolute path is - /foo/xyzzy/fnord.nix. + /foo/xyzzy/fnord.nix. + + If the first component of a path is a ~, + it is interpreted as if the rest of the path were relative to the + user's home directory. e.g. ~/foo would be + equivalent to /home/edolstra/foo for a user + whose home directory is /home/edolstra. + Booleans with values true and diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l index 82520ee7a..705190900 100644 --- a/src/libexpr/lexer.l +++ b/src/libexpr/lexer.l @@ -80,6 +80,7 @@ static Expr * unescapeStr(SymbolTable & symbols, const char * s) ID [a-zA-Z\_][a-zA-Z0-9\_\'\-]* INT [0-9]+ PATH [a-zA-Z0-9\.\_\-\+]*(\/[a-zA-Z0-9\.\_\-\+]+)+ +HPATH \~(\/[a-zA-Z0-9\.\_\-\+]+)+ SPATH \<[a-zA-Z0-9\.\_\-\+]+(\/[a-zA-Z0-9\.\_\-\+]+)*\> URI [a-zA-Z][a-zA-Z0-9\+\-\.]*\:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~\*\']+ @@ -159,6 +160,7 @@ or { return OR_KW; } . return yytext[0]; /* just in case: shouldn't be reached */ {PATH} { yylval->path = strdup(yytext); return PATH; } +{HPATH} { yylval->path = strdup(yytext); return HPATH; } {SPATH} { yylval->path = strdup(yytext); return SPATH; } {URI} { yylval->uri = strdup(yytext); return URI; } diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 7d877cd67..f4648b902 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -268,7 +268,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err %token ID ATTRPATH %token STR IND_STR %token INT -%token PATH SPATH +%token PATH HPATH SPATH %token URI %token IF THEN ELSE ASSERT WITH LET IN REC INHERIT EQ NEQ AND OR IMPL OR_KW %token DOLLAR_CURLY /* == ${ */ @@ -376,6 +376,14 @@ expr_simple $$ = stripIndentation(CUR_POS, data->symbols, *$2); } | PATH { $$ = new ExprPath(absPath($1, data->basePath)); } + | HPATH { + auto path = string{$1 + 1}; + $$ = new ExprConcatStrings(CUR_POS, false, new vector{ + new ExprPath("/"), + new ExprApp(new ExprVar(data->symbols.create("__getEnv")), + new ExprString(data->symbols.create("HOME"))), + new ExprString(data->symbols.create(path))}); + } | SPATH { string path($1 + 1, strlen($1) - 2); $$ = new ExprApp(CUR_POS, From 4646e946100f103edd509a716b9c1a8849fc7895 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 19 Feb 2015 08:39:25 -0500 Subject: [PATCH 2/5] ExprConcatStrings: canonicalize concatenated paths --- src/libexpr/eval.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 298f6a3a6..95b56e84d 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1174,7 +1174,8 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) else if (firstType == tPath) { if (!context.empty()) throwEvalError("a string that refers to a store path cannot be appended to a path, at %1%", pos); - mkPath(v, s.str().c_str()); + auto path = canonPath(s.str()); + mkPath(v, path.c_str()); } else mkString(v, s.str(), context); } From 4b7c9f834c6e861ced90558a13fe4b78b584b710 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 19 Feb 2015 08:49:10 -0500 Subject: [PATCH 3/5] tilde paths: get HOME at parse time --- src/libexpr/parser.y | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index f4648b902..010024de5 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -379,9 +379,7 @@ expr_simple | HPATH { auto path = string{$1 + 1}; $$ = new ExprConcatStrings(CUR_POS, false, new vector{ - new ExprPath("/"), - new ExprApp(new ExprVar(data->symbols.create("__getEnv")), - new ExprString(data->symbols.create("HOME"))), + new ExprPath(getEnv("HOME", "/")), new ExprString(data->symbols.create(path))}); } | SPATH { From e3e38a048e3dbe6d0e8beff7023a05113fe36fe8 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 19 Feb 2015 08:51:21 -0500 Subject: [PATCH 4/5] tilde paths: construct the entire path at parse time --- src/libexpr/parser.y | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 010024de5..1ab84c045 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -376,12 +376,7 @@ expr_simple $$ = stripIndentation(CUR_POS, data->symbols, *$2); } | PATH { $$ = new ExprPath(absPath($1, data->basePath)); } - | HPATH { - auto path = string{$1 + 1}; - $$ = new ExprConcatStrings(CUR_POS, false, new vector{ - new ExprPath(getEnv("HOME", "/")), - new ExprString(data->symbols.create(path))}); - } + | HPATH { $$ = new ExprPath(getEnv("HOME", "/") + string{$1 + 1}); } | SPATH { string path($1 + 1, strlen($1) - 2); $$ = new ExprApp(CUR_POS, From c4653afbcd96bf8f43bb54c1c2f79a27fd615e11 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 19 Feb 2015 08:52:13 -0500 Subject: [PATCH 5/5] tilde paths: The rest of the string has to start with a slash anyway --- src/libexpr/parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 1ab84c045..36fdf3ba7 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -376,7 +376,7 @@ expr_simple $$ = stripIndentation(CUR_POS, data->symbols, *$2); } | PATH { $$ = new ExprPath(absPath($1, data->basePath)); } - | HPATH { $$ = new ExprPath(getEnv("HOME", "/") + string{$1 + 1}); } + | HPATH { $$ = new ExprPath(getEnv("HOME", "") + string{$1 + 1}); } | SPATH { string path($1 + 1, strlen($1) - 2); $$ = new ExprApp(CUR_POS,