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é

Reply via email to