mirror of
https://github.com/bower/bower.git
synced 2026-02-11 22:44:58 -05:00
Update codebase to the almost finalised architecture.
The GitRemoteResolver is almost done.
This commit is contained in:
@@ -1,240 +0,0 @@
|
||||
var util = require('util');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var events = require('events');
|
||||
var mout = require('mout');
|
||||
var Q = require('q');
|
||||
var tmp = require('tmp');
|
||||
var UnitOfWork = require('./UnitOfWork');
|
||||
var config = require('./config');
|
||||
var createPackage;
|
||||
var createError = require('../util/createError');
|
||||
|
||||
var Package = function (endpoint, options) {
|
||||
options = options || {};
|
||||
|
||||
this._endpoint = endpoint;
|
||||
this._name = options.name;
|
||||
this._guessedName = !this.name;
|
||||
this._range = options.range || '*';
|
||||
this._unitOfWork = options.unitOfWork || new UnitOfWork();
|
||||
this._config = options.config || config;
|
||||
};
|
||||
|
||||
util.inherits(Package, events.EventEmitter);
|
||||
|
||||
// -----------------
|
||||
|
||||
Package.prototype.getName = function () {
|
||||
return this._name;
|
||||
};
|
||||
|
||||
Package.prototype.getEndpoint = function () {
|
||||
return this._endpoint;
|
||||
};
|
||||
|
||||
Package.prototype.getRange = function () {
|
||||
return this._range;
|
||||
};
|
||||
|
||||
Package.prototype.getTempDir = function () {
|
||||
return this._tempDir;
|
||||
};
|
||||
|
||||
Package.prototype.resolve = function () {
|
||||
// Throw if already resolved
|
||||
if (this._resolved) {
|
||||
throw createError('Package is already resolved', 'EALREADYRES');
|
||||
}
|
||||
|
||||
// 1st - Enqueue the package in the unit of work
|
||||
return this._unitOfWork.enqueue(this)
|
||||
.then(function (done) {
|
||||
// 2nd - Create temporary dir
|
||||
return this._createTempDir()
|
||||
// 3nd - Resolve self
|
||||
.then(this._resolveSelf.bind(this))
|
||||
// 4th - Read json
|
||||
.then(this._readJson.bind(this))
|
||||
// 5th - Parse json
|
||||
.then(this._parseJson.bind(this))
|
||||
// 6th - Mark as resolved & call done
|
||||
// to inform the unit of work
|
||||
.then(function (dependencies) {
|
||||
this._resolved = true;
|
||||
done();
|
||||
return dependencies;
|
||||
}.bind(this), function (err) {
|
||||
this._resolveError = err;
|
||||
done();
|
||||
throw err;
|
||||
}.bind(this))
|
||||
// 7th - Resolve dependencies
|
||||
.then(this._resolveDependencies.bind(this));
|
||||
}.bind(this), function (err) {
|
||||
// If error is of a duplicate package,
|
||||
// copy everything from the resolved package (duplicate) to itself
|
||||
if (err.code === 'EDUPL') {
|
||||
mout.object.mixIn(this, err.pkg);
|
||||
} else {
|
||||
this._resolveError = err;
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Package.prototype.getResolveError = function () {
|
||||
return this._resolveError;
|
||||
};
|
||||
|
||||
Package.prototype.getJson = function () {
|
||||
this._assertResolved();
|
||||
return this._json;
|
||||
};
|
||||
|
||||
Package.prototype.getDependencies = function () {
|
||||
this._assertResolved();
|
||||
return this._dependencies;
|
||||
};
|
||||
|
||||
Package.prototype.install = function () {
|
||||
this._assertResolved();
|
||||
|
||||
// TODO
|
||||
};
|
||||
|
||||
// -----------------
|
||||
|
||||
Package.prototype._resolveSelf = function () {};
|
||||
|
||||
// -----------------
|
||||
|
||||
|
||||
Package.prototype._createTempDir = function () {
|
||||
console.log('_createTempDir');
|
||||
|
||||
// Resolved if cached
|
||||
if (this._tempDir) {
|
||||
return Q.fcall(this._tempDir);
|
||||
}
|
||||
|
||||
return Q.nfcall(tmp.dir, {
|
||||
prefix: 'bower-' + this.name + '-',
|
||||
mode: parseInt('0777', 8) & (~process.umask())
|
||||
})
|
||||
.then(function (dir) {
|
||||
this._tempDir = dir;
|
||||
return dir;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
Package.prototype._readJson = function () {
|
||||
console.log('_readJson');
|
||||
|
||||
// Resolve if cached
|
||||
if (this._json) {
|
||||
return Q.fcall(this._json);
|
||||
}
|
||||
|
||||
var jsonFile;
|
||||
|
||||
// Try bower.json
|
||||
jsonFile = path.join(this.getTempDir(), 'bower.json');
|
||||
return Q.nfcall(fs.readFile, jsonFile)
|
||||
// Try component.json
|
||||
.then(null, function (err) {
|
||||
if (err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
|
||||
jsonFile = path.join(this.getTempDir(), 'component.json');
|
||||
return Q.nfcall(fs.readFile, jsonFile)
|
||||
// Issue a deprecation message if it exists
|
||||
.then(function (contents) {
|
||||
this.emit('warn', 'Package "' + this.name + '" is using the deprecated component.json file');
|
||||
return contents;
|
||||
}.bind(this));
|
||||
}.bind(this))
|
||||
// If we got the file contents, validate them
|
||||
.then(function (contents) {
|
||||
// TODO: change the validation to a separate module in the bower organization
|
||||
try {
|
||||
this._json = JSON.parse(contents);
|
||||
return this._json;
|
||||
} catch (e) {
|
||||
throw createError('Unable to parse "' + jsonFile + '" file', e.code, {
|
||||
details: e.message
|
||||
});
|
||||
}
|
||||
// Otherwise there was an error
|
||||
}.bind(this), function (err) {
|
||||
// If no json file was found, return one just with the name
|
||||
if (err.code === 'ENOENT') {
|
||||
this._json = { name: this.name };
|
||||
return this._json;
|
||||
}
|
||||
|
||||
// If we got here, the error code is something else so we re-throw it
|
||||
throw err;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
Package.prototype._parseJson = function (json) {
|
||||
console.log('_parseJson');
|
||||
|
||||
// Resolve if cached
|
||||
if (this._dependencies) {
|
||||
return Q.fcall(this._dependencies);
|
||||
}
|
||||
|
||||
// Check if name defined in the json is different
|
||||
// If so and if the name was "guessed", assume the json name
|
||||
if (this._guessedName && json.name !== this.name) {
|
||||
this.name = json.name;
|
||||
this.emit('name_change', this.name);
|
||||
}
|
||||
|
||||
// Handle ignore property, deleting all files from the temporary directory
|
||||
return Q.fcall(function () {
|
||||
// Delete all the files specified in the ignore from the temporary directory
|
||||
// TODO:
|
||||
}.bind(this))
|
||||
// Handle the dependencies property
|
||||
.then(function () {
|
||||
var key,
|
||||
promises = [];
|
||||
|
||||
// Read the dependencies, creating a package for each one
|
||||
createPackage = createPackage || require('./createPackage');
|
||||
if (json.dependencies) {
|
||||
for (key in json.dependencies) {
|
||||
promises.push(createPackage(json.dependencies[key], { name: key, unitOfWork: this._unitOfWork }));
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve all the create packages promises
|
||||
return Q.all(promises).then(function (packages) {
|
||||
this._dependencies = packages;
|
||||
return packages;
|
||||
}.bind(this));
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Package.prototype._resolveDependencies = function (dependencies) {
|
||||
console.log('_resolveDependencies');
|
||||
|
||||
var promises = dependencies.map(function (dep) {
|
||||
return dep.resolve();
|
||||
});
|
||||
|
||||
return Q.all(promises);
|
||||
};
|
||||
|
||||
Package.prototype._assertResolved = function () {
|
||||
if (!this._resolved) {
|
||||
throw createError('Package is not yet resolved', 'ENOTRES');
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Package;
|
||||
@@ -1,75 +0,0 @@
|
||||
var util = require('util');
|
||||
var Q = require('q');
|
||||
var Package = require('../Package');
|
||||
|
||||
var GitRemotePackage = function (endpoint, options) {
|
||||
Package.call(this, endpoint, options);
|
||||
};
|
||||
|
||||
util.inherits(GitRemotePackage, Package);
|
||||
|
||||
// -----------------
|
||||
|
||||
GitRemotePackage.prototype._resolveSelf = function () {
|
||||
var promise;
|
||||
|
||||
console.log('_resolveSelf of git remote package');
|
||||
promise = this._clone()
|
||||
.then(this._fetch.bind(this))
|
||||
.then(this._versions.bind(this))
|
||||
.then(this._checkout.bind(this));
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
GitRemotePackage.prototype._clone = function () {
|
||||
// check cache
|
||||
// clone only if not cached
|
||||
var deferred = Q.defer();
|
||||
|
||||
console.log('_clone');
|
||||
setTimeout(function () {
|
||||
deferred.resolve();
|
||||
}, 1000);
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
GitRemotePackage.prototype._fetch = function () {
|
||||
// fetch origin with --prune
|
||||
// reset --hard origin/HEAD
|
||||
var deferred = Q.defer();
|
||||
|
||||
console.log('_fetch');
|
||||
setTimeout(function () {
|
||||
deferred.resolve();
|
||||
}, 1000);
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
GitRemotePackage.prototype._versions = function () {
|
||||
// retrieve versions
|
||||
var deferred = Q.defer();
|
||||
|
||||
console.log('_versions');
|
||||
setTimeout(function () {
|
||||
deferred.resolve();
|
||||
}, 1000);
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
GitRemotePackage.prototype._checkout = function () {
|
||||
// resolve range to a specific version and check it out
|
||||
var deferred = Q.defer();
|
||||
|
||||
console.log('_checkout');
|
||||
setTimeout(function () {
|
||||
deferred.resolve();
|
||||
}, 1000);
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
module.exports = GitRemotePackage;
|
||||
@@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
UrlPackage: require('./UrlPackage'),
|
||||
GitFsPackage: require('./GitFsPackage'),
|
||||
GitRemotePackage: require('./GitRemotePackage')
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
commands: require('./commands'),
|
||||
config: require('./core/config')
|
||||
config: require('./config')
|
||||
};
|
||||
0
lib/resolve/Manager.js
Normal file
0
lib/resolve/Manager.js
Normal file
@@ -1,7 +1,11 @@
|
||||
var Q = require('Q');
|
||||
var packages = require('./packages');
|
||||
var GitFsResolver = require('./resolvers/GitFsResolver');
|
||||
var GitRemoteResolver = require('./resolvers/GitRemoteResolver');
|
||||
var LocalResolver = require('./resolvers/LocalResolver');
|
||||
var UrlResolver = require('./resolvers/UrlResolver');
|
||||
var GitFsResolver = require('./resolvers/GitFsResolver');
|
||||
|
||||
function createPackage(endpoint, options) {
|
||||
function createResolver(endpoint, options) {
|
||||
var split = endpoint.split('#'),
|
||||
range;
|
||||
|
||||
0
lib/resolve/resolvers/FsResolver.js
Normal file
0
lib/resolve/resolvers/FsResolver.js
Normal file
200
lib/resolve/resolvers/GitRemoteResolver.js
Normal file
200
lib/resolve/resolvers/GitRemoteResolver.js
Normal file
@@ -0,0 +1,200 @@
|
||||
var util = require('util');
|
||||
var Q = require('q');
|
||||
var semver = require('semver');
|
||||
var mout = require('mout');
|
||||
var Resolver = require('./Resolver');
|
||||
var cmd = require('../../util/cmd');
|
||||
var createError = require('../../util/createError');
|
||||
|
||||
var GitRemoteResolver = function (source, options) {
|
||||
Resolver.call(this, source, options);
|
||||
};
|
||||
|
||||
util.inherits(GitRemoteResolver, Resolver);
|
||||
|
||||
// -----------------
|
||||
|
||||
GitRemoteResolver.prototype.hasNew = function (oldTarget, oldResolution) {
|
||||
return this._resolveTarget(this._target)
|
||||
.then(function (resolution) {
|
||||
// Resolution types are different
|
||||
if (oldResolution.type !== resolution.type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If resolved to a tag
|
||||
// There is new content if the tags are not equal
|
||||
if (resolution.type === 'tag') {
|
||||
return semver.neq(resolution.tag, oldResolution.tag);
|
||||
}
|
||||
|
||||
|
||||
// If resolved to a commit hash, just check if they are different
|
||||
// Use the same strategy if it the resolution is to a branch
|
||||
return resolution.commit !== oldResolution.commit;
|
||||
});
|
||||
};
|
||||
|
||||
GitRemoteResolver.prototype._resolveSelf = function () {
|
||||
var promise;
|
||||
|
||||
promise = this._resolveTarget()
|
||||
.then(this._checkout.bind(this));
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
GitRemoteResolver.prototype._resolveTarget = function () {
|
||||
var target = this._target,
|
||||
source = this._source,
|
||||
promise,
|
||||
branches,
|
||||
errorMessage,
|
||||
errorDetails;
|
||||
|
||||
// Target is a range/version
|
||||
if (semver.valid(target) || semver.validRange(target)) {
|
||||
return GitRemoteResolver._fetchVersions(this._source)
|
||||
.then(function (versions) {
|
||||
// Find the highest one that satifies the target
|
||||
var version = mout.array.find(versions, function (version) {
|
||||
return semver.satisfies(version, target);
|
||||
});
|
||||
|
||||
if (!version) {
|
||||
errorMessage = !semver.validRange(target) ?
|
||||
'Tag "' + target + '" does not exist' :
|
||||
'No tag found that was able to satisfy "' + target + '"';
|
||||
errorDetails = !versions.length ?
|
||||
'No tags found in "' + source + '"' :
|
||||
'Available tags in "' + source + '" are: ' + versions.join(', ');
|
||||
throw createError(errorMessage, 'ENORESTARGET', errorDetails);
|
||||
}
|
||||
|
||||
return { type: 'tag', tag: version };
|
||||
});
|
||||
}
|
||||
|
||||
// Resolve the rest to a commit version
|
||||
promise = GitRemoteResolver._fetchHeads(this._source);
|
||||
|
||||
// Target is a commit, so it's a stale target (not a moving target)
|
||||
// There's nothing to do in this case
|
||||
if ((/^[a-f0-9]{40}$/).test(target)) {
|
||||
return Q.resolve({ type: 'commit', commit: target });
|
||||
}
|
||||
|
||||
// If target is *, use master branch
|
||||
if (target === '*') {
|
||||
target = 'master';
|
||||
}
|
||||
|
||||
// Target is a branch
|
||||
return promise.then(function (heads) {
|
||||
if (!heads[target]) {
|
||||
branches = Object.keys(heads);
|
||||
errorDetails = !branches.length ?
|
||||
'No branches found in "' + source + '"' :
|
||||
'Available branches in "' + source + '" are ' + branches.join(', ');
|
||||
|
||||
throw createError('Branch "' + target + '" does not exist', 'ENORESTARGET', errorDetails);
|
||||
}
|
||||
|
||||
return { type: 'branch', branch: target, commit: heads[target] };
|
||||
});
|
||||
};
|
||||
|
||||
GitRemoteResolver.prototype._checkout = function (resolution) {
|
||||
var dir = this._tempDir,
|
||||
branch;
|
||||
|
||||
console.log(resolution);
|
||||
if (resolution.type === 'commit') {
|
||||
return Q.nfcall(cmd, 'git', ['clone', this._source, dir])
|
||||
.then(function () {
|
||||
return Q.nfcall(cmd, 'git', ['checkout', resolution.commit], { cwd: dir });
|
||||
});
|
||||
} else {
|
||||
branch = resolution.tag || resolution.branch;
|
||||
return Q.nfcall(cmd, 'git', ['clone', this._source, '-b', branch, '--depth', 1], { cwd: dir });
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------
|
||||
|
||||
GitRemoteResolver._fetchRefs = function (source) {
|
||||
if (this._refs && this._refs[source]) {
|
||||
return Q.resolve(this._refs[source]);
|
||||
}
|
||||
|
||||
return Q.nfcall(cmd, 'git', ['ls-remote', '--tags', '--heads', source])
|
||||
.then(function (stdout) {
|
||||
// Make them an array
|
||||
var refs = stdout.toString().split('\n');
|
||||
|
||||
this._refs = this._refs || {};
|
||||
return this._refs[source] = refs;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
GitRemoteResolver._fetchVersions = function (source) {
|
||||
if (this._versions && this._versions[source]) {
|
||||
return Q.resolve(this._versions[source]);
|
||||
}
|
||||
|
||||
return this._fetchRefs(source)
|
||||
.then(function (refs) {
|
||||
var versions = [];
|
||||
|
||||
// Parse each ref line, extracting the tag
|
||||
refs.forEach(function (line) {
|
||||
var match = line.match(/^[a-f0-9]{40}\s+refs\/tags\/(\S+)$/),
|
||||
cleaned;
|
||||
|
||||
// Ensure it's valid
|
||||
if (match) {
|
||||
cleaned = semver.clean(match[1]);
|
||||
if (cleaned) {
|
||||
versions.push(cleaned);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Sort them by desc order
|
||||
versions = versions.sort(function (a, b) {
|
||||
return semver.gt(a, b) ? -1 : 1;
|
||||
});
|
||||
|
||||
this._versions = this._versions || {};
|
||||
return this._versions[source] = versions;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
GitRemoteResolver._fetchHeads = function (source) {
|
||||
if (this._heads && this._heads[source]) {
|
||||
return Q.resolve(this._heads[source]);
|
||||
}
|
||||
|
||||
// Request heads of the source of only the specified branch
|
||||
return this._fetchRefs(source)
|
||||
.then(function (refs) {
|
||||
this._heads = this._heads || {};
|
||||
var heads = this._heads[source] = this._heads[source] || {};
|
||||
|
||||
// Foreach line in the refs, extract only the heads
|
||||
// Organize them in an object where keys are branches and values
|
||||
// the commit hash
|
||||
mout.array.forEach(refs, function (line) {
|
||||
var match = line.match(/^([a-f0-9]{40})\s+refs\/heads\/(\S+)$/);
|
||||
|
||||
if (match) {
|
||||
heads[match[2]] = match[1];
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return heads;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
module.exports = GitRemoteResolver;
|
||||
138
lib/resolve/resolvers/Resolver.js
Normal file
138
lib/resolve/resolvers/Resolver.js
Normal file
@@ -0,0 +1,138 @@
|
||||
var util = require('util');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var events = require('events');
|
||||
var Q = require('q');
|
||||
var tmp = require('tmp');
|
||||
var config = require('../../config');
|
||||
var createError = require('../../util/createError');
|
||||
|
||||
var Resolver = function (source, options) {
|
||||
options = options || {};
|
||||
|
||||
this._source = source;
|
||||
this._target = options.target || '*';
|
||||
this._name = options.name;
|
||||
this._guessedName = !this.name;
|
||||
this._config = options.config || config;
|
||||
};
|
||||
|
||||
util.inherits(Resolver, events.EventEmitter);
|
||||
|
||||
// -----------------
|
||||
|
||||
Resolver.prototype.getSource = function () {
|
||||
return this._name;
|
||||
};
|
||||
|
||||
Resolver.prototype.getTarget = function () {
|
||||
return this._target;
|
||||
};
|
||||
|
||||
Resolver.prototype.getTempDir = function () {
|
||||
return this._tempDir;
|
||||
};
|
||||
|
||||
Resolver.prototype.resolve = function () {
|
||||
// 1nd - Create temporary dir
|
||||
return this._createTempDir()
|
||||
// 2nd - Resolve self
|
||||
.then(this._resolveSelf.bind(this))
|
||||
// 3th - Read json
|
||||
.then(this._readJson.bind(this))
|
||||
// 4th - Parse json
|
||||
.then(this._parseJson.bind(this));
|
||||
};
|
||||
|
||||
Resolver.prototype.isCacheable = function () {
|
||||
return false;
|
||||
};
|
||||
|
||||
Resolver.prototype.getDependencies = function () {
|
||||
return this._json.dependencies;
|
||||
};
|
||||
|
||||
// -----------------
|
||||
|
||||
Resolver.prototype.hasNew = function (oldTarget, oldResolution) {
|
||||
return true;
|
||||
};
|
||||
|
||||
Resolver.prototype._resolveSelf = function () {};
|
||||
|
||||
// -----------------
|
||||
|
||||
Resolver.prototype._createTempDir = function () {
|
||||
return Q.nfcall(tmp.dir, {
|
||||
prefix: 'bower-' + this._name + '-', // TODO: add a bower folder as the prefix
|
||||
mode: parseInt('0777', 8) & (~process.umask()),
|
||||
unsafeCleanup: true
|
||||
})
|
||||
.then(function (dir) {
|
||||
this._tempDir = dir;
|
||||
return dir;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
Resolver.prototype._readJson = function () {
|
||||
var jsonFile;
|
||||
|
||||
// Try bower.json
|
||||
jsonFile = path.join(this.getTempDir(), 'bower.json');
|
||||
return Q.nfcall(fs.readFile, jsonFile)
|
||||
// Try component.json
|
||||
.then(null, function (err) {
|
||||
if (err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
|
||||
jsonFile = path.join(this.getTempDir(), 'component.json');
|
||||
return Q.nfcall(fs.readFile, jsonFile)
|
||||
// Issue a deprecation message if it exists
|
||||
.then(function (contents) {
|
||||
this.emit('warn', 'Package "' + this.name + '" is using the deprecated component.json file');
|
||||
return contents;
|
||||
}.bind(this));
|
||||
}.bind(this))
|
||||
// If we got the file contents, validate them
|
||||
.then(function (contents) {
|
||||
// TODO: change the validation to a separate module in the bower organization
|
||||
try {
|
||||
this._json = JSON.parse(contents);
|
||||
return this._json;
|
||||
} catch (e) {
|
||||
throw createError('Unable to parse "' + jsonFile + '" file', e.code, {
|
||||
details: e.message
|
||||
});
|
||||
}
|
||||
// Otherwise there was an error
|
||||
}.bind(this), function (err) {
|
||||
// If no json file was found, return one just with the name
|
||||
if (err.code === 'ENOENT') {
|
||||
this._json = { name: this.name };
|
||||
return this._json;
|
||||
}
|
||||
|
||||
// If we got here, the error code is something else so we re-throw it
|
||||
throw err;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
Resolver.prototype._parseJson = function () {
|
||||
// Check if name defined in the json is different
|
||||
// If so and if the name was "guessed", assume the json name
|
||||
if (this._guessedName && this._json.name !== this.name) {
|
||||
this.name = this._json.name;
|
||||
this.emit('name_change', this.name);
|
||||
}
|
||||
|
||||
this._json.dependencies = this._json.dependencies || {};
|
||||
|
||||
// Handle ignore property, deleting all files from the temporary directory
|
||||
return Q.fcall(function () {
|
||||
// Delete all the files specified in the ignore from the temporary directory
|
||||
// TODO:
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
module.exports = Resolver;
|
||||
52
lib/util/cmd.js
Normal file
52
lib/util/cmd.js
Normal file
@@ -0,0 +1,52 @@
|
||||
var cp = require('child_process');
|
||||
var createError = require('./createError');
|
||||
|
||||
// Executes a shell command
|
||||
|
||||
// TODO: I think we need to use spawn because it escapes args
|
||||
|
||||
module.exports = function (command, args, options, callback) {
|
||||
var process,
|
||||
stderr = '',
|
||||
stdout = '';
|
||||
|
||||
if (!callback) {
|
||||
callback = options || args;
|
||||
}
|
||||
|
||||
process = cp.spawn(command, args, options);
|
||||
|
||||
process.stdout.on('data', function (data) {
|
||||
stdout += data.toString();
|
||||
});
|
||||
|
||||
process.stderr.on('data', function (data) {
|
||||
stderr += data.toString();
|
||||
});
|
||||
|
||||
process.on('exit', function (code) {
|
||||
var fullCommand,
|
||||
error;
|
||||
|
||||
process.removeAllListeners();
|
||||
|
||||
if (code) {
|
||||
// Generate the full command to be presented in the error message
|
||||
if (!Array.isArray(args)) {
|
||||
args = [];
|
||||
}
|
||||
|
||||
fullCommand = command;
|
||||
fullCommand += args.length ? ' ' + args.join(' ') : '';
|
||||
|
||||
// Build the error instance
|
||||
error = createError('Failed to execute "' + fullCommand + '", exit code of #' + code, 'ECMDERR');
|
||||
error.details = stderr;
|
||||
error.exitCode = code;
|
||||
|
||||
return callback(error);
|
||||
}
|
||||
|
||||
return callback(null, stdout, stderr);
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user