digitalmars.D.announce - dubmore: Support of local and remote archive dependencies
- Andre Pany (156/156) May 17 2017 Hi,
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é
May 17 2017