set basic layout. adding status bar

This commit is contained in:
Rohit
2019-06-04 13:11:32 -04:00
parent cd7f6c8648
commit dbd8de27cc
7977 changed files with 757176 additions and 310 deletions

1284
node_modules/bower/lib/core/Manager.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

304
node_modules/bower/lib/core/PackageRepository.js generated vendored Normal file
View File

@@ -0,0 +1,304 @@
var mout = require('mout');
var Q = require('q');
var ResolveCache = require('./ResolveCache');
var resolverFactory = require('./resolverFactory');
var createError = require('../util/createError');
var RegistryClient = require('bower-registry-client');
function PackageRepository(config, logger) {
var registryOptions;
this._config = config;
this._logger = logger;
// Instantiate the registry
registryOptions = mout.object.deepMixIn({}, this._config);
registryOptions.cache = this._config.storage.registry;
this._registryClient = new RegistryClient(registryOptions, logger);
// Instantiate the resolve cache
this._resolveCache = new ResolveCache(this._config);
}
// -----------------
PackageRepository.prototype.fetch = function(decEndpoint) {
var logger;
var that = this;
var isTargetable;
var info = {
decEndpoint: decEndpoint
};
// Create a new logger that pipes everything to ours that will be
// used to fetch
logger = this._logger.geminate();
// Intercept all logs, adding additional information
logger.intercept(function(log) {
that._extendLog(log, info);
});
return (
this._getResolver(decEndpoint, logger)
// Decide if we retrieve from the cache or not
// Also decide if we validate the cached entry or not
.then(function(resolver) {
info.resolver = resolver;
isTargetable = resolver.constructor.isTargetable;
if (!resolver.isCacheable()) {
return that._resolve(resolver, logger);
}
// If force flag is used, bypass cache, but write to cache anyway
if (that._config.force) {
logger.action(
'resolve',
resolver.getSource() + '#' + resolver.getTarget()
);
return that._resolve(resolver, logger);
}
// Note that we use the resolver methods to query the
// cache because transformations/normalisations can occur
return (
that._resolveCache
.retrieve(resolver.getSource(), resolver.getTarget())
// Decide if we can use the one from the resolve cache
.spread(function(canonicalDir, pkgMeta) {
// If there's no package in the cache
if (!canonicalDir) {
// And the offline flag is passed, error out
if (that._config.offline) {
throw createError(
'No cached version for ' +
resolver.getSource() +
'#' +
resolver.getTarget(),
'ENOCACHE',
{
resolver: resolver
}
);
}
// Otherwise, we have to resolve it
logger.info(
'not-cached',
resolver.getSource() +
(resolver.getTarget()
? '#' + resolver.getTarget()
: '')
);
logger.action(
'resolve',
resolver.getSource() +
'#' +
resolver.getTarget()
);
return that._resolve(resolver, logger);
}
info.canonicalDir = canonicalDir;
info.pkgMeta = pkgMeta;
logger.info(
'cached',
resolver.getSource() +
(pkgMeta._release
? '#' + pkgMeta._release
: '')
);
// If offline flag is used, use directly the cached one
if (that._config.offline) {
return [canonicalDir, pkgMeta, isTargetable];
}
// Otherwise check for new contents
logger.action(
'validate',
(pkgMeta._release
? pkgMeta._release + ' against '
: '') +
resolver.getSource() +
(resolver.getTarget()
? '#' + resolver.getTarget()
: '')
);
return resolver
.hasNew(pkgMeta)
.then(function(hasNew) {
// If there are no new contents, resolve to
// the cached one
if (!hasNew) {
return [
canonicalDir,
pkgMeta,
isTargetable
];
}
// Otherwise resolve to the newest one
logger.info(
'new',
'version for ' +
resolver.getSource() +
'#' +
resolver.getTarget()
);
logger.action(
'resolve',
resolver.getSource() +
'#' +
resolver.getTarget()
);
return that._resolve(resolver, logger);
});
})
);
})
// If something went wrong, also extend the error
.fail(function(err) {
that._extendLog(err, info);
throw err;
})
);
};
PackageRepository.prototype.versions = function(source) {
// Resolve the source using the factory because the
// source can actually be a registry name
return this._getResolver({ source: source }).then(
function(resolver) {
// If offline, resolve using the cached versions
if (this._config.offline) {
return this._resolveCache.versions(resolver.getSource());
}
// Otherwise, fetch remotely
return resolver.constructor.versions(resolver.getSource());
}.bind(this)
);
};
PackageRepository.prototype.eliminate = function(pkgMeta) {
return Q.all([
this._resolveCache.eliminate(pkgMeta),
Q.nfcall(
this._registryClient.clearCache.bind(this._registryClient),
pkgMeta.name
)
]);
};
PackageRepository.prototype.clear = function() {
return Q.all([
this._resolveCache.clear(),
Q.nfcall(this._registryClient.clearCache.bind(this._registryClient))
]);
};
PackageRepository.prototype.reset = function() {
this._resolveCache.reset();
this._registryClient.resetCache();
};
PackageRepository.prototype.list = function() {
return this._resolveCache.list();
};
PackageRepository.prototype.getRegistryClient = function() {
return this._registryClient;
};
PackageRepository.prototype.getResolveCache = function() {
return this._resolveCache;
};
PackageRepository.clearRuntimeCache = function() {
ResolveCache.clearRuntimeCache();
RegistryClient.clearRuntimeCache();
resolverFactory.clearRuntimeCache();
};
// ---------------------
PackageRepository.prototype._getResolver = function(decEndpoint, logger) {
logger = logger || this._logger;
// Get the appropriate resolver
return resolverFactory(
decEndpoint,
{ config: this._config, logger: logger },
this._registryClient
);
};
PackageRepository.prototype._resolve = function(resolver, logger) {
var that = this;
// Resolve the resolver
return (
resolver
.resolve()
// Store in the cache
.then(function(canonicalDir) {
if (!resolver.isCacheable()) {
return canonicalDir;
}
return that._resolveCache.store(
canonicalDir,
resolver.getPkgMeta()
);
})
// Resolve promise with canonical dir and package meta
.then(function(dir) {
var pkgMeta = resolver.getPkgMeta();
logger.info(
'resolved',
resolver.getSource() +
(pkgMeta._release ? '#' + pkgMeta._release : '')
);
return [dir, pkgMeta, resolver.constructor.isTargetable()];
})
);
};
PackageRepository.prototype._extendLog = function(log, info) {
log.data = log.data || {};
// Store endpoint info in each log
if (info.decEndpoint) {
log.data.endpoint = mout.object.pick(info.decEndpoint, [
'name',
'source',
'target'
]);
}
// Store the resolver info in each log
if (info.resolver) {
log.data.resolver = {
name: info.resolver.getName(),
source: info.resolver.getSource(),
target: info.resolver.getTarget()
};
}
// Store the canonical dir and its meta in each log
if (info.canonicalDir) {
log.data.canonicalDir = info.canonicalDir;
log.data.pkgMeta = info.pkgMeta;
}
return log;
};
module.exports = PackageRepository;

1033
node_modules/bower/lib/core/Project.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

440
node_modules/bower/lib/core/ResolveCache.js generated vendored Normal file
View File

@@ -0,0 +1,440 @@
var fs = require('../util/fs');
var path = require('path');
var mout = require('mout');
var Q = require('q');
var mkdirp = require('mkdirp');
var rimraf = require('../util/rimraf');
var LRU = require('lru-cache');
var lockFile = require('lockfile');
var md5 = require('md5-hex');
var semver = require('../util/semver');
var readJson = require('../util/readJson');
var copy = require('../util/copy');
function ResolveCache(config) {
// TODO: Make some config entries, such as:
// - Max MB
// - Max versions per source
// - Max MB per source
// - etc..
this._config = config;
this._dir = this._config.storage.packages;
this._lockDir = this._config.storage.packages;
mkdirp.sync(this._lockDir);
// Cache is stored/retrieved statically to ensure singularity
// among instances
this._cache = this.constructor._cache.get(this._dir);
if (!this._cache) {
this._cache = new LRU({
max: 100,
maxAge: 60 * 5 * 1000 // 5 minutes
});
this.constructor._cache.set(this._dir, this._cache);
}
// Ensure dir is created
mkdirp.sync(this._dir);
}
// -----------------
ResolveCache.prototype.retrieve = function(source, target) {
var sourceId = md5(source);
var dir = path.join(this._dir, sourceId);
var that = this;
target = target || '*';
return this._getVersions(sourceId)
.spread(function(versions) {
var suitable;
// If target is a semver, find a suitable version
if (semver.validRange(target)) {
suitable = semver.maxSatisfying(versions, target, true);
if (suitable) {
return suitable;
}
}
// If target is '*' check if there's a cached '_wildcard'
if (target === '*') {
return mout.array.find(versions, function(version) {
return version === '_wildcard';
});
}
// Otherwise check if there's an exact match
return mout.array.find(versions, function(version) {
return version === target;
});
})
.then(function(version) {
var canonicalDir;
if (!version) {
return [];
}
// Resolve with canonical dir and package meta
canonicalDir = path.join(dir, encodeURIComponent(version));
return that._readPkgMeta(canonicalDir).then(
function(pkgMeta) {
return [canonicalDir, pkgMeta];
},
function() {
// If there was an error, invalidate the in-memory cache,
// delete the cached package and try again
that._cache.del(sourceId);
return Q.nfcall(rimraf, canonicalDir).then(function() {
return that.retrieve(source, target);
});
}
);
});
};
ResolveCache.prototype.store = function(canonicalDir, pkgMeta) {
var sourceId;
var release;
var dir;
var pkgLock;
var promise;
var that = this;
promise = pkgMeta ? Q.resolve(pkgMeta) : this._readPkgMeta(canonicalDir);
return promise
.then(function(pkgMeta) {
sourceId = md5(pkgMeta._source);
release = that._getPkgRelease(pkgMeta);
dir = path.join(that._dir, sourceId, release);
pkgLock = path.join(
that._lockDir,
sourceId + '-' + release + '.lock'
);
// Check if destination directory exists to prevent issuing lock at all times
return Q.nfcall(fs.stat, dir)
.fail(function(err) {
var lockParams = { wait: 250, retries: 25, stale: 60000 };
return Q.nfcall(lockFile.lock, pkgLock, lockParams)
.then(function() {
// Ensure other process didn't start copying files before lock was created
return Q.nfcall(fs.stat, dir).fail(function(err) {
// If stat fails, it is expected to return ENOENT
if (err.code !== 'ENOENT') {
throw err;
}
// Create missing directory and copy files there
return Q.nfcall(mkdirp, path.dirname(dir)).then(
function() {
return Q.nfcall(
fs.rename,
canonicalDir,
dir
).fail(function(err) {
// If error is EXDEV it means that we are trying to rename
// across different drives, so we copy and remove it instead
if (err.code !== 'EXDEV') {
throw err;
}
return copy.copyDir(
canonicalDir,
dir
);
});
}
);
});
})
.finally(function() {
lockFile.unlockSync(pkgLock);
});
})
.finally(function() {
// Ensure no tmp dir is left on disk.
return Q.nfcall(rimraf, canonicalDir);
});
})
.then(function() {
var versions = that._cache.get(sourceId);
// Add it to the in memory cache
// and sort the versions afterwards
if (versions && versions.indexOf(release) === -1) {
versions.push(release);
that._sortVersions(versions);
}
// Resolve with the final location
return dir;
});
};
ResolveCache.prototype.eliminate = function(pkgMeta) {
var sourceId = md5(pkgMeta._source);
var release = this._getPkgRelease(pkgMeta);
var dir = path.join(this._dir, sourceId, release);
var that = this;
return Q.nfcall(rimraf, dir).then(function() {
var versions = that._cache.get(sourceId) || [];
mout.array.remove(versions, release);
// If this was the last package in the cache,
// delete the parent folder (source)
// For extra security, check against the file system
// if this was really the last package
if (!versions.length) {
that._cache.del(sourceId);
return that._getVersions(sourceId).spread(function(versions) {
if (!versions.length) {
// Do not keep in-memory cache if it's completely
// empty
that._cache.del(sourceId);
return Q.nfcall(rimraf, path.dirname(dir));
}
});
}
});
};
ResolveCache.prototype.clear = function() {
return Q.nfcall(rimraf, this._dir)
.then(
function() {
return Q.nfcall(fs.mkdir, this._dir);
}.bind(this)
)
.then(
function() {
this._cache.reset();
}.bind(this)
);
};
ResolveCache.prototype.reset = function() {
this._cache.reset();
return this;
};
ResolveCache.prototype.versions = function(source) {
var sourceId = md5(source);
return this._getVersions(sourceId).spread(function(versions) {
return versions.filter(function(version) {
return semver.valid(version);
});
});
};
ResolveCache.prototype.list = function() {
var promises;
var dirs = [];
var that = this;
// Get the list of directories
return (
Q.nfcall(fs.readdir, this._dir)
.then(function(sourceIds) {
promises = sourceIds.map(function(sourceId) {
return Q.nfcall(
fs.readdir,
path.join(that._dir, sourceId)
).then(
function(versions) {
versions.forEach(function(version) {
var dir = path.join(
that._dir,
sourceId,
version
);
dirs.push(dir);
});
},
function(err) {
// Ignore lurking files, e.g.: .DS_Store if the user
// has navigated throughout the cache
if (err.code === 'ENOTDIR' && err.path) {
return Q.nfcall(rimraf, err.path);
}
throw err;
}
);
});
return Q.all(promises);
})
// Read every package meta
.then(function() {
promises = dirs.map(function(dir) {
return that._readPkgMeta(dir).then(
function(pkgMeta) {
return {
canonicalDir: dir,
pkgMeta: pkgMeta
};
},
function() {
// If it fails to read, invalidate the in memory
// cache for the source and delete the entry directory
var sourceId = path.basename(path.dirname(dir));
that._cache.del(sourceId);
return Q.nfcall(rimraf, dir);
}
);
});
return Q.all(promises);
})
// Sort by name ASC & release ASC
.then(function(entries) {
// Ignore falsy entries due to errors reading
// package metas
entries = entries.filter(function(entry) {
return !!entry;
});
return entries.sort(function(entry1, entry2) {
var pkgMeta1 = entry1.pkgMeta;
var pkgMeta2 = entry2.pkgMeta;
var comp = pkgMeta1.name.localeCompare(pkgMeta2.name);
// Sort by name
if (comp) {
return comp;
}
// Sort by version
if (pkgMeta1.version && pkgMeta2.version) {
return semver.compare(
pkgMeta1.version,
pkgMeta2.version
);
}
if (pkgMeta1.version) {
return -1;
}
if (pkgMeta2.version) {
return 1;
}
// Sort by target
return pkgMeta1._target.localeCompare(pkgMeta2._target);
});
})
);
};
// ------------------------
ResolveCache.clearRuntimeCache = function() {
// Note that _cache refers to the static _cache variable
// that holds other caches per dir!
// Do not confuse it with the instance cache
// Clear cache of each directory
this._cache.forEach(function(cache) {
cache.reset();
});
// Clear root cache
this._cache.reset();
};
// ------------------------
ResolveCache.prototype._getPkgRelease = function(pkgMeta) {
var release =
pkgMeta.version ||
(pkgMeta._target === '*' ? '_wildcard' : pkgMeta._target);
// Encode some dangerous chars such as / and \
release = encodeURIComponent(release);
return release;
};
ResolveCache.prototype._readPkgMeta = function(dir) {
var filename = path.join(dir, '.bower.json');
return readJson(filename).spread(function(json) {
return json;
});
};
ResolveCache.prototype._getVersions = function(sourceId) {
var dir;
var versions = this._cache.get(sourceId);
var that = this;
if (versions) {
return Q.resolve([versions, true]);
}
dir = path.join(this._dir, sourceId);
return Q.nfcall(fs.readdir, dir).then(
function(versions) {
// Sort and cache in memory
that._sortVersions(versions);
versions = versions.map(decodeURIComponent);
that._cache.set(sourceId, versions);
return [versions, false];
},
function(err) {
// If the directory does not exists, resolve
// as an empty array
if (err.code === 'ENOENT') {
versions = [];
that._cache.set(sourceId, versions);
return [versions, false];
}
throw err;
}
);
};
ResolveCache.prototype._sortVersions = function(versions) {
// Sort DESC
versions.sort(function(version1, version2) {
var validSemver1 = semver.valid(version1);
var validSemver2 = semver.valid(version2);
// If both are semvers, compare them
if (validSemver1 && validSemver2) {
return semver.rcompare(version1, version2);
}
// If one of them are semvers, give higher priority
if (validSemver1) {
return -1;
}
if (validSemver2) {
return 1;
}
// Otherwise they are considered equal
return 0;
});
};
// ------------------------
ResolveCache._cache = new LRU({
max: 5,
maxAge: 60 * 30 * 1000 // 30 minutes
});
module.exports = ResolveCache;

279
node_modules/bower/lib/core/resolverFactory.js generated vendored Normal file
View File

@@ -0,0 +1,279 @@
var Q = require('q');
var fs = require('../util/fs');
var path = require('path');
var mout = require('mout');
var resolvers = require('./resolvers');
var createError = require('../util/createError');
var resolve = require('../util/resolve');
var pluginResolverFactory = require('./resolvers/pluginResolverFactory');
function createInstance(decEndpoint, options, registryClient) {
decEndpoint = mout.object.pick(decEndpoint, ['name', 'target', 'source']);
options.version = require('../version');
return getConstructor(decEndpoint, options, registryClient).spread(function(
ConcreteResolver,
decEndpoint
) {
return new ConcreteResolver(
decEndpoint,
options.config,
options.logger
);
});
}
function getConstructor(decEndpoint, options, registryClient) {
var source = decEndpoint.source;
var config = options.config;
// Below we try a series of async tests to guess the type of resolver to use
// If a step was unable to guess the resolver, it returns undefined
// If a step can guess the resolver, it returns with constructor of resolver
var promise = Q.resolve();
var addResolver = function(resolverFactory) {
promise = promise.then(function(result) {
if (result === undefined) {
return resolverFactory(decEndpoint, options);
} else {
return result;
}
});
};
// Plugin resolvers.
//
// It requires each resolver defined in config.resolvers and calls
// its "match" to check if given resolves supports given decEndpoint
addResolver(function() {
var selectedResolver;
var resolverNames;
if (Array.isArray(config.resolvers)) {
resolverNames = config.resolvers;
} else if (!!config.resolvers) {
resolverNames = config.resolvers.split(',');
} else {
resolverNames = [];
}
var resolverPromises = resolverNames.map(function(resolverName) {
var resolver = resolvers[resolverName];
if (resolver === undefined) {
var resolverPath = resolve(resolverName, { cwd: config.cwd });
if (resolverPath === undefined) {
throw createError(
'Bower resolver not found: ' + resolverName,
'ENORESOLVER'
);
}
resolver = pluginResolverFactory(
require(resolverPath),
options
);
}
return function() {
if (selectedResolver === undefined) {
var match = resolver.match.bind(resolver);
return Q.fcall(match, source).then(function(result) {
if (result) {
return (selectedResolver = resolver);
}
});
} else {
return selectedResolver;
}
};
});
return resolverPromises
.reduce(Q.when, new Q(undefined))
.then(function(resolver) {
if (resolver) {
return Q.fcall(
resolver.locate.bind(resolver),
decEndpoint.source
).then(function(result) {
if (result && result !== decEndpoint.source) {
decEndpoint.source = result;
decEndpoint.registry = true;
return getConstructor(
decEndpoint,
options,
registryClient
);
} else {
return [resolver, decEndpoint];
}
});
}
});
});
// Git case: git git+ssh, git+http, git+https
// .git at the end (probably ssh shorthand)
// git@ at the start
addResolver(function() {
if (
/^git(\+(ssh|https?))?:\/\//i.test(source) ||
/\.git\/?$/i.test(source) ||
/^git@/i.test(source)
) {
decEndpoint.source = source.replace(/^git\+/, '');
// If it's a GitHub repository, return the specialized resolver
if (resolvers.GitHub.getOrgRepoPair(source)) {
return [resolvers.GitHub, decEndpoint];
}
return [resolvers.GitRemote, decEndpoint];
}
});
// SVN case: svn, svn+ssh, svn+http, svn+https, svn+file
addResolver(function() {
if (/^svn(\+(ssh|https?|file))?:\/\//i.test(source)) {
return [resolvers.Svn, decEndpoint];
}
});
// URL case
addResolver(function() {
if (/^https?:\/\//i.exec(source)) {
return [resolvers.Url, decEndpoint];
}
});
// If source is ./ or ../ or an absolute path
addResolver(function() {
var absolutePath = path.resolve(config.cwd, source);
if (
/^\.\.?[\/\\]/.test(source) ||
/^~\//.test(source) ||
path.normalize(source).replace(/[\/\\]+$/, '') === absolutePath
) {
return (
Q.nfcall(fs.stat, path.join(absolutePath, '.git'))
.then(function(stats) {
decEndpoint.source = absolutePath;
if (stats.isDirectory()) {
return Q.resolve([resolvers.GitFs, decEndpoint]);
}
throw new Error('Not a Git repository');
})
// If not, check if source is a valid Subversion repository
.fail(function() {
return Q.nfcall(
fs.stat,
path.join(absolutePath, '.svn')
).then(function(stats) {
decEndpoint.source = absolutePath;
if (stats.isDirectory()) {
return Q.resolve([resolvers.Svn, decEndpoint]);
}
throw new Error('Not a Subversion repository');
});
})
// If not, check if source is a valid file/folder
.fail(function() {
return Q.nfcall(fs.stat, absolutePath).then(function() {
decEndpoint.source = absolutePath;
return Q.resolve([resolvers.Fs, decEndpoint]);
});
})
);
}
});
// Check if is a shorthand and expand it
addResolver(function() {
// Check if the shorthandResolver is falsy
if (!config.shorthandResolver) {
return;
}
// Skip ssh and/or URL with auth
if (/[:@]/.test(source)) {
return;
}
// Ensure exactly only one "/"
var parts = source.split('/');
if (parts.length === 2) {
decEndpoint.source = mout.string.interpolate(
config.shorthandResolver,
{
shorthand: source,
owner: parts[0],
package: parts[1]
}
);
return getConstructor(decEndpoint, options, registryClient);
}
});
// As last resort, we try the registry
addResolver(function() {
if (!registryClient) {
return;
}
return Q.nfcall(
registryClient.lookup.bind(registryClient),
source
).then(function(entry) {
if (!entry) {
throw createError(
'Package ' + source + ' not found',
'ENOTFOUND'
);
}
decEndpoint.registry = true;
if (!decEndpoint.name) {
decEndpoint.name = decEndpoint.source;
}
decEndpoint.source = entry.url;
return getConstructor(decEndpoint, options);
});
});
addResolver(function() {
throw createError(
'Could not find appropriate resolver for ' + source,
'ENORESOLVER'
);
});
return promise;
}
function clearRuntimeCache() {
mout.object.values(resolvers).forEach(function(ConcreteResolver) {
ConcreteResolver.clearRuntimeCache();
});
}
module.exports = createInstance;
module.exports.getConstructor = getConstructor;
module.exports.clearRuntimeCache = clearRuntimeCache;

154
node_modules/bower/lib/core/resolvers/FsResolver.js generated vendored Normal file
View File

@@ -0,0 +1,154 @@
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;

102
node_modules/bower/lib/core/resolvers/GitFsResolver.js generated vendored Normal file
View File

@@ -0,0 +1,102 @@
var util = require('util');
var Q = require('q');
var mout = require('mout');
var path = require('path');
var GitResolver = require('./GitResolver');
var copy = require('../../util/copy');
var cmd = require('../../util/cmd');
function GitFsResolver(decEndpoint, config, logger) {
GitResolver.call(this, decEndpoint, config, logger);
// Ensure absolute path
this._source = path.resolve(this._config.cwd, this._source);
}
util.inherits(GitFsResolver, GitResolver);
mout.object.mixIn(GitFsResolver, GitResolver);
// -----------------
// Override the checkout function to work with the local copy
GitFsResolver.prototype._checkout = function() {
var resolution = this._resolution;
// The checkout process could be similar to the GitRemoteResolver by prepending file:// to the source
// But from my performance measures, it's faster to copy the folder and just checkout in there
this._logger.action(
'checkout',
resolution.tag || resolution.branch || resolution.commit,
{
resolution: resolution,
to: this._tempDir
}
);
// Copy files to the temporary directory first
return (
this._copy()
.then(
cmd.bind(
cmd,
'git',
[
'checkout',
'-f',
resolution.tag || resolution.branch || resolution.commit
],
{ cwd: this._tempDir }
)
)
// Cleanup unstaged files
.then(
cmd.bind(cmd, 'git', ['clean', '-f', '-d'], {
cwd: this._tempDir
})
)
);
};
GitFsResolver.prototype._copy = function() {
return copy.copyDir(this._source, this._tempDir);
};
// -----------------
// Grab refs locally
GitFsResolver.refs = function(source) {
var value;
// TODO: Normalize source because of the various available protocols?
value = this._cache.refs.get(source);
if (value) {
return Q.resolve(value);
}
value = cmd('git', ['show-ref', '--tags', '--heads'], {
cwd: source
}).spread(
function(stdout) {
var refs;
refs = stdout
.toString()
.trim() // Trim trailing and leading spaces
.replace(/[\t ]+/g, ' ') // Standardize spaces (some git versions make tabs, other spaces)
.split(/[\r\n]+/); // Split lines into an array
// Update the refs with the actual refs
this._cache.refs.set(source, refs);
return refs;
}.bind(this)
);
// Store the promise to be reused until it resolves
// to a specific value
this._cache.refs.set(source, value);
return value;
};
module.exports = GitFsResolver;

191
node_modules/bower/lib/core/resolvers/GitHubResolver.js generated vendored Normal file
View File

@@ -0,0 +1,191 @@
var util = require('util');
var path = require('path');
var mout = require('mout');
var Q = require('q');
var GitRemoteResolver = require('./GitRemoteResolver');
var download = require('../../util/download');
var extract = require('../../util/extract');
var createError = require('../../util/createError');
function GitHubResolver(decEndpoint, config, logger) {
var pair;
GitRemoteResolver.call(this, decEndpoint, config, logger);
// Grab the org/repo
// /xxxxx/yyyyy.git or :xxxxx/yyyyy.git (.git is optional)
pair = GitHubResolver.getOrgRepoPair(this._source);
if (!pair) {
throw createError('Invalid GitHub URL', 'EINVEND', {
details: this._source + ' does not seem to be a valid GitHub URL'
});
}
this._org = pair.org;
this._repo = pair.repo;
// Ensure trailing for all protocols
if (!mout.string.endsWith(this._source, '.git')) {
this._source += '.git';
}
// Use https:// rather than git:// if on a proxy
if (this._config.proxy || this._config.httpsProxy) {
this._source = this._source.replace('git://', 'https://');
}
// Enable shallow clones for GitHub repos
this._shallowClone = function() {
return Q.resolve(true);
};
}
util.inherits(GitHubResolver, GitRemoteResolver);
mout.object.mixIn(GitHubResolver, GitRemoteResolver);
// -----------------
GitHubResolver.prototype._checkout = function() {
var msg;
var name =
this._resolution.tag ||
this._resolution.branch ||
this._resolution.commit;
var tarballUrl =
'https://github.com/' +
this._org +
'/' +
this._repo +
'/archive/' +
name +
'.tar.gz';
var file = path.join(this._tempDir, 'archive.tar.gz');
var reqHeaders = {};
var that = this;
if (this._config.userAgent) {
reqHeaders['User-Agent'] = this._config.userAgent;
}
this._logger.action('download', tarballUrl, {
url: that._source,
to: file
});
// Download tarball
return download(tarballUrl, file, {
ca: this._config.ca.default,
strictSSL: this._config.strictSsl,
timeout: this._config.timeout,
headers: reqHeaders
})
.progress(function(state) {
// Retry?
if (state.retry) {
msg =
'Download of ' +
tarballUrl +
' failed with ' +
state.error.code +
', ';
msg += 'retrying in ' + (state.delay / 1000).toFixed(1) + 's';
that._logger.debug('error', state.error.message, {
error: state.error
});
return that._logger.warn('retry', msg);
}
// Progress
msg =
'received ' + (state.received / 1024 / 1024).toFixed(1) + 'MB';
if (state.total) {
msg +=
' of ' +
(state.total / 1024 / 1024).toFixed(1) +
'MB downloaded, ';
msg += state.percent + '%';
}
that._logger.info('progress', msg);
})
.then(
function() {
// Extract archive
that._logger.action('extract', path.basename(file), {
archive: file,
to: that._tempDir
});
return (
extract(file, that._tempDir)
// Fallback to standard git clone if extraction failed
.fail(function(err) {
msg =
'Decompression of ' +
path.basename(file) +
' failed' +
(err.code ? ' with ' + err.code : '') +
', ';
msg += 'trying with git..';
that._logger.debug('error', err.message, {
error: err
});
that._logger.warn('retry', msg);
return that
._cleanTempDir()
.then(
GitRemoteResolver.prototype._checkout.bind(
that
)
);
})
);
// Fallback to standard git clone if download failed
},
function(err) {
msg =
'Download of ' +
tarballUrl +
' failed' +
(err.code ? ' with ' + err.code : '') +
', ';
msg += 'trying with git..';
that._logger.debug('error', err.message, { error: err });
that._logger.warn('retry', msg);
return that
._cleanTempDir()
.then(GitRemoteResolver.prototype._checkout.bind(that));
}
);
};
GitHubResolver.prototype._savePkgMeta = function(meta) {
// Set homepage if not defined
if (!meta.homepage) {
meta.homepage = 'https://github.com/' + this._org + '/' + this._repo;
}
return GitRemoteResolver.prototype._savePkgMeta.call(this, meta);
};
// ----------------
GitHubResolver.getOrgRepoPair = function(url) {
var match;
match = url.match(
/(?:@|:\/\/)github.com[:\/]([^\/\s]+?)\/([^\/\s]+?)(?:\.git)?\/?$/i
);
if (!match) {
return null;
}
return {
org: match[1],
repo: match[2]
};
};
module.exports = GitHubResolver;

View File

@@ -0,0 +1,330 @@
var util = require('util');
var url = require('url');
var Q = require('q');
var mout = require('mout');
var LRU = require('lru-cache');
var GitResolver = require('./GitResolver');
var cmd = require('../../util/cmd');
function GitRemoteResolver(decEndpoint, config, logger) {
GitResolver.call(this, decEndpoint, config, logger);
if (!mout.string.startsWith(this._source, 'file://')) {
// Trim trailing slashes
this._source = this._source.replace(/\/+$/, '');
}
// If the name was guessed, remove the trailing .git
if (this._guessedName && mout.string.endsWith(this._name, '.git')) {
this._name = this._name.slice(0, -4);
}
// Get the remote of this source
if (!/:\/\//.test(this._source)) {
this._remote = url.parse('ssh://' + this._source);
} else {
this._remote = url.parse(this._source);
}
this._host = this._remote.host;
// Verify whether the server supports shallow cloning
this._shallowClone = this._supportsShallowCloning;
}
util.inherits(GitRemoteResolver, GitResolver);
mout.object.mixIn(GitRemoteResolver, GitResolver);
// -----------------
GitRemoteResolver.prototype._checkout = function() {
var promise;
var timer;
var reporter;
var that = this;
var resolution = this._resolution;
this._logger.action(
'checkout',
resolution.tag || resolution.branch || resolution.commit,
{
resolution: resolution,
to: this._tempDir
}
);
// If resolution is a commit, we need to clone the entire repo and check it out
// Because a commit is not a named ref, there's no better solution
if (resolution.type === 'commit') {
promise = this._slowClone(resolution);
// Otherwise we are checking out a named ref so we can optimize it
} else {
promise = this._fastClone(resolution);
}
// Throttle the progress reporter to 1 time each sec
reporter = mout.fn.throttle(function(data) {
var lines;
lines = data.split(/[\r\n]+/);
lines.forEach(function(line) {
if (/\d{1,3}\%/.test(line)) {
// TODO: There are some strange chars that appear once in a while (\u001b[K)
// Trim also those?
that._logger.info('progress', line.trim());
}
});
}, 1000);
// Start reporting progress after a few seconds
timer = setTimeout(function() {
promise.progress(reporter);
}, 8000);
return (
promise
// Add additional proxy information to the error if necessary
.fail(function(err) {
that._suggestProxyWorkaround(err);
throw err;
})
// Clear timer at the end
.fin(function() {
clearTimeout(timer);
reporter.cancel();
})
);
};
GitRemoteResolver.prototype._findResolution = function(target) {
var that = this;
// Override this function to include a meaningful message related to proxies
// if necessary
return GitResolver.prototype._findResolution
.call(this, target)
.fail(function(err) {
that._suggestProxyWorkaround(err);
throw err;
});
};
// ------------------------------
GitRemoteResolver.prototype._slowClone = function(resolution) {
return cmd('git', [
'clone',
this._source,
this._tempDir,
'--progress'
]).then(
cmd.bind(cmd, 'git', ['checkout', resolution.commit], {
cwd: this._tempDir
})
);
};
GitRemoteResolver.prototype._fastClone = function(resolution) {
var branch,
args,
that = this;
branch = resolution.tag || resolution.branch;
args = ['clone', this._source, '-b', branch, '--progress', '.'];
return this._shallowClone().then(function(shallowCloningSupported) {
// If the host does not support shallow clones, we don't use --depth=1
if (
shallowCloningSupported &&
!GitRemoteResolver._noShallow.get(that._host)
) {
args.push('--depth', 1);
}
return cmd('git', args, { cwd: that._tempDir }).spread(
function(stdout, stderr) {
// Only after 1.7.10 --branch accepts tags
// Detect those cases and inform the user to update git otherwise it's
// a lot slower than newer versions
if (!/branch .+? not found/i.test(stderr)) {
return;
}
that._logger.warn(
'old-git',
'It seems you are using an old version of git, it will be slower and propitious to errors!'
);
return cmd('git', ['checkout', resolution.commit], {
cwd: that._tempDir
});
},
function(err) {
// Some git servers do not support shallow clones
// When that happens, we mark this host and try again
if (
!GitRemoteResolver._noShallow.has(that._source) &&
err.details &&
/(rpc failed|shallow|--depth)/i.test(err.details)
) {
GitRemoteResolver._noShallow.set(that._host, true);
return that._fastClone(resolution);
}
throw err;
}
);
});
};
GitRemoteResolver.prototype._suggestProxyWorkaround = function(err) {
if (
(this._config.proxy || this._config.httpsProxy) &&
mout.string.startsWith(this._source, 'git://') &&
err.code === 'ECMDERR' &&
err.details
) {
err.details = err.details.trim();
err.details +=
'\n\nWhen under a proxy, you must configure git to use https:// instead of git://.';
err.details +=
'\nYou can configure it for every endpoint or for this specific host as follows:';
err.details += '\ngit config --global url."https://".insteadOf git://';
err.details +=
'\ngit config --global url."https://' +
this._host +
'".insteadOf git://' +
this._host;
err.details +=
'Ignore this suggestion if you already have this configured.';
}
};
// Verifies whether the server supports shallow cloning.
// This is done according to the rules found in the following links:
// * https://github.com/dimitri/el-get/pull/1921/files
// * http://stackoverflow.com/questions/9270488/is-it-possible-to-detect-whether-a-http-git-remote-is-smart-or-dumb
//
// Summary of the rules:
// * Protocols like ssh or git always support shallow cloning
// * HTTP-based protocols can be verified by sending a HEAD or GET request to the URI (appended to the URL of the Git repo):
// /info/refs?service=git-upload-pack
// * If the server responds with a 'Content-Type' header of 'application/x-git-upload-pack-advertisement',
// the server supports shallow cloning ("smart server")
// * If the server responds with a different content type, the server does not support shallow cloning ("dumb server")
// * Instead of doing the HEAD or GET request using an HTTP client, we're letting Git and Curl do the heavy lifting.
// Calling Git with the GIT_CURL_VERBOSE=2 env variable will provide the Git and Curl output, which includes
// the content type. This has the advantage that Git will take care of using stored credentials and any additional
// negotiation that needs to take place.
//
// The above should cover most cases, including BitBucket.
GitRemoteResolver.prototype._supportsShallowCloning = function() {
var value = true;
// Verify that the remote could be parsed and that a protocol is set
// This case is unlikely, but let's still cover it.
if (this._remote == null || this._remote.protocol == null) {
return Q.resolve(false);
}
if (
!this._host ||
!this._config.shallowCloneHosts ||
this._config.shallowCloneHosts.indexOf(this._host) === -1
) {
return Q.resolve(false);
}
// Check for protocol - the remote check for hosts supporting shallow cloning is only required for
// HTTP or HTTPS, not for Git or SSH.
// Also check for hosts that have been checked in a previous request and have been found to support
// shallow cloning.
if (
mout.string.startsWith(this._remote.protocol, 'http') &&
!GitRemoteResolver._canShallow.get(this._host)
) {
// Provide GIT_CURL_VERBOSE=2 environment variable to capture curl output.
// Calling ls-remote includes a call to the git-upload-pack service, which returns the content type in the response.
var processEnv = mout.object.merge(process.env, {
GIT_CURL_VERBOSE: '2'
});
value = cmd('git', ['ls-remote', '--heads', this._source], {
env: processEnv
}).spread(
function(stdout, stderr) {
// Check stderr for content-type, ignore stdout
var isSmartServer;
// If the content type is 'x-git', then the server supports shallow cloning
isSmartServer = mout.string.contains(
stderr,
'Content-Type: application/x-git-upload-pack-advertisement'
);
this._logger.debug(
'detect-smart-git',
'Smart Git host detected: ' + isSmartServer
);
if (isSmartServer) {
// Cache this host
GitRemoteResolver._canShallow.set(this._host, true);
}
return isSmartServer;
}.bind(this)
);
} else {
// One of the following cases:
// * A non-HTTP/HTTPS protocol
// * A host that has been checked before and that supports shallow cloning
return Q.resolve(true);
}
return value;
};
// ------------------------------
// Grab refs remotely
GitRemoteResolver.refs = function(source) {
var value;
// TODO: Normalize source because of the various available protocols?
value = this._cache.refs.get(source);
if (value) {
return Q.resolve(value);
}
// Store the promise in the refs object
value = cmd('git', ['ls-remote', '--tags', '--heads', source]).spread(
function(stdout) {
var refs;
refs = stdout
.toString()
.trim() // Trim trailing and leading spaces
.replace(/[\t ]+/g, ' ') // Standardize spaces (some git versions make tabs, other spaces)
.split(/[\r\n]+/); // Split lines into an array
// Update the refs with the actual refs
this._cache.refs.set(source, refs);
return refs;
}.bind(this)
);
// Store the promise to be reused until it resolves
// to a specific value
this._cache.refs.set(source, value);
return value;
};
// Store hosts that do not support shallow clones here
GitRemoteResolver._noShallow = new LRU({ max: 50, maxAge: 5 * 60 * 1000 });
// Store hosts that support shallow clones here
GitRemoteResolver._canShallow = new LRU({ max: 50, maxAge: 5 * 60 * 1000 });
module.exports = GitRemoteResolver;

434
node_modules/bower/lib/core/resolvers/GitResolver.js generated vendored Normal file
View File

@@ -0,0 +1,434 @@
var util = require('util');
var path = require('path');
var Q = require('q');
var rimraf = require('../../util/rimraf');
var mkdirp = require('mkdirp');
var which = require('which');
var LRU = require('lru-cache');
var mout = require('mout');
var Resolver = require('./Resolver');
var semver = require('../../util/semver');
var createError = require('../../util/createError');
var hasGit;
// Check if git is installed
try {
which.sync('git');
hasGit = true;
} catch (ex) {
hasGit = false;
}
function GitResolver(decEndpoint, config, logger) {
// Set template dir to the empty directory so that user templates are not run
// This environment variable is not multiple config aware but it's not documented
// anyway
mkdirp.sync(config.storage.empty);
process.env.GIT_TEMPLATE_DIR = config.storage.empty;
if (!config.strictSsl) {
process.env.GIT_SSL_NO_VERIFY = 'true';
}
if (!config.interactive) {
process.env.GIT_TERMINAL_PROMPT = '0';
if (!process.env.SSH_ASKPASS) {
process.env.SSH_ASKPASS = 'echo';
}
}
Resolver.call(this, decEndpoint, config, logger);
if (!hasGit) {
throw createError('git is not installed or not in the PATH', 'ENOGIT');
}
}
util.inherits(GitResolver, Resolver);
mout.object.mixIn(GitResolver, Resolver);
// -----------------
GitResolver.prototype._hasNew = function(pkgMeta) {
var oldResolution = pkgMeta._resolution || {};
return this._findResolution().then(function(resolution) {
// Check if resolution types are different
if (oldResolution.type !== resolution.type) {
return true;
}
// If resolved to a version, there is new content if the tags are not equal
if (
resolution.type === 'version' &&
semver.neq(resolution.tag, oldResolution.tag)
) {
return true;
}
// As last check, we compare both commit hashes
return resolution.commit !== oldResolution.commit;
});
};
GitResolver.prototype._resolve = function() {
var that = this;
return this._findResolution().then(function() {
return (
that
._checkout()
// Always run cleanup after checkout to ensure that .git is removed!
// If it's not removed, problems might arise when the "tmp" module attempts
// to delete the temporary folder
.fin(function() {
return that._cleanup();
})
);
});
};
// -----------------
// Abstract functions that should be implemented by concrete git resolvers
GitResolver.prototype._checkout = function() {
throw new Error('_checkout not implemented');
};
GitResolver.refs = function(source) {
throw new Error('refs not implemented');
};
// -----------------
GitResolver.prototype._findResolution = function(target) {
var err;
var self = this.constructor;
var that = this;
target = target || this._target || '*';
// 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)) {
this._resolution = { type: 'commit', commit: target };
return Q.resolve(this._resolution);
}
// Target is a range/version
if (semver.validRange(target)) {
return self.versions(this._source, true).then(function(versions) {
var versionsArr, version, index;
// If there are no tags and target is *,
// fallback to the latest commit on master
if (!versions.length && target === '*') {
return that._findResolution('master');
}
versionsArr = versions.map(function(obj) {
return obj.version;
});
// Find a satisfying version, enabling strict match so that pre-releases
// have lower priority over normal ones when target is *
index = semver.maxSatisfyingIndex(versionsArr, target, true);
if (index !== -1) {
version = versions[index];
return (that._resolution = {
type: 'version',
tag: version.tag,
commit: version.commit
});
}
// Check if there's an exact branch/tag with this name as last resort
return Q.all([
self.branches(that._source),
self.tags(that._source)
]).spread(function(branches, tags) {
// Use hasOwn because a branch/tag could have a name like "hasOwnProperty"
if (mout.object.hasOwn(tags, target)) {
return (that._resolution = {
type: 'tag',
tag: target,
commit: tags[target]
});
}
if (mout.object.hasOwn(branches, target)) {
return (that._resolution = {
type: 'branch',
branch: target,
commit: branches[target]
});
}
throw createError(
'No tag found that was able to satisfy ' + target,
'ENORESTARGET',
{
details: !versions.length
? 'No versions found in ' + that._source
: 'Available versions in ' +
that._source +
': ' +
versions
.map(function(version) {
return version.version;
})
.join(', ')
}
);
});
});
}
// Otherwise, target is either a tag or a branch
return Q.all([self.branches(that._source), self.tags(that._source)]).spread(
function(branches, tags) {
// Use hasOwn because a branch/tag could have a name like "hasOwnProperty"
if (mout.object.hasOwn(tags, target)) {
return (that._resolution = {
type: 'tag',
tag: target,
commit: tags[target]
});
}
if (mout.object.hasOwn(branches, target)) {
return (that._resolution = {
type: 'branch',
branch: target,
commit: branches[target]
});
}
if (/^[a-f0-9]{4,40}$/.test(target)) {
if (target.length < 12) {
that._logger.warn(
'short-sha',
'Consider using longer commit SHA to avoid conflicts'
);
}
that._resolution = { type: 'commit', commit: target };
return that._resolution;
}
branches = Object.keys(branches);
tags = Object.keys(tags);
err = createError(
'Tag/branch ' + target + ' does not exist',
'ENORESTARGET'
);
err.details = !tags.length
? 'No tags found in ' + that._source
: 'Available tags: ' + tags.join(', ');
err.details += '\n';
err.details += !branches.length
? 'No branches found in ' + that._source
: 'Available branches: ' + branches.join(', ');
throw err;
}
);
};
GitResolver.prototype._cleanup = function() {
var gitFolder = path.join(this._tempDir, '.git');
return Q.nfcall(rimraf, gitFolder);
};
GitResolver.prototype._savePkgMeta = function(meta) {
var version;
if (this._resolution.type === 'version') {
version = semver.clean(this._resolution.tag);
// Warn if the package meta version is different than the resolved one
if (
typeof meta.version === 'string' &&
semver.valid(meta.version) &&
semver.neq(meta.version, version)
) {
this._logger.warn(
'mismatch',
'Version declared in the json (' +
meta.version +
') is different than the resolved one (' +
version +
')',
{
resolution: this._resolution,
pkgMeta: meta
}
);
}
// Ensure package meta version is the same as the resolution
meta.version = version;
} else {
// If resolved to a target that is not a version,
// remove the version from the meta
delete meta.version;
}
// Save version/tag/commit in the release
// Note that we can't store branches because _release is supposed to be
// an unique id of this ref.
meta._release =
version ||
this._resolution.tag ||
this._resolution.commit.substr(0, 10);
// Save resolution to be used in hasNew later
meta._resolution = this._resolution;
return Resolver.prototype._savePkgMeta.call(this, meta);
};
// ------------------------------
GitResolver.versions = function(source, extra) {
var value = this._cache.versions.get(source);
if (value) {
return Q.resolve(value).then(
function() {
var versions = this._cache.versions.get(source);
// If no extra information was requested,
// resolve simply with the versions
if (!extra) {
versions = versions.map(function(version) {
return version.version;
});
}
return versions;
}.bind(this)
);
}
value = this.tags(source).then(
function(tags) {
var tag;
var version;
var versions = [];
// For each tag
for (tag in tags) {
version = semver.clean(tag);
if (version) {
versions.push({
version: version,
tag: tag,
commit: tags[tag]
});
}
}
// Sort them by DESC order
versions.sort(function(a, b) {
return semver.rcompare(a.version, b.version);
});
this._cache.versions.set(source, versions);
// Call the function again to keep it DRY
return this.versions(source, extra);
}.bind(this)
);
// Store the promise to be reused until it resolves
// to a specific value
this._cache.versions.set(source, value);
return value;
};
GitResolver.tags = function(source) {
var value = this._cache.tags.get(source);
if (value) {
return Q.resolve(value);
}
value = this.refs(source).then(
function(refs) {
var tags = {};
// For each line in the refs, match only the tags
refs.forEach(function(line) {
var match = line.match(/^([a-f0-9]{40})\s+refs\/tags\/(\S+)/);
if (match && !mout.string.endsWith(match[2], '^{}')) {
tags[match[2]] = match[1];
}
});
this._cache.tags.set(source, tags);
return tags;
}.bind(this)
);
// Store the promise to be reused until it resolves
// to a specific value
this._cache.tags.set(source, value);
return value;
};
GitResolver.branches = function(source) {
var value = this._cache.branches.get(source);
if (value) {
return Q.resolve(value);
}
value = this.refs(source).then(
function(refs) {
var branches = {};
// For each line in the refs, extract only the heads
// Organize them in an object where keys are branches and values
// the commit hashes
refs.forEach(function(line) {
var match = line.match(/^([a-f0-9]{40})\s+refs\/heads\/(\S+)/);
if (match) {
branches[match[2]] = match[1];
}
});
this._cache.branches.set(source, branches);
return branches;
}.bind(this)
);
// Store the promise to be reused until it resolves
// to a specific value
this._cache.branches.set(source, value);
return value;
};
GitResolver.clearRuntimeCache = function() {
// Reset cache for branches, tags, etc
mout.object.forOwn(GitResolver._cache, function(lru) {
lru.reset();
});
};
GitResolver._cache = {
branches: new LRU({ max: 50, maxAge: 5 * 60 * 1000 }),
tags: new LRU({ max: 50, maxAge: 5 * 60 * 1000 }),
versions: new LRU({ max: 50, maxAge: 5 * 60 * 1000 }),
refs: new LRU({ max: 50, maxAge: 5 * 60 * 1000 })
};
module.exports = GitResolver;

252
node_modules/bower/lib/core/resolvers/Resolver.js generated vendored Normal file
View File

@@ -0,0 +1,252 @@
var fs = require('../../util/fs');
var path = require('path');
var Q = require('q');
var tmp = require('tmp');
var mkdirp = require('mkdirp');
var rimraf = require('../../util/rimraf');
var readJson = require('../../util/readJson');
var createError = require('../../util/createError');
var removeIgnores = require('../../util/removeIgnores');
var md5 = require('md5-hex');
tmp.setGracefulCleanup();
function Resolver(decEndpoint, config, logger) {
this._source = decEndpoint.source;
this._target = decEndpoint.target || '*';
this._name = decEndpoint.name || path.basename(this._source);
this._config = config;
this._logger = logger;
this._guessedName = !decEndpoint.name;
}
// -----------------
Resolver.prototype.getSource = function() {
return this._source;
};
Resolver.prototype.getName = function() {
return this._name;
};
Resolver.prototype.getTarget = function() {
return this._target;
};
Resolver.prototype.getTempDir = function() {
return this._tempDir;
};
Resolver.prototype.getPkgMeta = function() {
return this._pkgMeta;
};
Resolver.prototype.hasNew = function(pkgMeta) {
var promise;
var that = this;
// If already working, error out
if (this._working) {
return Q.reject(createError('Already working', 'EWORKING'));
}
this._working = true;
// Avoid reading the package meta if already given
promise = this._hasNew(pkgMeta);
return promise.fin(function() {
that._working = false;
});
};
Resolver.prototype.resolve = function() {
var that = this;
// If already working, error out
if (this._working) {
return Q.reject(createError('Already working', 'EWORKING'));
}
this._working = true;
// Create temporary dir
return (
this._createTempDir()
// Resolve self
.then(this._resolve.bind(this))
// Read json, generating the package meta
.then(this._readJson.bind(this, null))
// Apply and save package meta
.then(function(meta) {
return that
._applyPkgMeta(meta)
.then(that._savePkgMeta.bind(that, meta));
})
.then(
function() {
// Resolve with the folder
return that._tempDir;
},
function(err) {
// If something went wrong, unset the temporary dir
that._tempDir = null;
throw err;
}
)
.fin(function() {
that._working = false;
})
);
};
Resolver.prototype.isCacheable = function() {
// Bypass cache for local dependencies
if (
this._source &&
/^(?:file:[\/\\]{2}|[A-Z]:)?\.?\.?[\/\\]/.test(this._source)
) {
return false;
}
// We don't want to cache moving targets like branches
if (
this._pkgMeta &&
this._pkgMeta._resolution &&
this._pkgMeta._resolution.type === 'branch'
) {
return false;
}
return true;
};
// -----------------
// Abstract functions that must be implemented by concrete resolvers
Resolver.prototype._resolve = function() {
throw new Error('_resolve not implemented');
};
// Abstract functions that can be re-implemented by concrete resolvers
// as necessary
Resolver.prototype._hasNew = function(pkgMeta) {
return Q.resolve(true);
};
Resolver.isTargetable = function() {
return true;
};
Resolver.versions = function(source) {
return Q.resolve([]);
};
Resolver.clearRuntimeCache = function() {};
// -----------------
Resolver.prototype._createTempDir = function() {
return Q.nfcall(mkdirp, this._config.tmp)
.then(
function() {
return Q.nfcall(tmp.dir, {
template: path.join(
this._config.tmp,
md5(this._name) + '-' + process.pid + '-XXXXXX'
),
mode: 0777 & ~process.umask(),
unsafeCleanup: true
});
}.bind(this)
)
.then(
function(dir) {
// nfcall may return multiple callback arguments as an array
return (this._tempDir = Array.isArray(dir) ? dir[0] : dir);
}.bind(this)
);
};
Resolver.prototype._cleanTempDir = function() {
var tempDir = this._tempDir;
if (!tempDir) {
return Q.resolve();
}
// Delete and create folder
return Q.nfcall(rimraf, tempDir)
.then(function() {
return Q.nfcall(mkdirp, tempDir, 0777 & ~process.umask());
})
.then(function() {
return tempDir;
});
};
Resolver.prototype._readJson = function(dir) {
var that = this;
dir = dir || this._tempDir;
return readJson(dir, {
assume: { name: this._name },
logger: that._logger
}).spread(function(json, deprecated) {
if (deprecated) {
that._logger.warn(
'deprecated',
'Package ' +
that._name +
' is using the deprecated ' +
deprecated
);
}
return json;
});
};
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 (meta.name !== this._name && this._guessedName) {
this._name = meta.name;
}
// Handle ignore property, deleting all files from the temporary directory
// If no ignores were specified, simply resolve
if (!meta.ignore || !meta.ignore.length) {
return Q.resolve(meta);
}
// Otherwise remove them from the temp dir
return removeIgnores(this._tempDir, meta).then(function() {
return meta;
});
};
Resolver.prototype._savePkgMeta = function(meta) {
var that = this;
var contents;
// Store original source & target
meta._source = this._source;
meta._target = this._target;
// Stringify contents
contents = JSON.stringify(meta, null, 2);
return Q.nfcall(
fs.writeFile,
path.join(this._tempDir, '.bower.json'),
contents
).then(function() {
return (that._pkgMeta = meta);
});
};
module.exports = Resolver;

491
node_modules/bower/lib/core/resolvers/SvnResolver.js generated vendored Normal file
View File

@@ -0,0 +1,491 @@
var util = require('util');
var Q = require('q');
var which = require('which');
var LRU = require('lru-cache');
var mout = require('mout');
var Resolver = require('./Resolver');
var semver = require('../../util/semver');
var createError = require('../../util/createError');
var cmd = require('../../util/cmd');
var hasSvn;
// Check if svn is installed
try {
which.sync('svn');
hasSvn = true;
} catch (ex) {
hasSvn = false;
}
function SvnResolver(decEndpoint, config, logger) {
Resolver.call(this, decEndpoint, config, logger);
if (!hasSvn) {
throw createError('svn is not installed or not in the PATH', 'ENOSVN');
}
}
util.inherits(SvnResolver, Resolver);
mout.object.mixIn(SvnResolver, Resolver);
// -----------------
SvnResolver.getSource = function(source) {
var uri = this._source || source;
return uri
.replace(/^svn\+(https?|file):\/\//i, '$1://') // Change svn+http or svn+https or svn+file to http(s), file respectively
.replace('svn://', 'http://') // Change svn to http
.replace(/\/+$/, ''); // Remove trailing slashes
};
SvnResolver.prototype._hasNew = function(pkgMeta) {
var oldResolution = pkgMeta._resolution || {};
return this._findResolution().then(function(resolution) {
// Check if resolution types are different
if (oldResolution.type !== resolution.type) {
return true;
}
// If resolved to a version, there is new content if the tags are not equal
if (
resolution.type === 'version' &&
semver.neq(resolution.tag, oldResolution.tag)
) {
return true;
}
// As last check, we compare both commit hashes
return resolution.commit !== oldResolution.commit;
});
};
SvnResolver.prototype._resolve = function() {
var that = this;
return this._findResolution().then(function() {
return that._export();
});
};
// -----------------
SvnResolver.prototype._export = function() {
var promise;
var timer;
var reporter;
var that = this;
var resolution = this._resolution;
this.source = SvnResolver.getSource(this._source);
this._logger.action(
'export',
resolution.tag || resolution.branch || resolution.commit,
{
resolution: resolution,
to: this._tempDir
}
);
if (resolution.type === 'commit') {
promise = cmd('svn', [
'export',
'--force',
'--non-interactive',
this._source + '/trunk',
'-r' + resolution.commit,
this._tempDir
]);
} else if (resolution.type === 'branch' && resolution.branch === 'trunk') {
promise = cmd('svn', [
'export',
'--force',
'--non-interactive',
this._source + '/trunk',
this._tempDir
]);
} else if (resolution.type === 'branch') {
promise = cmd('svn', [
'export',
'--force',
'--non-interactive',
this._source + '/branches/' + resolution.branch,
this._tempDir
]);
} else {
promise = cmd('svn', [
'export',
'--force',
'--non-interactive',
this._source + '/tags/' + resolution.tag,
this._tempDir
]);
}
// Throttle the progress reporter to 1 time each sec
reporter = mout.fn.throttle(function(data) {
var lines;
lines = data.split(/[\r\n]+/);
lines.forEach(function(line) {
if (/\d{1,3}\%/.test(line)) {
// TODO: There are some strange chars that appear once in a while (\u001b[K)
// Trim also those?
that._logger.info('progress', line.trim());
}
});
}, 1000);
// Start reporting progress after a few seconds
timer = setTimeout(function() {
promise.progress(reporter);
}, 8000);
return (
promise
// Add additional proxy information to the error if necessary
.fail(function(err) {
throw err;
})
// Clear timer at the end
.fin(function() {
clearTimeout(timer);
reporter.cancel();
})
);
};
// -----------------
SvnResolver.prototype._findResolution = function(target) {
var err;
var self = this.constructor;
var that = this;
target = target || this._target || '*';
this._source = SvnResolver.getSource(this._source);
// Target is a revision, so it's a stale target (not a moving target)
// There's nothing to do in this case
if (/^r\d+/.test(target)) {
target = target.split('r');
this._resolution = { type: 'commit', commit: target[1] };
return Q.resolve(this._resolution);
}
// Target is a range/version
if (semver.validRange(target)) {
return self.versions(this._source, true).then(function(versions) {
var versionsArr, version, index;
versionsArr = versions.map(function(obj) {
return obj.version;
});
// If there are no tags and target is *,
// fallback to the latest commit on trunk
if (!versions.length && target === '*') {
return that._findResolution('trunk');
}
versionsArr = versions.map(function(obj) {
return obj.version;
});
// Find a satisfying version, enabling strict match so that pre-releases
// have lower priority over normal ones when target is *
index = semver.maxSatisfyingIndex(versionsArr, target, true);
if (index !== -1) {
version = versions[index];
return (that._resolution = {
type: 'version',
tag: version.tag,
commit: version.commit
});
}
// Check if there's an exact branch/tag with this name as last resort
return Q.all([
self.branches(that._source),
self.tags(that._source)
]).spread(function(branches, tags) {
// Use hasOwn because a branch/tag could have a name like "hasOwnProperty"
if (mout.object.hasOwn(tags, target)) {
return (that._resolution = {
type: 'tag',
tag: target,
commit: tags[target]
});
}
if (mout.object.hasOwn(branches, target)) {
return (that._resolution = {
type: 'branch',
branch: target,
commit: branches[target]
});
}
throw createError(
'No tag found that was able to satisfy ' + target,
'ENORESTARGET',
{
details: !versions.length
? 'No versions found in ' + that._source
: 'Available versions in ' +
that._source +
': ' +
versions
.map(function(version) {
return version.version;
})
.join(', ')
}
);
});
});
}
// Otherwise, target is either a tag or a branch
return Q.all([self.branches(that._source), self.tags(that._source)]).spread(
function(branches, tags) {
// Use hasOwn because a branch/tag could have a name like "hasOwnProperty"
if (mout.object.hasOwn(tags, target)) {
return (that._resolution = {
type: 'tag',
tag: target,
commit: tags[target]
});
}
if (mout.object.hasOwn(branches, target)) {
return (that._resolution = {
type: 'branch',
branch: target,
commit: branches[target]
});
}
branches = Object.keys(branches);
tags = Object.keys(tags);
err = createError(
'target ' + target + ' does not exist',
'ENORESTARGET'
);
err.details = !tags.length
? 'No tags found in ' + that._source
: 'Available tags: ' + tags.join(', ');
err.details += '\n';
err.details += !branches.length
? 'No branches found in ' + that._source
: 'Available branches: ' + branches.join(', ');
throw err;
}
);
};
SvnResolver.prototype._savePkgMeta = function(meta) {
var version;
if (this._resolution.type === 'version') {
version = semver.clean(this._resolution.tag);
// Warn if the package meta version is different than the resolved one
if (
typeof meta.version === 'string' &&
semver.neq(meta.version, version)
) {
this._logger.warn(
'mismatch',
'Version declared in the json (' +
meta.version +
') is different than the resolved one (' +
version +
')',
{
resolution: this._resolution,
pkgMeta: meta
}
);
}
// Ensure package meta version is the same as the resolution
meta.version = version;
} else {
// If resolved to a target that is not a version,
// remove the version from the meta
delete meta.version;
}
// Save version/tag/commit in the release
// Note that we can't store branches because _release is supposed to be
// an unique id of this ref.
meta._release = version || this._resolution.tag || this._resolution.commit;
// Save resolution to be used in hasNew later
meta._resolution = this._resolution;
return Resolver.prototype._savePkgMeta.call(this, meta);
};
// ------------------------------
SvnResolver.versions = function(source, extra) {
source = SvnResolver.getSource(source);
var value = this._cache.versions.get(source);
if (value) {
return Q.resolve(value).then(
function() {
var versions = this._cache.versions.get(source);
// If no extra information was requested,
// resolve simply with the versions
if (!extra) {
versions = versions.map(function(version) {
return version.version;
});
}
return versions;
}.bind(this)
);
}
value = this.tags(source).then(
function(tags) {
var tag;
var version;
var versions = [];
// For each tag
for (tag in tags) {
version = semver.clean(tag);
if (version) {
versions.push({
version: version,
tag: tag,
commit: tags[tag]
});
}
}
// Sort them by DESC order
versions.sort(function(a, b) {
return semver.rcompare(a.version, b.version);
});
this._cache.versions.set(source, versions);
// Call the function again to keep it DRY
return this.versions(source, extra);
}.bind(this)
);
// Store the promise to be reused until it resolves
// to a specific value
this._cache.versions.set(source, value);
return value;
};
SvnResolver.tags = function(source) {
source = SvnResolver.getSource(source);
var value = this._cache.tags.get(source);
if (value) {
return Q.resolve(value);
}
value = cmd('svn', [
'list',
source + '/tags',
'--verbose',
'--non-interactive'
]).spread(
function(stout) {
var tags = SvnResolver.parseSubversionListOutput(stout.toString());
this._cache.tags.set(source, tags);
return tags;
}.bind(this)
);
// Store the promise to be reused until it resolves
// to a specific value
this._cache.tags.set(source, value);
return value;
};
SvnResolver.branches = function(source) {
source = SvnResolver.getSource(source);
var value = this._cache.branches.get(source);
if (value) {
return Q.resolve(value);
}
value = cmd('svn', [
'list',
source + '/branches',
'--verbose',
'--non-interactive'
]).spread(
function(stout) {
var branches = SvnResolver.parseSubversionListOutput(
stout.toString()
);
// trunk is a branch!
branches.trunk = '*';
this._cache.branches.set(source, branches);
return branches;
}.bind(this)
);
// Store the promise to be reused until it resolves
// to a specific value
this._cache.branches.set(source, value);
return value;
};
SvnResolver.parseSubversionListOutput = function(stout) {
var entries = {};
var lines = stout.trim().split(/[\r\n]+/);
// For each line in the refs, match only the branches
lines.forEach(function(line) {
var match = line.match(/\s+([0-9]+)\s.+\s([\w.$-]+)\//i);
if (match && match[2] !== '.') {
entries[match[2]] = match[1];
}
});
return entries;
};
SvnResolver.clearRuntimeCache = function() {
// Reset cache for branches, tags, etc
mout.object.forOwn(SvnResolver._cache, function(lru) {
lru.reset();
});
};
SvnResolver._cache = {
branches: new LRU({ max: 50, maxAge: 5 * 60 * 1000 }),
tags: new LRU({ max: 50, maxAge: 5 * 60 * 1000 }),
versions: new LRU({ max: 50, maxAge: 5 * 60 * 1000 })
};
module.exports = SvnResolver;

323
node_modules/bower/lib/core/resolvers/UrlResolver.js generated vendored Normal file
View File

@@ -0,0 +1,323 @@
var util = require('util');
var path = require('path');
var fs = require('../../util/fs');
var url = require('url');
var request = require('request');
var Q = require('q');
var mout = require('mout');
var junk = require('junk');
var Resolver = require('./Resolver');
var download = require('../../util/download');
var extract = require('../../util/extract');
var createError = require('../../util/createError');
function UrlResolver(decEndpoint, config, logger) {
Resolver.call(this, decEndpoint, config, logger);
// If target was specified, error out
if (this._target !== '*') {
throw createError("URL sources can't resolve targets", 'ENORESTARGET');
}
// If the name was guessed
if (this._guessedName) {
// Remove the ?xxx part
this._name = this._name.replace(/\?.*$/, '');
// Remove extension
this._name = this._name.substr(
0,
this._name.length - path.extname(this._name).length
);
}
this._remote = url.parse(this._source);
}
util.inherits(UrlResolver, Resolver);
mout.object.mixIn(UrlResolver, Resolver);
// -----------------
UrlResolver.isTargetable = function() {
return false;
};
UrlResolver.prototype._hasNew = function(pkgMeta) {
var oldCacheHeaders = pkgMeta._cacheHeaders || {};
var reqHeaders = {};
// If the previous cache headers contain an ETag,
// send the "If-None-Match" header with it
if (oldCacheHeaders.ETag) {
reqHeaders['If-None-Match'] = oldCacheHeaders.ETag;
}
if (this._config.userAgent) {
reqHeaders['User-Agent'] = this._config.userAgent;
}
// Make an HEAD request to the source
return (
Q.nfcall(request.head, this._source, {
ca: this._config.ca.default,
strictSSL: this._config.strictSsl,
timeout: this._config.timeout,
headers: reqHeaders
})
// Compare new headers with the old ones
.spread(
function(response) {
var cacheHeaders;
// If the server responded with 303 then the resource
// still has the same ETag
if (response.statusCode === 304) {
return false;
}
// If status code is not in the 2xx range,
// then just resolve to true
if (
response.statusCode < 200 ||
response.statusCode >= 300
) {
return true;
}
// Fallback to comparing cache headers
cacheHeaders = this._collectCacheHeaders(response);
return !mout.object.equals(oldCacheHeaders, cacheHeaders);
}.bind(this),
function() {
// Assume new contents if the request failed
// Note that we do not retry the request using the "request-replay" module
// because it would take too long
return true;
}
)
);
};
// TODO: There's room for improvement by using streams if the URL
// is an archive file, by piping read stream to the zip extractor
// This will likely increase the complexity of code but might worth it
UrlResolver.prototype._resolve = function() {
// Download
return (
this._download()
// Parse headers
.spread(this._parseHeaders.bind(this))
// Extract file
.spread(this._extract.bind(this))
// Rename file to index
.then(this._rename.bind(this))
);
};
// -----------------
UrlResolver.prototype._parseSourceURL = function(_url) {
return url.parse(path.basename(_url)).pathname;
};
UrlResolver.prototype._download = function() {
var fileName = this._parseSourceURL(this._source);
if (!fileName) {
this._source = this._source.replace(/\/(?=\?|#)/, '');
fileName = this._parseSourceURL(this._source);
}
var file = path.join(this._tempDir, fileName);
var reqHeaders = {};
var that = this;
if (this._config.userAgent) {
reqHeaders['User-Agent'] = this._config.userAgent;
}
this._logger.action('download', that._source, {
url: that._source,
to: file
});
// Download the file
return download(this._source, file, {
ca: this._config.ca.default,
strictSSL: this._config.strictSsl,
timeout: this._config.timeout,
headers: reqHeaders
})
.progress(function(state) {
var msg;
// Retry?
if (state.retry) {
msg =
'Download of ' +
that._source +
' failed' +
(state.error.code ? ' with ' + state.error.code : '') +
', ';
msg += 'retrying in ' + (state.delay / 1000).toFixed(1) + 's';
that._logger.debug('error', state.error.message, {
error: state.error
});
return that._logger.warn('retry', msg);
}
// Progress
msg =
'received ' + (state.received / 1024 / 1024).toFixed(1) + 'MB';
if (state.total) {
msg +=
' of ' +
(state.total / 1024 / 1024).toFixed(1) +
'MB downloaded, ';
msg += state.percent + '%';
}
that._logger.info('progress', msg);
})
.then(function(response) {
that._response = response;
return [file, response];
});
};
UrlResolver.prototype._parseHeaders = function(file, response) {
var disposition;
var newFile;
var match;
// Check if we got a Content-Disposition header
disposition = response.headers['content-disposition'];
if (!disposition) {
return Q.resolve([file, response]);
}
// Since there's various security issues with parsing this header, we only
// interpret word chars plus dots, dashes and spaces
match = disposition.match(/filename=(?:"([\w\-\. ]+)")/i);
if (!match) {
// The spec defines that the filename must be in quotes,
// though a wide range of servers do not follow the rule
match = disposition.match(/filename=([\w\-\.]+)/i);
if (!match) {
return Q.resolve([file, response]);
}
}
// Trim spaces
newFile = match[1].trim();
// The filename can't end with a dot because this is known
// to cause issues in Windows
// See: http://superuser.com/questions/230385/dots-at-end-of-file-name
if (mout.string.endsWith(newFile, '.')) {
return Q.resolve([file, response]);
}
newFile = path.join(this._tempDir, newFile);
return Q.nfcall(fs.rename, file, newFile).then(function() {
return [newFile, response];
});
};
UrlResolver.prototype._extract = function(file, response) {
var mimeType = response.headers['content-type'];
if (mimeType) {
// Clean everything after ; and trim the end result
mimeType = mimeType.split(';')[0].trim();
// Some servers add quotes around the content-type, so we trim that also
mimeType = mout.string.trim(mimeType, ['"', "'"]);
}
if (!extract.canExtract(file, mimeType)) {
return Q.resolve();
}
this._logger.action('extract', path.basename(this._source), {
archive: file,
to: this._tempDir
});
return extract(file, this._tempDir, {
mimeType: mimeType
});
};
UrlResolver.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 &&
!/^(component|bower)\.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)
);
};
UrlResolver.prototype._savePkgMeta = function(meta) {
// Store collected headers in the package meta
meta._cacheHeaders = this._collectCacheHeaders(this._response);
// Store ETAG under _release
if (meta._cacheHeaders.ETag) {
meta._release =
'e-tag:' +
mout.string.trim(meta._cacheHeaders.ETag.substr(0, 10), '"');
}
// Store main if is a single file
if (this._singleFile) {
meta.main = this._singleFile;
}
return Resolver.prototype._savePkgMeta.call(this, meta);
};
UrlResolver.prototype._collectCacheHeaders = function(res) {
var headers = {};
// Collect cache headers
this.constructor._cacheHeaders.forEach(function(name) {
var value = res.headers[name.toLowerCase()];
if (value != null) {
headers[name] = value;
}
});
return headers;
};
UrlResolver._cacheHeaders = [
'Content-MD5',
'ETag',
'Last-Modified',
'Content-Language',
'Content-Length',
'Content-Type',
'Content-Disposition'
];
module.exports = UrlResolver;

8
node_modules/bower/lib/core/resolvers/index.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
module.exports = {
GitFs: require('./GitFsResolver'),
GitRemote: require('./GitRemoteResolver'),
GitHub: require('./GitHubResolver'),
Svn: require('./SvnResolver'),
Fs: require('./FsResolver'),
Url: require('./UrlResolver')
};

View File

@@ -0,0 +1,385 @@
var Q = require('q');
var path = require('path');
var fs = require('../../util/fs');
var object = require('mout/object');
var semver = require('../../util/semver');
var createError = require('../../util/createError');
var readJson = require('../../util/readJson');
var removeIgnores = require('../../util/removeIgnores');
function pluginResolverFactory(resolverFactory, bower) {
bower = bower || {};
if (typeof resolverFactory !== 'function') {
throw createError(
'Resolver has "' +
typeof resolverFactory +
'" type instead of "function" type.',
'ERESOLERAPI'
);
}
var resolver = resolverFactory(bower);
function maxSatisfyingVersion(versions, target) {
var versionsArr, index;
versionsArr = versions.map(function(obj) {
return obj.version;
});
// Find a satisfying version, enabling strict match so that pre-releases
// have lower priority over normal ones when target is *
index = semver.maxSatisfyingIndex(versionsArr, target, true);
if (index !== -1) {
return versions[index];
}
}
function PluginResolver(decEndpoint) {
this._decEndpoint = decEndpoint;
}
// @private
PluginResolver.prototype.getEndpoint = function() {
return object.merge(this._decEndpoint, {
name: this.getName(),
source: this.getSource(),
target: this.getTarget()
});
};
PluginResolver.prototype.getSource = function() {
return this._decEndpoint.source;
};
PluginResolver.prototype.getTarget = function() {
return this._decEndpoint.target || '*';
};
PluginResolver.prototype.getName = function() {
if (!this._decEndpoint.name && typeof resolver.getName === 'function') {
return resolver.getName.call(resolver, this.getSource());
} else if (!this._decEndpoint.name) {
return path.basename(this.getSource());
} else {
return this._decEndpoint.name;
}
};
PluginResolver.prototype.getPkgMeta = function() {
return this._pkgMeta;
};
// -----------------
// Plugin Resolver is always considered potentially cacheable
// The "resolve" method decides whether to use cached or fetch new version.
PluginResolver.prototype.isCacheable = function() {
return true;
};
// Not only it's always potentially cacheable, but also always potenially new.
// The "resolve" handles logic of re-downloading target if needed.
PluginResolver.prototype.hasNew = function(pkgMeta) {
if (this.hasNewPromise) {
return this.hasNewPromise;
}
this._pkgMeta = pkgMeta;
return (this.hasNewPromise = this.resolve().then(function(result) {
return result !== undefined;
}));
};
PluginResolver.prototype.resolve = function() {
if (this.resolvePromise) {
return this.resolvePromise;
}
var that = this;
return (this.resolvePromise = Q.fcall(function() {
var target = that.getTarget();
// It means that we can accept ranges as targets
if (that.constructor.isTargetable()) {
that._release = target;
if (semver.validRange(target)) {
return Q.fcall(
resolver.releases.bind(resolver),
that.getSource()
).then(function(result) {
if (!result) {
throw createError(
'Resolver did not provide releases of package.'
);
}
var releases = (that._releases = result);
var versions = releases.filter(function(target) {
return semver.clean(target.version);
});
var maxRelease = maxSatisfyingVersion(versions, target);
if (maxRelease) {
that._version = maxRelease.version;
that._release = that._decEndpoint.target =
maxRelease.target;
} else {
throw createError(
'No version found that was able to satisfy ' +
target,
'ENORESTARGET',
{
details: !versions.length
? 'No versions found in ' +
that.getSource()
: 'Available versions: ' +
versions
.map(function(version) {
return version.version;
})
.join(', ')
}
);
}
});
}
} else {
if (semver.validRange(target) && target !== '*') {
return Q.reject(
createError(
'Resolver does not accept version ranges (' +
target +
')'
)
);
}
}
})
.then(function() {
// We pass old _resolution (if hasNew has been called before contents).
// So resolver can decide wheter use cached version of contents new one.
if (typeof resolver.fetch !== 'function') {
throw createError(
'Resolver does not implement the "fetch" method.'
);
}
var cached = {};
if (that._releases) {
cached.releases = that._releases;
}
if (that._pkgMeta) {
cached.endpoint = {
name: that._pkgMeta.name,
source: that._pkgMeta._source,
target: that._pkgMeta._target
};
cached.release = that._pkgMeta._release;
cached.version = that._pkgMeta.version;
cached.resolution = that._pkgMeta._resolution || {};
}
return Q.fcall(
resolver.fetch.bind(resolver),
that.getEndpoint(),
cached
);
})
.then(function(result) {
// Empty result means to re-use existing resolution
if (!result) {
return;
} else {
if (!result.tempPath) {
throw createError(
'Resolver did not provide path to extracted contents of package.'
);
}
that._tempDir = result.tempPath;
return that._readJson(that._tempDir).then(function(meta) {
return that
._applyPkgMeta(meta, result)
.then(that._savePkgMeta.bind(that, meta, result))
.then(function() {
return that._tempDir;
});
});
}
}));
};
PluginResolver.prototype._readJson = function(dir) {
var that = this;
return readJson(dir, {
assume: { name: that.getName() },
logger: bower.logger
}).spread(function(json, deprecated) {
if (deprecated) {
bower.logger.warn(
'deprecated',
'Package ' +
that.getName() +
' is using the deprecated ' +
deprecated
);
}
return json;
});
};
PluginResolver.prototype._applyPkgMeta = function(meta, result) {
// Check if name defined in the json is different
// If so and if the name was "guessed", assume the json name
if (meta.name !== this._name) {
this._name = meta.name;
}
// Handle ignore property, deleting all files from the temporary directory
// If no ignores were specified, simply resolve
if (
result.removeIgnores === false ||
!meta.ignore ||
!meta.ignore.length
) {
return Q.resolve(meta);
}
// Otherwise remove them from the temp dir
return removeIgnores(this._tempDir, meta).then(function() {
return meta;
});
};
PluginResolver.prototype._savePkgMeta = function(meta, result) {
var that = this;
meta._source = that.getSource();
meta._target = that.getTarget();
if (result.resolution) {
meta._resolution = result.resolution;
}
if (that._release) {
meta._release = that._release;
}
if (that._version) {
meta.version = that._version;
} else {
delete meta.version;
}
// Stringify contents
var contents = JSON.stringify(meta, null, 2);
return Q.nfcall(
fs.writeFile,
path.join(this._tempDir, '.bower.json'),
contents
).then(function() {
return (that._pkgMeta = meta);
});
};
// It is used only by "bower info". It returns all semver versions.
PluginResolver.versions = function(source) {
return Q.fcall(resolver.releases.bind(resolver), source).then(function(
result
) {
if (!result) {
throw createError(
'Resolver did not provide releases of package.'
);
}
var releases = (this._releases = result);
var versions = releases.map(function(version) {
return semver.clean(version.version);
});
versions = versions.filter(function(version) {
return version;
});
versions.sort(function(a, b) {
return semver.rcompare(a, b);
});
return versions;
});
};
PluginResolver.isTargetable = function() {
// If resolver doesn't define versions function, it's not targetable..
return typeof resolver.releases === 'function';
};
PluginResolver.clearRuntimeCache = function() {
resolver = resolverFactory(bower);
};
PluginResolver.match = function(source) {
if (typeof resolver.match !== 'function') {
throw createError(
'Resolver is missing "match" method.',
'ERESOLVERAPI'
);
}
var match = resolver.match.bind(resolver);
return Q.fcall(match, source).then(function(result) {
if (typeof result !== 'boolean') {
throw createError(
'Resolver\'s "match" method should return a boolean',
'ERESOLVERAPI'
);
}
return result;
});
};
PluginResolver.locate = function(source) {
if (typeof resolver.locate !== 'function') {
return source;
}
return Q.fcall(resolver.locate.bind(resolver), source).then(function(
result
) {
if (typeof result !== 'string') {
throw createError(
'Resolver\'s "locate" method should return a string',
'ERESOLVERAPI'
);
}
return result;
});
};
return PluginResolver;
}
module.exports = pluginResolverFactory;

122
node_modules/bower/lib/core/scripts.js generated vendored Normal file
View File

@@ -0,0 +1,122 @@
var mout = require('mout');
var cmd = require('../util/cmd');
var Q = require('q');
var shellquote = require('shell-quote');
var orderByDependencies = function(packages, installed, json) {
var ordered = [];
installed = mout.object.keys(installed);
var depsSatisfied = function(packageName) {
return (
mout.array.difference(
mout.object.keys(packages[packageName].dependencies),
installed,
ordered
).length === 0
);
};
var depsFromBowerJson =
json && json.dependencies ? mout.object.keys(json.dependencies) : [];
var packageNames = mout.object.keys(packages);
//get the list of the packages that are specified in bower.json in that order
//its nice to maintain that order for users
var desiredOrder = mout.array.intersection(depsFromBowerJson, packageNames);
//then add to the end any remaining packages that werent in bower.json
desiredOrder = desiredOrder.concat(
mout.array.difference(packageNames, desiredOrder)
);
//the desired order isn't necessarily a correct dependency specific order
//so we ensure that below
var resolvedOne = true;
while (resolvedOne) {
resolvedOne = false;
for (var i = 0; i < desiredOrder.length; i++) {
var packageName = desiredOrder[i];
if (depsSatisfied(packageName)) {
ordered.push(packageName);
mout.array.remove(desiredOrder, packageName);
//as soon as we resolve a package start the loop again
resolvedOne = true;
break;
}
}
if (!resolvedOne && desiredOrder.length > 0) {
//if we're here then some package(s) doesn't have all its deps satisified
//so lets just jam those names on the end
ordered = ordered.concat(desiredOrder);
}
}
return ordered;
};
var run = function(cmdString, action, logger, config) {
logger.action(action, cmdString);
//pass env + BOWER_PID so callees can identify a preinstall+postinstall from the same bower instance
var env = mout.object.mixIn({ BOWER_PID: process.pid }, process.env);
var args = shellquote.parse(cmdString, env);
var cmdName = args[0];
mout.array.remove(args, cmdName); //no rest() in mout
var options = {
cwd: config.cwd,
env: env
};
var promise = cmd(cmdName, args, options);
promise.progress(function(progress) {
progress.split('\n').forEach(function(line) {
if (line) {
logger.action(action, line);
}
});
});
return promise;
};
var hook = function(
action,
ordered,
config,
logger,
packages,
installed,
json
) {
if (
mout.object.keys(packages).length === 0 ||
!config.scripts ||
!config.scripts[action]
) {
return Q();
}
var orderedPackages = ordered
? orderByDependencies(packages, installed, json)
: mout.object.keys(packages);
var placeholder = new RegExp('%', 'g');
var cmdString = mout.string.replace(
config.scripts[action],
placeholder,
orderedPackages.join(' ')
);
return run(cmdString, action, logger, config);
};
module.exports = {
preuninstall: mout.function.partial(hook, 'preuninstall', false),
postuninstall: mout.function.partial(hook, 'postuninstall', false),
preinstall: mout.function.partial(hook, 'preinstall', true),
postinstall: mout.function.partial(hook, 'postinstall', true),
//only exposed for test
_orderByDependencies: orderByDependencies
};