* Export the nix-env derivation name parsing and version comparison
logic through the `parseDrvName' and `compareVersions' primops. This will allow expressions to easily check whether some dependency is a specific needed version or falls in some version range. See tests/lang/eval-okay-versions.nix for examples.
This commit is contained in:
parent
b3b0b2a29e
commit
d567baabbd
9 changed files with 103 additions and 37 deletions
|
@ -12,8 +12,14 @@
|
|||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>TODO: Berkeley DB no longer needed.</para></listitem>
|
||||
|
||||
<listitem><para><command>nix-store --dump-db / --load-db</command>.</para></listitem>
|
||||
|
||||
<listitem><para>New primops:
|
||||
<varname>builtins.parseDrvName</varname> and
|
||||
<varname>builtins.compareVersions</varname>.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
|
|
@ -2,11 +2,13 @@ pkglib_LTLIBRARIES = libexpr.la
|
|||
|
||||
libexpr_la_SOURCES = \
|
||||
nixexpr.cc eval.cc primops.cc lexer-tab.cc parser-tab.cc \
|
||||
get-drvs.cc attr-path.cc expr-to-xml.cc common-opts.cc
|
||||
get-drvs.cc attr-path.cc expr-to-xml.cc common-opts.cc \
|
||||
names.cc
|
||||
|
||||
pkginclude_HEADERS = \
|
||||
nixexpr.hh eval.hh parser.hh lexer-tab.hh parser-tab.hh \
|
||||
get-drvs.hh attr-path.hh expr-to-xml.hh common-opts.hh
|
||||
get-drvs.hh attr-path.hh expr-to-xml.hh common-opts.hh \
|
||||
names.hh
|
||||
|
||||
libexpr_la_LIBADD = ../libutil/libutil.la ../libstore/libstore.la \
|
||||
../boost/format/libformat.la
|
||||
|
|
|
@ -92,25 +92,6 @@ int compareVersions(const string & v1, const string & v2)
|
|||
}
|
||||
|
||||
|
||||
static void testCompareVersions()
|
||||
{
|
||||
#define TEST(v1, v2, n) assert( \
|
||||
compareVersions(v1, v2) == n && compareVersions(v2, v1) == -n)
|
||||
TEST("1.0", "2.3", -1);
|
||||
TEST("2.1", "2.3", -1);
|
||||
TEST("2.3", "2.3", 0);
|
||||
TEST("2.5", "2.3", 1);
|
||||
TEST("3.1", "2.3", 1);
|
||||
TEST("2.3.1", "2.3", 1);
|
||||
TEST("2.3.1", "2.3a", 1);
|
||||
TEST("2.3pre1", "2.3", -1);
|
||||
TEST("2.3pre3", "2.3pre12", -1);
|
||||
TEST("2.3a", "2.3c", -1);
|
||||
TEST("2.3pre1", "2.3c", -1);
|
||||
TEST("2.3pre1", "2.3q", -1);
|
||||
}
|
||||
|
||||
|
||||
DrvNames drvNamesFromArgs(const Strings & opArgs)
|
||||
{
|
||||
DrvNames result;
|
|
@ -7,6 +7,7 @@
|
|||
#include "expr-to-xml.hh"
|
||||
#include "nixexpr-ast.hh"
|
||||
#include "parser.hh"
|
||||
#include "names.hh"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -817,7 +818,7 @@ static Expr prim_removeAttrs(EvalState & state, const ATermVector & args)
|
|||
}
|
||||
|
||||
|
||||
/* Determine whether the argument is a list. */
|
||||
/* Determine whether the argument is an attribute set. */
|
||||
static Expr prim_isAttrs(EvalState & state, const ATermVector & args)
|
||||
{
|
||||
ATermList list;
|
||||
|
@ -950,23 +951,54 @@ static Expr prim_unsafeDiscardStringContext(EvalState & state, const ATermVector
|
|||
return makeStr(s, PathSet());
|
||||
}
|
||||
|
||||
|
||||
/* Expression serialization/deserialization */
|
||||
|
||||
static Expr prim_ExprToString ( EvalState & state, const ATermVector & args)
|
||||
|
||||
static Expr prim_exprToString(EvalState & state, const ATermVector & args)
|
||||
{
|
||||
return makeStr ( atPrint ( evalExpr ( state, args [ 0 ] ) ) );
|
||||
/* !!! this disregards context */
|
||||
return makeStr(atPrint(evalExpr(state, args[0])));
|
||||
}
|
||||
|
||||
static Expr prim_StringToExpr ( EvalState & state, const ATermVector & args)
|
||||
|
||||
static Expr prim_stringToExpr(EvalState & state, const ATermVector & args)
|
||||
{
|
||||
string s;
|
||||
PathSet l;
|
||||
if (! matchStr ( evalExpr ( state, args[0] ), s, l )) {
|
||||
throw EvalError("__stringToExpr needs string argument!");
|
||||
}
|
||||
return ATreadFromString(s.c_str());
|
||||
/* !!! this can introduce arbitrary garbage terms in the
|
||||
evaluator! */;
|
||||
string s;
|
||||
PathSet l;
|
||||
if (!matchStr(evalExpr(state, args[0]), s, l))
|
||||
throw EvalError("stringToExpr needs string argument!");
|
||||
return ATreadFromString(s.c_str());
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* Versions
|
||||
*************************************************************/
|
||||
|
||||
|
||||
static Expr prim_parseDrvName(EvalState & state, const ATermVector & args)
|
||||
{
|
||||
string name = evalStringNoCtx(state, args[0]);
|
||||
DrvName parsed(name);
|
||||
ATermMap attrs(2);
|
||||
attrs.set(toATerm("name"), makeAttrRHS(makeStr(parsed.name), makeNoPos()));
|
||||
attrs.set(toATerm("version"), makeAttrRHS(makeStr(parsed.version), makeNoPos()));
|
||||
return makeAttrs(attrs);
|
||||
}
|
||||
|
||||
|
||||
static Expr prim_compareVersions(EvalState & state, const ATermVector & args)
|
||||
{
|
||||
string version1 = evalStringNoCtx(state, args[0]);
|
||||
string version2 = evalStringNoCtx(state, args[1]);
|
||||
int d = compareVersions(version1, version2);
|
||||
return makeInt(d);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* Primop registration
|
||||
*************************************************************/
|
||||
|
@ -994,8 +1026,8 @@ void EvalState::addPrimOps()
|
|||
addPrimOp("__trace", 2, prim_trace);
|
||||
|
||||
// Expr <-> String
|
||||
addPrimOp("__exprToString", 1, prim_ExprToString);
|
||||
addPrimOp("__stringToExpr", 1, prim_StringToExpr);
|
||||
addPrimOp("__exprToString", 1, prim_exprToString);
|
||||
addPrimOp("__stringToExpr", 1, prim_stringToExpr);
|
||||
|
||||
addPrimOp("relativise", 2, prim_relativise);
|
||||
|
||||
|
@ -1040,6 +1072,9 @@ void EvalState::addPrimOps()
|
|||
addPrimOp("__stringLength", 1, prim_stringLength);
|
||||
addPrimOp("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext);
|
||||
|
||||
// Versions
|
||||
addPrimOp("__parseDrvName", 1, prim_parseDrvName);
|
||||
addPrimOp("__compareVersions", 2, prim_compareVersions);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
bin_PROGRAMS = nix-env
|
||||
|
||||
nix_env_SOURCES = nix-env.cc names.cc names.hh \
|
||||
profiles.cc profiles.hh help.txt
|
||||
nix_env_SOURCES = nix-env.cc profiles.cc profiles.hh help.txt
|
||||
nix_env_LDADD = ../libmain/libmain.la ../libexpr/libexpr.la \
|
||||
../libstore/libstore.la ../libutil/libutil.la \
|
||||
../boost/format/libformat.la ${bdb_lib} ${aterm_lib}
|
||||
|
|
1
tests/lang/eval-okay-versions.exp
Normal file
1
tests/lang/eval-okay-versions.exp
Normal file
|
@ -0,0 +1 @@
|
|||
Bool(True)
|
40
tests/lang/eval-okay-versions.nix
Normal file
40
tests/lang/eval-okay-versions.nix
Normal file
|
@ -0,0 +1,40 @@
|
|||
let
|
||||
|
||||
name1 = "hello-1.0.2";
|
||||
name2 = "hello";
|
||||
name3 = "915resolution-0.5.2";
|
||||
name4 = "xf86-video-i810-1.7.4";
|
||||
|
||||
eq = 0;
|
||||
lt = builtins.sub 0 1;
|
||||
gt = 1;
|
||||
|
||||
versionTest = v1: v2: expected:
|
||||
let d1 = builtins.compareVersions v1 v2;
|
||||
d2 = builtins.compareVersions v2 v1;
|
||||
in d1 == builtins.sub 0 d2 && d1 == expected;
|
||||
|
||||
tests = [
|
||||
((builtins.parseDrvName name1).name == "hello")
|
||||
((builtins.parseDrvName name1).version == "1.0.2")
|
||||
((builtins.parseDrvName name2).name == "hello")
|
||||
((builtins.parseDrvName name2).version == "")
|
||||
((builtins.parseDrvName name3).name == "915resolution")
|
||||
((builtins.parseDrvName name3).version == "0.5.2")
|
||||
((builtins.parseDrvName name4).name == "xf86-video-i810")
|
||||
((builtins.parseDrvName name4).version == "1.7.4")
|
||||
(versionTest "1.0" "2.3" lt)
|
||||
(versionTest "2.1" "2.3" lt)
|
||||
(versionTest "2.3" "2.3" eq)
|
||||
(versionTest "2.5" "2.3" gt)
|
||||
(versionTest "3.1" "2.3" gt)
|
||||
(versionTest "2.3.1" "2.3" gt)
|
||||
(versionTest "2.3.1" "2.3a" gt)
|
||||
(versionTest "2.3pre1" "2.3" lt)
|
||||
(versionTest "2.3pre3" "2.3pre12" lt)
|
||||
(versionTest "2.3a" "2.3c" lt)
|
||||
(versionTest "2.3pre1" "2.3c" lt)
|
||||
(versionTest "2.3pre1" "2.3q" lt)
|
||||
];
|
||||
|
||||
in (import ./lib.nix).and tests
|
|
@ -10,6 +10,8 @@ rec {
|
|||
concat =
|
||||
fold (x: y: x + y) "";
|
||||
|
||||
and = fold (x: y: x && y) true;
|
||||
|
||||
flatten = x:
|
||||
if isList x
|
||||
then fold (x: y: (flatten x) ++ y) [] x
|
||||
|
|
Loading…
Reference in a new issue