Update resolver implementation according to the API, integrate bower-json package.

This commit is contained in:
André Cruz
2013-04-20 14:09:01 +01:00
parent bb8c456a04
commit b1e97266e3
6 changed files with 69 additions and 75 deletions

View File

@@ -5,6 +5,7 @@ var events = require('events');
var Q = require('q');
var tmp = require('tmp');
var mkdirp = require('mkdirp');
var bowerJson = require('bower-json');
var config = require('../config');
var createError = require('../util/createError');
@@ -34,29 +35,43 @@ Resolver.prototype.getTempDir = function () {
return this._tempDir;
};
Resolver.prototype.hasNew = function (canonicalPkg) {
return Q.resolve(true);
};
Resolver.prototype.resolve = function () {
// Create temporary dir
return this._createTempDir()
// Resolve self
.then(this._resolveSelf.bind(this))
// Read json
.then(this._readJson.bind(this))
// Parse json
.then(this._parseJson.bind(this));
// Read json, generating the package meta
.then(function () {
return this._readJson(this._tempDir);
}.bind(this))
.then(function (meta) {
return Q.all([
// Apply package meta
this._applyPkgMeta(meta),
// Save package meta
this._savePkgMeta(meta)
]);
}.bind(this))
.then(function () {
// Resolve with the folder
return this._tempDir;
});
};
Resolver.prototype.hasNew = function (oldResolution) {
return Q.resolve(true);
};
Resolver.prototype.getDependencies = function () {
return this._json.dependencies;
Resolver.prototype.getPkgMeta = function () {
return this._pkgMeta;
};
// -----------------
// Abstract function that should be implemented by concrete resolvers
Resolver.prototype._resolveSelf = function () {};
Resolver.prototype._resolveSelf = function () {
throw new Error('_resolveSelf not implemented');
};
// -----------------
@@ -67,7 +82,7 @@ Resolver.prototype._createTempDir = function () {
.then(function () {
return Q.nfcall(tmp.dir, {
template: path.join(baseDir, this._name + '-XXXXXX'),
mode: parseInt('0777', 8) & (~process.umask()),
mode: parseInt('0777', 8) & (~process.umask())
//unsafeCleanup: true // TODO: don't forget enable this
});
}.bind(this))
@@ -80,60 +95,35 @@ Resolver.prototype._createTempDir = function () {
}.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) {
Resolver.prototype._readJson = function (dir) {
return Q.nfcall(bowerJson.find, dir)
.then(function (filename) {
// If it is a component.json, warn about the deprecation
if (path.basename(filename) === 'component.json') {
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;
// Read it
return Q.nfcall(bowerJson.read, filename)
.then(null, function (err) {
throw createError('Something went wrong when reading "' + filename + '"', err.code, {
details: err.message
});
});
}.bind(this), function () {
// No json file was found, assume one
return Q.nfcall(bowerJson.parse, { name: this._name });
}.bind(this));
};
Resolver.prototype._parseJson = function () {
Resolver.prototype._applyPkgMeta = function (meta) {
// 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;
if (this._guessedName && meta.name !== this.name) {
this.name = meta.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
@@ -141,4 +131,12 @@ Resolver.prototype._parseJson = function () {
}.bind(this));
};
Resolver.prototype._savePkgMeta = function (meta) {
var contents = JSON.stringify(meta, null, 2);
return Q.nfcall(fs.writeFile, path.join(this._tempDir, '.bower.json'), contents)
.then(function () {
this._pkgMeta = meta;
}.bind(this));
};
module.exports = Resolver;

View File

@@ -24,37 +24,33 @@ mout.object.mixIn(GitFsResolver, GitResolver);
GitFsResolver.prototype._resolveSelf = function () {
return this._findResolution()
.then(this._copy.bind(this))
.then(function () {
return this._checkout(this._resolution);
}.bind(this));
.then(this._checkout.bind(this));
};
// -----------------
GitFsResolver.prototype._copy = function () {
var tempDir = this._tempDir;
// Copy folder permissions
return Q.nfcall(fs.stat, this._source)
.then(function (stat) {
return Q.nfcall(fs.chmod, tempDir, stat.mode);
})
return Q.nfcall(fs.chmod, this._tempDir, stat.mode);
}.bind(this))
// Copy folder contents
.then(function () {
return Q.nfcall(ncp, this._source, tempDir);
return Q.nfcall(ncp, this._source, this._tempDir);
}.bind(this));
};
// Override the checkout function to work with the local copy
GitFsResolver.prototype._checkout = function (resolution) {
var dir = this._tempDir;
GitFsResolver.prototype._checkout = function () {
var resolution = this._resolution;
console.log(resolution);
// Checkout resolution
return cmd('git', ['checkout', '-f', resolution.tag || resolution.branch || resolution.commit], { cwd: dir })
return cmd('git', ['checkout', '-f', resolution.tag || resolution.branch || resolution.commit], { cwd: this._tempDir })
// Cleanup unstagged files
.then(cmd.bind(cmd, 'git', ['clean', '-f', '-d'], { cwd: dir }));
.then(cmd.bind(cmd, 'git', ['clean', '-f', '-d'], { cwd: this._tempDir }));
};
// -----------------

View File

@@ -13,21 +13,21 @@ mout.object.mixIn(GitRemoteResolver, GitResolver);
// -----------------
GitRemoteResolver.prototype._checkout = function (resolution) {
var dir = this._tempDir,
branch;
GitRemoteResolver.prototype._checkout = function () {
var branch,
resolution = this._resolution;
console.log(resolution);
// If resolution is a commit, we need to clone the entire repo and checkit out
// Because a commit is not a nammed ref, there's no better solution
if (resolution.type === 'commit') {
return cmd('git', ['clone', this._source, '.'], { cwd: dir })
.then(cmd.bind(cmd, 'git', ['checkout', resolution.commit], { cwd: dir }));
return cmd('git', ['clone', this._source, this._tempDir])
.then(cmd.bind(cmd, 'git', ['checkout', resolution.commit], { cwd: this._tempDir }));
// Otherwise we are checking out a named ref so we can optimize it
} else {
branch = resolution.tag || resolution.branch;
return cmd('git', ['clone', this._source, '-b', branch, '--depth', 1, '.'], { cwd: dir });
return cmd('git', ['clone', this._source, '-b', branch, '--depth', 1, '.'], { cwd: this._tempDir });
}
};

View File

@@ -158,7 +158,6 @@ GitResolver.fetchHeads = function (source) {
}
});
return heads;
}.bind(this));
};