Compare commits

..

1 Commits

Author SHA1 Message Date
Vlad Filippov
47e5834662 Lock lru-cache package 2015-11-24 12:07:46 -05:00
88 changed files with 914 additions and 2456 deletions

27
.jscsrc
View File

@@ -1,27 +0,0 @@
{
'validateIndentation': 4,
'requireCamelCaseOrUpperCaseIdentifiers': true,
'requireParenthesesAroundIIFE': true,
'requireCapitalizedConstructors': true,
'disallowEmptyBlocks': false,
'validateQuoteMarks': "'",
'requireOperatorBeforeLineBreak': false,
'requireCommaBeforeLineBreak': true,
'disallowMultipleLineStrings': true,
'requireDotNotation': true,
'disallowTabs': true,
'disallowNewlineBeforeBlockStatements': true,
'disallowTrailingWhitespace': true,
'disallowMixedSpacesAndTabs': true,
'requireSpaceBeforeBinaryOperators': true,
'requireSpaceBeforeBlockStatements': true,
'requireSpaceBeforeObjectValues': true,
'requireSpaceBetweenArguments': true,
'requireSpacesInFunctionDeclaration': {
'beforeOpeningCurlyBrace': true
},
'requireSpacesInNamedFunctionExpression': {
'beforeOpeningCurlyBrace': true,
'beforeOpeningRoundBrace': true
}
}

View File

@@ -9,6 +9,7 @@
"beforeEach"
],
"indent": 4,
"node": true,
"devel": true,
@@ -16,19 +17,26 @@
"curly": false,
"eqeqeq": true,
"forin": false,
"immed": true,
"latedef": false,
"newcap": true,
"noarg": true,
"noempty": false,
"nonew": true,
"plusplus": false,
"regexp": false,
"undef": true,
"unused": "vars",
"quotmark": "single",
"strict": false,
"trailing": true,
"camelcase": true,
"asi": false,
"boss": true,
"debug": false,
"eqnull": true,
"es5": false,
"esnext": false,
"evil": false,
"expr": false,
@@ -36,12 +44,16 @@
"globalstrict": false,
"iterator": false,
"lastsemic": false,
"laxbreak": true,
"laxcomma": false,
"loopfunc": true,
"multistr": false,
"onecase": true,
"regexdash": false,
"scripturl": false,
"smarttabs": false,
"shadow": false,
"sub": false,
"supernew": true,
"validthis": false,

View File

@@ -1,16 +1,10 @@
sudo: false
env:
- NODE_VERSION=0.10
- NODE_VERSION=0.11
- NODE_VERSION=0.12
- NODE_VERSION=4.0
- NODE_VERSION=5.0
install:
- test $TRAVIS_OS_NAME = "osx" && brew install nvm && source $(brew --prefix nvm)/nvm.sh || test $TRAVIS_OS_NAME = "linux"
- nvm install $NODE_VERSION
- npm install -g npm@^2.0.0
- node --version
- npm --version
- git --version

View File

@@ -1,97 +1,9 @@
# Changelog
## 1.6.8 - 2015-11-27
- Use fs-write-stream-atomic for downloads
- Improved downloader that properly cleans after itself
- Fix shallow host detection ([#2040](https://github.com/bower/bower/pull/2040))
- Upgrade to ([bower-config#1.2.3](https://github.com/bower/config/releases/tag/1.2.3))
- Properly restore env variables if they are undefined at the beginning
- Properly handle `default` setting for config.ca
- Display proper error if .bowerrc is a directory instead of file
## 1.6.7 - 2015-11-26
- Bundless all the dependencies again
## 1.6.6 - 2015-11-25
- Fixes regression with the published npm version
## 1.6.5 - 2015-10-24
- Updates to tests and documentation
- Fixes passing options when requesting downloads
## 1.6.4 - 2015-10-24
- Fix ignoring dependencies on multiple install run ([#1970](https://github.com/bower/bower/pull/1970))
- Use --non-interactive when running svn client ([#1969](https://github.com/bower/bower/pull/1969))
- Fix downloading of URLs ending with slash ([#1956](https://github.com/bower/bower/pull/1956))
- Add user-agent field for downloads by Bower ([#1960](https://github.com/bower/bower/pull/1960))
## 1.6.3 - 2015-10-16
Fixes regression issues introduced with 1.6.2, specifically:
- Allow for bower_components to be a symlink
- Allow setting custom registry in .bowerrc
## 1.6.2 - 2015-10-15
Fix dependency issues of 1.6.1. First published release of 1.6.x.
## 1.6.1 - 2015-10-15
Fix dependency issues of 1.6.0. Reverted release.
## 1.6.0 - 2015-10-15
- Shrinkwrap all dependencies and add them to bundledDependencies ([#1948](https://github.com/bower/bower/pull/1948))
- Allow for ignoring of child dependencies ([#1394](https://github.com/bower/bower/pull/1394))
- Allow passing `--config.resolvers` through CLI ([#1922](https://github.com/bower/bower/pull/1922))
- Use defaults values from package.json if it exists (bower init) ([#1731](https://github.com/bower/bower/issues/1731))
- Properly use cerificates set in .bowerrc ([#1869](https://github.com/bower/bower/pull/1869))
- Include package name when version conflict occurs ([#1917](https://github.com/bower/bower/pull/1917))
- Add timeout for permission check ([yeoman/insight#35](https://github.com/yeoman/insight/pull/35))
- Close file-handles when possible. Prevents all sorts of permission issues on Windows ([0bb1536](https://github.com/bower/bower/commit/0bb1536c9972e13f3be06bea9a8619632966c664))
- Prevent ENOENT error on Windows when in VM environment ([isaacs/chmodr#8](https://github.com/isaacs/chmodr/pull/8))
Reverted release.
## 1.5.4 - 2015-11-24
- [fix] Lock lru-cache dependency to 2.7.0
## 1.5.3 - 2015-09-24
- Revert auto sorting of bower dependencies, fixes ([#1897](https://github.com/bower/bower/issues/1897))
- Fix --save-exact feature for github endpoints, fixes ([#1925](https://github.com/bower/bower/issues/1925))
- Fix `bower init` to support private flag again ([#1819](https://github.com/bower/bower/pull/1819))
- Bump insight dependency to support prompt timeout ([#1102](https://github.com/bower/bower/issues/1102))
## 1.5.2 - 2015-08-25
- Revert update semver version from 2.x to 5.x, fixes ([#1896](https://github.com/bower/bower/issues/1896))
- Make bower commands work from subdirectories, fixes ([#1893](https://github.com/bower/bower/issues/1893))
- Put auto shallow cloning for git behind a flag, fixes ([#1764](https://github.com/bower/bower/issues/1764))
## 1.5.1 - 2015-08-24
- If cwd provided explicitly, force using it, fixes #1866
## 1.5.0 - 2015-08-24
- Pluggable Resolvers! http://bower.io/docs/pluggable-resolvers/
- Update semver version from 2.x to 5.x ([#1852](https://github.com/bower/bower/issues/1852))
- Auto-sort dependencies alphabetically ([#1381](https://github.com/bower/bower/issues/1381))
- Make bower commands work from subdirectories ([#1866](https://github.com/bower/bower/issues/1866))
- No longer prefer installing bower as global module ([#1865](https://github.com/bower/bower/issues/1865))
## 1.4.2 - 2015-11-24
- [fix] Lock lru-cache dependency to 2.7.0
## 1.4.1 - 2015-04-01
- [fix] Reading .bowerrc upwards directory tree ([#1763](https://github.com/bower/bower/issues/1763))

View File

@@ -1,23 +1,35 @@
# Contributing to Bower
Bower is a large community project with many different developers contributing at all levels to the project. We're **actively** looking for more contributors right now. If you're interested in becoming Bower maintainer or supporting in in any way, please full the following form: http://goo.gl/forms/P1ndzCNoiG. There is more information about [contributing](https://github.com/bower/bower/wiki/Contributor-Guidelines) in the Wiki.
Bower is a large community project with many different developers contributing at all levels to the project. We're **actively** looking for more contributors right now. (Jan 2014)
## Casual Involvement
* Improve the bower.io site ([tickets](https://github.com/bower/bower.github.io/issues))
* Move forward [bower.io redesign](https://github.com/bower/bower.github.io/issues/7)
* Attend team meetings
* Comment on issues and drive to resolution
## High-impact Involvement
* Maintaining the bower client.
* [Authoring client tests](https://github.com/bower/bower/issues/801)
* Read [Architecture doc](https://github.com/bower/bower/wiki/Rewrite-architecture)
* Triage, close, fix and resolve [issues](https://github.com/bower/bower/issues)
* Developing the [new registry server](https://github.com/bower/registry/tree/node_rewrite)
* Hooking in to Elastic Search rather than the in-memory search
* Getting bower/registry-client to talk to the new server without breaking backwards compatibility
* DevOps for the server
## Team Meetings
We communicate through a channel on slack: https://gitter.im/bower
We meet on Monday at 1:00pm PST, 9:00pm UTC in #bower on Freenode. [The meeting notes](http://goo.gl/NJZ1o2).
<hr>
Following these guidelines helps to communicate that you respect the time of
the developers managing and developing this open source project. In return,
they should reciprocate that respect in addressing your issue, assessing
changes, and helping you finalize your pull requests.
If you'd like to attend the meetings, please fill the [support form](http://goo.gl/forms/P1ndzCNoiG), and you'll get an invite.
## Using the issue tracker
@@ -26,8 +38,7 @@ The issue tracker is the preferred channel for [bug reports](#bugs),
requests](#pull-requests), but please respect the following restrictions:
* Please **do not** use the issue tracker for personal support requests. Use
[Stack Overflow](http://stackoverflow.com/questions/tagged/bower)
[Gitter Channel](https://gitter.im/bower/bower)
[Stack Overflow](http://stackoverflow.com/questions/tagged/bower), our
[Mailing List](http://groups.google.com/group/twitter-bower)
(twitter-bower@googlegroups.com), or
[#bower](http://webchat.freenode.net/?channels=bower) on Freenode.
@@ -35,6 +46,7 @@ requests](#pull-requests), but please respect the following restrictions:
* Please **do not** derail or troll issues. Keep the discussion on topic and
respect the opinions of others.
<a name="bugs"></a>
## Bug reports

View File

@@ -17,21 +17,6 @@ module.exports = function (grunt) {
'!test/tmp/**/*'
]
},
jscs: {
options: {
config: '.jscsrc',
fix: true
},
files: [
'Gruntfile.js',
'bin/*',
'lib/**/*.js',
'test/**/*.js',
'!test/assets/**/*',
'!test/reports/**/*',
'!test/tmp/**/*'
]
},
simplemocha: {
options: {
reporter: 'spec',
@@ -68,7 +53,7 @@ module.exports = function (grunt) {
});
grunt.registerTask('assets', ['exec:assets-force']);
grunt.registerTask('test', ['jshint', 'jscs', 'exec:assets', 'simplemocha:full']);
grunt.registerTask('test', ['jshint', 'exec:assets', 'simplemocha:full']);
grunt.registerTask('cover', 'exec:cover');
grunt.registerTask('travis', ['jshint', 'exec:assets', 'exec:cover', 'exec:coveralls']);
grunt.registerTask('default', 'test');

View File

@@ -1,17 +1,10 @@
# Bower - A package manager for the web
# Bower
> Bower needs resources for its maintenance. Please fill [<strong>Support Declaration</strong>](http://goo.gl/forms/P1ndzCNoiG) if you think you can help.
[![Build Status](https://travis-ci.org/bower/bower.svg?branch=master)](https://travis-ci.org/bower/bower)
[![Windows Build](https://ci.appveyor.com/api/projects/status/jr6vfra8w84plh2g/branch/master?svg=true)](https://ci.appveyor.com/project/sheerun/bower/history)
[![Coverage Status](https://img.shields.io/coveralls/bower/bower.svg)](https://coveralls.io/r/bower/bower?branch=master)
[![Join the chat at https://gitter.im/bower/bower](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bower/bower?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Issue Stats](http://issuestats.com/github/bower/bower/badge/pr?style=flat)](http://issuestats.com/github/bower/bower)
[![Issue Stats](http://issuestats.com/github/bower/bower/badge/issue?style=flat)](http://issuestats.com/github/bower/bower)
[![Build Status](https://travis-ci.org/bower/bower.svg?branch=master)](https://travis-ci.org/bower/bower) [![Windows Build](https://ci.appveyor.com/api/projects/status/jr6vfra8w84plh2g/branch/master?svg=true)](https://ci.appveyor.com/project/sheerun/bower/history) [![Coverage Status](https://img.shields.io/coveralls/bower/bower.svg)](https://coveralls.io/r/bower/bower?branch=master)
<img align="right" height="300" src="http://bower.io/img/bower-logo.png">
---
> A package manager for the web
Bower offers a generic, unopinionated solution to the problem of **front-end package management**, while exposing the package dependency model via an API that can be consumed by a more opinionated build stack. There are no system wide dependencies, no dependencies are shared between different apps, and the dependency tree is flat.
@@ -66,37 +59,43 @@ $ bower uninstall <package-name>
On `prezto` or `oh-my-zsh`, do not forget to `alias bower='noglob bower'` or `bower install jquery\#1.9.1`
### Never run Bower with sudo
### Running commands with sudo
Bower is a user command, there is no need to execute it with superuser permissions.
However, if you still want to run commands with sudo, use `--allow-root` option.
### Windows users
To use Bower on Windows, you must install
[Git for Windows](http://git-for-windows.github.io/) correctly. Be sure to check the
options shown below:
[msysgit](http://msysgit.github.io/) correctly. Be sure to check the
option shown below:
<img src="https://cloud.githubusercontent.com/assets/10702007/10532690/d2e8991a-7386-11e5-9a57-613c7f92e84e.png" width="534" height="418" alt="Git for Windows" />
<img src="https://cloud.githubusercontent.com/assets/10702007/10532694/dbe8857a-7386-11e5-9bd0-367e97644403.png" width="534" height="418" alt="Git for Windows" />
![msysgit](http://f.cl.ly/items/2V2O3i1p3R2F1r2v0a12/mysgit.png)
Note that if you use TortoiseGit and if Bower keeps asking for your SSH
password, you should add the following environment variable: `GIT_SSH -
C:\Program Files\TortoiseGit\bin\TortoisePlink.exe`. Adjust the `TortoisePlink`
path if needed.
### Ubuntu users
To use Bower on Ubuntu, you might need to link `nodejs` executable to `node`:
```
sudo ln -s /usr/bin/nodejs /usr/bin/node
```
## Configuration
Bower can be configured using JSON in a `.bowerrc` file. Read over available options at [bower.io/docs/config](http://bower.io/docs/config).
## Completion (experimental)
_NOTE_: Completion is still not implemented for the 1.0.0 release
Bower now has an experimental `completion` command that is based on, and works
similarly to the [npm completion](https://npmjs.org/doc/cli/completion.html). It is
not available for Windows users.
This command will output a Bash / ZSH script to put into your `~/.bashrc`,
`~/.bash_profile`, or `~/.zshrc` file.
```sh
$ bower completion >> ~/.bash_profile
```
## Support
@@ -107,10 +106,10 @@ Bower can be configured using JSON in a `.bowerrc` file. Read over available opt
## Contributing
We welcome [contributions](https://github.com/bower/bower/graphs/contributors) of all kinds from anyone. Please take a moment to
We welcome contributions of all kinds from anyone. Please take a moment to
review the [guidelines for contributing](CONTRIBUTING.md).
* [Bug reports](https://github.com/bower/bower/wiki/Report-a-Bug)
* [Bug reports](CONTRIBUTING.md#bugs)
* [Feature requests](CONTRIBUTING.md#features)
* [Pull requests](CONTRIBUTING.md#pull-requests)
@@ -121,8 +120,27 @@ Note that on Windows for tests to pass you need to configure Git before cloning:
git config --global core.autocrlf input
```
## Bower Team
Bower is made by lots of people across the globe, contributions large and small. Our thanks to everyone who has played a part.
### Core team
* [@satazor](https://github.com/satazor)
* [@wibblymat](https://github.com/wibblymat)
* [@paulirish](https://github.com/paulirish)
* [@benschwarz](https://github.com/benschwarz)
* [@svnlto](https://github.com/svnlto)
* [@sheerun](https://github.com/sheerun)
### Bower Alumni
* [@fat](https://github.com/fat)
* [@maccman](https://github.com/maccman)
## License
Copyright (c) 2015 Twitter and [other contributors](https://github.com/bower/bower/graphs/contributors)
Copyright (c) 2015 Twitter and other contributors
Licensed under the MIT License

View File

@@ -10,29 +10,27 @@ init:
environment:
matrix:
- nodejs_version: "0.10"
- nodejs_version: "0.12"
- nodejs_version: "5"
- nodejs_version: "4"
# - nodejs_version: "0.11"
# Allow failing jobs for bleeding-edge Node.js versions.
matrix:
allow_failures:
- nodejs_version: "0.10"
- nodejs_version: "0.11"
# Install scripts. (runs after repo cloning)
install:
# Get the latest stable version of Node 0.STABLE.latest
- ps: Install-Product node $env:nodejs_version
# Output useful info for debugging.
- node --version
- npm --version
- git --version
- svn --version
# Install all dependencies
# Install subversion
- choco install svn -y
# Install bower
- npm install
# Post-install test scripts.
test_script:
# Output useful info for debugging.
- node --version
- npm --version
- cmd: npm test
# Don't actually build.

View File

@@ -1,30 +0,0 @@
var abbrev = require('abbrev');
var mout = require('mout');
function expandNames(obj, prefix, stack) {
prefix = prefix || '';
stack = stack || [];
mout.object.forOwn(obj, function (value, name) {
name = prefix + name;
stack.push(name);
if (typeof value === 'object' && !value.line) {
expandNames(value, name + ' ', stack);
}
});
return stack;
}
module.exports = function(commands) {
var abbreviations = abbrev(expandNames(commands));
abbreviations.i = 'install';
abbreviations.rm = 'uninstall';
abbreviations.unlink = 'uninstall';
abbreviations.ls = 'list';
return abbreviations;
};

View File

@@ -1,8 +1,8 @@
var fs = require('../../util/fs');
var fs = require('graceful-fs');
var path = require('path');
var mout = require('mout');
var Q = require('q');
var rimraf = require('../../util/rimraf');
var rimraf = require('rimraf');
var endpointParser = require('bower-endpoint-parser');
var PackageRepository = require('../../core/PackageRepository');
var semver = require('../../util/semver');

View File

@@ -1,6 +1,6 @@
var Q = require('q');
var path = require('path');
var fs = require('../util/fs');
var fs = require('graceful-fs');
var createError = require('../util/createError');
function help(logger, name, config) {

View File

@@ -1,6 +1,5 @@
var Q = require('q');
var Logger = require('bower-logger');
var config = require('../config');
/**
* Require commands only when called.
@@ -39,12 +38,10 @@ function commandFactory(id) {
Q.try(func, logger)
.done(function () {
config.restore();
var args = [].slice.call(arguments);
args.unshift('end');
logger.emit.apply(logger, args);
}, function (error) {
config.restore();
logger.emit('error', error);
});

View File

@@ -1,23 +1,18 @@
var mout = require('mout');
var fs = require('../util/fs');
var fs = require('graceful-fs');
var path = require('path');
var Q = require('q');
var endpointParser = require('bower-endpoint-parser');
var Project = require('../core/Project');
var defaultConfig = require('../config');
var GitHubResolver = require('../core/resolvers/GitHubResolver');
var GitFsResolver = require('../core/resolvers/GitFsResolver');
var cmd = require('../util/cmd');
var createError = require('../util/createError');
function init(logger, config) {
var project;
config = config || {};
if (!config.cwd) {
config.cwd = process.cwd();
}
config = defaultConfig(config);
// This command requires interactive to be enabled
@@ -57,7 +52,7 @@ function readJson(project, logger) {
function saveJson(project, logger, json) {
// Cleanup empty props (null values, empty strings, objects and arrays)
mout.object.forOwn(json, function (value, key) {
if (!validConfigValue(value)) {
if (value == null || mout.lang.isEmpty(value)) {
delete json[key];
}
});
@@ -80,18 +75,6 @@ function saveJson(project, logger, json) {
});
}
// Test if value is of a type supported by bower.json[0] - Object, Array, String, Boolean - or a Number
// [0]: https://github.com/bower/bower.json-spec
function validConfigValue(val) {
return (
mout.lang.isObject(val) ||
mout.lang.isArray(val) ||
mout.lang.isString(val) ||
mout.lang.isBoolean(val) ||
mout.lang.isNumber(val)
);
}
function setDefaults(config, json) {
var name;
var promise = Q.resolve();
@@ -101,6 +84,19 @@ function setDefaults(config, json) {
json.name = path.basename(config.cwd);
}
// Version
if (!json.version) {
// Assume latest semver tag if it's a git repo
promise = promise.then(function () {
return GitFsResolver.versions(config.cwd)
.then(function (versions) {
json.version = versions[0] || '0.0.0';
}, function () {
json.version = '0.0.0';
});
});
}
// Main
if (!json.main) {
// Remove '.js' from the end of the package name if it is there
@@ -174,6 +170,12 @@ function promptUser(logger, json) {
'default': json.name,
'type': 'input'
},
{
'name': 'version',
'message': 'version',
'default': json.version,
'type': 'input'
},
{
'name': 'description',
'message': 'description',
@@ -239,6 +241,7 @@ function promptUser(logger, json) {
return Q.nfcall(logger.prompt.bind(logger), questions)
.then(function (answers) {
json.name = answers.name;
json.version = answers.version;
json.description = answers.description;
json.main = answers.main;
json.moduleType = answers.moduleType;

View File

@@ -1,5 +1,5 @@
var path = require('path');
var rimraf = require('../util/rimraf');
var rimraf = require('rimraf');
var Q = require('q');
var Project = require('../core/Project');
var createLink = require('../util/createLink');

View File

@@ -81,7 +81,7 @@ function checkVersions(project, tree, logger) {
}, true);
if (nodes.length) {
logger.info('check-new', 'Checking for new versions of the project dependencies...');
logger.info('check-new', 'Checking for new versions of the project dependencies..');
}
// Check for new versions for each node

View File

@@ -1,9 +1,12 @@
var mout = require('mout');
var Q = require('q');
var chalk = require('chalk');
var PackageRepository = require('../core/PackageRepository');
var Config = require('bower-config');
var Tracker = require('../util/analytics').Tracker;
var createError = require('../util/createError');
var defaultConfig = require('../config');
var GitHubResolver = require('../core/resolvers/GitHubResolver');
function register(logger, name, url, config) {
var repository;
@@ -28,6 +31,16 @@ function register(logger, name, url, config) {
throw createError('Usage: bower register <name> <url>', 'EINVFORMAT');
}
// The public registry only allows git:// endpoints
// As such, we attempt to convert URLs as necessary
if (config.registry.register === Config.DEFAULT_REGISTRY) {
url = convertUrl(url, logger);
if (!mout.string.startsWith(url, 'git://')) {
throw createError('The registry only accepts URLs starting with git://', 'EINVFORMAT');
}
}
tracker.track('register');
// Attempt to resolve the package referenced by the URL to ensure
@@ -71,6 +84,22 @@ function register(logger, name, url, config) {
});
}
function convertUrl(url, logger) {
var pair;
var newUrl;
if (!mout.string.startsWith(url, 'git://')) {
// Convert GitHub ssh & https to git://
pair = GitHubResolver.getOrgRepoPair(url);
if (pair) {
newUrl = 'git://github.com/' + pair.org + '/' + pair.repo + '.git';
logger.warn('convert', 'Converted ' + url + ' to ' + newUrl);
}
}
return newUrl || url;
}
// -------------------
register.readOptions = function (argv) {

View File

@@ -23,9 +23,7 @@ update.readOptions = function (argv) {
var options = cli.readOptions({
'force-latest': { type: Boolean, shorthand: 'F' },
'production': { type: Boolean, shorthand: 'p' },
'save': { type: Boolean, shorthand: 'S' },
'save-dev': { type: Boolean, shorthand: 'D' }
'production': { type: Boolean, shorthand: 'p' }
}, argv);
var names = options.argv.remain.slice(1);

View File

@@ -1,6 +1,6 @@
var semver = require('semver');
var which = require('which');
var fs = require('../util/fs');
var fs = require('fs');
var path = require('path');
var Q = require('q');
var execFile = require('child_process').execFile;

View File

@@ -3,19 +3,22 @@ var object = require('mout').object;
var bowerConfig = require('bower-config');
var Configstore = require('configstore');
var current;
var cachedConfigs = {};
function defaultConfig(config) {
config = config || {};
return readCachedConfig(config.cwd || process.cwd(), config);
var cachedConfig = readCachedConfig(config.cwd || process.cwd());
return object.merge(cachedConfig, config);
}
function readCachedConfig(cwd, overwrites) {
current = bowerConfig.create(cwd).load(overwrites);
var config = current.toObject();
function readCachedConfig(cwd) {
if (cachedConfigs[cwd]) {
return cachedConfigs[cwd];
}
var config = cachedConfigs[cwd] = bowerConfig.read(cwd);
var configstore = new Configstore('bower-github').all;
object.mixIn(config, configstore);
@@ -51,17 +54,9 @@ function readCachedConfig(cwd, overwrites) {
return config;
}
function restoreConfig () {
if (current) {
current.restore();
}
}
function resetCache () {
restoreConfig();
current = undefined;
cachedConfigs = {};
}
module.exports = defaultConfig;
module.exports.restore = restoreConfig;
module.exports.reset = resetCache;

View File

@@ -2,8 +2,8 @@ var Q = require('q');
var mout = require('mout');
var path = require('path');
var mkdirp = require('mkdirp');
var rimraf = require('../util/rimraf');
var fs = require('../util/fs');
var rimraf = require('rimraf');
var fs = require('graceful-fs');
var endpointParser = require('bower-endpoint-parser');
var PackageRepository = require('./PackageRepository');
var semver = require('../util/semver');
@@ -23,13 +23,11 @@ function Manager(config, logger) {
Manager.prototype.configure = function (setup) {
var targetsHash = {};
this._conflicted = {};
// Targets - ignore those specified in ignoredDependencies
this._targets = mout.array.reject(setup.targets || [], function(target) {
return mout.array.contains(this._config.ignoredDependencies, target.name );
}, this);
// Targets
this._targets = setup.targets || [];
this._targets.forEach(function (decEndpoint) {
decEndpoint.initialName = decEndpoint.name;
decEndpoint.dependants = mout.object.values(decEndpoint.dependants);
@@ -82,17 +80,6 @@ Manager.prototype.configure = function (setup) {
return this;
};
/**
* It starts recursive fetching of targets. The flow is as follows:
*
* 1. this._fetch() that calls:
* 2. this._onFetchError() or this._onFetchSuccess() that calls:
* 3. this._parseDependencies() that calls for all dependencies:
* 4. this._fetch() again.
*
* Fetching and parsing of dependencies continues until all dependencies are fetched.
*
*/
Manager.prototype.resolve = function () {
// If already resolving, error out
if (this._working) {
@@ -158,7 +145,6 @@ Manager.prototype.postinstall = function (json) {
Manager.prototype.install = function (json) {
var componentsDir;
var componentsDirContents;
var that = this;
// If already resolving, error out
@@ -175,25 +161,16 @@ Manager.prototype.install = function (json) {
return Q.nfcall(mkdirp, componentsDir)
.then(function () {
var promises = [];
componentsDirContents = fs.readdirSync(componentsDir);
mout.object.forOwn(that._dissected, function (decEndpoint, name) {
var promise;
var dst;
var release = decEndpoint.pkgMeta._release;
var exists = mout.array.contains(componentsDirContents, name);
that._logger.action('install', name + (release ? '#' + release : ''), that.toData(decEndpoint));
dst = path.join(componentsDir, name);
if (exists && !that._installed[name] && !that._config.force) {
// There is a folder in the components directory that has
// this name, but it was not installed by bower.
that._logger.warn('skipped', name + ' was not installed because there is already a non-bower directory with that name in the components directory (' + path.relative(that._config.cwd, dst) + '). You can force installation with --force.');
return;
}
// Remove existent and copy canonical dir
promise = Q.nfcall(rimraf, dst)
.then(copy.copyDir.bind(copy, decEndpoint.canonicalDir, dst))
@@ -360,7 +337,7 @@ Manager.prototype._onFetchSuccess = function (decEndpoint, canonicalDir, pkgMeta
resolved.push(decEndpoint);
// Parse dependencies
this._parseDependencies(decEndpoint, pkgMeta);
this._parseDependencies(decEndpoint, pkgMeta, 'dependencies');
// Check if there are incompatibilities for this package name
// If there are, we need to fetch them
@@ -437,32 +414,18 @@ Manager.prototype._failFast = function () {
}.bind(this), 20000);
};
/**
* Parses decEndpoint dependencies and fetches missing ones.
*
* It fetches all non-yet-fetching dependencies with _fetch.
*
*
* @param {string} pkgMeta Metadata of package to resolve dependencies.
*/
Manager.prototype._parseDependencies = function (decEndpoint, pkgMeta) {
Manager.prototype._parseDependencies = function (decEndpoint, pkgMeta, jsonKey) {
var pending = [];
decEndpoint.dependencies = decEndpoint.dependencies || {};
// Parse package dependencies
mout.object.forOwn(pkgMeta.dependencies, function (value, key) {
mout.object.forOwn(pkgMeta[jsonKey], function (value, key) {
var resolved;
var fetching;
var compatible;
var childDecEndpoint = endpointParser.json2decomposed(key, value);
// Check if this depdendency should be skipped.
if (mout.array.contains(this._config.ignoredDependencies, childDecEndpoint.name)) {
this._logger.action('skipped', childDecEndpoint.name, this.toData(decEndpoint));
return;
}
// Check if a compatible one is already resolved
// If there's one, we don't need to resolve it twice
resolved = this._resolved[key];
@@ -526,24 +489,11 @@ Manager.prototype._parseDependencies = function (decEndpoint, pkgMeta) {
if (pending.length > 0) {
Q.all(pending)
.then(function () {
this._parseDependencies(decEndpoint, pkgMeta);
this._parseDependencies(decEndpoint, pkgMeta, jsonKey);
}.bind(this));
}
};
/**
* After batch of packages has been fetched, the results are stored in _resolved hash.
*
* {
* packageName: [array, of, decEndpoints]
* }
*
* This method takes all possible decEndpoints and selects only one of them per packageName.
*
* It stores selected packages in the this._dissected array.
*
* The _dissected array is used later on by install method to move packages to config.directory.
*/
Manager.prototype._dissect = function () {
var err;
var componentsDir;
@@ -621,11 +571,6 @@ Manager.prototype._dissect = function () {
return;
}
// Packages that didn't have any conflicts in resolution yet have
// "resolution" entry in bower.json are deemed unnecessary
//
// Probably in future we want to use them for force given resolution, but for now...
// See: https://github.com/bower/bower/issues/1362
this._logger.warn('extra-resolution', 'Unnecessary resolution: ' + name + '#' + resolution, {
name: name,
resolution: resolution,
@@ -645,16 +590,12 @@ Manager.prototype._dissect = function () {
}
// Skip if source is the same as dest
// FIXME: Shoudn't we force installation if force flag is used here?
dst = path.join(componentsDir, name);
if (dst === decEndpoint.canonicalDir) {
return false;
}
// We skip installing decEndpoint, if:
// 1. We have installed package with the same name
// 2. Packages have matching meta fields (needs explanation)
// 3. We didn't force the installation
// Analyse a few props
if (installedMeta &&
installedMeta._target === decEndpoint.target &&
installedMeta._originalSource === decEndpoint.source &&

View File

@@ -38,7 +38,8 @@ PackageRepository.prototype.fetch = function (decEndpoint) {
that._extendLog(log, info);
});
return this._getResolver(decEndpoint, logger)
// Get the appropriate resolver
return resolverFactory(decEndpoint, this._config, logger, this._registryClient)
// Decide if we retrieve from the cache or not
// Also decide if we validate the cached entry or not
.then(function (resolver) {
@@ -90,7 +91,7 @@ PackageRepository.prototype.fetch = function (decEndpoint) {
logger.action('validate', (pkgMeta._release ? pkgMeta._release + ' against ': '') +
resolver.getSource() + (resolver.getTarget() ? '#' + resolver.getTarget() : ''));
return resolver.hasNew(pkgMeta)
return resolver.hasNew(canonicalDir, pkgMeta)
.then(function (hasNew) {
// If there are no new contents, resolve to
// the cached one
@@ -116,15 +117,15 @@ PackageRepository.prototype.fetch = function (decEndpoint) {
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) {
return resolverFactory.getConstructor(source, this._config, this._registryClient)
.spread(function (ConcreteResolver, source) {
// If offline, resolve using the cached versions
if (this._config.offline) {
return this._resolveCache.versions(resolver.getSource());
return this._resolveCache.versions(source);
}
// Otherwise, fetch remotely
return resolver.constructor.versions(resolver.getSource());
return ConcreteResolver.versions(source);
}.bind(this));
};
@@ -167,13 +168,6 @@ PackageRepository.clearRuntimeCache = function () {
// ---------------------
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;

View File

@@ -1,21 +1,26 @@
var glob = require('glob');
var path = require('path');
var fs = require('../util/fs');
var fs = require('graceful-fs');
var Q = require('q');
var mout = require('mout');
var rimraf = require('../util/rimraf');
var rimraf = require('rimraf');
var endpointParser = require('bower-endpoint-parser');
var Logger = require('bower-logger');
var md5 = require('md5-hex');
var Manager = require('./Manager');
var defaultConfig = require('../config');
var semver = require('../util/semver');
var md5 = require('../util/md5');
var createError = require('../util/createError');
var readJson = require('../util/readJson');
var validLink = require('../util/validLink');
var scripts = require('./scripts');
function Project(config, logger) {
this._config = config;
// This is the only architecture component that ensures defaults
// on config and logger
// The reason behind it is that users can likely use this component
// directly if commands do not fulfil their needs
this._config = defaultConfig(config);
this._logger = logger || new Logger();
this._manager = new Manager(this._config, this._logger);
@@ -81,7 +86,7 @@ Project.prototype.install = function (decEndpoints, options, config) {
})
.then(function (installed) {
// Handle save and saveDev options
if (that._options.save || that._options.saveDev || that._options.saveExact) {
if (that._options.save || that._options.saveDev) {
// Cycle through the specified endpoints
decEndpoints.forEach(function (decEndpoint) {
var jsonEndpoint;
@@ -89,17 +94,15 @@ Project.prototype.install = function (decEndpoints, options, config) {
jsonEndpoint = endpointParser.decomposed2json(decEndpoint);
if (that._options.saveExact) {
if (decEndpoint.name !== decEndpoint.source) {
jsonEndpoint[decEndpoint.name] = decEndpoint.source + '#' + decEndpoint.pkgMeta.version;
} else {
jsonEndpoint[decEndpoint.name] = decEndpoint.pkgMeta.version;
}
jsonEndpoint[decEndpoint.name] = decEndpoint.pkgMeta.version;
}
if (that._options.save) {
that._json.dependencies = mout.object.mixIn(that._json.dependencies || {}, jsonEndpoint);
}
if (that._options.saveDev) {
that._json.devDependencies = mout.object.mixIn(that._json.devDependencies || {}, jsonEndpoint);
} else {
that._json.dependencies = mout.object.mixIn(that._json.dependencies || {}, jsonEndpoint);
}
});
}
@@ -197,27 +200,6 @@ Project.prototype.update = function (names, options) {
return that._manager.install(that._json);
})
.then(function (installed) {
if (that._options.save || that._options.saveDev) {
// Cycle through the specified endpoints
targets.forEach(function (target) {
// Abort if current and new version are identical
if (target.target === target.pkgMeta.version) {
return false;
}
var jsonEndpoint = endpointParser.decomposed2json(target);
// Bower uses the ~ range specifier for new installs
jsonEndpoint[target.name] = '~' + target.pkgMeta.version;
if (that._options.saveDev && mout.object.has(that._json, 'devDependencies.' + target.name)) {
that._json.devDependencies = mout.object.mixIn(that._json.devDependencies || {}, jsonEndpoint);
}
if (that._options.save && mout.object.has(that._json, 'dependencies.' + target.name)) {
that._json.dependencies = mout.object.mixIn(that._json.dependencies || {}, jsonEndpoint);
}
});
}
// Save JSON, might contain changes to resolutions
return that.saveJson()
.then(function () {
@@ -577,29 +559,9 @@ Project.prototype._readJson = function () {
return Q.resolve(this._json);
}
return Q.fcall(function() {
// This will throw if package.json does not exist
return fs.readFileSync(path.join(that._config.cwd, 'package.json'));
})
.then(function(buffer) {
// If package.json exists, use it's values as defaults
var defaults = {}, npm = JSON.parse(buffer.toString());
defaults.name = npm.name || path.basename(that._config.cwd) || 'root';
defaults.description = npm.description;
defaults.main = npm.main;
defaults.authors = npm.contributors || npm.author;
defaults.license = npm.license;
defaults.keywords = npm.keywords;
return defaults;
})
.catch(function(err) {
// Most likely no package.json so just set default name
return { name: path.basename(that._config.cwd) || 'root' };
})
.then(function(defaults) {
return that._json = readJson(that._config.cwd, { assume: defaults });
// Read local json
return this._json = readJson(this._config.cwd, {
assume: { name: path.basename(this._config.cwd) || 'root' }
})
.spread(function (json, deprecated, assumed) {
var jsonStr;

View File

@@ -1,15 +1,15 @@
var fs = require('../util/fs');
var fs = require('graceful-fs');
var path = require('path');
var mout = require('mout');
var Q = require('q');
var mkdirp = require('mkdirp');
var rimraf = require('../util/rimraf');
var rimraf = require('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');
var md5 = require('../util/md5');
function ResolveCache(config) {
// TODO: Make some config entries, such as:

View File

@@ -1,217 +1,166 @@
/*jshint laxbreak:true*/
var Q = require('q');
var fs = require('../util/fs');
var fs = require('graceful-fs');
var path = require('path');
var mout = require('mout');
var resolvers = require('./resolvers');
var createError = require('../util/createError');
var pluginResolverFactory = require('./resolvers/pluginResolverFactory');
function createInstance(decEndpoint, config, logger, registryClient) {
return getConstructor(decEndpoint.source, config, registryClient)
.spread(function (ConcreteResolver, source, fromRegistry) {
var decEndpointCopy = mout.object.pick(decEndpoint, ['name', 'target']);
function createInstance(decEndpoint, options, registryClient) {
decEndpoint = mout.object.pick(decEndpoint, ['name', 'target', 'source']);
decEndpointCopy.source = source;
options.version = require('../../package.json').version;
// Signal if it was fetched from the registry
if (fromRegistry) {
decEndpoint.registry = true;
// If no name was specified, assume the name from the registry
if (!decEndpointCopy.name) {
decEndpointCopy.name = decEndpoint.name = decEndpoint.source;
}
}
return getConstructor(decEndpoint, options, registryClient)
.spread(function (ConcreteResolver, decEndpoint) {
return new ConcreteResolver(decEndpoint, options.config, options.logger);
return new ConcreteResolver(decEndpointCopy, config, 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 construcotor 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]
|| pluginResolverFactory(require(resolverName), 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];
}
});
}
});
});
function getConstructor(source, config, registryClient) {
var absolutePath,
promise;
// 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 (/^git(\+(ssh|https?))?:\/\//i.test(source) || /\.git\/?$/i.test(source) || /^git@/i.test(source)) {
source = source.replace(/^git\+/, '');
return Q.fcall(function () {
// If it's a GitHub repository, return the specialized resolver
if (resolvers.GitHub.getOrgRepoPair(source)) {
return [resolvers.GitHub, decEndpoint];
return [resolvers.GitHub, source];
}
return [resolvers.GitRemote, decEndpoint];
}
});
return [resolvers.GitRemote, source];
});
}
// 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];
}
});
if (/^svn(\+(ssh|https?|file))?:\/\//i.test(source)) {
return Q.fcall(function () {
return [resolvers.Svn, source];
});
}
// URL case
addResolver(function () {
if (/^https?:\/\//i.exec(source)) {
return [resolvers.Url, decEndpoint];
}
});
if (/^https?:\/\//i.exec(source)) {
return Q.fcall(function () {
return [resolvers.Url, source];
});
}
// 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 throws an error
// If a step was able to guess the resolver, it resolves with a function
// That function returns a promise that will resolve with the concrete type
// If source is ./ or ../ or an absolute path
absolutePath = path.resolve(config.cwd, source);
addResolver(function () {
var absolutePath = path.resolve(config.cwd, source);
if (/^\.\.?[\/\\]/.test(source) || /^~\//.test(source) || path.normalize(source).replace(/[\/\\]+$/, '') === absolutePath) {
promise = Q.nfcall(fs.stat, path.join(absolutePath, '.git'))
.then(function (stats) {
if (stats.isDirectory()) {
return function () {
return Q.resolve([resolvers.GitFs, absolutePath]);
};
}
if (/^\.\.?[\/\\]/.test(source) || /^~\//.test(source) ||
path.normalize(source).replace(/[\/\\]+$/, '') === absolutePath
) {
return Q.nfcall(fs.stat, path.join(absolutePath, '.git'))
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.GitFs, decEndpoint]);
return function () {
return Q.resolve([resolvers.Svn, absolutePath]);
};
}
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]);
});
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 () {
return function () {
return Q.resolve([resolvers.Fs, absolutePath]);
};
});
});
} else {
promise = Q.reject(new Error('Not an absolute or relative file'));
}
return promise
// Check if is a shorthand and expand it
addResolver(function () {
.fail(function (err) {
var parts;
// Skip ssh and/or URL with auth
if (/[:@]/.test(source)) {
return;
throw err;
}
// Ensure exactly only one "/"
var parts = source.split('/');
parts = source.split('/');
if (parts.length === 2) {
decEndpoint.source = mout.string.interpolate(config.shorthandResolver, {
source = mout.string.interpolate(config.shorthandResolver, {
shorthand: source,
owner: parts[0],
package: parts[1]
});
return getConstructor(decEndpoint, options, registryClient);
return function () {
return getConstructor(source, config, registryClient);
};
}
});
throw err;
})
// As last resort, we try the registry
addResolver(function () {
.fail(function (err) {
if (!registryClient) {
return;
throw err;
}
return Q.nfcall(registryClient.lookup.bind(registryClient), source)
.then(function (entry) {
if (!entry) {
throw createError('Package ' + source + ' not found', 'ENOTFOUND');
}
return function () {
return Q.nfcall(registryClient.lookup.bind(registryClient), source)
.then(function (entry) {
if (!entry) {
throw createError('Package ' + source + ' not found', 'ENOTFOUND');
}
decEndpoint.registry = true;
// TODO: Handle entry.type.. for now it's only 'alias'
// When we got published packages, this needs to be adjusted
source = entry.url;
if (!decEndpoint.name) {
decEndpoint.name = decEndpoint.source;
}
decEndpoint.source = entry.url;
return getConstructor(decEndpoint, options);
});
});
addResolver(function () {
return getConstructor(source, config, registryClient)
.spread(function (ConcreteResolver, source) {
return [ConcreteResolver, source, true];
});
});
};
})
// If we got the function, simply call and return
.then(function (func) {
return func();
// Finally throw a meaningful error
}, function () {
throw createError('Could not find appropriate resolver for ' + source, 'ENORESOLVER');
});
return promise;
}
function clearRuntimeCache() {

View File

@@ -1,5 +1,5 @@
var util = require('util');
var fs = require('../../util/fs');
var fs = require('graceful-fs');
var path = require('path');
var mout = require('mout');
var Q = require('q');

View File

@@ -72,7 +72,7 @@ GitHubResolver.prototype._checkout = function () {
// Download tarball
return download(tarballUrl, file, {
ca: this._config.ca.default,
proxy: this._config.httpsProxy,
strictSSL: this._config.strictSsl,
timeout: this._config.timeout,
headers: reqHeaders

View File

@@ -1,4 +1,3 @@
/*jshint laxbreak:true*/
var util = require('util');
var url = require('url');
var Q = require('q');
@@ -120,7 +119,7 @@ GitRemoteResolver.prototype._fastClone = function (resolution) {
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)) {
if (shallowCloningSupported && !GitRemoteResolver._noShallow.get(this._host)) {
args.push('--depth', 1);
}
@@ -192,11 +191,6 @@ GitRemoteResolver.prototype._supportsShallowCloning = function () {
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
@@ -205,7 +199,7 @@ GitRemoteResolver.prototype._supportsShallowCloning = function () {
&& !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' });
var processEnv = mout.object.merge(process.env, { 'GIT_CURL_VERBOSE': 2 });
value = cmd('git', ['ls-remote', '--heads', this._source], {
env: processEnv

View File

@@ -1,7 +1,8 @@
var util = require('util');
var path = require('path');
var Q = require('q');
var rimraf = require('../../util/rimraf');
var chmodr = require('chmodr');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var which = require('which');
var LRU = require('lru-cache');
@@ -39,7 +40,7 @@ mout.object.mixIn(GitResolver, Resolver);
// -----------------
GitResolver.prototype._hasNew = function (pkgMeta) {
GitResolver.prototype._hasNew = function (canonicalDir, pkgMeta) {
var oldResolution = pkgMeta._resolution || {};
return this._findResolution()
@@ -143,7 +144,7 @@ GitResolver.prototype._findResolution = function (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(', ')
'Available versions: ' + versions.map(function (version) { return version.version; }).join(', ')
});
});
});
@@ -194,7 +195,23 @@ GitResolver.prototype._findResolution = function (target) {
GitResolver.prototype._cleanup = function () {
var gitFolder = path.join(this._tempDir, '.git');
return Q.nfcall(rimraf, gitFolder);
// Remove the .git folder
// Note that on windows, we need to chmod to 0777 before due to a bug in git
// See: https://github.com/isaacs/rimraf/issues/19
if (process.platform === 'win32') {
return Q.nfcall(chmodr, gitFolder, 0777)
.then(function () {
return Q.nfcall(rimraf, gitFolder);
}, function (err) {
// If .git does not exist, chmodr returns ENOENT
// so, we ignore that error code
if (err.code !== 'ENOENT') {
throw err;
}
});
} else {
return Q.nfcall(rimraf, gitFolder);
}
};
GitResolver.prototype._savePkgMeta = function (meta) {

View File

@@ -1,13 +1,12 @@
var fs = require('../../util/fs');
var fs = require('graceful-fs');
var path = require('path');
var Q = require('q');
var tmp = require('tmp');
var mkdirp = require('mkdirp');
var rimraf = require('../../util/rimraf');
var rimraf = require('rimraf');
var readJson = require('../../util/readJson');
var createError = require('../../util/createError');
var removeIgnores = require('../../util/removeIgnores');
var md5 = require('md5-hex');
tmp.setGracefulCleanup();
@@ -44,8 +43,9 @@ Resolver.prototype.getPkgMeta = function () {
return this._pkgMeta;
};
Resolver.prototype.hasNew = function (pkgMeta) {
Resolver.prototype.hasNew = function (canonicalDir, pkgMeta) {
var promise;
var metaFile;
var that = this;
// If already working, error out
@@ -56,7 +56,24 @@ Resolver.prototype.hasNew = function (pkgMeta) {
this._working = true;
// Avoid reading the package meta if already given
promise = this._hasNew(pkgMeta);
if (pkgMeta) {
promise = this._hasNew(canonicalDir, pkgMeta);
// Otherwise call _hasNew with both the package meta and the canonical dir
} else {
metaFile = path.join(canonicalDir, '.bower.json');
promise = readJson(metaFile)
.spread(function (pkgMeta) {
return that._hasNew(canonicalDir, pkgMeta);
}, function (err) {
that._logger.debug('read-json', 'Failed to read ' + metaFile, {
filename: metaFile,
error: err
});
return true; // Simply resolve to true if there was an error reading the file
});
}
return promise.fin(function () {
that._working = false;
@@ -108,7 +125,8 @@ Resolver.prototype.isCacheable = function () {
// We don't want to cache moving targets like branches
if (this._pkgMeta &&
this._pkgMeta._resolution &&
this._pkgMeta._resolution.type === 'branch') {
this._pkgMeta._resolution.type === 'branch')
{
return false;
}
@@ -125,7 +143,7 @@ Resolver.prototype._resolve = function () {
// Abstract functions that can be re-implemented by concrete resolvers
// as necessary
Resolver.prototype._hasNew = function (pkgMeta) {
Resolver.prototype._hasNew = function (canonicalDir, pkgMeta) {
return Q.resolve(true);
};
@@ -145,7 +163,7 @@ 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'),
template: path.join(this._config.tmp, this._name + '-' + process.pid + '-XXXXXX'),
mode: 0777 & ~process.umask(),
unsafeCleanup: true
});

View File

@@ -40,7 +40,7 @@ SvnResolver.getSource = function (source) {
.replace(/\/+$/, ''); // Remove trailing slashes
};
SvnResolver.prototype._hasNew = function (pkgMeta) {
SvnResolver.prototype._hasNew = function (canonicalDir, pkgMeta) {
var oldResolution = pkgMeta._resolution || {};
return this._findResolution()
@@ -86,13 +86,13 @@ SvnResolver.prototype._export = function () {
});
if (resolution.type === 'commit') {
promise = cmd('svn', ['export', '--force', '--non-interactive', this._source + '/trunk', '-r' + resolution.commit, this._tempDir]);
promise = cmd('svn', ['export', '--force', 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]);
promise = cmd('svn', ['export', '--force', this._source + '/trunk', this._tempDir]);
} else if (resolution.type === 'branch') {
promise = cmd('svn', ['export', '--force', '--non-interactive', this._source + '/branches/' + resolution.branch, this._tempDir]);
promise = cmd('svn', ['export', '--force', this._source + '/branches/' + resolution.branch, this._tempDir]);
} else {
promise = cmd('svn', ['export', '--force', '--non-interactive', this._source + '/tags/' + resolution.tag, this._tempDir]);
promise = cmd('svn', ['export', '--force', this._source + '/tags/' + resolution.tag, this._tempDir]);
}
// Throttle the progress reporter to 1 time each sec
@@ -188,7 +188,7 @@ SvnResolver.prototype._findResolution = function (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(', ')
'Available versions: ' + versions.map(function (version) { return version.version; }).join(', ')
});
});
});
@@ -324,7 +324,7 @@ SvnResolver.tags = function (source) {
return Q.resolve(value);
}
value = cmd('svn', ['list', source + '/tags', '--verbose', '--non-interactive'])
value = cmd('svn', ['list', source + '/tags', '--verbose'])
.spread(function (stout) {
var tags = SvnResolver.parseSubversionListOutput(stout.toString());
@@ -349,7 +349,7 @@ SvnResolver.branches = function (source) {
return Q.resolve(value);
}
value = cmd('svn', ['list', source + '/branches', '--verbose', '--non-interactive'])
value = cmd('svn', ['list', source + '/branches', '--verbose'])
.spread(function (stout) {
var branches = SvnResolver.parseSubversionListOutput(stout.toString());

View File

@@ -1,6 +1,6 @@
var util = require('util');
var path = require('path');
var fs = require('../../util/fs');
var fs = require('graceful-fs');
var url = require('url');
var request = require('request');
var Q = require('q');
@@ -39,7 +39,7 @@ UrlResolver.isTargetable = function () {
return false;
};
UrlResolver.prototype._hasNew = function (pkgMeta) {
UrlResolver.prototype._hasNew = function (canonicalDir, pkgMeta) {
var oldCacheHeaders = pkgMeta._cacheHeaders || {};
var reqHeaders = {};
@@ -55,7 +55,7 @@ UrlResolver.prototype._hasNew = function (pkgMeta) {
// Make an HEAD request to the source
return Q.nfcall(request.head, this._source, {
ca: this._config.ca.default,
proxy: this._remote.protocol === 'https:' ? this._config.httpsProxy : this._config.proxy,
strictSSL: this._config.strictSsl,
timeout: this._config.timeout,
headers: reqHeaders
@@ -104,18 +104,8 @@ UrlResolver.prototype._resolve = function () {
// -----------------
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 fileName = url.parse(path.basename(this._source)).pathname;
var file = path.join(this._tempDir, fileName);
var reqHeaders = {};
var that = this;
@@ -131,7 +121,7 @@ UrlResolver.prototype._download = function () {
// Download the file
return download(this._source, file, {
ca: this._config.ca.default,
proxy: this._remote.protocol === 'https:' ? this._config.httpsProxy : this._config.proxy,
strictSSL: this._config.strictSsl,
timeout: this._config.timeout,
headers: reqHeaders

View File

@@ -1,322 +0,0 @@
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 = this._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() }
})
.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;

View File

@@ -93,4 +93,4 @@ module.exports = {
postinstall: mout.function.partial(hook, 'postinstall', true),
//only exposed for test
_orderByDependencies: orderByDependencies
};
};

View File

@@ -1,6 +1,30 @@
var abbrev = require('abbrev');
var mout = require('mout');
var commands = require('./commands');
var pkg = require('../package.json');
var abbreviations = require('./abbreviations')(commands);
var abbreviations = abbrev(expandNames(commands));
abbreviations.i = 'install';
abbreviations.rm = 'uninstall';
abbreviations.unlink = 'uninstall';
abbreviations.ls = 'list';
function expandNames(obj, prefix, stack) {
prefix = prefix || '';
stack = stack || [];
mout.object.forOwn(obj, function (value, name) {
name = prefix + name;
stack.push(name);
if (typeof value === 'object' && !value.line) {
expandNames(value, name + ' ', stack);
}
});
return stack;
}
function clearRuntimeCache() {
// Note that in edge cases, some architecture components instance's

View File

@@ -31,10 +31,10 @@ JsonRenderer.prototype.error = function (err) {
err.message = message;
// Stack
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
/*jshint camelcase:false*/
stack = err.fstream_stack || err.stack || 'N/A';
err.stacktrace = (Array.isArray(stack) ? stack.join('\n') : stack);
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
/*jshint camelcase:true*/
this.log(err);
this.end();

View File

@@ -71,12 +71,12 @@ StandardRenderer.prototype.error = function (err) {
// Print trace if verbose, the error has no code
// or if the error is a node error
if (this._config.verbose || !err.code || err.errno) {
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
/*jshint camelcase:false*/
stack = err.fstream_stack || err.stack || 'N/A';
str = chalk.yellow('\nStack trace:\n');
str += (Array.isArray(stack) ? stack.join('\n') : stack) + '\n';
str += chalk.yellow('\nConsole trace:\n');
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
/*jshint camelcase:true*/
this._write(process.stderr, str);
this._write(process.stderr, new Error().stack);

View File

@@ -19,27 +19,13 @@ var enableAnalytics = false;
// because it takes time to read config and configstore has concurrency issues:
//
// https://github.com/yeoman/configstore/issues/20
function ensureInsight () {
if (!insight) {
var Insight = require('insight');
if (process.env.NODE_ENV === 'test') {
insight = new Insight({
trackingCode: 'UA-00000000-0',
pkg: {
name: 'bower-test',
version: '1.0.0'
}
});
insight.config.clear();
} else {
insight = new Insight({
trackingCode: 'UA-43531210-1',
pkg: require('../../package.json')
});
}
insight = new Insight({
trackingCode: 'UA-43531210-1',
pkg: require('../../package.json')
});
}
}
@@ -82,7 +68,7 @@ analytics.setup = function setup (config) {
});
};
var Tracker = analytics.Tracker = function Tracker (config) {
var Tracker = analytics.Tracker = function Tracker(config) {
function analyticsEnabled () {
// Allow for overriding analytics default
if (config && config.analytics !== undefined) {
@@ -103,24 +89,24 @@ var Tracker = analytics.Tracker = function Tracker (config) {
}
};
Tracker.prototype.track = function track () {
Tracker.prototype.track = function track() {
insight.track.apply(insight, arguments);
};
Tracker.prototype.trackDecomposedEndpoints = function trackDecomposedEndpoints (command, endpoints) {
Tracker.prototype.trackDecomposedEndpoints = function trackDecomposedEndpoints(command, endpoints) {
endpoints.forEach(function (endpoint) {
this.track(command, endpoint.source, endpoint.target);
}.bind(this));
};
Tracker.prototype.trackPackages = function trackPackages (command, packages) {
mout.object.forOwn(packages, function (_package) {
var meta = _package.pkgMeta;
Tracker.prototype.trackPackages = function trackPackages(command, packages) {
mout.object.forOwn(packages, function (package) {
var meta = package.pkgMeta;
this.track(command, meta.name, meta.version);
}.bind(this));
};
Tracker.prototype.trackNames = function trackNames (command, names) {
Tracker.prototype.trackNames = function trackNames(command, names) {
names.forEach(function (name) {
this.track(command, name);
}.bind(this));

View File

@@ -1,6 +1,6 @@
var fstream = require('fstream');
var fstreamIgnore = require('fstream-ignore');
var fs = require('./fs');
var fs = require('graceful-fs');
var Q = require('q');
function copy(reader, writer) {

View File

@@ -1,4 +1,4 @@
var fs = require('./fs');
var fs = require('graceful-fs');
var path = require('path');
var Q = require('q');
var mkdirp = require('mkdirp');

View File

@@ -3,20 +3,19 @@ var request = require('request');
var Q = require('q');
var mout = require('mout');
var retry = require('retry');
var fs = require('graceful-fs');
var createError = require('./createError');
var createWriteStream = require('fs-write-stream-atomic');
var destroy = require('destroy');
var errorCodes = [
'EADDRINFO',
'ETIMEDOUT',
'ECONNRESET',
'ESOCKETTIMEDOUT',
'ENOTFOUND'
'ESOCKETTIMEDOUT'
];
function download(url, file, options) {
var operation;
var response;
var deferred = Q.defer();
var progressDelay = 8000;
@@ -25,23 +24,46 @@ function download(url, file, options) {
factor: 2,
minTimeout: 1000,
maxTimeout: 35000,
randomize: true,
progressDelay: progressDelay
randomize: true
}, options || {});
// Retry on network errors
operation = retry.operation(options);
operation.attempt(function () {
Q.fcall(fetch, url, file, options)
.then(function(response) {
deferred.resolve(response);
var req;
var writeStream;
var contentLength;
var bytesDownloaded = 0;
req = progress(request(url, options), {
delay: progressDelay
})
.progress(function (status) {
deferred.notify(status);
.on('response', function (res) {
var status = res.statusCode;
if (status < 200 || status >= 300) {
return deferred.reject(createError('Status code of ' + status, 'EHTTP'));
}
response = res;
contentLength = Number(res.headers['content-length']);
})
.fail(function (error) {
// Save timeout before retrying to report
.on('data', function (data) {
bytesDownloaded += data.length;
})
.on('progress', function (state) {
deferred.notify(state);
})
.on('end', function () {
// Check if the whole file was downloaded
// In some unstable connections the ACK/FIN packet might be sent in the
// middle of the download
// See: https://github.com/joyent/node/issues/6143
if (contentLength && bytesDownloaded < contentLength) {
req.emit('error', createError('Transfer closed with ' + (contentLength - bytesDownloaded) + ' bytes remaining to read', 'EINCOMPLETE'));
}
})
.on('error', function (error) {
var timeout = operation._timeouts[0];
// Reject if error is not a network error
@@ -52,88 +74,33 @@ function download(url, file, options) {
// Next attempt will start reporting download progress immediately
progressDelay = 0;
// This will schedule next retry or return false
// Check if there are more retries
if (operation.retry(error)) {
deferred.notify({
// Ensure that there are no more events from this request
req.removeAllListeners();
req.on('error', function () {});
// Ensure that there are no more events from the write stream
writeStream.removeAllListeners();
writeStream.on('error', function () {});
return deferred.notify({
retry: true,
delay: timeout,
error: error
});
} else {
deferred.reject(error);
}
});
});
return deferred.promise;
}
function fetch(url, file, options) {
var deferred = Q.defer();
var contentLength;
var bytesDownloaded = 0;
var reject = function (error) {
deferred.reject(error);
};
var req = progress(request(url, options), {
delay: options.progressDelay
})
.on('response', function (response) {
contentLength = Number(response.headers['content-length']);
var status = response.statusCode;
if (status < 200 || status >= 300) {
return deferred.reject(createError('Status code of ' + status, 'EHTTP'));
}
var writeStream = createWriteStream(file);
var errored = false;
// Change error listener so it cleans up writeStream before exiting
req.removeListener('error', reject);
req.on('error', function (error) {
errored = true;
destroy(req);
destroy(writeStream);
// Wait for writeStream to cleanup after itself...
// TODO: Maybe there's a better way?
setTimeout(function () {
deferred.reject(error);
}, 50);
// No more retries, reject!
deferred.reject(error);
});
writeStream.on('finish', function () {
if (!errored) {
destroy(req);
deferred.resolve(response);
}
// Pipe read stream to write stream
writeStream = req
.pipe(fs.createWriteStream(file))
.on('error', deferred.reject)
.on('close', function () {
deferred.resolve(response);
});
req.pipe(writeStream);
})
.on('data', function (data) {
bytesDownloaded += data.length;
})
.on('progress', function (state) {
deferred.notify(state);
})
.on('error', reject)
.on('end', function () {
// Check if the whole file was downloaded
// In some unstable connections the ACK/FIN packet might be sent in the
// middle of the download
// See: https://github.com/joyent/node/issues/6143
if (contentLength && bytesDownloaded < contentLength) {
req.emit('error', createError(
'Transfer closed with ' + (contentLength - bytesDownloaded) + ' bytes remaining to read',
'EINCOMPLETE'
));
}
});
return deferred.promise;

View File

@@ -1,5 +1,5 @@
var path = require('path');
var fs = require('./fs');
var fs = require('graceful-fs');
var zlib = require('zlib');
var DecompressZip = require('decompress-zip');
var tar = require('tar-fs');
@@ -7,8 +7,6 @@ var Q = require('q');
var mout = require('mout');
var junk = require('junk');
var createError = require('./createError');
var createWriteStream = require('fs-write-stream-atomic');
var destroy = require('destroy');
// This forces the default chunk size to something small in an attempt
// to avoid issue #314
@@ -51,24 +49,15 @@ function extractZip(archive, dst) {
function extractTar(archive, dst) {
var deferred = Q.defer();
var stream = fs.createReadStream(archive);
var reject = function (error) {
destroy(stream);
deferred.reject(error);
};
stream.on('error', reject)
fs.createReadStream(archive)
.on('error', deferred.reject)
.pipe(tar.extract(dst, {
ignore: isSymlink, // Filter symlink files
dmode: 0555, // Ensure dirs are readable
fmode: 0444 // Ensure files are readable
}))
.on('error', reject)
.on('finish', function (result) {
destroy(stream);
deferred.resolve(dst);
});
.on('error', deferred.reject)
.on('finish', deferred.resolve.bind(deferred, dst));
return deferred.promise;
}
@@ -76,26 +65,17 @@ function extractTar(archive, dst) {
function extractTarGz(archive, dst) {
var deferred = Q.defer();
var stream = fs.createReadStream(archive);
var reject = function (error) {
destroy(stream);
deferred.reject(error);
};
stream.on('error', reject)
fs.createReadStream(archive)
.on('error', deferred.reject)
.pipe(zlib.createGunzip())
.on('error', reject)
.on('error', deferred.reject)
.pipe(tar.extract(dst, {
ignore: isSymlink, // Filter symlink files
dmode: 0555, // Ensure dirs are readable
fmode: 0444 // Ensure files are readable
}))
.on('error', reject)
.on('finish', function (result) {
destroy(stream);
deferred.resolve(dst);
});
.on('error', deferred.reject)
.on('finish', deferred.resolve.bind(deferred, dst));
return deferred.promise;
}
@@ -103,21 +83,13 @@ function extractTarGz(archive, dst) {
function extractGz(archive, dst) {
var deferred = Q.defer();
var stream = fs.createReadStream(archive);
var reject = function (error) {
destroy(stream);
deferred.reject(error);
};
stream.on('error', reject)
fs.createReadStream(archive)
.on('error', deferred.reject)
.pipe(zlib.createGunzip())
.on('error', reject)
.pipe(createWriteStream(dst))
.on('error', reject)
.on('finish', function (result) {
destroy(stream);
deferred.resolve(dst);
});
.on('error', deferred.reject)
.pipe(fs.createWriteStream(dst))
.on('error', deferred.reject)
.on('close', deferred.resolve.bind(deferred, dst));
return deferred.promise;
}

View File

@@ -1,34 +0,0 @@
var fs = require('graceful-fs');
var readdir = fs.readdir.bind(fs);
var readdirSync = fs.readdirSync.bind(fs);
module.exports = fs;
module.exports.readdir = function (dir, callback) {
fs.stat(dir, function (err, stats) {
if (err) return callback(err);
if (stats.isDirectory()) {
return readdir(dir, callback);
} else {
var error = new Error('ENOTDIR, not a directory \'' + dir + '\'');
error.code = 'ENOTDIR';
error.path = dir;
error.errono = -20;
return callback(error);
}
});
};
module.exports.readdirSync = function (dir) {
var stats = fs.statSync(dir);
if (stats.isDirectory()) {
return readdirSync(dir);
} else {
var error = new Error();
error.code = 'ENOTDIR';
throw error;
}
};

7
lib/util/md5.js Normal file
View File

@@ -0,0 +1,7 @@
var crypto = require('crypto');
function md5(contents) {
return crypto.createHash('md5').update(contents).digest('hex');
}
module.exports = md5;

View File

@@ -1,5 +1,5 @@
var path = require('path');
var rimraf = require('../util/rimraf');
var rimraf = require('rimraf');
var fstreamIgnore = require('fstream-ignore');
var mout = require('mout');
var Q = require('q');

View File

@@ -1,46 +0,0 @@
var rimraf = require('rimraf');
var chmodr = require('chmodr');
var fs = require('./fs');
module.exports = function (dir, callback) {
var checkAndRetry = function (e) {
fs.lstat(dir, function (err, stats) {
if (err) {
if (err.code === 'ENOENT') return callback();
return callback(e);
}
chmodr(dir, 0777, function (err) {
if (err) return callback(e);
rimraf(dir, callback);
});
});
};
if (process.platform === 'win32') {
checkAndRetry();
} else {
rimraf(dir, checkAndRetry);
}
};
module.exports.sync = function (dir) {
var checkAndRetry = function () {
try {
fs.lstatSync(dir);
chmodr.sync(dir, 0777);
return rimraf.sync(dir);
} catch (e) {
if (e.code === 'ENOENT') return;
throw e;
}
};
try {
return rimraf.sync(dir);
} catch (e) {
return checkAndRetry();
} finally {
return checkAndRetry();
}
};

View File

@@ -1,5 +1,4 @@
/*jshint multistr:true*/
// jscs:disable disallowMultipleLineStrings
'use strict';
var isRoot = require('is-root');
var createError = require('./createError');

View File

@@ -1,5 +1,5 @@
var path = require('path');
var fs = require('./fs');
var fs = require('graceful-fs');
var Handlebars = require('handlebars');
var mout = require('mout');
var helpers = require('../../templates/helpers');

View File

@@ -1,3 +0,0 @@
var pkg = require('../../package.json');
module.exports = 'node/' + process.version + ' ' + process.platform + ' ' + process.arch + ' ' + ';Bower ' + pkg.version;

View File

@@ -1,5 +1,5 @@
var Q = require('q');
var fs = require('./fs');
var fs = require('graceful-fs');
function validLink(file) {
// Ensures that a file is a symlink that points

View File

@@ -1,46 +1,45 @@
{
"name": "bower",
"version": "1.6.8",
"version": "1.4.2",
"description": "The browser package manager",
"author": "Twitter",
"license": "MIT",
"licenses": [
{
"type": "MIT",
"url": "https://github.com/bower/bower/blob/master/LICENSE"
}
],
"repository": "bower/bower",
"main": "lib",
"homepage": "http://bower.io",
"engines": {
"node": ">=0.10.0"
},
"keywords": [
"bower"
],
"dependencies": {
"abbrev": "^1.0.5",
"archy": "1.0.0",
"bower-config": "^1.2.3",
"bower-config": "^0.6.1",
"bower-endpoint-parser": "^0.2.2",
"bower-json": "^0.4.0",
"bower-logger": "^0.2.2",
"bower-registry-client": "^1.0.0",
"bower-registry-client": "^0.3.0",
"cardinal": "0.4.4",
"chalk": "^1.0.0",
"chmodr": "^1.0.2",
"chmodr": "0.1.0",
"configstore": "^0.3.2",
"decompress-zip": "^0.1.0",
"destroy": "^1.0.3",
"fs-write-stream-atomic": "^1.0.4",
"fstream": "^1.0.3",
"fstream-ignore": "^1.0.2",
"github": "^0.2.3",
"glob": "^4.3.2",
"graceful-fs": "^3.0.5",
"handlebars": "^2.0.0",
"inquirer": "0.10.0",
"insight": "^0.7.0",
"inquirer": "0.8.0",
"insight": "^0.5.0",
"is-root": "^1.0.0",
"junk": "^1.0.0",
"lockfile": "^1.0.0",
"lru-cache": "^2.5.0",
"md5-hex": "^1.0.2",
"lru-cache": "2.7.0",
"mkdirp": "0.5.0",
"mout": "^0.11.0",
"nopt": "^3.0.1",
@@ -70,72 +69,21 @@
"grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-exec": "^0.4.6",
"grunt-jscs": "^2.3.0",
"grunt-simple-mocha": "^0.4.0",
"istanbul": "^0.3.5",
"load-grunt-tasks": "^2.0.0",
"mocha": "^2.1.0",
"multiline": "^1.0.2",
"nock": "^3.1.0",
"nock": "^0.56.0",
"node-uuid": "^1.4.2",
"proxyquire": "^1.3.0",
"spawn-sync": "1.0.13"
"spawn-sync": "^1.0.5"
},
"bundledDependencies": [
"abbrev",
"archy",
"bower-config",
"bower-endpoint-parser",
"bower-json",
"bower-logger",
"bower-registry-client",
"cardinal",
"chalk",
"chmodr",
"configstore",
"decompress-zip",
"destroy",
"fs-write-stream-atomic",
"fstream",
"fstream-ignore",
"github",
"glob",
"graceful-fs",
"handlebars",
"inquirer",
"insight",
"is-root",
"junk",
"lockfile",
"lru-cache",
"md5-hex",
"mkdirp",
"mout",
"nopt",
"opn",
"p-throttler",
"promptly",
"q",
"request",
"request-progress",
"retry",
"rimraf",
"semver",
"shell-quote",
"stringify-object",
"tar-fs",
"tmp",
"update-notifier",
"user-home",
"which"
],
"scripts": {
"test": "grunt test"
},
"bin": "bin/bower",
"files": [
"bin",
"lib",
"templates"
]
"bin": {
"bower": "bin/bower"
},
"preferGlobal": true
}

View File

@@ -62,7 +62,6 @@
"description": "Allows running commands as root"
},
{
"shorthand": "-v",
"flag": "--version",
"description": "Output Bower version"
},

View File

@@ -1,4 +1,4 @@
var fs = require('../../../lib/util/fs');
var fs = require('graceful-fs');
var path = require('path');
var Logger = require('bower-logger');
var Resolver = require('../../../lib/core/resolvers/Resolver');

View File

@@ -1,4 +1,4 @@
var fs = require('../../../lib/util/fs');
var fs = require('graceful-fs');
var path = require('path');
var Logger = require('bower-logger');
var Resolver = require('../../../lib/core/resolvers/Resolver');

View File

@@ -1,23 +1,31 @@
var expect = require('expect.js');
var runBin = require('../helpers').runBin;
var helpers = require('../helpers');
describe('bower', function () {
process.env.CI = '1';
it('runs bower installation', function () {
var result = runBin();
var text = result.stdout.toString();
var oldStdout;
var text;
before(function() {
oldStdout = process.stdout.write;
text = '';
process.stdout.write = function(args) {
text += args;
};
});
it('runs bower installation', function (done) {
helpers.require('bin/bower');
setTimeout(function() {
done();
}, 250);
});
after(function() {
process.stdout.write = oldStdout;
expect(text).to.contain('Usage:');
expect(text).to.contain('Commands:');
});
});
describe('abbreviations', function () {
it('Returns same value than the full command', function() {
var abbr = runBin(['install']);
var full = runBin(['i']);
expect(abbr.stdout.toString()).to.be.equal(full.stdout.toString());
});
});

View File

@@ -1,13 +1,13 @@
var expect = require('expect.js');
var md5 = require('md5-hex');
var helpers = require('../../helpers');
var cacheClean = helpers.command('cache/clean');
var md5 = helpers.require('lib/util/md5');
var object = require('mout/object');
describe('bower cache clean', function () {
// Because directory names are required to be md5 of _source
// Because directory names are required to be mp5 of _source
var cacheFilesFactory = function (spec) {
var files = {};
@@ -20,7 +20,7 @@ describe('bower cache clean', function () {
return files;
};
var cacheFiles = cacheFilesFactory([
{
name: 'angular',

View File

@@ -10,7 +10,7 @@ describe('bower home', function () {
expect(home.readOptions(['foo'])).to.eql(['foo']);
});
var mainPackage = new helpers.TempDir({
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
homepage: 'http://bower.io'
@@ -24,22 +24,22 @@ describe('bower home', function () {
});
it('opens repository home page in web browser', function () {
mainPackage.prepare();
package.prepare();
return Q.Promise(function(resolve) {
var home = helpers.command('home', { opn: resolve });
helpers.run(home, [mainPackage.path]);
helpers.run(home, [package.path]);
}).then(function(url) {
expect(url).to.be('http://bower.io');
});
});
it('opens home page of current repository', function () {
mainPackage.prepare();
package.prepare();
return Q.Promise(function(resolve) {
var home = helpers.command('home', { opn: resolve });
helpers.run(home, [undefined, { cwd: mainPackage.path }]);
helpers.run(home, [undefined, { cwd: package.path }]);
}).then(function(url) {
expect(url).to.be('http://bower.io');
});

View File

@@ -15,5 +15,7 @@ describe('integration tests', function () {
require('./uninstall');
require('./update');
require('./version');
// run last because it changes defaults
require('./bower');
});

View File

@@ -24,7 +24,7 @@ describe('bower info', function () {
description: 'Hello world! Hello!'
};
var mainPackage = new helpers.TempDir({
var package = new helpers.TempDir({
'0.1.2': { 'bower.json': meta },
'0.1.3': { 'bower.json': meta2 }
});
@@ -36,12 +36,12 @@ describe('bower info', function () {
});
it('shows info about given package', function () {
mainPackage.prepareGit({});
package.prepareGit({});
return helpers.run(info, [mainPackage.path]).spread(function(results) {
return helpers.run(info, [package.path]).spread(function(results) {
expect(results).to.eql({
'latest': meta2,
'name': mainPackage.path,
'name': package.path,
'versions': [
'0.1.3',
'0.1.2'

View File

@@ -5,7 +5,7 @@ var init = helpers.command('init');
describe('bower init', function () {
var mainPackage = new helpers.TempDir();
var package = new helpers.TempDir();
it('correctly reads arguments', function() {
expect(init.readOptions([]))
@@ -13,10 +13,10 @@ describe('bower init', function () {
});
it('generates bower.json file', function () {
mainPackage.prepare();
package.prepare();
var logger = init({
cwd: mainPackage.path,
cwd: package.path,
interactive: true
});
@@ -24,6 +24,7 @@ describe('bower init', function () {
.spread(function (prompt, answer) {
answer({
name: 'test-name',
version: 'test-version',
description: 'test-description',
moduleType: 'test-moduleType',
keywords: 'test-keyword',
@@ -40,23 +41,23 @@ describe('bower init', function () {
return helpers.expectEvent(logger, 'end');
})
.then(function () {
expect(mainPackage.readJson('bower.json')).to.eql({
expect(package.readJson('bower.json')).to.eql({
name: 'test-name',
version: 'test-version',
homepage: 'test-homepage',
authors: [ 'test-author' ],
description: 'test-description',
moduleType: 'test-moduleType',
keywords: [ 'test-keyword' ],
license: 'test-license',
private: true
license: 'test-license'
});
});
});
it('errors on non-interactive mode', function () {
mainPackage.prepare();
package.prepare();
return helpers.run(init, { cwd: mainPackage.path }).then(
return helpers.run(init, { cwd: package.path }).then(
function () { throw 'should fail'; },
function (reason) {
expect(reason.message).to.be('Register requires an interactive shell');
@@ -66,13 +67,13 @@ describe('bower init', function () {
});
it('warns about existing bower.json', function () {
mainPackage.prepare({
package.prepare({
'bower.json': {
name: 'foobar'
}
});
var logger = init({ cwd: mainPackage.path, interactive: true });
var logger = init({ cwd: package.path, interactive: true });
return helpers.expectEvent(logger, 'log').spread(function(event) {
expect(event.level).to.be('warn');
@@ -81,69 +82,4 @@ describe('bower init', function () {
);
});
});
it('gets defaults from package.json', function () {
mainPackage.prepare({
'package.json': {
'name': 'name from npm',
'description': 'description from npm',
'main': 'index.js',
'keywords': [
'foo',
'bar'
],
'author': 'JD Isaacks',
'license': 'ISC'
}
});
var logger = init({
cwd: mainPackage.path,
interactive: true
});
return helpers.expectEvent(logger, 'prompt')
.spread(function (prompt, answer) {
// Get defaults from prompt
var defaults = prompt.reduce(function(memo, obj) {
memo[obj.name] = obj['default'];
return memo;
}, {});
// Answer with defaults
answer({
name: defaults.name,
description: defaults.description,
main: defaults.main,
moduleType: defaults.moduleType,
keywords: defaults.keywords,
authors: defaults.authors,
license: defaults.license,
homepage: 'test-homepage',
private: true
});
return helpers.expectEvent(logger, 'prompt');
})
.spread(function (prompt, answer) {
answer({ prompt: true });
return helpers.expectEvent(logger, 'end');
})
.then(function () {
expect(mainPackage.readJson('bower.json')).to.eql({
'name': 'name from npm',
'description': 'description from npm',
'main': 'index.js',
'keywords': [
'foo',
'bar'
],
'authors': ['JD Isaacks'],
'license': 'ISC',
'private': true,
'homepage': 'test-homepage'
});
});
});
});

View File

@@ -1,7 +1,5 @@
var expect = require('expect.js');
var helpers = require('../helpers');
var nock = require('nock');
var fs = require('../../lib/util/fs');
describe('bower install', function () {
@@ -11,29 +9,29 @@ describe('bower install', function () {
it('correctly reads arguments', function() {
expect(install.readOptions(['jquery', 'angular', '-F', '-p', '-S', '-D', '-E']))
.to.eql([['jquery', 'angular'], {
forceLatest: true,
production: true,
save: true,
saveDev: true,
saveExact: true
}]);
.to.eql([['jquery', 'angular'], {
forceLatest: true,
production: true,
save: true,
saveDev: true,
saveExact: true
}]);
});
it('correctly reads long arguments', function() {
expect(install.readOptions([
'jquery', 'angular',
'--force-latest', '--production', '--save', '--save-dev', '--save-exact'
])).to.eql([['jquery', 'angular'], {
forceLatest: true,
production: true,
save: true,
saveDev: true,
saveExact: true
}]);
'jquery', 'angular',
'--force-latest', '--production', '--save', '--save-dev', '--save-exact'
])).to.eql([['jquery', 'angular'], {
forceLatest: true,
production: true,
save: true,
saveDev: true,
saveExact: true
}]);
});
var mainPackage = new helpers.TempDir({
var package = new helpers.TempDir({
'bower.json': {
name: 'package'
}
@@ -42,7 +40,7 @@ describe('bower install', function () {
var gitPackage = new helpers.TempDir();
it('writes to bower.json if --save flag is used', function () {
mainPackage.prepare();
package.prepare();
tempDir.prepare({
'bower.json': {
@@ -50,15 +48,14 @@ describe('bower install', function () {
}
});
return helpers.run(install, [[mainPackage.path], { save: true }]).then(function() {
return helpers.run(install, [[package.path], { save: true }]).then(function() {
expect(tempDir.read('bower.json')).to.contain('dependencies');
});
});
it('writes an exact version number to dependencies in bower.json if --save --save-exact flags are used', function () {
mainPackage.prepare({
package.prepare({
'bower.json': {
name: 'package',
version: '1.2.3'
}
});
@@ -70,17 +67,16 @@ describe('bower install', function () {
});
return helpers.run(install, [
[mainPackage.path],
{ saveExact: true, save: true }
]).then(function() {
expect(tempDir.readJson('bower.json').dependencies.package).to.equal(mainPackage.path + '#1.2.3');
});
[package.path],
{ saveExact: true, save: true }
]).then(function() {
expect(tempDir.readJson('bower.json').dependencies.package).to.equal('1.2.3');
});
});
it('writes an exact version number to devDependencies in bower.json if --save-dev --save-exact flags are used', function () {
mainPackage.prepare({
package.prepare({
'bower.json': {
name: 'package',
version: '0.1.0'
}
});
@@ -92,22 +88,42 @@ describe('bower install', function () {
});
return helpers.run(install, [
[mainPackage.path],
{ saveExact: true, saveDev: true }
]).then(function() {
expect(tempDir.readJson('bower.json').devDependencies.package).to.equal(mainPackage.path + '#0.1.0');
[package.path],
{ saveExact: true, saveDev: true }
]).then(function() {
expect(tempDir.readJson('bower.json').devDependencies.package).to.equal('0.1.0');
});
});
it('does not write to bower.json if only --save-exact flag is used', function() {
package.prepare({
'bower.json': {
version: '1.2.3'
}
});
tempDir.prepare({
'bower.json': {
name: 'test'
}
});
return helpers.run(install, [[package.path], { saveExact: true }]).then(function() {
expect(tempDir.read('bower.json')).to.not.contain('dependencies');
expect(tempDir.read('bower.json')).to.not.contain('devDependencies');
});
});
it('reads .bowerrc from cwd', function () {
mainPackage.prepare({ foo: 'bar' });
package.prepare({ foo: 'bar' });
tempDir.prepare({
'.bowerrc': { directory: 'assets' },
'bower.json': {
name: 'test',
dependencies: {
package: mainPackage.path
package: package.path
}
}
});
@@ -118,13 +134,13 @@ describe('bower install', function () {
});
it('runs preinstall hook', function () {
mainPackage.prepare();
package.prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: mainPackage.path
package: package.path
}
},
'.bowerrc': {
@@ -140,13 +156,13 @@ describe('bower install', function () {
});
it('runs preinstall hook', function () {
mainPackage.prepare();
package.prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: mainPackage.path
package: package.path
}
},
'.bowerrc': {
@@ -181,7 +197,7 @@ describe('bower install', function () {
});
it('runs postinstall after bower.json is written', function () {
mainPackage.prepare();
package.prepare();
tempDir.prepare({
'bower.json': {
@@ -194,19 +210,19 @@ describe('bower install', function () {
}
});
return helpers.run(install, [[mainPackage.path], { save: true }]).then(function() {
return helpers.run(install, [[package.path], { save: true }]).then(function() {
expect(tempDir.read('hook.txt')).to.contain('dependencies');
});
});
it('display the output of hook scripts', function (next) {
mainPackage.prepare();
package.prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: mainPackage.path
package: package.path
}
},
'.bowerrc': {
@@ -215,6 +231,7 @@ describe('bower install', function () {
}
}
});
var lastAction = null;
helpers.run(install).logger.intercept(function (log) {
@@ -227,28 +244,6 @@ describe('bower install', function () {
});
});
it('skips components not installed by bower', function () {
mainPackage.prepare({
'.git': {} //Make a dummy file instead of using slower gitPrepare()
});
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: mainPackage.path
}
}
});
return helpers.run(install).then(function() {
var packageFiles = fs.readdirSync(mainPackage.path);
//presence of .git file implies folder was not overwritten
expect(packageFiles).to.contain('.git');
});
});
it('works for git repositories', function () {
gitPackage.prepareGit({
'1.0.0': {
@@ -278,123 +273,4 @@ describe('bower install', function () {
expect(tempDir.read('bower_components/package/version.txt')).to.contain('1.0.0');
});
});
it('does not install ignored dependencies', function() {
mainPackage.prepare();
var package2 = new helpers.TempDir({
'bower.json': {
name: 'package2',
}
}).prepare();
var package3 = new helpers.TempDir({
'bower.json': {
name: 'package3',
dependencies: {
package2: package2.path,
package: mainPackage.path,
}
}
}).prepare();
tempDir.prepare({
'bower.json': {
name: 'test_tw',
dependencies: {
package3: package3.path
}
},
'.bowerrc': {
ignoredDependencies: ['package']
}
});
return helpers.run(install).then(function() {
expect(tempDir.exists('bower_components/package')).to.be(false);
expect(tempDir.exists('bower_components/package2')).to.be(true);
});
});
it('does not install ignored dependencies if run multiple times', function() {
mainPackage.prepare();
var package2 = new helpers.TempDir({
'bower.json': {
name: 'package2',
}
}).prepare();
var package3 = new helpers.TempDir({
'bower.json': {
name: 'package3',
dependencies: {
package2: package2.path,
package: mainPackage.path,
}
}
}).prepare();
tempDir.prepare({
'bower.json': {
name: 'test_tw',
dependencies: {
package3: package3.path
}
},
'.bowerrc': {
ignoredDependencies: ['package']
}
});
return helpers.run(install).then(function() {
return helpers.run(install).then(function() {
expect(tempDir.exists('bower_components/package')).to.be(false);
expect(tempDir.exists('bower_components/package2')).to.be(true);
});
});
});
it('recognizes proxy option in config', function (done) {
this.timeout(10000);
tempDir.prepare({
'bower.json': {
name: 'test_tw',
dependencies: {
pure: 'http://github.com/yahoo/pure/archive/v0.6.0.tar.gz'
}
}
});
var install = helpers.command('install', {
cwd: tempDir.path
});
nock('http://dummy.local')
.get('http://github.com/yahoo/pure/archive/v0.6.0.tar.gz')
.reply(500);
return helpers.run(install, [
undefined,
undefined,
{ proxy: 'http://dummy.local/' }
])
.fail(function(error) {
expect(error.message).to.equal('Status code of 500');
done();
});
});
it('errors if the components directory is not a directory', function () {
tempDir.prepare({
'.bowerrc': {
directory: '.bowerrc'
}
});
return helpers.run(install).fail(function(error) {
expect(error.code).to.equal('ENOTDIR');
});
});
});

View File

@@ -5,7 +5,7 @@ var link = helpers.command('link');
describe('bower link', function () {
var mainPackage = new helpers.TempDir({
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
},
@@ -22,7 +22,7 @@ describe('bower link', function () {
var linksDir = new helpers.TempDir();
beforeEach(function() {
mainPackage.prepare();
package.prepare();
otherPackage.prepare();
linksDir.prepare();
});
@@ -35,7 +35,7 @@ describe('bower link', function () {
it('creates self link', function () {
return helpers.run(link, [undefined, undefined,
{
cwd: mainPackage.path,
cwd: package.path,
storage: {
links: linksDir.path
}
@@ -49,7 +49,7 @@ describe('bower link', function () {
it('creates inter-link', function () {
return helpers.run(link, [undefined, undefined,
{
cwd: mainPackage.path,
cwd: package.path,
storage: {
links: linksDir.path
}
@@ -72,7 +72,7 @@ describe('bower link', function () {
it('creates inter-link with custom local name', function () {
return helpers.run(link, [undefined, undefined,
{
cwd: mainPackage.path,
cwd: package.path,
storage: {
links: linksDir.path
}

View File

@@ -63,20 +63,20 @@ describe('bower list', function () {
it('lists 1 dependency when 1 local package installed', function () {
var mainPackage = new helpers.TempDir({
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
main: 'test.txt'
}
}).prepare();
mainPackage.prepare();
package.prepare();
return install([mainPackage.path]).then(function() {
return install([package.path]).then(function() {
return list().spread(function(results) {
expect(results).to.be.an(Object);
expect(results.canonicalDir).to.equal(tempDir.path);
expect(results.pkgMeta.dependencies).to.eql({
package: mainPackage.path + '#*'
package: package.path + '#*'
});
expect(results.pkgMeta.devDependencies).to.eql({});
expect(results.dependencies.package).to.be.an(Object);
@@ -96,15 +96,15 @@ describe('bower list', function () {
it('lists 1 dependency with relative paths when 1 local package installed', function () {
var mainPackage = new helpers.TempDir({
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
main: 'test.txt'
}
}).prepare();
mainPackage.prepare();
package.prepare();
return install([mainPackage.path]).then(function() {
return install([package.path]).then(function() {
return list({relative: true}).spread(function(results) {
expect(results).to.be.an(Object);
expect(results.canonicalDir).to.equal(tempDir.path);
@@ -113,7 +113,7 @@ describe('bower list', function () {
expect(results.dependencies.package.pkgMeta).to.be.an(Object);
expect(results.dependencies.package.pkgMeta.main).to.equal('test.txt');
expect(results.pkgMeta.dependencies).to.eql({
package: mainPackage.path + '#*'
package: package.path + '#*'
});
expect(results.dependencies.package.canonicalDir).to.equal(
path.normalize('bower_components/package')
@@ -124,15 +124,15 @@ describe('bower list', function () {
it('lists 1 dependency with 1 source relative source mapping when 1 local package installed', function () {
var mainPackage = new helpers.TempDir({
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
main: 'test.txt'
}
}).prepare();
mainPackage.prepare();
package.prepare();
return install([mainPackage.path]).then(function() {
return install([package.path]).then(function() {
return list({paths: true}).spread(function(results) {
expect(results).to.be.an(Object);
expect(results.package).to.equal(
@@ -144,15 +144,15 @@ describe('bower list', function () {
it('lists 1 dependency with 2 source relative source mapping when 1 local package installed', function () {
var mainPackage = new helpers.TempDir({
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
main: ['test.txt', 'test2.txt']
}
}).prepare();
mainPackage.prepare();
package.prepare();
return install([mainPackage.path]).then(function() {
return install([package.path]).then(function() {
return list({paths: true}).spread(function(results) {
expect(results).to.be.an(Object);
expect(results.package).to.be.an(Object);
@@ -181,7 +181,7 @@ describe('bower list', function () {
'version.txt': '1.0.1'
}
});
tempDir.prepare({
'bower.json': {
name: 'test',
@@ -231,7 +231,7 @@ describe('bower list', function () {
'version.txt': '1.0.1'
}
});
tempDir.prepare({
'bower.json': {
name: 'test',

View File

@@ -5,7 +5,7 @@ var prune = helpers.command('prune');
describe('bower home', function () {
var mainPackage = new helpers.TempDir({
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
dependencies: {
@@ -26,30 +26,30 @@ describe('bower home', function () {
});
it('removes extraneous packages', function () {
mainPackage.prepare({
package.prepare({
'bower_components/angular/angular.js': 'angular source',
'bower_components/angular/.bower.json': { name: 'angular' }
});
return helpers.run(prune, [{}, { cwd: mainPackage.path }]).then(function() {
expect(mainPackage.exists('bower_components/angular/angular.js'))
return helpers.run(prune, [{}, { cwd: package.path }]).then(function() {
expect(package.exists('bower_components/angular/angular.js'))
.to.be(false);
});
});
it('leaves non-bower packages', function () {
mainPackage.prepare({
package.prepare({
'bower_components/angular/angular.js': 'angular source'
});
return helpers.run(prune, [{}, { cwd: mainPackage.path }]).then(function() {
expect(mainPackage.exists('bower_components/angular/angular.js'))
return helpers.run(prune, [{}, { cwd: package.path }]).then(function() {
expect(package.exists('bower_components/angular/angular.js'))
.to.be(true);
});
});
it('deals with custom directory', function () {
mainPackage.prepare({
package.prepare({
'.bowerrc': { directory: 'components' },
'bower_components/angular/.bower.json': { name: 'angular' },
'bower_components/angular/angular.js': 'angular source',
@@ -57,9 +57,9 @@ describe('bower home', function () {
'components/angular/angular.js': 'angular source'
});
return helpers.run(prune, [{}, { cwd: mainPackage.path }]).then(function() {
expect(mainPackage.exists('components/angular/angular.js')).to.be(false);
expect(mainPackage.exists('bower_components/angular/angular.js')).to.be(true);
return helpers.run(prune, [{}, { cwd: package.path }]).then(function() {
expect(package.exists('components/angular/angular.js')).to.be(false);
expect(package.exists('bower_components/angular/angular.js')).to.be(true);
});
});
});

View File

@@ -36,7 +36,7 @@ var registerFactory = function (canonicalDir, pkgMeta) {
describe('bower register', function () {
var mainPackage = new helpers.TempDir({
var package = new helpers.TempDir({
'bower.json': {
name: 'package'
}
@@ -62,10 +62,18 @@ describe('bower register', function () {
});
});
it('errors if trying to register private package', function () {
mainPackage.prepare({ 'bower.json': { private: true } });
it('errors if url is not correct', function () {
return helpers.run(register, ['some-name', 'url'])
.fail(function(reason) {
expect(reason.message).to.be('The registry only accepts URLs starting with git://');
expect(reason.code).to.be('EINVFORMAT');
});
});
var register = registerFactory(mainPackage.path, mainPackage.meta());
it('errors if trying to register private package', function () {
package.prepare({ 'bower.json': { private: true } });
var register = registerFactory(package.path, package.meta());
return helpers.run(register, ['some-name', 'git://fake-url.git'])
.fail(function(reason) {
expect(reason.message).to.be('The package you are trying to register is marked as private');
@@ -74,9 +82,9 @@ describe('bower register', function () {
});
it('should call registry client with name and url', function () {
mainPackage.prepare();
package.prepare();
var register = registerFactory(mainPackage.path, mainPackage.meta());
var register = registerFactory(package.path, package.meta());
return helpers.run(register, ['some-name', 'git://fake-url.git'])
.spread(function(result) {
expect(result).to.eql({
@@ -87,9 +95,9 @@ describe('bower register', function () {
});
it('should confirm in interactive mode', function () {
mainPackage.prepare();
package.prepare();
var register = registerFactory(mainPackage.path, mainPackage.meta());
var register = registerFactory(package.path, package.meta());
var promise = helpers.run(register,
['some-name', 'git://fake-url.git', { interactive: true }]
@@ -104,9 +112,9 @@ describe('bower register', function () {
});
it('should skip confirming when forcing', function () {
mainPackage.prepare();
package.prepare();
var register = registerFactory(mainPackage.path, mainPackage.meta());
var register = registerFactory(package.path, package.meta());
return helpers.run(register,
['some-name', 'git://fake-url.git',

View File

@@ -1,6 +1,6 @@
var path = require('path');
var expect = require('expect.js');
var fs = require('../../lib/util/fs');
var fs = require('fs');
var helpers = require('../helpers');
var uninstall = helpers.command('uninstall');

View File

@@ -1,20 +1,13 @@
var expect = require('expect.js');
var object = require('mout').object;
var semver = require('semver');
var helpers = require('../helpers');
var updateCmd = helpers.command('update');
var commands = helpers.require('lib/index').commands;
describe('bower update', function () {
this.timeout(10000);
var tempDir = new helpers.TempDir();
var subPackage = new helpers.TempDir({
'bower.json': {
name: 'subPackage'
}
}).prepare();
var tempDir = new helpers.TempDir();
var gitPackage = new helpers.TempDir();
@@ -27,29 +20,28 @@ describe('bower update', function () {
},
'1.0.1': {
'bower.json': {
name: 'package',
dependencies: {
subPackage: subPackage.path
}
name: 'package'
},
'version.txt': '1.0.1'
}
});
var mainPackage = new helpers.TempDir({
var package = new helpers.TempDir({
'bower.json': {
name: 'package'
}
}).prepare();
var update = function(packages, options, config) {
var updateLogger = function(packages, options, config) {
config = object.merge(config || {}, {
cwd: tempDir.path
});
var logger = commands.update(
packages, options, config
);
return commands.update(packages, options, config);
};
var update = function(packages, options, config) {
var logger = updateLogger(packages, options, config);
return helpers.expectEvent(logger, 'end');
};
@@ -67,23 +59,18 @@ describe('bower update', function () {
};
it('correctly reads arguments', function() {
expect(updateCmd.readOptions(['jquery', '-F', '-p', '-S', '-D']))
.to.eql([['jquery'], {
forceLatest: true,
production: true,
save: true,
saveDev: true
}]);
expect(updateCmd.readOptions(['jquery', '-F', '-p']))
.to.eql([['jquery'], { forceLatest: true, production: true }]);
});
it('install missing packages', function () {
mainPackage.prepare();
package.prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: mainPackage.path
package: package.path
}
}
});
@@ -94,86 +81,14 @@ describe('bower update', function () {
});
});
it('does not install ignored dependencies', function() {
var package3 = new helpers.TempDir({
'bower.json': {
name: 'package3'
}
}).prepare();
var package2 = new helpers.TempDir({
'bower.json': {
name: 'package2',
dependencies: {
package3: package3.path
}
}
}).prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package2: package2.path
}
},
'.bowerrc': {
ignoredDependencies: ['package3']
}
});
return update().then(function() {
expect(tempDir.exists('bower_components/package2/bower.json')).to.equal(true);
expect(tempDir.exists('bower_components/package3')).to.equal(false);
});
});
it('does not install ignored dependencies if run multiple times', function() {
var package3 = new helpers.TempDir({
'bower.json': {
name: 'package3'
}
}).prepare();
var package2 = new helpers.TempDir({
'bower.json': {
name: 'package2',
dependencies: {
package3: package3.path
}
}
}).prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package2: package2.path
}
},
'.bowerrc': {
ignoredDependencies: ['package3']
}
});
return update().then(function() {
return update().then(function() {
expect(tempDir.exists('bower_components/package2/bower.json')).to.equal(true);
expect(tempDir.exists('bower_components/package3')).to.equal(false);
});
});
});
it('runs preinstall hook when installing missing package', function () {
mainPackage.prepare();
package.prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: mainPackage.path
package: package.path
}
},
'.bowerrc': {
@@ -189,13 +104,13 @@ describe('bower update', function () {
});
it('runs postinstall hook when installing missing package', function () {
mainPackage.prepare();
package.prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: mainPackage.path
package: package.path
}
},
'.bowerrc': {
@@ -211,13 +126,13 @@ describe('bower update', function () {
});
it('doesn\'t runs postinstall when no package is update', function () {
mainPackage.prepare();
package.prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: mainPackage.path
package: package.path
}
},
'.bowerrc': {
@@ -250,7 +165,7 @@ describe('bower update', function () {
expect(tempDir.read('bower_components/package/version.txt')).to.contain('1.0.0');
tempDir.prepare({
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
@@ -265,277 +180,6 @@ describe('bower update', function () {
});
});
it('doesn\'t update extraneous packages', function () {
tempDir.prepare({
'bower.json': {
name: 'test'
}
});
return install(['underscore#1.5.0']).then(function() {
expect(tempDir.readJson('bower_components/underscore/package.json').version).to.equal('1.5.0');
return update(null, {save: true}).then(function() {
expect(tempDir.readJson('bower_components/underscore/package.json').version).to.equal('1.5.0');
expect(tempDir.readJson('bower.json')).to.not.have.property('dependencies');
});
});
});
it('updates bower.json dep after updating with --save flag', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
underscore: '~1.5.0'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('~1.5.0');
return update(null, {save: true}).then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('~1.5.2');
});
});
});
it('updates bower.json dev dep after updating with --save-dev flag', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
devDependencies: {
underscore: '~1.5.0'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').devDependencies.underscore).to.equal('~1.5.0');
return update(null, {saveDev: true}).then(function() {
expect(tempDir.readJson('bower.json').devDependencies.underscore).to.equal('~1.5.2');
});
});
});
it('replaces "any" range with latest version', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
underscore: '*'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('*');
return update(null, {save: true}).then(function() {
var version = semver.gte(tempDir.readJson('bower.json').dependencies.underscore.replace('~', ''), '1.8.3');
expect(version).to.be.ok();
});
});
});
it('updates multiple components in bower.json after updating with --save flag', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
underscore: '~1.5.0',
lodash: '~1.0.0'
},
devDependencies: {
neat: '~1.5.0'
},
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('~1.5.0');
expect(tempDir.readJson('bower.json').dependencies.lodash).to.equal('~1.0.0');
expect(tempDir.readJson('bower.json').devDependencies.neat).to.equal('~1.5.0');
return update(null, {save: true}).then(function() {
// Normal deps should have changed
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('~1.5.2');
expect(tempDir.readJson('bower.json').dependencies.lodash).to.equal('~1.0.2');
// Dev deps should not have changed
expect(tempDir.readJson('bower.json').devDependencies.neat).to.equal('~1.5.0');
});
});
});
it('updates multiple components in bower.json after updating with --save-dev flag', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
neat: '~1.5.0'
},
devDependencies: {
underscore: '~1.5.0',
lodash: '~1.0.0'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.neat).to.equal('~1.5.0');
expect(tempDir.readJson('bower.json').devDependencies.underscore).to.equal('~1.5.0');
expect(tempDir.readJson('bower.json').devDependencies.lodash).to.equal('~1.0.0');
return update(null, {saveDev: true}).then(function() {
// Normal deps should not have changed
expect(tempDir.readJson('bower.json').dependencies.neat).to.equal('~1.5.0');
// Dev deps should have changed
expect(tempDir.readJson('bower.json').devDependencies.underscore).to.equal('~1.5.2');
expect(tempDir.readJson('bower.json').devDependencies.lodash).to.equal('~1.0.2');
});
});
});
it('correctly interprets semver range specifier pre-1.0', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
underscore: '^0.1.0'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('^0.1.0');
return update(null, {save: true}).then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('~0.1.1');
});
});
});
it('correctly interprets semver range specifier post-1.0', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
lodash: '^1.0.0'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.lodash).to.equal('^1.0.0');
return update(null, {save: true}).then(function() {
expect(tempDir.readJson('bower.json').dependencies.lodash).to.equal('~1.3.1');
});
});
});
it('doesn\'t update bower.json if versions are identical', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
underscore: '1.5.0'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('1.5.0');
return update(null, {save: true}).then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('1.5.0');
});
});
});
it('does not install ignored dependencies when updating a package', function () {
var package3 = new helpers.TempDir({
'bower.json': {
name: 'package3'
}
}).prepare();
var package2 = new helpers.TempDir().prepareGit({
'1.0.0': {
'bower.json': {
name: 'package2',
version: '1.0.0',
dependencies: {
package3: package3.path
}
}
},
'1.0.1': {
'bower.json': {
name: 'package2',
version: '1.0.1',
dependencies: {
package3: package3.path
}
}
}
});
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package2: package2.path + '#1.0.0'
}
},
'.bowerrc': {
ignoredDependencies: ['package3']
}
});
return install().then(function() {
expect(tempDir.readJson('bower_components/package2/bower.json').version).to.equal('1.0.0');
expect(tempDir.exists('bower_components/package3')).to.equal(false);
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package2: package2.path + '#1.0.1'
}
},
'.bowerrc': {
ignoredDependencies: ['package3']
}
});
return update().then(function() {
expect(tempDir.readJson('bower_components/package2/bower.json').version).to.equal('1.0.1');
expect(tempDir.exists('bower_components/package3')).to.equal(false);
});
});
});
it('runs preinstall hook when updating a package', function () {
tempDir.prepare({
'bower.json': {
@@ -543,27 +187,27 @@ describe('bower update', function () {
dependencies: {
package: gitPackage.path + '#1.0.0'
}
},
'.bowerrc': {
scripts: {
preinstall: 'node -e \'require("fs").writeFileSync("preinstall.txt", "%")\''
}
}
});
return install().then(function() {
tempDir.prepare({
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: gitPackage.path + '#1.0.1'
}
},
'.bowerrc': {
scripts: {
preinstall: 'node -e \'require("fs").writeFileSync("preinstall.txt", "%")\''
}
}
});
expect(tempDir.exists('preinstall.txt')).to.be(false);
return update().then(function() {
expect(tempDir.read('preinstall.txt')).to.be('subPackage package');
expect(tempDir.read('preinstall.txt')).to.be('package');
});
});
});
@@ -575,28 +219,28 @@ describe('bower update', function () {
dependencies: {
package: gitPackage.path + '#1.0.0'
}
},
'.bowerrc': {
scripts: {
preinstall: 'node -e \'require("fs").writeFileSync("preinstall.txt", "%")\'',
postinstall: 'node -e \'require("fs").writeFileSync("postinstall.txt", "%")\''
}
}
});
return install().then(function() {
tempDir.prepare({
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: gitPackage.path + '#1.0.1'
}
},
'.bowerrc': {
scripts: {
preinstall: 'node -e \'require("fs").writeFileSync("preinstall.txt", "%")\'',
postinstall: 'node -e \'require("fs").writeFileSync("postinstall.txt", "%")\''
}
}
});
expect(tempDir.exists('postinstall.txt')).to.be(false);
return update().then(function() {
expect(tempDir.read('postinstall.txt')).to.be('subPackage package');
expect(tempDir.read('postinstall.txt')).to.be('package');
});
});
});

View File

@@ -5,7 +5,7 @@ var version = helpers.require('lib/commands').version;
describe('bower list', function () {
var mainPackage = new helpers.TempDir({
var package = new helpers.TempDir({
'bower.json': {
name: 'foobar',
version: '0.0.0'
@@ -22,41 +22,41 @@ describe('bower list', function () {
});
it('bumps patch version', function() {
mainPackage.prepare();
package.prepare();
return helpers.run(version, ['patch', {}, { cwd: mainPackage.path }]).then(function() {
expect(mainPackage.readJson('bower.json').version).to.be('0.0.1');
return helpers.run(version, ['patch', {}, { cwd: package.path }]).then(function() {
expect(package.readJson('bower.json').version).to.be('0.0.1');
});
});
it('bumps minor version', function() {
mainPackage.prepare();
package.prepare();
return helpers.run(version, ['minor', {}, { cwd: mainPackage.path }]).then(function() {
expect(mainPackage.readJson('bower.json').version).to.be('0.1.0');
return helpers.run(version, ['minor', {}, { cwd: package.path }]).then(function() {
expect(package.readJson('bower.json').version).to.be('0.1.0');
});
});
it('bumps major version', function() {
mainPackage.prepare();
package.prepare();
return helpers.run(version, ['major', {}, { cwd: mainPackage.path }]).then(function() {
expect(mainPackage.readJson('bower.json').version).to.be('1.0.0');
return helpers.run(version, ['major', {}, { cwd: package.path }]).then(function() {
expect(package.readJson('bower.json').version).to.be('1.0.0');
});
});
it('changes version', function() {
mainPackage.prepare();
package.prepare();
return helpers.run(version, ['1.2.3', {}, { cwd: mainPackage.path }]).then(function() {
expect(mainPackage.readJson('bower.json').version).to.be('1.2.3');
return helpers.run(version, ['1.2.3', {}, { cwd: package.path }]).then(function() {
expect(package.readJson('bower.json').version).to.be('1.2.3');
});
});
it('returns the new version', function() {
mainPackage.prepare();
package.prepare();
return helpers.run(version, ['major', {}, { cwd: mainPackage.path }]).then(function(results) {
return helpers.run(version, ['major', {}, { cwd: package.path }]).then(function(results) {
expect(results[0]).to.be('1.0.0');
});
});

View File

@@ -1,6 +1,6 @@
var expect = require('expect.js');
var path = require('path');
var rimraf = require('../../lib/util/rimraf');
var rimraf = require('rimraf');
var Logger = require('bower-logger');
var Manager = require('../../lib/core/Manager');
var defaultConfig = require('../../lib/config');

View File

@@ -2,8 +2,8 @@ var expect = require('expect.js');
var Q = require('q');
var path = require('path');
var mout = require('mout');
var fs = require('../../lib/util/fs');
var rimraf = require('../../lib/util/rimraf');
var fs = require('graceful-fs');
var rimraf = require('rimraf');
var RegistryClient = require('bower-registry-client');
var Logger = require('bower-logger');
var proxyquire = require('proxyquire');
@@ -45,10 +45,7 @@ describe('PackageRepository', function () {
});
// Mock the resolver factory to always return a resolver for the test package
function resolverFactory(decEndpoint, options, _registryClient) {
var _config = options.config;
var _logger = options.logger;
function resolverFactory(decEndpoint, _config, _logger, _registryClient) {
expect(_config).to.eql(config);
expect(_logger).to.be.an(Logger);
expect(_registryClient).to.be.an(RegistryClient);
@@ -70,9 +67,7 @@ describe('PackageRepository', function () {
return Q.resolve(resolver);
}
resolverFactory.getConstructor = function () {
return Q.resolve([resolvers.GitRemote, {
source: helpers.localSource(testPackage)
}]);
return Q.resolve([resolvers.GitRemote, helpers.localSource(testPackage), false]);
};
resolverFactory.clearRuntimeCache = function () {
resolverFactoryClearHook();
@@ -244,7 +239,8 @@ describe('PackageRepository', function () {
resolverFactoryHook = function (resolver) {
var originalHasNew = resolver.hasNew;
resolver.hasNew = function (pkgMeta) {
resolver.hasNew = function (canonicalDir, pkgMeta) {
expect(canonicalDir).to.equal(tempPackage);
expect(pkgMeta).to.eql(json);
called = true;
return originalHasNew.apply(this, arguments);
@@ -287,7 +283,8 @@ describe('PackageRepository', function () {
return originalResolve.apply(this, arguments);
};
resolver.hasNew = function (pkgMeta) {
resolver.hasNew = function (canonicalDir, pkgMeta) {
expect(canonicalDir).to.equal(tempPackage);
expect(pkgMeta).to.eql(json);
called.push('hasNew');
return Q.resolve(true);
@@ -330,7 +327,8 @@ describe('PackageRepository', function () {
return originalResolve.apply(this, arguments);
};
resolver.hasNew = function (pkgMeta) {
resolver.hasNew = function (canonicalDir, pkgMeta) {
expect(canonicalDir).to.equal(tempPackage);
expect(pkgMeta).to.eql(json);
called.push('hasNew');
return Q.resolve(false);
@@ -366,7 +364,8 @@ describe('PackageRepository', function () {
resolverFactoryHook = function (resolver) {
var originalResolve = resolver.resolve;
resolver.hasNew = function (pkgMeta) {
resolver.hasNew = function (canonicalDir, pkgMeta) {
expect(canonicalDir).to.equal(tempPackage);
expect(pkgMeta).to.eql(json);
called.push('resolve');
return originalResolve.apply(this, arguments);

View File

@@ -1,15 +1,15 @@
var path = require('path');
var mout = require('mout');
var rimraf = require('../../lib/util/rimraf');
var fs = require('../../lib/util/fs');
var rimraf = require('rimraf');
var fs = require('graceful-fs');
var Q = require('q');
var expect = require('expect.js');
var mkdirp = require('mkdirp');
var md5 = require('md5-hex');
var ResolveCache = require('../../lib/core/ResolveCache');
var defaultConfig = require('../../lib/config');
var cmd = require('../../lib/util/cmd');
var copy = require('../../lib/util/copy');
var md5 = require('../../lib/util/md5');
describe('ResolveCache', function () {
var resolveCache;

View File

@@ -1,10 +1,10 @@
var expect = require('expect.js');
var fs = require('../../lib/util/fs');
var fs = require('graceful-fs');
var path = require('path');
var mkdirp = require('mkdirp');
var mout = require('mout');
var Q = require('q');
var rimraf = require('../../lib/util/rimraf');
var rimraf = require('rimraf');
var RegistryClient = require('bower-registry-client');
var Logger = require('bower-logger');
var resolverFactory = require('../../lib/core/resolverFactory');
@@ -34,8 +34,8 @@ describe('resolverFactory', function () {
rimraf('pure', next);
});
function callFactory(decEndpoint, config, skipRegistry) {
return resolverFactory(decEndpoint, { config: defaultConfig(config), logger: logger }, skipRegistry ? undefined : registryClient);
function callFactory(decEndpoint, config) {
return resolverFactory(decEndpoint, defaultConfig(config), logger, registryClient);
}
it('should recognize git remote endpoints correctly', function (next) {
@@ -526,41 +526,6 @@ describe('resolverFactory', function () {
.done();
});
it('should recognize URL endpoints correctly', function (next) {
var promise = Q.resolve();
var endpoints;
endpoints = [
'http://bower.io/foo.js',
'https://bower.io/foo.js'
];
endpoints.forEach(function (source) {
// Test without name
promise = promise.then(function () {
return callFactory({ source: source });
})
.then(function (resolver) {
expect(resolver).to.be.a(resolvers.Url);
expect(resolver.getSource()).to.equal(source);
});
// Test with name
promise = promise.then(function () {
return callFactory({ name: 'foo', source: source });
})
.then(function (resolver) {
expect(resolver).to.be.a(resolvers.Url);
expect(resolver.getName()).to.equal('foo');
expect(resolver.getSource()).to.equal(source);
});
});
promise
.then(next.bind(next, null))
.done();
});
it('should recognize registry endpoints correctly', function (next) {
// Create a 'pure' file at the root to prevent regressions of #666
fs.writeFileSync('pure', 'foo');
@@ -608,15 +573,16 @@ describe('resolverFactory', function () {
.done();
});
// it('should set registry to true on the decomposed endpoint if fetched from the registry', function (next) {
// var decEndpoint = { source: 'pure' };
it('should set registry to true on the decomposed endpoint if fetched from the registry', function (next) {
var decEndpoint = { source: 'pure' };
// return callFactory(decEndpoint, { resolvers: ['sample-custom-resolver'] })
// .then(function () {
// next();
// })
// .done();
// });
callFactory(decEndpoint)
.then(function () {
expect(decEndpoint.registry).to.be(true);
next();
})
.done();
});
it('should use the configured shorthand resolver', function (next) {
callFactory({ source: 'bower/bower' })
@@ -651,7 +617,7 @@ describe('resolverFactory', function () {
it('should error out if there\'s no suitable resolver for a given source', function (next) {
callFactory({ source: 'some-package-that-will-never-exist' }, undefined, true)
resolverFactory({ source: 'some-package-that-will-never-exist' }, defaultConfig(), logger)
.then(function () {
throw new Error('Should have failed');
}, function (err) {

View File

@@ -1,8 +1,8 @@
var expect = require('expect.js');
var path = require('path');
var fs = require('../../../lib/util/fs');
var fs = require('graceful-fs');
var path = require('path');
var rimraf = require('../../../lib/util/rimraf');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var Q = require('q');
var Logger = require('bower-logger');
@@ -82,11 +82,13 @@ describe('FsResolver', function () {
it('should resolve always to true (for now..)', function (next) {
var resolver = create(testPackage);
var pkgMeta = {
tempSource = path.resolve(__dirname, '../../tmp/tmp');
mkdirp.sync(tempSource);
fs.writeFileSync(path.join(tempSource, '.bower.json'), JSON.stringify({
name: 'test'
};
}));
resolver.hasNew(pkgMeta)
resolver.hasNew(tempSource)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();

View File

@@ -1,8 +1,8 @@
var expect = require('expect.js');
var path = require('path');
var fs = require('../../../lib/util/fs');
var fs = require('graceful-fs');
var path = require('path');
var rimraf = require('../../../lib/util/rimraf');
var rimraf = require('rimraf');
var Logger = require('bower-logger');
var cmd = require('../../../lib/util/cmd');
var copy = require('../../../lib/util/copy');

View File

@@ -1,6 +1,6 @@
var path = require('path');
var nock = require('nock');
var fs = require('../../../lib/util/fs');
var fs = require('graceful-fs');
var expect = require('expect.js');
var Logger = require('bower-logger');
var GitRemoteResolver = require('../../../lib/core/resolvers/GitRemoteResolver');
@@ -16,6 +16,9 @@ describe('GitHub', function () {
});
afterEach(function () {
// Clean nocks
nock.cleanAll();
logger.removeAllListeners();
});
@@ -49,10 +52,10 @@ describe('GitHub', function () {
var resolver;
nock('https://github.com')
.get('/IndigoUnited/js-events-emitter/archive/0.1.0.tar.gz')
.get('/IndigoUnited/events-emitter/archive/0.1.0.tar.gz')
.replyWithFile(200, path.resolve(__dirname, '../../assets/package-tar.tar.gz'));
resolver = create({ source: 'git://github.com/IndigoUnited/js-events-emitter.git', target: '0.1.0' });
resolver = create({ source: 'git://github.com/IndigoUnited/events-emitter.git', target: '0.1.0' });
resolver.resolve()
.then(function (dir) {
@@ -73,7 +76,7 @@ describe('GitHub', function () {
var retried;
nock('https://github.com')
.get('/IndigoUnited/js-events-emitter/archive/0.1.0.tar.gz')
.get('/IndigoUnited/events-emitter/archive/0.1.0.tar.gz')
.reply(200, 'this is not a valid tar');
logger.on('log', function (entry) {
@@ -82,7 +85,7 @@ describe('GitHub', function () {
}
});
resolver = create({ source: 'git://github.com/IndigoUnited/js-events-emitter.git', target: '0.1.0' });
resolver = create({ source: 'git://github.com/IndigoUnited/events-emitter.git', target: '0.1.0' });
// Monkey patch source to file://
resolver._source = 'file://' + testPackage;
@@ -105,7 +108,7 @@ describe('GitHub', function () {
var retried;
nock('https://github.com')
.get('/IndigoUnited/js-events-emitter/archive/0.1.0.tar.gz')
.get('/IndigoUnited/events-emitter/archive/0.1.0.tar.gz')
.reply(500);
logger.on('log', function (entry) {
@@ -114,7 +117,7 @@ describe('GitHub', function () {
}
});
resolver = create({ source: 'git://github.com/IndigoUnited/js-events-emitter.git', target: '0.1.0' });
resolver = create({ source: 'git://github.com/IndigoUnited/events-emitter.git', target: '0.1.0' });
// Monkey patch source to file://
resolver._source = 'file://' + testPackage;

View File

@@ -1,6 +1,6 @@
var expect = require('expect.js');
var path = require('path');
var fs = require('../../../lib/util/fs');
var fs = require('graceful-fs');
var Logger = require('bower-logger');
var helpers = require('../../helpers');
var Q = require('q');
@@ -268,7 +268,7 @@ describe('GitRemoteResolver', function () {
return function (cmd, args, options) {
expect(cmd).to.be('git');
expect(args).to.eql([ 'ls-remote', '--heads', testSource ]);
expect(options.env.GIT_CURL_VERBOSE).to.be('2');
expect(options.env.GIT_CURL_VERBOSE).to.be(2);
return Q.all(['stdout', stderr]);
};
@@ -285,7 +285,7 @@ describe('GitRemoteResolver', function () {
*/}))
);
var resolver = new MyGitRemoteResolver({ source: testSource }, defaultConfig({ shallowCloneHosts: ['foo'] }), logger);
var resolver = new MyGitRemoteResolver({ source: testSource }, defaultConfig(), logger);
resolver._shallowClone().then(function (shallowCloningSupported) {
expect(shallowCloningSupported).to.be(false);
@@ -305,7 +305,7 @@ describe('GitRemoteResolver', function () {
*/}))
);
var resolver = new MyGitRemoteResolver({ source: testSource }, defaultConfig({ shallowCloneHosts: ['foo'] }), logger);
var resolver = new MyGitRemoteResolver({ source: testSource }, defaultConfig(), logger);
resolver._shallowClone().then(function (shallowCloningSupported) {
expect(shallowCloningSupported).to.be(false);
@@ -347,7 +347,7 @@ describe('GitRemoteResolver', function () {
*/}))
);
var resolver = new MyGitRemoteResolver({ source: testSource }, defaultConfig({ shallowCloneHosts: ['foo'] }), logger);
var resolver = new MyGitRemoteResolver({ source: testSource }, defaultConfig(), logger);
resolver._shallowClone().then(function (shallowCloningSupported) {
expect(shallowCloningSupported).to.be(true);
@@ -368,7 +368,7 @@ describe('GitRemoteResolver', function () {
if (counter === 1) {
expect(cmd).to.be('git');
expect(args).to.eql([ 'ls-remote', '--heads', testSource ]);
expect(options.env.GIT_CURL_VERBOSE).to.be('2');
expect(options.env.GIT_CURL_VERBOSE).to.be(2);
return Q.all(['stdout', multiline(function () {/*
foo: bar
@@ -383,12 +383,12 @@ describe('GitRemoteResolver', function () {
}
);
var resolver = new MyGitRemoteResolver({ source: testSource }, defaultConfig({ shallowCloneHosts: ['foo'] }), logger);
var resolver = new MyGitRemoteResolver({ source: testSource }, defaultConfig(), logger);
resolver._shallowClone().then(function (shallowCloningSupported) {
expect(shallowCloningSupported).to.be(true);
var resolver2 = new MyGitRemoteResolver({ source: testSource }, defaultConfig({ shallowCloneHosts: ['foo'] }), logger);
var resolver2 = new MyGitRemoteResolver({ source: testSource }, defaultConfig(), logger);
resolver2._shallowClone().then(function (shallowCloningSupported) {
expect(shallowCloningSupported).to.be(true);
@@ -413,7 +413,7 @@ describe('GitRemoteResolver', function () {
if (counter === 1) {
expect(cmd).to.be('git');
expect(args).to.eql([ 'ls-remote', '--heads', testSource1 ]);
expect(options.env.GIT_CURL_VERBOSE).to.be('2');
expect(options.env.GIT_CURL_VERBOSE).to.be(2);
return Q.all(['stdout', multiline(function () {/*
foo: bar
@@ -428,12 +428,12 @@ describe('GitRemoteResolver', function () {
}
);
var resolver = new MyGitRemoteResolver({ source: testSource1 }, defaultConfig({ shallowCloneHosts: ['foo'] }), logger);
var resolver = new MyGitRemoteResolver({ source: testSource1 }, defaultConfig(), logger);
resolver._shallowClone().then(function (shallowCloningSupported) {
expect(shallowCloningSupported).to.be(true);
var resolver2 = new MyGitRemoteResolver({ source: testSource2 }, defaultConfig({ shallowCloneHosts: ['foo'] }), logger);
var resolver2 = new MyGitRemoteResolver({ source: testSource2 }, defaultConfig(), logger);
resolver2._shallowClone().then(function (shallowCloningSupported) {
expect(shallowCloningSupported).to.be(true);
@@ -458,7 +458,7 @@ describe('GitRemoteResolver', function () {
if (counter === 1) {
expect(cmd).to.be('git');
expect(args).to.eql([ 'ls-remote', '--heads', testSource1 ]);
expect(options.env.GIT_CURL_VERBOSE).to.be('2');
expect(options.env.GIT_CURL_VERBOSE).to.be(2);
return Q.all(['stdout', multiline(function () {/*
foo: bar
@@ -470,7 +470,7 @@ describe('GitRemoteResolver', function () {
else {
expect(cmd).to.be('git');
expect(args).to.eql([ 'ls-remote', '--heads', testSource2 ]);
expect(options.env.GIT_CURL_VERBOSE).to.be('2');
expect(options.env.GIT_CURL_VERBOSE).to.be(2);
return Q.all(['stdout', multiline(function () {/*
foo: barbaz
@@ -482,12 +482,12 @@ describe('GitRemoteResolver', function () {
}
);
var resolver = new MyGitRemoteResolver({ source: testSource1 }, defaultConfig({ shallowCloneHosts: ['foo', 'foo.bar.baz'] }), logger);
var resolver = new MyGitRemoteResolver({ source: testSource1 }, defaultConfig(), logger);
resolver._shallowClone().then(function (shallowCloningSupported) {
expect(shallowCloningSupported).to.be(true);
var resolver2 = new MyGitRemoteResolver({ source: testSource2 }, defaultConfig({ shallowCloneHosts: ['foo', 'foo.bar.baz'] }), logger);
var resolver2 = new MyGitRemoteResolver({ source: testSource2 }, defaultConfig(), logger);
resolver2._shallowClone().then(function (shallowCloningSupported) {
expect(shallowCloningSupported).to.be(true);

View File

@@ -1,9 +1,9 @@
var expect = require('expect.js');
var util = require('util');
var path = require('path');
var fs = require('../../../lib/util/fs');
var fs = require('graceful-fs');
var chmodr = require('chmodr');
var rimraf = require('../../../lib/util/rimraf');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var Q = require('q');
var mout = require('mout');
@@ -61,7 +61,7 @@ describe('GitResolver', function () {
it('should be true when the resolution type is different', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '0.0.0',
_resolution: {
@@ -69,8 +69,7 @@ describe('GitResolver', function () {
tag: '0.0.0',
commit: 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
}
};
}));
GitResolver.refs = function () {
return Q.resolve([
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb refs/heads/master' // same commit hash on purpose
@@ -78,7 +77,7 @@ describe('GitResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -89,7 +88,7 @@ describe('GitResolver', function () {
it('should be true when a higher version for a range is available', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '1.0.0',
_resolution: {
@@ -97,8 +96,7 @@ describe('GitResolver', function () {
tag: '1.0.0',
commit: 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
}
};
}));
GitResolver.refs = function () {
return Q.resolve([
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa refs/heads/master',
@@ -108,7 +106,7 @@ describe('GitResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -119,7 +117,7 @@ describe('GitResolver', function () {
it('should be true when a resolved to a lower version of a range', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '1.0.1',
_resolution: {
@@ -127,8 +125,7 @@ describe('GitResolver', function () {
tag: '1.0.1',
commit: 'cccccccccccccccccccccccccccccccccccccccc'
}
};
}));
GitResolver.refs = function () {
return Q.resolve([
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa refs/heads/master',
@@ -137,7 +134,7 @@ describe('GitResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -148,7 +145,7 @@ describe('GitResolver', function () {
it('should be false when resolved to the same tag (with same commit hash) for a given range', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '1.0.1',
_resolution: {
@@ -156,8 +153,7 @@ describe('GitResolver', function () {
tag: '1.0.1',
commit: 'cccccccccccccccccccccccccccccccccccccccc'
}
};
}));
GitResolver.refs = function () {
return Q.resolve([
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa refs/heads/master',
@@ -167,7 +163,7 @@ describe('GitResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(false);
next();
@@ -178,7 +174,7 @@ describe('GitResolver', function () {
it('should be true when resolved to the same tag (with different commit hash) for a given range', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '1.0.1',
_resolution: {
@@ -186,8 +182,7 @@ describe('GitResolver', function () {
tag: '1.0.1',
commit: 'cccccccccccccccccccccccccccccccccccccccc'
}
};
}));
GitResolver.refs = function () {
return Q.resolve([
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa refs/heads/master',
@@ -197,7 +192,7 @@ describe('GitResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -208,15 +203,14 @@ describe('GitResolver', function () {
it('should be true when a different commit hash for a given branch is available', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
_resolution: {
type: 'branch',
branch: 'master',
commit: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
}
};
}));
GitResolver.refs = function () {
return Q.resolve([
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb refs/heads/master'
@@ -224,7 +218,7 @@ describe('GitResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -235,15 +229,14 @@ describe('GitResolver', function () {
it('should be false when resolved to the the same commit hash for a given branch', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
_resolution: {
type: 'branch',
branch: 'master',
commit: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
}
};
}));
GitResolver.refs = function () {
return Q.resolve([
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa refs/heads/master'
@@ -251,7 +244,7 @@ describe('GitResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(false);
next();
@@ -262,14 +255,13 @@ describe('GitResolver', function () {
it('should be false when targeting commit hashes', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
_resolution: {
type: 'commit',
commit: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
}
};
}));
GitResolver.refs = function () {
return Q.resolve([
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb refs/heads/master'
@@ -277,7 +269,7 @@ describe('GitResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -706,7 +698,7 @@ describe('GitResolver', function () {
}, function (err) {
expect(err).to.be.an(Error);
expect(err.message).to.match(/was able to satisfy ~0.2.0/i);
expect(err.details).to.match(/available versions in foo: 0\.1\.1, 0\.1\.0/i);
expect(err.details).to.match(/available versions: 0\.1\.1, 0\.1\.0/i);
expect(err.code).to.equal('ENORESTARGET');
next();
})

View File

@@ -1,8 +1,8 @@
var expect = require('expect.js');
var fs = require('../../../lib/util/fs');
var fs = require('graceful-fs');
var path = require('path');
var util = require('util');
var rimraf = require('../../../lib/util/rimraf');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var tmp = require('tmp');
var Q = require('q');
@@ -115,7 +115,7 @@ describe('Resolver', function () {
})
.done();
resolver.hasNew({})
resolver.hasNew(tempDir)
.then(function () {
succeeded = true;
}, function (err) {
@@ -129,17 +129,17 @@ describe('Resolver', function () {
var resolver = create('foo');
var succeeded;
resolver.hasNew({})
resolver.hasNew(tempDir)
.then(function () {
// Test if hasNew can be called again when done
resolver.hasNew({})
resolver.hasNew(tempDir)
.then(function () {
next(succeeded ? new Error('Should have failed') : null);
});
})
.done();
resolver.hasNew({})
resolver.hasNew(tempDir)
.then(function () {
succeeded = true;
}, function (err) {
@@ -152,7 +152,7 @@ describe('Resolver', function () {
it('should resolve to true by default', function (next) {
var resolver = create('foo');
resolver.hasNew({})
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.equal(true);
next();
@@ -160,17 +160,32 @@ describe('Resolver', function () {
.done();
});
it('should call _hasNew with the package meta', function (next) {
it('should resolve to true if the there\'s an error reading the package meta', function (next) {
var resolver = create('foo');
rimraf.sync(path.join(tempDir, '.bower.json'));
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.equal(true);
next();
})
.done();
});
it('should call _hasNew with the canonical dir and the package meta', function (next) {
var resolver = create('foo');
var canonical;
var meta;
resolver._hasNew = function (pkgMeta) {
resolver._hasNew = function (canonicalDir, pkgMeta) {
canonical = canonicalDir;
meta = pkgMeta;
return Q.resolve(true);
};
resolver.hasNew({ name: 'test' })
resolver.hasNew(tempDir)
.then(function () {
expect(canonical).to.equal(tempDir);
expect(meta).to.be.an('object');
expect(meta.name).to.equal('test');
next();
@@ -182,12 +197,12 @@ describe('Resolver', function () {
var resolver = create('foo');
var meta;
resolver._hasNew = function (pkgMeta) {
resolver._hasNew = function (canonicalDir, pkgMeta) {
meta = pkgMeta;
return Q.resolve(true);
};
resolver.hasNew({
resolver.hasNew(tempDir, {
name: 'foo'
})
.then(function () {
@@ -246,10 +261,10 @@ describe('Resolver', function () {
resolver._resolve = function () {};
resolver.hasNew({})
resolver.hasNew(tempDir)
.then(function () {
// Test if hasNew can be called again when done
resolver.hasNew({})
resolver.hasNew(tempDir)
.then(function () {
next(succeeded ? new Error('Should have failed') : null);
});
@@ -515,18 +530,6 @@ describe('Resolver', function () {
})
.done();
});
it('should remove @ from directory names', function (next) {
var resolver = create('foo@bar');
resolver._createTempDir()
.then(function (dir) {
expect(resolver._tempDir).to.be.ok();
expect(resolver._tempDir.indexOf('@')).to.equal(-1);
next();
})
.done();
});
});
describe('._cleanTempDir', function () {

View File

@@ -1,8 +1,8 @@
var expect = require('expect.js');
var util = require('util');
var path = require('path');
var fs = require('../../../lib/util/fs');
var rimraf = require('../../../lib/util/rimraf');
var fs = require('graceful-fs');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var Q = require('q');
var mout = require('mout');
@@ -63,7 +63,7 @@ else describe('SvnResolver', function () {
it('should be true when the resolution type is different', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '0.0.0',
_resolution: {
@@ -71,7 +71,7 @@ else describe('SvnResolver', function () {
tag: '0.0.0',
commit: 123
}
};
}));
SvnResolver.tags = function () {
return Q.resolve({
@@ -86,7 +86,7 @@ else describe('SvnResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -97,7 +97,7 @@ else describe('SvnResolver', function () {
it('should be true when a higher version for a range is available', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '1.0.0',
_resolution: {
@@ -105,7 +105,7 @@ else describe('SvnResolver', function () {
tag: '1.0.0',
commit: 3
}
};
}));
SvnResolver.tags = function () {
return Q.resolve({
@@ -115,7 +115,7 @@ else describe('SvnResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -126,7 +126,7 @@ else describe('SvnResolver', function () {
it('should be true when a resolved to a lower version of a range', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '1.0.1',
_resolution: {
@@ -134,8 +134,7 @@ else describe('SvnResolver', function () {
tag: '1.0.1',
commit: 3
}
};
}));
SvnResolver.tags = function () {
return Q.resolve({
'1.0.0': 2
@@ -143,7 +142,7 @@ else describe('SvnResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -154,7 +153,7 @@ else describe('SvnResolver', function () {
it('should be false when resolved to the same tag (with same commit hash) for a given range', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '1.0.1',
_resolution: {
@@ -162,8 +161,7 @@ else describe('SvnResolver', function () {
tag: '1.0.1',
commit: 2
}
};
}));
SvnResolver.tags = function () {
return Q.resolve({
'1.0.0': 1,
@@ -172,7 +170,7 @@ else describe('SvnResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(false);
next();
@@ -183,7 +181,7 @@ else describe('SvnResolver', function () {
it('should be true when resolved to the same tag (with different commit hash) for a given range', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '1.0.1',
_resolution: {
@@ -191,8 +189,7 @@ else describe('SvnResolver', function () {
tag: '1.0.1',
commit: 3
}
};
}));
SvnResolver.tags = function () {
return Q.resolve({
'1.0.0': 2,
@@ -201,7 +198,7 @@ else describe('SvnResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -213,14 +210,13 @@ else describe('SvnResolver', function () {
it('should be false when targeting commit hashes', function (next) {
var resolver;
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
_resolution: {
type: 'commit',
commit: 1
}
};
}));
SvnResolver.tags = function () {
return Q.resolve({
'1.0.0': 2
@@ -228,7 +224,7 @@ else describe('SvnResolver', function () {
};
resolver = create('foo');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -503,7 +499,7 @@ else describe('SvnResolver', function () {
}, function (err) {
expect(err).to.be.an(Error);
expect(err.message).to.match(/was able to satisfy ~0.2.0/i);
expect(err.details).to.match(/available versions in foo: 0\.1\.1, 0\.1\.0/i);
expect(err.details).to.match(/available versions: 0\.1\.1, 0\.1\.0/i);
expect(err.code).to.equal('ENORESTARGET');
next();
})

View File

@@ -1,9 +1,9 @@
var expect = require('expect.js');
var path = require('path');
var fs = require('../../../lib/util/fs');
var fs = require('graceful-fs');
var nock = require('nock');
var Q = require('q');
var rimraf = require('../../../lib/util/rimraf');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var Logger = require('bower-logger');
var cmd = require('../../../lib/util/cmd');
@@ -25,6 +25,9 @@ describe('UrlResolver', function () {
afterEach(function () {
logger.removeAllListeners();
// Clean nocks
nock.cleanAll();
});
function create(decEndpoint) {
@@ -90,12 +93,12 @@ describe('UrlResolver', function () {
.head('/foo.js')
.reply(500);
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '0.0.0'
};
}));
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -113,16 +116,16 @@ describe('UrlResolver', function () {
'Last-Modified': 'Tue, 15 Nov 2012 12:45:26 GMT'
});
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '0.0.0',
_cacheHeaders: {
'ETag': 'fk3454fdmmlw20i9nf',
'Last-Modified': 'Tue, 16 Nov 2012 13:35:29 GMT'
}
};
}));
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(true);
next();
@@ -140,16 +143,16 @@ describe('UrlResolver', function () {
'Last-Modified': 'Tue, 15 Nov 2012 12:45:26 GMT'
});
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '0.0.0',
_cacheHeaders: {
'ETag': '686897696a7c876b7e',
'Last-Modified': 'Tue, 15 Nov 2012 12:45:26 GMT'
}
};
}));
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(false);
next();
@@ -168,16 +171,16 @@ describe('UrlResolver', function () {
'Last-Modified': 'Tue, 15 Nov 2012 12:45:26 GMT'
});
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '0.0.0',
_cacheHeaders: {
'ETag': '686897696a7c876b7e',
'Last-Modified': 'Tue, 15 Nov 2012 12:45:26 GMT'
}
};
}));
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(false);
next();
@@ -202,18 +205,18 @@ describe('UrlResolver', function () {
});
var pkgMeta = {
fs.writeFileSync(path.join(tempDir, '.bower.json'), JSON.stringify({
name: 'foo',
version: '0.0.0',
_cacheHeaders: {
'ETag': '686897696a7c876b7e',
'Last-Modified': 'Tue, 15 Nov 2012 12:45:26 GMT'
}
};
}));
resolver = create(redirectingUrl + '/foo.js');
resolver.hasNew(pkgMeta)
resolver.hasNew(tempDir)
.then(function (hasNew) {
expect(hasNew).to.be(false);
next();

View File

@@ -1,8 +1,8 @@
var path = require('path');
var bower = require('../../lib/index.js');
var mkdirp = require('mkdirp');
var rimraf = require('../../lib/util/rimraf');
var fs = require('../../lib/util/fs');
var rimraf = require('rimraf');
var fs = require('fs');
var expect = require('expect.js');
var scripts = require('../../lib/core/scripts.js');
@@ -14,12 +14,12 @@ describe('scripts', function () {
// We cannot use pure touch, because Windows
var touch = function (file) {
return 'node -e "var fs = require(\'fs\'); fs.closeSync(fs.openSync(\'' + file + '\', \'w\'));"';
return 'node -e "var fs = require(\'fs\'); fs.closeSync(fs.openSync(\'' + file + '\', \'w\'));"';
};
// We cannot use pure touch, because Windows
var touchWithPid = function (file) {
return 'node -e "var fs = require(\'fs\'); fs.closeSync(fs.openSync(process.env.BOWER_PID + \'' + file + '\', \'w\'));"';
return 'node -e "var fs = require(\'fs\'); fs.closeSync(fs.openSync(process.env.BOWER_PID + \'' + file + '\', \'w\'));"';
};
var config = {

View File

@@ -3,17 +3,17 @@ require('chalk').enabled = false;
var Q = require('q');
var path = require('path');
var mkdirp = require('mkdirp');
var rimraf = require('../lib/util/rimraf');
var rimraf = require('rimraf');
var uuid = require('node-uuid');
var object = require('mout/object');
var fs = require('../lib/util/fs');
var fs = require('fs');
var glob = require('glob');
var os = require('os');
var which = require('which');
var path = require('path');
var proxyquire = require('proxyquire').noCallThru().noPreserveCache();
var spawnSync = require('spawn-sync');
var config = require('../lib/config');
var nock = require('nock');
// For better promise errors
Q.longStackSupport = true;
@@ -26,7 +26,6 @@ var env = {
'GIT_COMMITTER_DATE': 'Sun Apr 7 22:13:13 2013 +0000',
'GIT_COMMITTER_NAME': 'André Cruz',
'GIT_COMMITTER_EMAIL': 'amdfcruz@gmail.com',
'NODE_ENV': 'test'
};
object.mixIn(process.env, env);
@@ -162,7 +161,7 @@ exports.TempDir = (function() {
return TempDir;
})();
exports.expectEvent = function expectEvent (emitter, eventName) {
exports.expectEvent = function expectEvent(emitter, eventName) {
var deferred = Q.defer();
emitter.once(eventName, function () {
@@ -298,16 +297,3 @@ exports.localUrl = function (localPath) {
return localPath;
};
// Returns the result of executing the bower binary + args
// example: runBin('install') --> $ bower install
exports.runBin = function (args) {
args = args || [];
args.unshift(path.resolve(__dirname, '../bin/bower'));
return spawnSync('node', args);
};
afterEach(function () {
nock.cleanAll();
});

View File

@@ -1,9 +1,9 @@
var fs = require('../lib/util/fs');
var fs = require('graceful-fs');
var path = require('path');
var Q = require('q');
var semver = require('semver');
var mout = require('mout');
var rimraf = require('../lib/util/rimraf');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var chalk = require('chalk');
var cmd = require('../lib/util/cmd');

View File

@@ -1,9 +1,9 @@
var fs = require('../lib/util/fs');
var fs = require('graceful-fs');
var path = require('path');
var Q = require('q');
var semver = require('semver');
var mout = require('mout');
var rimraf = require('../lib/util/rimraf');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var chalk = require('chalk');
var cmd = require('../lib/util/cmd');

View File

@@ -27,7 +27,7 @@ describe('JsonRenderer', function () {
renderer.end();
}).spread(function(stdout, stderr) {
expect(stderr).to.eq(normalize(multiline(function() {/*
expect(stderr).to.eq(normalize(multiline(function(){/*
[{
"id": "foobar",
"message": "hello world"
@@ -52,7 +52,7 @@ describe('JsonRenderer', function () {
]
});
}).spread(function(stdout, stderr) {
expect(stderr).to.eq(normalize(multiline(function() {/*
expect(stderr).to.eq(normalize(multiline(function(){/*
[{
"id": "error",
"data": {
@@ -89,7 +89,7 @@ describe('JsonRenderer', function () {
renderer.end();
});
}).spread(function(stdout, stderr) {
expect(stderr).to.eq(normalize(multiline(function() {/*
expect(stderr).to.eq(normalize(multiline(function(){/*
[{
"type": "input",
"name": "field",

View File

@@ -17,7 +17,7 @@ describe('StandardRenderer', function () {
message: 'hello world'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.eq(multiline(function() {/*
expect(stdout).to.eq(multiline(function(){/*
bower foobar hello world
*/}));
@@ -32,7 +32,7 @@ describe('StandardRenderer', function () {
message: 'Hello error'
});
}).spread(function(stdout, stderr) {
expect(stderr).to.eq(multiline(function() {/*
expect(stderr).to.eq(multiline(function(){/*
bower EFOOBAR Hello error
*/}));
@@ -48,7 +48,7 @@ describe('StandardRenderer', function () {
details: ' Some awesome details\nMultiline! '
});
}).spread(function(stdout, stderr) {
expect(stderr).to.eq(multiline(function() {/*
expect(stderr).to.eq(multiline(function(){/*
bower EFOOBAR Hello error
Additional error details:
@@ -68,7 +68,7 @@ describe('StandardRenderer', function () {
details: ' Some awesome details\nMultiline! '
});
}).spread(function(stdout, stderr) {
expect(stderr).to.match(new RegExp(multiline(function() {/*
expect(stderr).to.match(new RegExp(multiline(function(){/*
System info:
Bower version: [^\r\n]+
Node version: [^\r\n]+
@@ -91,7 +91,7 @@ describe('StandardRenderer', function () {
]
});
}).spread(function(stdout, stderr) {
expect(stderr).to.string(multiline(function() {/*
expect(stderr).to.string(multiline(function(){/*
Stack trace:
./one.js:1
./two.js:2
@@ -109,7 +109,7 @@ describe('StandardRenderer', function () {
details: ' Some awesome details\nMultiline! '
});
}).spread(function(stdout, stderr) {
expect(stderr).to.match(new RegExp(multiline(function() {/*
expect(stderr).to.match(new RegExp(multiline(function(){/*
Console trace:
Error
at StandardRenderer.error \(.+?\)
@@ -127,7 +127,7 @@ describe('StandardRenderer', function () {
message: 'foobar'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
bower checkout jquery#foobar
*/}));
@@ -143,7 +143,7 @@ describe('StandardRenderer', function () {
message: 'foobar'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
bower jquery#master progress foobar
*/}));
@@ -159,7 +159,7 @@ describe('StandardRenderer', function () {
message: 'foobar'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
bower progress jquery#master foobar
*/}));
@@ -175,7 +175,7 @@ describe('StandardRenderer', function () {
message: 'foobar'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
bower jquery#master extract foobar
*/}));
@@ -244,7 +244,7 @@ describe('StandardRenderer', function () {
}
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
Please note that,
dependant1#release1, dependant2#release2 depends on fizfuz#~0.0.0 which resolved to fizfuz#0.0.0
@@ -311,7 +311,7 @@ describe('StandardRenderer', function () {
}
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
Unable to find a suitable version for , please choose one:
1) fizfuz#~0.0.0 which resolved to 0.0.0 and is required by dependant1#release1, dependant2#release2
@@ -339,7 +339,7 @@ describe('StandardRenderer', function () {
}
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
{
foo: 'bar',
@@ -362,7 +362,7 @@ describe('StandardRenderer', function () {
message: 'message'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
bower origin cached message
*/}));
@@ -390,7 +390,7 @@ describe('StandardRenderer', function () {
message: 'message'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
bower short-origin generic message
bower very-very-long-origin-string generic message
bower short-origin generic message
@@ -534,7 +534,7 @@ describe('StandardRenderer', function () {
]);
}).spread(function(stdout, stderr) {
if (helpers.isWin()) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
jquery#0.1.2 components\jquery
@@ -558,7 +558,7 @@ describe('StandardRenderer', function () {
*/}));
} else {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
jquery#0.1.2 components/jquery
@@ -592,7 +592,7 @@ describe('StandardRenderer', function () {
version: '1.2.3'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
{
version: '1.2.3'
@@ -617,7 +617,7 @@ describe('StandardRenderer', function () {
]
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
{
version: '1.2.3'
@@ -644,7 +644,7 @@ describe('StandardRenderer', function () {
name: 'bower'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
bower http://bower.io
Package not found.
@@ -670,14 +670,14 @@ describe('StandardRenderer', function () {
});
}).spread(function(stdout, stderr) {
if (helpers.isWin()) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
bower link ./bar > ./foo
jquery#0.1.2 components\jquery
*/}));
} else {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
bower link ./bar > ./foo
jquery#0.1.2 components/jquery
@@ -701,7 +701,7 @@ describe('StandardRenderer', function () {
}
]);
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
Search results:
jquery http://jquery.io
@@ -719,7 +719,7 @@ describe('StandardRenderer', function () {
url: 'http://jquery.io'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
Package jquery registered successfully!
All valid semver tags on http://jquery.io will be available as versions.
@@ -744,7 +744,7 @@ describe('StandardRenderer', function () {
}
]);
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
awesome-jquery=jquery#0.1.1
*/}));
@@ -779,7 +779,7 @@ describe('StandardRenderer', function () {
]
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
expect(stdout).to.equal(multiline(function(){/*
Usage:

View File

@@ -10,9 +10,6 @@ describe('analytics', function () {
return object.merge(stubs || {}, {
askPermission: function (message, callback) {
callback(undefined, promptResponse);
},
config: {
clear: function () {}
}
});
}
@@ -20,15 +17,6 @@ describe('analytics', function () {
};
describe('#setup', function () {
// Reset process.env.CI after tests are done
var oldCI;
beforeEach(function () {
oldCI = process.env.CI;
});
afterEach(function () {
process.env.CI = oldCI;
});
it('leaves analytics enabled if provided', function () {
return mockAnalytics()
.setup({ analytics: true })
@@ -92,40 +80,6 @@ describe('analytics', function () {
expect(enabled).to.be(false);
});
});
it('disables if process.env.CI is true', function () {
process.env.CI = true;
// Clear cache set by proxyquire
delete require.cache[require.resolve('../../lib/util/analytics')];
var analytics = require('../../lib/util/analytics');
return analytics.setup({ interactive: true })
.then(function (enabled) {
expect(enabled).to.be(false);
});
});
it('disables if prompt times out', function () {
// Create mock insight with very low permission timeout
var Insight = require('insight');
var mockInsight = new Insight({
trackingCode: 'mock',
pkg: require('../../package.json')
});
mockInsight._permissionTimeout = 0.1;
var mockAnalyticsWithInsight = proxyquire('../../lib/util/analytics', {
insight: function () {
return mockInsight;
}
});
return mockAnalyticsWithInsight
.setup({ interactive: true })
.then(function (enabled) {
expect(enabled).to.be(false);
});
});
});
describe('Tracker', function (next) {

View File

@@ -1,177 +0,0 @@
var expect = require('expect.js');
var helpers = require('../helpers');
var nock = require('nock');
var path = require('path');
var Q = require('q');
var fs = require('../../lib/util/fs');
var download = require('../../lib/util/download');
describe('download', function () {
var tempDir = new helpers.TempDir(),
source = path.resolve(__dirname, '../assets/package-tar.tar.gz'),
destination = tempDir.getPath('package.tar.gz');
function downloadTest(opts) {
var deferred = Q.defer();
tempDir.prepare();
opts.response(
nock('http://bower.io', opts.nockOpts)
);
download('http://bower.io/package.tar.gz', destination, opts.downloadOpts)
.then(function (result) {
if (opts.expect) {
opts.expect(result);
deferred.resolve();
} else {
deferred.reject(new Error('Error expected. Got successful response.'));
}
}, function (error) {
if (opts.expectError) {
opts.expectError(error);
deferred.resolve();
} else {
deferred.reject(error);
}
})
.done();
return deferred.promise;
}
it('download file to directory', function () {
return downloadTest({
response: function (nock) {
nock.get('/package.tar.gz').replyWithFile(200, source);
},
expect: function () {
expect(fs.existsSync(destination)).to.be(true);
expect(fs.readdirSync(tempDir.path)).to.have.length(1);
}
});
});
it('pass custom user-agent to server', function () {
var userAgent = 'Custom User-Agent';
return downloadTest({
nockOpts: {
reqheaders: {
'user-agent': userAgent
}
},
downloadOpts: {
headers: {
'User-Agent': userAgent
}
},
response: function (nock) {
nock.get('/package.tar.gz').replyWithFile(200, source);
},
expect: function () {
expect(fs.existsSync(destination)).to.be(true);
expect(fs.readdirSync(tempDir.path)).to.have.length(1);
}
});
});
it('handle server response 404', function () {
return downloadTest({
response: function (nock) {
nock.get('/package.tar.gz').reply(404);
},
expectError: function () {
expect(fs.readdirSync(tempDir.path)).to.be.empty();
}
});
});
it('handle network error', function () {
return downloadTest({
response: function (nock) {
nock.get('/package.tar.gz').replyWithError('network error');
},
expectError: function () {
expect(fs.readdirSync(tempDir.path)).to.be.empty();
}
});
});
it('handles connection timeout', function () {
return downloadTest({
response: function (nock) {
// First connection + 5 retries
nock.get('/package.tar.gz').times(6).delayConnection(1000).replyWithFile(200, source);
},
expectError: function (e) {
expect(e.code).to.be('ETIMEDOUT');
expect(fs.readdirSync(tempDir.path)).to.be.empty();
},
downloadOpts: {
timeout: 10,
maxTimeout: 0,
minTimeout: 0
}
});
});
it('handles socket timeout', function () {
return downloadTest({
response: function (nock) {
// First connection + 5 retries
nock.get('/package.tar.gz').times(6).socketDelay(1000).replyWithFile(200, source);
},
expectError: function (e) {
expect(e.code).to.be('ESOCKETTIMEDOUT');
expect(fs.readdirSync(tempDir.path)).to.be.empty();
},
downloadOpts: {
timeout: 10,
maxTimeout: 0,
minTimeout: 0
}
});
});
it('handles retries correctly', function () {
return downloadTest({
response: function (nock) {
// First connection + 5 retries
nock.get('/package.tar.gz').times(5).delayConnection(1000).replyWithFile(200, source);
// Success last time
nock.get('/package.tar.gz').replyWithFile(200, source);
},
expect: function () {
expect(fs.existsSync(destination)).to.be(true);
expect(fs.readdirSync(tempDir.path)).to.have.length(1);
},
downloadOpts: {
timeout: 10,
maxTimeout: 0,
minTimeout: 0
}
});
});
it('fails on incorrect Content-Length match', function () {
return downloadTest({
response: function (nock) {
// First connection + 5 retries
nock.get('/package.tar.gz').replyWithFile(200, source, { 'Content-Length': 5000 });
},
expectError: function (e) {
expect(e.code).to.be('EINCOMPLETE');
expect(e.message).to.be('Transfer closed with 4636 bytes remaining to read');
},
downloadOpts: {
timeout: 10,
maxTimeout: 0,
minTimeout: 0
}
});
});
});

View File

@@ -1,5 +1,4 @@
describe('util', function () {
require('./removeIgnores');
require('./analytics');
require('./download');
});