mirror of
https://github.com/bower/bower.git
synced 2026-01-14 08:47:54 -05:00
155 lines
4.4 KiB
JavaScript
155 lines
4.4 KiB
JavaScript
var util = require('util');
|
|
var fs = require('../../util/fs');
|
|
var path = require('path');
|
|
var mout = require('mout');
|
|
var Q = require('q');
|
|
var junk = require('junk');
|
|
var Resolver = require('./Resolver');
|
|
var copy = require('../../util/copy');
|
|
var extract = require('../../util/extract');
|
|
var createError = require('../../util/createError');
|
|
|
|
function FsResolver(decEndpoint, config, logger) {
|
|
Resolver.call(this, decEndpoint, config, logger);
|
|
|
|
// Ensure absolute path
|
|
this._source = path.resolve(this._config.cwd, this._source);
|
|
|
|
// If target was specified, simply reject the promise
|
|
if (this._target !== '*') {
|
|
throw createError(
|
|
"File system sources can't resolve targets",
|
|
'ENORESTARGET'
|
|
);
|
|
}
|
|
|
|
// If the name was guessed
|
|
if (this._guessedName) {
|
|
// Remove extension
|
|
this._name = this._name.substr(
|
|
0,
|
|
this._name.length - path.extname(this._name).length
|
|
);
|
|
}
|
|
}
|
|
|
|
util.inherits(FsResolver, Resolver);
|
|
mout.object.mixIn(FsResolver, Resolver);
|
|
|
|
// -----------------
|
|
|
|
FsResolver.isTargetable = function() {
|
|
return false;
|
|
};
|
|
|
|
// TODO: Should we store latest mtimes in the resolution and compare?
|
|
// This would be beneficial when copying big files/folders
|
|
|
|
// TODO: There's room for improvement by using streams if the source
|
|
// is an archive file, by piping read stream to the zip extractor
|
|
// This will likely increase the complexity of code but might worth it
|
|
FsResolver.prototype._resolve = function() {
|
|
return this._copy()
|
|
.then(this._extract.bind(this))
|
|
.then(this._rename.bind(this));
|
|
};
|
|
|
|
// -----------------
|
|
|
|
FsResolver.prototype._copy = function() {
|
|
var that = this;
|
|
|
|
return Q.nfcall(fs.stat, this._source).then(function(stat) {
|
|
var dst;
|
|
var copyOpts;
|
|
var promise;
|
|
|
|
that._sourceStat = stat;
|
|
copyOpts = { mode: stat.mode };
|
|
|
|
// If it's a folder
|
|
if (stat.isDirectory()) {
|
|
dst = that._tempDir;
|
|
|
|
// Read the bower.json inside the folder, so that we
|
|
// copy only the necessary files if it has ignore specified
|
|
promise = that
|
|
._readJson(that._source)
|
|
.then(function(json) {
|
|
copyOpts.ignore = json.ignore;
|
|
return copy.copyDir(that._source, dst, copyOpts);
|
|
})
|
|
.then(function() {
|
|
// Resolve to null because it's a dir
|
|
return;
|
|
});
|
|
// Else it's a file
|
|
} else {
|
|
dst = path.join(that._tempDir, path.basename(that._source));
|
|
promise = copy
|
|
.copyFile(that._source, dst, copyOpts)
|
|
.then(function() {
|
|
return dst;
|
|
});
|
|
}
|
|
|
|
that._logger.action('copy', that._source, {
|
|
src: that._source,
|
|
dst: dst
|
|
});
|
|
|
|
return promise;
|
|
});
|
|
};
|
|
|
|
FsResolver.prototype._extract = function(file) {
|
|
if (!file || !extract.canExtract(file)) {
|
|
return Q.resolve();
|
|
}
|
|
|
|
this._logger.action('extract', path.basename(this._source), {
|
|
archive: file,
|
|
to: this._tempDir
|
|
});
|
|
|
|
return extract(file, this._tempDir);
|
|
};
|
|
|
|
FsResolver.prototype._rename = function() {
|
|
return Q.nfcall(fs.readdir, this._tempDir).then(
|
|
function(files) {
|
|
var file;
|
|
var oldPath;
|
|
var newPath;
|
|
|
|
// Remove any OS specific files from the files array
|
|
// before checking its length
|
|
files = files.filter(junk.isnt);
|
|
|
|
// Only rename if there's only one file and it's not the json
|
|
if (
|
|
files.length === 1 &&
|
|
!/^(bower|component)\.json$/.test(files[0])
|
|
) {
|
|
file = files[0];
|
|
this._singleFile = 'index' + path.extname(file);
|
|
oldPath = path.join(this._tempDir, file);
|
|
newPath = path.join(this._tempDir, this._singleFile);
|
|
|
|
return Q.nfcall(fs.rename, oldPath, newPath);
|
|
}
|
|
}.bind(this)
|
|
);
|
|
};
|
|
|
|
FsResolver.prototype._savePkgMeta = function(meta) {
|
|
// Store main if is a single file
|
|
if (this._singleFile) {
|
|
meta.main = this._singleFile;
|
|
}
|
|
|
|
return Resolver.prototype._savePkgMeta.call(this, meta);
|
|
};
|
|
|
|
module.exports = FsResolver;
|