mirror of
https://github.com/bower/bower.git
synced 2026-04-24 03:00:19 -04:00
Remove links pointing to nonexistent folders on cache-clean, #182.
This commit is contained in:
committed by
Marcelo Conceição
parent
4f64412c19
commit
2ec352bc70
@@ -12,6 +12,7 @@ var nopt = require('nopt');
|
||||
var rimraf = require('rimraf');
|
||||
var path = require('path');
|
||||
var glob = require('glob');
|
||||
var fs = require('fs');
|
||||
var _ = require('lodash');
|
||||
|
||||
var help = require('./help');
|
||||
@@ -22,75 +23,119 @@ var fileExists = require('../util/file-exists');
|
||||
var optionTypes = { help: Boolean };
|
||||
var shorthand = { 'h': ['--help'] };
|
||||
|
||||
var removePkg = function (pkg, emitter, next) {
|
||||
var processCachedPackage = function (emitter, pkg, next) {
|
||||
removeCachedPackage(pkg, function (err, exists) {
|
||||
if (err) {
|
||||
emitter.emit('error', err);
|
||||
return next();
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
template('action', { name: 'cache cleared', shizzle: pkg })
|
||||
.on('data', emitter.emit.bind(emitter, 'data'));
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
};
|
||||
|
||||
var removeCachedPackage = function (pkg, next) {
|
||||
var folder = path.join(config.cache, pkg);
|
||||
|
||||
fileExists(folder, function (exists) {
|
||||
var err;
|
||||
|
||||
if (!exists) {
|
||||
err = new Error('Package ' + pkg + ' is not installed');
|
||||
emitter.emit('error', err);
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if (!exists) return next(null, false);
|
||||
rimraf(folder, function (err) {
|
||||
if (err) {
|
||||
emitter.emit('error', err);
|
||||
return next(err);
|
||||
}
|
||||
|
||||
emitter.emit('data', template('action', { name: 'cleared', shizzle: pkg }, true));
|
||||
next();
|
||||
if (err) return next(err);
|
||||
next(null, true);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var createFuncs = function (pkgs, emitter) {
|
||||
return pkgs.map(function (pkg) {
|
||||
pkg = pkg.replace(/^\.\//, '');
|
||||
return removePkg.bind(removePkg, pkg, emitter);
|
||||
var processLinkedPackage = function (emitter, pkg, next) {
|
||||
checkAndRemoveLinkToPackage(pkg, function (err, removed) {
|
||||
if (err) {
|
||||
emitter.emit('error', err);
|
||||
return next();
|
||||
}
|
||||
|
||||
if (removed) {
|
||||
template('action', { name: 'link cleared', shizzle: pkg })
|
||||
.on('data', emitter.emit.bind(emitter, 'data'));
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
};
|
||||
|
||||
var cleanCompletion = function (emitter, next) {
|
||||
fileExists(config.completion, function (exists) {
|
||||
if (!exists) return next();
|
||||
var checkAndRemoveLinkToPackage = function (pkg, next) {
|
||||
var folder = path.join(config.links, pkg);
|
||||
|
||||
rimraf(config.completion, function (err) {
|
||||
if (err) {
|
||||
emitter.emit('error', err);
|
||||
return next(err);
|
||||
fs.readlink(folder, function (err, linkString) {
|
||||
if (err && err.code === 'ENOENT') return next();
|
||||
|
||||
fileExists(linkString, function (exists) {
|
||||
if (!exists) {
|
||||
return rimraf(folder, function (err) {
|
||||
if (err) return next(err);
|
||||
next(null, true);
|
||||
});
|
||||
}
|
||||
|
||||
emitter.emit('data', template('action', { name: 'cleared', shizzle: 'completion cache' }, true));
|
||||
next();
|
||||
next(null, false);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = function (pkgs) {
|
||||
var emitter = new Emitter;
|
||||
var funcs;
|
||||
|
||||
// If no pkgs are passed we delete all
|
||||
// Otherwise we delete the passed ones
|
||||
if (!pkgs || !pkgs.length) {
|
||||
glob('./*', { cwd: config.cache }, function (err, dirs) {
|
||||
if (err) return emitter.emit('error', err);
|
||||
pkgs = dirs;
|
||||
funcs = createFuncs(pkgs, emitter);
|
||||
async.parallel({
|
||||
cache: function (next) {
|
||||
if (!pkgs || !pkgs.length) {
|
||||
glob('./*', { cwd: config.cache }, function (err, dirs) {
|
||||
if (err) {
|
||||
emitter.emit('error', err);
|
||||
return next();
|
||||
}
|
||||
|
||||
// If all the cache is to be cleared,
|
||||
// also clear the completion cache
|
||||
funcs.push(cleanCompletion.bind(cleanCompletion, emitter));
|
||||
var pkgs = dirs.map(function (dir) { return dir.replace(/^\.\//, ''); });
|
||||
async.forEach(pkgs, processCachedPackage.bind(this, emitter), next);
|
||||
});
|
||||
} else {
|
||||
pkgs = _.uniq(pkgs);
|
||||
async.forEach(pkgs, processCachedPackage.bind(this, emitter), next);
|
||||
}
|
||||
},
|
||||
links: function (next) {
|
||||
if (!pkgs || !pkgs.length) {
|
||||
glob('./*', { cwd: config.links }, function (err, dirs) {
|
||||
if (err) {
|
||||
emitter.emit('error', err);
|
||||
return next();
|
||||
}
|
||||
|
||||
async.parallel(funcs, emitter.emit.bind(emitter, 'end'));
|
||||
});
|
||||
} else {
|
||||
funcs = createFuncs(_.uniq(pkgs), emitter);
|
||||
async.parallel(funcs, emitter.emit.bind(emitter, 'end'));
|
||||
}
|
||||
var pkgs = dirs.map(function (dir) { return dir.replace(/^\.\//, ''); });
|
||||
async.forEach(pkgs, processLinkedPackage.bind(this, emitter), next);
|
||||
});
|
||||
} else {
|
||||
pkgs = _.uniq(pkgs);
|
||||
async.forEach(pkgs, processLinkedPackage.bind(this, emitter), next);
|
||||
}
|
||||
},
|
||||
completion: function (next) {
|
||||
rimraf(config.completion, function (err) {
|
||||
if (err) {
|
||||
emitter.emit('error', err);
|
||||
return next();
|
||||
}
|
||||
|
||||
template('action', { name: 'completion cleared', shizzle: 'completion cache' })
|
||||
.on('data', emitter.emit.bind(emitter, 'data'));
|
||||
|
||||
next();
|
||||
});
|
||||
}
|
||||
}, emitter.emit.bind(emitter, 'end'));
|
||||
|
||||
return emitter;
|
||||
};
|
||||
|
||||
@@ -13,24 +13,39 @@ describe('cache-clean', function () {
|
||||
function clean(done) {
|
||||
var del = 0;
|
||||
|
||||
rimraf(config.directory, function () {
|
||||
// Ignore the error if the local directory was not actually deleted
|
||||
if (++del >= 2) createCache(done);
|
||||
rimraf(config.cache, function (err) {
|
||||
if (err) return done(new Error('Unable to remove cache directory'));
|
||||
if (++del >= 3) createDirs(done);
|
||||
});
|
||||
|
||||
rimraf(config.cache, function () {
|
||||
// Ignore the error if the cache directory was not actually deleted
|
||||
if (++del >= 2) createCache(done);
|
||||
rimraf(config.links, function (err) {
|
||||
if (err) return done(new Error('Unable to remove links directory'));
|
||||
if (++del >= 3) createDirs(done);
|
||||
});
|
||||
|
||||
rimraf(__dirname + '/temp', function (err) {
|
||||
if (err) return done(new Error('Unable to remove temp directory'));
|
||||
if (++del >= 3) createDirs(done);
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(clean);
|
||||
beforeEach(function (done) {
|
||||
clean(function (err) {
|
||||
if (err) return done(err);
|
||||
fs.mkdirSync(__dirname + '/temp');
|
||||
done();
|
||||
});
|
||||
});
|
||||
after(clean);
|
||||
|
||||
function createCache(done) {
|
||||
function createDirs(done) {
|
||||
mkdirp(config.cache, function (err) {
|
||||
if (err) throw new Error('Unable to create cache');
|
||||
done();
|
||||
if (err) return done(new Error('Unable to create cache directory'));
|
||||
|
||||
mkdirp(config.links, function (err) {
|
||||
if (err) return done(new Error('Unable to create links directory'));
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -45,9 +60,18 @@ describe('cache-clean', function () {
|
||||
fs.writeFileSync(path.join(someDir, 'some-other-file'), 'bower is fantastic');
|
||||
}
|
||||
|
||||
function simulateLink(name, linkedPath) {
|
||||
var dir = path.join(config.links, name);
|
||||
fs.mkdirSync(linkedPath);
|
||||
fs.symlinkSync(linkedPath, dir);
|
||||
}
|
||||
|
||||
it('Should clean the entire cache', function (next) {
|
||||
simulatePackage('some-package');
|
||||
simulatePackage('other-package');
|
||||
simulateLink('linked-package', __dirname + '/temp/linked-package');
|
||||
fs.rmdirSync(__dirname + '/temp/linked-package'); // simulate invalid symlinks
|
||||
simulateLink('linked-package2', __dirname + '/temp/linked-package2');
|
||||
|
||||
var cleaner = cacheClean();
|
||||
|
||||
@@ -59,7 +83,19 @@ describe('cache-clean', function () {
|
||||
glob(config.cache + '/*', function (err, dirs) {
|
||||
if (err) throw err;
|
||||
assert(dirs.length === 0);
|
||||
next();
|
||||
|
||||
glob(config.links + '/*', function (err, dirs) {
|
||||
if (err) throw err;
|
||||
|
||||
dirs = dirs.map(function (dir) {
|
||||
return path.basename(dir);
|
||||
});
|
||||
|
||||
assert(dirs.length === 1);
|
||||
assert.deepEqual(dirs, ['linked-package2']);
|
||||
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -88,17 +124,28 @@ describe('cache-clean', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Should throw error on unknown package', function (next) {
|
||||
var cleaner = cacheClean(['not-cached-package']),
|
||||
cleanedPkg = false;
|
||||
it('Should clean only the selected links', function (next) {
|
||||
simulateLink('linked-package', __dirname + '/temp/linked-package');
|
||||
fs.rmdirSync(__dirname + '/temp/linked-package'); // simulate invalid symlinks
|
||||
simulateLink('linked-package2', __dirname + '/temp/linked-package2');
|
||||
fs.rmdirSync(__dirname + '/temp/linked-package2'); // simulate invalid symlinks
|
||||
|
||||
var cleaner = cacheClean(['linked-package']);
|
||||
|
||||
cleaner.on('error', function (err) {
|
||||
if (/not\-cached\-package/.test(err)) cleanedPkg = true;
|
||||
throw err;
|
||||
});
|
||||
|
||||
cleaner.on('end', function () {
|
||||
if (!cleanedPkg) throw new Error('Should have thrown an error.');
|
||||
next();
|
||||
glob(config.links + '/*', function (err, dirs) {
|
||||
if (err) throw err;
|
||||
dirs = dirs.map(function (dir) {
|
||||
return path.basename(dir);
|
||||
});
|
||||
|
||||
assert.deepEqual(dirs, ['linked-package2']);
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user