1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | var fs = require('fs'),
|
10 | path = require('path'),
|
11 | chalk,
|
12 | urllib = require('url'),
|
13 | debug = require('debug')('appc:util'),
|
14 | spinner,
|
15 | spriteIndex = 0,
|
16 | cachedConfig,
|
17 | sprite = '/-\\|';
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | function startSpinner() {
|
26 | stopSpinner();
|
27 | if (!spinner && process.stdout.isTTY && !process.env.TRAVIS) {
|
28 | var count = 0;
|
29 | spinner = setInterval(function() {
|
30 | if (count++ > 0) {
|
31 |
|
32 | process.stdout.write('\033[1D');
|
33 | }
|
34 | var s = ++spriteIndex % sprite.length;
|
35 | var c = sprite[s];
|
36 | process.stdout.write(c);
|
37 | },50);
|
38 | }
|
39 | }
|
40 |
|
41 |
|
42 |
|
43 |
|
44 | function stopSpinner() {
|
45 | if (spinner) {
|
46 | clearInterval(spinner);
|
47 |
|
48 | process.stdout.write('\033[1D');
|
49 | spinner = null;
|
50 | }
|
51 | }
|
52 |
|
53 |
|
54 |
|
55 |
|
56 | function waitMessage (msg) {
|
57 | process.stdout.write(msg);
|
58 | startSpinner();
|
59 | }
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | function okMessage (msg) {
|
65 | chalk = chalk || require('chalk');
|
66 | stopSpinner();
|
67 | msg = msg || '';
|
68 | process.stdout.write(msg+' '+chalk.green(isWindows()?'OK':'✓')+'\n');
|
69 | }
|
70 |
|
71 |
|
72 |
|
73 |
|
74 | function infoMessage (msg) {
|
75 | stopSpinner();
|
76 | console.log(msg);
|
77 | }
|
78 |
|
79 |
|
80 |
|
81 |
|
82 | function getHomeDir() {
|
83 | return process.env.HOME || process.env.USERPROFILE;
|
84 | }
|
85 |
|
86 |
|
87 |
|
88 |
|
89 | function getAppcDir() {
|
90 | return path.join(getHomeDir(), '.appcelerator');
|
91 | }
|
92 |
|
93 |
|
94 |
|
95 |
|
96 | function getInstallTag() {
|
97 | return path.join(getAppcDir(),'.installing');
|
98 | }
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | function getCacheDir() {
|
104 | return path.join(getAppcDir(), 'cache');
|
105 | }
|
106 |
|
107 |
|
108 |
|
109 |
|
110 | function getInstallDir () {
|
111 | return path.join(getAppcDir(), 'install');
|
112 | }
|
113 |
|
114 |
|
115 |
|
116 |
|
117 | function getVersionFile() {
|
118 | return path.join(getInstallDir(),'.version');
|
119 | }
|
120 |
|
121 |
|
122 |
|
123 |
|
124 | function getConfigFile() {
|
125 | return path.join(getAppcDir(), 'appc-cli.json');
|
126 | }
|
127 |
|
128 |
|
129 |
|
130 |
|
131 | function getNpmCacheDirectory() {
|
132 | return path.join(getAppcDir(),'.npm');
|
133 | }
|
134 |
|
135 |
|
136 |
|
137 |
|
138 | function writeVersion(version) {
|
139 | var versionFile = getVersionFile();
|
140 | debug('writing version: %s to %s',version,versionFile);
|
141 | if (fs.existsSync(versionFile)) {
|
142 | fs.unlinkSync(versionFile);
|
143 | }
|
144 | fs.writeFileSync(versionFile,version);
|
145 | }
|
146 |
|
147 |
|
148 |
|
149 |
|
150 | function getActiveVersion() {
|
151 | var versionFile = getVersionFile();
|
152 | if (fs.existsSync(versionFile)) {
|
153 | return fs.readFileSync(versionFile).toString().trim();
|
154 | }
|
155 | }
|
156 |
|
157 |
|
158 |
|
159 |
|
160 | function removeVersion() {
|
161 | var versionFile = getVersionFile();
|
162 | debug('remove version %s',versionFile);
|
163 | if (fs.existsSync(versionFile)) {
|
164 | fs.unlinkSync(versionFile);
|
165 | }
|
166 | }
|
167 |
|
168 |
|
169 |
|
170 |
|
171 | function listVersions (opts, versions) {
|
172 | chalk = chalk || require('chalk');
|
173 | if (!versions) {
|
174 | console.log(chalk.red('No versions available'));
|
175 | return;
|
176 | }
|
177 | var activeVersion = getActiveVersion();
|
178 | versions.forEach(function(entry){
|
179 | var ver = entry.version ? entry.version : entry,
|
180 | suffix = getInstallBinary(opts, ver) ? 'Installed' : 'Not Installed';
|
181 | if (versions.latest === ver) {
|
182 | suffix += chalk.white.bold(' (Latest)');
|
183 | }
|
184 | if (activeVersion && activeVersion === ver) {
|
185 | suffix += chalk.red(' (Active)');
|
186 | }
|
187 | var date = entry.date ? ' '+chalk.grey(pad(new Date(Date.parse(entry.date)), 15)) : '';
|
188 | console.log(chalk.yellow(pad(ver, 10))+' '+chalk.cyan(pad(suffix, 40))+date);
|
189 | });
|
190 | }
|
191 |
|
192 |
|
193 |
|
194 |
|
195 | function getVersionJson (versions) {
|
196 | var activeVersion = getActiveVersion(),
|
197 | obj = {
|
198 | versions: [],
|
199 | latest: undefined,
|
200 | active: activeVersion
|
201 | };
|
202 | if (Array.isArray(versions)) {
|
203 | if (versions[0].version) {
|
204 | obj.versions = Object.keys(versions).map(function(value, index){ return versions[index].version; });
|
205 | obj.latest = versions[0].version;
|
206 | } else {
|
207 | obj.versions = versions;
|
208 | obj.latest = versions[0];
|
209 | }
|
210 | }
|
211 | return obj;
|
212 | }
|
213 |
|
214 |
|
215 |
|
216 |
|
217 | function getInstalledVersions (callback) {
|
218 | var installDir = getInstallDir();
|
219 | if (fs.existsSync(installDir)) {
|
220 |
|
221 | try {
|
222 | var dirs = fs.readdirSync(installDir);
|
223 | if (dirs.length) {
|
224 | if (dirs.length > 1) {
|
225 |
|
226 | dirs = dirs.filter(function(e){ return e[0]!=='.'; }).sort(function(a,b){
|
227 | var av = parseInt(a.replace(/\./g,'')),
|
228 | bv = parseInt(b.replace(/\./g,''));
|
229 | return bv - av;
|
230 | });
|
231 | }
|
232 | debug('found the following version directories: %j',dirs);
|
233 | return dirs;
|
234 | }
|
235 | }
|
236 | catch (E) {
|
237 | debug('error reading install directory %o',E);
|
238 | if (E.code==='EACCES') {
|
239 | chalk = chalk || require('chalk');
|
240 | var message = process.platform==='win32' ? 'Please make sure you change the permissions and re-try' : 'Please make sure you change the permissions using these commands:\n\n\t'+chalk.yellow('sudo chown -R '+process.env.USER+' '+installDir+'\n\tchmod -R 0700 '+installDir)+'\n';
|
241 | fail('Ooops! Your install directory ('+installDir+') is not writable.\n'+message);
|
242 | }
|
243 | fail(E);
|
244 | }
|
245 | }
|
246 | }
|
247 |
|
248 |
|
249 |
|
250 |
|
251 | function getInstallBinary (opts, theversion) {
|
252 | opts = opts || {};
|
253 |
|
254 | var version = theversion || (opts.version!==true ? opts.version : null) || '',
|
255 | installDir = getInstallDir(),
|
256 | bin = path.join(installDir, version, 'package', 'bin', 'appc'),
|
257 | pkg,
|
258 | dirs;
|
259 |
|
260 | if (fs.existsSync(bin)) {
|
261 |
|
262 | pkg = path.join(installDir, version, 'package', 'package.json');
|
263 | return fs.existsSync(pkg) && bin;
|
264 | }
|
265 | else if (theversion) {
|
266 |
|
267 | return null;
|
268 | }
|
269 |
|
270 |
|
271 | theversion = getActiveVersion();
|
272 | if (theversion) {
|
273 | bin = getInstallBinary(opts, theversion);
|
274 | if (!bin) {
|
275 | if (!opts.version) {
|
276 | chalk = chalk || require('chalk');
|
277 | debug("you have specified a version (%s) that isn't found",theversion);
|
278 |
|
279 |
|
280 | console.log(chalk.red('version '+theversion+' specified previously is no longer available.'));
|
281 | }
|
282 | removeVersion();
|
283 | }
|
284 | else {
|
285 | return bin;
|
286 | }
|
287 | }
|
288 |
|
289 | dirs = getInstalledVersions();
|
290 | if (dirs) {
|
291 | for (var c=0;c<dirs.length;c++) {
|
292 | bin = path.join(installDir, dirs[c], 'package', 'bin', 'appc');
|
293 | if (fs.existsSync(bin)) {
|
294 |
|
295 | pkg = path.join(installDir, dirs[c], 'package', 'package.json');
|
296 | return fs.existsSync(pkg) && bin;
|
297 | }
|
298 | }
|
299 | }
|
300 | }
|
301 |
|
302 |
|
303 |
|
304 |
|
305 | function ensureDir (dir) {
|
306 | var last = expandPath(dir),
|
307 | parts = [];
|
308 |
|
309 | do {
|
310 | parts.unshift(path.basename(last));
|
311 | last = path.join(last, '..');
|
312 | } while (!fs.existsSync(last));
|
313 |
|
314 | if (!fs.existsSync(last)) {
|
315 | fs.mkdirSync(last);
|
316 | }
|
317 |
|
318 |
|
319 | for (var c=0;c<parts.length;c++) {
|
320 | var fp = path.join(last, parts[c]);
|
321 | if (!fs.existsSync(fp)) {
|
322 | fs.mkdirSync(fp);
|
323 | }
|
324 | last = fp;
|
325 | }
|
326 |
|
327 | return dir;
|
328 | }
|
329 |
|
330 |
|
331 |
|
332 |
|
333 | function expandPath (fn) {
|
334 | var home = getHomeDir(),
|
335 | p = fn.replace(/~\/?/g, function(value) {
|
336 | if (/\/$/.test(value)) {
|
337 | return home + '/';
|
338 | }
|
339 | return home;
|
340 | });
|
341 | return p;
|
342 | }
|
343 |
|
344 |
|
345 |
|
346 |
|
347 | function fail (msg) {
|
348 | stopSpinner();
|
349 | debug('fail %o',msg);
|
350 | if (msg.stack && process.env.DEBUG) {
|
351 | console.error(msg.stack);
|
352 | }
|
353 | chalk = chalk || require('chalk');
|
354 | console.error('\n'+(chalk.red(msg.message || msg)));
|
355 | process.exit(1);
|
356 | }
|
357 |
|
358 | var optionRE = /^-{1,2}([\w-_]+)=?(.*)?$/;
|
359 |
|
360 |
|
361 |
|
362 |
|
363 | function parseOpts() {
|
364 | var args = {};
|
365 | for (var c=2;c<process.argv.length;c++) {
|
366 | var arg = process.argv[c];
|
367 | if (optionRE.test(arg)) {
|
368 | var match = optionRE.exec(arg),
|
369 | name = match[1],
|
370 | value = match.length > 2 && match[2] || (process.argv[c+1] && !/^--/.test(process.argv[c+1]) ? process.argv[c+1] : null) || true;
|
371 | if (value==='true' || value==='false') {
|
372 | value = value==='true';
|
373 | }
|
374 | if (name.indexOf('no-') === 0) {
|
375 | name = name.substring(3);
|
376 | value = false;
|
377 | }
|
378 | args[name] = value;
|
379 | }
|
380 | }
|
381 | return args;
|
382 | }
|
383 |
|
384 |
|
385 |
|
386 |
|
387 | function parseArgs(opts) {
|
388 | if (!opts) throw new Error("missing opts");
|
389 | var args = [];
|
390 | for (var c=2;c<process.argv.length;c++) {
|
391 | var arg = process.argv[c];
|
392 | if (optionRE.test(arg)) {
|
393 | var match = optionRE.exec(arg),
|
394 | name = match[1],
|
395 | value = opts[name];
|
396 |
|
397 | if (value && String(process.argv[c+1]===String(value))) {
|
398 | c++;
|
399 | }
|
400 | continue;
|
401 | }
|
402 | else {
|
403 | args.push(arg);
|
404 | }
|
405 | }
|
406 | return args;
|
407 | }
|
408 |
|
409 |
|
410 |
|
411 |
|
412 | function makeURL (opts, urlpath) {
|
413 | if (typeof(opts)==='string') {
|
414 | urlpath = opts;
|
415 | opts = {};
|
416 | }
|
417 | else {
|
418 | opts = opts || {};
|
419 | }
|
420 | var baseurl;
|
421 | if (opts.registry) {
|
422 | baseurl = opts.registry;
|
423 | }
|
424 | else if (process.env.APPC_REGISTRY_SERVER) {
|
425 | baseurl = process.env.APPC_REGISTRY_SERVER;
|
426 | }
|
427 | else if (process.env.APPC_ENV || process.env.NODE_ENV) {
|
428 | var env = process.env.APPC_ENV || process.env.NODE_ENV;
|
429 | if (env === 'preproduction') {
|
430 | baseurl = DEFAULT_PREPROD_REGISTRY_URL;
|
431 | }
|
432 | else if (env === 'production') {
|
433 | baseurl = DEFAULT_PROD_REGISTRY_URL;
|
434 | }
|
435 | }
|
436 | if (!baseurl) {
|
437 | var config = readConfig();
|
438 | if (config && config.registry) {
|
439 | baseurl = config.registry;
|
440 | }
|
441 | else if (config && (config.defaultEnvironment==='preproduction'||config.environmentName==='preproduction')) {
|
442 | baseurl = DEFAULT_PREPROD_REGISTRY_URL;
|
443 | }
|
444 | else {
|
445 | baseurl = DEFAULT_PROD_REGISTRY_URL;
|
446 | }
|
447 | }
|
448 | return urllib.resolve(baseurl,urlpath);
|
449 | }
|
450 |
|
451 | function makeRequestError(msg, code) {
|
452 | var err = new Error(msg);
|
453 | err.code = code;
|
454 | return err;
|
455 | }
|
456 |
|
457 | var DEFAULT_PREPROD_REGISTRY_URL = 'https://8d2938f67044d8367d468453b5a6c2536185bcea.cloudapp-enterprise-preprod.appctest.com';
|
458 | var DEFAULT_PROD_REGISTRY_URL = 'https://software.appcelerator.com';
|
459 |
|
460 |
|
461 |
|
462 |
|
463 | function getRequest() {
|
464 | return require('request');
|
465 | }
|
466 |
|
467 |
|
468 |
|
469 |
|
470 | function request (location, callback) {
|
471 | var url = urllib.parse(location),
|
472 | userAgent = 'Appcelerator CLI/'+require('../package').version+' ('+process.platform+')',
|
473 | opts = {
|
474 | url: url,
|
475 | proxy: process.env.APPC_CONFIG_PROXY,
|
476 | headers: {
|
477 | 'user-agent': userAgent,
|
478 | host: url.host
|
479 | }
|
480 | },
|
481 | req = getRequest().get(opts);
|
482 |
|
483 | debug('request %j',opts);
|
484 |
|
485 |
|
486 | req.on('response', function(res) {
|
487 | debug('request response received');
|
488 | if (req.__err) {
|
489 | debug('request response callback skipped, request error already executed.');
|
490 | } else {
|
491 | callback(null, res, req);
|
492 | }
|
493 | });
|
494 |
|
495 |
|
496 | req.on('error',function(err){
|
497 | req.__err = true;
|
498 | debug('request error',err);
|
499 | if (err.name === 'AppCError') {
|
500 | return callback(err);
|
501 | }
|
502 | if (err.code === 'ECONNREFUSED') {
|
503 | return callback(makeRequestError("Error connecting to download server at "+url.host+". Make sure you are online.",err.code));
|
504 | }
|
505 | else if (err.code === 'ENOTFOUND') {
|
506 | return callback(makeRequestError("Error connecting to download server at "+url.host+" (not found). Make sure you are online.",err.code));
|
507 | }
|
508 | else if (err.code === 'ECONNRESET') {
|
509 | return callback(makeRequestError("Error connecting to download server at "+url.host+" (reset). Make sure you are online.",err.code));
|
510 | }
|
511 | return callback(err);
|
512 | });
|
513 |
|
514 | return req;
|
515 | }
|
516 |
|
517 |
|
518 |
|
519 |
|
520 | function requestJSON(location, callback, attempts) {
|
521 | return request(location, function(err,res,req){
|
522 | if (err) {
|
523 | if (err.code === 'ECONNREFUSED' || err.code === 'ECONNRESET' || err.message.indexOf('hang up') > 0) {
|
524 |
|
525 | attempts = attempts || 1;
|
526 | if (attempts > 10) {
|
527 | return callback(err);
|
528 | }
|
529 | return setTimeout(function(){
|
530 | return requestJSON(location, callback, attempts + 1);
|
531 | },500*attempts);
|
532 | }
|
533 | return callback(err);
|
534 | }
|
535 | if (res && req.headers && req.headers['content-type'] && req.headers['content-type'].indexOf('/json') < 0) {
|
536 |
|
537 | attempts = attempts || 1;
|
538 | if (attempts > 10) {
|
539 | return callback(err);
|
540 | }
|
541 | return setTimeout(function(){
|
542 | return requestJSON(location, callback, attempts + 1);
|
543 | },500*attempts);
|
544 | }
|
545 | if (res.statusCode===200) {
|
546 | var buf = '';
|
547 | res.on('data', function (chunk) {
|
548 | buf+=chunk;
|
549 | });
|
550 | res.on('end', function(){
|
551 | debug('attempting to parse JSON => [%s]',buf);
|
552 | callback(null, JSON.parse(buf));
|
553 | });
|
554 | res.on('error',callback);
|
555 | }
|
556 | else if (res.statusCode===301 || res.statusCode===302) {
|
557 | return requestJSON(res.headers.location, callback);
|
558 | }
|
559 | else if (res && /^(400|404|408|500|502|503|504)$/.test(String(res.statusCode))) {
|
560 | attempts = attempts || 1;
|
561 | if (attempts > 10) {
|
562 | return callback(err);
|
563 | }
|
564 | return setTimeout(function(){
|
565 | return requestJSON(location, callback, attempts + 1);
|
566 | },500*attempts);
|
567 | }
|
568 | else {
|
569 | return callback(new Error("Invalid response code: "+res.statusCode+" received from server."));
|
570 | }
|
571 | });
|
572 | }
|
573 |
|
574 |
|
575 |
|
576 |
|
577 | function pad(str, len) {
|
578 | chalk = chalk || require('chalk');
|
579 | var slen = chalk.stripColor(str).length;
|
580 | var newstr = str;
|
581 | for (var c=slen;c<len;c++) {
|
582 | newstr+=' ';
|
583 | }
|
584 | return newstr;
|
585 | }
|
586 |
|
587 |
|
588 |
|
589 |
|
590 | function canWriteDir(dir) {
|
591 | var del = !fs.existsSync(dir),
|
592 | fn;
|
593 | try {
|
594 | if (del) {
|
595 | ensureDir(dir);
|
596 | }
|
597 | if (fs.statSync(dir).isDirectory()) {
|
598 |
|
599 | fn = path.join(dir, String(+new Date())+(Math.random()*3)+'.txt');
|
600 |
|
601 | fs.writeFileSync(fn,'hi');
|
602 | return true;
|
603 | }
|
604 | else {
|
605 |
|
606 | return false;
|
607 | }
|
608 | }
|
609 | catch (E) {
|
610 | if (E.code==='EACCES') {
|
611 | return false;
|
612 | }
|
613 | console.log(E.stack, E.code);
|
614 | }
|
615 | finally {
|
616 | if (fs.existsSync(fn)) {
|
617 | try { fs.unlinkSync(fn); } catch (ig) {}
|
618 | }
|
619 | if (del) {
|
620 | try { fs.unlinkSync(path); } catch (ig) {}
|
621 | }
|
622 | }
|
623 | }
|
624 |
|
625 |
|
626 |
|
627 |
|
628 | function checkDirectory(dir, name) {
|
629 | var message;
|
630 | var errorlib = require('./error'),
|
631 | chalk = chalk || require('chalk');
|
632 | if (!canWriteDir(dir)) {
|
633 | message = process.platform==='win32' ? 'Please make sure you change the permissions and re-try' : 'Please make sure you change the permissions using these commands:\n\n\t'+chalk.yellow('sudo chown -R '+process.env.USER+' '+dir+'\n\tchmod -R 0700 '+dir)+'\n';
|
634 | return errorlib.createError('com.appcelerator.install.preflight.directory.unwritable',name,dir,message);
|
635 | }
|
636 | else {
|
637 |
|
638 | if (process.platform!=='win32') {
|
639 | var stat = fs.statSync(dir);
|
640 | if (stat.uid!==process.getuid()) {
|
641 | message = 'Please make sure you change the permissions using these commands:\n\n\t'+chalk.yellow('sudo chown -R '+process.env.USER+' '+dir+'\n\tchmod -R 0700 '+dir)+'\n';
|
642 | return errorlib.createError('com.appcelerator.install.preflight.directory.ownership',name,dir,process.env.USER,message);
|
643 | }
|
644 | }
|
645 | }
|
646 | }
|
647 |
|
648 |
|
649 | var whyYouDoAbort = isWindows() ? [':<'] : ['😡','😨','😥','😭','😱','😰','😤','😠'];
|
650 | function abortMessage (name) {
|
651 |
|
652 | if (process.stdout.isTTY) {
|
653 | stopSpinner();
|
654 | process.stdout.clearLine();
|
655 | process.stdout.cursorTo(0);
|
656 | }
|
657 | console.log(name+' aborted ... '+(whyYouDoAbort[Math.floor(Math.round(Math.random()*whyYouDoAbort.length))] || whyYouDoAbort[0]));
|
658 | process.exit(1);
|
659 | }
|
660 |
|
661 | function readConfig () {
|
662 | if (cachedConfig) { return cachedConfig; }
|
663 | var cf = getConfigFile();
|
664 | if (!fs.existsSync(cf)) {
|
665 | return null;
|
666 | }
|
667 | return (cachedConfig=JSON.parse(fs.readFileSync(cf)));
|
668 | }
|
669 |
|
670 | function writeConfig(config) {
|
671 | cachedConfig = config;
|
672 | var cf = getConfigFile();
|
673 | fs.writeFileSync(cf, JSON.stringify(config,null,2));
|
674 | }
|
675 |
|
676 |
|
677 |
|
678 |
|
679 |
|
680 |
|
681 |
|
682 |
|
683 |
|
684 |
|
685 |
|
686 |
|
687 |
|
688 |
|
689 | function updateCheck(opts, callback) {
|
690 |
|
691 | if (opts.version || opts.quiet) { return callback(); }
|
692 |
|
693 |
|
694 |
|
695 | var config = readConfig();
|
696 |
|
697 | if (!config) {
|
698 | return callback();
|
699 | }
|
700 |
|
701 | chalk = chalk || require('chalk');
|
702 |
|
703 | try {
|
704 | var check = config.lastUpdateCheck;
|
705 | var checkEveryMS = config.updateCheckInterval || 86400000;
|
706 | if (!check || check + checkEveryMS < Date.now()) {
|
707 |
|
708 | debug('update check skipping, %d, %d', check, checkEveryMS);
|
709 | }
|
710 | else {
|
711 |
|
712 | return callback();
|
713 | }
|
714 | }
|
715 | catch (E){
|
716 |
|
717 | return callback();
|
718 | }
|
719 |
|
720 | var url = makeURL(opts, '/api/appc/list');
|
721 | requestJSON(url, function(err,result){
|
722 |
|
723 | if (!err && result) {
|
724 | try {
|
725 | debug('update check completed, latest is %s',result.latest);
|
726 |
|
727 | config.lastUpdateCheck = Date.now();
|
728 |
|
729 | writeConfig(config);
|
730 |
|
731 | var found = getInstallBinary(opts, result.latest);
|
732 |
|
733 | debug('update check found %s',found);
|
734 | if (!found) {
|
735 | console.log('A new update '+chalk.yellow('('+result.latest+')')+' is available... Download with '+chalk.green('appc use '+result.latest));
|
736 | }
|
737 | }
|
738 | catch (E) {
|
739 | }
|
740 | }
|
741 | callback();
|
742 | });
|
743 | }
|
744 |
|
745 | function isWindows() {
|
746 | return process.platform === 'win32';
|
747 | }
|
748 |
|
749 |
|
750 |
|
751 |
|
752 |
|
753 | function resetLine () {
|
754 | if (process.stdout.isTTY) {
|
755 | process.stdout.clearLine();
|
756 | process.stdout.cursorTo(0);
|
757 | }
|
758 | }
|
759 |
|
760 |
|
761 |
|
762 |
|
763 |
|
764 |
|
765 |
|
766 |
|
767 |
|
768 |
|
769 |
|
770 |
|
771 |
|
772 |
|
773 |
|
774 |
|
775 |
|
776 |
|
777 |
|
778 |
|
779 |
|
780 |
|
781 |
|
782 |
|
783 |
|
784 |
|
785 | function rmdirSyncRecursive(_path, failSilent) {
|
786 | var files;
|
787 |
|
788 | try {
|
789 | files = fs.readdirSync(_path);
|
790 | } catch (err) {
|
791 |
|
792 | if(failSilent) return;
|
793 | throw new Error(err.message);
|
794 | }
|
795 |
|
796 |
|
797 | for(var i = 0; i < files.length; i++) {
|
798 | var file = path.join(_path, files[i]);
|
799 | var currFile = fs.lstatSync(file);
|
800 |
|
801 | if(currFile.isDirectory()) {
|
802 |
|
803 | rmdirSyncRecursive(file);
|
804 | } else if(currFile.isSymbolicLink()) {
|
805 |
|
806 | if (isWindows()) {
|
807 | fs.chmodSync(file, 666);
|
808 | }
|
809 |
|
810 | fs.unlinkSync(file);
|
811 | } else {
|
812 |
|
813 | if (isWindows) {
|
814 | fs.chmodSync(file, 666);
|
815 | }
|
816 |
|
817 | fs.unlinkSync(file);
|
818 | }
|
819 | }
|
820 |
|
821 | |
822 |
|
823 | return fs.rmdirSync(_path);
|
824 | }
|
825 |
|
826 |
|
827 |
|
828 |
|
829 | function mergeOptsToArgs(args, opts){
|
830 | var argv = [].concat(process.__argv.slice(3));
|
831 | if (argv.length) {
|
832 | for (var c=0;c<argv.length;c++) {
|
833 | var arg = argv[c];
|
834 | args.push(arg);
|
835 | }
|
836 | }
|
837 | return args;
|
838 | }
|
839 |
|
840 |
|
841 |
|
842 |
|
843 |
|
844 | function getProxyServer() {
|
845 | var config = readConfig(),
|
846 | proxy = '',
|
847 | parsed;
|
848 |
|
849 | if (config) {
|
850 | proxy = config.proxyServer || '';
|
851 | parsed = urllib.parse(proxy);
|
852 |
|
853 | if ((!/^https?\:$/.test(parsed.protocol)) || (!(parsed.host || ''))) {
|
854 | proxy = '';
|
855 | }
|
856 | }
|
857 |
|
858 | return proxy;
|
859 | }
|
860 |
|
861 | exports.getAppcDir = getAppcDir;
|
862 | exports.getHomeDir = getHomeDir;
|
863 | exports.getCacheDir = getCacheDir;
|
864 | exports.getConfigFile = getConfigFile;
|
865 | exports.getNpmCacheDirectory = getNpmCacheDirectory;
|
866 | exports.ensureDir = ensureDir;
|
867 | exports.expandPath = expandPath;
|
868 | exports.getInstallDir = getInstallDir;
|
869 | exports.listVersions = listVersions;
|
870 | exports.getVersionJson = getVersionJson;
|
871 | exports.getInstalledVersions = getInstalledVersions;
|
872 | exports.getInstallBinary = getInstallBinary;
|
873 | exports.fail = fail;
|
874 | exports.parseOpts = parseOpts;
|
875 | exports.parseArgs = parseArgs;
|
876 | exports.writeVersion = writeVersion;
|
877 | exports.getActiveVersion = getActiveVersion;
|
878 | exports.makeURL = makeURL;
|
879 | exports.request = request;
|
880 | exports.requestJSON = requestJSON;
|
881 | exports.pad = pad;
|
882 | exports.waitMessage = waitMessage;
|
883 | exports.okMessage = okMessage;
|
884 | exports.infoMessage = infoMessage;
|
885 | exports.stopSpinner = stopSpinner;
|
886 | exports.startSpinner = startSpinner;
|
887 | exports.canWriteDir = canWriteDir;
|
888 | exports.checkDirectory = checkDirectory;
|
889 | exports.abortMessage = abortMessage;
|
890 | exports.updateCheck = updateCheck;
|
891 | exports.isWindows = isWindows;
|
892 | exports.resetLine = resetLine;
|
893 | exports.rmdirSyncRecursive = rmdirSyncRecursive;
|
894 | exports.getRequest = getRequest;
|
895 | exports.mergeOptsToArgs = mergeOptsToArgs;
|
896 | exports.getInstallTag = getInstallTag;
|
897 | exports.getProxyServer = getProxyServer;
|