mirror of
https://github.com/bower/bower.git
synced 2026-01-13 16:28:05 -05:00
305 lines
11 KiB
JavaScript
305 lines
11 KiB
JavaScript
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;
|