Open-USB-Extreme/cmake/cmake-d/UseDub/DubUrl.d

159 lines
3.8 KiB
D

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