dubmore: Support of local and remote archive dependencies
Andre Pany via Digitalmars-d-announce
digitalmars-d-announce at puremagic.com
Wed May 17 03:23:47 PDT 2017
Hi,
I want to share with you a little application I wrote. With the
following application you can add local and remote archive
dependencies to your dub configuration.
/+ dub.json:
{
"name":"test"
"dependencies":{
"sample1":{"path":"C:\\D\\projects\\test2\\sample1.zip",
"sample2":{"url":"http://localhost:8080/sample2.zip"
},
}
+/
void main() {}
Place the dubmore executable into the same folder as dub and use
dubmore instead of dub.
Remarks:
- Only json is supported
- You need to have the console application unzip in your system
path
--
module dubmore;
import std.file, std.path, std.exception, std.process, std.array,
std.json, std.net.curl, std.experimental.logger, std.algorithm,
std.getopt, std.string;
void main(string[] args)
{
globalLogLevel = LogLevel.all;
string dubFile;
scope(exit) if (exists(dubFile~".old")) rename(dubFile~".old",
dubFile);
string[] dubArgs;
string packagesFolder = buildPath(getcwd(), "packages");
if (args.canFind("--force") && exists(packagesFolder))
rmdirRecurse(packagesFolder);
if (!exists(packagesFolder)) mkdir(packagesFolder);
if (exists(buildPath(getcwd(), "dub.json")))
{
dubFile = buildPath(getcwd(), "dub.json");
dubArgs = args[1..$];
auto jsRoot = parseJSON(readText(dubFile));
if (processJson(jsRoot, packagesFolder))
{
copy(dubFile, dubFile~".old");
writeTextFile(dubFile, jsRoot.toString);
}
}
else if (args.length > 1 && buildPath(getcwd(),
args[1].stripExtension~".d").exists)
{
enum marker = "dub.json:";
dubFile = buildPath(getcwd(), args[1].stripExtension~".d");
dubArgs = dubFile~args[2..$];
string sourceCode = readText(dubFile);
auto startPos = sourceCode.indexOf("/+");
auto markerPos = sourceCode.indexOf(marker);
auto endPos = sourceCode.indexOf("+/");
if (startPos > -1 && markerPos > startPos && markerPos < endPos)
{
auto jsRoot =
parseJSON(sourceCode[markerPos+marker.length..endPos]);
if (processJson(jsRoot, packagesFolder))
{
sourceCode = sourceCode[0..markerPos+marker.length]~"
"~jsRoot.toString~" "~sourceCode[endPos..$];
copy(dubFile, dubFile~".old");
writeTextFile(dubFile, sourceCode);
}
}
}
import std.stdio: writeln;
with (execute(["dub"]~dubArgs)) writeln(output);
}
private bool processJson(JSONValue jsRoot, string packagesFolder)
{
bool found = processDependencies(jsRoot, packagesFolder);
if ("configurations" in jsRoot && jsRoot["configurations"].type
== JSON_TYPE.ARRAY)
found = jsRoot["configurations"].array.any!(jsConfig =>
processDependencies(jsConfig, packagesFolder)) || found;
return found;
}
private bool processDependencies(JSONValue js, string
packagesFolder)
{
bool result;
if ("dependencies" in js && js["dependencies"].type ==
JSON_TYPE.OBJECT)
{
foreach(key; js["dependencies"].object.keys)
{
auto dep = js["dependencies"].object[key];
if (dep.type == JSON_TYPE.OBJECT && "url" in dep &&
dep["url"].type == JSON_TYPE.STRING)
{
string url = dep["url"].str;
string fileName = url.split("/").array[$-1];
string destination = buildPath(packagesFolder, fileName);
if (exists(destination))
{
dep["path"] = buildPath(destination.dirName,
destination.stripExtension);
}
else
{
try { dep["path"] = downloadAndExtract(url, destination); }
catch(Exception e)
{
error(e.msg);
continue;
}
}
dep.object.remove("url");
result = true;
}
else if (dep.type == JSON_TYPE.OBJECT && "path" in dep &&
dep["path"].type == JSON_TYPE.STRING &&
dep["path"].str.toLower.endsWith(".zip"))
{
string filePath = dep["path"].str;
string packageFolder = buildPath(packagesFolder,
filePath.baseName.stripExtension);
if (!exists(packageFolder))
with (execute(["unzip", "-o", filePath, "-d",
packagesFolder])) enforce(status == 0, output);
dep["path"] = packageFolder;
result = true;
}
}
}
return result;
}
private string downloadAndExtract(string url, string destination)
{
info("download: ", url, " to ", destination);
download(url, destination);
enforce(destination.toLower.endsWith(".zip"), "Unknown file
extenstion");
with (execute(["unzip", destination, "-d",
destination.dirName])) enforce(status == 0, output);
return buildPath(destination.dirName,
destination.baseName!(std.path.CaseSensitive.no)(".zip"));
}
private void writeTextFile(string filePath, string content)
{
import std.stdio: File;
auto f = File(filePath, "wb");
f.write(content);
f.close();
}
--
Kind regards
André
More information about the Digitalmars-d-announce
mailing list