tch-command-release
Version:
tch release command.
344 lines (319 loc) • 11.6 kB
JavaScript
/*
* fis
* http://fis.baidu.com/
*/
;
var port;
var hostname;
var diffHashTemp = [];
var hashTemp = {};
var hashTempPath = "./.hashTemp";
var diffHashPath = "./.diffTemp";
var hashT;
var oldHashData;
if(fis.util.exists(hashTempPath)){
oldHashData = fis.util.readJSON(hashTempPath);
}
var defaultHostname = (function(){
var net = require('os').networkInterfaces();
for(var key in net){
if(net.hasOwnProperty(key)){
var details = net[key];
if(details && details.length){
for(var i = 0, len = details.length; i < len; i++){
var ip = String(details[i].address).trim();
if(ip && /^\d+(?:\.\d+){3}$/.test(ip) && ip !== '127.0.0.1'){
return ip;
}
}
}
}
}
return '127.0.0.1';
})();
function upload(receiver, to, release, content, subpath, callback){
fis.util.upload(
//url, request options, post data, file
receiver, null, { to : to + release }, content, subpath,
function(err, res){
if(err || res.trim() != '0'){
fis.log.error('upload file [' + subpath + '] to [' + to +
'] by receiver [' + receiver + '] error [' + (err || res) + ']');
} else {
var time = '[' + fis.log.now(true) + ']';
process.stdout.write(
' - '.green.bold +
time.grey + ' ' +
subpath.replace(/^\//, '') +
' >> '.yellow.bold +
to + release +
'\n'
);
callback();
}
}
);
}
function ftpUpload(dest, md5, release, content, file, callback){
var output = dest.to,
ftpConf = dest,
serverConf = ftpConf.server;
if(!serverConf){
fis.log.error("ftp服务器的配置不存在!");
return;
}
var FtpDeploy = require('ftp-deploy'),
merge = require("merge");
var ftpDeploy = new FtpDeploy();
var defaultConf = {
exclude: ['.git', '.idea', 'tmp/*']
};
var config = merge(defaultConf,serverConf);
var server = fis.config.data.server,
path = fis.util.realpath(ftpConf.from);
config.localRoot = path;
config.remoteRoot= ftpConf.to;
//config.continueOnError = true;
ftpDeploy.deploy(config, function(err) {
if (err) console.log(err)
else console.log('finished');
});
// ftpDeploy.on('uploading', function(data) {
// data.totalFileCount; // total file count being transferred
// data.transferredFileCount; // number of files transferred
// data.percentComplete; // percent as a number 1 - 100
// data.filename; // filename being uploaded
// data.relativePath; // relative path to file being uploaded from local root location
// });
ftpDeploy.on('upload-error', function (data) {
console.log(data.err); // data will also include filename, relativePath, and other goodies
});
}
function deliver(output, md5, release, content, file, callback){
if(!release){
fis.log.error('unable to get release path of file['
+ file.realpath
+ ']: Maybe this file is neither in current project or releasable');
}
if(fis.util.exists(output) && !fis.util.isDir(output)){
fis.log.error('unable to deliver file['
+ file.realpath + '] to dir['
+ output + ']: invalid output dir.');
}
var target;
if(md5 == 0 || !file.useHash){
target = fis.util(output, release);
fis.util.write(target, content);
} else if(md5 == 1){
target = fis.util(output, file.getHashRelease(release));
fis.util.write(target, content);
} else {
if(file.useHash){
target = fis.util(output, file.getHashRelease(release));
fis.util.write(target, content);
}else{
target = fis.util(output, release);
fis.util.write(target, content);
}
}
callback();
}
function replaceFrom(path, from, subOnly){
if(path.indexOf(from) === 0){
from = from.replace(/\/$/, '');
if(subOnly){
return path.substring(from.length);
} else {
var index = from.lastIndexOf('/');
if(index < 1){
return path;
} else {
return path.substring(index);
}
}
}
return path;
}
function deploy(dest, file, callback){
if(file.release){
var release = replaceFrom(file.release, dest.from, dest.subOnly);
var content = file.getContent();
var charset = file.charset;
if(file.isText() && content.length){
if(dest.replace && dest.replace.from){
var reg = dest.replace.from;
if(typeof reg === 'string'){
reg = new RegExp(fis.util.escapeReg(reg), 'g');
} else if(!(reg instanceof RegExp)){
fis.log.error('invalid deploy.replace.from [' + reg + ']');
}
content = content.replace(reg, dest.replace.to);
}
if(dest.opt.live && file.isHtmlLike){
hostname = hostname || fis.config.get('livereload.hostname', defaultHostname);
port = port || fis.config.get('livereload.port', 8132);
var code = '<script type="text/javascript" charset="utf-8" src="http://' + hostname + ':' + port + '/livereload.js"></script>';
content = content.replace(/"(?:[^\\"\r\n\f]|\\[\s\S])*"|'(?:[^\\'\n\r\f]|\\[\s\S])*'|(<\/body>|<!--livereload-->)/ig, function(m, $1){
if($1){
m = code + m;
}
return m;
});
}
if (file.isHtmlLike) {
content = content.replace(/<!--livereload-->/ig, '');
}
if(charset !== 'utf8' && charset !== 'utf-8'){
content = fis.util.toEncoding(content, charset);
}
}
if(dest.receiver){
if(!file.useHash || dest.opt.md5 != 1){
upload(dest.receiver, dest.to, release, content, file.subpath, callback);
}
if(file.useHash && dest.opt.md5 > 0){
upload(dest.receiver, dest.to, file.getHashRelease(release), content, file.subpath, callback);
}
} else {
if(dest.method === "ftp"){
dest.to = dest.to.replace(dest.root,"");
ftpUpload(dest, dest.opt.md5, release, content, file, callback);
}else{
//匹配打包的图片和脚本
if(/\/\d+\.\d+\.\d+\/|\/img\/.*/.test(release)){
if(dest.opt.md5){
var hash = file.getHash();
if(oldHashData && oldHashData[release] !== hash || !oldHashData){
//如果是匹配图片
var _diffRelease;
if(/\/img\/.*/.test(release)){
if(release.indexOf("_"+hash)===-1){
_diffRelease = release.replace(/\.\w+$/,function($0){
return "_"+hash+$0;
})
}
}
diffHashTemp.push(_diffRelease||release);
}
hashTemp[release] = hash;
if(hashT) {
clearTimeout(hashT);
}
hashT = setTimeout(function(){
fis.util.write(diffHashPath,JSON.stringify(diffHashTemp));
fis.util.write(hashTempPath,JSON.stringify(hashTemp));
},200);
}
}else{
hashTemp[release] = hash;
if(hashT) {
clearTimeout(hashT);
}
hashT = setTimeout(function(){
fis.util.write(diffHashPath,JSON.stringify(diffHashTemp));
fis.util.write(hashTempPath,JSON.stringify(hashTemp));
},200);
}
deliver(dest.to, dest.opt.md5, release, content, file, callback);
}
}
} else {
fis.log.error('unreleasable file [' + file.realpath + ']');
}
}
function normilize(str){
str = (str || '').trim();
if(str[0] !== '/'){
str = '/' + str;
}
return str.replace(/\/$/, '') + '/';
}
var serverRoot = (function(){
var key = 'FIS_SERVER_DOCUMENT_ROOT';
if(process.env && process.env[key]){
var path = process.env[key];
if(fis.util.exists(path) && !fis.util.isDir(path)){
fis.log.error('invalid environment variable [' + key + '] of document root [' + path + ']');
}
return path;
} else {
return fis.project.getTempPath('www');
}
})();
var cwd = process.cwd();
function factory(dest, opt, root){
var ret = fis.util.clone(dest);
ret.opt = opt;
ret.root = ret.root || root;
ret.from = normilize(ret.from);
if(ret.to[0] === '.' && ret.method !== "ftp"){
ret.to = fis.util(cwd + '/' + ret.to);
} else if(/^output\b/.test(ret.to)){
ret.to = fis.util(root + '/' + ret.to);
} else if(ret.to === 'preview'){
ret.to = serverRoot;
} else {
ret.to = fis.util(ret.to);
}
return ret;
}
var tasks = [];
var running = 0;
function doTask(){
if(tasks.length){
if(running < exports.MAX_TASK_SIZE){
var task = tasks.shift();
running++;
deploy(task.dest, task.file, function(){
running--;
setTimeout(doTask, 0);
});
} else {
setTimeout(doTask, 1000);
}
} else {
running = 0;
exports.done();
}
}
var exports = module.exports = function(opt, collection,diffCollection){
var settings = fis.config.get('deploy', {});
var root = fis.project.getProjectPath();
var dests = [],
dest = opt.dest;
if(typeof dest === "string"){
fis.log.error("目录配置已经修改,请调整tch-conf里的配置");
return;
}
if(!dest.to){
if(
d === 'preview' || //release to preivew
/^(?:\.|output\b)/.test(d) || //release to output
fis.util.isAbsolute(d) //absolute path
){
dest.to = d;
} else {
fis.log.error('invalid deploy destination options [' + d + ']');
}
}
dests.push(factory(dest, opt, root));
fis.util.map(collection, function(subpath, file){
//console.log(file.release);
dests.forEach(function(d){
var from = d.from;
if(from.indexOf("output")>-1){
from = from.split("output")[1];
};
if(file.release &&
file.release.indexOf(from) === 0 && //relate to replaceFrom
fis.util.filter(file.release, d.include, d.exclude)
){
tasks.push({dest : d, file : file });
}
});
});
doTask();
};
//for callback
exports.done = function(){};
exports.MAX_TASK_SIZE = 5;