mirror of
https://github.com/apache/cordova-android.git
synced 2025-02-22 00:32:55 +08:00
204 lines
5.0 KiB
JavaScript
204 lines
5.0 KiB
JavaScript
var os = require('os');
|
|
var fs = require('fs');
|
|
var _ls = require('./ls');
|
|
|
|
// Module globals
|
|
var config = {
|
|
silent: false,
|
|
fatal: false
|
|
};
|
|
exports.config = config;
|
|
|
|
var state = {
|
|
error: null,
|
|
currentCmd: 'shell.js',
|
|
tempDir: null
|
|
};
|
|
exports.state = state;
|
|
|
|
var platform = os.type().match(/^Win/) ? 'win' : 'unix';
|
|
exports.platform = platform;
|
|
|
|
function log() {
|
|
if (!config.silent)
|
|
console.log.apply(this, arguments);
|
|
}
|
|
exports.log = log;
|
|
|
|
// Shows error message. Throws unless _continue or config.fatal are true
|
|
function error(msg, _continue) {
|
|
if (state.error === null)
|
|
state.error = '';
|
|
state.error += state.currentCmd + ': ' + msg + '\n';
|
|
|
|
if (msg.length > 0)
|
|
log(state.error);
|
|
|
|
if (config.fatal)
|
|
process.exit(1);
|
|
|
|
if (!_continue)
|
|
throw '';
|
|
}
|
|
exports.error = error;
|
|
|
|
// In the future, when Proxies are default, we can add methods like `.to()` to primitive strings.
|
|
// For now, this is a dummy function to bookmark places we need such strings
|
|
function ShellString(str) {
|
|
return str;
|
|
}
|
|
exports.ShellString = ShellString;
|
|
|
|
// Returns {'alice': true, 'bob': false} when passed a dictionary, e.g.:
|
|
// parseOptions('-a', {'a':'alice', 'b':'bob'});
|
|
function parseOptions(str, map) {
|
|
if (!map)
|
|
error('parseOptions() internal error: no map given');
|
|
|
|
// All options are false by default
|
|
var options = {};
|
|
for (var letter in map)
|
|
options[map[letter]] = false;
|
|
|
|
if (!str)
|
|
return options; // defaults
|
|
|
|
if (typeof str !== 'string')
|
|
error('parseOptions() internal error: wrong str');
|
|
|
|
// e.g. match[1] = 'Rf' for str = '-Rf'
|
|
var match = str.match(/^\-(.+)/);
|
|
if (!match)
|
|
return options;
|
|
|
|
// e.g. chars = ['R', 'f']
|
|
var chars = match[1].split('');
|
|
|
|
chars.forEach(function(c) {
|
|
if (c in map)
|
|
options[map[c]] = true;
|
|
else
|
|
error('option not recognized: '+c);
|
|
});
|
|
|
|
return options;
|
|
}
|
|
exports.parseOptions = parseOptions;
|
|
|
|
// Expands wildcards with matching (ie. existing) file names.
|
|
// For example:
|
|
// expand(['file*.js']) = ['file1.js', 'file2.js', ...]
|
|
// (if the files 'file1.js', 'file2.js', etc, exist in the current dir)
|
|
function expand(list) {
|
|
var expanded = [];
|
|
list.forEach(function(listEl) {
|
|
// Wildcard present on directory names ?
|
|
if(listEl.search(/\*[^\/]*\//) > -1 || listEl.search(/\*\*[^\/]*\//) > -1) {
|
|
var match = listEl.match(/^([^*]+\/|)(.*)/);
|
|
var root = match[1];
|
|
var rest = match[2];
|
|
var restRegex = rest.replace(/\*\*/g, ".*").replace(/\*/g, "[^\\/]*");
|
|
restRegex = new RegExp(restRegex);
|
|
|
|
_ls('-R', root).filter(function (e) {
|
|
return restRegex.test(e);
|
|
}).forEach(function(file) {
|
|
expanded.push(file);
|
|
});
|
|
}
|
|
// Wildcard present on file names ?
|
|
else if (listEl.search(/\*/) > -1) {
|
|
_ls('', listEl).forEach(function(file) {
|
|
expanded.push(file);
|
|
});
|
|
} else {
|
|
expanded.push(listEl);
|
|
}
|
|
});
|
|
return expanded;
|
|
}
|
|
exports.expand = expand;
|
|
|
|
// Normalizes _unlinkSync() across platforms to match Unix behavior, i.e.
|
|
// file can be unlinked even if it's read-only, see https://github.com/joyent/node/issues/3006
|
|
function unlinkSync(file) {
|
|
try {
|
|
fs.unlinkSync(file);
|
|
} catch(e) {
|
|
// Try to override file permission
|
|
if (e.code === 'EPERM') {
|
|
fs.chmodSync(file, '0666');
|
|
fs.unlinkSync(file);
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
exports.unlinkSync = unlinkSync;
|
|
|
|
// e.g. 'shelljs_a5f185d0443ca...'
|
|
function randomFileName() {
|
|
function randomHash(count) {
|
|
if (count === 1)
|
|
return parseInt(16*Math.random(), 10).toString(16);
|
|
else {
|
|
var hash = '';
|
|
for (var i=0; i<count; i++)
|
|
hash += randomHash(1);
|
|
return hash;
|
|
}
|
|
}
|
|
|
|
return 'shelljs_'+randomHash(20);
|
|
}
|
|
exports.randomFileName = randomFileName;
|
|
|
|
// extend(target_obj, source_obj1 [, source_obj2 ...])
|
|
// Shallow extend, e.g.:
|
|
// extend({A:1}, {b:2}, {c:3}) returns {A:1, b:2, c:3}
|
|
function extend(target) {
|
|
var sources = [].slice.call(arguments, 1);
|
|
sources.forEach(function(source) {
|
|
for (var key in source)
|
|
target[key] = source[key];
|
|
});
|
|
|
|
return target;
|
|
}
|
|
exports.extend = extend;
|
|
|
|
// Common wrapper for all Unix-like commands
|
|
function wrap(cmd, fn, options) {
|
|
return function() {
|
|
var retValue = null;
|
|
|
|
state.currentCmd = cmd;
|
|
state.error = null;
|
|
|
|
try {
|
|
var args = [].slice.call(arguments, 0);
|
|
|
|
if (options && options.notUnix) {
|
|
retValue = fn.apply(this, args);
|
|
} else {
|
|
if (args.length === 0 || typeof args[0] !== 'string' || args[0][0] !== '-')
|
|
args.unshift(''); // only add dummy option if '-option' not already present
|
|
retValue = fn.apply(this, args);
|
|
}
|
|
} catch (e) {
|
|
if (!state.error) {
|
|
// If state.error hasn't been set it's an error thrown by Node, not us - probably a bug...
|
|
console.log('shell.js: internal error');
|
|
console.log(e.stack || e);
|
|
process.exit(1);
|
|
}
|
|
if (config.fatal)
|
|
throw e;
|
|
}
|
|
|
|
state.currentCmd = 'shell.js';
|
|
return retValue;
|
|
};
|
|
} // wrap
|
|
exports.wrap = wrap;
|