123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- var fs = require('graceful-fs');
- var path = require('path');
- var mout = require('mout');
- var Q = require('q');
- var rimraf = require('rimraf');
- var endpointParser = require('bower-endpoint-parser');
- var PackageRepository = require('../../core/PackageRepository');
- var semver = require('../../util/semver');
- var cli = require('../../util/cli');
- var defaultConfig = require('../../config');
- function clean(logger, endpoints, options, config) {
- var decEndpoints;
- var names;
- options = options || {};
- config = defaultConfig(config);
- // If endpoints is an empty array, null them
- if (endpoints && !endpoints.length) {
- endpoints = null;
- }
- // Generate decomposed endpoints and names based on the endpoints
- if (endpoints) {
- decEndpoints = endpoints.map(function (endpoint) {
- return endpointParser.decompose(endpoint);
- });
- names = decEndpoints.map(function (decEndpoint) {
- return decEndpoint.name || decEndpoint.source;
- });
- }
- return Q.all([
- clearPackages(decEndpoints, config, logger),
- clearLinks(names, config, logger),
- !names ? clearCompletion(config, logger) : null
- ])
- .spread(function (entries) {
- return entries;
- });
- }
- function clearPackages(decEndpoints, config, logger) {
- var repository = new PackageRepository(config, logger);
- return repository.list()
- .then(function (entries) {
- var promises;
- // Filter entries according to the specified packages
- if (decEndpoints) {
- entries = entries.filter(function (entry) {
- return !!mout.array.find(decEndpoints, function (decEndpoint) {
- var entryPkgMeta = entry.pkgMeta;
- // Check if name or source match the entry
- if (decEndpoint.name !== entryPkgMeta.name &&
- decEndpoint.source !== entryPkgMeta.name &&
- decEndpoint.source !== entryPkgMeta._source
- ) {
- return false;
- }
- // If target is a wildcard, simply return true
- if (decEndpoint.target === '*') {
- return true;
- }
- // If it's a semver target, compare using semver spec
- if (semver.validRange(decEndpoint.target)) {
- return semver.satisfies(entryPkgMeta.version, decEndpoint.target);
- }
- // Otherwise, compare against target/release
- return decEndpoint.target === entryPkgMeta._target ||
- decEndpoint.target === entryPkgMeta._release;
- });
- });
- }
- promises = entries.map(function (entry) {
- return repository.eliminate(entry.pkgMeta)
- .then(function () {
- logger.info('deleted', 'Cached package ' + entry.pkgMeta.name + ': ' + entry.canonicalDir, {
- file: entry.canonicalDir
- });
- });
- });
- return Q.all(promises)
- .then(function () {
- if (!decEndpoints) {
- // Ensure that everything is cleaned,
- // even invalid packages in the cache
- return repository.clear();
- }
- })
- .then(function () {
- return entries;
- });
- });
- }
- function clearLinks(names, config, logger) {
- var promise;
- var dir = config.storage.links;
- // If no names are passed, grab all links
- if (!names) {
- promise = Q.nfcall(fs.readdir, dir)
- .fail(function (err) {
- if (err.code === 'ENOENT') {
- return [];
- }
- throw err;
- });
- // Otherwise use passed ones
- } else {
- promise = Q.resolve(names);
- }
- return promise
- .then(function (names) {
- var promises;
- var linksToRemove = [];
- // Decide which links to delete
- promises = names.map(function (name) {
- var link = path.join(config.storage.links, name);
- return Q.nfcall(fs.readlink, link)
- .then(function (linkTarget) {
- // Link exists, check if it points to a folder
- // that still exists
- return Q.nfcall(fs.stat, linkTarget)
- .then(function (stat) {
- // Target is not a folder..
- if (!stat.isDirectory()) {
- linksToRemove.push(link);
- }
- })
- // Error occurred reading the link
- .fail(function () {
- linksToRemove.push(link);
- });
- // Ignore if link does not exist
- }, function (err) {
- if (err.code !== 'ENOENT') {
- linksToRemove.push(link);
- }
- });
- });
- return Q.all(promises)
- .then(function () {
- var promises;
- // Remove each link that was declared as invalid
- promises = linksToRemove.map(function (link) {
- return Q.nfcall(rimraf, link)
- .then(function () {
- logger.info('deleted', 'Invalid link: ' + link, {
- file: link
- });
- });
- });
- return Q.all(promises);
- });
- });
- }
- function clearCompletion(config, logger) {
- var dir = config.storage.completion;
- return Q.nfcall(fs.stat, dir)
- .then(function () {
- return Q.nfcall(rimraf, dir)
- .then(function () {
- logger.info('deleted', 'Completion cache', {
- file: dir
- });
- });
- }, function (error) {
- if (error.code !== 'ENOENT') {
- throw error;
- }
- });
- }
- // -------------------
- clean.line = function (logger, argv) {
- var options = cli.readOptions(argv);
- var endpoints = options.argv.remain.slice(2);
- return clean(logger, endpoints, options);
- };
- clean.completion = function () {
- // TODO:
- };
- module.exports = clean;
|