Skip to content

Commit 80313c5

Browse files
committed
Experimental 'hx with' and internal tools for bundled haxe
1 parent de84ca0 commit 80313c5

File tree

4 files changed

+183
-19
lines changed

4 files changed

+183
-19
lines changed

src/BundledHaxe.hx

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import sys.io.File;
2+
import haxe.io.Path;
3+
import sys.FileSystem;
4+
5+
import tools.DownloadHelper;
6+
import tools.Utils;
7+
8+
class BundledHaxe {
9+
static var OS = ["Linux", "Mac", "Windows"];
10+
static var current = Path.join([Utils.bundleDir, ".current"]);
11+
12+
public static function getBundledVersion():String {
13+
return StringTools.trim(File.getContent(current));
14+
}
15+
16+
public static function setBundledVersion(version:String):Void {
17+
final v = HaxeNightlies.resolve(version);
18+
19+
function getOsPath(os) {
20+
return switch os {
21+
case "Linux": "linux64";
22+
case "Windows": "windows64";
23+
case "Mac": "mac";
24+
case _: throw 'Unexpected os $os';
25+
}
26+
}
27+
28+
function updateCurrent() {
29+
final prev = getBundledVersion();
30+
31+
if (prev != version) {
32+
for (os in OS) {
33+
final path = Path.join([Utils.bundleDir, getOsPath(os) + "_" + prev]);
34+
Utils.rmdir(path);
35+
Sys.println('Removed $path');
36+
}
37+
38+
File.saveContent(current, version);
39+
// TODO: git operations
40+
Sys.println('Set current bundled haxe version as $version');
41+
}
42+
}
43+
44+
final os = OS.copy();
45+
46+
function next() {
47+
if (os.length == 0) return updateCurrent();
48+
49+
final os = os.pop();
50+
final dest = Path.join([Utils.bundleDir, getOsPath(os) + "_" + version]);
51+
if (FileSystem.exists(dest)) {
52+
Sys.println('Bundled version $version for $os already exists');
53+
return next();
54+
}
55+
56+
final url = Utils.getBuildUrl(v, os);
57+
final filename = Path.withoutDirectory(url[1]);
58+
final path = Path.join([Utils.bundleDir, filename]);
59+
60+
DownloadHelper.download(url[0] + filename, path, () -> {
61+
Sys.println('Downloaded $filename');
62+
final out = DownloadHelper.extract(path);
63+
FileSystem.deleteFile(path);
64+
FileSystem.rename(Path.join([Utils.bundleDir, out]), dest);
65+
next();
66+
});
67+
}
68+
69+
next();
70+
}
71+
}

src/HaxeManager.hx

+14
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,20 @@ class HaxeManager {
3939
case ["--help", ["download"]]: HaxeDownload.displayUsage();
4040
case ["--help", ["select"]]: HaxeSelect.displayUsage();
4141

42+
// Experimental commands
43+
44+
// Note: this is not suited for eval (or -cmd) using stdin, as that
45+
// will not be forwarded properly
46+
case ["with", args] if (args.length > 0):
47+
var v = args.shift();
48+
if (v == "rc") v = HaxeRc.getRc();
49+
final path = Utils.find(v);
50+
Utils.runHaxe(path, args);
51+
52+
// Internal commands
53+
case ["bundled", []]: Sys.println(BundledHaxe.getBundledVersion());
54+
case ["bundle", [version]]: BundledHaxe.setBundledVersion(version);
55+
4256
case [v, []]: HaxeSelect.select(v);
4357
case _: throw 'Invalid arguments';
4458
}

src/HaxeRc.hx

+38-15
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,17 @@ import haxe.io.Path;
66

77
import tools.Utils;
88

9+
enum HaxeRcError {
10+
NotFound;
11+
ParseError(err:String);
12+
}
13+
914
class HaxeRc {
10-
public static function resolve() {
15+
public static function safeGetRc():Null<String> {
16+
return try getRc() catch(_) null;
17+
}
18+
19+
public static function getRc():Null<String> {
1120
final cwd = Utils.getCallSite();
1221

1322
// TODO (?): check parent directories too
@@ -16,23 +25,37 @@ class HaxeRc {
1625
if (FileSystem.exists(rc)) {
1726
try {
1827
final version = Json.parse(File.getContent(rc)).version;
19-
20-
if (SemVer.isValid(version)) {
21-
HaxeDownload.downloadRelease(version, r -> HaxeSelect.select(r));
22-
} else if (HaxeNightlies.isValid(version)) {
23-
switch (Utils.resolveRelease(version)) {
24-
case null:
25-
HaxeDownload.downloadNightly(version, r -> HaxeSelect.select(r));
26-
case r:
27-
HaxeSelect.select(r);
28-
}
29-
}
28+
return version;
3029
} catch (e) {
31-
Utils.displayError('Could not get Haxe version from .haxerc: $e');
32-
Sys.exit(1);
30+
throw ParseError(Std.string(e));
3331
}
3432
} else {
35-
Utils.displayError('Did not find any .haxerc to apply');
33+
throw NotFound;
34+
}
35+
}
36+
37+
public static function resolve() {
38+
try {
39+
final version = getRc();
40+
41+
if (SemVer.isValid(version)) {
42+
HaxeDownload.downloadRelease(version, r -> HaxeSelect.select(r));
43+
} else if (HaxeNightlies.isValid(version)) {
44+
switch (Utils.resolveRelease(version)) {
45+
case null:
46+
HaxeDownload.downloadNightly(version, r -> HaxeSelect.select(r));
47+
case r:
48+
HaxeSelect.select(r);
49+
}
50+
}
51+
} catch (e:HaxeRcError) {
52+
switch e {
53+
case NotFound:
54+
Utils.displayError('Did not find any .haxerc to apply');
55+
case ParseError(e):
56+
Utils.displayError('Could not get Haxe version from .haxerc: $e');
57+
}
58+
3659
Sys.exit(1);
3760
}
3861
}

src/tools/Utils.hx

+60-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import sys.FileSystem;
77
import sys.io.Process;
88

99
import ansi.ANSI;
10+
using tools.NullTools;
1011

1112
class Utils {
1213
public static inline var binDir = "bin";
14+
public static inline var bundleDir = "build";
1315
public static inline var currentDir = "current";
1416
public static inline var versionsDir = "versions";
1517
public static inline var releasesDir = "releases";
@@ -34,9 +36,9 @@ class Utils {
3436
Sys.stderr().flush();
3537
}
3638

37-
public static function getBuildUrl(v:String):Array<String> {
39+
public static function getBuildUrl(v:String, ?os:String):Array<String> {
3840
// TODO: arch variants
39-
return switch Sys.systemName() {
41+
return switch os.or(Sys.systemName()) {
4042
case "Linux":
4143
['https://build.haxe.org/builds/haxe/linux64/', 'haxe_$v.tar.gz'];
4244
case "Mac":
@@ -95,6 +97,28 @@ class Utils {
9597
};
9698
}
9799

100+
public static function runHaxe(path:String, args:Array<String>):Void {
101+
final exe = switch Sys.systemName() {
102+
case "Windows": "haxe.exe";
103+
case _: "haxe";
104+
};
105+
106+
final cwd = Sys.getCwd();
107+
final path = Path.join([cwd, path]);
108+
final old_std = Sys.getEnv("HAXE_STD_PATH");
109+
110+
Sys.setCwd(Utils.getCallSite());
111+
Sys.putEnv("HAXE_STD_PATH", Path.join([path, "std"]));
112+
113+
var ret = Sys.command(Path.join([path, exe]), args);
114+
115+
Sys.putEnv("HAXE_STD_PATH", old_std);
116+
Sys.setCwd(cwd);
117+
118+
Sys.exit(ret);
119+
}
120+
121+
// TODO: factorize with runHaxe
98122
public static function getVersionString(path:String):Null<String> {
99123
final exe = switch Sys.systemName() {
100124
case "Windows": "haxe.exe";
@@ -114,6 +138,18 @@ class Utils {
114138
}
115139
}
116140

141+
public static function find(v:String, ?rec:Bool = false):Null<String> {
142+
var dir = Path.join([versionsDir, v]);
143+
if (FileSystem.exists(dir)) return dir;
144+
145+
dir = Path.join([releasesDir, v]);
146+
if (FileSystem.exists(dir)) return dir;
147+
148+
v = resolveRelease(v);
149+
if (v != null) return Path.join([releasesDir, v]);
150+
return null;
151+
}
152+
117153
public static function hasVersion(v:String):Bool {
118154
final dir = Path.join([versionsDir, v]);
119155
return FileSystem.exists(dir);
@@ -135,9 +171,18 @@ class Utils {
135171
return null;
136172
}
137173

138-
public static function selectRelease(r:String):Void {
174+
public static function hasRelease(r:String):Bool {
139175
final dir = Path.join([releasesDir, r]);
140-
if (!FileSystem.exists(dir)) throw 'Version $r is not installed';
176+
return FileSystem.exists(dir);
177+
}
178+
179+
public static function selectRelease(r:String):Void {
180+
var dir = Path.join([releasesDir, r]);
181+
if (!hasRelease(r)) {
182+
r = resolveRelease(r);
183+
if (r == null) throw 'Version $r is not installed';
184+
dir = Path.join([releasesDir, r]);
185+
}
141186

142187
unlinkCurrent();
143188
link(dir);
@@ -161,4 +206,15 @@ class Utils {
161206
FileSync.symlink(dir, currentDir, [SYMLINK_DIR]);
162207
}
163208
}
209+
210+
public static function rmdir(dir:String) {
211+
if (!FileSystem.isDirectory(dir)) return; // TODO: error?
212+
213+
for (entry in FileSystem.readDirectory(dir)) {
214+
final path = Path.join([dir, entry]);
215+
try FileSystem.deleteFile(path) catch(_) rmdir(path);
216+
}
217+
218+
FileSystem.deleteDirectory(dir);
219+
}
164220
}

0 commit comments

Comments
 (0)