Merge branch 'dub'

Tested just with dmd compiler.
This commit is contained in:
Dragos Carp 2014-06-01 00:15:28 +02:00
commit f6f31bf6e6
6 changed files with 959 additions and 0 deletions

View file

@ -22,6 +22,7 @@ SET (MOD_SRCS
FindGDCPath.cmake FindGDCPath.cmake
UseDDoc.cmake UseDDoc.cmake
UseDDeps.cmake UseDDeps.cmake
UseDUB.cmake
dependencies.cmake dependencies.cmake
UseDUnittest.cmake UseDUnittest.cmake
FindPhobos.cmake FindPhobos.cmake

78
cmake-d/UseDub.cmake Normal file
View file

@ -0,0 +1,78 @@
# This modules add functions for downloading and building dub dependencies.
# This code sets the following variables and functions:
#
# DUB_DIRECTORY = the full path to Dub pacakges
#
# DubProject_Add(<dub_package> [version])
#
#============================================================================
# Copyright (c) 2014 Dragos Carp <dragos.carp@gmail.com>
#
# All rights reserved.
#
# See LICENSE for details.
#
if(NOT DUB_DIRECTORY)
set(DUB_DIRECTORY ${CMAKE_BINARY_DIR}/UseDub CACHE PATH "Dub packages directory")
endif(NOT DUB_DIRECTORY)
set(DUB_REGISTRY "http://code.dlang.org/packages")
file(MAKE_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp)
if(NOT CMAKE_D_COMPILER)
message(FATAL_ERROR "UseDub needs a D compiler or use it in a D project.")
endif(NOT CMAKE_D_COMPILER)
#compile json parsers
if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl)
find_file(DUB_GET_PACKAGE_URL_D_SRC "DubUrl.d"
PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH
PATH_SUFFIXES "UseDub")
find_file(SEMVER_SRC "semver.d"
PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH
PATH_SUFFIXES "UseDub")
get_filename_component(SEMVER_PATH ${SEMVER_SRC} PATH)
execute_process(COMMAND ${CMAKE_D_COMPILER} -I${SEMVER_PATH} ${DUB_GET_PACKAGE_URL_D_SRC} ${SEMVER_SRC}
WORKING_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp)
unset(DUB_GET_PACKAGE_URL_D_SRC CACHE)
endif(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl)
if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubToCMake)
find_file(DUB_PACKAGE_TO_CMAKE_D_SRC "DubToCMake.d"
PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH
PATH_SUFFIXES "UseDub")
execute_process(COMMAND ${CMAKE_D_COMPILER} ${DUB_PACKAGE_TO_CMAKE_D_SRC}
WORKING_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp)
unset(DUB_PACKAGE_TO_CMAKE_D_SRC CACHE)
endif(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubToCMake)
include(ExternalProject)
function(DubProject_Add name)
if(NOT EXISTS ${DUB_DIRECTORY}/${name}.json)
file(DOWNLOAD ${DUB_REGISTRY}/${name}.json ${DUB_DIRECTORY}/${name}.json)
endif(NOT EXISTS ${DUB_DIRECTORY}/${name}.json)
if(${ARGC} GREATER 1)
execute_process(COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubUrl -p ${name}.json -t ${ARGN}
WORKING_DIRECTORY ${DUB_DIRECTORY})
else(${ARGC} GREATER 1)
execute_process(COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubUrl -p ${name}.json
WORKING_DIRECTORY ${DUB_DIRECTORY})
endif(${ARGC} GREATER 1)
include(${DUB_DIRECTORY}/${name}.cmake)
ExternalProject_Add(${name}
DOWNLOAD_DIR ${DUB_DIRECTORY}/archive/${name}
SOURCE_DIR ${DUB_DIRECTORY}/source/${name}
URL ${DUB_PACKAGE_URL}
PATCH_COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubToCMake -p package.json
INSTALL_DIR ${DUB_DIRECTORY}/export
CMAKE_CACHE_ARGS
-DCMAKE_MODULE_PATH:PATH=${CMAKE_MODULE_PATH}
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
-DDUB_DIRECTORY:PATH=${DUB_DIRECTORY})
include_directories(${DUB_DIRECTORY}/source/${name}/source ${DUB_DIRECTORY}/source/${name}/src)
endfunction()

103
cmake-d/UseDub/DubToCMake.d Normal file
View file

@ -0,0 +1,103 @@
import std.file;
import std.getopt;
import std.json;
import std.stdio;
import std.string;
int main(string[] args)
{
string dubFile = "dub.json";
string cmakeFile = "CMakeLists.txt";
getopt(args,
"package|p", &dubFile,
"output|o", &cmakeFile);
if (!exists(dubFile))
{
stderr.writefln("Cannot find file: '%s'", dubFile);
return -1;
}
string json = readText(dubFile);
JSONValue root = parseJSON(json);
string target = root["targetName"].str;
string cmake = q"<
cmake_minimum_required(VERSION 2.8)
project(%1$s D)
find_file(APP_MAIN_FILE
NAMES app.d main.d %1$s/main.d %1$s/app.d
PATHS source src NO_DEFAULT_PATH)
file(GLOB_RECURSE SRC_FILES source/*.d src/*.d)
if(APP_MAIN_FILE)
list(REMOVE_ITEM SRC_FILES ${APP_MAIN_FILE})
endif(APP_MAIN_FILE)
include_directories(source src)
>".format(root["name"].str);
switch ("targetType" in root.object ? root["targetType"].str : "autodetect")
{
case "autodetect":
cmake ~= q"<
if(APP_MAIN_FILE)
add_executable(%1$s ${SRC_FILES} ${APP_MAIN_FILE})
else(APP_MAIN_FILE)
add_library(%1$s ${SRC_FILES})
endif(APP_MAIN_FILE)
>".format(target);
break;
case "none":
break;
case "executable":
cmake ~= q"<
add_executable(%s ${SRC_FILES} ${APP_MAIN_FILE})
>".format(target);
break;
case "library":
cmake ~= q"<
add_library(%s ${SRC_FILES})
>".format(target);
break;
case "sourceLibrary":
break;
case "staticLibrary":
cmake ~= q"<
add_library(%s STATIC ${SRC_FILES})
>".format(target);
break;
case "dynamicLibrary":
cmake ~= q"<
add_library(%s SHARED ${SRC_FILES})
>".format(target);
break;
default:
assert(false, "Unknown targetType");
break;
}
cmake ~= q"<
install(TARGETS %s
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
>".format(target);
if ("dependencies" in root.object)
{
cmake ~= "\ninclude(UseDub)\n";
foreach (dependency, version_; root["dependencies"].object)
{
cmake ~= "DubProject_Add(%s %s)\n".format(dependency, version_.str);
}
cmake ~= "\nadd_dependencies(%s %-(%s %))\n".format(target, root["dependencies"].object.keys);
}
std.file.write(cmakeFile, cmake);
return 0;
}

158
cmake-d/UseDub/DubUrl.d Normal file
View file

@ -0,0 +1,158 @@
import std.algorithm;
import std.array;
import std.file;
import std.getopt;
import std.json;
import std.stdio;
import std.string;
import semver;
/**
* Finds the best match of $(D range) in $(D choices) versions list.
*
* Params:
* range = Match criteria.
* choices = Versions list it is matched against.
*
* Returns:
* Best match in $(D choices) or empty string if no match is found.
*
* See_Also:
* $(WEB https://github.com/npm/npm/blob/master/doc/misc/semver.md#ranges Ranges definition)
*/
string matchVersion(string range, string[] choices)
{
foreach (ref choice; choices)
{
choice.skipOver('~');
}
if (range.skipOver('~'))
{
foreach (choice; choices)
{
if (choice.startsWith(range))
return choice;
}
return "";
}
return "";
}
unittest
{
}
int main(string[] args)
{
string registryFile = "";
string packageVersion = "";
bool listVersions;
string outputPath = ".";
getopt(args,
"package|p", &registryFile,
"tag|t", &packageVersion,
"list|l", &listVersions,
"output|o", &outputPath);
if (registryFile.empty)
{
stderr.writeln("Package registry file (<package_name>.json) need to be specified.");
return -1;
}
if (!exists(registryFile) && !registryFile.endsWith(".json"))
registryFile ~= ".json";
if (!exists(registryFile))
{
stderr.writefln("Package registry file '%s' not found.", registryFile);
return -1;
}
string json = readText(registryFile);
JSONValue node;
JSONValue root = parseJSON(json);
if (packageVersion.empty)
{
packageVersion = "*";
}
auto versionRange = SemVerRange(packageVersion);
if (!versionRange.valid)
{
// try exact string match
auto range = root["versions"].array.find!`a["version"].str == b`(packageVersion);
if (!range.empty)
{
node = range[0];
}
else
{
stderr.writefln("%s has no version tagged %s.", root["name"].str, packageVersion);
return -1;
}
}
else
{
string nodeVersionString(JSONValue node)
{
auto ver = node["version"].str;
ver.skipOver('~');
return ver;
}
auto nodes = root["versions"].array.filter!(a => SemVer(nodeVersionString(a)).valid).array;
auto maxVersion = nodes.map!(a => SemVer(nodeVersionString(a))).array.maxSatisfying(versionRange);
if (maxVersion.valid)
{
auto range = nodes.find!((a, b) => SemVer(nodeVersionString(a)) == b)(maxVersion);
assert(!range.empty);
node = range[0];
}
else
{
stderr.writefln("%s has no version %s.", root["name"].str, versionRange);
return -1;
}
}
if (registryFile.endsWith(".json"))
{
registryFile = registryFile[0..$-5];
}
if (listVersions)
{
writefln("Package '%s'", registryFile);
foreach(n; root["versions"].array)
{
writefln(" %s => %s", n["version"].str, n["downloadUrl"].str);
}
}
packageVersion = node["version"].str;
auto packageUrl = node["downloadUrl"].str;
auto packageName = root["name"].str;
if (!outputPath.isDir)
{
stderr.writefln("Output path '%s' need to be a directory.", outputPath);
return -1;
}
string output = "set(DUB_PACKAGE_NAME, \"%s\")\n".format(packageName) ~
"set(DUB_PACKAGE_VERSION \"%s\")\n".format(packageVersion) ~
"set(DUB_PACKAGE_URL \"%s\")\n".format(packageUrl);
std.file.write(outputPath ~ "/" ~ packageName ~ ".cmake", output);
return 0;
}

612
cmake-d/UseDub/semver.d Normal file
View file

@ -0,0 +1,612 @@
import std.algorithm;
import std.array;
import std.conv;
import std.range;
import std.regex;
import std.stdio;
import std.string;
enum ReleaseType
{
MAJOR,
MINOR,
PATCH,
PRERELEASE,
};
struct SemVer
{
uint[3] ids;
string[] prerelease;
string[] build;
bool isValid;
@disable this();
this(string semVer)
{
isValid = false;
if (semVer.empty)
return;
if (!semVer.skipOver('v'))
semVer.skipOver('=');
auto re = regex(`^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([a-zA-Z\d-.]+))?(?:\+([a-zA-Z\d-.]+))?$`);
auto m = semVer.matchAll(re);
if (m.empty)
return;
foreach (i, ref id; ids)
{
if (!m.captures[i+1].empty)
id = m.captures[i+1].to!uint;
}
if (!m.captures[4].empty)
{
prerelease = m.captures[4].splitter('.').array;
if (prerelease.any!empty)
return;
}
if (!m.captures[5].empty)
{
build = m.captures[5].splitter('.').array;
if (build.any!empty)
return;
}
isValid = true;
}
string toString() const
{
if (!isValid)
return "<invalid_semver>";
string semVer = "%(%s.%)".format(ids);
if (!prerelease.empty)
semVer ~= "-" ~ "%-(%s.%)".format(prerelease);
if (!build.empty)
semVer ~= "+" ~ "%-(%s.%)".format(build);
return semVer;
}
@property bool valid() const
{
return isValid;
}
SemVer inc(ReleaseType releaseType) const
in
{
assert(this.valid);
}
out(result)
{
assert(result.valid);
}
body
{
SemVer result = "0";
foreach (i; 0..releaseType)
result.ids[i] = this.ids[i];
if (releaseType != ReleaseType.PRERELEASE)
result.ids[releaseType] = this.ids[releaseType]+1;
return result;
}
SemVer appendPrerelease0()
{
if (prerelease.empty)
prerelease ~= "0";
return this;
}
unittest
{
assert(SemVer("1.2.3").inc(ReleaseType.MAJOR) == SemVer("2.0.0"));
assert(SemVer("1.2.3").inc(ReleaseType.MINOR) == SemVer("1.3.0"));
assert(SemVer("1.2.3-alpha").inc(ReleaseType.MINOR) == SemVer("1.3.0"));
assert(SemVer("1.2.3").inc(ReleaseType.PATCH) == SemVer("1.2.4"));
assert(SemVer("1.2.3-alpha").inc(ReleaseType.PATCH) == SemVer("1.2.4"));
assert(SemVer("1.2.3").inc(ReleaseType.PRERELEASE) == SemVer("1.2.3"));
assert(SemVer("1.2.3-alpha").inc(ReleaseType.PRERELEASE) == SemVer("1.2.3"));
}
int opCmp(ref const SemVer v) const
in
{
assert(this.valid);
assert(v.valid);
}
body
{
foreach (i; 0..ids.length)
{
if (ids[i] != v.ids[i])
return ids[i] < v.ids[i] ? -1 : 1;
}
if (!prerelease.empty && v.prerelease.empty)
return -1;
if (prerelease.empty && !v.prerelease.empty)
return 1;
foreach (a, b; lockstep(prerelease, v.prerelease))
{
if (a.isNumeric && b.isNumeric)
{
if (a.to!uint != b.to!uint)
return a.to!uint < b.to!uint ? -1 : 1;
else
continue;
}
if (a != b)
return a < b ? -1 : 1;
}
if (prerelease.length != v.prerelease.length)
return prerelease.length < v.prerelease.length ? -1 : 1;
return 0;
}
int opCmp(const SemVer v) const
{
return this.opCmp(v);
}
bool opEquals(ref const SemVer v) const
{
return this.opCmp(v) == 0;
}
bool opEquals(const SemVer v) const
{
return this.opEquals(v);
}
}
unittest
{
assert(!SemVer("1.2-.alpha.32").valid);
assert(!SemVer("1.2-alpha+").valid);
assert(!SemVer("1.2-alpha_").valid);
assert(!SemVer("1.2+32.").valid);
assert(!SemVer("1.2.5.6").valid);
assert(!SemVer("").valid);
assert(SemVer("1.0.0-alpha") < SemVer("1.0.0-alpha.1"));
assert(SemVer("1.0.0-alpha.1") < SemVer("1.0.0-alpha.beta"));
assert(SemVer("1.0.0-alpha.beta") < SemVer("1.0.0-beta"));
assert(SemVer("1.0.0-beta") < SemVer("1.0.0-beta.2"));
assert(SemVer("1.0.0-beta.2") < SemVer("1.0.0-beta.11"));
assert(SemVer("1.0.0-beta.11") < SemVer("1.0.0-rc.1"));
assert(SemVer("1.0.0-rc.1") < SemVer("1.0.0"));
assert(SemVer("1.0.0-rc.1") == SemVer("1.0.0-rc.1+build.5"));
}
struct SemVerRange
{
struct SimpleRange
{
string op;
SemVer semVer;
string toString() const
{
return op ~ semVer.toString;
}
}
SimpleRange[][] ranges;
invariant()
{
assert(ranges.all!(r => r.all!(r => ["<", "<=", "=", ">=", ">"].canFind(r.op))));
}
bool isValid;
@disable this();
this(string semVerRange)
{
isValid = false;
auto re = regex(`(~|~>|\^|<|<=|=|>=|>)?[v]?(\d+|\*|X|x)(?:\.(\d+|\*|X|x))?(?:\.(\d+|\*|X|x))?([\S]*)`);
ranges = [SimpleRange[].init];
while (!semVerRange.stripLeft.empty)
{
auto m = semVerRange.matchFirst(re);
if (m.empty)
return;
auto operator = m.captures[1];
auto wildcard = wildcardAt([m.captures[2], m.captures[3], m.captures[4]]);
auto expanded = expand([m.captures[2], m.captures[3], m.captures[4], m.captures[5]]);
if (expanded.empty)
return;
auto semVer = SemVer(expanded);
if (!semVer.valid)
return;
switch (m.captures.pre.strip)
{
case "":
break;
case "-":
if (ranges[$-1].empty || ranges[$-1][$-1].op != "=" ||
operator != "" || wildcard != ReleaseType.PRERELEASE)
return;
ranges[$-1][$-1].op = ">=";
operator = "<=";
break;
case "||":
ranges ~= SimpleRange[].init;
break;
default:
return;
}
switch (operator)
{
case "":
case "=":
final switch (wildcard)
{
case ReleaseType.MAJOR:
assert(semVer == SemVer("0.0.0"));
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
break;
case ReleaseType.MINOR:
case ReleaseType.PATCH:
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
ranges[$-1] ~= SimpleRange("<", semVer.inc(--wildcard).appendPrerelease0);
break;
case ReleaseType.PRERELEASE:
ranges[$-1] ~= SimpleRange("=", semVer);
break;
}
break;
case "<":
ranges[$-1] ~= SimpleRange(operator, semVer.appendPrerelease0);
break;
case "<=":
case ">=":
case ">":
if (wildcard < ReleaseType.PRERELEASE)
semVer.appendPrerelease0;
ranges[$-1] ~= SimpleRange(operator, semVer);
break;
case "~":
final switch (wildcard)
{
case ReleaseType.MAJOR:
return;
case ReleaseType.MINOR:
case ReleaseType.PATCH:
--wildcard;
break;
case ReleaseType.PRERELEASE:
--wildcard;
--wildcard;
break;
}
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
ranges[$-1] ~= SimpleRange("<", semVer.inc(wildcard).appendPrerelease0);
break;
case "~>":
final switch (wildcard)
{
case ReleaseType.MAJOR:
return;
case ReleaseType.MINOR:
--wildcard;
break;
case ReleaseType.PATCH:
case ReleaseType.PRERELEASE:
--wildcard;
--wildcard;
break;
}
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
ranges[$-1] ~= SimpleRange("<", semVer.inc(wildcard).appendPrerelease0);
break;
case "^":
if (wildcard == ReleaseType.MAJOR || !semVer.prerelease.empty)
return;
if (semVer.ids[ReleaseType.MAJOR] != 0)
{
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
ranges[$-1] ~= SimpleRange("<", semVer.inc(ReleaseType.MAJOR).appendPrerelease0);
}
else if (semVer.ids[ReleaseType.MINOR] != 0)
{
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
ranges[$-1] ~= SimpleRange("<", semVer.inc(ReleaseType.MINOR).appendPrerelease0);
}
else
{
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
ranges[$-1] ~= SimpleRange("<", semVer.inc(ReleaseType.PATCH).appendPrerelease0);
}
break;
default:
assert(0);
break;
}
semVerRange = m.captures.post;
}
isValid = true;
}
private static ReleaseType wildcardAt(string[3] semVer)
{
foreach (i; ReleaseType.MAJOR..ReleaseType.PRERELEASE)
{
if (["", "*", "X", "x"].canFind(semVer[i]))
return i;
}
return ReleaseType.PRERELEASE;
}
unittest
{
assert(wildcardAt(["*", "", ""]) == ReleaseType.MAJOR);
assert(wildcardAt(["X", "", ""]) == ReleaseType.MAJOR);
assert(wildcardAt(["1", "", ""]) == ReleaseType.MINOR);
assert(wildcardAt(["1", "x", ""]) == ReleaseType.MINOR);
assert(wildcardAt(["1", "2", ""]) == ReleaseType.PATCH);
assert(wildcardAt(["1", "2", "x"]) == ReleaseType.PATCH);
assert(wildcardAt(["1", "2", "3"]) == ReleaseType.PRERELEASE);
}
private static string expand(string[4] semVer)
{
ReleaseType wildcard = wildcardAt(semVer[0..3]);
if (wildcard != ReleaseType.PRERELEASE)
{
if (semVer[wildcard+1..$].any!`!["", "*", "X", "x"].canFind(a)`)
return "";
foreach (j; wildcard..ReleaseType.PRERELEASE)
semVer[j] = "0";
}
string result = "%-(%s.%)".format(semVer[0..3]);
if (!semVer[3].empty)
result ~= semVer[3];
return result;
}
unittest
{
assert(expand(["*", "", "", ""]) == "0.0.0");
assert(expand(["X", "", "", ""]) == "0.0.0");
assert(expand(["1", "2", "3", ""]) == "1.2.3");
assert(expand(["1", "2", "3", "-abc"]) == "1.2.3-abc");
assert(expand(["1", "2", "", ""]) == "1.2.0");
assert(expand(["1", "2", "", "-abc"]) == "");
assert(expand(["1", "2", "x", ""]) == "1.2.0");
assert(expand(["1", "", "", ""]) == "1.0.0");
assert(expand(["1", "x", "", ""]) == "1.0.0");
}
string toString() const
{
if (!isValid)
return "<invalid_semver_range>";
return "%(%(%s %) || %)".format(ranges);
}
@property bool valid() const
{
return isValid;
}
private static bool simpleRangeSatisfiedBy(SimpleRange simpleRange, SemVer semVer)
in
{
assert(semVer.valid);
assert(["<", "<=", "=", ">=", ">"].canFind(simpleRange.op));
assert(simpleRange.semVer.valid);
}
body
{
switch (simpleRange.op)
{
case "<":
return semVer < simpleRange.semVer;
case "<=":
return semVer <= simpleRange.semVer;
case "=":
return semVer == simpleRange.semVer;
case ">=":
return semVer >= simpleRange.semVer;
case ">":
return semVer > simpleRange.semVer;
default:
return false;
}
}
bool satisfiedBy(SemVer semVer)
in
{
assert(semVer.valid);
assert(valid);
}
body
{
return ranges.any!(r => r.all!(s => simpleRangeSatisfiedBy(s, semVer)));
}
}
bool satisfies(SemVer semVer, SemVerRange semVerRange)
{
return semVerRange.satisfiedBy(semVer);
}
SemVer maxSatisfying(SemVer[] semVers, SemVerRange semVerRange)
in
{
assert(semVers.all!"a.valid");
assert(semVerRange.valid);
}
body
{
auto found = semVers.sort!"a > b".find!(a => satisfies(a, semVerRange));
return found.empty ? SemVer("invalid") : found[0];
}
unittest
{
assert(SemVerRange("1.x || >=2.5.0 || 5.0.0 - 7.2.3").valid);
assert(!SemVerRange("blerg").valid);
assert(!SemVerRange("git+https://user:password0123@github.com/foo").valid);
assert(SemVer("1.2.3").satisfies(SemVerRange("1.x || >=2.5.0 || 5.0.0 - 7.2.3")));
assert(SemVer("1.2.3").satisfies(SemVerRange("1.0.0 - 2.0.0")));
assert(SemVer("1.0.0").satisfies(SemVerRange("1.0.0")));
assert(SemVer("0.2.4").satisfies(SemVerRange(">=*")));
assert(SemVer("1.2.3").satisfies(SemVerRange("*")));
assert(SemVer("v1.2.3-foo").satisfies(SemVerRange("*")));
assert(SemVer("1.0.0").satisfies(SemVerRange(">=1.0.0")));
assert(SemVer("1.0.1").satisfies(SemVerRange(">=1.0.0")));
assert(SemVer("1.1.0").satisfies(SemVerRange(">=1.0.0")));
assert(SemVer("1.0.1").satisfies(SemVerRange(">1.0.0")));
assert(SemVer("1.1.0").satisfies(SemVerRange(">1.0.0")));
assert(SemVer("2.0.0").satisfies(SemVerRange("<=2.0.0")));
assert(SemVer("1.9999.9999").satisfies(SemVerRange("<=2.0.0")));
assert(SemVer("0.2.9").satisfies(SemVerRange("<=2.0.0")));
assert(SemVer("1.9999.9999").satisfies(SemVerRange("<2.0.0")));
assert(SemVer("0.2.9").satisfies(SemVerRange("<2.0.0")));
assert(SemVer("1.0.0").satisfies(SemVerRange(">=1.0.0")));
assert(SemVer("1.0.1").satisfies(SemVerRange(">=1.0.0")));
assert(SemVer("1.1.0").satisfies(SemVerRange(">=1.0.0")));
assert(SemVer("1.0.1").satisfies(SemVerRange(">1.0.0")));
assert(SemVer("1.1.0").satisfies(SemVerRange(">1.0.0")));
assert(SemVer("2.0.0").satisfies(SemVerRange("<=2.0.0")));
assert(SemVer("1.9999.9999").satisfies(SemVerRange("<=2.0.0")));
assert(SemVer("0.2.9").satisfies(SemVerRange("<=2.0.0")));
assert(SemVer("1.9999.9999").satisfies(SemVerRange("<2.0.0")));
assert(SemVer("0.2.9").satisfies(SemVerRange("<2.0.0")));
assert(SemVer("v0.1.97").satisfies(SemVerRange(">=0.1.97")));
assert(SemVer("0.1.97").satisfies(SemVerRange(">=0.1.97")));
assert(SemVer("1.2.4").satisfies(SemVerRange("0.1.20 || 1.2.4")));
assert(SemVer("0.0.0").satisfies(SemVerRange(">=0.2.3 || <0.0.1")));
assert(SemVer("0.2.3").satisfies(SemVerRange(">=0.2.3 || <0.0.1")));
assert(SemVer("0.2.4").satisfies(SemVerRange(">=0.2.3 || <0.0.1")));
assert(SemVer("2.1.3").satisfies(SemVerRange("2.x.x")));
assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.x")));
assert(SemVer("2.1.3").satisfies(SemVerRange("1.2.x || 2.x")));
assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.x || 2.x")));
assert(SemVer("1.2.3").satisfies(SemVerRange("x")));
assert(SemVer("2.1.3").satisfies(SemVerRange("2.*.*")));
assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.*")));
assert(SemVer("2.1.3").satisfies(SemVerRange("1.2.* || 2.*")));
assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.* || 2.*")));
assert(SemVer("1.2.3").satisfies(SemVerRange("*")));
assert(SemVer("2.1.2").satisfies(SemVerRange("2")));
assert(SemVer("2.3.1").satisfies(SemVerRange("2.3")));
assert(SemVer("2.4.0").satisfies(SemVerRange("~2.4")));
assert(SemVer("2.4.5").satisfies(SemVerRange("~2.4")));
assert(SemVer("3.2.2").satisfies(SemVerRange("~>3.2.1")));
assert(SemVer("1.2.3").satisfies(SemVerRange("~1")));
assert(SemVer("1.2.3").satisfies(SemVerRange("~>1")));
assert(SemVer("1.0.2").satisfies(SemVerRange("~1.0")));
assert(SemVer("1.0.12").satisfies(SemVerRange("~1.0.3")));
assert(SemVer("1.0.0").satisfies(SemVerRange(">=1")));
assert(SemVer("1.1.1").satisfies(SemVerRange("<1.2")));
assert(SemVer("1.1.9").satisfies(SemVerRange("<=1.2")));
assert(SemVer("1.0.0-bet").satisfies(SemVerRange("1")));
assert(SemVer("0.5.5").satisfies(SemVerRange("~v0.5.4-pre")));
assert(SemVer("0.5.4").satisfies(SemVerRange("~v0.5.4-pre")));
assert(SemVer("0.7.2").satisfies(SemVerRange("=0.7.x")));
assert(SemVer("0.7.2").satisfies(SemVerRange(">=0.7.x")));
assert(SemVer("0.7.0-asdf").satisfies(SemVerRange("=0.7.x")));
assert(SemVer("0.7.0-asdf").satisfies(SemVerRange(">=0.7.x")));
assert(SemVer("0.6.2").satisfies(SemVerRange("<=0.7.x")));
assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 >=1.2.3")));
assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 =1.2.3")));
assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 1.2.3")));
assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 >=1.2.3 1.2.3")));
assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 1.2.3 >=1.2.3")));
assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 1.2.3")));
assert(SemVer("1.2.3").satisfies(SemVerRange(">=1.2.1 1.2.3")));
assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.3 >=1.2.1")));
assert(SemVer("1.2.3").satisfies(SemVerRange(">=1.2.3 >=1.2.1")));
assert(SemVer("1.2.3").satisfies(SemVerRange(">=1.2.1 >=1.2.3")));
assert(SemVer("1.2.3-beta").satisfies(SemVerRange("<=1.2.3")));
assert(SemVer("1.3.0-beta").satisfies(SemVerRange(">1.2")));
assert(SemVer("1.2.8").satisfies(SemVerRange(">=1.2")));
assert(SemVer("1.8.1").satisfies(SemVerRange("^1.2.3")));
assert(SemVer("1.2.3-beta").satisfies(SemVerRange("^1.2.3")));
assert(SemVer("0.1.2").satisfies(SemVerRange("^0.1.2")));
assert(SemVer("0.1.2").satisfies(SemVerRange("^0.1")));
assert(SemVer("1.4.2").satisfies(SemVerRange("^1.2")));
assert(SemVer("1.4.2").satisfies(SemVerRange("^1.2 ^1")));
assert(SemVer("1.2.0-pre").satisfies(SemVerRange("^1.2")));
assert(SemVer("1.2.3-pre").satisfies(SemVerRange("^1.2.3")));
assert(!SemVer("2.2.3").satisfies(SemVerRange("1.0.0 - 2.0.0")));
assert(!SemVer("1.0.1").satisfies(SemVerRange("1.0.0")));
assert(!SemVer("0.0.0").satisfies(SemVerRange(">=1.0.0")));
assert(!SemVer("0.0.1").satisfies(SemVerRange(">=1.0.0")));
assert(!SemVer("0.1.0").satisfies(SemVerRange(">=1.0.0")));
assert(!SemVer("0.0.1").satisfies(SemVerRange(">1.0.0")));
assert(!SemVer("0.1.0").satisfies(SemVerRange(">1.0.0")));
assert(!SemVer("3.0.0").satisfies(SemVerRange("<=2.0.0")));
assert(!SemVer("2.9999.9999").satisfies(SemVerRange("<=2.0.0")));
assert(!SemVer("2.2.9").satisfies(SemVerRange("<=2.0.0")));
assert(!SemVer("2.9999.9999").satisfies(SemVerRange("<2.0.0")));
assert(!SemVer("2.2.9").satisfies(SemVerRange("<2.0.0")));
assert(!SemVer("v0.1.93").satisfies(SemVerRange(">=0.1.97")));
assert(!SemVer("0.1.93").satisfies(SemVerRange(">=0.1.97")));
assert(!SemVer("1.2.3").satisfies(SemVerRange("0.1.20 || 1.2.4")));
assert(!SemVer("0.0.3").satisfies(SemVerRange(">=0.2.3 || <0.0.1")));
assert(!SemVer("0.2.2").satisfies(SemVerRange(">=0.2.3 || <0.0.1")));
assert(!SemVer("1.1.3").satisfies(SemVerRange("2.x.x")));
assert(!SemVer("3.1.3").satisfies(SemVerRange("2.x.x")));
assert(!SemVer("1.3.3").satisfies(SemVerRange("1.2.x")));
assert(!SemVer("3.1.3").satisfies(SemVerRange("1.2.x || 2.x")));
assert(!SemVer("1.1.3").satisfies(SemVerRange("1.2.x || 2.x")));
assert(!SemVer("1.1.3").satisfies(SemVerRange("2.*.*")));
assert(!SemVer("3.1.3").satisfies(SemVerRange("2.*.*")));
assert(!SemVer("1.3.3").satisfies(SemVerRange("1.2.*")));
assert(!SemVer("3.1.3").satisfies(SemVerRange("1.2.* || 2.*")));
assert(!SemVer("1.1.3").satisfies(SemVerRange("1.2.* || 2.*")));
assert(!SemVer("1.1.2").satisfies(SemVerRange("2")));
assert(!SemVer("2.4.1").satisfies(SemVerRange("2.3")));
assert(!SemVer("2.5.0").satisfies(SemVerRange("~2.4")));
assert(!SemVer("2.3.9").satisfies(SemVerRange("~2.4")));
assert(!SemVer("3.3.2").satisfies(SemVerRange("~>3.2.1")));
assert(!SemVer("3.2.0").satisfies(SemVerRange("~>3.2.1")));
assert(!SemVer("0.2.3").satisfies(SemVerRange("~1")));
assert(!SemVer("2.2.3").satisfies(SemVerRange("~>1")));
assert(!SemVer("1.1.0").satisfies(SemVerRange("~1.0")));
assert(!SemVer("1.0.0").satisfies(SemVerRange("<1")));
assert(!SemVer("1.1.1").satisfies(SemVerRange(">=1.2")));
assert(!SemVer("1.3.0").satisfies(SemVerRange("<=1.2")));
assert(!SemVer("2.0.0-beta").satisfies(SemVerRange("1")));
assert(!SemVer("0.5.4-alpha").satisfies(SemVerRange("~v0.5.4-beta")));
assert(!SemVer("1.0.0-beta").satisfies(SemVerRange("<1")));
assert(!SemVer("0.8.2").satisfies(SemVerRange("=0.7.x")));
assert(!SemVer("0.6.2").satisfies(SemVerRange(">=0.7.x")));
assert(!SemVer("0.7.2").satisfies(SemVerRange("<=0.7.x")));
assert(!SemVer("1.2.3-beta").satisfies(SemVerRange("<1.2.3")));
assert(!SemVer("1.2.3-beta").satisfies(SemVerRange("=1.2.3")));
assert(!SemVer("1.2.8").satisfies(SemVerRange(">1.3")));
assert(!SemVer("2.0.0-alpha").satisfies(SemVerRange("^1.2.3")));
assert(!SemVer("1.2.2").satisfies(SemVerRange("^1.2.3")));
assert(!SemVer("1.1.9").satisfies(SemVerRange("^1.2")));
assert(!SemVer("2.0.0-pre").satisfies(SemVerRange("^1.2.3")));
auto semVers = [SemVer("0.8.0"), SemVer("1.0.0"), SemVer("1.1.0")];
assert(semVers.maxSatisfying(SemVerRange("<=1.0.0")) == SemVer("1.0.0"));
assert(semVers.maxSatisfying(SemVerRange(">=1.0")) == SemVer("1.1.0"));
}

7
tests/dub/CMakeLists.txt Normal file
View file

@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 2.8)
project(DubTest D)
include(UseDub)
DubProject_Add(derelict-sdl2 ~2.0.0)