Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bower

Package Overview
Dependencies
Maintainers
2
Versions
99
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bower - npm Package Compare versions

Comparing version 0.6.8 to 0.7.0

lib/commands/completion.js

22

CHANGELOG.md
# Changelog
## 0.7.0 - 2013-02-01
- __Ability to resolve conflicts__ ([#214](https://github.com/twitter/bower/issues/214))
- __Add ability to search and publish to different endpoints by specifiying them in the `.bowerrc` file__
- __Add experimental autocompletion__
- __Ability to specify files to ignore when copying__
- Fix minor issues in the cache clean command
- Better error message for invalid semver tags ([#185](https://github.com/twitter/bower/issues/185))
- Only show discover message in the list command only if there are packages
- Fix mismatch issue due to reading cached component.json files ([#214](https://github.com/twitter/bower/issues/214))
- Better error messages when reading invalid .bowerrc files ([#220](https://github.com/twitter/bower/issues/220))
- Fix update command when used in packages pointing to assets ([#197](https://github.com/twitter/bower/issues/197))
- Bower now obeys packages's `.bowerrc` if they define a different `json` ([#205](https://github.com/twitter/bower/issues/205))
## 0.6.8 - 2012-12-14

@@ -7,5 +21,5 @@ - Improve list command

- Add --offline option to prevent versions from being fetched
- Fix uninstall command not fired the `end` event
- Fix error when executing and unknown command ([#178](https://github.com/twitter/bower/issues/179))
- Fix help for the ls command (alias of list)
- Fix uninstall command not firing the `end` event
- Fix error when executing an unknown command ([#179](https://github.com/twitter/bower/issues/179))
- Fix help for the ls command (alias of list)

@@ -67,2 +81,2 @@ ## 0.6.7 - 2012-12-10

- Add jshintrc and fix a lot of issues related with JSHint warnings
- `bower register` now prompts if the user really wants to proceed
- `bower register` now prompts if the user really wants to proceed

@@ -29,10 +29,18 @@ // ==========================================

fileExists(folder, function (exists) {
if (!exists) return emitter.emit('error', new Error('Package ' + pkg + ' is not installed'));
var err;
if (!exists) {
err = new Error('Package ' + pkg + ' is not installed');
emitter.emit('error', err);
return next(err);
}
rimraf(folder, function (err) {
if (err) emitter.emit('error', err);
else {
emitter.emit('data', template('action', { name: 'cleared', shizzle: pkg }, true));
next();
if (err) {
emitter.emit('error', err);
return next(err);
}
emitter.emit('data', template('action', { name: 'cleared', shizzle: pkg }, true));
next();
});

@@ -49,4 +57,21 @@ });

var cleanCompletion = function (emitter, next) {
fileExists(config.completion, function (exists) {
if (!exists) return next();
rimraf(config.completion, function (err) {
if (err) {
emitter.emit('error', err);
return next(err);
}
emitter.emit('data', template('action', { name: 'cleared', shizzle: 'completion cache' }, true));
next();
});
});
};
module.exports = function (pkgs) {
var emitter = new Emitter;
var funcs;

@@ -59,6 +84,13 @@ // If no pkgs are passed we delete all

pkgs = dirs;
async.parallel(createFuncs(pkgs, emitter), emitter.emit.bind(emitter, 'end'));
funcs = createFuncs(pkgs, emitter);
// If all the cache is to be cleared,
// also clear the completion cache
funcs.push(cleanCompletion.bind(cleanCompletion, emitter));
async.parallel(funcs, emitter.emit.bind(emitter, 'end'));
});
} else {
async.parallel(createFuncs(_.uniq(pkgs), emitter), emitter.emit.bind(emitter, 'end'));
funcs = createFuncs(_.uniq(pkgs), emitter);
async.parallel(funcs, emitter.emit.bind(emitter, 'end'));
}

@@ -76,1 +108,13 @@

};
module.exports.completion = function (opts, cb) {
glob('./*', { cwd: config.cache }, function (err, dirs) {
if (err) return cb(err);
dirs = dirs.map(function (dir) {
return dir.replace(/^\.\//, '');
});
cb(null, dirs);
});
};
module.exports.completion.options = shorthand;

@@ -45,2 +45,6 @@ // ==========================================

return module.exports(paths[0]);
};
};
module.exports.completion = function (opts, cb) {
return cb(null, Object.keys(require('../commands')));
};

5

lib/commands/index.js

@@ -21,3 +21,4 @@ // ==========================================

'search': require('./search'),
'cache-clean': require('./cache-clean')
};
'cache-clean': require('./cache-clean'),
'completion': require('./completion')
};

@@ -13,2 +13,3 @@ // ==========================================

var source = require('../core/source');
var install = require('./install');
var help = require('./help');

@@ -46,2 +47,5 @@

return emitter;
};
};
module.exports.completion = install.completion;
module.exports.completion.options = shorthand;

@@ -16,9 +16,13 @@ // ==========================================

var nopt = require('nopt');
var fs = require('fs');
var path = require('path');
var Manager = require('../core/manager');
var config = require('../core/config');
var source = require('../core/source');
var save = require('../util/save');
var help = require('./help');
var optionTypes = { help: Boolean, save: Boolean, force: Boolean };
var shorthand = { 'h': ['--help'], 'S': ['--save'], 'f': ['--force'] };
var optionTypes = { help: Boolean, save: Boolean, force: Boolean, 'force-latest': Boolean };
var shorthand = { 'h': ['--help'], 'S': ['--save'], 'f': ['--force'], 'F': ['--force-latest'] };

@@ -29,5 +33,8 @@ module.exports = function (paths, options) {

var emitter = new Emitter;
var manager = new Manager(paths, { force: options && options.force });
var manager = new Manager(paths, {
force: options.force,
forceLatest: options['force-latest']
});
if (options.save) save(manager, paths);
if (options.save) save(manager);

@@ -50,1 +57,27 @@ manager

};
module.exports.completion = function (opts, cb) {
var cache = path.join(config.completion, 'install.json');
var done = function done(err, results) {
if (err) return cb(err);
var names = results.map(function (pkg) {
return pkg.name;
});
return cb(null, names);
};
fs.readFile(cache, function (err, body) {
if (!err) return done(null, JSON.parse(body));
// expected error, do the first request and cache the results
source.all(function (err, results) {
if (err) return cb(err);
fs.writeFile(cache, JSON.stringify(results, null, 2), function (err) {
done(err, results);
});
});
});
};
module.exports.completion.options = shorthand;

@@ -111,2 +111,12 @@ // ==========================================

return module.exports(name);
};
};
module.exports.completion = function (opts, cb) {
fs.readdir(config.links, function (err, dirs) {
// ignore ENOENT, ~/.bower/links not created yet
if (err && err.code === 'ENOENT') return cb(null, []);
cb(err, dirs);
});
};
module.exports.completion.options = shorthand;

@@ -145,11 +145,5 @@ // ==========================================

// If the user passed the paths or map options, we don't need to fetch versions
if (!options.offline && !options.paths && !options.map && options.argv) {
template('action', { name: 'discover', shizzle: 'Please wait while newer package versions are being discovered' })
.on('data', emitter.emit.bind(emitter, 'data'));
checkVersions = true;
}
manager.once('resolveLocal', function () {
var packages = {};
var values;

@@ -160,27 +154,38 @@ Object.keys(manager.dependencies).forEach(function (key) {

async.forEach(_.values(packages), function (pkg, next) {
pkg.once('loadJSON', function () {
// Only check versions if not offline and it's a repo
var fetchVersions = checkVersions &&
this.json.repository &&
(this.json.repository.type === 'git' || this.json.repository.type === 'local-repo');
values = _.values(packages);
if (fetchVersions) {
pkg.once('versions', function (versions) {
pkg.tags = versions.map(function (ver) {
return semver.valid(ver) ? semver.clean(ver) : ver;
});
if (values.length) {
// If the user passed the paths or map options, we don't need to fetch versions
if (!options.offline && !options.paths && !options.map && options.argv) {
template('action', { name: 'discover', shizzle: 'Please wait while newer package versions are being discovered' })
.on('data', emitter.emit.bind(emitter, 'data'));
checkVersions = true;
}
async.forEach(values, function (pkg, next) {
pkg.once('loadJSON', function () {
// Only check versions if not offline and it's a repo
var fetchVersions = checkVersions &&
this.json.repository &&
(this.json.repository.type === 'git' || this.json.repository.type === 'local-repo');
if (fetchVersions) {
pkg.once('versions', function (versions) {
pkg.tags = versions.map(function (ver) {
return semver.valid(ver) ? semver.clean(ver) : ver;
});
next();
}).versions();
} else {
pkg.tags = [];
next();
}).versions();
} else {
pkg.tags = [];
next();
}
}).loadJSON();
}, function () {
var tree = getTree(packages);
if (!options.paths && !options.map && options.argv) return cliTree(emitter, packages, tree);
tree = options.paths ? shallowTree(packages, tree) : deepTree(packages, tree);
emitter.emit('data', options.argv ? JSON.stringify(tree, null, 2) : tree);
});
}
}).loadJSON();
}, function () {
var tree = getTree(packages);
if (!options.paths && !options.map && options.argv) return cliTree(emitter, packages, tree);
tree = options.paths ? shallowTree(packages, tree) : deepTree(packages, tree);
emitter.emit('data', options.argv ? JSON.stringify(tree, null, 2) : tree);
});
}
}).resolveLocal();

@@ -195,2 +200,14 @@

return module.exports(options);
};
};
module.exports.completion = function (opts, cb) {
if (!/^-/.test(opts.word)) return cb(null, []);
var results = Object.keys(optionTypes).map(function (option) {
return '--' + option;
});
cb(null, results);
};
module.exports.completion.options = shorthand;

@@ -14,2 +14,3 @@ // ==========================================

var source = require('../core/source');
var install = require('./install');
var help = require('./help');

@@ -50,2 +51,5 @@

return module.exports(names[0]);
};
};
module.exports.completion = install.completion;
module.exports.completion.options = shorthand;

@@ -56,2 +56,13 @@ // ==========================================

return module.exports(args[0], args[1], options);
};
};
module.exports.completion = function (opts, cb) {
var word = opts.word;
// completing options?
if (word.charAt(0) === '-') {
return cb(null, Object.keys(optionTypes).map(function (option) {
return '--' + option;
}));
}
};

@@ -14,2 +14,3 @@ // ==========================================

var source = require('../core/source');
var install = require('./install');
var help = require('./help');

@@ -50,2 +51,5 @@

return module.exports(names[0]);
};
};
module.exports.completion = install.completion;
module.exports.completion.options = shorthand;

@@ -147,3 +147,6 @@ // ==========================================

async.forEach(uninstallables, function (pkg, next) {
pkg.on('uninstall', next).uninstall();
pkg.on('uninstall', function () {
emitter.emit('package', pkg);
next();
}).uninstall();
}, function () {

@@ -179,2 +182,21 @@ // Finally save

return module.exports(names, options);
};
};
module.exports.completion = function (opts, cb) {
var word = opts.word;
// completing options?
if (opts.words[0] === 'uninstall' && word.charAt(0) === '-') {
return cb(null, Object.keys(optionTypes).map(function (option) {
return '--' + option;
}));
}
fs.readdir(config.directory, function (err, dirs) {
// ignore ENOENT, ./components not created yet
if (err && err.code === 'ENOENT') return cb(null, []);
cb(err, dirs);
});
};
module.exports.completion.options = shorthand;

@@ -14,7 +14,9 @@ // ==========================================

var Manager = require('../core/manager');
var help = require('./help');
var Manager = require('../core/manager');
var help = require('./help');
var uninstall = require('./uninstall');
var save = require('../util/save');
var shorthand = { 'h': ['--help'], 'f': ['--force'] };
var optionTypes = { help: Boolean, force: Boolean };
var optionTypes = { help: Boolean, save: Boolean, force: Boolean, 'force-latest': Boolean };
var shorthand = { 'h': ['--help'], 'S': ['--save'], 'f': ['--force'], 'F': ['--force-latest'] };

@@ -24,4 +26,7 @@ module.exports = function (names, options) {

var manager = new Manager([], { force: options && options.force });
var emitter = new Emitter;
var manager = new Manager([], {
force: options.force,
forceLatest: options['force-latest']
});

@@ -47,2 +52,5 @@ manager.on('data', emitter.emit.bind(emitter, 'data'));

manager = new Manager(endpoints, options);
if (options.save) save(manager);
manager

@@ -64,3 +72,5 @@ .on('data', emitter.emit.bind(emitter, 'data'))

if (!pkg.json.commit || pkg.json.version !== '0.0.0') {
// Add tag only if the endpoint is a repository
var json = pkg.json;
if (!json.commit && (!json.repository || json.repository === 'git' || json.repository === 'local-repo')) {
endpoint += '#' + ((!names || names.indexOf(pkg.name) > -1) ? '~' : '') + pkg.version;

@@ -84,2 +94,5 @@ }

return module.exports(paths, options);
};
};
module.exports.completion = uninstall.completion;
module.exports.completion.options = shorthand;

@@ -26,9 +26,15 @@ var path = require('path');

// Bower Config
var config = require('rc') ('bower', {
cache : path.join(roaming, folder, 'cache'),
links : path.join(roaming, folder, 'links'),
json : 'component.json',
endpoint : 'https://bower.herokuapp.com',
directory : 'components'
});
var config;
try {
config = require('rc') ('bower', {
cache : path.join(roaming, folder, 'cache'),
links : path.join(roaming, folder, 'links'),
completion : path.join(roaming, folder, 'completion'),
json : 'component.json',
endpoint : 'https://bower.herokuapp.com',
directory : 'components'
});
} catch (e) {
throw new Error('Unable to parse global .bowerrc file: ' + e.message);
}

@@ -38,3 +44,7 @@ // If there is a local .bowerrc file, merge it

if (fileExists(localFile)) {
_.extend(config, JSON.parse(fs.readFileSync(localFile)));
try {
_.extend(config, JSON.parse(fs.readFileSync(localFile)));
} catch (e) {
throw new Error('Unable to parse local .bowerrc file: ' + e.message);
}
}

@@ -46,2 +56,2 @@

module.exports = config;
module.exports = config;

@@ -9,3 +9,4 @@ // ==========================================

// Events:
// - install: fired when package installed
// - install: fired when everything is installed
// - package: fired for each installed packaged
// - resolve: fired when deps resolved (with a true/false indicating success or error)

@@ -22,2 +23,3 @@ // - error: fired on all errors

var fs = require('fs');
var _ = require('lodash');

@@ -90,2 +92,7 @@ var Package = require('./package');

if (this.endpoints.length) {
// TODO: When resolving specific endpoints we need to restore all the local
// packages and their hierarchy (all from the local folder)
// If something goes wrong, simply do resolveFromJSON before
// calling resolved() (slower)
// This will solve issue #200
this.once('resolveEndpoints', resolved).resolveEndpoints();

@@ -128,2 +135,3 @@ } else {

var pkg = new Package(name, endpoint, this);
pkg.root = true;
this.dependencies[name] = this.dependencies[name] || [];

@@ -153,2 +161,3 @@ this.dependencies[name].push(pkg);

var pkg = new Package(name, endpoint, this);
pkg.root = true;
this.dependencies[name] = this.dependencies[name] || [];

@@ -187,8 +196,28 @@ this.dependencies[name].push(pkg);

Manager.prototype.prune = function () {
try {
this.dependencies = prune(this.getDeepDependencies());
} catch (err) {
this.emit('error', err);
var result = prune(this.getDeepDependencies(), this.opts.forceLatest);
var name;
// If there is conflicted deps, print them and fail
if (result.conflicted) {
for (name in result.conflicted) {
this.reportConflicts(name, result.conflicted[name]);
}
return false;
}
this.dependencies = {};
// If there is conflicted deps but they where forcebly resolved
// Print a warning about them
if (result.forceblyResolved) {
for (name in result.forceblyResolved) {
this.reportForceblyResolved(name, result.forceblyResolved[name]);
this.dependencies[name] = result.forceblyResolved[name];
this.dependencies[name][0].root = true;
}
}
_.extend(this.dependencies, result.resolved);
return true;

@@ -200,3 +229,6 @@ };

var pkg = this.dependencies[name][0];
pkg.once('install', next).install();
pkg.once('install', function () {
this.emit('package', pkg);
next();
}.bind(this)).install();
pkg.once('error', next);

@@ -227,2 +259,38 @@ }.bind(this), function () {

Manager.prototype.reportConflicts = function (name, packages) {
var versions = [];
var requirements = [];
packages = packages.filter(function (pkg) { return !!pkg.version; });
packages.forEach(function (pkg) {
requirements.push({ pkg: pkg, tag: pkg.originalTag || '~' + pkg.version });
versions.push((pkg.originalTag || '~' + pkg.version).white);
});
this.emit('error', new Error('No resolvable version for ' + name));
this.emit('data', template('conflict', {
name: name,
requirements: requirements,
json: config.json,
versions: versions.slice(0, -1).join(', ') + ' or ' + versions[versions.length - 1]
}, true));
};
Manager.prototype.reportForceblyResolved = function (name, packages) {
var requirements = [];
packages = packages.filter(function (pkg) { return !!pkg.version; });
packages.forEach(function (pkg) {
requirements.push({ pkg: pkg, tag: pkg.originalTag || '~' + pkg.version });
});
this.emit('data', template('resolved-conflict', {
name: name,
requirements: requirements,
json: config.json,
resolvedTo: packages[0].version,
forceLatest: this.opts.forceLatest
}, true));
};
module.exports = Manager;

@@ -24,2 +24,3 @@ // ==========================================

var path = require('path');
var glob = require('glob');
var url = require('url');

@@ -192,3 +193,3 @@ var tmp = require('tmp');

var err = new Error('Local path is a local repository');
err.details = 'To avoid loosing work, please remove ' + localPath + ' manually.';
err.details = 'To avoid losing work, please remove ' + localPath + ' manually.';
return this.emit('error', err, this);

@@ -224,21 +225,65 @@ }

Package.prototype.cleanUpLocal = function () {
this.json.name = this.name;
this.json.version = this.commit ? '0.0.0' : this.version || '0.0.0';
this.once('readLocalConfig', function () {
this.json.name = this.name;
this.json.version = this.commit ? '0.0.0' : this.version || '0.0.0';
// Detect commit and save it in the json for later use
if (this.commit) this.json.commit = this.commit;
else delete this.json.commit;
// Detect commit and save it in the json for later use
if (this.commit) this.json.commit = this.commit;
else delete this.json.commit;
if (this.gitUrl) this.json.repository = { type: 'git', url: this.gitUrl };
else if (this.gitPath) this.json.repository = { type: 'local-repo', path: this.originalPath };
else if (this.originalPath) this.json.repository = { type: 'local', path: this.originalPath };
else if (this.assetUrl) this.json = this.generateAssetJSON();
if (this.gitUrl) this.json.repository = { type: 'git', url: this.gitUrl };
else if (this.gitPath) this.json.repository = { type: 'local-repo', path: this.originalPath };
else if (this.originalPath) this.json.repository = { type: 'local', path: this.originalPath };
else if (this.assetUrl) this.json = this.generateAssetJSON();
var jsonStr = JSON.stringify(this.json, null, 2);
fs.writeFile(path.join(this.localPath, config.json), jsonStr);
if (this.gitUrl || this.gitPath) fs.writeFile(path.join(this.gitPath, config.json), jsonStr);
var jsonStr = JSON.stringify(this.json, null, 2);
rimraf(path.join(this.localPath, '.git'), this.emit.bind(this, 'install'));
fs.writeFile(path.join(this.localPath, this.localConfig.json), jsonStr);
if (this.gitUrl || this.gitPath) fs.writeFile(path.join(this.gitPath, this.localConfig.json), jsonStr);
this.removeLocalPaths();
}.bind(this)).readLocalConfig();
};
// finish clean up local by removing .git/ and any ignored files
Package.prototype.removeLocalPaths = function () {
var removePatterns = ['.git'];
if (this.json.ignore) {
removePatterns.push.apply(removePatterns, this.json.ignore);
}
var removePaths = [];
// 3: done
var pathsRemoved = function (err) {
if (err) return this.emit('error', err);
this.emit('install');
}.bind(this);
// 2: trigger after paths have been globbed
var rimrafPaths = function (err) {
if (err) return this.emit('error', err);
async.forEach(removePaths, function (removePath, next) {
// rimraf all the paths
rimraf(removePath, function (err) {
if (err) return this.emit('error', err);
next();
}.bind(this));
// finished callback
}.bind(this), pathsRemoved);
}.bind(this);
// 1: get paths
var globOpts = { dot: true };
async.forEach(removePatterns, function (removePattern, next) {
// glob path for file path pattern matching
var globPattern = path.join(this.localPath, removePattern);
glob(globPattern, globOpts, function (err, globPaths) {
if (err) return this.emit('error', err);
removePaths = removePaths.concat(globPaths);
next();
}.bind(this));
}.bind(this), rimrafPaths);
};
Package.prototype.generateAssetJSON = function () {

@@ -263,54 +308,94 @@ return {

// Private
Package.prototype.readLocalConfig = function () {
if (this.localConfig) return this.emit('readLocalConfig');
var checkExistence = function () {
fileExists(path.join(this.path, this.localConfig.json), function (exists) {
if (!exists) {
this.localConfig.json = 'component.json';
}
this.emit('readLocalConfig');
}.bind(this));
}.bind(this);
fs.readFile(path.join(this.path, '.bowerrc'), function (err, file) {
// If the local .bowerrc file do not exists then we check if the
// json specific in the config exists (if not, we fallback to component.json)
if (err) {
this.localConfig = { json: config.json };
checkExistence();
} else {
// If the local .bowerrc file exists, we read it and check if a custom json file
// is defined. If not, we check if the global config json file exists (if not, we fallback to component.json)
try {
this.localConfig = JSON.parse(file);
} catch (e) {
return this.emit('error', new Error('Unable to parse local .bowerrc file: ' + e.message));
}
if (!this.localConfig.json) {
this.localConfig.json = config.json;
return checkExistence();
}
this.emit('readLocalConfig');
}
}.bind(this));
};
Package.prototype.loadJSON = function () {
if (!this.path || this.assetUrl) return this.emit('loadJSON');
var jsonFile = path.join(this.path, config.json);
fileExists(jsonFile, function (exists) {
// If the json does not exists, we attempt to at least get the version
if (!exists) {
return this.once('describeTag', function (tag) {
tag = semver.clean(tag);
if (!tag) this.version = this.tag;
else {
this.version = tag;
if (!this.tag) this.tag = this.version;
}
this.once('readLocalConfig', function () {
var jsonFile = path.join(this.path, this.localConfig.json);
fileExists(jsonFile, function (exists) {
// If the json does not exists, we attempt to get the version
if (!exists) {
return this.once('describeTag', function (tag) {
tag = semver.clean(tag);
if (!tag) this.version = this.tag;
else {
this.version = tag;
if (!this.tag) this.tag = this.version;
}
this.emit('loadJSON');
}.bind(this)).describeTag();
}
readJSON(jsonFile, function (err, json) {
if (err) {
err.details = 'There was an error while reading the ' + config.json;
return this.emit('error', err);
this.emit('loadJSON');
}.bind(this)).describeTag();
}
this.json = json;
this.version = this.commit || json.commit || json.version;
this.commit = this.commit || json.commit;
// Only overwrite the name if not already set
// This is because some packages have different names declared in the registry and the json
if (!this.name) this.name = json.name;
readJSON(jsonFile, function (err, json) {
if (err) {
err.details = 'An error was caught when reading the ' + this.localConfig.json + ':' + err.message;
return this.emit('error', err);
}
// Read the endpoint from the json to ensure it is set correctly
this.readEndpoint();
this.json = json;
this.version = this.commit || json.commit || json.version;
this.commit = this.commit || json.commit;
// Only overwrite the name if not already set
// This is because some packages have different names declared in the registry and the json
if (!this.name) this.name = json.name;
// Detect if the tag mismatches the json.version
// This is very often to happen because developers tag their new releases but forget to update the json accordingly
var cleanedTag;
if (this.tag && (cleanedTag = semver.clean(this.tag)) && cleanedTag !== this.version) {
// Only print the warning once
if (!this.unitWork.retrieve('mismatch#' + this.name + '_' + cleanedTag)) {
template('warning-mismatch', { name: this.name, json: config.json, tag: cleanedTag, version: this.version || 'N/A' })
.on('data', this.emit.bind(this, 'data'));
this.unitWork.store('mismatch#' + this.name + '_' + cleanedTag, true);
// Read the endpoint from the json to ensure it is set correctly
this.readEndpoint();
// Detect if the tag mismatches the json.version
// This is very often to happen because developers tag their new releases but forget to update the json accordingly
var cleanedTag;
if (this.tag && (cleanedTag = semver.clean(this.tag)) && cleanedTag !== this.version) {
// Only print the warning once
if (!this.unitWork.retrieve('mismatch#' + this.name + '_' + cleanedTag)) {
template('warning-mismatch', { name: this.name, json: this.localConfig.json, tag: cleanedTag, version: this.version || 'N/A' })
.on('data', this.emit.bind(this, 'data'));
this.unitWork.store('mismatch#' + this.name + '_' + cleanedTag, true);
}
// Assume the tag
this.version = cleanedTag;
}
// Assume the tag
this.version = cleanedTag;
}
this.emit('loadJSON');
}.bind(this), this);
}.bind(this));
this.emit('loadJSON');
}.bind(this), this);
}.bind(this));
}.bind(this)).readLocalConfig();
};

@@ -363,3 +448,2 @@

}.bind(this)).on('error', this.emit.bind(this, 'error'));
}.bind(this));

@@ -548,2 +632,6 @@ };

if (this.tag) {
if (!semver.validRange(this.tag)) {
return this.emit('error', new Error('Tag ' + this.tag + ' is not a valid semver range/version'));
}
versions = versions.filter(function (version) {

@@ -710,3 +798,4 @@ return semver.satisfies(version, this.tag);

gitPath: this.gitPath,
dependencies: this.dependencies
dependencies: this.dependencies,
localConfig: this.localConfig
};

@@ -713,0 +802,0 @@ };

@@ -15,10 +15,33 @@ // ==========================================

if (process.env.HTTP_PROXY) {
request = request.defaults({'proxy': process.env.HTTP_PROXY});
request = request.defaults({proxy: process.env.HTTP_PROXY, timeout: 5000 });
}
// allow for searchpath endpoints to be used for search and lookup
var endpoints = [];
endpoints.push(endpoint);
if (config.searchpath) {
for (var i = 0; i < config.searchpath.length; i += 1) {
endpoints.push(config.searchpath[i] + '/packages');
}
}
exports.lookup = function (name, callback) {
request.get(endpoint + '/' + encodeURIComponent(name), function (err, response, body) {
if (err || response.statusCode !== 200) return callback(err || new Error(name + ' not found'));
callback(err, body && JSON.parse(body).url);
});
// walk all endpoints to find the first matching component
var f = function (i) {
var endpoint = endpoints[i];
request.get(endpoint + '/' + encodeURIComponent(name), function (err, response, body) {
if (err || (response.statusCode !== 200 && response.statusCode !== 404)) {
return callback(err || new Error(name + ' failed to look up for endpoint: ' + endpoint));
}
if (response && response.statusCode !== 404) {
callback(err, body && JSON.parse(body).url);
} else {
if (i + 1 < endpoints.length) f(i + 1);
else return callback(new Error(name + ' not found'));
}
});
};
f(0);
};

@@ -49,5 +72,28 @@

exports.search = function (name, callback) {
request.get(endpoint + '/search/' + encodeURIComponent(name), function (err, response, body) {
callback(err, body && JSON.parse(body));
});
// walk all endpoints to produced federated search results
var f = function (i, map, results) {
var endpoint = endpoints[i];
request.get(endpoint + '/search/' + encodeURIComponent(name), function (err, response, body) {
if (err || (response.statusCode !== 200 && response.statusCode !== 404)) {
return callback(err || new Error(name + ' failed to look up for endpoint: ' + endpoint));
}
if (response && response.statusCode !== 404) {
var array = body && JSON.parse(body);
for (var x = 0; x < array.length; x += 1) {
var pkgName = array[x].name;
if (!map[pkgName]) {
map[pkgName] = pkgName;
results.push({ name: pkgName, url: array[x].url, endpoint: array[x].endpoint });
}
}
}
if (i + 1 < endpoints.length) f(i + 1, map, results);
else return callback(null, results);
});
};
f(0, {}, []);
};

@@ -71,5 +117,28 @@

exports.all = function (callback) {
request.get(endpoint, function (err, response, body) {
callback(err, body && JSON.parse(body));
});
// walk all endpoints to produced federated search results
var f = function (i, map, results) {
var endpoint = endpoints[i];
request.get(endpoint, function (err, response, body) {
if (err || (response.statusCode !== 200 && response.statusCode !== 404)) {
return callback(err || new Error('Failed to look up endpoint: ' + endpoint));
}
if (response && response.statusCode !== 404) {
var array = body && JSON.parse(body);
for (var x = 0; x < array.length; x += 1) {
var pkgName = array[x].name;
if (!map[pkgName]) {
map[pkgName] = pkgName;
results.push({ name: pkgName, url: array[x].url, endpoint: array[x].endpoint });
}
}
}
if (i + 1 < endpoints.length) f(i + 1, map, results);
else return callback(null, results);
});
};
f(0, {}, []);
};

@@ -24,5 +24,6 @@ // ==========================================

grey : function (s) { return s.grey; },
red : function (s) { return s.red; }
red : function (s) { return s.red; },
white : function (s) { return s.white; }
}, context);
return this.ri([context], partials || {}, indent);
};

@@ -9,4 +9,4 @@ // ==========================================

var semver = require('semver');
var sort = require('stable');
var semver = require('semver');
var sort = require('stable');

@@ -43,34 +43,62 @@ var versionRequirements = function (dependencyMap) {

module.exports = function (dependencyMap) {
module.exports = function (dependencyMap, forceLatest) {
// generate version requirements
// compare dependency map with version requirements
// raise exceptions when requirements are not satisified
// remove duplicates
// check for conflicts
// select best version
// return a pruned dependencyMap
// return an object with the resolved deps, conflict deps and forcebly resolved ones
var result = {};
var resolved = {};
var conflicted = null;
var forceblyResolved = null;
var versionMap = versionRequirements(dependencyMap);
var sortFunc = function (a, b) {
if (semver.gt(a.version, b.version)) return -1;
if (semver.lt(a.version, b.version)) return 1;
// If the comparison determines that both packages are equal, do not give priority to local ones
if (a.path === a.localPath && b.path !== b.localPath) return 1;
return 0;
};
// Note that bellow we use a stable sort algorithm
// This is because if two packages are equal, the initial order should be respected
for (var name in dependencyMap) {
var matches = dependencyMap[name].filter(validVersions.bind(this, versionMap[name]));
// Sort the packages using a stable sort algorithm
// This is because if two packages are equal, the initial order should be respected
dependencyMap[name] = sort(matches, function (a, b) {
if (semver.gt(a.version, b.version)) return -1;
if (semver.lt(a.version, b.version)) return 1;
if (!matches.length) {
// No resolvable dependency
// We resolve to the latest package if the forceLatest is ture
// Otherwise, check if any of those are root packages
// If so, we assume that as the resolver (with a warning)
// Otherwise resolve to the greater one only if forceLatest is true,
if (forceLatest) {
forceblyResolved = forceblyResolved || {};
forceblyResolved[name] = sort(dependencyMap[name], sortFunc);
continue;
}
// If the comparison determines that both packages are equal, do not give priority to local ones
if (a.path === a.localPath && b.path !== b.localPath) return 1;
return 0;
});
if (!dependencyMap[name].length) {
throw new Error('No resolvable dependency for: ' + name);
matches = dependencyMap[name].filter(function (pkg) { return !!pkg.root; });
if (matches.length) {
forceblyResolved = forceblyResolved || {};
forceblyResolved[name] = sort(dependencyMap[name], function (a, b) {
if (a.root) return 1;
if (a.root) return -1;
return sortFunc(a, b);
});
} else {
conflicted = conflicted || {};
conflicted[name] = dependencyMap[name];
}
} else {
resolved[name] = [ sort(matches, sortFunc)[0] ];
}
result[name] = [ dependencyMap[name][0] ];
}
return result;
return {
resolved: resolved,
conflicted: conflicted,
forceblyResolved: forceblyResolved
};
};

@@ -23,3 +23,4 @@ // ==========================================

};
readJSON.cache.reset();
readJSON(path, cb);
};

@@ -12,38 +12,26 @@ // ==========================================

var semver = require('semver');
var _ = require('lodash');
var config = require('../core/config');
function save(eventType, manager, paths) {
// Tipically wait for the resolve event and also the load json event
manager.on(eventType, manager.on('loadJSON', function () {
// Find the original required packages in the command
var pkgs = paths.map(function (curr) {
curr = curr.split('#')[0];
function save(manager) {
// Wait for the resolve event and then for the load json event
manager.on('resolve', function () {
manager.on('loadJSON', function () {
manager.json.dependencies = manager.json.dependencies || {};
return _.find(Object.keys(this.dependencies), function (key) {
var dep = this.dependencies[key][0];
return dep.name === curr
|| (dep.gitUrl && dep.gitUrl === curr)
|| (dep.assetUrl && dep.assetUrl === curr)
|| (dep.originalPath && dep.originalPath === curr);
}.bind(this));
// Only include the root packages
for (var name in manager.dependencies) {
var curr = manager.dependencies[name][0];
if (curr.root) {
addDependency(manager.json, curr);
}
}
}.bind(this));
pkgs = _.compact(pkgs).map(function (name) {
return this.dependencies[name][0];
}.bind(this));
pkgs.forEach(addDependency.bind(this));
// Finally save the modified json
fs.writeFileSync(path.join(this.cwd, config.json), JSON.stringify(this.json, null, 2));
}).loadJSON.bind(manager));
// Finally save the modified json
fs.writeFileSync(path.join(manager.cwd, config.json), JSON.stringify(manager.json, null, 2));
}).loadJSON();
});
}
function addDependency(pkg) {
if (!this.json.dependencies) this.json.dependencies = {};
function addDependency(json, pkg) {
var path;

@@ -62,5 +50,5 @@ var tag;

return this.json.dependencies[pkg.name] = path ? path + (tag ? '#' + tag : '') : tag || 'latest';
return json.dependencies[pkg.name] = path ? path + (tag ? '#' + tag : '') : tag || 'latest';
}
module.exports = save.bind(this, 'resolve');
module.exports = save;
{
"name": "bower",
"description": "The browser package manager.",
"version": "0.6.8",
"version": "0.7.0",
"author": "Twitter",

@@ -6,0 +6,0 @@ "licenses": [

@@ -33,3 +33,3 @@ BOWER [![Build Status](https://secure.travis-ci.org/twitter/bower.png)](http://travis-ci.org/twitter/bower)

As you can see, packages can be installed by name, Git endpoint, GitHub shorthand, URL or local path.
If you install and URL that is a zip or tar file, bower will automatically extract the contents of it.
If you install from a URL that points to a zip or tar file, bower will automatically extract its contents.
When tags are available in the endpoint, you can specify a [semver](http://semver.org/) tag to fetch concrete versions:

@@ -77,3 +77,3 @@

Bower can be configured by creating a .bowerrc file in your home folder (usually ~/bowerrc) with one or all of the following configuration parameters. You can also configure Bower on a per-project basis by creating a .bowerrc file in the project directory, Bower will merge this configuration with the configuration found in your home directory. This allows you to version your project specific Bower configuration with the rest of your code base.
Bower can be configured by creating a .bowerrc file in your home folder (usually ~/.bowerrc) with one or all of the following configuration parameters. You can also configure Bower on a per-project basis by creating a .bowerrc file in the project directory, Bower will merge this configuration with the configuration found in your home directory. This allows you to version your project specific Bower configuration with the rest of your code base.

@@ -90,3 +90,17 @@ ```json

The __searchpath__ array provides additional URLs of read-only Bower registries that should be consulted to look up components. This is most typically used if your business wishes to
house some components internally while still taking advantage of public Bower registries. For example, you might configure the following:
```json
{
"directory" : "components",
"json" : "component.json",
"endpoint" : "http://bower.mycompany.com",
"searchpath" : ["https://bower.herokuapp.com"]
}
```
Bower will first look to **http://bower.mycompany.com** while trying to find your components. If not found, the main registry at **https://bower.herokuapp.com** will be consulted to see if a copy of the resource can be retrieved.
### Defining a package

@@ -109,3 +123,3 @@

For now, `name`, `version`, `main`, and `dependencies` are the only properties that are used by Bower. If you have several files you're distributing as part of your package, pass an array to `main` like this:
For now, `name`, `version`, `main`, `dependencies`, and `ignore` are the only properties that are used by Bower. If you have several files you're distributing as part of your package, pass an array to `main` like this:

@@ -126,2 +140,26 @@ ```json

You can also point to packages by adding their URL or file path in the dependency's property.
```json
{
"dependencies": {
"eventEmitter": "Wolfy87/EventEmitter", // GitHub short URL
"eventEmitter": "Wolfy87/EventEmitter#>=3", // with version
"eventEmitter": "git://github.com/Wolfy87/EventEmitter",
"eventEmitter": "git@github.com:Wolfy87/EventEmitter.git"
}
}
```
Chances are you have a bunch of extra stuff in the repo that are not needed in production. List these non-necessary file paths in `ignore`.
```json
{
"ignore": [
"tests/",
"**/*.txt"
]
}
```
### Installing dependencies

@@ -210,5 +248,25 @@

For the install command, there is an additional `package` event that is emitted for each installed/uninstalled package.
### Completion
**experimental**
Based on the completion feature and fantastic work done in
[npm](https://npmjs.org/doc/completion.html), Bower now has an experimental
`completion` command that works similarly.
This command will output a Bash / ZSH script to put into your `~/.bashrc`, `~/.bash_profile` or `~/.zshrc` file.
```
bower completion >> ~/.bash_profile
```
*This doesn't work for Windows user, even with Cygwin.*
### Windows users
A lot of people are experience problems using bower on windows because [msysgit](http://code.google.com/p/msysgit/) must be installed correctly.
A lot of people are experiencing problems using bower on windows because [msysgit](http://code.google.com/p/msysgit/) must be installed correctly.
Be sure to check the option shown above, otherwise it will simply not work:

@@ -221,13 +279,12 @@

**What distinguishes Bower from Jam, Volo, Component, or Ender? What does it do better?**
**What distinguishes Bower from Jam, Volo or Ender? What does it do better?**
Bower is a lower level component than Jam, Volo, Component, or Ender. These managers could consume Bower as a dependency.
Bower is a lower level component than Jam, Volo, or Ender. These managers could consume Bower as a dependency.
Bower's aim is simply to install Git paths, resolve dependencies from a `component.json`, check versions, and then provide an API which reports on these things. Nothing more. This is a major diversion from past attempts at browser package management.
Bower is working under the assumption that there is a single, common problem in frontend application development: dependency resolution. Past attempts (Jam, Volo, Ender, Component) try to tackle this problem in such a way that they actually end up alienating and further segregating the JavaScript community around transports (Sprockets, CommonJS, RequireJS, regular script tags).
Bower is working under the assumption that there is a single, common problem in frontend application development: dependency resolution. Past attempts (Jam, Volo, Ender) try to tackle this problem in such a way that they actually end up alienating and further segregating the JavaScript community around transports (Sprockets, CommonJS, RequireJS, regular script tags).
Bower offers a generic, unopinionated solution to the problem of package management, while exposing an API that can be consumed by a more opinionated build stack.
**Volo is an arguably more established project and works with the GitHub search API. Will it take long for Bower to contain a decent number of packages?**

@@ -282,5 +339,8 @@

+ [@tomdale](http://github.com/tomdale)
+ [@uzquiano](http://github.com/uzquiano)
+ [@visionmedia](http://github.com/visionmedia)
+ [@wagenet](http://github.com/wagenet)
+ [@wycats](http://github.com/wycats)
+ [@sindresorhus](http://github.com/sindresorhus)
+ [@hemanth](http://github.com/hemanth)

@@ -287,0 +347,0 @@ ## License

@@ -5,5 +5,5 @@ {

"dependencies": {
"jquery": "1.6.0",
"package-deps-on-jquery-old": "test/assets/package-deps-on-jquery-old",
"jquery-pjax": "1.0.0"
}
}

@@ -55,3 +55,3 @@ /*jshint plusplus:false*/

cleaner.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -61,3 +61,3 @@

glob(config.cache + '/*', function (err, dirs) {
if (err) throw new Error(err);
if (err) throw err;
assert(dirs.length === 0);

@@ -77,3 +77,3 @@ next();

cleaner.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -83,3 +83,3 @@

glob(config.cache + '/*', function (err, dirs) {
if (err) throw new Error(err);
if (err) throw err;
dirs = dirs.map(function (dir) {

@@ -96,10 +96,12 @@ return path.basename(dir);

it('Should throw error on unknown package', function (next) {
var cleaner = cacheClean(['not-cached-package']);
var cleaner = cacheClean(['not-cached-package']),
cleanedPkg = false;
cleaner.on('error', function (err) {
if (/not\-cached\-package/.test(err)) next();
if (/not\-cached\-package/.test(err)) cleanedPkg = true;
});
cleaner.on('end', function () {
throw new Error('Should have thrown an error.');
if (!cleanedPkg) throw new Error('Should have thrown an error.');
next();
});

@@ -115,3 +117,3 @@ });

cleaner.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -121,3 +123,3 @@

glob(config.cache + '/*', function (err, dirs) {
if (err) throw new Error(err);
if (err) throw err;
assert(dirs.length === 0);

@@ -124,0 +126,0 @@ next();

@@ -12,4 +12,8 @@ /*jshint plusplus:false*/

describe('manager', function () {
var savedConfigJson = config.json;
function clean(done) {
// Restore possibly dirtied config.json
config.json = savedConfigJson;
var del = 0;

@@ -43,3 +47,3 @@

manager.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -61,3 +65,3 @@

manager.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -68,2 +72,22 @@

it('Should resolve nested JSON dependencies even when using another name for component.json project-wise', function (next) {
// Using another name for .json file leads to unfetchable deps
// https://github.com/twitter/bower/issues/205
config.json = 'foocomponent.json';
var manager = new Manager([]);
manager.cwd = __dirname + '/assets/project-nonstandard-json';
manager.on('resolve', function () {
assert.deepEqual(manager.dependencies['jquery-pjax'][0].version, '1.0.0');
assert.notEqual(manager.dependencies.jquery[0].version, null);
next();
});
manager.on('error', function (err) {
throw err;
});
manager.resolve();
});
it('Should override packages at the project level', function (next) {

@@ -80,3 +104,3 @@ var manager = new Manager([]);

manager.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -87,2 +111,17 @@

it('Should not error out in resolved conflicts', function (next) {
var manager = new Manager([]);
manager.cwd = __dirname + '/assets/project-nested';
manager.on('error', function (err) {
throw err;
});
manager.on('resolve', function () {
assert.deepEqual(manager.dependencies.jquery[0].version, '1.7.2');
next();
});
manager.resolve();
});
it('Should detect unresolvable packages in nested JSON dependencies', function (next) {

@@ -104,2 +143,17 @@ var manager = new Manager([]);

it('Should resolve to latest version on unresolvable packages in nested JSON dependencies', function (next) {
var manager = new Manager([], { forceLatest: true });
manager.cwd = __dirname + '/assets/project-nested-conflict';
manager.on('error', function (err) {
throw err;
});
manager.on('resolve', function () {
assert.ok(semver.gte(manager.dependencies.jquery[0].version, '1.7.0'));
next();
});
manager.resolve();
});
it('Should fetch remote sources if the force option is passed', function (next) {

@@ -113,3 +167,3 @@ this.timeout(40000); // Increase the timeout because this one takes longer

manager.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -116,0 +170,0 @@

@@ -5,5 +5,7 @@ /*jshint plusplus:false*/

var fs = require('fs');
var path = require('path');
var nock = require('nock');
var _ = require('lodash');
var rimraf = require('rimraf');
var glob = require('glob');
var async = require('async');

@@ -14,2 +16,3 @@ var config = require('../lib/core/config');

describe('package', function () {
var savedConfigJson = config.json;

@@ -19,2 +22,5 @@ function clean(done) {

// Restore possibly dirtied config.json
config.json = savedConfigJson;
rimraf(config.directory, function () {

@@ -81,3 +87,3 @@ // Ignore the error if the local directory was not actually deleted

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -114,3 +120,3 @@

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -145,3 +151,3 @@

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -174,3 +180,3 @@

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -181,3 +187,55 @@

it('Should load correct json', function (next) {
it('Should load configured json file package-wise', function (next) {
var pkg = new Package('mypackage', __dirname + '/assets/package-nonstandard-json');
pkg.on('loadJSON', function () {
assert(pkg.json);
assert.equal(pkg.json.name, 'mypackage');
assert.equal(pkg.json.version, '1.0.0');
next();
});
pkg.on('error', function (err) {
throw err;
});
pkg.loadJSON();
});
it('Should load configured json file project-wise if not defined package-wise', function (next) {
config.json = 'foocomponent.json';
var pkg = new Package('mypackage', __dirname + '/assets/package-nonstandard-json-copy');
pkg.on('loadJSON', function () {
assert(pkg.json);
assert.equal(pkg.json.name, 'mypackage');
assert.equal(pkg.json.version, '1.0.0');
// Test the same but with a package that has a .bowerrc but does not specify a different json
pkg = new Package('mypackage', __dirname + '/assets/package-empty-rc');
pkg.on('loadJSON', function () {
assert(pkg.json);
assert.equal(pkg.json.name, 'mypackage-foo');
assert.equal(pkg.json.version, '1.0.0');
next();
});
pkg.on('error', function (err) {
throw err;
});
pkg.loadJSON();
});
pkg.on('error', function (err) {
throw err;
});
pkg.loadJSON();
});
it('Should fallback to component.json if the json project-wise does not exist', function (next) {
config.json = 'foocomponent.json';
var pkg = new Package('jquery', __dirname + '/assets/package-jquery');

@@ -188,2 +246,3 @@

assert.equal(pkg.json.name, 'jquery');
assert.equal(pkg.json.version, '1.8.1');
next();

@@ -193,3 +252,3 @@ });

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -200,2 +259,36 @@

it('Should fallback to component.json if not defined project wise and package-wise', function (next) {
var pkg = new Package('jquery', __dirname + '/assets/package-jquery');
pkg.on('loadJSON', function () {
assert(pkg.json);
assert.equal(pkg.json.name, 'jquery');
assert.equal(pkg.json.version, '1.8.1');
// Test the same but with a package that has a .bowerrc but does not specify a different json
pkg = new Package('jquery', __dirname + '/assets/package-empty-rc');
pkg.on('loadJSON', function () {
assert(pkg.json);
assert.equal(pkg.json.name, 'mypackage');
assert.equal(pkg.json.version, '1.0.0');
// Test the same but with a package that has a .bowerrc but does not specify a different json
next();
});
pkg.on('error', function (err) {
throw err;
});
pkg.loadJSON();
});
pkg.on('error', function (err) {
throw err;
});
pkg.loadJSON();
});
it('Should give an error on an invalid components.json', function (next) {

@@ -225,3 +318,3 @@ var pkg = new Package('jquery', __dirname + '/assets/package-invalid-json');

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -251,3 +344,3 @@

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -281,3 +374,3 @@

fs.renameSync(dir + '/.git', dir + '/git_repo');
throw new Error(err);
throw err;
});

@@ -305,3 +398,3 @@

fs.renameSync(dir + '/.git', dir + '/git_repo');
throw new Error(err);
throw err;
});

@@ -325,3 +418,3 @@

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -331,3 +424,3 @@

async.map([pkg.localPath, cachePath], fs.stat, function (err, results) {
if (err) throw new Error(err);
if (err) throw err;
var mode0777 = parseInt('0777', 8);

@@ -352,3 +445,3 @@ var expectedMode = mode0777 & (~process.umask());

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -358,3 +451,3 @@

fs.stat(pkg.localPath, function (err, stat) {
if (err) throw new Error(err);
if (err) throw err;
var mode0777 = parseInt('0777', 8);

@@ -368,3 +461,3 @@ var expectedMode = mode0777 & (~process.umask());

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -383,3 +476,3 @@

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -389,3 +482,3 @@

fs.readdir(pkg.localPath, function (err, files) {
if (err) throw new Error(err);
if (err) throw err;

@@ -408,3 +501,3 @@ assert(files.indexOf('index.js') !== -1);

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -414,3 +507,3 @@

fs.readdir(pkg.localPath, function (err, files) {
if (err) throw new Error(err);
if (err) throw err;

@@ -436,3 +529,3 @@ assert(files.indexOf('index.js') === -1);

pkg.on('error', function (err) {
throw new Error(err);
throw err;
});

@@ -442,3 +535,3 @@

fs.readdir(pkg.localPath, function (err, files) {
if (err) throw new Error(err);
if (err) throw err;

@@ -456,2 +549,64 @@ assert(files.indexOf('index.js') === -1);

});
it('Should remove ignored filepaths', function (next) {
var pkg = new Package('turtles', __dirname + '/assets/package-ignorables');
pkg.on('resolve', function () {
pkg.install();
});
pkg.on('error', function (err) {
throw new Error(err);
});
var pkgInstallPath = path.join(__dirname, '/../components/turtles/');
pkg.on('install', function () {
// these files should have been deleted
assert(!fs.existsSync(pkgInstallPath + 'don.txt'));
assert(!fs.existsSync(pkgInstallPath + 'leo.txt'));
assert(!fs.existsSync(pkgInstallPath + '/test/'));
// ignored dot files
assert(!fs.existsSync(pkgInstallPath + '/config/.jshintrc'));
assert(!fs.existsSync(pkgInstallPath + '.casey'));
assert(!fs.existsSync(pkgInstallPath + '.hide/turtle-location.mdown'));
// this file should still be there
assert(fs.existsSync(pkgInstallPath + 'index.js'));
// all ignore file pattern should be removed
async.forEach(pkg.json.ignore, function (ignorePattern, asyncNext) {
var pattern = path.join(__dirname, '/../components/turtles/' + ignorePattern);
glob(pattern, function (err, globPath) {
assert(globPath.length === 0);
asyncNext();
});
}, next);
});
pkg.resolve();
});
it('Should remove .git directory', function (next) {
var dir = __dirname + '/assets/package-repo';
fs.renameSync(dir + '/git_repo', dir + '/.git');
var pkg = new Package('spark-md5', dir);
pkg.on('resolve', function () {
pkg.install();
});
pkg.on('error', function (err) {
fs.renameSync(dir + '/.git', dir + '/git_repo');
throw new Error(err);
});
var pkgInstallPath = path.join(__dirname, '/../components/spark-md5/');
pkg.on('install', function () {
fs.renameSync(dir + '/.git', dir + '/git_repo');
assert(!fs.existsSync(pkgInstallPath + '/.git/'));
next();
});
pkg.resolve();
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc