UNPKG

nyx_server

Version:

Node内容发布

293 lines (261 loc) 11.2 kB
/* global process */ /** * 项目发布命令,该命令将项目信息注册到数据库 */ var projectFn = require("../core/Project"); var Project = require("../core/ProjectLoader").Project; var build = require("./build"); var cdn = require("./cdn"); var gencid = require("./gencid"); var config = require("../config/default-config"); var cmd = require("../core/utils/cmd"); var path = require("path"); var log4js = require("log4js"); var log = log4js.getLogger("Publish"); var Promise = require("bluebird"); var fs = Promise.promisifyAll(require("fs")); var glob = require("glob"); var buildUtil = require("./lib/build/utils"); var Optimist = require('../optimist/optimist'); var help = require('../optimist/help'); var optimist = new Optimist(); optimist .info('项目版本发布') .usage('nyx publish [--version v]') .define("version").type("string", "number").describe('项目版本号').require(true) .define("message").type("string").describe('描述信息').require(true); var argv = optimist.getArgv(); var Publish = function(){}; Publish.prototype.execute = function(){ var argvAnalysis = optimist.analysis; if (argvAnalysis.options.hasOwnProperty('help') || argvAnalysis.shortKeys.hasOwnProperty('h')) { help.detailed(optimist); process.exit(1); } var version = argv.version; //发布的版本号 var message = argv.message; //描述信息 if(!version || !message){ help.detailed(optimist); process.exit(1); } var project = new Project(process.cwd()); //1、替换碎片id, 创建碎片实例(配置)数据 return gencid.execute1(project).then(function(){ return build.execute1("*"); //2、build }).then(function(){ return adjustProjectVersion(version); }).then(function(){ return adjustVersion(version); //3、修改版本号,重新计算文件名称,修改文件依赖 }).then(function(){ return cdn.execute1("*"); //上传cdn }).then(function(){ return commitLocalFile(message); //提交本地 }).then(function(){ return commitLocalVersion(version); }).then(function(){ return commitRemote().catch(function(err){ deleteLocalTag(version); throw err; }); }).then(function(){ log.info("publish处理完成"); return true; }).catch(function(err){ log.error(err); }); }; function deleteLocalTag(version){ return cmd('git', ['tag', "-d" , version]); } /** * 创建本地版本 * @param version 版本 */ function commitLocalVersion(version){ return cmd("git" , ["tag"]).then(function(data){ var tags = data[0].match(/.*[\r|\n]/g); if(!tags) return; for(var i=0; i<tags.length; i++){ var tag = tags[i].replace(/[\r|\n]/g ,""); if(tag == version){ throw new Error("版本"+version+"已经存在"); } } return true; }).then(function(){ return cmd('git', ['tag', version]); }); } function commitLocalFile(message){ return cmd("git" , ["add" , "." ,"-A"]).then(function(){ return cmd('git', ['commit', '-a' , '--m' , '"'+message+'"']).then( function(data){ return []; //提交成功 }, function(data){ //提交失败。 var stdout = data.stdout; if(stdout.match(/\s*nothing\s*to\s*commit\s*/ig)){ //git commit当没有数据可以提交是返回的code==1 //这里需要处理没有数据提交的情况,如果是没有数据提交则返回正常。 return []; } throw new Error(data); }, function(data){ //回显通知 return []; } ); }); } function commitRemote(){ return cmd('git' , ['status']).then(function(result){ var regx = /\s*On\s*branch\s*(\S*)\s*.*[\r|n]*/i; var matchs = regx.exec(result); if(typeof matchs != 'undefined' && matchs.length && matchs.length>0){ console.log('push to branch '+matchs[1]); return cmd('git', ['push', '--tag' , '--progress' , 'origin' , matchs[1]]); } console.log('waring : no find branch , use default set . please confirm.'); return cmd('git', ['push', '--tag' , '--progress' , 'origin']); }); } function adjustProjectVersion(version){ var packageFile = path.join(process.cwd() , "package.json"); var packageInfo = require(packageFile); packageInfo.version = version; return new Promise(function(resolve , reject){ fs.writeFile(packageFile , JSON.stringify(packageInfo) , function(err){ if(err){ reject(err); }else{ resolve(true); } }); }); } var versionString = "@version@"; var versionPattern = new RegExp(versionString); function adjustVersion(version){ var project = new Project(process.cwd()); var allpromise = []; var p= projectFn.loadTemplates(project).map(function(template){ var basePath = template.basePath; return _adjustVersion(basePath , version); }); allpromise.push(p); p= projectFn.loadChips(project).map(function(chip){ var basePath = chip.basePath; return _adjustVersion(basePath , version); }); allpromise.push(p); return Promise.all(allpromise); } /** * 修改所有js文件中的@version@为真实的版本号 */ function _adjustVersion(basePath , version){ return new Promise(function(resolve , reject){ var patterns = path.join(basePath , config.DIST_DIR , "**/!(*.min).js"); glob(patterns , function(err , files){ var p =Promise.map(files , function(file){ log.info("adjustVersion file :" + file); return new Promise(function(resolve , reject){ fs.readFile(file , "utf-8" ,function(err , data){ var haschange = false; data = data.replace(/(@version@)/ , function(match , oldversion , offset , input){ haschange = true; return version; }); if(haschange){ var ret = {filePath : file , content : data}; resolve(ret); }else{ resolve(null); } }); }); }).filter(function(result){ return result != null; }).map(function(result){ var content = result.content; var oldFilePath = result.filePath; var suffix = buildUtil.md5Suffix(content,"md5","hex"); var extname = path.extname(oldFilePath); var baseName = path.basename(oldFilePath , extname); var oldMinFilePath = path.dirname(oldFilePath)+'/'+ baseName+".min"+extname; var appPromise = []; appPromise.push(fs.unlinkAsync(oldFilePath).then(function(err){ if(err){log.error("unlinkAsync "+err);} })); appPromise.push(fs.unlinkAsync(oldMinFilePath).then(function(err){ if(err){log.error("unlinkAsync "+err);} })); baseName = buildUtil.getWithoutMd5Suffix(baseName); //去除文件MD5后缀 var fileNamePrefix = path.dirname(oldFilePath)+'/'+ baseName+'_'+suffix; //处理压缩文件 var compressContent = buildUtil.compressContent(content); var newCompressedFileName = fileNamePrefix+'.min'+extname; //压缩的文件名 var newFileName = fileNamePrefix+extname; //未压缩的文件名 appPromise.push(fs.writeFileAsync(newFileName , content).then(function(err){ if(err){log.error("writeFileAsync ,"+err);} })); appPromise.push(fs.writeFileAsync(newCompressedFileName , compressContent).then(function(err){ if(err){log.error("writeFileAsync ,"+err);} })); return Promise.all(appPromise).then(function(){ return {"originMinFile" : oldMinFilePath , 'newMinFile':newCompressedFileName}; }); }).map(function(compareMinFiles){ //console.log(compareMinFiles); //替换模板中引用的地址 var oldBasename = path.basename(compareMinFiles.originMinFile); var newBasename = path.basename(compareMinFiles.newMinFile); //console.log(oldBasename , newBasename); return new Promise(function(resolve ,reject){ glob(path.join(basePath , config.DIST_DIR , "**/*.ejs") , function(err , files){ var allpromise = []; files.forEach(function(file){ allpromise.push(fs.readFileAsync(file , "utf-8").then(function(content){ content = content.replace(oldBasename , newBasename); fs.writeFileAsync(file , content).then(function(err){ return true; }); })); }); resolve(Promise.all(allpromise)); }); }); }); resolve(p); }); }); } function getProjectInfo(){ var packagePath = path.join(process.cwd() , "package.json"); return new Promise(function(resolve , reject){ fs.exists(packagePath , function(exists){ if(!exists){ resolve(null); }else{ fs.readFile(packagePath , "utf-8" , function(err , data){ if(err){ log.error(err); resolve(null); }else{ var v = JSON.parse(data); resolve(v); } }); } }); }); } Publish.prototype.showhelp = function(){ help.detailed(optimist); }; Publish.prototype.optimist = function() { return optimist; }; module.exports = new Publish();