Skip to content

Instantly share code, notes, and snippets.

@rikkimax
Last active February 23, 2017 13:19
Show Gist options
  • Save rikkimax/4718740223748256d94b3b1474525012 to your computer and use it in GitHub Desktop.
Save rikkimax/4718740223748256d94b3b1474525012 to your computer and use it in GitHub Desktop.
import std.stdio : writeln;
import std.file : write;
void main() {
import std.file : chdir, tempDir, remove, rmdirRecurse, isDir, mkdirRecurse, exists;
import std.process : thisProcessID;
import std.path : buildPath;
import std.conv : text;
chdir("testbed");
string processTempDir = buildPath(tempDir(), thisProcessID().text);
if (exists(processTempDir)) {
if (isDir(processTempDir))
rmdirRecurse(processTempDir);
else
remove(processTempDir);
}
mkdirRecurse(processTempDir);
import schemes;
import known;
KnownSchemes knownSchemes = KnownSchemes.get;
SchemeVars vars;
vars.workingDirectory = processTempDir;
/+writeln(cast(string)knownSchemes.Git_Github.getFile("rikkimax", "csuf", "HEAD", "dub.json"));
writeln(cast(string)knownSchemes.Git_Repo_or_cz.getFile(null, "iv.d", "HEAD", "timer.d"));
writeln(cast(string)knownSchemes.Mecurial_BitBucket.getFile("alphaglosined", "libglosined", "default", "libglosined.dproj"));
writeln(cast(string)knownSchemes.Svn_SourceForge.getFile(null, "tortoisesvn", "version-1.5.0", "build.txt", vars));+/
/+write("csuf-head.zip", knownSchemes.Git_Github.getArchive("rikkimax", "csuf", "HEAD", vars));
write("iv.d-head.zip", knownSchemes.Git_Repo_or_cz.getArchive(null, "iv.d", "HEAD", vars));
write("libglosined-head.zip", knownSchemes.Mecurial_BitBucket.getArchive("alphaglosined", "libglosined", "default", vars));
write("tortoisesvn-version-1.5.0.zip", knownSchemes.Svn_SourceForge.getArchive(null, "tortoisesvn", "version-1.5.0", vars));+/
/+writeln(knownSchemes.Git_Github.getTags("rikkimax", "csuf"),
knownSchemes.Git_Github.getBranches("rikkimax", "csuf"));
writeln(knownSchemes.Git_Repo_or_cz.getTags(null, "iv.d"),
knownSchemes.Git_Repo_or_cz.getBranches(null, "iv.d"));
writeln(knownSchemes.Mecurial_BitBucket.getTags("alphaglosined", "libglosined"),
knownSchemes.Mecurial_BitBucket.getBranches("alphaglosined", "libglosined"));
writeln(knownSchemes.Svn_SourceForge.getTags(null, "tortoisesvn"),
knownSchemes.Svn_SourceForge.getBranches(null, "tortoisesvn"));+/
}
module known;
import schemes;
__gshared {
string executable_git = `c:/cygwin/bin/git`;
string executable_svn = `svn`;
string executable_mercurial = `mercurial`;
string executable_mercurial_python = `c:/cygwin/bin/python2.7`;
string executable_7z = `c:/Program Files/7-Zip/7z`;
}
struct KnownSchemes {
static KnownSchemes get() {
KnownSchemes ret;
// generic
ret.Git_WithUser = Scheme("git", "generic", "",
SchemePerform.forComplex([
SchemePerformComplex.forExecute(executable_git, ["clone", "--depth=1", "--recursive", "--single-branch", "--bare",
"-b", "~%ID%", "%URL%/", "~%USERNAME%/", "~%REPOSITORY%", "~.git",
"%WORKINGDIR%/", "~%USERNAME%", "~_", "~%REPOSITORY%", "~_", "~%ID%", "~.git"]),
SchemePerformComplex.forExecute(executable_git, ["--no-pager", "--git-dir",
"%WORKINGDIR%/", "~%USERNAME%", "~_", "~%REPOSITORY%", "~_", "~%ID%", "~.git",
"show", "%ID%", "~:", "~%FILENAME%"])
]),
SchemePerform.forComplex([
SchemePerformComplex.forExecute(executable_git, ["clone", "--depth=1", "--recursive", "--single-branch",
"-b", "~%ID%", "%URL%/", "~%USERNAME%/", "~%REPOSITORY%", "~.git",
"%WORKINGDIR%/", "~%USERNAME%", "~_", "~%REPOSITORY%", "~_", "~%ID%"]),
SchemePerformComplex.forExecute(executable_7z, ["u", "-r", "output.zip",
"%WORKINGDIR%/", "~%USERNAME%", "~_", "~%REPOSITORY%", "~_", "~%ID%", "~/."]),
SchemePerformComplex.forReadFile("output.zip")
]),
SchemePerform.forComplex(
[SchemePerformComplex.forExecute(executable_git, ["ls-remote", "-tq", "%URL%/", "~%USERNAME%/", "~%REPOSITORY%", "~.git"], null)]),
SchemeView(true, false, '\t', [1, 0]),
SchemePerform.forComplex(
[SchemePerformComplex.forExecute(executable_git, ["ls-remote", "-hq", "%URL%/", "~%USERNAME%/", "~%REPOSITORY%", "~.git"], null)]),
SchemeView(true, false, '\t', [1, 0])
);
ret.Git_WithoutUser = Scheme("git", "generic", "",
SchemePerform.forComplex([
SchemePerformComplex.forExecute(executable_git, ["clone", "--depth=1", "--recursive", "--single-branch", "--bare",
"-b", "~%ID%", "%URL%/", "~%REPOSITORY%", "~.git",
"%WORKINGDIR%/", "~%USERNAME%", "~_", "~%REPOSITORY%", "~_", "~%ID%", "~.git"]),
SchemePerformComplex.forExecute(executable_git, ["--no-pager", "--git-dir",
"%WORKINGDIR%/", "~%USERNAME%", "~_", "~%REPOSITORY%", "~_", "~%ID%", "~.git",
"show", "%ID%", "~:", "~%FILENAME%"])
]),
SchemePerform.forComplex([
SchemePerformComplex.forExecute(executable_git, ["clone", "--depth=1", "--recursive", "--single-branch",
"-b", "~%ID%", "%URL%/", "~%REPOSITORY%", "~.git",
"%WORKINGDIR%/", "~%USERNAME%", "~_", "~%REPOSITORY%", "~_", "~%ID%"]),
SchemePerformComplex.forExecute(executable_7z, ["u", "-r", "output.zip",
"%WORKINGDIR%/", "~%USERNAME%", "~_", "~%REPOSITORY%", "~_", "~%ID%", "~/."]),
SchemePerformComplex.forReadFile("output.zip")
]),
SchemePerform.forComplex(
[SchemePerformComplex.forExecute(executable_git, ["ls-remote", "-tq", "%URL%/", "~%REPOSITORY%", "~.git"], null)]),
SchemeView(true, false, '\t', [1, 0]),
SchemePerform.forComplex(
[SchemePerformComplex.forExecute(executable_git, ["ls-remote", "-hq", "%URL%/", "~%REPOSITORY%", "~.git"], null)]),
SchemeView(true, false, '\t', [1, 0])
);
ret.Svn = Scheme("svn", "generic", "",
SchemePerform.forComplex(
[
SchemePerformComplex.forConditional(
SchemePerformComplex.forExecute("svn",
["cat", "%URL%/", "~%REPOSITORY%/", "~code/tags/", "~%ID%/", "~%FILENAME%"]),
SchemePerformComplex.forExecute("svn",
["cat", "%URL%/", "~%REPOSITORY%/", "~code/branches/", "~%ID%/", "~%FILENAME%"]),
SchemePerformComplex.forExecute("svn",
["cat", "%URL%/", "~%REPOSITORY%/", "~code/trunk/", "~%FILENAME%"]))
]),
SchemePerform.forComplex(
[
SchemePerformComplex.forConditional(
SchemePerformComplex.forExecute(executable_svn,
["export", "%URL%/", "~%REPOSITORY%/", "~code/tags/", "~%ID%",
"%WORKINGDIR%/", "~%USERNAME%", "~_", "~%REPOSITORY%", "~_", "~%ID%"]),
SchemePerformComplex.forExecute(executable_svn,
["export", "%URL%/", "~%REPOSITORY%/", "~code/branches/", "~%ID%",
"%WORKINGDIR%/", "~%USERNAME%", "~_", "~%REPOSITORY%", "~_", "~%ID%"]),
SchemePerformComplex.forExecute(executable_svn,
["export", "%URL%/", "~%REPOSITORY%/", "~code/trunk",
"%WORKINGDIR%/", "~%USERNAME%", "~_", "~%REPOSITORY%", "~_", "~%ID%"])),
SchemePerformComplex.forExecute(executable_7z, ["u", "-r", "output.zip",
"%WORKINGDIR%/", "~%USERNAME%", "~_", "~%REPOSITORY%", "~_", "~%ID%", "~/."]),
SchemePerformComplex.forReadFile("output.zip")
]),
SchemePerform.forComplex(
[SchemePerformComplex.forExecute(executable_svn, ["ls", "%URL%/", "~%REPOSITORY%/", "~code/tags/"])]),
SchemeView(),
SchemePerform.forComplex(
[SchemePerformComplex.forExecute(executable_svn, ["ls", "%URL%/", "~%REPOSITORY%/", "~code/branches/"])]),
SchemeView(),
);
// ret.Mercurial_WithoutUser = ...
ret.Mercurial_WithUser = Scheme("mercurial", "generic", "",
SchemePerform(),
SchemePerform(),
SchemePerform.forComplex(
[SchemePerformComplex.forWriteFile("tmp.py", [`
from mercurial import ui, hg, node
from sys import argv
peer = hg.peer(ui.ui(), {}, argv[1])
for name, rev in peer.branchmap().items():
print ":>", name, node.short(rev[0])`]),
SchemePerformComplex.forExecute(executable_mercurial_python, ["tmp.py", "%URL%/", "~%USERNAME%/", "~%REPOSITORY%"])]),
SchemeView(true, true, ' ', [0, 1], ":> "),
SchemePerform.forComplex(
[SchemePerformComplex.forWriteFile("tmp.py", [`
from mercurial import ui, hg, node
from sys import argv
peer = hg.peer(ui.ui(), {}, argv[1])
for name, rev in peer.tagmap().items():
print ":>", name, node.short(rev[0])`]),
SchemePerformComplex.forExecute(executable_mercurial_python, ["tmp.py", "%URL%/", "~%USERNAME%/", "~%REPOSITORY%"])]),
SchemeView(true, true, ' ', [0, 1], ":> "),
);
// non-generic
ret.Git_Github = Scheme(ret.Git_WithUser, "github", "http://github.com",
SchemePerform.forURL(["%URL%/", "%USERNAME%/", "%REPOSITORY%/", "raw/", "%ID%/", "%FILENAME%"]),
SchemePerform.forURL(["%URL%/", "%USERNAME%/", "%REPOSITORY%/", "archive/", "%ID%", ".zip"]));
ret.Git_Repo_or_cz = Scheme(ret.Git_WithoutUser, "repo.or.cz", "http://repo.or.cz",
SchemePerform.forURL(["%URL%/", "%REPOSITORY%", ".git/blob_plain/", "%ID%", ":/", "%FILENAME%"]),
SchemePerform.forURL(["%URL%/", "%REPOSITORY%", ".git/snapshot/", "%ID%.zip"]));
ret.Svn_SourceForge = Scheme(ret.Svn, "sourceforge", "svn://svn.code.sf.net/p");
ret.Mecurial_BitBucket = Scheme(ret.Mercurial_WithUser, "bitbucket", "http://bitbucket.org",
SchemePerform.forURL(["%URL%/", "%USERNAME%/", "%REPOSITORY%/", "raw/", "%ID%/", "%FILENAME%"]),
SchemePerform.forURL(["%URL%/", "%USERNAME%/", "%REPOSITORY%/", "get/", "%ID%", ".zip"]));
return ret;
}
// generic
Scheme Git_WithoutUser, Git_WithUser;
Scheme Svn;
Scheme Mecurial_WithoutUser, Mercurial_WithUser;
// non-generic
Scheme Git_Github;
Scheme Git_Repo_or_cz;
Scheme Svn_SourceForge;
Scheme Mecurial_BitBucket;
}
module schemes;
import std.array : appender;
///
struct SchemeVars {
///
string workingDirectory;
///
string serverURL;
}
///
struct Scheme {
///
string name, varient;
private {
SchemePerform getFile_, getArchive_, getTags_, getBranches_;
SchemeView getTagsView_, getBranchesView_;
string defaultServerURL;
}
///
this(string name, string varient, string defaultServerURL,
SchemePerform getFile_, SchemePerform getArchive_,
SchemePerform getTags_, SchemeView getTagsView_,
SchemePerform getBranches_, SchemeView getBranchesView_) {
this.name = name;
this.varient = varient;
this.defaultServerURL = defaultServerURL;
this.getFile_ = getFile_;
this.getArchive_ = getArchive_;
this.getTags_ = getTags_;
this.getTagsView_ = getTagsView_;
this.getBranches_ = getBranches_;
this.getBranchesView_ = getBranchesView_;
}
///
this(ref Scheme other, string varient, string defaultServerURL) {
this.name = other.name;
this.varient = varient;
this.defaultServerURL = defaultServerURL;
this.getFile_ = other.getFile_;
this.getArchive_ = other.getArchive_;
this.getTags_ = other.getTags_;
this.getTagsView_ = other.getTagsView_;
this.getBranches_ = other.getBranches_;
this.getBranchesView_ = other.getBranchesView_;
}
///
this(ref Scheme other, string varient, string defaultServerURL, SchemePerform getFile_) {
this(other, varient, defaultServerURL);
this.getFile_ = getFile_;
}
///
this(ref Scheme other, string varient, string defaultServerURL,
SchemePerform getFile_, SchemePerform getArchive_) {
this(other, varient, defaultServerURL);
this.getFile_ = getFile_;
this.getArchive_ = other.getArchive_;
}
///
ubyte[] getFile(string username, string repository, string id, string filename, SchemeVars vars=SchemeVars()) {
string serverURL = vars.serverURL !is null ? vars.serverURL : defaultServerURL;
if (getFile_.isURL) {
import std.net.curl : get, AutoProtocol;
auto url = appender!string();
url.reserve(128);
string[] parts;
if (parts is null) {
foreach(tag; getTags(username, repository)) {
if (tag.id == id) {
parts = getFile_.partsForTag;
}
}
}
if (parts is null) {
foreach(branch; getBranches(username, repository)) {
if (branch.id == id) {
parts = getFile_.partsForBranch;
}
}
}
if (parts is null) {
parts = getFile_.partsForElse;
}
foreach(i, p; parts) {
if (p.length >= 10 && p[0 .. 10] == "%USERNAME%") {
url ~= username;
if (p.length == 11)
url ~= '/';
} else if (p.length >= 12 && p[0 .. 12] == "%REPOSITORY%") {
url ~= repository;
if (p.length == 13)
url ~= '/';
} else if (p.length >= 4 && p[0 .. 4] == "%ID%") {
url ~= id;
if (p.length == 5)
url ~= '/';
} else if (p.length >= 10 && p[0 .. 10] == "%FILENAME%") {
url ~= filename;
if (p.length == 11)
url ~= '/';
} else if (p.length >= 5 && p[0 .. 5] == "%URL%") {
url ~= serverURL;
if (p.length == 6)
url ~= '/';
} else {
url ~= p;
}
}
try {
return get!(AutoProtocol, ubyte)(url.data);
} catch (Exception e) {
return null;
}
} else if (getFile_.isComplex) {
import std.file : write;
ubyte[] theoutput;
foreach(step; getFile_.steps) {
StartOfStep:
if (step.isWriteFile) {
auto contents = appender!string();
contents.reserve(1024 * 1024 * 4); // 4mb
foreach(i, p; step.writeParts) {
if (p.length == 10 && p[0 .. 10] == "%USERNAME%") {
contents ~= username;
} else if (p.length == 12 && p[0 .. 12] == "%REPOSITORY%") {
contents ~= repository;
} else if (p.length == 4 && p[0 .. 4] == "%ID%") {
contents ~= id;
} else if (p.length == 10 && p[0 .. 10] == "%FILENAME%") {
contents ~= filename;
} else if (p.length >= 12 && p[0 .. 12] == "%WORKINGDIR%") {
contents ~= vars.workingDirectory;
} else if (p.length >= 5 && p[0 .. 5] == "%URL%") {
contents ~= serverURL;
} else {
contents ~= p;
}
}
write(step.writeName, contents.data);
} else if (step.isReadFile) {
import std.file : read;
if (step.appendNotAssignOutput) {
theoutput ~= cast(ubyte[])read(step.readName);
} else {
theoutput = cast(ubyte[])read(step.readName);
}
} else if (step.isExecute) {
import std.process : execute;
string[] args;
args ~= step.program;
foreach(i, p; step.programArgs) {
if (p[0] == '~')
p = p[1 .. $];
else
args.length++;
if (p.length >= 10 && p[0 .. 10] == "%USERNAME%") {
args[$-1] ~= username;
if (p.length == 11)
args[$-1] ~= '/';
} else if (p.length >= 12 && p[0 .. 12] == "%REPOSITORY%") {
args[$-1] ~= repository;
if (p.length == 13)
args[$-1] ~= '/';
} else if (p.length >= 4 && p[0 .. 4] == "%ID%") {
args[$-1] ~= id;
if (p.length == 5)
args[$-1] ~= '/';
} else if (p.length >= 10 && p[0 .. 10] == "%FILENAME%") {
args[$-1] ~= filename;
if (p.length == 11)
args[$-1] ~= '/';
} else if (p.length >= 12 && p[0 .. 12] == "%WORKINGDIR%") {
args[$-1] ~= vars.workingDirectory;
if (p.length == 13)
args[$-1] ~= '/';
} else if (p.length >= 5 && p[0 .. 5] == "%URL%") {
args[$-1] ~= serverURL;
if (p.length == 6)
args[$-1] ~= '/';
} else {
args[$-1] ~= p;
}
}
auto called = execute(args);
if (step.appendNotAssignOutput) {
theoutput ~= cast(ubyte[])called.output;
} else {
theoutput = cast(ubyte[])called.output;
}
if (step.programOutputToFile !is null) {
write(step.programOutputToFile, called.output);
}
} else if (step.isConstant) {
if (step.appendNotAssignOutput) {
theoutput ~= cast(ubyte[])step.constant;
} else {
theoutput = cast(ubyte[])step.constant;
}
} else if (step.isConditional) {
foreach(tag; getTags(username, repository)) {
if (tag.id == id) {
step = *step.isTag;
goto StartOfStep;
}
}
foreach(branch; getBranches(username, repository)) {
if (branch.id == id) {
step = *step.isBranch;
goto StartOfStep;
}
}
step = *step.isElse;
goto StartOfStep;
}
}
return theoutput;
}
return null;
}
///
string getArchiveURL(string username, string repository, string id, SchemeVars vars=SchemeVars()) {
string serverURL = vars.serverURL !is null ? vars.serverURL : defaultServerURL;
if (getArchive_.isURL) {
import std.net.curl : get, AutoProtocol;
auto url = appender!string();
url.reserve(128);
string[] parts;
if (parts is null) {
foreach(tag; getTags(username, repository)) {
if (tag.id == id) {
parts = getFile_.partsForTag;
}
}
}
if (parts is null) {
foreach(branch; getBranches(username, repository)) {
if (branch.id == id) {
parts = getFile_.partsForBranch;
}
}
}
if (parts is null) {
parts = getFile_.partsForElse;
}
foreach(i, p; parts) {
if (p.length >= 10 && p[0 .. 10] == "%USERNAME%") {
url ~= username;
if (p.length == 11)
url ~= '/';
} else if (p.length >= 12 && p[0 .. 12] == "%REPOSITORY%") {
url ~= repository;
if (p.length == 13)
url ~= '/';
} else if (p.length >= 4 && p[0 .. 4] == "%ID%") {
url ~= id;
if (p.length == 5)
url ~= '/';
} else if (p.length >= 5 && p[0 .. 5] == "%URL%") {
url ~= serverURL;
if (p.length == 6)
url ~= '/';
} else {
url ~= p;
}
}
return url.data;
}
return null;
}
///
ubyte[] getArchive(string username, string repository, string id, SchemeVars vars=SchemeVars()) {
string serverURL = vars.serverURL !is null ? vars.serverURL : defaultServerURL;
if (getArchive_.isURL) {
import std.net.curl : get, AutoProtocol;
auto url = appender!string();
url.reserve(128);
string[] parts;
if (parts is null) {
foreach(tag; getTags(username, repository)) {
if (tag.id == id) {
parts = getArchive_.partsForTag;
}
}
}
if (parts is null) {
foreach(branch; getBranches(username, repository)) {
if (branch.id == id) {
parts = getArchive_.partsForBranch;
}
}
}
if (parts is null) {
parts = getArchive_.partsForElse;
}
foreach(i, p; parts) {
if (p.length >= 10 && p[0 .. 10] == "%USERNAME%") {
url ~= username;
if (p.length == 11)
url ~= '/';
} else if (p.length >= 12 && p[0 .. 12] == "%REPOSITORY%") {
url ~= repository;
if (p.length == 13)
url ~= '/';
} else if (p.length >= 4 && p[0 .. 4] == "%ID%") {
url ~= id;
if (p.length == 5)
url ~= '/';
} else if (p.length >= 5 && p[0 .. 5] == "%URL%") {
url ~= serverURL;
if (p.length == 6)
url ~= '/';
} else {
url ~= p;
}
}
try {
return get!(AutoProtocol, ubyte)(url.data);
} catch (Exception e) {
return null;
}
} else if (getArchive_.isComplex) {
import std.file : write;
ubyte[] theoutput;
foreach(step; getArchive_.steps) {
StartOfStep:
if (step.isWriteFile) {
auto contents = appender!string();
contents.reserve(1024 * 1024 * 4); // 4mb
foreach(i, p; step.writeParts) {
if (p.length == 10 && p[0 .. 10] == "%USERNAME%") {
contents ~= username;
} else if (p.length == 12 && p[0 .. 12] == "%REPOSITORY%") {
contents ~= repository;
} else if (p.length == 4 && p[0 .. 4] == "%ID%") {
contents ~= id;
} else if (p.length == 12 && p[0 .. 12] == "%WORKINGDIR%") {
contents ~= vars.workingDirectory;
} else if (p.length >= 5 && p[0 .. 5] == "%URL%") {
contents ~= serverURL;
} else {
contents ~= p;
}
}
write(step.writeName, contents.data);
} else if (step.isReadFile) {
import std.file : read;
if (step.appendNotAssignOutput) {
theoutput ~= cast(ubyte[])read(step.readName);
} else {
theoutput = cast(ubyte[])read(step.readName);
}
} else if (step.isExecute) {
import std.process : execute;
string[] args;
args ~= step.program;
foreach(i, p; step.programArgs) {
if (p[0] == '~')
p = p[1 .. $];
else
args.length++;
if (p.length >= 10 && p[0 .. 10] == "%USERNAME%") {
args[$-1] ~= username;
if (p.length == 11)
args[$-1] ~= '/';
} else if (p.length >= 12 && p[0 .. 12] == "%REPOSITORY%") {
args[$-1] ~= repository;
if (p.length == 13)
args[$-1] ~= '/';
} else if (p.length >= 4 && p[0 .. 4] == "%ID%") {
args[$-1] ~= id;
if (p.length == 5)
args[$-1] ~= '/';
} else if (p.length >= 12 && p[0 .. 12] == "%WORKINGDIR%") {
args[$-1] ~= vars.workingDirectory;
if (p.length == 13)
args[$-1] ~= '/';
} else if (p.length >= 5 && p[0 .. 5] == "%URL%") {
args[$-1] ~= serverURL;
if (p.length == 6)
args[$-1] ~= '/';
} else {
args[$-1] ~= p;
}
}
import std.stdio;
writeln(args);
auto called = execute(args);
if (step.appendNotAssignOutput) {
theoutput ~= cast(ubyte[])called.output;
} else {
theoutput = cast(ubyte[])called.output;
}
if (step.programOutputToFile !is null) {
write(step.programOutputToFile, called.output);
}
} else if (step.isConstant) {
if (step.appendNotAssignOutput) {
theoutput ~= cast(ubyte[])step.constant;
} else {
theoutput = cast(ubyte[])step.constant;
}
} else if (step.isConditional) {
foreach(tag; getTags(username, repository)) {
if (tag.id == id) {
step = *step.isTag;
goto StartOfStep;
}
}
foreach(branch; getBranches(username, repository)) {
if (branch.id == id) {
step = *step.isBranch;
goto StartOfStep;
}
}
step = *step.isElse;
goto StartOfStep;
}
}
return theoutput;
}
return null;
}
SchemeId[] getTags(string username, string repository, SchemeVars vars=SchemeVars()) {
return getIds(getTags_, getTagsView_, username, repository, vars);
}
SchemeId[] getBranches(string username, string repository, SchemeVars vars=SchemeVars()) {
return getIds(getBranches_, getBranchesView_, username, repository, vars);
}
private SchemeId[] getIds(SchemePerform root, SchemeView rootView, string username, string repository, SchemeVars vars=SchemeVars()) {
char[] allidsText;
string serverURL = vars.serverURL !is null ? vars.serverURL : defaultServerURL;
if (root.isURL) {
import std.net.curl : get, AutoProtocol;
auto url = appender!string();
url.reserve(128);
foreach(i, p; root.partsForElse) {
if (p.length >= 10 && p[0 .. 10] == "%USERNAME%") {
url ~= username;
if (p.length == 11)
url ~= '/';
} else if (p.length >= 12 && p[0 .. 12] == "%REPOSITORY%") {
url ~= repository;
if (p.length == 13)
url ~= '/';
} else if (p.length >= 5 && p[0 .. 5] == "%URL%") {
url ~= serverURL;
if (p.length == 6)
url ~= '/';
} else {
url ~= p;
}
}
try {
allidsText = get(url.data);
} catch (Exception e) {
return null;
}
} else if (root.isComplex) {
import std.file : write;
ubyte[] theoutput;
foreach(step; root.steps) {
if (step.isWriteFile) {
auto contents = appender!string();
contents.reserve(1024 * 1024 * 4); // 4mb
foreach(i, p; step.writeParts) {
if (p.length == 10 && p[0 .. 10] == "%USERNAME%") {
contents ~= username;
} else if (p.length == 12 && p[0 .. 12] == "%REPOSITORY%") {
contents ~= repository;
} else if (p.length >= 5 && p[0 .. 5] == "%URL%") {
contents ~= serverURL;
} else {
contents ~= p;
}
}
write(step.writeName, contents.data);
} else if (step.isReadFile) {
import std.file : read;
if (step.appendNotAssignOutput) {
theoutput ~= cast(ubyte[])read(step.readName);
} else {
theoutput = cast(ubyte[])read(step.readName);
}
} else if (step.isExecute) {
import std.process : execute;
string[] args;
args ~= step.program;
foreach(i, p; step.programArgs) {
if (p[0] == '~')
p = p[1 .. $];
else
args.length++;
if (p.length >= 10 && p[0 .. 10] == "%USERNAME%") {
args[$-1] ~= username;
if (p.length == 11)
args[$-1] ~= '/';
} else if (p.length >= 12 && p[0 .. 12] == "%REPOSITORY%") {
args[$-1] ~= repository;
if (p.length == 13)
args[$-1] ~= '/';
} else if (p.length >= 5 && p[0 .. 5] == "%URL%") {
args[$-1] ~= serverURL;
if (p.length == 6)
args[$-1] ~= '/';
} else {
args[$-1] ~= p;
}
}
auto called = execute(args);
if (step.appendNotAssignOutput) {
theoutput ~= cast(ubyte[])called.output;
} else {
theoutput = cast(ubyte[])called.output;
}
if (step.programOutputToFile !is null) {
write(step.programOutputToFile, called.output);
}
} else if (step.isConstant) {
if (step.appendNotAssignOutput) {
theoutput ~= cast(ubyte[])step.constant;
} else {
theoutput = cast(ubyte[])step.constant;
}
}
}
allidsText = cast(char[])theoutput;
}
if (allidsText !is null) {
import std.string : lineSplitter;
SchemeId[] ret;
if (rootView.isDelimated) {
foreach(line; allidsText.lineSplitter) {
import std.algorithm : splitter;
if (rootView.requirePrefix) {
if (rootView.prefix == line[0 .. rootView.prefix.length])
line = line[rootView.prefix.length .. $];
else
continue;
}
string hash, id;
uint ofx;
foreach(v; line.splitter(rootView.deliminator)) {
if (ofx <= rootView.itemColumn.length) {
if (rootView.itemColumn[0] == ofx) {
id = cast(string)v;
} else if (rootView.itemColumn[1] == ofx) {
hash = cast(string)v;
}
}
ofx++;
}
if (hash !is null && id !is null) {
ret ~= SchemeId(id, hash);
}
}
} else {
foreach(line; allidsText.lineSplitter) {
ret ~= SchemeId(cast(string)line);
}
}
return ret;
}
return null;
}
}
///
struct SchemePerform {
///
bool isURL;
///
bool isComplex;
union {
struct {
///
string[] partsForTag, partsForBranch, partsForElse;
}
struct {
///
SchemePerformComplex[] steps;
}
}
///
static SchemePerform forURL(string[] parts) {
SchemePerform ret;
ret.isURL = true;
ret.partsForTag = parts;
ret.partsForBranch = parts;
ret.partsForElse = parts;
return ret;
}
///
static SchemePerform forURL(string[] partsForTag, string[] partsForBranch, string[] partsForElse) {
SchemePerform ret;
ret.isURL = true;
ret.partsForTag = partsForTag;
ret.partsForBranch = partsForBranch;
ret.partsForElse = partsForElse;
return ret;
}
///
static SchemePerform forComplex(SchemePerformComplex[] steps) {
SchemePerform ret;
ret.isComplex = true;
ret.steps = steps;
return ret;
}
}
///
struct SchemePerformComplex {
///
bool isWriteFile, isReadFile, isExecute, isConstant, isConditional;
///
bool appendNotAssignOutput;
union {
struct {
///
string writeName;
///
string[] writeParts;
}
struct {
///
string readName;
}
struct {
///
string program;
///
string[] programArgs;
///
string programOutputToFile;
}
struct {
string constant;
}
struct {
SchemePerformComplex* isTag, isBranch, isElse;
}
}
static {
///
SchemePerformComplex forWriteFile(string writeName, string[] writeParts) {
SchemePerformComplex ret;
ret.isWriteFile = true;
ret.writeName = writeName;
ret.writeParts = writeParts;
return ret;
}
///
SchemePerformComplex forReadFile(string readName, bool appendNotAssignOutput=false) {
SchemePerformComplex ret;
ret.isReadFile = true;
ret.readName = readName;
ret.appendNotAssignOutput = appendNotAssignOutput;
return ret;
}
///
SchemePerformComplex forExecute(string program, string[] programArgs, string programOutputToFile=null, bool appendNotAssignOutput=false) {
SchemePerformComplex ret;
ret.isExecute = true;
ret.program = program;
ret.programArgs = programArgs;
ret.programOutputToFile = programOutputToFile;
ret.appendNotAssignOutput = appendNotAssignOutput;
return ret;
}
SchemePerformComplex forConstant(string constant, bool appendNotAssignOutput=false) {
SchemePerformComplex ret;
ret.isConstant = true;
ret.constant = constant;
ret.appendNotAssignOutput = appendNotAssignOutput;
return ret;
}
SchemePerformComplex forConditional(SchemePerformComplex isTag, SchemePerformComplex isBranch, SchemePerformComplex isElse) {
SchemePerformComplex ret;
ret.isConditional = true;
ret.isTag = new SchemePerformComplex;
ret.isBranch = new SchemePerformComplex;
ret.isElse = new SchemePerformComplex;
*ret.isTag = isTag;
*ret.isBranch = isBranch;
*ret.isElse = isElse;
return ret;
}
}
}
///
struct SchemeView {
///
bool isDelimated;
///
bool requirePrefix;
///
char deliminator;
///
uint[2] itemColumn;
///
string prefix;
}
///
struct SchemeId {
///
string id;
///
string hash;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment