Compare commits

...

137 Commits

Author SHA1 Message Date
Adam Stankiewicz
87cf578ba8 Update changelog 2015-12-11 21:51:30 +01:00
Adam Stankiewicz
3ead440c7c Update changelog 2015-12-11 21:50:50 +01:00
Adam Stankiewicz
e168c894a2 Bump to 1.7.1 2015-12-11 21:43:21 +01:00
Adam Stankiewicz
75e3661371 Update changelog 2015-12-11 21:42:34 +01:00
Adam Stankiewicz
baf8f7bf6b Fix missing parenthesis 2015-12-11 21:37:08 +01:00
Adam Stankiewicz
88758cd98c Revert "Add bower update --save functionality"
This reverts commit d2ba80e6e9.
2015-12-11 21:33:45 +01:00
Adam Stankiewicz
3bd2d62e67 Revert "Add failing tests for single package updates, optimize older tests"
This reverts commit 6616d09f47.
2015-12-11 21:32:47 +01:00
Adam Stankiewicz
d3eef5772a Revert "Only update packages requested by the user"
This reverts commit e3f402fc66.
2015-12-11 21:25:15 +01:00
Adam Stankiewicz
7c714901d4 Fix test for StandardRenderer 2015-12-11 20:33:54 +01:00
Adam Stankiewicz
7792b6d35d Use coveralls as npm script (fix certain versions of node) 2015-12-11 20:24:40 +01:00
Adam Stankiewicz
2db983dba3 Better formatting of help 2015-12-11 20:16:54 +01:00
Adam Stankiewicz
b9718bb309 Fix search command on no arguments, fixes #2066 2015-12-11 20:15:04 +01:00
Adam Stankiewicz
26f609e614 Ignore for now failing windows build on node 5 2015-12-10 21:25:01 +01:00
Adam Stankiewicz
4c2b56096b Merge pull request #2096 from contolini/readme-clean-up
Readme updates
2015-12-10 17:56:08 +01:00
Chris Contolini
5af929f0be Clean up readme 2015-12-09 20:08:44 -05:00
Adam Stankiewicz
686e883d87 Merge pull request #2094 from accommodavid/tar-test
Add test for tar archives
2015-12-09 11:34:57 +01:00
Adam Stankiewicz
f2767648e7 Merge pull request #2093 from contolini/hide-prereleases
Hide prerelease versions from `bower info`
2015-12-09 11:33:54 +01:00
Accommodavid
9e4bdd270d Add test for tar archives
Adds a test that checks if dependencies that point to tar archives (not
tar.gz) are handled and extracted correctly. Also removes a test from
`test/commands/install.js` that was duplicated.

Re-add postinstall test
2015-12-09 09:05:13 +01:00
Chris Contolini
7cb88ab49f Add renderer tests for prereleases 2015-12-08 17:59:21 -05:00
Chris Contolini
a532c55dca Hide prereleases when showing package info 2015-12-08 17:59:21 -05:00
Adam Stankiewicz
c559432c19 Properly call coveralls script 2015-12-08 20:05:04 +01:00
Adam Stankiewicz
322c49edf4 Get rid of STRICT_REQUIRE flag for coverage testing 2015-12-08 19:52:10 +01:00
Adam Stankiewicz
fe9b27a647 Try to fix appveyor build with npm-env 2015-12-08 19:15:06 +01:00
Adam Stankiewicz
1605374a25 Properly run code coverage on appveyor 2015-12-08 14:32:05 +01:00
Adam Stankiewicz
ac244a1400 Run coverage on appveyor as well 2015-12-08 14:21:05 +01:00
Adam Stankiewicz
d50e50f3b5 Add discord chat link, closes #2088 2015-12-08 11:14:33 +01:00
Adam Stankiewicz
3030469c59 Update update-notifier to 0.6.0 2015-12-08 11:00:51 +01:00
Adam Stankiewicz
977e0ddc52 Update changelog 2015-12-07 20:34:47 +01:00
Adam Stankiewicz
de3e1089da Better formatting of help message 2015-12-07 20:32:33 +01:00
Adam Stankiewicz
7897ad7dba Move bug reports to the top 2015-12-07 16:35:19 +01:00
Adam Stankiewicz
accdab3ece Link bug reports to wiki 2015-12-07 16:34:26 +01:00
David DeSandro
612aaa88eb add help menu for update --save, update --save-dev
Ref #2035
2015-12-07 08:42:17 -05:00
Adam Stankiewicz
338ac99080 Bump to 1.7.0 2015-12-07 13:34:01 +01:00
Adam Stankiewicz
9605bbea5f Bump bower-config to 1.3.0 2015-12-07 13:08:58 +01:00
Adam Stankiewicz
3791aee9d6 Merge pull request #2085 from pertrai1/feature/eslintrc
adding eslintrc for new ruleset option
2015-12-06 15:48:52 +01:00
Rob Simpson
20a223a959 adding eslintrc for new ruleset option 2015-12-06 06:10:13 -05:00
Adam Stankiewicz
ea5bd51327 Merge pull request #2083 from prometheansacrifice/updating-changelog
Adds changelog for release 1.7.0
2015-12-06 11:26:26 +01:00
Manas
b94c20b8da Release 1.7.0 2015-12-05 22:28:18 +05:30
Adam Stankiewicz
b81ba140e3 Bump to 1.6.9 and release 2015-12-04 22:28:09 +01:00
Adam Stankiewicz
4ffdb500b9 Update to npm version of fs-write-stream-atomic 2015-12-04 22:28:09 +01:00
Adam Stankiewicz
1696cde273 Merge pull request #2074 from eppeters/bower-search-prompt-before-listing-all
Prompt before listing all repos when running `bower search` without a query param
2015-12-03 00:21:57 +01:00
Adam Stankiewicz
94ffc35b25 Merge pull request #2070 from contolini/dont-update-all
Only update the packages requested by the user
2015-12-02 23:14:58 +01:00
Edward Peters
5a1e5eb9c7 Make 'bower search' show the help display when a user does not enter a
search term. Keep current behavior when running with config.json
enabled, or in non-interactive mode.

Rewrite bower search tests to cover the different cases of using the
command without a query parameter (interactive w/o config.json,
interactive w/ config.json, and non-interactive)
2015-12-02 17:07:27 -05:00
Chris Contolini
8c1f30b1c8 Format test files to comply with new jscs rules 2015-12-02 14:10:33 -05:00
Chris Contolini
e3f402fc66 Only update packages requested by the user 2015-12-02 14:10:28 -05:00
Chris Contolini
6616d09f47 Add failing tests for single package updates, optimize older tests 2015-12-02 14:10:28 -05:00
Adam Stankiewicz
25ad2ef946 Merge pull request #2076 from prometheansacrifice/instructions-for-squashing-commits
Adds instructions for squashing commits
2015-12-02 13:51:13 +01:00
Manas
ba4a1a9d45 Adds instructions for squashing commits 2015-12-02 13:30:45 +05:30
Adam Stankiewicz
3a37202dc5 Rollback to original fs-write-stream-atomic 2015-12-01 15:58:18 +01:00
Adam Stankiewicz
12258324d3 More code style rules to enforce 2015-11-30 11:06:57 +01:00
Adam Stankiewicz
2adb0b0807 Merge pull request #2063 from AnthonyBobsin/style-guide
Implements jscs to enforce a newly created style guide for the repo.
2015-11-30 10:54:40 +01:00
AnthonyBobsin
19fc84007d Implements jscs to enforce a newly created style guide for the repo. Uses jscs to fix some minor style guide warnings. 2015-11-29 16:22:58 -05:00
Adam Stankiewicz
8fcbd3671d Merge pull request #2062 from contolini/update-save
Add `bower update --save` functionality
2015-11-28 19:29:40 +01:00
Chris Contolini
0eadbef02d Merge branch 'master' into update-save 2015-11-28 08:42:43 -08:00
Adam Stankiewicz
107ad1d3fc Merge pull request #2060 from Utsav2/remove-at
Remove @ in temporary directories
2015-11-28 13:14:30 +01:00
Chris Contolini
d2ba80e6e9 Add bower update --save functionality 2015-11-28 05:40:24 -05:00
Utsav Shah
852a586d5c Replace temp directory name with md5 hash
Fixes issues with characters like @ interfering with directory name
lookups
2015-11-27 13:17:36 -06:00
Utsav Shah
e8a2d92785 Remove @ in temporary directories 2015-11-27 11:36:14 -06:00
Adam Stankiewicz
50ed13e4ee Release 1.6.8 2015-11-27 15:53:52 +01:00
Adam Stankiewicz
cb9b737b9d Merge pull request #2058 from bower/enotdir-coverage
Add directory test for install command
2015-11-27 15:19:10 +01:00
Adam Stankiewicz
700b46162c Remove minor bumps of node from Travis 2015-11-27 14:47:11 +01:00
Accommodavid
0e1153f610 Add ENOTDIR test for install command 2015-11-27 14:43:22 +01:00
Adam Stankiewicz
8669ed2aac Bump bower-config to 1.2.3 2015-11-27 14:08:50 +01:00
Adam Stankiewicz
ca0a36abcf Make downloader work on all platforms, fixes #2050 2015-11-27 13:45:19 +01:00
Adam Stankiewicz
4c6fdc905f Revert "Fix tests on Windows (cleanup of downloaded files)"
This reverts commit bb7c02b07b.
2015-11-27 00:33:15 +01:00
Adam Stankiewicz
cdbc4a123c Merge pull request #2040 from bower/fix-shallow-host
Fix shallow clone host
2015-11-26 18:25:49 +01:00
Adam Stankiewicz
bb7c02b07b Fix tests on Windows (cleanup of downloaded files) 2015-11-26 18:06:26 +01:00
Adam Stankiewicz
4f42aeabd7 Fix tests for abbreviations on Windows 2015-11-26 16:20:59 +01:00
Adam Stankiewicz
b77517ef64 Remove iojs from versions tested on travis (node 4.0 should be enough) 2015-11-26 14:35:52 +01:00
Adam Stankiewicz
b9c3f750eb Remove npm-shrinkwrap.json (bundledDependencies are enough..) 2015-11-26 14:25:14 +01:00
Adam Stankiewicz
aaecbfab17 evert "Merge pull request #2027 from watilde/patch/supports-tilde"
This reverts commit 2ff53fc448, reversing
changes made to 89286e628b.
2015-11-26 14:23:19 +01:00
Adam Stankiewicz
c4539aa603 Update npm-shrinkwrap.json 2015-11-26 14:01:10 +01:00
Adam Stankiewicz
7f801319bf Merge branch 'release-1.6.6' 2015-11-26 12:37:35 +01:00
Adam Stankiewicz
1a990f4563 Release 1.6.7 2015-11-26 12:31:53 +01:00
Trevor Heins
944a328f30 Merge pull request #2051 from kunyan/improve/2049
Add badge links to readme #2048 #2049
2015-11-26 00:00:46 -05:00
Kun Yan
e11b60d812 Add badge links to readme #2048 #2049
Signed-off-by: Kun Yan <kyan@redhat.com>
2015-11-26 10:38:35 +08:00
Adam Stankiewicz
c91e99b782 Merge pull request #2045 from zzarcon/chore/move_abbreviations_from_index
Move abbreviations to a different file
2015-11-26 00:01:43 +01:00
Hector Leon Zarco Garcia
da8ec1e4ab Move abbreviations to a different file 2015-11-25 23:58:30 +01:00
Vlad Filippov
e7868f0fb1 Changelog updates
[skip ci]
2015-11-25 10:54:11 -05:00
Adam Stankiewicz
eca46dbd85 Merge pull request #2042 from paulohp/update-node-version-appveyor
Added major versions (5 and 4) to appveyor
2015-11-25 16:47:13 +01:00
Vlad Filippov
67bd5d026f Bump to 1.6.6 2015-11-25 10:45:42 -05:00
Paulo Pires
51de67cc73 added major versions 5 and 4 to appveyor 2015-11-25 09:33:03 -02:00
Vlad Filippov
3d4f9cd919 Fix shallow clone host 2015-11-24 14:21:27 -05:00
Rob Simpson
2f72cd4b7d Adding contributing link to CONTRIBUTING.md
We now have a section in the wiki for contributors so I added a link to this until all of it can be merged together.
2015-11-24 00:10:47 -05:00
Adam Stankiewicz
2ff53fc448 Merge pull request #2027 from watilde/patch/supports-tilde
Supports ~/ paths to cwd field in .bowerrc
2015-11-21 16:32:52 +01:00
Daijiro Wachi
42cd2e584f Update npm-shrinkwrap.json to add untildify 2015-11-19 23:46:22 +01:00
Daijiro Wachi
49de3cca62 Add a test case to support ~/ paths to cwd field 2015-11-19 23:31:22 +01:00
Daijiro Wachi
718db0309f Supports ~/ paths to cwd field in .bowerrc
+ Add untildify module
+ Update config.js to convert tilde path to home path

Fixes #1784
2015-11-19 21:36:28 +01:00
Adam Stankiewicz
89286e628b Update to fixed version of fs-write-stream-atomic 2015-11-18 15:06:46 +01:00
Adam Stankiewicz
c8042b4781 Fix tests on node 0.10 by updating nock 2015-11-18 14:50:00 +01:00
Adam Stankiewicz
9fdd96c92b Update fs-write-stream-atomic to fork with timing fix
It turned out that removing files synchronously on windows can cause
issues. This commit makes Appveyor build for Windows little better.
2015-11-17 12:13:26 +01:00
Adam Stankiewicz
ce15df27ca Properly destroy read stream for downloads 2015-11-17 12:13:26 +01:00
Rob Simpson
468657bfe2 bug report link fix on readme 2015-11-16 21:27:54 -05:00
Rob Simpson
814180d129 update bug report link to point to wiki 2015-11-16 21:25:48 -05:00
Rob Simpson
93be2fef6d Update README.md 2015-11-16 16:08:04 -05:00
Rob Simpson
3ab71f27ff Update README.md 2015-11-16 16:06:11 -05:00
Adam Stankiewicz
38fa1b6858 Downgrade spawn-sync to 1.0.13 (windows build) 2015-11-15 13:18:33 +01:00
Adam Stankiewicz
c6ed215260 Re-order scripts for appveyor build 2015-11-15 13:15:05 +01:00
Adam Stankiewicz
74eba8d2e8 Move spawn-sync back to devDependencies... 2015-11-15 13:14:28 +01:00
Adam Stankiewicz
5a72dae2c8 Build on both node 0.10 and 0.12 on appveyor 2015-11-15 13:10:10 +01:00
Adam Stankiewicz
6194821643 Skip installing npm and svn for appveyor 2015-11-15 13:06:16 +01:00
Adam Stankiewicz
37aab9c72e Downgrade spawn-sync for appveyor 2015-11-15 13:01:24 +01:00
Adam Stankiewicz
0a0dc8cef9 Update spawn-sync to fix appveyor tests 2015-11-15 12:51:41 +01:00
Adam Stankiewicz
c6d89b79b4 Remove npm-shrinkwrap from devDependencies (issues with npm@3.x) 2015-11-15 12:02:39 +01:00
Adam Stankiewicz
8a435dff27 Update to newest npm in appveyor builds 2015-11-15 11:51:45 +01:00
Michael Robinson
459925eba7 Merge pull request #1972 from pwielgolaski/#1958
fix passing options to request
2015-11-15 22:22:12 +13:00
Adam Stankiewicz
6614a43658 Bump to 1.6.5 2015-11-14 15:56:13 +01:00
Adam Stankiewicz
88fd65ae34 Merge pull request #1988 from faceleg/travis-node-versions
Run travis tests in all versions of node
2015-11-14 15:52:47 +01:00
Adam Stankiewicz
83da088024 Update CONTRIBUTING.md 2015-11-14 15:39:41 +01:00
Piotr Wielgolaski
51a986d0d4 add test for download.js and fix download behavior to not leave temporary files in case of error 2015-11-07 18:26:48 +01:00
Michael Robinson
0aefe8fc0e Be more specific with node version 5 2015-11-05 10:47:39 +13:00
Michael Robinson
2845984169 Use environment vars for node versions because OS X 2015-11-05 10:47:24 +13:00
Michael Robinson
2a91dc5fb1 Updated travis tests to run in supported node versions 2015-11-05 10:43:02 +13:00
Michael Robinson
5eca9274ee Added language to travis.yml 2015-11-05 10:40:44 +13:00
Michael Robinson
d57d81ca85 Run travis tests in all versions of node 2015-11-05 10:38:15 +13:00
Adam Stankiewicz
a5dcf9cc24 Merge pull request #1973 from gronke/remove-insecure-suggestion-from-readme
remove hint to use --allow-root flag from readme
2015-10-26 10:30:59 +01:00
Stefan Grönke
484c8985ed remove hint to use --allow-root flag from readme 2015-10-26 01:14:09 +01:00
Piotr Wielgolaski
931b0a8905 fix passing options to request
options from download need to be pass to request library that make HTTP
request

Also when there is http error stream need to be closed otherwise there
is issue reported that unlink operation is not permitted on Windows
2015-10-24 16:52:22 +02:00
Adam Stankiewicz
bfd1e93325 Install stable version on npm on appveyor 2015-10-24 12:01:59 +02:00
Adam Stankiewicz
bf23751549 Bump to 1.6.4 2015-10-24 11:51:50 +02:00
Adam Stankiewicz
b79034fbb9 Merge pull request #1956 from bower/strip-trailing-slash
strip trailing slash in urlResolver
2015-10-24 11:09:32 +02:00
Adam Stankiewicz
eaa05ac6c1 Merge pull request #1960 from bower/add-user-agent
add User-Agent to downloadd
2015-10-24 11:08:31 +02:00
Adam Stankiewicz
8f0a3d727e Merge pull request #1969 from chrisjons/svn_improvements
use --non-interactive when running svn client
2015-10-24 10:41:21 +02:00
Adam Stankiewicz
b6a524e6b4 Merge pull request #1970 from twalpole/ignore2
fix issue #1962 - ignoredDependenices multiple install run
2015-10-24 10:39:20 +02:00
Thomas Walpole
43d00deb88 fix issue #1962 - ignoredDependenices multiple install run 2015-10-23 11:52:40 -07:00
Christian Jönsson
4836a0cae9 use --non-interactive when running svn client
If there is a problem in connecting to the Subversion server,
e.g. credential or certificate related, the CLI client will pause to
ask the user for input on the console. This is not handled by bower
Subversion Resolver, causing the install process to hang forever
with no message printed to the bower user.

Running the Subversion CLI client with the option --non-interactive
will instead cause the client to exit upon such an error.This is
detected by the bower resolver and the message printed to the user,
making it much easier to investigate and solve the underlying problem.
2015-10-23 13:05:16 +02:00
Adam Stankiewicz
302c4ade51 Leave link only to Support Declaration 2015-10-22 12:19:42 +02:00
Adam Stankiewicz
75d80e014a Mention about Support Declaration and BountySource 2015-10-22 12:15:50 +02:00
Patrick Kettner
0f790f4293 add User-Agent to downloadd 2015-10-20 13:51:50 -07:00
Patrick Kettner
452217e9fa strip trailing slash in urlResolver 2015-10-17 21:48:10 -05:00
Adam Stankiewicz
f66c0cfe5c Update npm to 2.0.0 on travis 2015-10-16 12:05:36 +02:00
Adam Stankiewicz
30898c13d3 Update changelog 2015-10-16 12:01:25 +02:00
Adam Stankiewicz
2330d59ffa Bump to 1.6.3 2015-10-16 11:49:04 +02:00
Adam Stankiewicz
1316be57dc Update bower-config to 1.2.2 2015-10-16 11:46:51 +02:00
Adam Stankiewicz
ff0f2a8f83 Use stat instead of lstat for checking if something is directory, fixes #1951 2015-10-16 11:17:03 +02:00
Adam Stankiewicz
7e5184d342 Merge pull request #1954 from scottaddie/master
Replace README file msysgit references with Git for Windows
2015-10-16 11:05:35 +02:00
Scott Addie
8fa1fd55e9 Replace README file msysgit references with Git for Windows 2015-10-15 22:18:30 -05:00
59 changed files with 1421 additions and 2083 deletions

45
.eslintrc Normal file
View 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
View 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
}
}

View File

@@ -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,

View File

@@ -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

View File

@@ -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))

View File

@@ -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** &mdash; check if the issue has already been
reported.
2. **Check if the issue has been fixed** &mdash; try to reproduce it using the
latest `master` or development branch in the repository.
3. **Isolate the problem** &mdash; 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.

View File

@@ -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');

View File

@@ -1,10 +1,17 @@
# Bower
# Bower - A package manager for the web
[![Build Status](https://travis-ci.org/bower/bower.svg?branch=master)](https://travis-ci.org/bower/bower) [![Windows Build](https://ci.appveyor.com/api/projects/status/jr6vfra8w84plh2g/branch/master?svg=true)](https://ci.appveyor.com/project/sheerun/bower/history) [![Coverage Status](https://img.shields.io/coveralls/bower/bower.svg)](https://coveralls.io/r/bower/bower?branch=master)
> Bower needs resources for its maintenance. Please see [our blog](http://bower.io/blog/) if you think you can help.
[![Build Status](https://travis-ci.org/bower/bower.svg?branch=master)](https://travis-ci.org/bower/bower)
[![Windows Build](https://ci.appveyor.com/api/projects/status/jr6vfra8w84plh2g/branch/master?svg=true)](https://ci.appveyor.com/project/sheerun/bower/history)
[![Coverage Status](https://img.shields.io/coveralls/bower/bower.svg)](https://coveralls.io/r/bower/bower?branch=master)
[![Discord chat](https://img.shields.io/badge/discord-join%20chat%20%E2%86%92-brightgreen.svg?style=flat)](https://discord.gg/0fFM7QF0KpZRh2cY)
[![Issue Stats](http://issuestats.com/github/bower/bower/badge/pr?style=flat)](http://issuestats.com/github/bower/bower)
[![Issue Stats](http://issuestats.com/github/bower/bower/badge/issue?style=flat)](http://issuestats.com/github/bower/bower)
<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:
![msysgit](http://f.cl.ly/items/2V2O3i1p3R2F1r2v0a12/mysgit.png)
<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)

View File

@@ -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

View File

@@ -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
View 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;
};

View File

@@ -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;
}

View File

@@ -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];
};

View File

@@ -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);

View File

@@ -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) {

View File

@@ -1,3 +1,4 @@
/*jshint laxbreak:true*/
var Q = require('q');
var fs = require('../util/fs');
var path = require('path');

View File

@@ -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);
}

View File

@@ -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
});

View File

@@ -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());

View File

@@ -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;

View File

@@ -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

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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));

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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
View 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

File diff suppressed because it is too large Load Diff

View File

@@ -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": [

View File

@@ -2,7 +2,6 @@
"command": "search",
"description": "Finds all packages or a specific package.",
"usage": [
"search [<options>]",
"search <name> [<options>]"
],
"options": [

View File

@@ -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"
}
]
}

View File

@@ -7,6 +7,7 @@ Usage:
{{/each}}
{{/condense}}
Options:
{{#condense}}
@@ -20,3 +21,4 @@ Options:
Description:
{{#indent level="4"}}{{description}}{{/indent}}

View File

@@ -24,3 +24,4 @@ Options:
{{/condense}}
See 'bower help <command>' for more information on a specific command.

View File

@@ -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

Binary file not shown.

View File

@@ -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());
});
});

View File

@@ -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');
});

View File

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

View File

@@ -24,7 +24,7 @@ describe('bower info', function () {
description: 'Hello world! Hello!'
};
var 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'

View File

@@ -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',

View File

@@ -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');
});
});
});
});

View File

@@ -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
}

View File

@@ -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',

View File

@@ -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);
});
});
});

View File

@@ -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',

View File

@@ -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');
});
});
});

View File

@@ -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: {

View File

@@ -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');
});
});

View File

@@ -16,9 +16,6 @@ describe('GitHub', function () {
});
afterEach(function () {
// Clean nocks
nock.cleanAll();
logger.removeAllListeners();
});

View File

@@ -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 () {

View File

@@ -25,9 +25,6 @@ describe('UrlResolver', function () {
afterEach(function () {
logger.removeAllListeners();
// Clean nocks
nock.cleanAll();
});
function create(decEndpoint) {

View File

@@ -14,12 +14,12 @@ describe('scripts', function () {
// We cannot use pure touch, because Windows
var touch = function (file) {
return 'node -e "var fs = require(\'fs\'); fs.closeSync(fs.openSync(\'' + file + '\', \'w\'));"';
return 'node -e "var fs = require(\'fs\'); fs.closeSync(fs.openSync(\'' + file + '\', \'w\'));"';
};
// We cannot use pure touch, because Windows
var touchWithPid = function (file) {
return 'node -e "var fs = require(\'fs\'); fs.closeSync(fs.openSync(process.env.BOWER_PID + \'' + file + '\', \'w\'));"';
return 'node -e "var fs = require(\'fs\'); fs.closeSync(fs.openSync(process.env.BOWER_PID + \'' + file + '\', \'w\'));"';
};
var config = {

View File

@@ -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();
});

View File

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

View File

@@ -17,7 +17,7 @@ describe('StandardRenderer', function () {
message: 'hello world'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.eq(multiline(function(){/*
expect(stdout).to.eq(multiline(function() {/*
bower foobar hello world
*/}));
@@ -32,7 +32,7 @@ describe('StandardRenderer', function () {
message: 'Hello error'
});
}).spread(function(stdout, stderr) {
expect(stderr).to.eq(multiline(function(){/*
expect(stderr).to.eq(multiline(function() {/*
bower EFOOBAR Hello error
*/}));
@@ -48,7 +48,7 @@ describe('StandardRenderer', function () {
details: ' Some awesome details\nMultiline! '
});
}).spread(function(stdout, stderr) {
expect(stderr).to.eq(multiline(function(){/*
expect(stderr).to.eq(multiline(function() {/*
bower EFOOBAR Hello error
Additional error details:
@@ -68,7 +68,7 @@ describe('StandardRenderer', function () {
details: ' Some awesome details\nMultiline! '
});
}).spread(function(stdout, stderr) {
expect(stderr).to.match(new RegExp(multiline(function(){/*
expect(stderr).to.match(new RegExp(multiline(function() {/*
System info:
Bower version: [^\r\n]+
Node version: [^\r\n]+
@@ -91,7 +91,7 @@ describe('StandardRenderer', function () {
]
});
}).spread(function(stdout, stderr) {
expect(stderr).to.string(multiline(function(){/*
expect(stderr).to.string(multiline(function() {/*
Stack trace:
./one.js:1
./two.js:2
@@ -109,7 +109,7 @@ describe('StandardRenderer', function () {
details: ' Some awesome details\nMultiline! '
});
}).spread(function(stdout, stderr) {
expect(stderr).to.match(new RegExp(multiline(function(){/*
expect(stderr).to.match(new RegExp(multiline(function() {/*
Console trace:
Error
at StandardRenderer.error \(.+?\)
@@ -127,7 +127,7 @@ describe('StandardRenderer', function () {
message: 'foobar'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
expect(stdout).to.equal(multiline(function() {/*
bower checkout jquery#foobar
*/}));
@@ -143,7 +143,7 @@ describe('StandardRenderer', function () {
message: 'foobar'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
expect(stdout).to.equal(multiline(function() {/*
bower jquery#master progress foobar
*/}));
@@ -159,7 +159,7 @@ describe('StandardRenderer', function () {
message: 'foobar'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
expect(stdout).to.equal(multiline(function() {/*
bower progress jquery#master foobar
*/}));
@@ -175,7 +175,7 @@ describe('StandardRenderer', function () {
message: 'foobar'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
expect(stdout).to.equal(multiline(function() {/*
bower jquery#master extract foobar
*/}));
@@ -244,7 +244,7 @@ describe('StandardRenderer', function () {
}
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
expect(stdout).to.equal(multiline(function() {/*
Please note that,
dependant1#release1, dependant2#release2 depends on fizfuz#~0.0.0 which resolved to fizfuz#0.0.0
@@ -311,7 +311,7 @@ describe('StandardRenderer', function () {
}
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
expect(stdout).to.equal(multiline(function() {/*
Unable to find a suitable version for , please choose one:
1) fizfuz#~0.0.0 which resolved to 0.0.0 and is required by dependant1#release1, dependant2#release2
@@ -339,7 +339,7 @@ describe('StandardRenderer', function () {
}
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
expect(stdout).to.equal(multiline(function() {/*
{
foo: 'bar',
@@ -362,7 +362,7 @@ describe('StandardRenderer', function () {
message: 'message'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
expect(stdout).to.equal(multiline(function() {/*
bower origin cached message
*/}));
@@ -390,7 +390,7 @@ describe('StandardRenderer', function () {
message: 'message'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
expect(stdout).to.equal(multiline(function() {/*
bower short-origin generic message
bower very-very-long-origin-string generic message
bower short-origin generic message
@@ -534,7 +534,7 @@ describe('StandardRenderer', function () {
]);
}).spread(function(stdout, stderr) {
if (helpers.isWin()) {
expect(stdout).to.equal(multiline(function(){/*
expect(stdout).to.equal(multiline(function() {/*
jquery#0.1.2 components\jquery
@@ -558,7 +558,7 @@ describe('StandardRenderer', function () {
*/}));
} else {
expect(stdout).to.equal(multiline(function(){/*
expect(stdout).to.equal(multiline(function() {/*
jquery#0.1.2 components/jquery
@@ -592,7 +592,7 @@ describe('StandardRenderer', function () {
version: '1.2.3'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
expect(stdout).to.equal(multiline(function() {/*
{
version: '1.2.3'
@@ -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
View 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
}
});
});
});

View File

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