Skip to content

Commit f3945cd

Browse files
committed
Wip: Adding redub install command
1 parent 8444351 commit f3945cd

File tree

11 files changed

+368
-29
lines changed

11 files changed

+368
-29
lines changed

hipjson/source/hipjson.d

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module hipjson;
22
import hip.util.shashmap;
33

4-
JSONValue parseJSON(string jsonData)
4+
JSONValue parseJSON(const char[] jsonData)
55
{
66
return JSONValue.parse(jsonData);
77
}
@@ -412,7 +412,7 @@ struct JSONValue
412412
}
413413

414414

415-
private static JSONValue parse(string data)
415+
private static JSONValue parse(const char[] data)
416416
{
417417
import core.memory;
418418
import std.conv:to;
@@ -422,7 +422,7 @@ struct JSONValue
422422
ptrdiff_t index = 0;
423423
StringPool pool = StringPool(cast(size_t)(data.length*0.75));
424424

425-
bool getNextString(string data, ptrdiff_t currentIndex, out ptrdiff_t newIndex, out string theString)
425+
bool getNextString(const char[] data, ptrdiff_t currentIndex, out ptrdiff_t newIndex, out string theString)
426426
{
427427
assert(data[currentIndex] == '"', "getNextString must start with a quotation mark");
428428
ptrdiff_t i = currentIndex + 1;
@@ -460,7 +460,7 @@ struct JSONValue
460460
}
461461

462462

463-
bool getNextNumber(string data, ptrdiff_t currentIndex, out ptrdiff_t newIndex, out JSONData theData, out JSONType type)
463+
bool getNextNumber(const char[] data, ptrdiff_t currentIndex, out ptrdiff_t newIndex, out JSONData theData, out JSONType type)
464464
{
465465
assert(data[currentIndex].isNumeric);
466466
bool hasDecimal = false;
@@ -486,7 +486,7 @@ struct JSONValue
486486
}
487487
else
488488
{
489-
static long strToLong(string str)
489+
static long strToLong(const char[] str)
490490
{
491491
long result = 0;
492492
foreach(ch; str)

source/app.d

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ int main(string[] args)
6767
"deps": &depsMain,
6868
"test": &testMain,
6969
"init": &initMain,
70+
"install": &installMain,
7071
// "watch": &watchMain,
7172
"run": cast(int function(string[]))null
7273
];
@@ -266,4 +267,57 @@ int buildMain(string[] args)
266267
{
267268
ProjectDetails d = resolveDependencies(args);
268269
return buildProject(d).getReturnCode;
270+
}
271+
272+
int installMain(string[] args)
273+
{
274+
import std.string;
275+
import redub.cli.dub;
276+
import redub.logging;
277+
setLogLevel(LogLevel.info);
278+
if(args.length == 1)
279+
{
280+
error("redub install requires 1 additional argument: ",
281+
"\n\topend: installs opend",
282+
"\n\tldc <version?|?>: installs ldc latest if version is unspecified.",
283+
"\n\t\thelp: Lists available ldc versions",
284+
);
285+
return 1;
286+
}
287+
string compiler = args[1];
288+
if(compiler.startsWith("opend"))
289+
{
290+
import redub.misc.opend_install;
291+
return installOpend();
292+
}
293+
else if(compiler.startsWith("ldc"))
294+
{
295+
import redub.api;
296+
import redub.misc.ldc_install;
297+
import redub.misc.github_tag_check;
298+
enum ldcRepo = "ldc-developers/ldc";
299+
string ldcVer = args.length > 2 ? args[2] : null;
300+
if(!ldcVer)
301+
ldcVer = getLatestGitRepositoryTag(ldcRepo);
302+
else if(ldcVer == "help")
303+
{
304+
import hipjson;
305+
JSONValue gitTags = getGithubRepoAPI(ldcRepo);
306+
info("Listing available LDC versions:");
307+
int limit = 25;
308+
foreach(entry; gitTags.array)
309+
{
310+
info("\t", entry["name"].str);
311+
if(--limit == 0)
312+
break;
313+
}
314+
return 0;
315+
}
316+
return cast(int)installLdc(ldcVer);
317+
}
318+
else if(compiler.startsWith("dmd"))
319+
{
320+
//return installDmd();
321+
}
322+
return 0;
269323
}

source/redub/api.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,7 @@ private string getPackageFromCli(ref string[] args)
865865
return null;
866866
}
867867

868-
private string getVersionFromPackage(ref string pkg)
868+
string getVersionFromPackage(ref string pkg)
869869
{
870870
import std.algorithm.searching;
871871
ptrdiff_t ver = countUntil!((a => a == '@'))(pkg);

source/redub/building/compile.d

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -199,18 +199,6 @@ CompilationResult execCompilation(immutable ThreadBuildData data, shared Project
199199
return res;
200200
}
201201

202-
bool makeFileExecutable(string filePath)
203-
{
204-
version(Windows) return true;
205-
version(Posix)
206-
{
207-
import std.file;
208-
if(!std.file.exists(filePath)) return false;
209-
import std.conv:octal;
210-
std.file.setAttributes(filePath, octal!700);
211-
return true;
212-
}
213-
}
214202

215203
CompilationResult link(ProjectNode root, string rootHash, const ThreadBuildData data, CompilingSession info, immutable string[string] env)
216204
{
@@ -241,6 +229,7 @@ CompilationResult link(ProjectNode root, string rootHash, const ThreadBuildData
241229
string inDir = getCacheOutputDir(rootHash, cast()root.requirements, info);
242230
if(root.requirements.cfg.targetType == TargetType.executable && std.system.os.isPosix && info.isa != ISA.webAssembly)
243231
{
232+
import redub.misc.make_file_executable;
244233
string execPath = buildNormalizedPath(inDir, getOutputName(data.cfg, os));
245234
if(!makeFileExecutable(execPath))
246235
throw new Exception("Could not make the output file as executable "~execPath);

source/redub/extensions/update.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ int updateMain(string[] args)
7272

7373
if(gitCode == isNotGitRepo || gitCode == hasNoGitWindows || gitCode == hasNoGitPosix)
7474
{
75-
latest = getLatestVersion();
75+
latest = getLatestRedubVersion();
7676
if(SemVer(latest[1..$]) > SemVer(RedubVersionOnly[1..$]))
7777
{
7878
replaceRedub = true;

source/redub/misc/_7zip.d

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
module redub.misc._7zip;
2+
version(Windows):
3+
private enum installLink = "https://www.7-zip.org/a/7zr.exe";
4+
//7zip is only used on windows currently.
5+
6+
private bool install7Zip(out string _7zpath)
7+
{
8+
import std.array;
9+
import std.file;
10+
import redub.api;
11+
import redub.meta;
12+
import redub.misc.path;
13+
import std.net.curl;
14+
import redub.libs.package_suppliers.utils;
15+
string workspace = getDubWorkspacePath;
16+
_7zpath = buildNormalizedPath(workspace, "7z.exe");
17+
if(!exists(workspace))
18+
mkdirRecurse(workspace);
19+
if(exists(_7zpath))
20+
return true;
21+
22+
try
23+
download(installLink, _7zpath);
24+
catch (Exception e)
25+
throw new NetworkException("Could not download "~installLink~": "~e.msg);
26+
return true;
27+
}
28+
29+
bool extract7ZipToFolder(string zPath, string outputDirectory)
30+
{
31+
import redub.logging;
32+
import std.file;
33+
import std.process;
34+
string _7z;
35+
if(!install7Zip(_7z))
36+
return false;
37+
if(!std.file.exists(zPath))
38+
{
39+
error("File ", zPath, " does not exists.");
40+
return false;
41+
}
42+
info("Extracting ", zPath, " to ", outputDirectory);
43+
if(!std.file.exists(outputDirectory))
44+
std.file.mkdirRecurse(outputDirectory);
45+
46+
string dir = getcwd;
47+
chdir(outputDirectory);
48+
scope(exit)
49+
chdir(dir);
50+
auto res = executeShell(_7z ~ " x -y "~zPath, t);
51+
if(res.status)
52+
error("Could not extract 7z '", zPath, "' to '", outputDirectory, "': ", res.output);
53+
return res.status == 0;
54+
}

source/redub/misc/github_tag_check.d

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
module redub.misc.github_tag_check;
2+
import hipjson;
23

34
private enum RedubUserRepository = "MrcSnm/redub";
4-
private enum GithubTagAPI = "https://api.github.com/repos/"~RedubUserRepository~"/tags";
55
private enum CreateIssueURL = "https://github.com/"~RedubUserRepository~"/issues/new/choose";
66

77

88
void showNewerVersionMessage()
99
{
1010
import redub.buildapi;
1111
import redub.logging;
12-
string ver = getLatestVersion();
12+
string ver = getLatestRedubVersion();
1313
if(ver)
1414
{
1515
if(ver != RedubVersionOnly)
@@ -27,18 +27,35 @@ void showNewerVersionMessage()
2727
);
2828
}
2929

30-
string getLatestVersion()
30+
/**
31+
* Params:
32+
* repo = The repository which you want to fetch from. Both user/repo
33+
* Returns:
34+
*/
35+
string getLatestGitRepositoryTag(string repo)
36+
{
37+
JSONValue v = getGithubRepoAPI(repo);
38+
if(v.isNull)
39+
return null;
40+
return v.array[0]["name"].str;
41+
}
42+
43+
JSONValue getGithubRepoAPI(string repo)
3144
{
3245
import std.net.curl;
33-
import hipjson;
46+
import std.conv:text;
47+
string api = i"https://api.github.com/repos/$(repo)/tags".text;
48+
char[] tagsContent = get(api);
49+
if(tagsContent.length == 0)
50+
return JSONValue(null);
51+
return parseJSON(tagsContent);
52+
}
53+
54+
string getLatestRedubVersion()
55+
{
3456
static string newestVer;
3557
if(!newestVer)
36-
{
37-
char[] tagsContent = get(GithubTagAPI);
38-
if(tagsContent.length == 0)
39-
return null;
40-
newestVer = parseJSON(cast(string)tagsContent).array[0]["name"].str;
41-
}
58+
newestVer = getLatestGitRepositoryTag(RedubUserRepository);
4259
return newestVer;
4360
}
4461

source/redub/misc/ldc_install.d

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
module redub.misc.ldc_install;
2+
import std.system;
3+
4+
bool installLdc(string ldcVersion, OS os = std.system.os, ISA isa = instructionSetArchitecture)
5+
{
6+
import std.array;
7+
import std.file;
8+
import redub.api;
9+
import redub.meta;
10+
import redub.misc.path;
11+
import redub.misc.unzip;
12+
import redub.libs.package_suppliers.utils;
13+
import redub.misc.make_file_executable;
14+
import redub.logging;
15+
string downloadLink = getLdcDownloadLink(ldcVersion, os, isa);
16+
17+
string workspace = buildNormalizedPath(getDubWorkspacePath, "redub-ldc");
18+
string binPath = buildNormalizedPath(workspace, getLdcFolderName(ldcVersion, os, isa), "bin");
19+
if(!exists(workspace))
20+
mkdirRecurse(workspace);
21+
if(exists(binPath))
22+
{
23+
infos("LDC ",ldcVersion," is already installed at path ", binPath);
24+
return true;
25+
}
26+
27+
if(!downloadAndExtract(downloadLink, workspace))
28+
return false;
29+
foreach(executable; ["ldc2", "ldmd2", "rdmd", "dub"].staticArray)
30+
if(!makeFileExecutable(buildNormalizedPath(binPath, executable)))
31+
return false;
32+
return true;
33+
}
34+
35+
string getLdcFolderName(string ver, OS os = std.system.os, ISA isa = instructionSetArchitecture)
36+
{
37+
import redub.command_generators.commons;
38+
import redub.api;
39+
import core.interpolation;
40+
import std.conv:to,text;
41+
import std.string:startsWith;
42+
string sys;
43+
if(ver.startsWith("v"))
44+
ver = ver[1..$];
45+
46+
if(os.isWindows)
47+
sys = "windows-multilib";
48+
else if(os.isApple)
49+
sys = "osx-universal";
50+
else if(os.isPosix)
51+
sys = isa == ISA.aarch64 ? "linux-aarch64" : "linux-x86_64";
52+
else
53+
throw new RedubException("Redub has no support to LDC for the OS '"~os.to!string~"'");
54+
return i"ldc2-$(ver)-$(sys)".text;
55+
}
56+
string getLdcDownloadLink(string ver, OS os = std.system.os, ISA isa = instructionSetArchitecture)
57+
{
58+
import redub.command_generators.commons;
59+
import redub.api;
60+
import core.interpolation;
61+
import std.conv:to,text;
62+
import std.string:startsWith;
63+
string sys;
64+
if(ver.startsWith("v"))
65+
ver = ver[1..$];
66+
67+
if(os.isWindows)
68+
sys = "windows-multilib.7z";
69+
else if(os.isApple)
70+
sys = "osx-universal.tar.xz";
71+
else if(os.isPosix)
72+
sys = isa == ISA.aarch64 ? "linux-aarch64.tar.xz" : "linux-x86_64.tar.xz";
73+
else
74+
throw new RedubException("Redub has no support to LDC for the OS '"~os.to!string~"'");
75+
return i"https://github.com/ldc-developers/ldc/releases/download/v$(ver)/ldc2-$(ver)-$(sys)".text;
76+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module redub.misc.make_file_executable;
2+
3+
bool makeFileExecutable(string filePath)
4+
{
5+
import std.file;
6+
version(Windows) return true;
7+
version(Posix)
8+
{
9+
if(!std.file.exists(filePath)) return false;
10+
import std.conv:octal;
11+
std.file.setAttributes(filePath, octal!700);
12+
return true;
13+
}
14+
}

0 commit comments

Comments
 (0)