aics
Version:
424 lines (387 loc) • 15.4 kB
JavaScript
var path = require('path');
var util = require('util');
var fs = require('fs');
var cjson = require('cjson');
var request = require('request');
var qs = require('querystring');
var unzip = require('unzip');
var walk = require('walk-promise');
var md5 = require('md5');
var archiver = require('archiver');
var readline = require('readline');
var chalk = require('chalk');
var walkSync = require('walk-sync');
var http = require('http');
var account = require('../account.json');
var argv = require('minimist')(process.argv.slice(2));
var Tools = require('../lib/tools');
var aicsConfig = require('../lib/config');
module.exports = ProjectManager;
function ProjectManager() {
}
var packs = {};
ProjectManager.config = function() {
var configPath = path.resolve('project.json');
if (!fs.existsSync(configPath)) {
console.log("not in a aics project ,frist run aics project init [name] ");
process.exit(1);
}
var json = cjson.load(configPath);
if (!json.prototype) {
console.log("project use some prototype");
process.exit(1);
}
if (!json.name) {
console.log("project need a name");
process.exit(1);
}
if (!json.version) {
console.log("project need a version");
process.exit(1);
}
if (!json.packages) {
console.log("project some packages");
process.exit(1);
}
return json;
}
/*
*简化了aics项目的构成合并项目和包的概念
*.aics 文件夹存放包描述文件列表
*.aics/tmp 临时目录用来打包或下载文件
*.aics-project.json 项目描述文件
*--0.0.x 版本用来管理项目的包依赖关系
* ./aics/example.json 包描述文件
*/
ProjectManager.init = function(args) {
var name;
if (args.length < 4 || (typeof argv.e == "boolean") || (typeof argv.p == "boolean")) {
console.log('\n' + chalk.red.bold('参数错误!') + '\n');
console.log(chalk.green.bold('Usage'));
console.log("init [option] <string> ");
console.log('\n' + chalk.green.bold('option:'));
console.log("[null] 创建aics package项目");
console.log(" -p 创建AICS project项目");
console.log(" -e 根据项目模版创建项目 访问http://codedepot.fami2u.com/projects 获取更多项目模版");
console.log('\n' + chalk.green.bold('example:'));
console.log("aics init fami2u 创建一个名称为fami2u的代码包");
console.log("aics init -p fami2u 创建一个名称为fami2u的项目");
console.log("aics init -e fami2u:example 根据项目模版创建项目 访问http://codedepot.fami2u.com/projects 获取更多项目模版");
return;
}
if (argv.e) {
var param = {
"project": argv.e
};
if (argv.e.split(":").length > 1) {
name = argv.e.split(":").pop();
} else {
console.log("\n项目名输入错误.\n");
return;
}
request(aicsConfig.host + "/project/info?" + qs.stringify(param), function(error, response, body) {
body = JSON.parse(body);
fs.stat('.aics', function(err, stats) {
if (!stats) {
fs.mkdir(".aics");
}
fs.writeFile(name + '.md', body.documentation, 'utf8', function(err) {
if (err) {
console.log('写入 README.md 错误')
} else {
fs.writeFile('.aics/project.json', JSON.stringify(body, null, 4), 'utf8', function(err) {
if (err) {
console.log('写入 .aics/project.json 错误');
} else {
}
});
console.log('\n' + chalk.green.bold('Success.') + '\n');
}
});
})
});
} else if (argv.p && (typeof argv.p == "string")) {
fs.stat('.aics', function(err, stats) {
if (!stats) {
fs.mkdir(".aics");
console.log('在当前目录创建.aics文件夹成功.\n')
}
var project = require('../example/aics-project.json');
project.name = account.username + ":" + argv.p;
fs.writeFile('.aics/project.json', JSON.stringify(project, null, 4), 'utf8', function(err) {
if (err) {
console.log('写入 .aics/project.json 错误')
};
console.log('创建 .aics/project.json 成功.')
fs.writeFile('.aics/packages.json', "{}", 'utf8', function(err) {
if (err) {
console.log('写入 package.json 错误')
};
console.log('创建 .aics/packages.json 成功.')
});
fs.writeFile('README.md', "## " + argv.p, 'utf8', function(err) {
if (err) {
console.log('写入 README.md 错误')
} else {
console.log('创建 README.md 成功.')
}
});
});
})
} else {
var projectName = argv._.pop();
fs.stat('.aics', function(err, stats) {
if (!stats) {
fs.mkdir('.aics');
}
var packageJson = require(path.resolve(__dirname, '../example/example-package.json'));
packageJson.name = account.username + ":" + projectName;
fs.writeFile('.aics/' + projectName + '.depot.json', JSON.stringify(packageJson, null, 4), 'utf8', function(err) {
if (err) {
console.log('写入 .aics/' + projectName + '.depot.json 错误')
};
console.log('创建 .aics/' + projectName + '.depot.json 成功.')
fs.writeFile('README.md', "## " + projectName, 'utf8', function(err) {
if (err) {
console.log('写入 README.md 错误')
} else {
console.log('创建 README.md 成功.')
}
});
});
})
}
}
ProjectManager.update = function(configname) {
if (!configname) {
var config = require(path.resolve(".aics") + "/project.json");
console.log("更新项目依赖的代码包...");
for (var pname in config.packages) {
queryPackage(pname, config.packages[pname]);
}
} else if (configname == "--all") {
//更新所有包
//遍历.aics下的json文件
walk(path.resolve(".aics")).then(function(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
if (file.name.indexOf(".depot.json") > 0) {
//确定是包文件
console.log("读取包配置文件: .aics/" + file.name);
var config = Tools.projectConfig(".aics/" + file.name);
if (config.dependencies) {
for (var pname in config.dependencies) {
queryPackage(pname, config.dependencies[pname]);
}
}
}
}
});
} else {
//指定包更新
configname = configname + ".depot.json";
var config = Tools.projectConfig(".aics/" + configname);
if (config.dependencies) {
console.log("读取包配置文件: .aics/" + configname);
for (var pname in config.dependencies) {
queryPackage(pname, config.dependencies[pname]);
}
}
}
}
ProjectManager.remove = function(name) {
}
ProjectManager.add = function(name) {
var projConf;
if (!name) {
console.log(" 在 add 命令后添加您要添加的代码包名称。可以在http://codedepot.fami2u.com 寻找感兴趣的代码包");
return;
}
//读取项目配置文件中的
var config = Tools.getAics();
if (typeof config[name] == "string") {
console.log(chalk.green(name) + " has been Installd.");
return;
}
//为当前项目添加包依赖
var packageinfo = name.split("@");
var param = {
name: packageinfo.shift(),
version: packageinfo.pop() || ""
};
request(aicsConfig.host + "/package/info?" + qs.stringify(param), function(error, response, body) {
if (body == "NONE") {
console.log("Not Found: " + chalk.red(name));
} else {
var result = JSON.parse(body);
config = Tools.projectConfig(path.resolve(".aics/project.json"));
config.packages[name] = result.version;
Tools.setAics(name, result.version);
fs.writeFile(path.resolve(".aics/project.json"), JSON.stringify(config, null, 4), 'utf8', function(err, res) {
setupPackage(result);
});
}
});
// Tools.updateProjectConfig(config);
// queryPackage(packageinfo[0], (packageinfo[1] ? packageinfo[1] : ""));
}
ProjectManager.addfile = function(name, file) {
if (!name || !file) {
console.log('\nerror.\n');
console.log('Useage:');
console.log('aics addfile packageName file[dir]\n');
return;
}
var config = null,
trees = [];
try {
var paths = path.resolve('.aics/' + name + '.depot.json');
var states = fs.statSync(paths);
if (states) {
config = require(paths);
}
} catch (e) {
console.log("代码包配置文件不存在.");
return;
}
try {
var states = fs.statSync(file);
if (states) {
if (states.isDirectory()) {
var trees = walkSync(file, {
directories: false
});
for (var i = trees.length - 1; i >= 0; i--) {
trees[i] = file + "/" + trees[i];
};
config.files = config.files.concat(trees);
} else {
config.files = config.files.concat(file);
}
config.files = Array.from(new Set(config.files));
fs.writeFile(path.resolve('.aics/' + name + '.depot.json'), JSON.stringify(config, null, 4), 'utf8', function(err) {
if (err) {
console.log(err);
} else {
console.log("\nComplate!\n");
}
});
}
} catch (e) {
console.log(file + "不存在.");
return;
}
}
ProjectManager.files = function(name) {
if (!name) {
console.log('\nerror.\n');
console.log('Useage:');
console.log('aics files packagename\n');
return;
}
try {
var paths = path.resolve('.aics/' + name + '.depot.json');
var states = fs.statSync(paths);
if (states) {
config = require(paths);
config.files.map(function(file) {
console.log(util.inspect(file, {
colors: true
}));
})
}
} catch (e) {
console.log("代码包配置文件不存在.");
return;
}
}
queryPackage = function(name, version) {
var _aics = Tools.getAics();
if (_aics[name] == version) {
console.log("代码包: " + name + "@" + version + " 已安装");
} else {
request(aicsConfig.host + "/package/info?" + qs.stringify({
name: name,
version: version
}), function(error, response, body) {
if (body == "NONE") {
console.log("未发现代码包: " + name);
} else {
var result = JSON.parse(body);
var name = result.name;
var version = result.version;
setupPackage(result);
for (var pname in result.dependencies) {
queryPackage(pname, result.dependencies[pname]);
}
}
});
Tools.setAics(name, version);
}
}
setupPackage = function(packages) {
console.log("Downloading " + packages.name + "@" + packages.version + "...");
var packagePath = packages.name.split(':');
//判断临时文件夹是否存在
var tmppath = Tools.mkdir(".aics/tmp" + "/" + packagePath.join('/') + "@" + packages.version);
request(packages.url)
.on('error', function(err) {
console.log(err)
})
.pipe(fs.createWriteStream(tmppath + "/build.zip"))
.on('close', function() {
fs.createReadStream(tmppath + "/build.zip")
.pipe(unzip.Extract({
path: tmppath
}))
.on("close", function() {
var rootPath = path.resolve('.');
Tools.mergeFile(tmppath + '/packages', rootPath + '/.meteor/packages');
fs.unlinkSync(tmppath + "/packages");
walk(tmppath).then(function(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var filename = file.name;
if ((filename.indexOf(".") != 0) && (filename.indexOf("build.zip") == -1)) {
exportFiles(packages, file, tmppath);
}
}
console.log("已写入代码包文件: " + packages.name.replace("$", ":") + "@" + packages.version);
});
});
});
}
exportFiles = function(packages, file, tmppath) {
var filename = file.name;
var fileroot = file.root;
var filepath = path.resolve(fileroot.replace(tmppath, "./"));
Tools.mkdir(filepath);
// console.log(file.root + "/" + filename + "@" + version);
if (fs.existsSync(filepath + "/" + filename)) {
var org = fs.readFileSync(file.root + "/" + filename)
var orgmd5 = md5(org);
var tar = fs.readFileSync(filepath + "/" + filename)
var tarmd5 = md5(tar);
if (tarmd5 != orgmd5) {
fs.writeFile(filepath + "/" + filename + "@" + packages.version, org, function(err) {
//删除临时文件
// fs.unlinkSync(file.root + "/" + filename);
if (err) {
console.log(err);
} else {
console.log("代码包中的文件于本地不一致: " + filepath + "/" + filename + " in " + packages.name + "@" + packages.version);
}
});
} else {
//删除临时文件
// fs.unlinkSync(file.root + "/" + filename);
}
} else {
fs.createReadStream(file.root + "/" + filename)
.pipe(fs.createWriteStream(filepath + "/" + filename))
.on("close", function() {
//删除临时文件
// fs.unlinkSync(file.root + "/" + filename);
});
}
}