* 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:
Eelco Dolstra 2008-07-01 10:10:32 +00:00
parent b3b0b2a29e
commit d567baabbd
9 changed files with 103 additions and 37 deletions

View file

@ -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>

View file

@ -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

View file

@ -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;

View file

@ -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)
{ {
/* !!! this disregards context */
return makeStr(atPrint(evalExpr(state, args[0]))); 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)
{ {
/* !!! this can introduce arbitrary garbage terms in the
evaluator! */;
string s; string s;
PathSet l; PathSet l;
if (! matchStr ( evalExpr ( state, args[0] ), s, l )) { if (!matchStr(evalExpr(state, args[0]), s, l))
throw EvalError("__stringToExpr needs string argument!"); throw EvalError("stringToExpr needs string argument!");
}
return ATreadFromString(s.c_str()); 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);
} }

View file

@ -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}

View file

@ -0,0 +1 @@
Bool(True)

View 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

View file

@ -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