mirror of
https://github.com/bower/bower.git
synced 2026-04-24 03:00:19 -04:00
Compare commits
137 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87cf578ba8 | ||
|
|
3ead440c7c | ||
|
|
e168c894a2 | ||
|
|
75e3661371 | ||
|
|
baf8f7bf6b | ||
|
|
88758cd98c | ||
|
|
3bd2d62e67 | ||
|
|
d3eef5772a | ||
|
|
7c714901d4 | ||
|
|
7792b6d35d | ||
|
|
2db983dba3 | ||
|
|
b9718bb309 | ||
|
|
26f609e614 | ||
|
|
4c2b56096b | ||
|
|
5af929f0be | ||
|
|
686e883d87 | ||
|
|
f2767648e7 | ||
|
|
9e4bdd270d | ||
|
|
7cb88ab49f | ||
|
|
a532c55dca | ||
|
|
c559432c19 | ||
|
|
322c49edf4 | ||
|
|
fe9b27a647 | ||
|
|
1605374a25 | ||
|
|
ac244a1400 | ||
|
|
d50e50f3b5 | ||
|
|
3030469c59 | ||
|
|
977e0ddc52 | ||
|
|
de3e1089da | ||
|
|
7897ad7dba | ||
|
|
accdab3ece | ||
|
|
612aaa88eb | ||
|
|
338ac99080 | ||
|
|
9605bbea5f | ||
|
|
3791aee9d6 | ||
|
|
20a223a959 | ||
|
|
ea5bd51327 | ||
|
|
b94c20b8da | ||
|
|
b81ba140e3 | ||
|
|
4ffdb500b9 | ||
|
|
1696cde273 | ||
|
|
94ffc35b25 | ||
|
|
5a1e5eb9c7 | ||
|
|
8c1f30b1c8 | ||
|
|
e3f402fc66 | ||
|
|
6616d09f47 | ||
|
|
25ad2ef946 | ||
|
|
ba4a1a9d45 | ||
|
|
3a37202dc5 | ||
|
|
12258324d3 | ||
|
|
2adb0b0807 | ||
|
|
19fc84007d | ||
|
|
8fcbd3671d | ||
|
|
0eadbef02d | ||
|
|
107ad1d3fc | ||
|
|
d2ba80e6e9 | ||
|
|
852a586d5c | ||
|
|
e8a2d92785 | ||
|
|
50ed13e4ee | ||
|
|
cb9b737b9d | ||
|
|
700b46162c | ||
|
|
0e1153f610 | ||
|
|
8669ed2aac | ||
|
|
ca0a36abcf | ||
|
|
4c6fdc905f | ||
|
|
cdbc4a123c | ||
|
|
bb7c02b07b | ||
|
|
4f42aeabd7 | ||
|
|
b77517ef64 | ||
|
|
b9c3f750eb | ||
|
|
aaecbfab17 | ||
|
|
c4539aa603 | ||
|
|
7f801319bf | ||
|
|
1a990f4563 | ||
|
|
944a328f30 | ||
|
|
e11b60d812 | ||
|
|
c91e99b782 | ||
|
|
da8ec1e4ab | ||
|
|
e7868f0fb1 | ||
|
|
eca46dbd85 | ||
|
|
67bd5d026f | ||
|
|
51de67cc73 | ||
|
|
3d4f9cd919 | ||
|
|
2f72cd4b7d | ||
|
|
2ff53fc448 | ||
|
|
42cd2e584f | ||
|
|
49de3cca62 | ||
|
|
718db0309f | ||
|
|
89286e628b | ||
|
|
c8042b4781 | ||
|
|
9fdd96c92b | ||
|
|
ce15df27ca | ||
|
|
468657bfe2 | ||
|
|
814180d129 | ||
|
|
93be2fef6d | ||
|
|
3ab71f27ff | ||
|
|
38fa1b6858 | ||
|
|
c6ed215260 | ||
|
|
74eba8d2e8 | ||
|
|
5a72dae2c8 | ||
|
|
6194821643 | ||
|
|
37aab9c72e | ||
|
|
0a0dc8cef9 | ||
|
|
c6d89b79b4 | ||
|
|
8a435dff27 | ||
|
|
459925eba7 | ||
|
|
6614a43658 | ||
|
|
88fd65ae34 | ||
|
|
83da088024 | ||
|
|
51a986d0d4 | ||
|
|
0aefe8fc0e | ||
|
|
2845984169 | ||
|
|
2a91dc5fb1 | ||
|
|
5eca9274ee | ||
|
|
d57d81ca85 | ||
|
|
a5dcf9cc24 | ||
|
|
484c8985ed | ||
|
|
931b0a8905 | ||
|
|
bfd1e93325 | ||
|
|
bf23751549 | ||
|
|
b79034fbb9 | ||
|
|
eaa05ac6c1 | ||
|
|
8f0a3d727e | ||
|
|
b6a524e6b4 | ||
|
|
43d00deb88 | ||
|
|
4836a0cae9 | ||
|
|
302c4ade51 | ||
|
|
75d80e014a | ||
|
|
0f790f4293 | ||
|
|
452217e9fa | ||
|
|
f66c0cfe5c | ||
|
|
30898c13d3 | ||
|
|
2330d59ffa | ||
|
|
1316be57dc | ||
|
|
ff0f2a8f83 | ||
|
|
7e5184d342 | ||
|
|
8fa1fd55e9 |
45
.eslintrc
Normal file
45
.eslintrc
Normal file
@@ -0,0 +1,45 @@
|
||||
env:
|
||||
node: true
|
||||
|
||||
# enable ECMAScript features
|
||||
ecmaFeatures:
|
||||
arrowFunctions: true
|
||||
binaryLiterals: true
|
||||
blockBindings: true
|
||||
classes: true
|
||||
forOf: true
|
||||
generators: true
|
||||
objectLiteralShorthandMethods: true
|
||||
objectLiteralShorthandProperties: true
|
||||
octalLiterals: true
|
||||
templateStrings: true
|
||||
|
||||
rules:
|
||||
no-debugger: 2
|
||||
no-dupe-args: 2
|
||||
no-dupe-keys: 2
|
||||
no-duplicate-case: 2
|
||||
no-ex-assign: 2
|
||||
no-reserved-keys: 2
|
||||
no-unreachable: 2
|
||||
valid-typeof: 2
|
||||
no-fallthrough: 2
|
||||
quotes: [2, "single", "avoid-escape"]
|
||||
indent: [2, 2]
|
||||
comma-spacing: 2
|
||||
semi: 2
|
||||
space-infix-ops: 2
|
||||
space-return-throw-case: 2
|
||||
space-before-function-paren: [2, "never"]
|
||||
space-before-blocks: [2, "always"]
|
||||
new-parens: 2
|
||||
max-len: [2, 80, 2]
|
||||
no-multiple-empty-lines: [2, {max: 2}]
|
||||
eol-last: 2
|
||||
no-trailing-spaces: 2
|
||||
space-after-keywords: 2
|
||||
|
||||
# ECMAScript 6
|
||||
prefer-const: 2
|
||||
strict: [2, "global"]
|
||||
no-undef: 2
|
||||
27
.jscsrc
Normal file
27
.jscsrc
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
'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
|
||||
}
|
||||
}
|
||||
12
.jshintrc
12
.jshintrc
@@ -9,7 +9,6 @@
|
||||
"beforeEach"
|
||||
],
|
||||
|
||||
"indent": 4,
|
||||
"node": true,
|
||||
"devel": true,
|
||||
|
||||
@@ -17,26 +16,19 @@
|
||||
"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,
|
||||
@@ -44,16 +36,12 @@
|
||||
"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,
|
||||
|
||||
|
||||
@@ -3,10 +3,14 @@ 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
|
||||
|
||||
81
CHANGELOG.md
81
CHANGELOG.md
@@ -1,5 +1,77 @@
|
||||
# Changelog
|
||||
|
||||
## 1.7.1 - 2015-12-11
|
||||
|
||||
- Rollback "Add `bower update --save` functionality", it causes issues and needs more testing
|
||||
- Fix backward-compatibility of `bower search --json` ([#2066](https://github.com/bower/bower/issues/2066))
|
||||
- Ignore prerelease versions from `bower info` output
|
||||
- Update update-notifier to 0.6.0
|
||||
- Better formatting of help messages (https://github.com/bower/bower/commit/de3e1089da80f47ea3667c5ab80d301cddfd8c3e)
|
||||
- Add help menu for update `--save` and `update --save-dev` (https://github.com/bower/bower/commit/612aaa88eb4d4b268b2d8665c338ac086af3a5b0)
|
||||
|
||||
## 1.7.0 - 2015-12-07
|
||||
|
||||
- Add `bower update --save` functionality ([#2035](https://github.com/bower/bower/issues/2035))
|
||||
- `bower search` shows help message when no package name is specified ([#2066](https://github.com/bower/bower/issues/2066))
|
||||
- Update only those packages that are explicitly requested by the user. Related Issues
|
||||
- [#256](https://github.com/bower/bower/issues/256)
|
||||
- [#924](https://github.com/bower/bower/issues/924)
|
||||
- [#1770](https://github.com/bower/bower/issues/1770)
|
||||
- Allow for @ in username for SVN on windows ([#1650](https://github.com/bower/bower/issues/1650))
|
||||
- Update bower config
|
||||
- Loads the .bowerrc file from the cwd specified on the command line
|
||||
- Allow the use of environment variables in .bowerrc ([#41](https://github.com/bower/config/issues/41))
|
||||
- Allow for array notation in ENV variables ([#44](https://github.com/bower/config/issues/44))
|
||||
|
||||
## 1.6.9 - 2015-12-04
|
||||
|
||||
- Change git version of fs-write-stream-atomic back to npm version ([#2079](https://github.com/bower/bower/issues/2079))
|
||||
|
||||
## 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))
|
||||
@@ -12,6 +84,11 @@
|
||||
- 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
|
||||
|
||||
@@ -38,6 +115,10 @@
|
||||
- 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))
|
||||
|
||||
@@ -1,35 +1,26 @@
|
||||
# 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. (Jan 2014)
|
||||
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.
|
||||
|
||||
<a name="bugs"></a>
|
||||
## 🐛 [Bug reports](https://github.com/bower/bower/wiki/Report-a-Bug)
|
||||
|
||||
## 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 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.
|
||||
We communicate through a channel on slack: https://gitter.im/bower
|
||||
|
||||
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
|
||||
|
||||
@@ -38,7 +29,8 @@ 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), our
|
||||
[Stack Overflow](http://stackoverflow.com/questions/tagged/bower)
|
||||
[Gitter Channel](https://gitter.im/bower/bower)
|
||||
[Mailing List](http://groups.google.com/group/twitter-bower)
|
||||
(twitter-bower@googlegroups.com), or
|
||||
[#bower](http://webchat.freenode.net/?channels=bower) on Freenode.
|
||||
@@ -46,49 +38,6 @@ 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
|
||||
|
||||
A bug is a _demonstrable problem_ that is caused by the code in the repository.
|
||||
Good bug reports are extremely helpful - thank you!
|
||||
|
||||
Guidelines for bug reports:
|
||||
|
||||
1. **Use the GitHub issue search** — check if the issue has already been
|
||||
reported.
|
||||
|
||||
2. **Check if the issue has been fixed** — try to reproduce it using the
|
||||
latest `master` or development branch in the repository.
|
||||
|
||||
3. **Isolate the problem** — ideally create a [reduced test
|
||||
case](http://css-tricks.com/6263-reduced-test-cases/).
|
||||
|
||||
A good bug report shouldn't leave others needing to chase you up for more
|
||||
information. Please try to be as detailed as possible in your report. What is
|
||||
your environment? What steps will reproduce the issue? What OS experiences the
|
||||
problem? What would you expect to be the outcome? All these details will help
|
||||
people to fix any potential bugs.
|
||||
|
||||
Example:
|
||||
|
||||
> Short and descriptive example bug report title
|
||||
>
|
||||
> A summary of the issue and the browser/OS environment in which it occurs. If
|
||||
> suitable, include the steps required to reproduce the bug.
|
||||
>
|
||||
> 1. This is the first step
|
||||
> 2. This is the second step
|
||||
> 3. Further steps, etc.
|
||||
>
|
||||
> `<url>` - a link to the reduced test case
|
||||
>
|
||||
> Any other information you want to share that is relevant to the issue being
|
||||
> reported. This might include the lines of code that you have identified as
|
||||
> causing the bug, and potential solutions (and your opinions on their
|
||||
> merits).
|
||||
|
||||
|
||||
<a name="features"></a>
|
||||
## Feature requests
|
||||
|
||||
@@ -172,6 +121,8 @@ included in the project:
|
||||
force push to your remote feature branch. You may also be asked to squash
|
||||
commits.
|
||||
|
||||
10. If you are asked to squash your commits, then please use `git rebase -i master`. It will ask you to pick your commits - pick the major commits and squash the rest.
|
||||
|
||||
**IMPORTANT**: By submitting a patch, you agree to license your work under the
|
||||
same license as that used by the project.
|
||||
|
||||
|
||||
21
Gruntfile.js
21
Gruntfile.js
@@ -17,6 +17,21 @@ 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',
|
||||
@@ -40,10 +55,10 @@ module.exports = function (grunt) {
|
||||
command: 'node test/packages.js --force && node test/packages-svn.js --force'
|
||||
},
|
||||
cover: {
|
||||
command: 'STRICT_REQUIRE=1 node node_modules/istanbul/lib/cli.js cover --dir ./test/reports node_modules/mocha/bin/_mocha -- --timeout 30000 -R dot test/test.js'
|
||||
command: 'node node_modules/istanbul/lib/cli.js cover --dir ./test/reports node_modules/mocha/bin/_mocha -- --timeout 30000 -R dot test/test.js'
|
||||
},
|
||||
coveralls: {
|
||||
command: 'node node_modules/.bin/coveralls < test/reports/lcov.info'
|
||||
command: 'npm run coveralls < test/reports/lcov.info'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -53,7 +68,7 @@ module.exports = function (grunt) {
|
||||
});
|
||||
|
||||
grunt.registerTask('assets', ['exec:assets-force']);
|
||||
grunt.registerTask('test', ['jshint', 'exec:assets', 'simplemocha:full']);
|
||||
grunt.registerTask('test', ['jscs', 'jshint', 'exec:assets', 'simplemocha:full']);
|
||||
grunt.registerTask('cover', 'exec:cover');
|
||||
grunt.registerTask('travis', ['jshint', 'exec:assets', 'exec:cover', 'exec:coveralls']);
|
||||
grunt.registerTask('default', 'test');
|
||||
|
||||
34
README.md
34
README.md
@@ -1,10 +1,17 @@
|
||||
# Bower
|
||||
# Bower - A package manager for the web
|
||||
|
||||
[](https://travis-ci.org/bower/bower) [](https://ci.appveyor.com/project/sheerun/bower/history) [](https://coveralls.io/r/bower/bower?branch=master)
|
||||
> Bower needs resources for its maintenance. Please see [our blog](http://bower.io/blog/) if you think you can help.
|
||||
|
||||
[](https://travis-ci.org/bower/bower)
|
||||
[](https://ci.appveyor.com/project/sheerun/bower/history)
|
||||
[](https://coveralls.io/r/bower/bower?branch=master)
|
||||
[](https://discord.gg/0fFM7QF0KpZRh2cY)
|
||||
[](http://issuestats.com/github/bower/bower)
|
||||
[](http://issuestats.com/github/bower/bower)
|
||||
|
||||
<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.
|
||||
|
||||
@@ -45,7 +52,7 @@ $ bower install <package>#<version> --save
|
||||
|
||||
We discourage using bower components statically for performance and security reasons (if component has an `upload.php` file that is not ignored, that can be easily exploited to do malicious stuff).
|
||||
|
||||
The best approach is to process components installed by bower with build tool (like [Grunt](http://gruntjs.com/) or [gulp](http://gulpjs.com/)), and serve them concatenated or using module loader (like [RequireJS](http://requirejs.org/)).
|
||||
The best approach is to process components installed by bower with build tool (like [Grunt](http://gruntjs.com/) or [gulp](http://gulpjs.com/)), and serve them concatenated or using a module loader (like [RequireJS](http://requirejs.org/)).
|
||||
|
||||
### Uninstalling packages
|
||||
|
||||
@@ -59,18 +66,19 @@ $ 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`
|
||||
|
||||
### Running commands with sudo
|
||||
### Never run Bower 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.
|
||||
Bower is a user command; there is no need to execute it with superuser permissions.
|
||||
|
||||
### Windows users
|
||||
|
||||
To use Bower on Windows, you must install
|
||||
[msysgit](http://msysgit.github.io/) correctly. Be sure to check the
|
||||
option shown below:
|
||||
[Git for Windows](http://git-for-windows.github.io/) correctly. Be sure to check the
|
||||
options 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" />
|
||||
|
||||
Note that if you use TortoiseGit and if Bower keeps asking for your SSH
|
||||
password, you should add the following environment variable: `GIT_SSH -
|
||||
@@ -92,6 +100,7 @@ Bower can be configured using JSON in a `.bowerrc` file. Read over available opt
|
||||
|
||||
## Support
|
||||
|
||||
* [Discord chat](https://discord.gg/0fFM7QF0KpZRh2cY)
|
||||
* [StackOverflow](http://stackoverflow.com/questions/tagged/bower)
|
||||
* [Mailinglist](http://groups.google.com/group/twitter-bower) - twitter-bower@googlegroups.com
|
||||
* [\#bower](http://webchat.freenode.net/?channels=bower) on Freenode
|
||||
@@ -99,10 +108,9 @@ 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
|
||||
review the [guidelines for contributing](CONTRIBUTING.md).
|
||||
We welcome [contributions](https://github.com/bower/bower/graphs/contributors) of all kinds from anyone. Please take a moment to review the [guidelines for contributing](CONTRIBUTING.md).
|
||||
|
||||
* [Bug reports](CONTRIBUTING.md#bugs)
|
||||
* [Bug reports](https://github.com/bower/bower/wiki/Report-a-Bug)
|
||||
* [Feature requests](CONTRIBUTING.md#features)
|
||||
* [Pull requests](CONTRIBUTING.md#pull-requests)
|
||||
|
||||
|
||||
21
appveyor.yml
21
appveyor.yml
@@ -10,28 +10,31 @@ init:
|
||||
environment:
|
||||
matrix:
|
||||
- nodejs_version: "0.10"
|
||||
# - nodejs_version: "0.11"
|
||||
- nodejs_version: "0.12"
|
||||
- nodejs_version: "5"
|
||||
- nodejs_version: "4"
|
||||
|
||||
# Allow failing jobs for bleeding-edge Node.js versions.
|
||||
matrix:
|
||||
allow_failures:
|
||||
- nodejs_version: "0.11"
|
||||
- nodejs_version: "0.10"
|
||||
- nodejs_version: "5"
|
||||
|
||||
# Install scripts. (runs after repo cloning)
|
||||
install:
|
||||
# Get the latest stable version of Node 0.STABLE.latest
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
# Install subversion
|
||||
- choco install svn -y
|
||||
# Install bower
|
||||
# Output useful info for debugging.
|
||||
- node --version
|
||||
- npm --version
|
||||
- git --version
|
||||
- svn --version
|
||||
# Install all dependencies
|
||||
- npm install
|
||||
|
||||
# Post-install test scripts.
|
||||
test_script:
|
||||
# Output useful info for debugging.
|
||||
- node --version
|
||||
- npm --version
|
||||
- cmd: npm test
|
||||
- cmd: npm run ci
|
||||
|
||||
# Don't actually build.
|
||||
build: off
|
||||
|
||||
54
bin/bower
54
bin/bower
@@ -99,30 +99,40 @@ analytics.setup(bower.config).then(function () {
|
||||
// Get the renderer and configure it with the executed command
|
||||
renderer = cli.getRenderer(command, logger.json, bower.config);
|
||||
|
||||
logger
|
||||
.on('end', function (data) {
|
||||
if (!bower.config.silent && !bower.config.quiet) {
|
||||
renderer.end(data);
|
||||
}
|
||||
})
|
||||
.on('error', function (err) {
|
||||
if (levels.error >= loglevel) {
|
||||
renderer.error(err);
|
||||
}
|
||||
function handleLogger(logger, renderer) {
|
||||
logger
|
||||
.on('end', function (data) {
|
||||
if (!bower.config.silent && !bower.config.quiet) {
|
||||
renderer.end(data);
|
||||
}
|
||||
})
|
||||
.on('error', function (err) {
|
||||
if (command !== 'help' && err.code === cli.READ_OPTIONS_ERROR_CODE) {
|
||||
logger = bower.commands.help(command);
|
||||
renderer = cli.getRenderer('help', logger.json, bower.config);
|
||||
handleLogger(logger, renderer);
|
||||
} else {
|
||||
if (levels.error >= loglevel) {
|
||||
renderer.error(err);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
})
|
||||
.on('log', function (log) {
|
||||
if (levels[log.level] >= loglevel) {
|
||||
renderer.log(log);
|
||||
}
|
||||
})
|
||||
.on('prompt', function (prompt, callback) {
|
||||
renderer.prompt(prompt)
|
||||
.then(function (answer) {
|
||||
callback(answer);
|
||||
process.exit(1);
|
||||
}
|
||||
})
|
||||
.on('log', function (log) {
|
||||
if (levels[log.level] >= loglevel) {
|
||||
renderer.log(log);
|
||||
}
|
||||
})
|
||||
.on('prompt', function (prompt, callback) {
|
||||
renderer.prompt(prompt)
|
||||
.then(function (answer) {
|
||||
callback(answer);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
handleLogger(logger, renderer);
|
||||
|
||||
// Warn if HOME is not SET
|
||||
if (!userHome) {
|
||||
|
||||
30
lib/abbreviations.js
Normal file
30
lib/abbreviations.js
Normal file
@@ -0,0 +1,30 @@
|
||||
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;
|
||||
};
|
||||
@@ -10,24 +10,24 @@ var config = require('../config');
|
||||
* return as soon as possible and load and execute the command asynchronously.
|
||||
*/
|
||||
function commandFactory(id) {
|
||||
if (process.env.STRICT_REQUIRE) {
|
||||
require(id);
|
||||
}
|
||||
|
||||
function command() {
|
||||
function runApi() {
|
||||
var command = require(id);
|
||||
var commandArgs = [].slice.call(arguments);
|
||||
|
||||
return withLogger(function (logger) {
|
||||
commandArgs.unshift(logger);
|
||||
return require(id).apply(undefined, commandArgs);
|
||||
|
||||
return command.apply(undefined, commandArgs);
|
||||
});
|
||||
}
|
||||
|
||||
function runFromArgv(argv) {
|
||||
return withLogger(function (logger) {
|
||||
var command = require(id);
|
||||
var commandArgs;
|
||||
var command = require(id);
|
||||
|
||||
var commandArgs = command.readOptions(argv);
|
||||
commandArgs = command.readOptions(argv);
|
||||
|
||||
return withLogger(function (logger) {
|
||||
commandArgs.unshift(logger);
|
||||
|
||||
return command.apply(undefined, commandArgs);
|
||||
@@ -38,7 +38,7 @@ function commandFactory(id) {
|
||||
var logger = new Logger();
|
||||
|
||||
Q.try(func, logger)
|
||||
.done(function () {
|
||||
.then(function () {
|
||||
config.restore();
|
||||
var args = [].slice.call(arguments);
|
||||
args.unshift('end');
|
||||
@@ -51,9 +51,9 @@ function commandFactory(id) {
|
||||
return logger;
|
||||
}
|
||||
|
||||
command.line = runFromArgv;
|
||||
runApi.line = runFromArgv;
|
||||
|
||||
return command;
|
||||
return runApi;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,33 +2,41 @@ var Q = require('q');
|
||||
var RegistryClient = require('bower-registry-client');
|
||||
var Tracker = require('../util/analytics').Tracker;
|
||||
var defaultConfig = require('../config');
|
||||
var cli = require('../util/cli');
|
||||
|
||||
function search(logger, name, config) {
|
||||
var registryClient;
|
||||
var tracker;
|
||||
|
||||
var json = config ? config.json : undefined;
|
||||
config = defaultConfig(config);
|
||||
config.json = config.json || json; // Hack until bower-config is fixed...
|
||||
config.cache = config.storage.registry;
|
||||
|
||||
registryClient = new RegistryClient(config, logger);
|
||||
tracker = new Tracker(config);
|
||||
tracker.track('search', name);
|
||||
|
||||
// If no name was specified, list all packages
|
||||
if (!name) {
|
||||
return Q.nfcall(registryClient.list.bind(registryClient));
|
||||
// Otherwise search it
|
||||
} else {
|
||||
if (name) {
|
||||
return Q.nfcall(registryClient.search.bind(registryClient), name);
|
||||
} else {
|
||||
// List all packages when in interactive mode + json enabled, and
|
||||
// always when in non-interactive mode
|
||||
if (config.interactive && !config.json) {
|
||||
throw cli.createReadOptionsError('search');
|
||||
}
|
||||
|
||||
return Q.nfcall(registryClient.list.bind(registryClient));
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------
|
||||
|
||||
search.readOptions = function (argv) {
|
||||
var cli = require('../util/cli');
|
||||
var options = cli.readOptions(argv);
|
||||
var name = options.argv.remain.slice(1).join(' ');
|
||||
var terms = options.argv.remain.slice(1);
|
||||
|
||||
var name = terms.join(' ');
|
||||
|
||||
return [name];
|
||||
};
|
||||
|
||||
@@ -25,8 +25,11 @@ Manager.prototype.configure = function (setup) {
|
||||
var targetsHash = {};
|
||||
this._conflicted = {};
|
||||
|
||||
// Targets
|
||||
this._targets = setup.targets || [];
|
||||
// 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);
|
||||
|
||||
this._targets.forEach(function (decEndpoint) {
|
||||
decEndpoint.initialName = decEndpoint.name;
|
||||
decEndpoint.dependants = mout.object.values(decEndpoint.dependants);
|
||||
|
||||
@@ -556,11 +556,11 @@ Project.prototype._readJson = function () {
|
||||
return Q.resolve(this._json);
|
||||
}
|
||||
|
||||
return Q.fcall(function(){
|
||||
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){
|
||||
.then(function(buffer) {
|
||||
// If package.json exists, use it's values as defaults
|
||||
var defaults = {}, npm = JSON.parse(buffer.toString());
|
||||
|
||||
@@ -573,11 +573,11 @@ Project.prototype._readJson = function () {
|
||||
|
||||
return defaults;
|
||||
})
|
||||
.catch(function(err){
|
||||
.catch(function(err) {
|
||||
// Most likely no package.json so just set default name
|
||||
return { name: path.basename(that._config.cwd) || 'root' };
|
||||
})
|
||||
.then(function(defaults){
|
||||
.then(function(defaults) {
|
||||
return that._json = readJson(that._config.cwd, { assume: defaults });
|
||||
})
|
||||
.spread(function (json, deprecated, assumed) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/*jshint laxbreak:true*/
|
||||
var Q = require('q');
|
||||
var fs = require('../util/fs');
|
||||
var path = require('path');
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/*jshint laxbreak:true*/
|
||||
var util = require('util');
|
||||
var url = require('url');
|
||||
var Q = require('q');
|
||||
@@ -119,7 +120,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(this._host)) {
|
||||
if (shallowCloningSupported && !GitRemoteResolver._noShallow.get(that._host)) {
|
||||
args.push('--depth', 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ var rimraf = require('../../util/rimraf');
|
||||
var readJson = require('../../util/readJson');
|
||||
var createError = require('../../util/createError');
|
||||
var removeIgnores = require('../../util/removeIgnores');
|
||||
var md5 = require('md5-hex');
|
||||
|
||||
tmp.setGracefulCleanup();
|
||||
|
||||
@@ -107,8 +108,7 @@ 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;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,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, this._name + '-' + process.pid + '-XXXXXX'),
|
||||
template: path.join(this._config.tmp, md5(this._name) + '-' + process.pid + '-XXXXXX'),
|
||||
mode: 0777 & ~process.umask(),
|
||||
unsafeCleanup: true
|
||||
});
|
||||
|
||||
@@ -86,13 +86,13 @@ SvnResolver.prototype._export = function () {
|
||||
});
|
||||
|
||||
if (resolution.type === 'commit') {
|
||||
promise = cmd('svn', ['export', '--force', this._source + '/trunk', '-r' + resolution.commit, this._tempDir]);
|
||||
promise = cmd('svn', ['export', '--force', '--non-interactive', this._source + '/trunk', '-r' + resolution.commit, this._tempDir]);
|
||||
} else if (resolution.type === 'branch' && resolution.branch === 'trunk') {
|
||||
promise = cmd('svn', ['export', '--force', this._source + '/trunk', this._tempDir]);
|
||||
promise = cmd('svn', ['export', '--force', '--non-interactive', this._source + '/trunk', this._tempDir]);
|
||||
} else if (resolution.type === 'branch') {
|
||||
promise = cmd('svn', ['export', '--force', this._source + '/branches/' + resolution.branch, this._tempDir]);
|
||||
promise = cmd('svn', ['export', '--force', '--non-interactive', this._source + '/branches/' + resolution.branch, this._tempDir]);
|
||||
} else {
|
||||
promise = cmd('svn', ['export', '--force', this._source + '/tags/' + resolution.tag, this._tempDir]);
|
||||
promise = cmd('svn', ['export', '--force', '--non-interactive', this._source + '/tags/' + resolution.tag, this._tempDir]);
|
||||
}
|
||||
|
||||
// Throttle the progress reporter to 1 time each sec
|
||||
@@ -324,7 +324,7 @@ SvnResolver.tags = function (source) {
|
||||
return Q.resolve(value);
|
||||
}
|
||||
|
||||
value = cmd('svn', ['list', source + '/tags', '--verbose'])
|
||||
value = cmd('svn', ['list', source + '/tags', '--verbose', '--non-interactive'])
|
||||
.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'])
|
||||
value = cmd('svn', ['list', source + '/branches', '--verbose', '--non-interactive'])
|
||||
.spread(function (stout) {
|
||||
var branches = SvnResolver.parseSubversionListOutput(stout.toString());
|
||||
|
||||
|
||||
@@ -104,8 +104,18 @@ UrlResolver.prototype._resolve = function () {
|
||||
|
||||
// -----------------
|
||||
|
||||
UrlResolver.prototype._parseSourceURL = function (_url) {
|
||||
return url.parse(path.basename(_url)).pathname;
|
||||
};
|
||||
|
||||
UrlResolver.prototype._download = function () {
|
||||
var fileName = url.parse(path.basename(this._source)).pathname;
|
||||
var fileName = this._parseSourceURL(this._source);
|
||||
|
||||
if (!fileName) {
|
||||
this._source = this._source.replace(/\/(?=\?|#)/, '');
|
||||
fileName = this._parseSourceURL(this._source);
|
||||
}
|
||||
|
||||
var file = path.join(this._tempDir, fileName);
|
||||
var reqHeaders = {};
|
||||
var that = this;
|
||||
|
||||
26
lib/index.js
26
lib/index.js
@@ -1,30 +1,6 @@
|
||||
var abbrev = require('abbrev');
|
||||
var mout = require('mout');
|
||||
var commands = require('./commands');
|
||||
var pkg = require('../package.json');
|
||||
|
||||
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;
|
||||
}
|
||||
var abbreviations = require('./abbreviations')(commands);
|
||||
|
||||
function clearRuntimeCache() {
|
||||
// Note that in edge cases, some architecture components instance's
|
||||
|
||||
@@ -31,10 +31,10 @@ JsonRenderer.prototype.error = function (err) {
|
||||
err.message = message;
|
||||
|
||||
// Stack
|
||||
/*jshint camelcase:false*/
|
||||
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||
stack = err.fstream_stack || err.stack || 'N/A';
|
||||
err.stacktrace = (Array.isArray(stack) ? stack.join('\n') : stack);
|
||||
/*jshint camelcase:true*/
|
||||
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||
|
||||
this.log(err);
|
||||
this.end();
|
||||
|
||||
@@ -5,6 +5,7 @@ var archy = require('archy');
|
||||
var Q = require('q');
|
||||
var stringifyObject = require('stringify-object');
|
||||
var os = require('os');
|
||||
var semverUtils = require('semver-utils');
|
||||
var pkg = require(path.join(__dirname, '../..', 'package.json'));
|
||||
var template = require('../util/template');
|
||||
|
||||
@@ -71,12 +72,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) {
|
||||
/*jshint camelcase:false*/
|
||||
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||
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');
|
||||
/*jshint camelcase:true*/
|
||||
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||
|
||||
this._write(process.stderr, str);
|
||||
this._write(process.stderr, new Error().stack);
|
||||
@@ -209,6 +210,19 @@ StandardRenderer.prototype._info = function (data) {
|
||||
|
||||
// Render the versions at the end
|
||||
if (includeVersions) {
|
||||
data.hidePreReleases = false;
|
||||
data.numPreReleases = 0;
|
||||
// If output isn't verbose, hide prereleases
|
||||
if (!this._config.verbose) {
|
||||
data.versions = mout.array.filter(data.versions, function(version) {
|
||||
version = semverUtils.parse(version);
|
||||
if (!version.release && !version.build) {
|
||||
return true;
|
||||
}
|
||||
data.numPreReleases++;
|
||||
});
|
||||
data.hidePreReleases = !!data.numPreReleases;
|
||||
}
|
||||
str += '\n' + template.render('std/info.std', data);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,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 +103,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));
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
var mout = require('mout');
|
||||
var nopt = require('nopt');
|
||||
var renderers = require('../renderers');
|
||||
var createError = require('./createError');
|
||||
|
||||
var READ_OPTIONS_ERROR_CODE = 'EREADOPTIONS';
|
||||
|
||||
function readOptions(options, argv) {
|
||||
var types;
|
||||
@@ -37,6 +40,16 @@ function readOptions(options, argv) {
|
||||
return parsedOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an error for the case where a command has trouble parsing command
|
||||
* line options.
|
||||
**/
|
||||
function createReadOptionsError(commandName) {
|
||||
var errorString = commandName + ' syntax error';
|
||||
|
||||
return createError(errorString, READ_OPTIONS_ERROR_CODE);
|
||||
}
|
||||
|
||||
function getRenderer(command, json, config) {
|
||||
if (config.json || json) {
|
||||
return new renderers.Json(command, config);
|
||||
@@ -47,3 +60,6 @@ function getRenderer(command, json, config) {
|
||||
|
||||
module.exports.readOptions = readOptions;
|
||||
module.exports.getRenderer = getRenderer;
|
||||
|
||||
module.exports.createReadOptionsError = createReadOptionsError;
|
||||
module.exports.READ_OPTIONS_ERROR_CODE = READ_OPTIONS_ERROR_CODE;
|
||||
|
||||
@@ -5,12 +5,14 @@ var mout = require('mout');
|
||||
var retry = require('retry');
|
||||
var createError = require('./createError');
|
||||
var createWriteStream = require('fs-write-stream-atomic');
|
||||
var destroy = require('destroy');
|
||||
|
||||
var errorCodes = [
|
||||
'EADDRINFO',
|
||||
'ETIMEDOUT',
|
||||
'ECONNRESET',
|
||||
'ESOCKETTIMEDOUT'
|
||||
'ESOCKETTIMEDOUT',
|
||||
'ENOTFOUND'
|
||||
];
|
||||
|
||||
function download(url, file, options) {
|
||||
@@ -23,18 +25,22 @@ function download(url, file, options) {
|
||||
factor: 2,
|
||||
minTimeout: 1000,
|
||||
maxTimeout: 35000,
|
||||
randomize: true
|
||||
randomize: true,
|
||||
progressDelay: progressDelay
|
||||
}, options || {});
|
||||
|
||||
// Retry on network errors
|
||||
operation = retry.operation(options);
|
||||
|
||||
operation.attempt(function () {
|
||||
Q.fcall(fetch, url, file, {
|
||||
progressDelay: progressDelay
|
||||
}).then(function(response) {
|
||||
Q.fcall(fetch, url, file, options)
|
||||
.then(function(response) {
|
||||
deferred.resolve(response);
|
||||
}).fail(function (error) {
|
||||
})
|
||||
.progress(function (status) {
|
||||
deferred.notify(status);
|
||||
})
|
||||
.fail(function (error) {
|
||||
// Save timeout before retrying to report
|
||||
var timeout = operation._timeouts[0];
|
||||
|
||||
@@ -46,13 +52,16 @@ function download(url, file, options) {
|
||||
// Next attempt will start reporting download progress immediately
|
||||
progressDelay = 0;
|
||||
|
||||
deferred.notify({
|
||||
retry: true,
|
||||
delay: timeout,
|
||||
error: error
|
||||
});
|
||||
|
||||
operation.retry(error);
|
||||
// This will schedule next retry or return false
|
||||
if (operation.retry(error)) {
|
||||
deferred.notify({
|
||||
retry: true,
|
||||
delay: timeout,
|
||||
error: error
|
||||
});
|
||||
} else {
|
||||
deferred.reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -60,27 +69,52 @@ function download(url, file, options) {
|
||||
}
|
||||
|
||||
function fetch(url, file, options) {
|
||||
var response;
|
||||
var deferred = Q.defer();
|
||||
|
||||
// Retry on network errors
|
||||
var req;
|
||||
var writeStream;
|
||||
var contentLength;
|
||||
var bytesDownloaded = 0;
|
||||
|
||||
req = progress(request(url, options), {
|
||||
var reject = function (error) {
|
||||
deferred.reject(error);
|
||||
};
|
||||
|
||||
var req = progress(request(url, options), {
|
||||
delay: options.progressDelay
|
||||
})
|
||||
.on('response', function (res) {
|
||||
var status = res.statusCode;
|
||||
.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'));
|
||||
}
|
||||
|
||||
response = res;
|
||||
contentLength = Number(res.headers['content-length']);
|
||||
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);
|
||||
});
|
||||
|
||||
writeStream.on('finish', function () {
|
||||
if (!errored) {
|
||||
destroy(req);
|
||||
deferred.resolve(response);
|
||||
}
|
||||
});
|
||||
|
||||
req.pipe(writeStream);
|
||||
})
|
||||
.on('data', function (data) {
|
||||
bytesDownloaded += data.length;
|
||||
@@ -88,9 +122,7 @@ function fetch(url, file, options) {
|
||||
.on('progress', function (state) {
|
||||
deferred.notify(state);
|
||||
})
|
||||
.on('error', function (error) {
|
||||
deferred.reject(error);
|
||||
})
|
||||
.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
|
||||
@@ -104,20 +136,6 @@ function fetch(url, file, options) {
|
||||
}
|
||||
});
|
||||
|
||||
writeStream = createWriteStream(file);
|
||||
|
||||
// Pipe read stream to write stream
|
||||
writeStream.on('error', function (error) {
|
||||
writeStream.destroy();
|
||||
deferred.reject(error);
|
||||
});
|
||||
|
||||
writeStream.on('finish', function () {
|
||||
deferred.resolve(response);
|
||||
});
|
||||
|
||||
req.pipe(writeStream);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ var readdirSync = fs.readdirSync.bind(fs);
|
||||
module.exports = fs;
|
||||
|
||||
module.exports.readdir = function (dir, callback) {
|
||||
fs.lstat(dir, function (err, stats) {
|
||||
fs.stat(dir, function (err, stats) {
|
||||
if (err) return callback(err);
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
@@ -22,7 +22,7 @@ module.exports.readdir = function (dir, callback) {
|
||||
};
|
||||
|
||||
module.exports.readdirSync = function (dir) {
|
||||
var stats = fs.lstatSync(dir);
|
||||
var stats = fs.statSync(dir);
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
return readdirSync(dir);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*jshint multistr:true*/
|
||||
// jscs:disable disallowMultipleLineStrings
|
||||
'use strict';
|
||||
var isRoot = require('is-root');
|
||||
var createError = require('./createError');
|
||||
|
||||
3
lib/util/userAgent.js
Normal file
3
lib/util/userAgent.js
Normal file
@@ -0,0 +1,3 @@
|
||||
var pkg = require('../../package.json');
|
||||
|
||||
module.exports = 'node/' + process.version + ' ' + process.platform + ' ' + process.arch + ' ' + ';Bower ' + pkg.version;
|
||||
1306
npm-shrinkwrap.json
generated
1306
npm-shrinkwrap.json
generated
File diff suppressed because it is too large
Load Diff
19
package.json
19
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bower",
|
||||
"version": "1.6.2",
|
||||
"version": "1.7.1",
|
||||
"description": "The browser package manager",
|
||||
"author": "Twitter",
|
||||
"license": "MIT",
|
||||
@@ -16,7 +16,7 @@
|
||||
"dependencies": {
|
||||
"abbrev": "^1.0.5",
|
||||
"archy": "1.0.0",
|
||||
"bower-config": "^1.2.1",
|
||||
"bower-config": "^1.3.0",
|
||||
"bower-endpoint-parser": "^0.2.2",
|
||||
"bower-json": "^0.4.0",
|
||||
"bower-logger": "^0.2.2",
|
||||
@@ -27,7 +27,7 @@
|
||||
"configstore": "^0.3.2",
|
||||
"decompress-zip": "^0.1.0",
|
||||
"destroy": "^1.0.3",
|
||||
"fs-write-stream-atomic": "^1.0.4",
|
||||
"fs-write-stream-atomic": "^1.0.5",
|
||||
"fstream": "^1.0.3",
|
||||
"fstream-ignore": "^1.0.2",
|
||||
"github": "^0.2.3",
|
||||
@@ -53,11 +53,12 @@
|
||||
"retry": "0.6.1",
|
||||
"rimraf": "^2.2.8",
|
||||
"semver": "^2.3.0",
|
||||
"semver-utils": "^1.1.1",
|
||||
"shell-quote": "^1.4.2",
|
||||
"stringify-object": "^1.0.0",
|
||||
"tar-fs": "^1.4.1",
|
||||
"tmp": "0.0.24",
|
||||
"update-notifier": "^0.3.0",
|
||||
"update-notifier": "^0.6.0",
|
||||
"user-home": "^1.1.0",
|
||||
"which": "^1.0.8"
|
||||
},
|
||||
@@ -70,16 +71,16 @@
|
||||
"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": "^2.13.0",
|
||||
"nock": "^3.1.0",
|
||||
"node-uuid": "^1.4.2",
|
||||
"npm-shrinkwrap": "^5.4.1",
|
||||
"proxyquire": "^1.3.0",
|
||||
"spawn-sync": "^1.0.5"
|
||||
"spawn-sync": "1.0.13"
|
||||
},
|
||||
"bundledDependencies": [
|
||||
"abbrev",
|
||||
@@ -130,7 +131,9 @@
|
||||
"which"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "grunt test"
|
||||
"test": "grunt test",
|
||||
"ci": "grunt travis",
|
||||
"coveralls": "coveralls"
|
||||
},
|
||||
"bin": "bin/bower",
|
||||
"files": [
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"command": "search",
|
||||
"description": "Finds all packages or a specific package.",
|
||||
"usage": [
|
||||
"search [<options>]",
|
||||
"search <name> [<options>]"
|
||||
],
|
||||
"options": [
|
||||
|
||||
@@ -19,6 +19,16 @@
|
||||
"shorthand": "-p",
|
||||
"flag": "--production",
|
||||
"description": "Do not install project devDependencies"
|
||||
},
|
||||
{
|
||||
"shorthand": "-S",
|
||||
"flag": "--save",
|
||||
"description": "Update dependencies in bower.json"
|
||||
},
|
||||
{
|
||||
"shorthand": "-D",
|
||||
"flag": "--save-dev",
|
||||
"description": "Update devDependencies in bower.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ Usage:
|
||||
{{/each}}
|
||||
{{/condense}}
|
||||
|
||||
|
||||
Options:
|
||||
|
||||
{{#condense}}
|
||||
@@ -20,3 +21,4 @@ Options:
|
||||
Description:
|
||||
|
||||
{{#indent level="4"}}{{description}}{{/indent}}
|
||||
|
||||
|
||||
@@ -24,3 +24,4 @@ Options:
|
||||
{{/condense}}
|
||||
|
||||
See 'bower help <command>' for more information on a specific command.
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
{{/versions}}
|
||||
{{/condense}}
|
||||
|
||||
|
||||
{{#if hidePreReleases}}
|
||||
Show {{numPreReleases}} additional prereleases with ‘bower info {{name}} --verbose’
|
||||
{{/if}}
|
||||
You can request info for a specific version with 'bower info {{name}}#<version>'
|
||||
{{else}}No versions available.
|
||||
{{/if}}
|
||||
BIN
test/assets/package-tar.tar
Normal file
BIN
test/assets/package-tar.tar
Normal file
Binary file not shown.
@@ -1,31 +1,23 @@
|
||||
var expect = require('expect.js');
|
||||
var helpers = require('../helpers');
|
||||
var runBin = require('../helpers').runBin;
|
||||
|
||||
describe('bower', function () {
|
||||
process.env.CI = '1';
|
||||
|
||||
var oldStdout;
|
||||
var text;
|
||||
it('runs bower installation', function () {
|
||||
var result = runBin();
|
||||
var text = result.stdout.toString();
|
||||
|
||||
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());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ describe('bower home', function () {
|
||||
expect(home.readOptions(['foo'])).to.eql(['foo']);
|
||||
});
|
||||
|
||||
var package = new helpers.TempDir({
|
||||
var mainPackage = 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 () {
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
return Q.Promise(function(resolve) {
|
||||
var home = helpers.command('home', { opn: resolve });
|
||||
helpers.run(home, [package.path]);
|
||||
helpers.run(home, [mainPackage.path]);
|
||||
}).then(function(url) {
|
||||
expect(url).to.be('http://bower.io');
|
||||
});
|
||||
});
|
||||
|
||||
it('opens home page of current repository', function () {
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
return Q.Promise(function(resolve) {
|
||||
var home = helpers.command('home', { opn: resolve });
|
||||
helpers.run(home, [undefined, { cwd: package.path }]);
|
||||
helpers.run(home, [undefined, { cwd: mainPackage.path }]);
|
||||
}).then(function(url) {
|
||||
expect(url).to.be('http://bower.io');
|
||||
});
|
||||
|
||||
@@ -15,7 +15,5 @@ describe('integration tests', function () {
|
||||
require('./uninstall');
|
||||
require('./update');
|
||||
require('./version');
|
||||
|
||||
// run last because it changes defaults
|
||||
require('./bower');
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ describe('bower info', function () {
|
||||
description: 'Hello world! Hello!'
|
||||
};
|
||||
|
||||
var package = new helpers.TempDir({
|
||||
var mainPackage = 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 () {
|
||||
package.prepareGit({});
|
||||
mainPackage.prepareGit({});
|
||||
|
||||
return helpers.run(info, [package.path]).spread(function(results) {
|
||||
return helpers.run(info, [mainPackage.path]).spread(function(results) {
|
||||
expect(results).to.eql({
|
||||
'latest': meta2,
|
||||
'name': package.path,
|
||||
'name': mainPackage.path,
|
||||
'versions': [
|
||||
'0.1.3',
|
||||
'0.1.2'
|
||||
|
||||
@@ -5,7 +5,7 @@ var init = helpers.command('init');
|
||||
|
||||
describe('bower init', function () {
|
||||
|
||||
var package = new helpers.TempDir();
|
||||
var mainPackage = 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 () {
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
var logger = init({
|
||||
cwd: package.path,
|
||||
cwd: mainPackage.path,
|
||||
interactive: true
|
||||
});
|
||||
|
||||
@@ -40,7 +40,7 @@ describe('bower init', function () {
|
||||
return helpers.expectEvent(logger, 'end');
|
||||
})
|
||||
.then(function () {
|
||||
expect(package.readJson('bower.json')).to.eql({
|
||||
expect(mainPackage.readJson('bower.json')).to.eql({
|
||||
name: 'test-name',
|
||||
homepage: 'test-homepage',
|
||||
authors: [ 'test-author' ],
|
||||
@@ -54,9 +54,9 @@ describe('bower init', function () {
|
||||
});
|
||||
|
||||
it('errors on non-interactive mode', function () {
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
return helpers.run(init, { cwd: package.path }).then(
|
||||
return helpers.run(init, { cwd: mainPackage.path }).then(
|
||||
function () { throw 'should fail'; },
|
||||
function (reason) {
|
||||
expect(reason.message).to.be('Register requires an interactive shell');
|
||||
@@ -66,13 +66,13 @@ describe('bower init', function () {
|
||||
});
|
||||
|
||||
it('warns about existing bower.json', function () {
|
||||
package.prepare({
|
||||
mainPackage.prepare({
|
||||
'bower.json': {
|
||||
name: 'foobar'
|
||||
}
|
||||
});
|
||||
|
||||
var logger = init({ cwd: package.path, interactive: true });
|
||||
var logger = init({ cwd: mainPackage.path, interactive: true });
|
||||
|
||||
return helpers.expectEvent(logger, 'log').spread(function(event) {
|
||||
expect(event.level).to.be('warn');
|
||||
@@ -83,7 +83,7 @@ describe('bower init', function () {
|
||||
});
|
||||
|
||||
it('gets defaults from package.json', function () {
|
||||
package.prepare({
|
||||
mainPackage.prepare({
|
||||
'package.json': {
|
||||
'name': 'name from npm',
|
||||
'description': 'description from npm',
|
||||
@@ -98,7 +98,7 @@ describe('bower init', function () {
|
||||
});
|
||||
|
||||
var logger = init({
|
||||
cwd: package.path,
|
||||
cwd: mainPackage.path,
|
||||
interactive: true
|
||||
});
|
||||
|
||||
@@ -106,7 +106,7 @@ describe('bower init', function () {
|
||||
.spread(function (prompt, answer) {
|
||||
|
||||
// Get defaults from prompt
|
||||
var defaults = prompt.reduce(function(memo, obj){
|
||||
var defaults = prompt.reduce(function(memo, obj) {
|
||||
memo[obj.name] = obj['default'];
|
||||
return memo;
|
||||
}, {});
|
||||
@@ -131,7 +131,7 @@ describe('bower init', function () {
|
||||
return helpers.expectEvent(logger, 'end');
|
||||
})
|
||||
.then(function () {
|
||||
expect(package.readJson('bower.json')).to.eql({
|
||||
expect(mainPackage.readJson('bower.json')).to.eql({
|
||||
'name': 'name from npm',
|
||||
'description': 'description from npm',
|
||||
'main': 'index.js',
|
||||
|
||||
@@ -1,349 +1,450 @@
|
||||
var expect = require('expect.js');
|
||||
var path = require('path');
|
||||
var helpers = require('../helpers');
|
||||
var nock = require('nock');
|
||||
var fs = require('../../lib/util/fs');
|
||||
|
||||
describe('bower install', function () {
|
||||
describe('bower install', function() {
|
||||
|
||||
var tempDir = new helpers.TempDir();
|
||||
|
||||
var install = helpers.command('install', { cwd: tempDir.path });
|
||||
|
||||
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
|
||||
}]);
|
||||
});
|
||||
|
||||
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
|
||||
}]);
|
||||
});
|
||||
|
||||
var package = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'package'
|
||||
}
|
||||
}).prepare();
|
||||
|
||||
var gitPackage = new helpers.TempDir();
|
||||
|
||||
it('writes to bower.json if --save flag is used', function () {
|
||||
package.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test'
|
||||
}
|
||||
});
|
||||
|
||||
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 () {
|
||||
package.prepare({
|
||||
'bower.json': {
|
||||
name: 'package',
|
||||
version: '1.2.3'
|
||||
}
|
||||
});
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test'
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install, [
|
||||
[package.path],
|
||||
{ saveExact: true, save: true }
|
||||
]).then(function() {
|
||||
expect(tempDir.readJson('bower.json').dependencies.package).to.equal(package.path + '#1.2.3');
|
||||
});
|
||||
});
|
||||
|
||||
it('writes an exact version number to devDependencies in bower.json if --save-dev --save-exact flags are used', function () {
|
||||
package.prepare({
|
||||
'bower.json': {
|
||||
name: 'package',
|
||||
version: '0.1.0'
|
||||
}
|
||||
});
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test'
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install, [
|
||||
[package.path],
|
||||
{ saveExact: true, saveDev: true }
|
||||
]).then(function() {
|
||||
expect(tempDir.readJson('bower.json').devDependencies.package).to.equal(package.path + '#0.1.0');
|
||||
});
|
||||
});
|
||||
|
||||
it('reads .bowerrc from cwd', function () {
|
||||
package.prepare({ foo: 'bar' });
|
||||
|
||||
tempDir.prepare({
|
||||
'.bowerrc': { directory: 'assets' },
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: package.path
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install).then(function() {
|
||||
expect(tempDir.read('assets/package/foo')).to.be('bar');
|
||||
});
|
||||
});
|
||||
|
||||
it('runs preinstall hook', function () {
|
||||
package.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: package.path
|
||||
}
|
||||
},
|
||||
'.bowerrc': {
|
||||
scripts: {
|
||||
preinstall: 'node -e \'require("fs").writeFileSync("preinstall.txt", "%")\''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install).then(function() {
|
||||
expect(tempDir.read('preinstall.txt')).to.be('package');
|
||||
});
|
||||
});
|
||||
|
||||
it('runs preinstall hook', function () {
|
||||
package.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: package.path
|
||||
}
|
||||
},
|
||||
'.bowerrc': {
|
||||
scripts: {
|
||||
postinstall: 'node -e \'require("fs").writeFileSync("postinstall.txt", "%")\''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install).then(function() {
|
||||
expect(tempDir.read('postinstall.txt')).to.be('package');
|
||||
});
|
||||
});
|
||||
|
||||
// To be discussed, but that's the implementation now
|
||||
it('does not run hooks if nothing is installed', function () {
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test'
|
||||
},
|
||||
'.bowerrc': {
|
||||
scripts: {
|
||||
postinstall: 'node -e \'require("fs").writeFileSync("hooks.txt", "%")\'',
|
||||
preinstall: 'node -e \'require("fs").writeFileSync("hooks.txt", "%")\''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install).then(function() {
|
||||
expect(tempDir.exists('hooks.txt')).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('runs postinstall after bower.json is written', function () {
|
||||
package.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test'
|
||||
},
|
||||
'.bowerrc': {
|
||||
scripts: {
|
||||
postinstall: 'node -e \'var fs = require("fs"); fs.writeFileSync("hook.txt", fs.readFileSync("bower.json"));\''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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) {
|
||||
package.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: package.path
|
||||
}
|
||||
},
|
||||
'.bowerrc': {
|
||||
scripts: {
|
||||
postinstall: 'node -e \'process.stdout.write("foobar")\''
|
||||
}
|
||||
}
|
||||
});
|
||||
var lastAction = null;
|
||||
|
||||
helpers.run(install).logger.intercept(function (log) {
|
||||
if (log.level === 'action') {
|
||||
lastAction = log;
|
||||
}
|
||||
}).on('end', function () {
|
||||
expect(lastAction.message).to.be('foobar');
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
it('skips components not installed by bower', function () {
|
||||
package.prepare({
|
||||
'.git': {} //Make a dummy file instead of using slower gitPrepare()
|
||||
});
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: package.path
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install).then(function() {
|
||||
var packageFiles = fs.readdirSync(package.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': {
|
||||
'bower.json': {
|
||||
name: 'package'
|
||||
},
|
||||
'version.txt': '1.0.0'
|
||||
},
|
||||
'1.0.1': {
|
||||
'bower.json': {
|
||||
name: 'package'
|
||||
},
|
||||
'version.txt': '1.0.1'
|
||||
}
|
||||
});
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: gitPackage.path + '#1.0.0'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install).then(function() {
|
||||
expect(tempDir.read('bower_components/package/version.txt')).to.contain('1.0.0');
|
||||
});
|
||||
});
|
||||
|
||||
it('does not install ignored dependencies', function() {
|
||||
package.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: package.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('recognizes proxy option in config', function () {
|
||||
this.timeout(10000);
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test_tw',
|
||||
dependencies: {
|
||||
pure: 'http://github.com/yahoo/pure/archive/v0.6.0.tar.gz'
|
||||
}
|
||||
}
|
||||
});
|
||||
var tempDir = new helpers.TempDir();
|
||||
|
||||
var install = helpers.command('install', {
|
||||
cwd: tempDir.path
|
||||
cwd: tempDir.path
|
||||
});
|
||||
|
||||
nock.disableNetConnect();
|
||||
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');
|
||||
nock.enableNetConnect();
|
||||
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
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
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
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
var mainPackage = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'package'
|
||||
}
|
||||
}).prepare();
|
||||
|
||||
var gitPackage = new helpers.TempDir();
|
||||
|
||||
gitPackage.prepareGit({
|
||||
'1.0.0': {
|
||||
'bower.json': {
|
||||
name: 'package'
|
||||
},
|
||||
'version.txt': '1.0.0'
|
||||
},
|
||||
'1.0.1': {
|
||||
'bower.json': {
|
||||
name: 'package'
|
||||
},
|
||||
'version.txt': '1.0.1'
|
||||
}
|
||||
});
|
||||
|
||||
it('writes to bower.json if --save flag is used', function() {
|
||||
mainPackage.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test'
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install, [
|
||||
[mainPackage.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({
|
||||
'bower.json': {
|
||||
name: 'package',
|
||||
version: '1.2.3'
|
||||
}
|
||||
});
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test'
|
||||
}
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
it('writes an exact version number to devDependencies in bower.json if --save-dev --save-exact flags are used', function() {
|
||||
mainPackage.prepare({
|
||||
'bower.json': {
|
||||
name: 'package',
|
||||
version: '0.1.0'
|
||||
}
|
||||
});
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test'
|
||||
}
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
it('reads .bowerrc from cwd', function() {
|
||||
mainPackage.prepare({
|
||||
foo: 'bar'
|
||||
});
|
||||
|
||||
tempDir.prepare({
|
||||
'.bowerrc': {
|
||||
directory: 'assets'
|
||||
},
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: mainPackage.path
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install).then(function() {
|
||||
expect(tempDir.read('assets/package/foo')).to.be('bar');
|
||||
});
|
||||
});
|
||||
|
||||
it('runs preinstall hook', function() {
|
||||
mainPackage.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: mainPackage.path
|
||||
}
|
||||
},
|
||||
'.bowerrc': {
|
||||
scripts: {
|
||||
preinstall: 'node -e \'require("fs").writeFileSync("preinstall.txt", "%")\''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install).then(function() {
|
||||
expect(tempDir.read('preinstall.txt')).to.be('package');
|
||||
});
|
||||
});
|
||||
|
||||
it('runs postinstall hook', function() {
|
||||
mainPackage.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: mainPackage.path
|
||||
}
|
||||
},
|
||||
'.bowerrc': {
|
||||
scripts: {
|
||||
postinstall: 'node -e \'require("fs").writeFileSync("postinstall.txt", "%")\''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install).then(function() {
|
||||
expect(tempDir.read('postinstall.txt')).to.be('package');
|
||||
});
|
||||
});
|
||||
|
||||
// To be discussed, but that's the implementation now
|
||||
it('does not run hooks if nothing is installed', function() {
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test'
|
||||
},
|
||||
'.bowerrc': {
|
||||
scripts: {
|
||||
postinstall: 'node -e \'require("fs").writeFileSync("hooks.txt", "%")\'',
|
||||
preinstall: 'node -e \'require("fs").writeFileSync("hooks.txt", "%")\''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install).then(function() {
|
||||
expect(tempDir.exists('hooks.txt')).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('runs postinstall after bower.json is written', function() {
|
||||
mainPackage.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test'
|
||||
},
|
||||
'.bowerrc': {
|
||||
scripts: {
|
||||
postinstall: 'node -e \'var fs = require("fs"); fs.writeFileSync("hook.txt", fs.readFileSync("bower.json"));\''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install, [
|
||||
[mainPackage.path], {
|
||||
save: true
|
||||
}
|
||||
]).then(function() {
|
||||
expect(tempDir.read('hook.txt')).to.contain('dependencies');
|
||||
});
|
||||
});
|
||||
|
||||
it('display the output of hook scripts', function(next) {
|
||||
mainPackage.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: mainPackage.path
|
||||
}
|
||||
},
|
||||
'.bowerrc': {
|
||||
scripts: {
|
||||
postinstall: 'node -e \'process.stdout.write("foobar")\''
|
||||
}
|
||||
}
|
||||
});
|
||||
var lastAction = null;
|
||||
|
||||
helpers.run(install).logger.intercept(function(log) {
|
||||
if (log.level === 'action') {
|
||||
lastAction = log;
|
||||
}
|
||||
}).on('end', function() {
|
||||
expect(lastAction.message).to.be('foobar');
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
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': {
|
||||
'bower.json': {
|
||||
name: 'package'
|
||||
},
|
||||
'version.txt': '1.0.0'
|
||||
},
|
||||
'1.0.1': {
|
||||
'bower.json': {
|
||||
name: 'package'
|
||||
},
|
||||
'version.txt': '1.0.1'
|
||||
}
|
||||
});
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: gitPackage.path + '#1.0.0'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install).then(function() {
|
||||
expect(tempDir.read('bower_components/package/version.txt')).to.contain('1.0.0');
|
||||
});
|
||||
});
|
||||
|
||||
it('works for dependencies that point to tar files', function() {
|
||||
var packageDir = path.join(__dirname, '../assets/package-tar.tar');
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: packageDir
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(install).then(function() {
|
||||
expect(tempDir.read('bower_components/package/index.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');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@ var link = helpers.command('link');
|
||||
|
||||
describe('bower link', function () {
|
||||
|
||||
var package = new helpers.TempDir({
|
||||
var mainPackage = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'package',
|
||||
},
|
||||
@@ -22,7 +22,7 @@ describe('bower link', function () {
|
||||
var linksDir = new helpers.TempDir();
|
||||
|
||||
beforeEach(function() {
|
||||
package.prepare();
|
||||
mainPackage.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: package.path,
|
||||
cwd: mainPackage.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: package.path,
|
||||
cwd: mainPackage.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: package.path,
|
||||
cwd: mainPackage.path,
|
||||
storage: {
|
||||
links: linksDir.path
|
||||
}
|
||||
|
||||
@@ -63,20 +63,20 @@ describe('bower list', function () {
|
||||
|
||||
it('lists 1 dependency when 1 local package installed', function () {
|
||||
|
||||
var package = new helpers.TempDir({
|
||||
var mainPackage = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'package',
|
||||
main: 'test.txt'
|
||||
}
|
||||
}).prepare();
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
return install([package.path]).then(function() {
|
||||
return install([mainPackage.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: package.path + '#*'
|
||||
package: mainPackage.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 package = new helpers.TempDir({
|
||||
var mainPackage = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'package',
|
||||
main: 'test.txt'
|
||||
}
|
||||
}).prepare();
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
return install([package.path]).then(function() {
|
||||
return install([mainPackage.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: package.path + '#*'
|
||||
package: mainPackage.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 package = new helpers.TempDir({
|
||||
var mainPackage = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'package',
|
||||
main: 'test.txt'
|
||||
}
|
||||
}).prepare();
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
return install([package.path]).then(function() {
|
||||
return install([mainPackage.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 package = new helpers.TempDir({
|
||||
var mainPackage = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'package',
|
||||
main: ['test.txt', 'test2.txt']
|
||||
}
|
||||
}).prepare();
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
return install([package.path]).then(function() {
|
||||
return install([mainPackage.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',
|
||||
|
||||
@@ -5,7 +5,7 @@ var prune = helpers.command('prune');
|
||||
|
||||
describe('bower home', function () {
|
||||
|
||||
var package = new helpers.TempDir({
|
||||
var mainPackage = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'package',
|
||||
dependencies: {
|
||||
@@ -26,30 +26,30 @@ describe('bower home', function () {
|
||||
});
|
||||
|
||||
it('removes extraneous packages', function () {
|
||||
package.prepare({
|
||||
mainPackage.prepare({
|
||||
'bower_components/angular/angular.js': 'angular source',
|
||||
'bower_components/angular/.bower.json': { name: 'angular' }
|
||||
});
|
||||
|
||||
return helpers.run(prune, [{}, { cwd: package.path }]).then(function() {
|
||||
expect(package.exists('bower_components/angular/angular.js'))
|
||||
return helpers.run(prune, [{}, { cwd: mainPackage.path }]).then(function() {
|
||||
expect(mainPackage.exists('bower_components/angular/angular.js'))
|
||||
.to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('leaves non-bower packages', function () {
|
||||
package.prepare({
|
||||
mainPackage.prepare({
|
||||
'bower_components/angular/angular.js': 'angular source'
|
||||
});
|
||||
|
||||
return helpers.run(prune, [{}, { cwd: package.path }]).then(function() {
|
||||
expect(package.exists('bower_components/angular/angular.js'))
|
||||
return helpers.run(prune, [{}, { cwd: mainPackage.path }]).then(function() {
|
||||
expect(mainPackage.exists('bower_components/angular/angular.js'))
|
||||
.to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('deals with custom directory', function () {
|
||||
package.prepare({
|
||||
mainPackage.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: 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);
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -36,7 +36,7 @@ var registerFactory = function (canonicalDir, pkgMeta) {
|
||||
|
||||
describe('bower register', function () {
|
||||
|
||||
var package = new helpers.TempDir({
|
||||
var mainPackage = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'package'
|
||||
}
|
||||
@@ -63,9 +63,9 @@ describe('bower register', function () {
|
||||
});
|
||||
|
||||
it('errors if trying to register private package', function () {
|
||||
package.prepare({ 'bower.json': { private: true } });
|
||||
mainPackage.prepare({ 'bower.json': { private: true } });
|
||||
|
||||
var register = registerFactory(package.path, package.meta());
|
||||
var register = registerFactory(mainPackage.path, mainPackage.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 +74,9 @@ describe('bower register', function () {
|
||||
});
|
||||
|
||||
it('should call registry client with name and url', function () {
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
var register = registerFactory(package.path, package.meta());
|
||||
var register = registerFactory(mainPackage.path, mainPackage.meta());
|
||||
return helpers.run(register, ['some-name', 'git://fake-url.git'])
|
||||
.spread(function(result) {
|
||||
expect(result).to.eql({
|
||||
@@ -87,9 +87,9 @@ describe('bower register', function () {
|
||||
});
|
||||
|
||||
it('should confirm in interactive mode', function () {
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
var register = registerFactory(package.path, package.meta());
|
||||
var register = registerFactory(mainPackage.path, mainPackage.meta());
|
||||
|
||||
var promise = helpers.run(register,
|
||||
['some-name', 'git://fake-url.git', { interactive: true }]
|
||||
@@ -104,9 +104,9 @@ describe('bower register', function () {
|
||||
});
|
||||
|
||||
it('should skip confirming when forcing', function () {
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
var register = registerFactory(package.path, package.meta());
|
||||
var register = registerFactory(mainPackage.path, mainPackage.meta());
|
||||
|
||||
return helpers.run(register,
|
||||
['some-name', 'git://fake-url.git',
|
||||
|
||||
@@ -27,7 +27,9 @@ describe('bower search', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('lists all repositories if no query given', function () {
|
||||
it('lists all repositories when no query given in non-interactive mode', function () {
|
||||
var nonInteractiveConfig = { interactive: false };
|
||||
|
||||
return Q.Promise(function(resolve) {
|
||||
var search = helpers.command('search', {
|
||||
'bower-registry-client': function() {
|
||||
@@ -37,8 +39,45 @@ describe('bower search', function () {
|
||||
}
|
||||
});
|
||||
|
||||
helpers.run(search, [], {});
|
||||
helpers.run(search, [null, nonInteractiveConfig]);
|
||||
});
|
||||
});
|
||||
|
||||
it('lists all repositories when no query given and config.json is enabled in interactive mode', function () {
|
||||
var interactiveConfig = { interactive: true, json: true };
|
||||
|
||||
var search = helpers.command('search', {
|
||||
'bower-registry-client': function() {
|
||||
return {
|
||||
list: function (cb) { return cb(null, 'foobar'); }
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(search, [null, interactiveConfig])
|
||||
.spread(function(result) {
|
||||
expect(result).to.be('foobar');
|
||||
});
|
||||
});
|
||||
|
||||
it('does not list any repositories in interactive mode if no query given and config.json is disabled', function () {
|
||||
var interactiveConfig = { interactive: true };
|
||||
|
||||
var search = helpers.command('search', {
|
||||
'bower-registry-client': function() {
|
||||
return {
|
||||
list: function() { throw 'list called'; },
|
||||
search: function() { throw 'search called'; }
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return helpers.run(search, [null, interactiveConfig])
|
||||
.then(function(commandResult) {
|
||||
expect().fail('should fail');
|
||||
})
|
||||
.catch(function(e) {
|
||||
expect(e.code).to.be('EREADOPTIONS');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,13 +6,14 @@ 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'
|
||||
}
|
||||
'bower.json': {
|
||||
name: 'subPackage'
|
||||
}
|
||||
}).prepare();
|
||||
|
||||
var gitPackage = new helpers.TempDir();
|
||||
@@ -28,14 +29,14 @@ describe('bower update', function () {
|
||||
'bower.json': {
|
||||
name: 'package',
|
||||
dependencies: {
|
||||
subPackage: subPackage.path
|
||||
subPackage: subPackage.path
|
||||
}
|
||||
},
|
||||
'version.txt': '1.0.1'
|
||||
}
|
||||
});
|
||||
|
||||
var package = new helpers.TempDir({
|
||||
var mainPackage = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'package'
|
||||
}
|
||||
@@ -72,14 +73,14 @@ describe('bower update', function () {
|
||||
.to.eql([['jquery'], { forceLatest: true, production: true }]);
|
||||
});
|
||||
|
||||
it('install missing packages', function () {
|
||||
package.prepare();
|
||||
it('install missing packages', function() {
|
||||
mainPackage.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: package.path
|
||||
package: mainPackage.path
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -91,48 +92,84 @@ describe('bower update', function () {
|
||||
});
|
||||
|
||||
it('does not install ignored dependencies', function() {
|
||||
var package3 = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'package3'
|
||||
}
|
||||
}).prepare();
|
||||
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('runs preinstall hook when installing missing package', function () {
|
||||
package.prepare();
|
||||
var package2 = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'package2',
|
||||
dependencies: {
|
||||
package3: package3.path
|
||||
}
|
||||
}
|
||||
}).prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: package.path
|
||||
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();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: mainPackage.path
|
||||
}
|
||||
},
|
||||
'.bowerrc': {
|
||||
@@ -147,14 +184,14 @@ describe('bower update', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('runs postinstall hook when installing missing package', function () {
|
||||
package.prepare();
|
||||
it('runs postinstall hook when installing missing package', function() {
|
||||
mainPackage.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: package.path
|
||||
package: mainPackage.path
|
||||
}
|
||||
},
|
||||
'.bowerrc': {
|
||||
@@ -169,14 +206,14 @@ describe('bower update', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('doesn\'t runs postinstall when no package is update', function () {
|
||||
package.prepare();
|
||||
it('doesn\'t runs postinstall when no package is update', function() {
|
||||
mainPackage.prepare();
|
||||
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
package: package.path
|
||||
package: mainPackage.path
|
||||
}
|
||||
},
|
||||
'.bowerrc': {
|
||||
@@ -195,7 +232,7 @@ describe('bower update', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('updates a package', function () {
|
||||
it('updates a package', function() {
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
@@ -209,7 +246,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: {
|
||||
@@ -288,7 +325,7 @@ describe('bower update', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('runs preinstall hook when updating a package', function () {
|
||||
it('runs preinstall hook when updating a package', function() {
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
@@ -320,7 +357,7 @@ describe('bower update', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('runs postinstall hook when updating a package', function () {
|
||||
it('runs postinstall hook when updating a package', function() {
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
@@ -331,7 +368,7 @@ describe('bower update', function () {
|
||||
});
|
||||
|
||||
return install().then(function() {
|
||||
tempDir.prepare({
|
||||
tempDir.prepare({
|
||||
'bower.json': {
|
||||
name: 'test',
|
||||
dependencies: {
|
||||
|
||||
@@ -5,7 +5,7 @@ var version = helpers.require('lib/commands').version;
|
||||
|
||||
describe('bower list', function () {
|
||||
|
||||
var package = new helpers.TempDir({
|
||||
var mainPackage = new helpers.TempDir({
|
||||
'bower.json': {
|
||||
name: 'foobar',
|
||||
version: '0.0.0'
|
||||
@@ -22,41 +22,41 @@ describe('bower list', function () {
|
||||
});
|
||||
|
||||
it('bumps patch version', function() {
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
return helpers.run(version, ['patch', {}, { cwd: package.path }]).then(function() {
|
||||
expect(package.readJson('bower.json').version).to.be('0.0.1');
|
||||
return helpers.run(version, ['patch', {}, { cwd: mainPackage.path }]).then(function() {
|
||||
expect(mainPackage.readJson('bower.json').version).to.be('0.0.1');
|
||||
});
|
||||
});
|
||||
|
||||
it('bumps minor version', function() {
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
return helpers.run(version, ['minor', {}, { cwd: package.path }]).then(function() {
|
||||
expect(package.readJson('bower.json').version).to.be('0.1.0');
|
||||
return helpers.run(version, ['minor', {}, { cwd: mainPackage.path }]).then(function() {
|
||||
expect(mainPackage.readJson('bower.json').version).to.be('0.1.0');
|
||||
});
|
||||
});
|
||||
|
||||
it('bumps major version', function() {
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
return helpers.run(version, ['major', {}, { cwd: package.path }]).then(function() {
|
||||
expect(package.readJson('bower.json').version).to.be('1.0.0');
|
||||
return helpers.run(version, ['major', {}, { cwd: mainPackage.path }]).then(function() {
|
||||
expect(mainPackage.readJson('bower.json').version).to.be('1.0.0');
|
||||
});
|
||||
});
|
||||
|
||||
it('changes version', function() {
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
return helpers.run(version, ['1.2.3', {}, { cwd: package.path }]).then(function() {
|
||||
expect(package.readJson('bower.json').version).to.be('1.2.3');
|
||||
return helpers.run(version, ['1.2.3', {}, { cwd: mainPackage.path }]).then(function() {
|
||||
expect(mainPackage.readJson('bower.json').version).to.be('1.2.3');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns the new version', function() {
|
||||
package.prepare();
|
||||
mainPackage.prepare();
|
||||
|
||||
return helpers.run(version, ['major', {}, { cwd: package.path }]).then(function(results) {
|
||||
return helpers.run(version, ['major', {}, { cwd: mainPackage.path }]).then(function(results) {
|
||||
expect(results[0]).to.be('1.0.0');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,9 +16,6 @@ describe('GitHub', function () {
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
// Clean nocks
|
||||
nock.cleanAll();
|
||||
|
||||
logger.removeAllListeners();
|
||||
});
|
||||
|
||||
|
||||
@@ -515,6 +515,18 @@ 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 () {
|
||||
|
||||
@@ -25,9 +25,6 @@ describe('UrlResolver', function () {
|
||||
|
||||
afterEach(function () {
|
||||
logger.removeAllListeners();
|
||||
|
||||
// Clean nocks
|
||||
nock.cleanAll();
|
||||
});
|
||||
|
||||
function create(decEndpoint) {
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -10,10 +10,10 @@ var fs = require('../lib/util/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;
|
||||
@@ -162,7 +162,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 () {
|
||||
@@ -220,7 +220,7 @@ exports.command = function (command, stubs) {
|
||||
};
|
||||
|
||||
exports.run = function (command, args) {
|
||||
var logger = command.apply(command, args || []);
|
||||
var logger = command.apply(null, args || []);
|
||||
|
||||
// Hack so we can intercept prompring for data
|
||||
logger.prompt = function(data) {
|
||||
@@ -298,3 +298,16 @@ 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();
|
||||
});
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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'
|
||||
@@ -613,11 +613,15 @@ describe('StandardRenderer', function () {
|
||||
versions: [
|
||||
'1.2.0',
|
||||
'1.2.1',
|
||||
'1.2.2'
|
||||
'1.2.2',
|
||||
'1.2.3+build-1234',
|
||||
'1.2.8-build.2098+sha.cb9c0f2',
|
||||
'1.3.0-rc.5',
|
||||
'1.3.0-beta.18'
|
||||
]
|
||||
});
|
||||
}).spread(function(stdout, stderr) {
|
||||
expect(stdout).to.equal(multiline(function(){/*
|
||||
expect(stdout).to.equal(multiline(function() {/*
|
||||
|
||||
{
|
||||
version: '1.2.3'
|
||||
@@ -627,6 +631,48 @@ describe('StandardRenderer', function () {
|
||||
- 1.2.0
|
||||
- 1.2.1
|
||||
- 1.2.2
|
||||
|
||||
Show 4 additional prereleases with ‘bower info foo --verbose’
|
||||
You can request info for a specific version with 'bower info foo#<version>'
|
||||
|
||||
*/}));
|
||||
});
|
||||
});
|
||||
|
||||
it('outputs full info command log with prereleases', function() {
|
||||
return helpers.capture(function() {
|
||||
var renderer = new StandardRenderer('info', { verbose: true });
|
||||
renderer.end({
|
||||
name: 'foo',
|
||||
latest: {
|
||||
version: '1.2.3'
|
||||
},
|
||||
versions: [
|
||||
'1.2.0',
|
||||
'1.2.1',
|
||||
'1.2.2',
|
||||
'1.2.3+build-1234',
|
||||
'1.2.8-build.2098+sha.cb9c0f2',
|
||||
'1.3.0-rc.5',
|
||||
'1.3.0-beta.18'
|
||||
]
|
||||
});
|
||||
}).spread(function(stdout, stderr) {
|
||||
expect(stdout).to.equal(multiline(function() {/*
|
||||
|
||||
{
|
||||
version: '1.2.3'
|
||||
}
|
||||
|
||||
Available versions:
|
||||
- 1.2.0
|
||||
- 1.2.1
|
||||
- 1.2.2
|
||||
- 1.2.3+build-1234
|
||||
- 1.2.8-build.2098+sha.cb9c0f2
|
||||
- 1.3.0-rc.5
|
||||
- 1.3.0-beta.18
|
||||
|
||||
You can request info for a specific version with 'bower info foo#<version>'
|
||||
|
||||
*/}));
|
||||
@@ -644,7 +690,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 +716,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 +747,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 +765,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 +790,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,11 +825,12 @@ describe('StandardRenderer', function () {
|
||||
]
|
||||
});
|
||||
}).spread(function(stdout, stderr) {
|
||||
expect(stdout).to.equal(multiline(function(){/*
|
||||
expect(stdout).to.equal(multiline(function() {/*
|
||||
|
||||
Usage:
|
||||
|
||||
bower uninstall <name> [<name> ..] [<options>]
|
||||
|
||||
Options:
|
||||
|
||||
-h, --help Show this help message
|
||||
@@ -795,6 +842,7 @@ describe('StandardRenderer', function () {
|
||||
|
||||
Uninstalls a package locally from your bower_components directory
|
||||
|
||||
|
||||
*/}));
|
||||
});
|
||||
});
|
||||
|
||||
177
test/util/download.js
Normal file
177
test/util/download.js
Normal file
@@ -0,0 +1,177 @@
|
||||
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
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,5 @@
|
||||
describe('util', function () {
|
||||
require('./removeIgnores');
|
||||
require('./analytics');
|
||||
require('./download');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user