diff --git a/lib/util.js b/lib/util.js index 2a1a030..7601b3b 100644 --- a/lib/util.js +++ b/lib/util.js @@ -11,7 +11,7 @@ var fs = require('fs'), Url = require('url'), _exists = fs.existsSync || pth.existsSync, toString = Object.prototype.toString, - iconv, tar; + iconv; var IS_WIN = process.platform.indexOf('win') === 0; @@ -90,13 +90,6 @@ function getIconv(){ return iconv; } -function getTar(){ - if(!tar){ - tar = require('tar'); - } - return tar; -} - var _ = module.exports = function(path){ var type = typeof path; if(arguments.length > 1) { @@ -372,7 +365,7 @@ _.isUtf8 = function(bytes) { i += 1; continue; } - + if((// non-overlong 2-byte (0xC2 <= bytes[i] && bytes[i] <= 0xDF) && (0x80 <= bytes[i+1] && bytes[i+1] <= 0xBF) @@ -380,7 +373,7 @@ _.isUtf8 = function(bytes) { i += 2; continue; } - + if( (// excluding overlongs bytes[i] == 0xE0 && @@ -401,7 +394,7 @@ _.isUtf8 = function(bytes) { i += 3; continue; } - + if( (// planes 1-3 bytes[i] == 0xF0 && @@ -548,7 +541,7 @@ _.del = function(rPath, include, exclude){ if(/^(?:\w:)?\/$/.test(path)){ fis.log.error('unable to delete directory [' + rPath + '].'); } - + if(stat.isDirectory()){ fs.readdirSync(path).forEach(function(name){ if(name != '.' && name != '..') { @@ -720,6 +713,7 @@ _.parseUrl = function(url, opt){ opt = opt || {}; url = Url.parse(url); var ssl = url.protocol === 'https:'; + opt.protocol = url.protocol; opt.host = opt.host || opt.hostname || ((ssl || url.protocol === 'http:') ? url.hostname : 'localhost'); @@ -730,6 +724,76 @@ _.parseUrl = function(url, opt){ return opt; }; +_.unPack = function(source, dest, res, callback) { + var packageExt = fis.config.get('system.packageExt', '.tar'); + switch (packageExt) { + case '.tar': + var tar = require('tar'); + _.unPack = function (source, dest, res, callback) { + fs.createReadStream(source) + .pipe(tar.Extract({path: dest})) + .on('error', function (err) { + if (callback) { + callback(err); + } else { + fis.log.error('extract tar file [' + source + '] fail, error [' + err + ']'); + } + }) + .on('end', function () { + if (callback && (typeof callback(null, source, res) === 'undefined')) { + fs.unlinkSync(source); + } + }); + }; + break; + case '.tar.gz': + var targz = require('tar.gz'); + _.unPack = function (source, dest, res, callback) { + //delay 1s before extract to make sure it works + setTimeout(function(){ + new targz().extract(source, dest, function (err) { + if (err) { + if (callback) { + callback(err); + } else { + fis.log.error('extract tar.gz file [' + source + '] fail, error [' + err + ']'); + } + } + if (callback && (typeof callback(null, source, res) === 'undefined')) { + fs.unlinkSync(source); + } + }, 1000); + }) + }; + break; + case '.zip': + var unzip = require('unzip'); + _.unPack = function (source, dest, res, callback) { + fs.createReadStream(source) + .pipe(unzip.Extract({path: dest})) + .on('error', function (err) { + if (callback) { + callback(err); + } else { + fis.log.error('extract zip file [' + source + '] fail, error [' + err + ']'); + } + }) + .on('close', function () { + if (callback && (typeof callback(null, source, res) === 'undefined')) { + fs.unlinkSync(source); + } + }); + }; + break; + default: + fis.log.error('no suitable unpack tool'); + return; + } + + _.unPack(source, dest, res, callback); + +}; + _.download = function(url, callback, extract, opt){ opt = _.parseUrl(url, opt || {}); var http = opt.protocol === 'https:' ? require('https') : require('http'), @@ -752,35 +816,26 @@ _.download = function(url, callback, extract, opt){ req = http.request(opt, function(res){ var status = res.statusCode; res - .on('data', function(chunk){ - writer.write(chunk); - }) - .on('end', function(){ - if(status >= 200 && status < 300 || status === 304){ - if(extract){ - fs - .createReadStream(tmp) - .pipe(getTar().Extract({ path : extract })) - .on('error', function(err){ - if(callback){ - callback(err); - } else { - fis.log.error('extract tar file [' + tmp + '] fail, error [' + err + ']'); - } - }) - .on('end', function(){ - if(callback && (typeof callback(null, tmp, res) === 'undefined')){ - fs.unlinkSync(tmp); - } - }); - } else if(callback && (typeof callback(null, tmp, res) === 'undefined')){ - fs.unlinkSync(tmp); - } - } else { - http_err_handler(status); - } - }) - .on('error', http_err_handler); + res + .on('data', function(chunk){ + writer.write(chunk); + }) + .on('end', function(){ + if(status >= 200 && status < 300 || status === 304){ + if(extract){ + _.unPack(tmp, extract, res, callback); + } else if(callback && (typeof callback(null, tmp, res) === 'undefined')){ + fs.unlinkSync(tmp); + } + } else if(status >= 300 && status < 400 && res.headers){ + var url = res.headers.location; + _.download(url, callback, extract); + } + else { + http_err_handler(status); + } + }) + .on('error', http_err_handler); }); req.on('error', http_err_handler); if(data){ @@ -810,12 +865,12 @@ _.upload = function(url, opt, data, content, subpath, callback){ collect.push(endl); collect.push(content); collect.push('--' + boundary + '--' + endl); - + var length = 0; collect.forEach(function(ele){ length += ele.length; }); - + opt = opt || {}; opt.method = opt.method || 'POST'; opt.headers = { @@ -854,7 +909,8 @@ _.upload = function(url, opt, data, content, subpath, callback){ _.install = function (name, version, opt){ version = version === '*' ? 'latest' : ( version || 'latest' ); var remote = opt.remote.replace(/^\/$/, ''); - var url = remote + '/' + name + '/' + version + '.tar'; + var ext = fis.config.get('system.packageExt', '.tar'); + var url = remote + '/' + name + '/' + version + ext; var extract = opt.extract || process.cwd(); if(opt.before){ opt.before(name, version); diff --git a/package.json b/package.json index 4fa8e54..123aaaa 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,8 @@ }, "dependencies": { "tar": "0.1.17", + "tar.gz":"0.1.1", + "unzip": "0.1.11", "iconv-lite": "0.2.10" }, "devDependencies": {