| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508 |
- /*
- * Copyright (C)2005-2012 Haxe Foundation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
- package tools.hxinst;
- class Main {
- static var SYS = 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" ) {
- // use C:/ for Vista, Win7
- var baseDir = (Sys.getEnv("ALLUSERSPROFILE") == "C:\\ProgramData") ? "C:" : Sys.getEnv("ProgramFiles");
- baseDir + "/HaxeFoundation";
- } 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 ) {
- Sys.print(txt+" [y/n] ");
- switch( Sys.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
- Sys.stderr().writeString(txt+"\n");
- #end
- throw "Installation aborted";
- }
- function display( txt ) {
- #if xcross
- wnd.log(txt);
- #else
- Sys.println(txt);
- #end
- Sys.sleep(0.03);
- }
- function version(v : { major : Int, minor : Int, build : Int }, twoDigitMinor ) {
- var min = twoDigitMinor && v.minor < 10 ? "0"+v.minor : Std.string(v.minor);
- return v.major+"."+min+if( v.build > 0 ) "."+v.build else "";
- }
- function command( cmd ) {
- display("Execute "+cmd);
- if( Sys.command(cmd) != 0 )
- error("Command '"+cmd+"' failed !");
- }
- function commandOutput( cmd ) {
- var p = try new sys.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.CallStack.toString(haxe.CallStack.exceptionStack()));
- #if xcross
- xcross.Api.error("Error","Installation aborted");
- #end
- }
- #if xcross
- wnd.enabled = true;
- #end
- }
- function checkRights() {
- try {
- if( !sys.FileSystem.exists(baseDir) )
- sys.FileSystem.createDirectory(baseDir);
- var tmp = baseDir + "/.tmp.haxe.inst";
- var f = sys.io.File.write(tmp,true);
- f.close();
- sys.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;
- }
- }
- var cacheResult : Null<Bool>;
- function is64() {
- if( cacheResult != null )
- return cacheResult;
- var p = new sys.io.Process("uname", ["-m"]);
- var ret = p.stdout.readAll().toString();
- p.exitCode();
- cacheResult = ret.indexOf("x86_64") != -1;
- return cacheResult;
- }
- function install() {
- // CLEANUP
- var dirs = [
- "/usr/local/lib/neko",
- "/usr/local/lib/haxe",
- "/opt/neko",
- "/opt/haxe",
- "c:/motion-twin",
- "c:/program files/motion-twin",
- ];
- for( d in dirs )
- if( !debug && sys.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("Testing proxy "+p.host+":"+p.port);
- haxe.Http.PROXY = p;
- try {
- haxe.Http.requestUrl("http://google.com");
- } catch( e : Dynamic ) {
- display("Could not connect on Google, trying with no proxy");
- haxe.Http.PROXY = null;
- }
- }
- // GET haxe Version
- display("Getting Local Haxe Version");
- var content = commandOutput("haxe");
- var r = ~/^Haxe Compiler ([0-9]+)\.([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 : Std.parseInt(r.matched(4))
- };
- if( haxeVersion.build == null ) haxeVersion.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.requestUrl("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|-linux64)(\.zip|\.tar\.gz)$/;
- for( f in haxe.Http.requestUrl("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"+(is64() ? "64":"") ) 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,false);
- if( needHaxe )
- txt += " and ";
- }
- if( needHaxe )
- txt += "Haxe "+version(haxeFile.version,true);
- 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
- Sys.print(txt+"\r");
- #end
- }
- function download( url, file ) {
- if( sys.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
- Sys.print("\n");
- #end
- var f = sys.io.File.write(file,true);
- f.write(str.getBytes());
- f.close();
- }
- function unzip( file ) {
- var ch = sys.io.File.read(file,true);
- var entries;
- if( haxe.io.Path.extension(file) == "zip" )
- entries = haxe.zip.Reader.readZip(ch);
- else {
- entries = new List();
- for( f in new format.tgz.Reader(ch).read() )
- entries.add({
- fileName : f.fileName,
- fileTime : f.fileTime,
- fileSize : f.fileSize,
- data : f.data,
- dataSize : f.data.length,
- compressed : false,
- crc32 : null,
- });
- }
- ch.close();
- return entries;
- }
- function copy( file, isNeko ) {
- var data = unzip(file);
- var dir = baseDir + "/" + if( isNeko ) "neko" else "haxe";
- if( !sys.FileSystem.exists(dir) )
- sys.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( !sys.FileSystem.exists(ddir) )
- sys.FileSystem.createDirectory(ddir);
- continue;
- }
- var filename = dir + "/" + path.join("/");
- var ch = sys.io.File.write(filename,true);
- ch.write(haxe.zip.Reader.unzip(f));
- ch.close();
- if( SYS != "Windows" ) {
- var exe = haxe.io.Path.extension(filename) == "";
- 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( !sys.FileSystem.exists(haxelib) ) {
- sys.FileSystem.createDirectory(haxelib);
- Sys.command("chmod 777 "+haxelib);
- }
- }
- function removeRec( file ) {
- if( !sys.FileSystem.isDirectory(file) ) {
- sys.FileSystem.deleteFile(file);
- return;
- }
- for( f in sys.FileSystem.readDirectory(file) )
- removeRec(file+"/"+f);
- sys.FileSystem.deleteDirectory(file);
- }
- static function main() {
- var debug = 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;
- }
- }
|