123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- package tools.hxinst;
- class Main {
- static var SYS = neko.Sys.systemName();
- static var NULL = if( SYS == "Windows" ) "NUL" else "/dev/null";
- #if xcross
- static var wnd : xcross.Winlog;
- #end
- var baseDir : String;
- var binDir : String;
- var libDir : String;
- var debug : Bool;
- function new(dbg) {
- debug = dbg;
- if( debug ) {
- libDir = "/usr/local/lib";
- binDir = "/usr/local/bin";
- } else {
- libDir = "/usr/lib";
- binDir = "/usr/bin";
- }
- baseDir = if( SYS == "Windows" ) neko.Sys.getEnv("ProgramFiles") + "/Motion-Twin" else libDir;
- }
- function newVersion(v1,v2) {
- if( v1 == null )
- return true;
- return (v1.major * 10000 + v1.minor * 100 + v1.build < v2.major * 10000 + v2.minor * 100 + v2.build);
- }
- function ask( txt ) {
- #if xcross
- return xcross.Api.confirm("Question",txt);
- #else
- var answer = null;
- while( true ) {
- neko.Lib.print(txt+" [y/n] ");
- switch( neko.io.File.stdin().readLine() ) {
- case "n": answer = false; break;
- case "y": answer = true; break;
- }
- }
- return answer;
- #end
- }
- function error( txt ) {
- #if xcross
- xcross.Api.error("Error",txt);
- #else
- neko.io.File.stderr().writeString(txt+"\n");
- #end
- throw "Installation aborted";
- }
- function display( txt ) {
- #if xcross
- wnd.log(txt);
- #else
- neko.Lib.println(txt);
- #end
- neko.Sys.sleep(0.03);
- }
- function version(v : { major : Int, minor : Int, build : Int } ) {
- return v.major+"."+v.minor+if( v.build > 0 ) "."+v.build else "";
- }
- function command( cmd ) {
- display("Execute "+cmd);
- if( neko.Sys.command(cmd) != 0 )
- error("Command '"+cmd+"' failed !");
- }
- function commandOutput( cmd ) {
- var p = try new neko.io.Process(cmd,[]) catch( e : Dynamic ) return "";
- return p.stderr.readAll().toString() + p.stdout.readAll().toString();
- }
- function run() {
- try {
- install();
- display("Installation Completed");
- #if xcross
- xcross.Api.message("Done","Installation Completed");
- #end
- } catch( e : Dynamic ) {
- display("");
- display("");
- display("ERROR = "+Std.string(e));
- display(haxe.Stack.toString(haxe.Stack.exceptionStack()));
- #if xcross
- xcross.Api.error("Error","Installation aborted");
- #end
- }
- #if xcross
- wnd.enabled = true;
- #end
- }
- function checkRights() {
- try {
- if( !neko.FileSystem.exists(baseDir) )
- neko.FileSystem.createDirectory(baseDir);
- var tmp = baseDir + "/.tmp.haxe.inst";
- var f = neko.io.File.write(tmp,true);
- f.close();
- neko.FileSystem.deleteFile(tmp);
- return true;
- } catch( e : Dynamic ) {
- #if xcross
- if( xcross.Api.authorize() )
- return false;
- #end
- var msg;
- if( SYS == "Windows" )
- msg = "You don't have administrative access on this computer,\nplease login on an administrator account.\nOnce haxe is installed, execute '"+baseDir+"\\haxesetup' on your own account.";
- else
- msg = "You don't have the rights to write in "+baseDir+", please run the installer using 'sudo'";
- try error(msg) catch( e : Dynamic ) {};
- return false;
- }
- }
- function install() {
- // CLEANUP
- var dirs = [
- "/usr/local/lib/neko",
- "/usr/local/lib/haxe",
- "/opt/neko",
- "/opt/haxe",
- ];
- for( d in dirs )
- if( !debug && neko.FileSystem.exists(d) )
- error("A previous haXe/Neko version seems to be installed in '"+d+"', please remove it first");
- if( debug )
- display("DEBUG MODE ON");
- // PROXY
- var p = neko.net.ProxyDetect.detect();
- if( p == null )
- display("No proxy found");
- else {
- display("Testing proxy "+p.host+":"+p.port);
- haxe.Http.PROXY = p;
- try {
- haxe.Http.request("http://google.com");
- } catch( e : Dynamic ) {
- display("Could not connect on Google, don't use the proxy");
- haxe.Http.PROXY = p;
- }
- }
- // GET haxe Version
- display("Getting Local haXe Version");
- var content = commandOutput("haxe");
- var r = ~/^Haxe Compiler ([0-9]+)\.([0-9]+)/;
- var haxeVersion = null;
- if( r.match(content) )
- haxeVersion = {
- major : Std.parseInt(r.matched(1)),
- minor : Std.parseInt(r.matched(2)),
- build : 0,
- };
- // GET Neko Version
- display("Getting Local Neko Version");
- var content = commandOutput("neko");
- var r = ~/^NekoVM ([0-9]+)\.([0-9]+)(\.([0-9]+))?/;
- var nekoVersion = null;
- if( r.match(content) )
- nekoVersion = {
- major : Std.parseInt(r.matched(1)),
- minor : Std.parseInt(r.matched(2)),
- build : Std.parseInt(r.matched(4))
- };
- // GET haXe files list
- display("Getting Latest haXe Version");
- var haxeFile = null;
- var r = ~/^haxe-([0-9]+)\.([0-9]+)(-win|-linux|-osx)(\.zip|\.tar\.gz)$/;
- for( f in haxe.Http.request("http://haxe.org/wiki/latest").split("\n") )
- if( r.match(f) ) {
- var pf = r.matched(3);
- switch( SYS ) {
- case "Windows": if( pf != "-win" ) continue;
- case "Linux": if( pf != "-linux" ) continue;
- case "Mac": if( pf != "-osx" ) continue;
- default: continue;
- }
- haxeFile = {
- file : f,
- version : {
- major : Std.parseInt(r.matched(1)),
- minor : Std.parseInt(r.matched(2)),
- build : 0,
- },
- };
- break;
- }
- if( haxeFile == null )
- error("No haXe File found for your plaform");
- // GET Neko files list
- display("Getting Latest Neko Version");
- var nekoFile = null;
- var r = ~/^neko-([0-9]+)\.([0-9]+)(\.([0-9]+))?(-win|-linux|-osx)(\.zip|\.tar\.gz)$/;
- for( f in haxe.Http.request("http://nekovm.org/latest.n").split("\n") )
- if( r.match(f) ) {
- var pf = r.matched(5);
- switch( SYS ) {
- case "Windows": if( pf != "-win" ) continue;
- case "Linux": if( pf != "-linux" ) continue;
- case "Mac": if( pf != "-osx" ) continue;
- default: continue;
- }
- nekoFile = {
- file : f,
- version : {
- major : Std.parseInt(r.matched(1)),
- minor : Std.parseInt(r.matched(2)),
- build : Std.parseInt(r.matched(4)),
- }
- };
- break;
- }
- if( nekoFile == null )
- error("No haXe File found for your plaform");
- // ASK QUESTIONS IF OK TO INSTALL
- var needHaxe = newVersion(haxeVersion,haxeFile.version);
- var needNeko = newVersion(nekoVersion,nekoFile.version);
- if( !needHaxe && !needNeko ) {
- if( !ask("Both your haXe and Neko versions are up-to-date, do you want to reinstall everything ?") )
- throw "Installation Aborted";
- needHaxe = true;
- needNeko = true;
- } else {
- var txt = "";
- if( needNeko ) {
- txt += "Neko "+version(nekoFile.version);
- if( needHaxe )
- txt += " and ";
- }
- if( needHaxe )
- txt += "haXe "+version(haxeFile.version);
- if( !ask("Do you want to install "+txt+" ?") )
- error("Installation Aborted");
- }
- // DOWNLOAD
- if( needNeko )
- download("http://nekovm.org/_media",nekoFile.file);
- if( needHaxe )
- download("http://haxe.org/file",haxeFile.file);
- // INSTALL
- if( needNeko ) {
- copy(nekoFile.file,true);
- installNeko();
- }
- if( needHaxe ) {
- copy(haxeFile.file,false);
- installHaxe();
- }
- }
- static function logProgress( txt ) {
- #if xcross
- wnd.logProgress(txt);
- #else
- neko.Lib.print(txt+"\r");
- #end
- }
- function download( url, file ) {
- if( neko.FileSystem.exists(file) ) {
- display("Using local version of "+file+", skipping download");
- return;
- }
- var str = new haxe.io.BytesOutput();
- var progress = new Progress(str);
- progress.update = function() {
- var p = progress.cur * 100 / progress.max;
- p = Std.int(p * 10) / 10;
- logProgress("Downloading "+file+" ("+p+"%)");
- };
- var h = new haxe.Http(url+"/"+file);
- var me = this;
- h.onError = function(e) {
- me.error(Std.string(e));
- };
- logProgress("Downloading "+file+"...");
- h.customRequest(false,progress);
- #if xcross
- wnd.log("");
- #else
- neko.Lib.print("\n");
- #end
- var f = neko.io.File.write(file,true);
- f.write(str.getBytes());
- f.close();
- }
- function unzip( file ) {
- var ch = neko.io.File.read(file,true);
- var entries = if( neko.io.Path.extension(file) == "zip" ) neko.zip.Reader.readZip(ch) else neko.zip.Reader.readTar(ch,true);
- ch.close();
- return entries;
- }
- function copy( file, isNeko ) {
- var data = unzip(file);
- var dir = baseDir + "/" + if( isNeko ) "neko" else "haxe";
- if( !neko.FileSystem.exists(dir) )
- neko.FileSystem.createDirectory(dir);
- if( !isNeko ) {
- try {
- removeRec(dir+"/std");
- } catch( e : Dynamic ) {
- }
- }
- for( f in data ) {
- var path = f.fileName.split("/");
- path.shift(); // base directory
- if( path[path.length-1] == "" ) {
- path.pop();
- if( path.length == 0 )
- continue;
- var ddir = dir+"/"+path.join("/");
- display("Installing directory "+path.join("/"));
- if( !neko.FileSystem.exists(ddir) )
- neko.FileSystem.createDirectory(ddir);
- continue;
- }
- var filename = dir + "/" + path.join("/");
- var ch = neko.io.File.write(filename,true);
- ch.write(neko.zip.Reader.unzip(f));
- ch.close();
- if( SYS != "Windows" ) {
- var exe = neko.io.Path.extension(filename) == "";
- neko.Sys.command("chmod "+(if( exe ) 755 else 644)+" "+filename);
- }
- }
- }
- function link( dir, file, dest ) {
- command("rm -rf "+dest+"/"+file);
- command("ln -s "+baseDir+"/"+dir+"/"+file+" "+dest+"/"+file);
- }
- function installNeko() {
- if( SYS == "Windows" )
- return;
- var so = if( SYS == "Mac" ) ".dylib" else ".so";
- link("neko","neko",binDir);
- link("neko","nekoc",binDir);
- link("neko","nekotools",binDir);
- link("neko","libneko"+so,libDir);
- }
- function installHaxe() {
- if( SYS == "Windows" ) {
- command('"'+baseDir+'/haxe/haxesetup" -silent');
- return;
- }
- link("haxe","haxe",binDir);
- link("haxe","haxelib",binDir);
- link("haxe","haxedoc",binDir);
- // HAXELIB setup
- var haxelib = baseDir + "/haxe/lib";
- if( !neko.FileSystem.exists(haxelib) ) {
- neko.FileSystem.createDirectory(haxelib);
- neko.Sys.command("chmod 777 "+haxelib);
- }
- }
- function removeRec( file ) {
- if( !neko.FileSystem.isDirectory(file) ) {
- neko.FileSystem.deleteFile(file);
- return;
- }
- for( f in neko.FileSystem.readDirectory(file) )
- removeRec(file+"/"+f);
- neko.FileSystem.deleteDirectory(file);
- }
- static function main() {
- var debug = neko.Sys.getEnv("INST_DEBUG") != null;
- var i = new Main(debug);
- if( !i.checkRights() )
- return;
- #if xcross
- wnd = new xcross.Winlog("haXe Installer");
- wnd.button = "Exit";
- wnd.enabled = false;
- wnd.onClick = function() {
- neko.vm.Ui.stopLoop();
- };
- neko.vm.Thread.create(i.run);
- neko.vm.Ui.loop();
- #else
- i.run();
- #end
- }
- }
- // --------- TOOLS --------------
- class Progress extends haxe.io.Output {
- var o : haxe.io.Output;
- public var cur : Int;
- public var max : Int;
- public function new(o) {
- this.o = o;
- cur = 0;
- }
- public dynamic function update() {
- }
- public override function writeByte(c) {
- o.writeByte(c);
- cur++;
- update();
- }
- public override function writeBytes(s,p,l) {
- var r = o.writeBytes(s,p,l);
- cur += r;
- update();
- return r;
- }
- public override function close() {
- super.close();
- o.close();
- }
- public override function prepare(m) {
- max = m;
- }
- }
|