forked from lix-project/lix
* 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
|
@ -12,8 +12,14 @@
|
||||||
|
|
||||||
<itemizedlist>
|
<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><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>
|
</itemizedlist>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -2,11 +2,13 @@ pkglib_LTLIBRARIES = libexpr.la
|
||||||
|
|
||||||
libexpr_la_SOURCES = \
|
libexpr_la_SOURCES = \
|
||||||
nixexpr.cc eval.cc primops.cc lexer-tab.cc parser-tab.cc \
|
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 = \
|
pkginclude_HEADERS = \
|
||||||
nixexpr.hh eval.hh parser.hh lexer-tab.hh parser-tab.hh \
|
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 \
|
libexpr_la_LIBADD = ../libutil/libutil.la ../libstore/libstore.la \
|
||||||
../boost/format/libformat.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 drvNamesFromArgs(const Strings & opArgs)
|
||||||
{
|
{
|
||||||
DrvNames result;
|
DrvNames result;
|
|
@ -7,6 +7,7 @@
|
||||||
#include "expr-to-xml.hh"
|
#include "expr-to-xml.hh"
|
||||||
#include "nixexpr-ast.hh"
|
#include "nixexpr-ast.hh"
|
||||||
#include "parser.hh"
|
#include "parser.hh"
|
||||||
|
#include "names.hh"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.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)
|
static Expr prim_isAttrs(EvalState & state, const ATermVector & args)
|
||||||
{
|
{
|
||||||
ATermList list;
|
ATermList list;
|
||||||
|
@ -950,23 +951,54 @@ static Expr prim_unsafeDiscardStringContext(EvalState & state, const ATermVector
|
||||||
return makeStr(s, PathSet());
|
return makeStr(s, PathSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Expression serialization/deserialization */
|
/* 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;
|
/* !!! this can introduce arbitrary garbage terms in the
|
||||||
PathSet l;
|
evaluator! */;
|
||||||
if (! matchStr ( evalExpr ( state, args[0] ), s, l )) {
|
string s;
|
||||||
throw EvalError("__stringToExpr needs string argument!");
|
PathSet l;
|
||||||
}
|
if (!matchStr(evalExpr(state, args[0]), s, l))
|
||||||
return ATreadFromString(s.c_str());
|
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
|
* Primop registration
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
|
@ -994,8 +1026,8 @@ void EvalState::addPrimOps()
|
||||||
addPrimOp("__trace", 2, prim_trace);
|
addPrimOp("__trace", 2, prim_trace);
|
||||||
|
|
||||||
// Expr <-> String
|
// Expr <-> String
|
||||||
addPrimOp("__exprToString", 1, prim_ExprToString);
|
addPrimOp("__exprToString", 1, prim_exprToString);
|
||||||
addPrimOp("__stringToExpr", 1, prim_StringToExpr);
|
addPrimOp("__stringToExpr", 1, prim_stringToExpr);
|
||||||
|
|
||||||
addPrimOp("relativise", 2, prim_relativise);
|
addPrimOp("relativise", 2, prim_relativise);
|
||||||
|
|
||||||
|
@ -1040,6 +1072,9 @@ void EvalState::addPrimOps()
|
||||||
addPrimOp("__stringLength", 1, prim_stringLength);
|
addPrimOp("__stringLength", 1, prim_stringLength);
|
||||||
addPrimOp("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext);
|
addPrimOp("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext);
|
||||||
|
|
||||||
|
// Versions
|
||||||
|
addPrimOp("__parseDrvName", 1, prim_parseDrvName);
|
||||||
|
addPrimOp("__compareVersions", 2, prim_compareVersions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
bin_PROGRAMS = nix-env
|
bin_PROGRAMS = nix-env
|
||||||
|
|
||||||
nix_env_SOURCES = nix-env.cc names.cc names.hh \
|
nix_env_SOURCES = nix-env.cc profiles.cc profiles.hh help.txt
|
||||||
profiles.cc profiles.hh help.txt
|
|
||||||
nix_env_LDADD = ../libmain/libmain.la ../libexpr/libexpr.la \
|
nix_env_LDADD = ../libmain/libmain.la ../libexpr/libexpr.la \
|
||||||
../libstore/libstore.la ../libutil/libutil.la \
|
../libstore/libstore.la ../libutil/libutil.la \
|
||||||
../boost/format/libformat.la ${bdb_lib} ${aterm_lib}
|
../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 =
|
concat =
|
||||||
fold (x: y: x + y) "";
|
fold (x: y: x + y) "";
|
||||||
|
|
||||||
|
and = fold (x: y: x && y) true;
|
||||||
|
|
||||||
flatten = x:
|
flatten = x:
|
||||||
if isList x
|
if isList x
|
||||||
then fold (x: y: (flatten x) ++ y) [] x
|
then fold (x: y: (flatten x) ++ y) [] x
|
||||||
|
|
Loading…
Reference in a new issue