UNPKG

10.6 kBJavaScriptView Raw
1var path = require('path');
2var util = require('util');
3var fs = require('fs');
4var request = require('request');
5var qs = require('querystring');
6var unzip = require('unzip');
7var walk = require('walk-promise');
8var md5 = require('md5');
9var archiver = require('archiver');
10var chalk = require('chalk');
11var argv = require('minimist')(process.argv.slice(2));
12var Tools = require('../lib/tools');
13var AccountManager = require('../lib/account');
14
15module.exports = ProjectManager;
16
17function ProjectManager() {}
18
19var packs = {};
20ProjectManager.config = function() {
21 var configPath = path.resolve('project.json');
22 if (!fs.existsSync(configPath)) {
23 console.log("not in a aics project ,frist run aics project init [name] ");
24 process.exit(1);
25 }
26 var json = require(configPath);
27
28 if (!json.prototype) {
29 console.log("project use some prototype");
30 process.exit(1);
31 }
32
33 if (!json.name) {
34 console.log("project need a name");
35 process.exit(1);
36 }
37
38 if (!json.version) {
39 console.log("project need a version");
40 process.exit(1);
41 }
42
43 if (!json.packages) {
44 console.log("project some packages");
45 process.exit(1);
46 }
47
48 return json;
49}
50
51/*
52*简化了aics项目的构成合并项目和包的概念
53*.aics 文件夹存放包描述文件列表
54*.aics/tmp 临时目录用来打包或下载文件
55*.aics-project.json 项目描述文件
56*--0.0.x 版本用来管理项目的包依赖关系
57* ./aics/example.json 包描述文件
58*/
59
60ProjectManager.initProject = function(args) {
61 fs.stat('.aics', function(err, stats) {
62 if (!stats) {
63 fs.mkdir(".aics");
64 console.log('在当前目录创建.aics文件夹成功.\n')
65 }
66 var project = require('json/project.json');
67 project.name = AccountManager.username + ":" + argv.p;
68 fs.writeFile('.aics/project.json', JSON.stringify(project, null, 2), 'utf8', function(err) {
69 if (err) {
70 console.log('写入 .aics/project.json 错误')
71 };
72 console.log('创建 .aics/project.json 成功.')
73 fs.writeFile('.aics/packages.json', "{}", 'utf8', function(err) {
74 if (err) {
75 console.log('写入 package.json 错误')
76 };
77 console.log('创建 .aics/packages.json 成功.')
78 });
79 fs.writeFile('README.md', "## " + argv.p, 'utf8', function(err) {
80 if (err) {
81 console.log('写入 README.md 错误')
82 } else {
83 console.log('创建 README.md 成功.')
84 }
85 });
86 });
87 })
88}
89ProjectManager.initWithSample = function(example) {
90 var param = {
91 "project": example
92 };
93 if (example.split(":").length > 1) {
94 name = argv.e.split(":").pop();
95 } else {
96 console.log("\n项目名输入错误.\n");
97 return;
98 }
99 request(process.env.AICS_HOST + "/project/info?" + qs.stringify(param), function(error, response, body) {
100 console.log(body)
101 body = JSON.parse(body);
102 try {
103 fs.stat('.aics', function(err, stats) {
104 if (!stats) {
105 fs.mkdir(".aics");
106 }
107 })
108 } catch (e) {
109 fs.mkdir(".aics");
110 }
111
112 fs.writeFile('README.md', body.documentation, 'utf8', function(err) {
113 if (err) {
114 console.log('写入 README.md 错误')
115 } else {
116 body.documentation = "README.md";
117 fs.writeFile('.aics/project.json', JSON.stringify(body, null, 2), 'utf8', function(err) {
118 if (err) {
119 console.log('写入 .aics/project.json 错误');
120 } else {
121
122 }
123 });
124 console.log('\n' + chalk.green.bold('Success.') + '\n');
125 }
126 });
127 });
128}
129ProjectManager.update = function(configname) {
130 if (!configname) {
131 var config = require(path.resolve(".aics") + "/project.json");
132 console.log("更新项目依赖的代码包...");
133 for (var pname in config.packages) {
134 queryPackage(pname, config.packages[pname]);
135 }
136
137 } else if (configname == "--all") {
138 //更新所有包
139 //遍历.aics下的json文件
140 walk(path.resolve(".aics")).then(function(files) {
141 for (var i = 0; i < files.length; i++) {
142 var file = files[i];
143 if (file.name.indexOf(".depot.json") > 0) {
144 //确定是包文件
145 console.log("读取包配置文件: .aics/" + file.name);
146 var config = Tools.projectConfig(".aics/" + file.name);
147 if (config.dependencies) {
148 for (var pname in config.dependencies) {
149 queryPackage(pname, config.dependencies[pname]);
150 }
151 }
152 }
153
154 }
155 });
156
157
158 } else {
159 //指定包更新
160 configname = configname + ".depot.json";
161 var config = Tools.projectConfig(".aics/" + configname);
162 if (config.dependencies) {
163 console.log("读取包配置文件: .aics/" + configname);
164 for (var pname in config.dependencies) {
165 queryPackage(pname, config.dependencies[pname]);
166 }
167 }
168 }
169}
170ProjectManager.remove = function(name) {
171
172}
173ProjectManager.add = function(name) {
174 var projConf;
175 if (!name) {
176 console.log(" 在 add 命令后添加您要添加的代码包名称。可以在http://codedepot.fami2u.com 寻找感兴趣的代码包");
177 return;
178 }
179 //读取项目配置文件中的
180 var config = Tools.getAics();
181 if (typeof config[name] == "string") {
182 console.log(chalk.green(name) + " has been Installd.");
183 return;
184 }
185 //为当前项目添加包依赖
186 var packageinfo = name.split("@");
187 var param = {
188 name: packageinfo.shift(),
189 version: packageinfo.pop() || ""
190 };
191 request(process.env.AICS_HOST + "/package/info?" + qs.stringify(param), function(error, response, body) {
192 if (body == "NONE") {
193 console.log("Not Found: " + chalk.red(name));
194 } else {
195 var result = JSON.parse(body);
196 config = Tools.projectConfig(path.resolve(".aics/project.json"));
197 config.packages[name] = result.version;
198
199 fs.writeFile(path.resolve(".aics/project.json"), JSON.stringify(config, null, 2), 'utf8', function(err, res) {
200 setupPackage(result);
201 });
202 // setupPackage(result);
203 }
204 });
205 // Tools.updateProjectConfig(config);
206 // queryPackage(packageinfo[0], (packageinfo[1] ? packageinfo[1] : ""));
207}
208
209ProjectManager.publish = function(params) {
210 var config = require(path.resolve('.aics/project.json'));
211 if (!configCheck(config)) {
212 console.log(chalk.red.bold("配置文件出错."));
213 return;
214 }
215 fs.readFile(path.resolve(config.documentation), 'utf8', function(err, res) {
216 config.documentation = res;
217 config.creater = AccountManager.get().secret;
218 var r = request.post(process.env.AICS_HOST + '/project/create?' + qs.stringify(config), function(err, httpResponse, body) {
219 console.log(body);
220 });
221 })
222}
223queryPackage = function(name, version) {
224 var _aics = Tools.getAics();
225 if (_aics[name] == version) {
226 console.log("代码包: " + name + "@" + version + " 已安装");
227 } else {
228 request(process.env.AICS_HOST + "/package/info?" + qs.stringify({
229 name: name,
230 version: version
231 }), function(error, response, body) {
232 if (body == "NONE") {
233 console.log("未发现代码包: " + name);
234 } else {
235 var result = JSON.parse(body);
236 var name = result.name;
237 var version = result.version;
238 setupPackage(result);
239 for (var pname in result.dependencies) {
240 queryPackage(pname, result.dependencies[pname]);
241 }
242 }
243 });
244 // Tools.setAics(name, version);
245 }
246}
247setupPackage = function(packages) {
248 console.log("Downloading " + packages.name + "@" + packages.version + "...");
249 var packagePath = packages.name.split(':');
250 //判断临时文件夹是否存在
251 var tmppath = Tools.mkdir(".aics/tmp" + "/" + packagePath.join('/') + "@" + packages.version);
252 if (!packages.url || packages.url.indexOf('http://') < 0) {
253 console.log('请求URL不合法')
254 return;
255 }
256 request(packages.url)
257 .on('error', function(err) {
258 console.log(err)
259 })
260 .pipe(fs.createWriteStream(tmppath + "/build.zip"))
261 .on('close', function() {
262 fs.createReadStream(tmppath + "/build.zip")
263 .pipe(unzip.Extract({
264 path: tmppath
265 }))
266 .on("close", function() {
267 var rootPath = path.resolve('.');
268 // Tools.mergeFile(tmppath + '/packages', rootPath + '/.meteor/packages');
269 fs.unlinkSync(tmppath + "/packages");
270 walk(tmppath).then(function(files) {
271 for (var i = 0; i < files.length; i++) {
272 var file = files[i];
273 var filename = file.name;
274 if ((filename.indexOf(".") != 0) && (filename.indexOf("build.zip") == -1)) {
275 exportFiles(packages, file, tmppath);
276 }
277 }
278 console.log("已写入代码包文件: " + packages.name.replace("$", ":") + "@" + packages.version);
279 Tools.setAics(packages.name, packages.version);
280 });
281 });
282 });
283}
284
285exportFiles = function(packages, file, tmppath) {
286 var filename = file.name;
287 var fileroot = file.root;
288 var filepath = path.resolve(fileroot.replace(tmppath, "./"));
289 Tools.mkdir(filepath);
290 // console.log(file.root + "/" + filename + "@" + version);
291 if (fs.existsSync(filepath + "/" + filename)) {
292 var org = fs.readFileSync(file.root + "/" + filename)
293 var orgmd5 = md5(org);
294 var tar = fs.readFileSync(filepath + "/" + filename)
295 var tarmd5 = md5(tar);
296 if (tarmd5 != orgmd5) {
297 fs.writeFile(filepath + "/" + filename + "@" + packages.version, org, function(err) {
298 //删除临时文件
299 // fs.unlinkSync(file.root + "/" + filename);
300 if (err) {
301 console.log(err);
302 } else {
303 console.log("代码包中的文件于本地不一致: " + filepath + "/" + filename + " in " + packages.name + "@" + packages.version);
304 }
305 });
306
307 } else {
308 //删除临时文件
309 // fs.unlinkSync(file.root + "/" + filename);
310 }
311 } else {
312 fs.createReadStream(file.root + "/" + filename)
313 .pipe(fs.createWriteStream(filepath + "/" + filename))
314 .on("close", function() {
315 //删除临时文件
316 // fs.unlinkSync(file.root + "/" + filename);
317 });
318 }
319}
320configCheck = function(config) {
321 if (!config.stack) {
322 console.log("project belong to some stack");
323 return false;
324 }
325 if (!config.name) {
326 console.log("project need a name");
327 return false;
328 }
329 if (!config.version) {
330 console.log("project need a version");
331 return false;
332 }
333 if (!config.files) {
334 console.log("project need a files list");
335 return false;
336 }
337
338 return true;
339}