Last active
February 23, 2017 13:19
-
-
Save rikkimax/4718740223748256d94b3b1474525012 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"));+/ | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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