summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore19
-rw-r--r--.rspec1
-rw-r--r--.travis.yml37
-rw-r--r--CHANGELOG.md134
-rw-r--r--CODE_OF_CONDUCT.md40
-rw-r--r--CONTRIBUTING.md26
-rw-r--r--DEVELOPMENT.md6
-rw-r--r--ISSUES.md2
-rw-r--r--README.md24
-rw-r--r--Rakefile29
-rwxr-xr-xbin/bundle2
-rw-r--r--bundler.gemspec9
-rw-r--r--lib/bundler.rb25
-rw-r--r--lib/bundler/anonymizable_uri.rb32
-rw-r--r--lib/bundler/cli.rb169
-rw-r--r--lib/bundler/cli/cache.rb1
-rw-r--r--lib/bundler/cli/clean.rb15
-rw-r--r--lib/bundler/cli/common.rb2
-rw-r--r--lib/bundler/cli/console.rb48
-rw-r--r--lib/bundler/cli/exec.rb51
-rw-r--r--lib/bundler/cli/gem.rb165
-rw-r--r--lib/bundler/cli/install.rb31
-rw-r--r--lib/bundler/cli/outdated.rb2
-rw-r--r--lib/bundler/cli/package.rb9
-rw-r--r--lib/bundler/cli/show.rb32
-rw-r--r--lib/bundler/cli/update.rb4
-rw-r--r--lib/bundler/cli/viz.rb2
-rw-r--r--lib/bundler/definition.rb33
-rw-r--r--lib/bundler/dependency.rb9
-rw-r--r--lib/bundler/dsl.rb45
-rw-r--r--lib/bundler/endpoint_specification.rb2
-rw-r--r--lib/bundler/env.rb69
-rw-r--r--lib/bundler/fetcher.rb52
-rw-r--r--lib/bundler/friendly_errors.rb43
-rw-r--r--lib/bundler/gem_helper.rb26
-rw-r--r--lib/bundler/gem_helpers.rb1
-rw-r--r--lib/bundler/graph.rb5
-rw-r--r--lib/bundler/index.rb30
-rw-r--r--lib/bundler/installer.rb49
-rw-r--r--lib/bundler/lockfile_parser.rb18
-rw-r--r--lib/bundler/parallel_workers.rb18
-rw-r--r--lib/bundler/parallel_workers/thread_worker.rb30
-rw-r--r--lib/bundler/parallel_workers/unix_worker.rb101
-rw-r--r--lib/bundler/parallel_workers/worker.rb69
-rw-r--r--lib/bundler/resolver.rb3
-rw-r--r--lib/bundler/ruby_version.rb2
-rw-r--r--lib/bundler/rubygems_ext.rb1
-rw-r--r--lib/bundler/rubygems_integration.rb57
-rw-r--r--lib/bundler/runtime.rb59
-rw-r--r--lib/bundler/settings.rb38
-rw-r--r--lib/bundler/setup.rb3
-rw-r--r--lib/bundler/shared_helpers.rb69
-rw-r--r--lib/bundler/source.rb12
-rw-r--r--lib/bundler/source/git.rb6
-rw-r--r--lib/bundler/source/git/git_proxy.rb4
-rw-r--r--lib/bundler/source/path.rb21
-rw-r--r--lib/bundler/source/rubygems.rb104
-rw-r--r--lib/bundler/source_list.rb4
-rw-r--r--lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt13
-rw-r--r--lib/bundler/templates/newgem/LICENSE.txt.tt35
-rw-r--r--lib/bundler/templates/newgem/README.md.tt10
-rw-r--r--lib/bundler/templates/newgem/Rakefile.tt2
-rw-r--r--lib/bundler/templates/newgem/bin/console.tt14
-rw-r--r--lib/bundler/templates/newgem/bin/newgem.tt3
-rw-r--r--lib/bundler/templates/newgem/bin/setup.tt7
-rw-r--r--lib/bundler/templates/newgem/exe/newgem.tt3
-rw-r--r--lib/bundler/templates/newgem/gitignore.tt2
-rw-r--r--lib/bundler/templates/newgem/lib/newgem/version.rb.tt2
-rw-r--r--lib/bundler/templates/newgem/newgem.gemspec.tt33
-rw-r--r--lib/bundler/templates/newgem/test/test_newgem.rb.tt2
-rw-r--r--lib/bundler/ui/shell.rb2
-rw-r--r--lib/bundler/version.rb2
-rw-r--r--lib/bundler/worker.rb73
-rw-r--r--man/bundle-config.ronn32
-rw-r--r--man/bundle-install.ronn195
-rw-r--r--man/bundle-package.ronn7
-rw-r--r--man/bundle-update.ronn69
-rw-r--r--man/bundle.ronn6
-rw-r--r--man/gemfile.5.ronn87
-rw-r--r--spec/bundler/anonymizable_uri_spec.rb20
-rw-r--r--spec/bundler/bundler_spec.rb15
-rw-r--r--spec/bundler/cli_spec.rb21
-rw-r--r--spec/bundler/dsl_spec.rb103
-rw-r--r--spec/bundler/fetcher_spec.rb17
-rw-r--r--spec/bundler/gem_helper_spec.rb37
-rw-r--r--spec/bundler/settings_spec.rb40
-rw-r--r--spec/bundler/source/rubygems_spec.rb1
-rw-r--r--spec/bundler/source_list_spec.rb13
-rw-r--r--spec/cache/cache_path_spec.rb33
-rw-r--r--spec/cache/platform_spec.rb20
-rw-r--r--spec/commands/binstubs_spec.rb33
-rw-r--r--spec/commands/check_spec.rb42
-rw-r--r--spec/commands/clean_spec.rb42
-rw-r--r--spec/commands/config_spec.rb37
-rw-r--r--spec/commands/console_spec.rb22
-rw-r--r--spec/commands/exec_spec.rb24
-rw-r--r--spec/commands/licenses_spec.rb13
-rw-r--r--spec/commands/newgem_spec.rb227
-rw-r--r--spec/commands/open_spec.rb12
-rw-r--r--spec/commands/outdated_spec.rb24
-rw-r--r--spec/commands/package_spec.rb26
-rw-r--r--spec/commands/show_spec.rb31
-rw-r--r--spec/install/deploy_spec.rb32
-rw-r--r--spec/install/gemfile/git_spec.rb18
-rw-r--r--spec/install/gemfile/path_spec.rb10
-rw-r--r--spec/install/gemfile_spec.rb26
-rw-r--r--spec/install/gems/dependency_api_spec.rb37
-rw-r--r--spec/install/gems/groups_spec.rb16
-rw-r--r--spec/install/gems/platform_spec.rb30
-rw-r--r--spec/install/gems/simple_case_spec.rb19
-rw-r--r--spec/install/gems/sources_spec.rb36
-rw-r--r--spec/install/gems/standalone_spec.rb4
-rw-r--r--spec/install/gems/win32_spec.rb4
-rw-r--r--spec/install/path_spec.rb2
-rw-r--r--spec/install/post_bundle_message_spec.rb13
-rw-r--r--spec/install/security_policy_spec.rb16
-rw-r--r--spec/lock/lockfile_spec.rb2
-rw-r--r--spec/other/bundle_ruby_spec.rb6
-rw-r--r--spec/other/platform_spec.rb208
-rw-r--r--spec/quality_spec.rb25
-rw-r--r--spec/realworld/edgecases_spec.rb4
-rw-r--r--spec/realworld/parallel_spec.rb40
-rw-r--r--spec/runtime/load_spec.rb16
-rw-r--r--spec/runtime/require_spec.rb25
-rw-r--r--spec/spec_helper.rb55
-rw-r--r--spec/support/builders.rb4
-rw-r--r--spec/support/helpers.rb71
-rw-r--r--spec/support/less_than_proc.rb14
-rw-r--r--spec/update/gems_spec.rb8
-rw-r--r--spec/update/git_spec.rb8
130 files changed, 2762 insertions, 1339 deletions
diff --git a/.gitignore b/.gitignore
index 874a3b8e2f..4f79ffe3ca 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,23 +3,14 @@
# https://help.github.com/articles/ignoring-files and find useful gitignore
# samples at https://github.com/github/gitignore
-# system crap
-.DS_Store
-.*.swp
-
# files created by running the specs
-tmp/
-
-# built gems
-pkg/
-*.gem
+/tmp/
-# rubinius bytecode
-*.rbc
-.rbx/
+# gems built by `rake build`
+/pkg/
# output from ronn
-lib/bundler/man/
+/lib/bundler/man/
# output from ci_reporter
-spec/reports/
+/spec/reports/
diff --git a/.rspec b/.rspec
index 8c18f1abdd..19a7e9ad6d 100644
--- a/.rspec
+++ b/.rspec
@@ -1,2 +1,3 @@
--format documentation
--color
+--warnings
diff --git a/.travis.yml b/.travis.yml
index d9311830e1..ec981a5a2f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,11 @@
language: ruby
script: rake spec:travis
before_script: travis_retry rake spec:travis:deps
+
branches:
only:
- master
+ - 1-8-stable
- 1-7-stable
- 1-6-stable
- 1-5-stable
@@ -11,39 +13,50 @@ branches:
- 1-2-stable
- 1-1-stable
- 1-0-stable
+
notifications:
email:
# andre
- secure: "bCcvqJT7YrBawtkXXwHhT+jOFth7r2Qv/30PkkbhQxk6Jb3xambjCOJ3U6vJ\ngYmiL50exi5lUp3oc3SEbHN5t2CrZqOZDQ6o7P8EAmB5c0oH2RrYaFOkI5Gt\nul/jGH/96A9sj0aMwG7JfdMSfhqj1DUKAm2PnnbXPL853VfmT24="
# terence
- secure: "MQ8eA5Jb8YzEpAo58DRGfVJklAPcEbAulpBZnTxp0am6ldneDtJHbQk21w6R\nj5GsDHlzr/lMp/GHIimtUZ7rLohfND8fj/W7fs1Dkd4eN02/ERt98x3pHlqv\nvZgSnZ39uVYv+OcphraE24QaRaGWLhWZAMYQTVe/Yz50NyG8g1U="
- campfire:
+ slack:
on_success: change
on_failure: always
rooms:
- # Bundler Ops
- secure: MNTSGIySYwHia5gIgRiZxXtPMPDIP9KmzQk7Kq2ZoVvP3mIk8W1TMkvcyFkEf6uCasyVZZixzUBfY+E0BlHAz1ycQpTh1jvSpuIpEVYW48ShJldJ+8W8xfzafyOHii3z7VrDaomEffmMDdmHRsbQAfekMjdR4bTpXtT9V+wOXlg=
+ - secure: JxBi7DDJGkIF/7f/FSN/HUHpvV4EKfQccZHTPd1b2pNJn3GXo6u+tNVbAw2WjxYzPyPQI3ZcYBCU9SEXp/i7VmG8uMzh8Kyildw+miSKYKVb90uYqcsXWzbxwyNBgJLvyDkzST45H5lgnyAicee3WkFes/WDZikIajbH7ztdb04=
+
rvm:
- - 2.1.1
+ - 2.1
- 2.0.0
- 1.9.3
- 1.8.7
+
# Rubygems versions MUST be available as rake tasks
# see Rakefile:66 for the list of possible RGV values
env:
# We need to know if changes to rubygems will break bundler on release
- RGV=master
# Test the latest rubygems release with all of our supported rubies
- - RGV=v2.2.2
+ - RGV=v2.4.4
+
matrix:
+ fast_finish: true
include:
+ # Ruby 2.1, Rubygems 2.2.2 and up
+ - rvm: 2.1
+ env: RGV=v2.2.2
# Ruby 2.0.0, Rubygems 2.0 and up
- rvm: 2.0.0
+ env: RGV=v2.2.2
+ - rvm: 2.0.0
env: RGV=v2.1.11
- rvm: 2.0.0
env: RGV=v2.0.14
# Ruby 1.9.3, Rubygems 1.5.3 and up
- rvm: 1.9.3
+ env: RGV=v2.2.2
+ - rvm: 1.9.3
env: RGV=v2.1.11
- rvm: 1.9.3
env: RGV=v2.0.14
@@ -57,7 +70,7 @@ matrix:
env: RGV=v1.5.3
# Ruby 1.8.7, Rubygems 1.3.6 and up
- rvm: 1.8.7
- env: RGV=v2.1.11
+ env: RGV=v2.2.2
- rvm: 1.8.7
env: RGV=v2.0.14
- rvm: 1.8.7
@@ -82,20 +95,14 @@ matrix:
# Ruby 1.9.2 sanity check
# (but it's just too slow and sometimes goes over the Travis limit)
- rvm: 1.9.2
- env: RGV=v2.2.2
+ env: RGV=v2.3.0
# Ruby-head (we want to know how we're doing, but not fail the build)
- rvm: ruby-head
env: RGV=master
- # JRuby, the latest (not maintained, but good to know)
- - rvm: jruby
- env: RGV=v2.2.2
- # Rubinius, the latest (not maintained, but good to know)
- - rvm: rbx
- env: RGV=v2.2.2
allow_failures:
- rvm: 1.8.7
- env: RGV=2.1.11
+ env: RGV=v2.1.11
- rvm: 1.9.2
- rvm: ruby-head
- rvm: jruby
- - rvm: rbx
+ - rvm: rbx-2
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0c7f609c77..d7bde91d2e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,120 @@
+## 1.8.8 (2015-04-29)
+
+Bugfixes:
+
+ - Respect Gemfile sources when installing a gem present in two sources (#3585, @tmoore)
+
+## 1.8.7 (2015-04-07)
+
+Bugfixes:
+
+ - stop suppressing errors inside gems that get required (#3549, @indirect)
+
+## 1.8.6 (2015-03-30)
+
+Bugfixes:
+
+ - keep gems locked when updating another gem from the same source (#3250, @indirect)
+ - resolve race that could build gems without saved arguments (#3404, @indirect)
+
+## 1.8.5 (2015-03-11)
+
+Bugfixes:
+
+ - remove MIT license from gemspec when removing license file (@indirect)
+ - respect 'no' immediately as well as saving it in `gem` config (@kirs)
+
+## 1.8.4 (2015-03-05)
+
+Bugfixes:
+
+ - document --all-platforms option (#3449, @moeffju)
+ - find gems from all sources on exec after install (#3450, @TimMoore)
+
+## 1.8.3 (2015-02-24)
+
+Bugfixes:
+
+ - handle boolean values for gem settings (@EduardoBautista)
+ - stop always looking for updated `path` gems (#3414, #3417, #3429, @TimMoore)
+
+## 1.8.2 (2015-02-14)
+
+Bugfixes:
+
+ - allow config settings for gems with 'http' in the name again (#3398, @TimMoore)
+
+## 1.8.1 (2015-02-13)
+
+Bugfixes:
+
+ - synchronize building git gem native extensions (#3385, @antifuchs & @indirect)
+ - set gemspec bindir correctly (#3392, @TimMoore)
+ - request lockfile deletion when it is malformed (#3396, @indirect)
+ - explain problem when mirror config is missing (#3386, @indirect)
+ - explain problem when caching causes permission error (#3390, @indirect)
+ - normalize URLs in config keys (#3391, @indirect)
+
+## 1.8.0 (2015-02-10)
+
+Bugfixes:
+
+ - gemfile `github` blocks now work (#3379, @indirect)
+
+Bugfixes from v1.7.13:
+
+ - look up installed gems in remote sources (#3300, #3368, #3377, #3380, #3381, @indirect)
+ - look up gems across all sources to satisfy dependencies (#3365, @keiths-osc)
+ - request dependencies for no more than 100 gems at a time (#3367, @segiddins)
+
+## 1.8.0.rc (2015-01-26)
+
+Features:
+
+ - add `config disable_multisource` option to ensure sources can't compete (@indirect)
+
+Bugfixes:
+
+ - don't add extra quotes around long, quoted config values (@aroben, #3338)
+
+Security:
+
+ - warn when more than one top-level source is present (@indirect)
+
+## 1.8.0.pre (2015-01-26)
+
+Features:
+
+ - add metadata allowed_push_host to new gem template (#3002, @juanitofatas)
+ - adds a `--no-install` flag to `bundle package` (@d-reinhold)
+ - add `bundle config auto_install true` to install automatically (@smashwilson)
+ - add `bundle viz --without` to exclude gem groups from resulting graph (@fnichol)
+ - prevent whitespace in gem declarations with clear messaging (@benlakey)
+ - tries to find a `bundler-<command>` executable on your path for non-bundler commands (@andremedeiros)
+ - tries to find `gems.rb` and it's new counterpart, `gems.locked` (@andremedeiros)
+ - change the initial version of new gems from `0.0.1` to `0.1.0` (@petedmarsh)
+ - add `package --all-platforms` to cache gems for each known platform (@ccutrer)
+ - speed up `exec` when running commands on the $PATH (@kirs)
+ - add gem code of conduct file and option (@kirs)
+ - add config settings for gem license and tests (@kirs)
+ - add `bin/setup` and `bin/console` to new gems (@indirect)
+ - include configured user-agent in network requests (@indirect)
+ - support `github`, `gist`, and `bitbucket` options on git gems (@indirect)
+ - add `package --cache-path` and `config cache_path` for cache location (@jnraine)
+ - allow `config` to work even when a Gemfile is not present (@dholdren)
+ - add `config gemfile /path` for other Gemfile locations (@dholdren)
+
+Bugfixes:
+
+ - reduce memory usage with threaded parallel workers (@Who828)
+ - support read-only git gems (@pmahoney)
+ - various resolver performance improvements (@dubek)
+ - untaint git gem paths for Rubygems compatibility (@tdtds)
+
+Documentation:
+
+ - add missing Gemfile global `path` explanation (@agenteo)
+
## 1.7.15 (2015-04-29)
Bugfixes:
@@ -121,6 +238,22 @@ Bugfixes:
- Warn on ambiguous gems available from more than one source (@TimMoore)
+## 1.6.7 (2014-10-19)
+
+Features:
+
+ - warn to upgrade when using useless source blocks (@danfinnie)
+
+Documentation:
+
+ - explain how to use gem server credentials via ENV (@hwartig)
+
+## 1.6.6 (2014-08-23)
+
+Bugfixes:
+
+ - restore Gemfile credentials to Gemfile.lock (@indirect)
+
## 1.6.5 (2014-07-23)
Bugfixes:
@@ -202,6 +335,7 @@ Features:
- `bundle show --verbose` Add gem summary to the output (@lardcanoe)
- `bundle gem GEM --ext` now generates a skeleton for a C extension (@superdealloc)
- Avoid using threequals operator where possible (@as-cii)
+ - Add `bundle update --group` to update specific group (#2731 @banyan)
Documentation:
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000000..e5e8828d73
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,40 @@
+# Bundler Code of Conduct
+
+The Bundler project strongly values contributors from anywhere, regardless of gender, sexual orientation, disability, physical appearance, body size, race, or religion. As a result, the Bundler team has agreed to and enforces this code of conduct in order to provide a harassment-free experience for everyone who participates in the development of Bundler.
+
+### Summary
+
+Harassment in code and discussion or violation of physical boundaries is completely unacceptable anywhere in the Bundler project’s codebases, issue trackers, IRC channel, Campfire, mailing lists, meetups, and other events. Violators will be warned and then blocked or banned by the core team at or before the 3rd violation.
+
+### In detail
+
+Harassment includes offensive verbal comments related to gender, sexual orientation, disability, physical appearance, body size, race, religion, sexual images, deliberate intimidation, stalking, sustained disruption, and unwelcome sexual attention.
+
+Individuals asked to stop any harassing behavior are expected to comply immediately.
+
+Maintainers, including the core team, are also subject to the anti-harassment policy.
+
+If anyone engages in harassing behavior, including maintainers, we may take appropriate action, up to and including warning the offender, deletion of comments, removal from the project’s codebase and communication systems, and escalation to Github support.
+
+If you are being harassed, notice that someone else is being harassed, or have any other concerns, please contact a member of [the core team](http://bundler.io/contributors.html) or [email the core team](mailto:team@bundler.io) immediately.
+
+We expect everyone to follow these rules anywhere in the Bundler project’s codebases, issue trackers, IRC channel, group chat, and mailing lists.
+
+Finally, don't forget that it is human to make mistakes! We all do. Let’s work together to help each other, resolve issues, and learn from the mistakes that we will all inevitably make from time to time.
+
+
+### Thanks
+
+Thanks to the [JSConf Code of Conduct](http://jsconf.com/codeofconduct.html) and [Fedora Code of Conduct](http://fedoraproject.org/code-of-conduct) for inspiration and ideas. Additional thanks to [Contributor Covenant](http://contributor-covenant.org) for the [default code of conduct](https://github.com/bundler/bundler/blob/master/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt) included in generated gems.
+
+
+### License
+
+<p class="license" xmlns:dct="http://purl.org/dc/terms/" xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#">
+ To the extent possible under law, <a rel="dct:publisher" href="http://bundler.io">The Bundler Team</a> has waived all copyright and related or neighboring rights to the <span property="dct:title">Bundler Code of Conduct</span>. This work is published from the <span property="vcard:Country" datatype="dct:ISO3166" content="US" about="http://bundler.io">United States.</span>
+ <br>
+ <br>
+ <a rel="license" href="http://creativecommons.org/publicdomain/zero/1.0/">
+ <img src="http://i.creativecommons.org/p/zero/1.0/88x31.png" style="border-style: none;" alt="CC0">
+ </a>
+</p> \ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a2fc0cec3d..24e0cdaa26 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,18 +2,20 @@
Bundler welcomes contributions from *everyone*. While contributing, please follow the project [code of conduct](http://bundler.io/conduct.html), so that everyone can be included.
-Here are some ways you can contribute:
-
- - by using prerelease versions
- - by reporting bugs
- - by suggesting new features
- - by writing or editing documentation
- - by closing issues
- - by reviewing patches
- - by refactoring code
- - by writing code (no patch is too small! fix typos or bad whitespace)
-
-If you'd like to help make Bundler better, you totally rock! Please check out the [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md) file for an introduction to the project, guidelines for contributing, and details about what would be helpful.
+If you'd like to help make Bundler better, you totally rock! Here are some ways you can contribute:
+
+ - by using prerelease versions (run `gem install bundler --pre`)
+ - by [reporting bugs you encounter](https://github.com/bundler/bundler/issues/new)
+ - by [suggesting new features](https://github.com/bundler/bundler-features/issues/new)
+ - by adding to or editing [the Bundler documentation website](http://bundler.io) and [Bundler man pages](http://bundler.io/man/bundle.1.html)
+ - by [checking issues for completeness](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md#bug-triage)
+ - by closing issues that are not complete
+ - by adding a failing test for reproducible [reported bugs](https://github.com/bundler/bundler/issues)
+ - by reviewing [pull requests](https://github.com/bundler/bundler/pulls) and suggesting improvements
+ - by improving existing code, including [suggestions from PullReview](https://www.pullreview.com/github/bundler/bundler/reviews/master)
+ - by [writing code](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md) (no patch is too small! fix typos or bad whitespace)
+
+If you need help getting started, check out the [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md) file for steps that will get you up and running.
Thanks for helping us make Bundler better.
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index dc52a9907a..a31c5a3781 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -2,7 +2,7 @@ Great to have you here! Here are a few ways you can help out with [Bundler](http
# Where should I start?
-You can start learning about Bundler by reading [the documentation](http://bundler.io). If you want, you can also read a (lengthy) explanation of [why Bundler exists and what it does](http://bundler.io/v1.5/rationale.html). You can also check out discussions about Bundler on the [Bundler mailing list](https://groups.google.com/group/ruby-bundler) and in the [Bundler IRC channel](http://webchat.freenode.net/?channels=%23bundler), which is #bundler on Freenode.
+You can start learning about Bundler by reading [the documentation](http://bundler.io). If you want, you can also read a (lengthy) explanation of [why Bundler exists and what it does](http://bundler.io/rationale.html). You can also check out discussions about Bundler on the [Bundler mailing list](https://groups.google.com/group/ruby-bundler) and in the [Bundler IRC channel](http://webchat.freenode.net/?channels=%23bundler), which is #bundler on Freenode. Please note that this project is released with a contributor [code of conduct](http://bundler.io/conduct.html). By participating in this project you agree to abide by its terms.
## Your first commits
@@ -70,7 +70,7 @@ Finally, the ticket may be a duplicate of another older ticket. If you notice a
If you would like to add a new feature to Bundler, please follow these steps:
- 1. [Create an issue](https://github.com/bundler/bundler-features/issues/new) to discuss your feature.
+ 1. [Create an issue](https://github.com/bundler/bundler-features/issues/new) in the bundler-features repo to discuss your feature.
2. Base your commits on the master branch, since we follow [SemVer](http://semver.org) and don't add new features to old releases.
3. Commit the code and at least one test covering your changes to a feature branch in your fork.
4. Put a line in the [CHANGELOG](https://github.com/bundler/bundler/blob/master/CHANGELOG.md) summarizing your changes under the next release under the "Features" heading.
@@ -115,3 +115,5 @@ Finally, sharing your experiences and discoveries by writing them up is a valuab
Examples of how Bundler is used help everyone, and we’ve discovered that people already use it in ways that we never imagined when we were writing it. If you’re still not sure what to write about, there are also several projects doing interesting things based on Bundler. They could probably use publicity too.
If you let someone on the core team know you wrote about Bundler, we will add your post to the list of Bundler resources on the Github project wiki.
+
+Finally, participate carefully in the all contributors to the Bundler project must agree to the contributor [code of conduct](http://bundler.io/conduct.html). By participating in this project you agree to abide by its terms.
diff --git a/ISSUES.md b/ISSUES.md
index 560f6508e0..221d04d282 100644
--- a/ISSUES.md
+++ b/ISSUES.md
@@ -10,7 +10,7 @@ discuss features. The bundler issue tracker is only for bugs.**
Instructions for common Bundler uses can be found on the [Bundler documentation site](http://bundler.io/).
-Detailed information about each Bundler command, including help with common problems, can be found in the [Bundler man pages](http://bundler.io/v1.3/man/bundle.1.html).
+Detailed information about each Bundler command, including help with common problems, can be found in the [Bundler man pages](http://bundler.io/man/bundle.1.html).
## Troubleshooting
diff --git a/README.md b/README.md
index ef5a8fe2dc..1719323aff 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,11 @@
-[![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg)](https://codeclimate.com/github/bundler/bundler)
-[![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg)](https://travis-ci.org/bundler/bundler)
-[![Version ](https://img.shields.io/gem/v/bundler.svg)](https://rubygems.org/gems/bundler)
+[![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler)
+[![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg?style=flat)](https://travis-ci.org/bundler/bundler)
+[![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg?style=flat)](https://codeclimate.com/github/bundler/bundler)
+[![Inline docs ](http://inch-ci.org/github/bundler/bundler.svg?style=flat)](http://inch-ci.org/github/bundler/bundler)
# Bundler: a gem to bundle gems
-Bundler keeps ruby applications running the same code on every machine.
+
+Bundler makes sure Ruby applications run the same code on every machine.
It does this by managing the gems that the application depends on. Given a list of gems, it can automatically download and install those gems, as well as any other gems needed by the gems that are listed. Before installing gems, it checks the versions of every gem to make sure that they are compatible, and can all be loaded at the same time. After the gems have been installed, Bundler can help you update some or all of them when new versions become available. Finally, it records the exact versions that have been installed, so that others can install the exact same gems.
@@ -23,18 +25,12 @@ See [bundler.io](http://bundler.io) for the full documentation.
For help with common problems, see [ISSUES](https://github.com/bundler/bundler/blob/master/ISSUES.md).
-### Contributing
-
-If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md)
-
-The `master` branch contains our current progress towards version 1.5. Versions 1.0-1.3 each have their own stable branches. Please submit bugfixes as pull requests to the stable branch for the version you would like to fix.
-
-### Core Team
-
-The Bundler core team consists of André Arko ([@indirect](http://github.com/indirect)), Terence Lee ([@hone](http://github.com/hone)), and Jessica Lynn Suttles ([@jlsuttles](http://github.com/jlsuttles)), with support and advice from original Bundler author Yehuda Katz ([@wycats](http://github.com/wycats)).
-
### Other questions
To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/bundler/bundler/blob/master/CHANGELOG.md).
Feel free to chat with the Bundler core team (and many other users) on IRC in the [#bundler](irc://irc.freenode.net/bundler) channel on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler).
+
+### Contributing
+
+If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md)
diff --git a/Rakefile b/Rakefile
index e3812c0725..114f0020e1 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,10 +1,10 @@
# -*- encoding: utf-8 -*-
$:.unshift File.expand_path("../lib", __FILE__)
-require 'rubygems'
require 'shellwords'
require 'benchmark'
RUBYGEMS_REPO = File.expand_path("tmp/rubygems")
+BUNDLER_SPEC = Gem::Specification.load("bundler.gemspec")
def safe_task(&block)
yield
@@ -30,8 +30,7 @@ end
namespace :spec do
desc "Ensure spec dependencies are installed"
task :deps do
- spec = Gem::Specification.load("bundler.gemspec")
- deps = Hash[spec.development_dependencies.map do |d|
+ deps = Hash[BUNDLER_SPEC.development_dependencies.map do |d|
[d.name, d.requirement.to_s]
end]
@@ -65,7 +64,7 @@ namespace :spec do
# https://github.com/rubygems/rubygems/issues/784
sh "gem update --system 2.1.11"
else
- # Downgrade Rubygems so RSpec 3 can be instaled
+ # Downgrade Rubygems so RSpec 3 can be installed
# https://github.com/rubygems/rubygems/issues/813
sh "gem update --system 2.2.0"
end
@@ -76,13 +75,12 @@ namespace :spec do
end
begin
+ rspec = BUNDLER_SPEC.development_dependencies.find{|d| d.name == "rspec" }
+ gem 'rspec', rspec.requirement.to_s
require 'rspec/core/rake_task'
desc "Run specs"
- RSpec::Core::RakeTask.new do |t|
- t.rspec_opts = %w(--format documentation --color)
- t.ruby_opts = %w(-w)
- end
+ RSpec::Core::RakeTask.new
task :spec => "man:build"
namespace :spec do
@@ -114,7 +112,7 @@ begin
rubyopt = ENV["RUBYOPT"]
# When editing this list, also edit .travis.yml!
branches = %w(master 2.2)
- releases = %w(v1.3.6 v1.3.7 v1.4.2 v1.5.3 v1.6.2 v1.7.2 v1.8.29 v2.0.14 v2.1.11 v2.2.2)
+ releases = %w(v1.3.6 v1.3.7 v1.4.2 v1.5.3 v1.6.2 v1.7.2 v1.8.29 v2.0.14 v2.1.11 v2.2.2 v2.4.4)
(branches + releases).each do |rg|
desc "Run specs with Rubygems #{rg}"
RSpec::Core::RakeTask.new(rg) do |t|
@@ -160,7 +158,9 @@ begin
end
task "setup_co" do
- ENV["RUBYOPT"] = "-I#{File.expand_path ENV['RG']} #{rubyopt}"
+ rg = File.expand_path ENV['RG']
+ puts "Running specs against Rubygems in #{rg}..."
+ ENV["RUBYOPT"] = "-I#{rg} #{rubyopt}"
end
task "co" => "setup_co"
@@ -234,12 +234,15 @@ begin
task :clean do
rm_rf "lib/bundler/man"
end
+
+ task(:require) { }
end
rescue LoadError
namespace :man do
- task(:build) { warn "Install the ronn gem to be able to release!" }
- task(:clean) { warn "Install the ronn gem to be able to release!" }
+ task(:require) { abort "Install the ronn gem to be able to release!" }
+ task(:build) { warn "Install the ronn gem to build the help pages" }
+ task(:clean) { }
end
end
@@ -251,6 +254,6 @@ end
require 'bundler/gem_tasks'
task :build => ["man:clean", "man:build"]
-task :release => ["man:clean", "man:build"]
+task :release => ["man:require", "man:clean", "man:build"]
task :default => :spec
diff --git a/bin/bundle b/bin/bundle
index 63285e96e2..89c823eae3 100755
--- a/bin/bundle
+++ b/bin/bundle
@@ -6,7 +6,7 @@ Signal.trap("INT") { exit 1 }
require 'bundler'
# Check if an older version of bundler is installed
$LOAD_PATH.each do |path|
- if path =~ %r'/bundler-0.(\d+)' && $1.to_i < 9
+ if path =~ %r'/bundler-0\.(\d+)' && $1.to_i < 9
err = "Looks like you have a version of bundler that's older than 0.9.\n"
err << "Please remove your old versions.\n"
err << "An easy way to do this is by running `gem cleanup bundler`."
diff --git a/bundler.gemspec b/bundler.gemspec
index 89439612b1..bd7e32e7c9 100644
--- a/bundler.gemspec
+++ b/bundler.gemspec
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
s.version = Bundler::VERSION
s.licenses = ['MIT']
s.authors = ["André Arko", "Terence Lee", "Carl Lerche", "Yehuda Katz"]
- s.email = ["andre@arko.net"]
+ s.email = ["andre.arko+terence.lee@gmail.com"]
s.homepage = "http://bundler.io"
s.summary = %q{The best way to manage your application's dependencies}
s.description = %q{Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably}
@@ -21,9 +21,10 @@ Gem::Specification.new do |s|
s.add_development_dependency 'ronn', '~> 0.7.3'
s.add_development_dependency 'rspec', '~> 3.0'
- s.files = `git ls-files -z`.split("\x0")
- s.files += Dir.glob('lib/bundler/man/**/*') # man/ is ignored by git
- s.test_files = s.files.grep(%r{^spec/})
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ # we don't check in man pages, but we need to ship them because
+ # we use them to generate the long-form help for each command.
+ s.files += Dir.glob('lib/bundler/man/**/*')
s.executables = %w(bundle bundler)
s.require_paths = ["lib"]
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 428723c082..025337418c 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -191,7 +191,13 @@ module Bundler
end
def root
- @root ||= default_gemfile.dirname.expand_path
+ @root ||= begin
+ default_gemfile.dirname.expand_path
+ rescue GemfileNotFound
+ bundle_dir = default_bundle_dir
+ raise GemfileNotFound, "Could not locate Gemfile or .bundle/ directory" unless bundle_dir
+ Pathname.new(File.expand_path("..", bundle_dir))
+ end
end
def app_config_path
@@ -202,7 +208,7 @@ module Bundler
def app_cache(custom_path = nil)
path = custom_path || root
- path.join("vendor/cache")
+ path.join(self.settings.app_cache_path)
end
def tmp(name = Process.pid.to_s)
@@ -210,11 +216,16 @@ module Bundler
@tmp.join(name)
end
+ def cleanup
+ FileUtils.remove_entry_secure(@tmp) if @tmp
+ rescue
+ end
+
def settings
return @settings if defined?(@settings)
@settings = Settings.new(app_config_path)
rescue GemfileNotFound
- @settings = Settings.new
+ @settings = Settings.new(Pathname.new(".bundle").expand_path)
end
def with_original_env
@@ -253,6 +264,10 @@ module Bundler
SharedHelpers.default_lockfile
end
+ def default_bundle_dir
+ SharedHelpers.default_bundle_dir
+ end
+
def system_bindir
# Gem.bindir doesn't always return the location that Rubygems will install
# system binaries. If you put '-n foo' in your .gemrc, Rubygems will
@@ -369,6 +384,10 @@ module Bundler
@ruby_version ||= SystemRubyVersion.new
end
+ def reset!
+ @definition = nil
+ end
+
private
def eval_yaml_gemspec(path, contents)
diff --git a/lib/bundler/anonymizable_uri.rb b/lib/bundler/anonymizable_uri.rb
index 032346fd25..333a568f84 100644
--- a/lib/bundler/anonymizable_uri.rb
+++ b/lib/bundler/anonymizable_uri.rb
@@ -3,14 +3,30 @@ module Bundler
attr_reader :original_uri,
:without_credentials
- def initialize(original_uri)
- @original_uri = original_uri.freeze
- @without_credentials ||=
- if original_uri.userinfo
- original_uri.dup.tap { |uri| uri.user = uri.password = nil }.freeze
- else
- original_uri
- end
+ def initialize(original_uri, fallback_auth = nil)
+ @original_uri = apply_auth(original_uri, fallback_auth).freeze
+ @without_credentials = remove_auth(@original_uri).freeze
end
+
+ private
+
+ def apply_auth(uri, auth = nil)
+ if auth && uri.userinfo.nil?
+ uri = uri.dup
+ uri.userinfo = auth
+ end
+
+ uri
+ end
+
+ def remove_auth(uri)
+ if uri.userinfo
+ uri = uri.dup
+ uri.user = uri.password = nil
+ end
+
+ uri
+ end
+
end
end
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index c3e5d8b468..6a22072565 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -4,19 +4,25 @@ require 'bundler/vendored_thor'
module Bundler
class CLI < Thor
include Thor::Actions
+ AUTO_INSTALL_CMDS = %w[show binstubs outdated exec open console licenses clean]
def self.start(*)
super
rescue Exception => e
Bundler.ui = UI::Shell.new
raise e
+ ensure
+ Bundler.cleanup
end
- def initialize(*)
+ def initialize(*args)
super
- ENV['BUNDLE_GEMFILE'] = File.expand_path(options[:gemfile]) if options[:gemfile]
+ current_cmd = args.last[:current_command].name
+ custom_gemfile = options[:gemfile] || Bundler.settings[:gemfile]
+ ENV['BUNDLE_GEMFILE'] = File.expand_path(custom_gemfile) if custom_gemfile
Bundler::Retry.attempts = options[:retry] || Bundler.settings[:retry] || Bundler::Retry::DEFAULT_ATTEMPTS
Bundler.rubygems.ui = UI::RGProxy.new(Bundler.ui)
+ auto_install if AUTO_INSTALL_CMDS.include?(current_cmd)
rescue UnknownArgumentError => e
raise InvalidOption, e.message
ensure
@@ -29,10 +35,10 @@ module Bundler
stop_on_unknown_option! :exec
default_task :install
- class_option "no-color", :type => :boolean, :banner => "Disable colorization in output"
- class_option "verbose", :type => :boolean, :banner => "Enable verbose output mode", :aliases => "-V"
- class_option "retry", :type => :numeric, :aliases => "-r", :banner =>
- "Specify the number of times you wish to attempt network commands"
+ class_option "no-color", :type => :boolean, :desc => "Disable colorization in output"
+ class_option "retry", :type => :numeric, :aliases => "-r", :banner => "NUM",
+ :desc => "Specify the number of times you wish to attempt network commands"
+ class_option "verbose", :type => :boolean, :desc => "Enable verbose output mode", :aliases => "-V"
def help(cli = nil)
case cli
@@ -64,6 +70,12 @@ module Bundler
end
end
+ def self.handle_no_command_error(command, has_namespace = $thor_runner)
+ return super unless command_path = Bundler.which("bundler-#{command}")
+
+ Kernel.exec(command_path, *ARGV[1..-1])
+ end
+
desc "init [OPTIONS]", "Generates a Gemfile into the current working directory"
long_desc <<-D
Init generates a default Gemfile in the current working directory. When adding a
@@ -82,12 +94,12 @@ module Bundler
all gems are found, Bundler prints a success message and exits with a status of 0.
If not, the first missing gem is listed and Bundler exits status 1.
D
+ method_option "dry-run", :type => :boolean, :default => false, :banner =>
+ "Lock the Gemfile"
method_option "gemfile", :type => :string, :banner =>
"Use the specified gemfile instead of Gemfile"
method_option "path", :type => :string, :banner =>
"Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME). Bundler will remember this value for future installs on this machine"
- method_option "dry-run", :type => :boolean, :default => false, :banner =>
- "Lock the Gemfile"
def check
require 'bundler/cli/check'
Check.new(options).run
@@ -104,41 +116,41 @@ module Bundler
If the bundle has already been installed, bundler will tell you so and then exit.
D
- method_option "without", :type => :array, :banner =>
- "Exclude gems that are part of the specified named group."
+ method_option "binstubs", :type => :string, :lazy_default => "bin", :banner =>
+ "Generate bin stubs for bundled gems to ./bin"
+ method_option "clean", :type => :boolean, :banner =>
+ "Run bundle clean automatically after install"
+ method_option "deployment", :type => :boolean, :banner =>
+ "Install using defaults tuned for deployment environments"
+ method_option "frozen", :type => :boolean, :banner =>
+ "Do not allow the Gemfile.lock to be updated after this install"
+ method_option "full-index", :type => :boolean, :banner =>
+ "Use the rubygems modern index instead of the API endpoint"
method_option "gemfile", :type => :string, :banner =>
"Use the specified gemfile instead of Gemfile"
- method_option "no-prune", :type => :boolean, :banner =>
- "Don't remove stale gems from the cache."
+ method_option "jobs", :aliases => "-j", :type => :numeric, :banner =>
+ "Specify the number of jobs to run in parallel"
+ method_option "local", :type => :boolean, :banner =>
+ "Do not attempt to fetch gems remotely and use the gem cache instead"
method_option "no-cache", :type => :boolean, :banner =>
"Don't update the existing gem cache."
+ method_option "no-prune", :type => :boolean, :banner =>
+ "Don't remove stale gems from the cache."
+ method_option "path", :type => :string, :banner =>
+ "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME). Bundler will remember this value for future installs on this machine"
method_option "quiet", :type => :boolean, :banner =>
"Only output warnings and errors."
- method_option "local", :type => :boolean, :banner =>
- "Do not attempt to fetch gems remotely and use the gem cache instead"
- method_option "binstubs", :type => :string, :lazy_default => "bin", :banner =>
- "Generate bin stubs for bundled gems to ./bin"
method_option "shebang", :type => :string, :banner =>
"Specify a different shebang executable name than the default (usually 'ruby')"
- method_option "path", :type => :string, :banner =>
- "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME). Bundler will remember this value for future installs on this machine"
- method_option "system", :type => :boolean, :banner =>
- "Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
- method_option "frozen", :type => :boolean, :banner =>
- "Do not allow the Gemfile.lock to be updated after this install"
- method_option "deployment", :type => :boolean, :banner =>
- "Install using defaults tuned for deployment environments"
method_option "standalone", :type => :array, :lazy_default => [], :banner =>
"Make a bundle that can work without the Bundler runtime"
- method_option "full-index", :type => :boolean, :banner =>
- "Use the rubygems modern index instead of the API endpoint"
- method_option "clean", :type => :boolean, :banner =>
- "Run bundle clean automatically after install"
+ method_option "system", :type => :boolean, :banner =>
+ "Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
method_option "trust-policy", :alias => "P", :type => :string, :banner =>
"Gem trust policy (like gem install -P). Must be one of " +
Bundler.rubygems.security_policy_keys.join('|')
- method_option "jobs", :aliases => "-j", :type => :numeric, :banner =>
- "Specify the number of jobs to run in parallel"
+ method_option "without", :type => :array, :banner =>
+ "Exclude gems that are part of the specified named group."
def install
require 'bundler/cli/install'
@@ -151,17 +163,18 @@ module Bundler
update when you have changed the Gemfile, or if you want to get the newest
possible versions of the gems in the bundle.
D
- method_option "source", :type => :array, :banner => "Update a specific source (and all gems associated with it)"
+ method_option "full-index", :type => :boolean, :banner =>
+ "Use the rubygems modern index instead of the API endpoint"
+ method_option "group", :aliases => "-g", :type => :array, :banner =>
+ "Update a specific group"
+ method_option "jobs", :aliases => "-j", :type => :numeric, :banner =>
+ "Specify the number of jobs to run in parallel"
method_option "local", :type => :boolean, :banner =>
"Do not attempt to fetch gems remotely and use the gem cache instead"
method_option "quiet", :type => :boolean, :banner =>
"Only output warnings and errors."
- method_option "full-index", :type => :boolean, :banner =>
- "Use the rubygems modern index instead of the API endpoint"
- method_option "jobs", :aliases => "-j", :type => :numeric, :banner =>
- "Specify the number of jobs to run in parallel"
- method_option "group", :aliases => "-g", :type => :array, :banner =>
- "Update a specific group"
+ method_option "source", :type => :array, :banner =>
+ "Update a specific source (and all gems associated with it)"
def update(*gems)
require 'bundler/cli/update'
Update.new(options, gems).run
@@ -174,21 +187,23 @@ module Bundler
D
method_option "paths", :type => :boolean,
:banner => "List the paths of all gems that are required by your Gemfile."
+ method_option "outdated", :type => :boolean,
+ :banner => "Show verbose output including whether gems are outdated."
def show(gem_name = nil)
require 'bundler/cli/show'
Show.new(options, gem_name).run
end
map %w(list) => "show"
- desc "binstubs GEM [OPTIONS]", "install the binstubs of the listed gem"
+ desc "binstubs GEM [OPTIONS]", "Install the binstubs of the listed gem"
long_desc <<-D
Generate binstubs for executables in [GEM]. Binstubs are put into bin,
or the --binstubs directory if one has been set.
D
- method_option "path", :type => :string, :lazy_default => "bin", :banner =>
- "binstub destination directory (default bin)"
method_option "force", :type => :boolean, :default => false, :banner =>
- "overwrite existing binstubs if they exist"
+ "Overwrite existing binstubs if they exist"
+ method_option "path", :type => :string, :lazy_default => "bin", :banner =>
+ "Binstub destination directory (default bin)"
def binstubs(*gems)
require 'bundler/cli/binstubs'
Binstubs.new(options, gems).run
@@ -201,10 +216,10 @@ module Bundler
versions of the given gems. Prerelease gems are ignored by default. If your gems
are up to date, Bundler will exit with a status of 0. Otherwise, it will exit 1.
D
- method_option "pre", :type => :boolean, :banner => "Check for newer pre-release gems"
- method_option "source", :type => :array, :banner => "Check against a specific source"
method_option "local", :type => :boolean, :banner =>
"Do not attempt to fetch gems remotely and use the gem cache instead"
+ method_option "pre", :type => :boolean, :banner => "Check for newer pre-release gems"
+ method_option "source", :type => :array, :banner => "Check against a specific source"
method_option "strict", :type => :boolean, :banner =>
"Only list newer versions allowed by your Gemfile requirements"
def outdated(*gems)
@@ -213,20 +228,25 @@ module Bundler
end
desc "cache [OPTIONS]", "Cache all the gems to vendor/cache", :hide => true
- method_option "no-prune", :type => :boolean, :banner => "Don't remove stale gems from the cache."
method_option "all", :type => :boolean, :banner => "Include all sources (including path and git)."
+ method_option "all-platforms", :type => :boolean, :banner => "Include gems for all platforms, not just the current one"
+ method_option "no-prune", :type => :boolean, :banner => "Don't remove stale gems from the cache."
def cache
require 'bundler/cli/cache'
Cache.new(options).run
end
desc "package [OPTIONS]", "Locks and then caches all of the gems into vendor/cache"
- method_option "no-prune", :type => :boolean, :banner => "Don't remove stale gems from the cache."
method_option "all", :type => :boolean, :banner => "Include all sources (including path and git)."
- method_option "quiet", :type => :boolean, :banner => "Only output warnings and errors."
+ method_option "all-platforms", :type => :boolean, :banner => "Include gems for all platforms, not just the current one"
+ method_option "cache-path", :type => :string, :banner =>
+ "Specify a different cache path than the default (vendor/cache)."
+ method_option "gemfile", :type => :string, :banner => "Use the specified gemfile instead of Gemfile"
+ method_option "no-install", :type => :boolean, :banner => "Don't actually install the gems, just package."
+ method_option "no-prune", :type => :boolean, :banner => "Don't remove stale gems from the cache."
method_option "path", :type => :string, :banner =>
"Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME). Bundler will remember this value for future installs on this machine"
- method_option "gemfile", :type => :string, :banner => "Use the specified gemfile instead of Gemfile"
+ method_option "quiet", :type => :boolean, :banner => "Only output warnings and errors."
long_desc <<-D
The package command will copy the .gem files for every gem in the bundle into the
directory ./vendor/cache. If you then check that directory into your source
@@ -274,16 +294,10 @@ module Bundler
Open.new(options, name).run
end
- CONSOLES = {
- 'pry' => :Pry,
- 'ripl' => :Ripl,
- 'irb' => :IRB,
- }
-
desc "console [GROUP]", "Opens an IRB session with the bundle pre-loaded"
def console(group = nil)
require 'bundler/cli/console'
- Console.new(options, group, CONSOLES).run
+ Console.new(options, group).run
end
desc "version", "Prints the bundler's version information"
@@ -313,23 +327,25 @@ module Bundler
The associated gems must also be installed via 'bundle install'.
D
method_option :file, :type => :string, :default => 'gem_graph', :aliases => '-f', :banner => "The name to use for the generated file. see format option"
- method_option :version, :type => :boolean, :default => false, :aliases => '-v', :banner => "Set to show each gem version."
- method_option :requirements, :type => :boolean, :default => false, :aliases => '-r', :banner => "Set to show the version of each required dependency."
method_option :format, :type => :string, :default => "png", :aliases => '-F', :banner => "This is output format option. Supported format is png, jpg, svg, dot ..."
+ method_option :requirements, :type => :boolean, :default => false, :aliases => '-r', :banner => "Set to show the version of each required dependency."
+ method_option :version, :type => :boolean, :default => false, :aliases => '-v', :banner => "Set to show each gem version."
+ method_option :without, :type => :array, :default => [], :banner => "Exclude gems that are part of the specified named group."
def viz
require 'bundler/cli/viz'
Viz.new(options).run
end
desc "gem GEM [OPTIONS]", "Creates a skeleton for creating a rubygem"
- method_option :bin, :type => :boolean, :default => false, :aliases => '-b', :banner => "Generate a binary for your library."
- method_option :test, :type => :string, :lazy_default => 'rspec', :aliases => '-t', :banner => "Generate a test directory for your library: 'rspec' is the default, but 'minitest' is also supported."
- method_option :edit, :type => :string, :aliases => "-e",
- :lazy_default => [ENV['BUNDLER_EDITOR'], ENV['VISUAL'], ENV['EDITOR']].find{|e| !e.nil? && !e.empty? },
- :required => false, :banner => "/path/to/your/editor",
- :desc => "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)"
- method_option :ext, :type => :boolean, :detailt => false, :banner => "Generate the boilerplate for C extension code"
-
+ method_option :bin, :type => :boolean, :default => false, :aliases => '-b', :desc => "Generate a binary for your library. Set a default with `bundle config gem.mit true`."
+ method_option :coc, :type => :boolean, :desc => "Generate a code of conduct file. Set a default with `bundle config gem.coc true`."
+ method_option :edit, :type => :string, :aliases => "-e", :required => false, :banner => "EDITOR",
+ :lazy_default => [ENV['BUNDLER_EDITOR'], ENV['VISUAL'], ENV['EDITOR']].find{|e| !e.nil? && !e.empty? },
+ :desc => "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)"
+ method_option :ext, :type => :boolean, :default => false, :desc => "Generate the boilerplate for C extension code"
+ method_option :mit, :type => :boolean, :desc => "Generate an MIT license file"
+ method_option :test, :type => :string, :lazy_default => 'rspec', :aliases => '-t', :banner => "rspec",
+ :desc => "Generate a test directory for your library, either rspec or minitest. Set a default with `bundle config gem.test rspec`."
def gem(name)
require 'bundler/cli/gem'
Gem.new(options, name, self).run
@@ -341,9 +357,9 @@ module Bundler
desc "clean [OPTIONS]", "Cleans up unused gems in your bundler directory"
method_option "dry-run", :type => :boolean, :default => false, :banner =>
- "only print out changes, do not actually clean gems"
+ "Only print out changes, do not actually clean gems"
method_option "force", :type => :boolean, :default => false, :banner =>
- "forces clean even if --path is not set"
+ "Forces clean even if --path is not set"
def clean
require 'bundler/cli/clean'
Clean.new(options.dup).run
@@ -368,5 +384,26 @@ module Bundler
Env.new.write($stdout)
end
+ private
+
+ # Automatically invoke `bundle install` and resume if
+ # Bundler.settings[:auto_install] exists. This is set through config cmd
+ # `bundle config auto_install 1`.
+ #
+ # Note that this method `nil`s out the global Definition object, so it
+ # should be called first, before you instantiate anything like an
+ # `Installer` that'll keep a reference to the old one instead.
+ def auto_install
+ return unless Bundler.settings[:auto_install]
+
+ begin
+ Bundler.definition.specs
+ rescue GemNotFound
+ Bundler.ui.info "Automatically installing missing gems."
+ Bundler.reset!
+ invoke :install, []
+ Bundler.reset!
+ end
+ end
end
end
diff --git a/lib/bundler/cli/cache.rb b/lib/bundler/cli/cache.rb
index 653ead7f56..751cb80149 100644
--- a/lib/bundler/cli/cache.rb
+++ b/lib/bundler/cli/cache.rb
@@ -9,6 +9,7 @@ module Bundler
Bundler.definition.validate_ruby!
Bundler.definition.resolve_with_cache!
setup_cache_all
+ Bundler.settings[:cache_all_platforms] = options["all-platforms"] if options.key?("all-platforms")
Bundler.load.cache
Bundler.settings[:no_prune] = true if options["no-prune"]
Bundler.load.lock
diff --git a/lib/bundler/cli/clean.rb b/lib/bundler/cli/clean.rb
index e7a4c01460..99508820e2 100644
--- a/lib/bundler/cli/clean.rb
+++ b/lib/bundler/cli/clean.rb
@@ -7,10 +7,17 @@ module Bundler
end
def run
- if Bundler.settings[:path] || options[:force]
- Bundler.load.clean(options[:"dry-run"])
- else
- Bundler.ui.error "Can only use bundle clean when --path is set or --force is set"
+ require_path_or_force
+ Bundler.load.clean(options[:"dry-run"])
+ end
+
+ protected
+
+ def require_path_or_force
+ if !Bundler.settings[:path] && !options[:force]
+ Bundler.ui.error "Cleaning all the gems on your system is dangerous! " \
+ "If you're sure you want to remove every system gem not in this " \
+ "bundle, run `bundle clean --force`."
exit 1
end
end
diff --git a/lib/bundler/cli/common.rb b/lib/bundler/cli/common.rb
index 0548525af0..83315a272e 100644
--- a/lib/bundler/cli/common.rb
+++ b/lib/bundler/cli/common.rb
@@ -25,6 +25,8 @@ module Bundler
else
ask_for_spec_from(specs)
end
+ rescue RegexpError
+ raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies)
end
def self.ask_for_spec_from(specs)
diff --git a/lib/bundler/cli/console.rb b/lib/bundler/cli/console.rb
index bf000936fc..bc4f377d25 100644
--- a/lib/bundler/cli/console.rb
+++ b/lib/bundler/cli/console.rb
@@ -1,41 +1,37 @@
module Bundler
class CLI::Console
- attr_reader :options, :group, :consoles
- def initialize(options, group, consoles)
+ attr_reader :options, :group
+ def initialize(options, group)
@options = options
@group = group
- @consoles = consoles
end
def run
group ? Bundler.require(:default, *(group.split.map! {|g| g.to_sym })) : Bundler.require
ARGV.clear
- preferred = Bundler.settings[:console] || 'irb'
-
- # See if console is available
- begin
- require preferred || true
- rescue LoadError
- # Is it in Gemfile?
- Bundler.ui.error "Could not load the #{preferred} console"
- Bundler.ui.info "Falling back on IRB..."
-
- require 'irb'
- preferred = 'irb'
- end
-
- constant = consoles[preferred]
+ console = get_console(Bundler.settings[:console] || 'irb')
+ console.start
+ end
- console = begin
- Object.const_get(constant)
- rescue NameError => e
- Bundler.ui.error e.inspect
- Bundler.ui.error "Could not load the #{constant} console"
- return
- end
+ def get_console(name)
+ require name
+ get_constant(name)
+ rescue LoadError
+ Bundler.ui.error "Couldn't load console #{name}"
+ get_constant('irb')
+ end
- console.start
+ def get_constant(name)
+ const_name = {
+ 'pry' => :Pry,
+ 'ripl' => :Ripl,
+ 'irb' => :IRB,
+ }[name]
+ Object.const_get(const_name)
+ rescue NameError
+ Bundler.ui.error "Could not find constant #{const_name}"
+ exit 1
end
end
diff --git a/lib/bundler/cli/exec.rb b/lib/bundler/cli/exec.rb
index 1739ab6f78..7713906f26 100644
--- a/lib/bundler/cli/exec.rb
+++ b/lib/bundler/cli/exec.rb
@@ -1,36 +1,43 @@
module Bundler
class CLI::Exec
- attr_reader :options, :args
+ attr_reader :options, :args, :cmd
def initialize(options, args)
@options = options
+ @cmd = args.shift
@args = args
+
+ if RUBY_VERSION >= "2.0"
+ @args << { :close_others => !options.keep_file_descriptors? }
+ elsif options.keep_file_descriptors?
+ Bundler.ui.warn "Ruby version #{RUBY_VERSION} defaults to keeping non-standard file descriptors on Kernel#exec."
+ end
end
def run
- Bundler.definition.validate_ruby!
- Bundler.load.setup_environment
+ raise ArgumentError if cmd.nil?
- begin
- if RUBY_VERSION >= "2.0"
- @args << { :close_others => !options.keep_file_descriptors? }
- elsif options.keep_file_descriptors?
- Bundler.ui.warn "Ruby version #{RUBY_VERSION} defaults to keeping non-standard file descriptors on Kernel#exec."
- end
-
- # Run
- Kernel.exec(*args)
- rescue Errno::EACCES
- Bundler.ui.error "bundler: not executable: #{args.first}"
- exit 126
- rescue Errno::ENOENT
- Bundler.ui.error "bundler: command not found: #{args.first}"
- Bundler.ui.warn "Install missing gem executables with `bundle install`"
- exit 127
- rescue ArgumentError
- Bundler.ui.error "bundler: exec needs a command to run"
- exit 128
+ # First, try to exec directly to something in PATH
+ SharedHelpers.set_bundle_environment
+ bin_path = Bundler.which(@cmd)
+ if bin_path
+ Kernel.exec(bin_path, *args)
end
+
+ # If that didn't work, set up the whole bundle
+ Bundler.definition.validate_ruby!
+ Bundler.load.setup_environment
+ Kernel.exec(@cmd, *args)
+ rescue Errno::EACCES
+ Bundler.ui.error "bundler: not executable: #{cmd}"
+ exit 126
+ rescue Errno::ENOENT
+ Bundler.ui.error "bundler: command not found: #{cmd}"
+ Bundler.ui.warn "Install missing gem executables with `bundle install`"
+ exit 127
+ rescue ArgumentError
+ Bundler.ui.error "bundler: exec needs a command to run"
+ exit 128
end
end
diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb
index 243f02856b..313cfbabfb 100644
--- a/lib/bundler/cli/gem.rb
+++ b/lib/bundler/cli/gem.rb
@@ -1,31 +1,32 @@
+require 'pathname'
+
module Bundler
class CLI::Gem
- attr_reader :options, :gem_name, :thor
+ attr_reader :options, :gem_name, :thor, :name, :target
+
def initialize(options, gem_name, thor)
@options = options
- @gem_name = gem_name
+ @gem_name = resolve_name(gem_name)
@thor = thor
+
+ @name = @gem_name
+ @target = Pathname.pwd.join(gem_name)
+
+ validate_ext_name if options[:ext]
end
def run
- if options[:ext] && gem_name.index('-')
- Bundler.ui.error "You have specified a gem name which does not conform to the \n" \
- "naming guidelines for C extensions. For more information, \n" \
- "see the 'Extension Naming' section at the following URL:\n" \
- "http://guides.rubygems.org/gems-with-extensions/\n"
- exit 1
- end
+ Bundler.ui.confirm "Creating gem '#{name}'..."
- name = gem_name.chomp("/") # remove trailing slash if present
underscored_name = name.tr('-', '_')
namespaced_path = name.tr('-', '/')
- target = File.join(Dir.pwd, name)
- constant_name = name.split('_').map{|p| p[0..0].upcase + p[1..-1] }.join
+ constant_name = name.split('_').map{|p| p[0..0].upcase + p[1..-1] unless p.empty?}.join
constant_name = constant_name.split('-').map{|q| q[0..0].upcase + q[1..-1] }.join('::') if constant_name =~ /-/
constant_array = constant_name.split('::')
git_user_name = `git config user.name`.chomp
git_user_email = `git config user.email`.chomp
- opts = {
+
+ config = {
:name => name,
:underscored_name => underscored_name,
:namespaced_path => namespaced_path,
@@ -35,44 +36,130 @@ module Bundler
:author => git_user_name.empty? ? "TODO: Write your name" : git_user_name,
:email => git_user_email.empty? ? "TODO: Write your email address" : git_user_email,
:test => options[:test],
- :ext => options[:ext]
+ :ext => options[:ext],
+ :bin => options[:bin]
+ }
+
+ templates = {
+ "Gemfile.tt" => "Gemfile",
+ "gitignore.tt" => ".gitignore",
+ "lib/newgem.rb.tt" => "lib/#{namespaced_path}.rb",
+ "lib/newgem/version.rb.tt" => "lib/#{namespaced_path}/version.rb",
+ "newgem.gemspec.tt" => "#{name}.gemspec",
+ "Rakefile.tt" => "Rakefile",
+ "README.md.tt" => "README.md",
+ "bin/console.tt" => "bin/console",
+ "bin/setup.tt" => "bin/setup"
}
- gemspec_dest = File.join(target, "#{name}.gemspec")
- thor.template(File.join("newgem/Gemfile.tt"), File.join(target, "Gemfile"), opts)
- thor.template(File.join("newgem/Rakefile.tt"), File.join(target, "Rakefile"), opts)
- thor.template(File.join("newgem/LICENSE.txt.tt"), File.join(target, "LICENSE.txt"), opts)
- thor.template(File.join("newgem/README.md.tt"), File.join(target, "README.md"), opts)
- thor.template(File.join("newgem/gitignore.tt"), File.join(target, ".gitignore"), opts)
- thor.template(File.join("newgem/newgem.gemspec.tt"), gemspec_dest, opts)
- thor.template(File.join("newgem/lib/newgem.rb.tt"), File.join(target, "lib/#{namespaced_path}.rb"), opts)
- thor.template(File.join("newgem/lib/newgem/version.rb.tt"), File.join(target, "lib/#{namespaced_path}/version.rb"), opts)
- if options[:bin]
- thor.template(File.join("newgem/bin/newgem.tt"), File.join(target, 'bin', name), opts)
+
+ if ask_and_set(:coc, "Do you want to include a code of conduct in gems you generate?",
+ "Codes of conduct can increase contributions to your project by contributors who " \
+ "prefer collaborative, safe spaces. You can read more about the code of conduct at " \
+ "contributor-covenant.org. Having a code of conduct means agreeing to the responsibility " \
+ "of enforcing it, so be sure that you are prepared to do that. For suggestions about " \
+ "how to enforce codes of conduct, see bit.ly/coc-enforcement."
+ )
+ templates.merge!("CODE_OF_CONDUCT.md.tt" => "CODE_OF_CONDUCT.md")
end
- case options[:test]
- when 'rspec'
- thor.template(File.join("newgem/rspec.tt"), File.join(target, ".rspec"), opts)
- thor.template(File.join("newgem/spec/spec_helper.rb.tt"), File.join(target, "spec/spec_helper.rb"), opts)
- thor.template(File.join("newgem/spec/newgem_spec.rb.tt"), File.join(target, "spec/#{namespaced_path}_spec.rb"), opts)
- when 'minitest'
- thor.template(File.join("newgem/test/minitest_helper.rb.tt"), File.join(target, "test/minitest_helper.rb"), opts)
- thor.template(File.join("newgem/test/test_newgem.rb.tt"), File.join(target, "test/test_#{namespaced_path}.rb"), opts)
+
+ if ask_and_set(:mit, "Do you want to license your code permissively under the MIT license?",
+ "This means that any other developer or company will be legally allowed to use your code " \
+ "for free as long as they admit you created it. You can read more about the MIT license " \
+ "at choosealicense.com/licenses/mit."
+ )
+ config[:mit] = true
+ templates.merge!("LICENSE.txt.tt" => "LICENSE.txt")
end
- if options[:test]
- thor.template(File.join("newgem/.travis.yml.tt"), File.join(target, ".travis.yml"), opts)
+
+ if test_framework = ask_and_set_test_framework
+ templates.merge!(".travis.yml.tt" => ".travis.yml")
+
+ case test_framework
+ when 'rspec'
+ templates.merge!(
+ "rspec.tt" => ".rspec",
+ "spec/spec_helper.rb.tt" => "spec/spec_helper.rb",
+ "spec/newgem_spec.rb.tt" => "spec/#{namespaced_path}_spec.rb"
+ )
+ when 'minitest'
+ templates.merge!(
+ "test/minitest_helper.rb.tt" => "test/minitest_helper.rb",
+ "test/test_newgem.rb.tt" => "test/test_#{namespaced_path}.rb"
+ )
+ end
end
+
+ templates.merge!("exe/newgem.tt" => "exe/#{name}") if options[:bin]
+
if options[:ext]
- thor.template(File.join("newgem/ext/newgem/extconf.rb.tt"), File.join(target, "ext/#{name}/extconf.rb"), opts)
- thor.template(File.join("newgem/ext/newgem/newgem.h.tt"), File.join(target, "ext/#{name}/#{underscored_name}.h"), opts)
- thor.template(File.join("newgem/ext/newgem/newgem.c.tt"), File.join(target, "ext/#{name}/#{underscored_name}.c"), opts)
+ templates.merge!(
+ "ext/newgem/extconf.rb.tt" => "ext/#{name}/extconf.rb",
+ "ext/newgem/newgem.h.tt" => "ext/#{name}/#{underscored_name}.h",
+ "ext/newgem/newgem.c.tt" => "ext/#{name}/#{underscored_name}.c"
+ )
end
+
+ templates.each do |src, dst|
+ thor.template("newgem/#{src}", target.join(dst), config)
+ end
+
Bundler.ui.info "Initializing git repo in #{target}"
Dir.chdir(target) { `git init`; `git add .` }
if options[:edit]
- thor.run("#{options["edit"]} \"#{gemspec_dest}\"") # Open gemspec in editor
+ # Open gemspec in editor
+ thor.run("#{options["edit"]} \"#{target.join("#{name}.gemspec")}\"")
end
end
+ private
+
+ def resolve_name(name)
+ Pathname.pwd.join(name).basename.to_s
+ end
+
+ def ask_and_set(key, header, message)
+ choice = options[key] || Bundler.settings["gem.#{key}"]
+
+ if choice.nil?
+ Bundler.ui.confirm header
+ choice = (Bundler.ui.ask("#{message} y/(n):") =~ /y|yes/)
+ Bundler.settings.set_global("gem.#{key}", choice)
+ end
+
+ choice
+ end
+
+ def validate_ext_name
+ return unless gem_name.index('-')
+
+ Bundler.ui.error "You have specified a gem name which does not conform to the \n" \
+ "naming guidelines for C extensions. For more information, \n" \
+ "see the 'Extension Naming' section at the following URL:\n" \
+ "http://guides.rubygems.org/gems-with-extensions/\n"
+ exit 1
+ end
+
+ def ask_and_set_test_framework
+ test_framework = options[:test] || Bundler.settings["gem.test"]
+
+ if test_framework.nil?
+ Bundler.ui.confirm "Do you want to generate tests with your gem?"
+ result = Bundler.ui.ask "Type 'rspec' or 'minitest' to generate those test files now and " \
+ "in the future. rspec/minitest/(none):"
+ if result =~ /rspec|minitest/
+ test_framework = result
+ else
+ test_framework = false
+ end
+ end
+
+ if Bundler.settings["gem.test"].nil?
+ Bundler.settings.set_global("gem.test", test_framework)
+ end
+
+ test_framework
+ end
+
end
end
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index b2f16ed26f..43dd40a500 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -44,7 +44,7 @@ module Bundler
"before deploying."
end
- if Bundler.root.join("vendor/cache").exist?
+ if Bundler.app_cache.exist?
options[:local] = true
end
@@ -66,6 +66,7 @@ module Bundler
Bundler.settings[:shebang] = options["shebang"] if options["shebang"]
Bundler.settings[:jobs] = options["jobs"] if options["jobs"]
Bundler.settings[:no_prune] = true if options["no-prune"]
+ Bundler.settings[:no_install] = true if options["no-install"]
Bundler.settings[:clean] = options["clean"] if options["clean"]
Bundler.settings.without = options[:without]
Bundler::Fetcher.disable_endpoint = options["full-index"]
@@ -77,23 +78,24 @@ module Bundler
definition = Bundler.definition
definition.validate_ruby!
Installer.install(Bundler.root, definition, options)
- Bundler.load.cache if Bundler.root.join("vendor/cache").exist? && !options["no-cache"] && !Bundler.settings[:frozen]
+ Bundler.load.cache if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.settings[:frozen]
+
+ Bundler.ui.confirm "Bundle complete! #{dependencies_count_for(definition)}, #{gems_installed_for(definition)}."
+ confirm_without_groups
if Bundler.settings[:path]
absolute_path = File.expand_path(Bundler.settings[:path])
relative_path = absolute_path.sub(File.expand_path('.'), '.')
- Bundler.ui.confirm "Your bundle is complete!"
- without_groups_messages
- Bundler.ui.confirm "It was installed into #{relative_path}"
+ Bundler.ui.confirm "Bundled gems are installed into #{relative_path}."
else
- Bundler.ui.confirm "Your bundle is complete!"
- without_groups_messages
Bundler.ui.confirm "Use `bundle show [gemname]` to see where a bundled gem is installed."
end
+
Installer.post_install_messages.to_a.each do |name, msg|
Bundler.ui.confirm "Post-install message from #{name}:"
Bundler.ui.info msg
end
+
Installer.ambiguous_gems.to_a.each do |name, installed_from_uri, *also_found_in_uris|
Bundler.ui.error "Warning: the gem '#{name}' was found in multiple sources."
Bundler.ui.error "Installed from: #{installed_from_uri}"
@@ -111,7 +113,7 @@ module Bundler
end
rescue GemNotFound, VersionConflict => e
if options[:local] && Bundler.app_cache.exist?
- Bundler.ui.warn "Some gems seem to be missing from your vendor/cache directory."
+ Bundler.ui.warn "Some gems seem to be missing from your #{Bundler.settings.app_cache_path} directory."
end
unless Bundler.definition.has_rubygems_remotes?
@@ -133,11 +135,22 @@ module Bundler
"application for all non-root users on this machine.", :wrap => true
end
- def without_groups_messages
+ def confirm_without_groups
if Bundler.settings.without.any?
require "bundler/cli/common"
Bundler.ui.confirm Bundler::CLI::Common.without_groups_message
end
end
+
+ def dependencies_count_for(definition)
+ count = definition.dependencies.count
+ "#{count} Gemfile #{count == 1 ? 'dependency' : 'dependencies'}"
+ end
+
+ def gems_installed_for(definition)
+ count = definition.specs.count
+ "#{count} #{count == 1 ? 'gem' : 'gems'} now installed"
+ end
+
end
end
diff --git a/lib/bundler/cli/outdated.rb b/lib/bundler/cli/outdated.rb
index ee6387acb7..f8779d762a 100644
--- a/lib/bundler/cli/outdated.rb
+++ b/lib/bundler/cli/outdated.rb
@@ -70,7 +70,7 @@ module Bundler
end
if out_count.zero?
- Bundler.ui.info "Your bundle is up to date!\n"
+ Bundler.ui.info "Bundle up to date!\n"
else
exit 1
end
diff --git a/lib/bundler/cli/package.rb b/lib/bundler/cli/package.rb
index 5adad44c35..f99678c9ec 100644
--- a/lib/bundler/cli/package.rb
+++ b/lib/bundler/cli/package.rb
@@ -9,6 +9,8 @@ module Bundler
def run
Bundler.ui.level = "error" if options[:quiet]
Bundler.settings[:path] = File.expand_path(options[:path]) if options[:path]
+ Bundler.settings[:cache_all_platforms] = options["all-platforms"] if options.key?("all-platforms")
+ Bundler.settings[:cache_path] = options["cache-path"] if options.key?("cache-path")
setup_cache_all
install
@@ -22,7 +24,12 @@ module Bundler
def install
require 'bundler/cli/install'
- Bundler::CLI::Install.new(options.dup).run
+ options = self.options.dup
+ if Bundler.settings[:cache_all_platforms]
+ options["local"] = false
+ options["update"] = true
+ end
+ Bundler::CLI::Install.new(options).run
end
def setup_cache_all
diff --git a/lib/bundler/cli/show.rb b/lib/bundler/cli/show.rb
index 07ff63dcd8..96c1490209 100644
--- a/lib/bundler/cli/show.rb
+++ b/lib/bundler/cli/show.rb
@@ -2,10 +2,12 @@ require 'bundler/cli/common'
module Bundler
class CLI::Show
- attr_reader :options, :gem_name
+ attr_reader :options, :gem_name, :latest_specs
def initialize(options, gem_name)
@options = options
@gem_name = gem_name
+ @verbose = options[:verbose] || options[:outdated]
+ @latest_specs = fetch_latest_specs if @verbose
end
def run
@@ -36,13 +38,37 @@ module Bundler
Bundler.ui.info "Gems included by the bundle:"
Bundler.load.specs.sort_by { |s| s.name }.each do |s|
desc = " * #{s.name} (#{s.version}#{s.git_version})"
- if @options[:verbose]
- Bundler.ui.info "#{desc} - #{s.summary || 'No description available.'}"
+ if @verbose
+ latest = latest_specs.find { |l| l.name == s.name }
+ Bundler.ui.info <<-END.gsub(/^ +/, '')
+ #{desc}
+ \tSummary: #{s.summary || 'No description available.'}
+ \tHomepage: #{s.homepage || 'No website available.'}
+ \tStatus: #{outdated?(s, latest) ? "Outdated - #{s.version} < #{latest.version}" : "Up to date"}
+ END
else
Bundler.ui.info desc
end
end
end
end
+
+ private
+
+ def fetch_latest_specs
+ definition = Bundler.definition(true)
+ if options[:outdated]
+ Bundler.ui.info "Fetching remote specs for outdated check...\n\n"
+ Bundler.ui.silence { definition.resolve_remotely! }
+ else
+ definition.resolve_with_cache!
+ end
+ definition.specs
+ end
+
+ def outdated?(current, latest)
+ return false unless latest
+ Gem::Version.new(current.version) < Gem::Version.new(latest.version)
+ end
end
end
diff --git a/lib/bundler/cli/update.rb b/lib/bundler/cli/update.rb
index dd15de9936..6ed38f2c3a 100644
--- a/lib/bundler/cli/update.rb
+++ b/lib/bundler/cli/update.rb
@@ -49,14 +49,14 @@ module Bundler
Bundler.definition.validate_ruby!
Installer.install Bundler.root, Bundler.definition, opts
- Bundler.load.cache if Bundler.root.join("vendor/cache").exist?
+ Bundler.load.cache if Bundler.app_cache.exist?
if Bundler.settings[:clean] && Bundler.settings[:path]
require "bundler/cli/clean"
Bundler::CLI::Clean.new(options).run
end
- Bundler.ui.confirm "Your bundle is updated!"
+ Bundler.ui.confirm "Bundle updated!"
without_groups_messages
end
diff --git a/lib/bundler/cli/viz.rb b/lib/bundler/cli/viz.rb
index c404ddbbc5..09557e599c 100644
--- a/lib/bundler/cli/viz.rb
+++ b/lib/bundler/cli/viz.rb
@@ -8,7 +8,7 @@ module Bundler
def run
require 'graphviz'
output_file = File.expand_path(options[:file])
- graph = Graph.new(Bundler.load, output_file, options[:version], options[:requirements], options[:format])
+ graph = Graph.new(Bundler.load, output_file, options[:version], options[:requirements], options[:format], options[:without])
graph.viz
rescue LoadError => e
Bundler.ui.error e.inspect
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 2b15b15573..86dbfba2a5 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -129,7 +129,7 @@ module Bundler
# @return [Bundler::SpecSet]
def specs
@specs ||= begin
- specs = resolve.materialize(requested_dependencies)
+ specs = resolve.materialize(Bundler.settings[:cache_all_platforms] ? dependencies : requested_dependencies)
unless specs["bundler"].any?
local = Bundler.settings[:frozen] ? rubygems_index : index
@@ -201,11 +201,7 @@ module Bundler
sources.all_sources.each do |source|
source.dependency_names = dependency_names.dup
idx.add_source source.specs
-
- if source.is_a?(Source::Git) || source.is_a?(Source::Path)
- dependency_names -= source.specs.map{|s| s.name }.uniq
- end
-
+ dependency_names -= pinned_spec_names(source.specs)
dependency_names.push(*source.unmet_deps).uniq!
end
end
@@ -409,11 +405,18 @@ module Bundler
if locked
unlocking = @locked_specs.any? do |locked_spec|
- locked_spec.source != locked
+ locked_spec.source.class == locked.class && locked_spec.source != locked
end
end
- !locked || unlocking || source.specs != locked.specs
+ !locked || unlocking || dependencies_for_source_changed?(locked) || source.specs != locked.specs
+ end
+
+ def dependencies_for_source_changed?(source)
+ deps_for_source = @dependencies.select { |s| s.source == source }
+ locked_deps_for_source = @locked_deps.select { |s| s.source == source }
+
+ deps_for_source != locked_deps_for_source
end
# Get all locals and override their matching sources.
@@ -607,5 +610,19 @@ module Bundler
source_requirements
end
+ def pinned_spec_names(specs)
+ names = []
+ specs.each do |s|
+ # TODO when two sources without blocks is an error, we can change
+ # this check to !s.source.is_a?(Source::LocalRubygems). For now,
+ # we need to ask every Rubygems for every gem name.
+ if s.source.is_a?(Source::Git) || s.source.is_a?(Source::Path)
+ names << s.name
+ end
+ end
+ names.uniq!
+ names
+ end
+
end
end
diff --git a/lib/bundler/dependency.rb b/lib/bundler/dependency.rb
index 0224c3feca..6a9284fd56 100644
--- a/lib/bundler/dependency.rb
+++ b/lib/bundler/dependency.rb
@@ -26,6 +26,14 @@ module Bundler
:jruby_18 => Gem::Platform::JAVA,
:jruby_19 => Gem::Platform::JAVA,
:mswin => Gem::Platform::MSWIN,
+ :mswin_18 => Gem::Platform::MSWIN,
+ :mswin_19 => Gem::Platform::MSWIN,
+ :mswin_20 => Gem::Platform::MSWIN,
+ :mswin_21 => Gem::Platform::MSWIN,
+ :mswin64 => Gem::Platform::MSWIN64,
+ :mswin64_19 => Gem::Platform::MSWIN64,
+ :mswin64_20 => Gem::Platform::MSWIN64,
+ :mswin64_21 => Gem::Platform::MSWIN64,
:mingw => Gem::Platform::MINGW,
:mingw_18 => Gem::Platform::MINGW,
:mingw_19 => Gem::Platform::MINGW,
@@ -93,7 +101,6 @@ module Bundler
out << "\n"
end
-
def specific?
super
rescue NoMethodError
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index ef5c6fbaaa..9736525a4f 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -24,14 +24,14 @@ module Bundler
@platforms = []
@env = nil
@ruby_version = nil
- add_github_sources
+ add_git_sources
end
def eval_gemfile(gemfile, contents = nil)
contents ||= Bundler.read_file(gemfile.to_s)
instance_eval(contents, gemfile.to_s, 1)
rescue SyntaxError => e
- syntax_msg = e.message.gsub("#{gemfile.to_s}:", 'on line ')
+ syntax_msg = e.message.gsub("#{gemfile}:", 'on line ')
raise GemfileError, "Gemfile syntax error #{syntax_msg}"
rescue ScriptError, RegexpError, NameError, ArgumentError => e
e.backtrace[0] = "#{e.backtrace[0]}: #{e.message} (#{e.class})"
@@ -112,6 +112,7 @@ module Bundler
if block_given?
with_source(@sources.add_rubygems_source("remotes" => source), &blk)
else
+ check_primary_source_safety(@sources)
@sources.add_rubygems_remote(source)
end
end
@@ -148,6 +149,14 @@ module Bundler
with_source(@sources.add_git_source(normalize_hash(options).merge("uri" => uri)), &blk)
end
+ def github(repo, options = {})
+ raise ArgumentError, "Github sources require a block" unless block_given?
+ github_uri = @git_sources["github"].call(repo)
+ git_options = normalize_hash(options).merge("uri" => github_uri)
+ git_source = @sources.add_git_source(git_options)
+ with_source(git_source) { yield }
+ end
+
def to_definition(lockfile, unlock)
Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version)
end
@@ -182,13 +191,19 @@ module Bundler
private
- def add_github_sources
+ def add_git_sources
git_source(:github) do |repo_name|
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
"git://github.com/#{repo_name}.git"
end
git_source(:gist){ |repo_name| "https://gist.github.com/#{repo_name}.git" }
+
+ git_source(:bitbucket) do |repo_name|
+ user_name, repo_name = repo_name.split '/'
+ repo_name ||= user_name
+ "https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git"
+ end
end
def with_source(source)
@@ -214,7 +229,10 @@ module Bundler
def normalize_options(name, version, opts)
if name.is_a?(Symbol)
- raise GemfileError, %{You need to specify gem names as Strings. Use 'gem "#{name.to_s}"' instead.}
+ raise GemfileError, %{You need to specify gem names as Strings. Use 'gem "#{name}"' instead.}
+ end
+ if name =~ /\s/
+ raise GemfileError, %{'#{name}' is not a valid gem name because it contains whitespace.}
end
normalize_hash(opts)
@@ -290,5 +308,24 @@ module Bundler
raise GemfileError, "Unknown source '#{source}'"
end
end
+
+ def check_primary_source_safety(source)
+ return unless source.rubygems_primary_remotes.any?
+
+ if Bundler.settings[:disable_multisource]
+ raise GemspecError, "Warning: this Gemfile contains multiple primary sources. " \
+ "Each source after the first must include a block to indicate which gems " \
+ "should come from that source. To downgrade this error to a warning, run " \
+ "`bundle config --delete disable_multisource`."
+ else
+ Bundler.ui.warn "Warning: this Gemfile contains multiple primary sources. " \
+ "Using `source` more than once without a block is a security risk, and " \
+ "may result in installing unexpected gems. To resolve this warning, use " \
+ "a block to indicate which gems should come from the secondary source. " \
+ "To upgrade this warning to an error, run `bundle config " \
+ "disable_multisource true`."
+ end
+ end
+
end
end
diff --git a/lib/bundler/endpoint_specification.rb b/lib/bundler/endpoint_specification.rb
index 8566f26562..71d5e115fc 100644
--- a/lib/bundler/endpoint_specification.rb
+++ b/lib/bundler/endpoint_specification.rb
@@ -18,7 +18,7 @@ module Bundler
end
# needed for standalone, load required_paths from local gemspec
- # after the gem in installed
+ # after the gem is installed
def require_paths
if @remote_specification
@remote_specification.require_paths
diff --git a/lib/bundler/env.rb b/lib/bundler/env.rb
index 0f6f315346..031d7fd97b 100644
--- a/lib/bundler/env.rb
+++ b/lib/bundler/env.rb
@@ -1,43 +1,44 @@
+require 'bundler/rubygems_integration'
+require 'bundler/source/git/git_proxy'
+
module Bundler
class Env
def write(io)
- io.write(report)
+ io.write report(:print_gemfile => true)
end
- def report
- out = "Bundler #{Bundler::VERSION}\n"
-
- out << "Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}"
- out << " patchlevel #{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
- out << ") [#{RUBY_PLATFORM}]\n"
-
- out << "Rubygems #{Gem::VERSION}\n"
-
- out << "rvm #{ENV['rvm_version']}\n" if ENV['rvm_version']
-
- out << "GEM_HOME #{ENV['GEM_HOME']}\n"
-
- out << "GEM_PATH #{ENV['GEM_PATH']}\n" unless ENV['GEM_PATH'] == ENV['GEM_HOME']
+ def report(options = {})
+ print_gemfile = options.delete(:print_gemfile)
+ out = "Environment\n\n"
+ out << " Bundler #{Bundler::VERSION}\n"
+ out << " Rubygems #{Gem::VERSION}\n"
+ out << " Ruby #{ruby_version}"
+ out << " GEM_HOME #{ENV['GEM_HOME']}\n" unless ENV['GEM_HOME'].nil? || ENV['GEM_HOME'].empty?
+ out << " GEM_PATH #{ENV['GEM_PATH']}\n" unless ENV['GEM_PATH'] == ENV['GEM_HOME']
+ out << " RVM #{ENV['rvm_version']}\n" if ENV['rvm_version']
+ out << " Git #{git_version}\n"
%w(rubygems-bundler open_gem).each do |name|
- specs = Gem::Specification.find_all{|s| s.name == name }
- out << "#{name} (#{specs.map(&:version).join(',')})\n" unless specs.empty?
+ specs = Bundler.rubygems.find_name(name)
+ out << " #{name} (#{specs.map(&:version).join(',')})\n" unless specs.empty?
end
- out << "\nBundler settings\n" unless Bundler.settings.all.empty?
+ out << "\nBundler settings\n\n" unless Bundler.settings.all.empty?
Bundler.settings.all.each do |setting|
- out << " #{setting}\n"
+ out << " " << setting << "\n"
Bundler.settings.pretty_values_for(setting).each do |line|
- out << " " << line << "\n"
+ out << " " << line << "\n"
end
end
- out << "\n\n" << "Gemfile\n"
- out << read_file("Gemfile") << "\n"
+ if print_gemfile
+ out << "\nGemfile\n\n"
+ out << " " << read_file(Bundler.default_gemfile).gsub(/\n/, "\n ") << "\n"
- out << "\n\n" << "Gemfile.lock\n"
- out << read_file("Gemfile.lock") << "\n"
+ out << "\n" << "Gemfile.lock\n\n"
+ out << " " << read_file(Bundler.default_lockfile).gsub(/\n/, "\n ") << "\n"
+ end
out
end
@@ -45,12 +46,30 @@ module Bundler
private
def read_file(filename)
- File.read(filename).strip
+ File.read(filename.to_s).strip
rescue Errno::ENOENT
"<No #{filename} found>"
rescue => e
"#{e.class}: #{e.message}"
end
+ def ruby_version
+ str = "#{RUBY_VERSION}"
+ if RUBY_VERSION < '1.9'
+ str << " (#{RUBY_RELEASE_DATE}"
+ str << " patchlevel #{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
+ str << ") [#{RUBY_PLATFORM}]\n"
+ else
+ str << "p#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
+ str << " (#{RUBY_RELEASE_DATE} revision #{RUBY_REVISION}) [#{RUBY_PLATFORM}]\n"
+ end
+ end
+
+ def git_version
+ Bundler::Source::Git::GitProxy.new(nil, nil, nil).version
+ rescue Bundler::Source::Git::GitNotInstalledError
+ "not installed"
+ end
+
end
end
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb
index e9eec30370..46ac8e44e8 100644
--- a/lib/bundler/fetcher.rb
+++ b/lib/bundler/fetcher.rb
@@ -6,6 +6,8 @@ module Bundler
# Handles all the fetching with the rubygems server
class Fetcher
+ # This error is raised when it looks like the network is down
+ class NetworkDownError < HTTPError; end
# This error is raised if the API returns a 413 (only printed in verbose)
class FallbackError < HTTPError; end
# This is the error raised if OpenSSL fails the cert verification
@@ -73,18 +75,27 @@ module Bundler
ruby = Bundler.ruby_version
agent = "bundler/#{Bundler::VERSION}"
- agent += " rubygems/#{Gem::VERSION}"
- agent += " ruby/#{ruby.version}"
- agent += " (#{ruby.host})"
- agent += " command/#{ARGV.first}"
+ agent << " rubygems/#{Gem::VERSION}"
+ agent << " ruby/#{ruby.version}"
+ agent << " (#{ruby.host})"
+ agent << " command/#{ARGV.first}"
if ruby.engine != "ruby"
# engine_version raises on unknown engines
engine_version = ruby.engine_version rescue "???"
- agent += " #{ruby.engine}/#{engine_version}"
+ agent << " #{ruby.engine}/#{engine_version}"
end
+
+ agent << " options/#{Bundler.settings.all.join(",")}"
+
# add a random ID so we can consolidate runs server-side
agent << " " << SecureRandom.hex(8)
+
+ # add any user agent strings set in the config
+ extra_ua = Bundler.settings[:user_agent]
+ agent << " " << extra_ua if extra_ua
+
+ agent
end
end
@@ -95,7 +106,7 @@ module Bundler
@api_timeout = 10 # How long to wait for each API call
@max_retries = 3 # How many retries for the API call
- @anonymizable_uri = resolve_remote_uri(remote_uri)
+ @anonymizable_uri = configured_uri_for(remote_uri)
Socket.do_not_reverse_lookup = true
connection # create persistent connection
@@ -231,6 +242,8 @@ module Bundler
elsif fetch(dependency_api_uri)
@use_api = true
end
+ rescue NetworkDownError => e
+ raise HTTPError, e.message
rescue AuthenticationRequiredError
# We got a 401 from the server. Don't fall back to the full index, just fail.
raise
@@ -270,7 +283,7 @@ module Bundler
when Net::HTTPRequestEntityTooLarge
raise FallbackError, response.body
when Net::HTTPUnauthorized
- raise AuthenticationRequiredError, remote_uri
+ raise AuthenticationRequiredError, remote_uri.host
else
raise HTTPError, "#{response.class}: #{response.body}"
end
@@ -289,7 +302,13 @@ module Bundler
raise CertificateFailureError.new(uri)
rescue *HTTP_ERRORS => e
Bundler.ui.trace e
- raise HTTPError, "Network error while fetching #{uri}"
+ case e.message
+ when /host down:/, /getaddrinfo: nodename nor servname provided/
+ raise NetworkDownError, "Could not reach host #{uri.host}. Check your network " \
+ "connection and try again."
+ else
+ raise HTTPError, "Network error while fetching #{uri}"
+ end
end
def dependency_api_uri(gem_names = [])
@@ -304,7 +323,7 @@ module Bundler
gem_list = []
deps_list = []
- gem_names.each_slice(Source::Rubygems::API_REQUEST_LIMIT) do |names|
+ gem_names.each_slice(Source::Rubygems::API_REQUEST_SIZE) do |names|
marshalled_deps = fetch dependency_api_uri(names)
gem_list += Bundler.load_marshal(marshalled_deps)
end
@@ -377,17 +396,10 @@ module Bundler
private
- def resolve_remote_uri(uri)
- add_configured_credentials(Bundler::Source.mirror_for(uri))
- end
-
- def add_configured_credentials(uri)
- auth = Bundler.settings[uri.to_s]
- if auth
- uri = uri.dup
- uri.user, uri.password = *auth.split(":", 2)
- end
- AnonymizableURI.new(uri)
+ def configured_uri_for(uri)
+ uri = Bundler::Source.mirror_for(uri)
+ config_auth = Bundler.settings[uri.to_s] || Bundler.settings[uri.host]
+ AnonymizableURI.new(uri, config_auth)
end
def fetch_uri
diff --git a/lib/bundler/friendly_errors.rb b/lib/bundler/friendly_errors.rb
index 818a6b55f7..fde582c7f7 100644
--- a/lib/bundler/friendly_errors.rb
+++ b/lib/bundler/friendly_errors.rb
@@ -1,3 +1,4 @@
+# encoding: utf-8
require "bundler/vendored_thor"
module Bundler
@@ -33,10 +34,42 @@ module Bundler
rescue SystemExit => e
exit e.status
rescue Exception => e
- Bundler.ui.error <<-ERR, :wrap => true
- Unfortunately, a fatal error has occurred. Please see the Bundler \
- troubleshooting documentation at http://bit.ly/bundler-issues. Thanks!
- ERR
- raise e
+ request_issue_report_for(e)
+ exit 1
+ end
+
+ def self.request_issue_report_for(e)
+ Bundler.ui.info <<-EOS.gsub(/^ {6}/, '')
+ #{'――― ERROR REPORT TEMPLATE ―――――――――――――――――――――――――――――――――――――――――――――――――――――――'}
+ - What did you do?
+ - What did you expect to happen?
+ - What happened instead?
+
+ Error details
+
+ #{e.class}: #{e.message}
+ #{e.backtrace.join("\n ")}
+
+ #{Bundler::Env.new.report(:print_gemfile => false).gsub(/\n/, "\n ").strip}
+ #{'――― TEMPLATE END ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――'}
+
+ EOS
+
+ Bundler.ui.error "Unfortunately, an unexpected error occurred, and Bundler cannot continue."
+
+ Bundler.ui.warn <<-EOS.gsub(/^ {6}/, '')
+
+ First, try this link to see if there are any existing issue reports for this error:
+ #{issues_url(e)}
+
+ If there aren't any reports for this error yet, please create copy and paste the report template above into a new issue. Don't forget to anonymize any private data! The new issue form is located at:
+ https://github.com/bundler/bundler/issues/new
+ EOS
end
+
+ def self.issues_url(exception)
+ 'https://github.com/bundler/bundler/search?q=' \
+ "#{CGI.escape(exception.message)}&type=Issues"
+ end
+
end
diff --git a/lib/bundler/gem_helper.rb b/lib/bundler/gem_helper.rb
index 6b7a1760ca..6db31901e4 100644
--- a/lib/bundler/gem_helper.rb
+++ b/lib/bundler/gem_helper.rb
@@ -44,9 +44,22 @@ module Bundler
install_gem(built_gem_path)
end
- desc "Create tag #{version_tag} and build and push #{name}-#{version}.gem to Rubygems"
- task 'release' => 'build' do
- release_gem(built_gem_path)
+ desc "Create tag #{version_tag} and build and push #{name}-#{version}.gem to Rubygems\n" \
+ "To prevent publishing in Rubygems use `gem_push=no rake release`"
+ task 'release' => ['build', 'release:guard_clean',
+ 'release:source_control_push', 'release:rubygem_push'] do
+ end
+
+ task 'release:guard_clean' do
+ guard_clean
+ end
+
+ task 'release:source_control_push' do
+ tag_version { git_push } unless already_tagged?
+ end
+
+ task 'release:rubygem_push' do
+ rubygem_push(built_gem_path) if gem_push?
end
GemHelper.instance = self
@@ -70,13 +83,6 @@ module Bundler
Bundler.ui.confirm "#{name} (#{version}) installed."
end
- def release_gem(built_gem_path=nil)
- guard_clean
- built_gem_path ||= build_gem
- tag_version { git_push } unless already_tagged?
- rubygem_push(built_gem_path) if gem_push?
- end
-
protected
def rubygem_push(path)
if Pathname.new("~/.gem/credentials").expand_path.exist?
diff --git a/lib/bundler/gem_helpers.rb b/lib/bundler/gem_helpers.rb
index 2040604b78..a3bb514954 100644
--- a/lib/bundler/gem_helpers.rb
+++ b/lib/bundler/gem_helpers.rb
@@ -5,6 +5,7 @@ module Bundler
GENERICS = [
[Gem::Platform.new('java'), Gem::Platform.new('java')],
[Gem::Platform.new('mswin32'), Gem::Platform.new('mswin32')],
+ [Gem::Platform.new('mswin64'), Gem::Platform.new('mswin64')],
[Gem::Platform.new('x64-mingw32'), Gem::Platform.new('x64-mingw32')],
[Gem::Platform.new('x86_64-mingw32'), Gem::Platform.new('x64-mingw32')],
[Gem::Platform.new('mingw32'), Gem::Platform.new('x86-mingw32')]
diff --git a/lib/bundler/graph.rb b/lib/bundler/graph.rb
index 92f538b9fd..0b5c5723b4 100644
--- a/lib/bundler/graph.rb
+++ b/lib/bundler/graph.rb
@@ -3,12 +3,13 @@ module Bundler
class Graph
GRAPH_NAME = :Gemfile
- def initialize(env, output_file, show_version = false, show_requirements = false, output_format = "png")
+ def initialize(env, output_file, show_version = false, show_requirements = false, output_format = "png", without = [])
@env = env
@output_file = output_file
@show_version = show_version
@show_requirements = show_requirements
@output_format = output_format
+ @without_groups = without.map(&:to_sym)
@groups = []
@relations = Hash.new {|h, k| h[k] = Set.new}
@@ -53,6 +54,8 @@ module Bundler
relations = Hash.new {|h, k| h[k] = Set.new}
@env.current_dependencies.each do |dependency|
dependency.groups.each do |group|
+ next if @without_groups.include?(group)
+
relations[group.to_s].add(dependency)
@relations[group.to_s].add(dependency.name)
diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb
index 30f1940323..8076c685e5 100644
--- a/lib/bundler/index.rb
+++ b/lib/bundler/index.rb
@@ -16,7 +16,7 @@ module Bundler
def initialize
@sources = []
@cache = {}
- @specs = Hash.new { |h,k| h[k] = [] }
+ @specs = Hash.new { |h,k| h[k] = Hash.new }
@all_specs = Hash.new { |h,k| h[k] = [] }
end
@@ -24,11 +24,11 @@ module Bundler
super
@sources = @sources.dup
@cache = {}
- @specs = Hash.new { |h,k| h[k] = [] }
+ @specs = Hash.new { |h,k| h[k] = Hash.new }
@all_specs = Hash.new { |h,k| h[k] = [] }
- o.specs.each do |name, array|
- @specs[name] = array.dup
+ o.specs.each do |name, hash|
+ @specs[name] = hash.dup
end
o.all_specs.each do |name, array|
@all_specs[name] = array.dup
@@ -88,19 +88,14 @@ module Bundler
alias [] search
def <<(spec)
- arr = specs_by_name(spec.name)
+ @specs[spec.name]["#{spec.version}-#{spec.platform}"] = spec
- arr.delete_if do |s|
- same_version?(s.version, spec.version) && s.platform == spec.platform
- end
-
- arr << spec
spec
end
def each(&blk)
- specs.values.each do |specs|
- specs.each(&blk)
+ specs.values.each do |spec_sets|
+ spec_sets.values.each(&blk)
end
end
@@ -123,9 +118,9 @@ module Bundler
if (dupes = search_by_spec(s)) && dupes.any?
@all_specs[s.name] = [s] + dupes
next unless override_dupes
- @specs[s.name] -= dupes
+ self << s
end
- @specs[s.name] << s
+ self << s
end
self
end
@@ -155,7 +150,7 @@ module Bundler
private
def specs_by_name(name)
- @specs[name]
+ @specs[name].values
end
def search_by_dependency(dependency, base = nil)
@@ -182,9 +177,8 @@ module Bundler
end
def search_by_spec(spec)
- specs_by_name(spec.name).select do |s|
- same_version?(s.version, spec.version) && Gem::Platform.new(s.platform) == Gem::Platform.new(spec.platform)
- end
+ spec = @specs[spec.name]["#{spec.version}-#{spec.platform}"]
+ spec ? [spec] : []
end
if RUBY_VERSION < '1.9'
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index a4747c61c9..0654d91f09 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -1,6 +1,6 @@
require 'erb'
require 'rubygems/dependency_installer'
-require 'bundler/parallel_workers'
+require 'bundler/worker'
module Bundler
class Installer < Environment
@@ -84,7 +84,7 @@ module Bundler
# that said, it's a rare situation (other than rake), and parallel
# installation is just SO MUCH FASTER. so we let people opt in.
jobs = [Bundler.settings[:jobs].to_i-1, 1].max
- if jobs > 1 && can_install_parallely?
+ if jobs > 1 && can_install_in_parallel?
install_in_parallel jobs, options[:standalone]
else
install_sequentially options[:standalone]
@@ -96,20 +96,26 @@ module Bundler
def install_gem_from_spec(spec, standalone = false, worker = 0)
# Fetch the build settings, if there are any
- settings = Bundler.settings["build.#{spec.name}"]
- install_message = nil
- post_install_message = nil
- debug_message = nil
- Bundler.rubygems.with_build_args [settings] do
- install_message, post_install_message, debug_message = spec.source.install(spec)
- if install_message.include? 'Installing'
- Bundler.ui.confirm install_message
- else
- Bundler.ui.info install_message
+ settings = Bundler.settings["build.#{spec.name}"]
+ messages = nil
+
+ if settings
+ Bundler.rubygems.with_build_args [settings] do
+ messages = spec.source.install(spec)
end
- Bundler.ui.debug debug_message if debug_message
- Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
+ else
+ messages = spec.source.install(spec)
+ end
+
+ install_message, post_install_message, debug_message = *messages
+
+ if install_message.include? 'Installing'
+ Bundler.ui.confirm install_message
+ else
+ Bundler.ui.info install_message
end
+ Bundler.ui.debug debug_message if debug_message
+ Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
if Bundler.settings[:bin] && standalone
generate_standalone_bundler_executable_stubs(spec)
@@ -194,14 +200,13 @@ module Bundler
private
- def can_install_parallely?
- min_rubygems = "2.0.7"
- if Bundler.current_ruby.mri? || Bundler.rubygems.provides?(">= #{min_rubygems}")
+ def can_install_in_parallel?
+ if Bundler.rubygems.provides?(">= 2.1.0")
true
else
Bundler.ui.warn "Rubygems #{Gem::VERSION} is not threadsafe, so your "\
- "gems must be installed one at a time. Upgrade to Rubygems " \
- "#{min_rubygems} or higher to enable parallel gem installation."
+ "gems must be installed one at a time. Upgrade to Rubygems 2.1.0 " \
+ "or higher to enable parallel gem installation."
false
end
end
@@ -254,7 +259,7 @@ module Bundler
file.puts "ruby_version = RbConfig::CONFIG[\"ruby_version\"]"
file.puts "path = File.expand_path('..', __FILE__)"
paths.each do |path|
- file.puts %{$:.unshift File.expand_path("\#{path}/#{path}")}
+ file.puts %{$:.unshift "\#{path}/#{path}"}
end
end
end
@@ -277,9 +282,9 @@ module Bundler
remains[spec.name] = true
end
- worker_pool = ParallelWorkers.worker_pool size, lambda { |name, worker|
+ worker_pool = Worker.new size, lambda { |name, worker_num|
spec = name2spec[name]
- message = install_gem_from_spec spec, standalone, worker
+ message = install_gem_from_spec spec, standalone, worker_num
{ :name => spec.name, :post_install => message }
}
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index 32eb43a4dc..7030508988 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -47,14 +47,18 @@ module Bundler
end
@sources << @rubygems_aggregate
@specs = @specs.values
+ rescue ArgumentError => e
+ Bundler.ui.debug(e)
+ raise LockfileError, "Your lockfile is unreadable. Run `rm Gemfile.lock` " \
+ "and then `bundle install` to generate a new lockfile."
end
private
TYPES = {
- "GIT" => Bundler::Source::Git,
- "GEM" => Bundler::Source::Rubygems,
- "PATH" => Bundler::Source::Path
+ GIT => Bundler::Source::Git,
+ GEM => Bundler::Source::Rubygems,
+ PATH => Bundler::Source::Path,
}
def parse_source(line)
@@ -64,18 +68,18 @@ module Bundler
@opts, @type = {}, line
when SPECS
case @type
- when "PATH"
+ when PATH
@current_source = TYPES[@type].from_lock(@opts)
@sources << @current_source
- when "GIT"
+ when GIT
@current_source = TYPES[@type].from_lock(@opts)
# Strip out duplicate GIT sections
- if @type == "GIT" && @sources.include?(@current_source)
+ if @sources.include?(@current_source)
@current_source = @sources.find { |s| s == @current_source }
else
@sources << @current_source
end
- when "GEM"
+ when GEM
Array(@opts["remote"]).each do |url|
@rubygems_aggregate.add_remote(url)
end
diff --git a/lib/bundler/parallel_workers.rb b/lib/bundler/parallel_workers.rb
deleted file mode 100644
index b28f630461..0000000000
--- a/lib/bundler/parallel_workers.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'thread'
-
-require "bundler/parallel_workers/worker"
-
-module Bundler
- module ParallelWorkers
- autoload :UnixWorker, "bundler/parallel_workers/unix_worker"
- autoload :ThreadWorker, "bundler/parallel_workers/thread_worker"
-
- def self.worker_pool(size, job)
- if Bundler.current_ruby.mswin? || Bundler.current_ruby.jruby? || Bundler.current_ruby.rbx?
- ThreadWorker.new(size, job)
- else
- UnixWorker.new(size, job)
- end
- end
- end
-end
diff --git a/lib/bundler/parallel_workers/thread_worker.rb b/lib/bundler/parallel_workers/thread_worker.rb
deleted file mode 100644
index ef2c9ecd18..0000000000
--- a/lib/bundler/parallel_workers/thread_worker.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-module Bundler
- module ParallelWorkers
- class ThreadWorker < Worker
-
- private
-
- # On platforms where fork is not available
- # use Threads for parallely downloading gems
- #
- # @param size [Integer] Size of thread worker pool
- # @param func [Proc] Job to be run inside thread worker pool
- def prepare_workers(size, func)
- @threads = size.times.map do |i|
- Thread.start do
- loop do
- obj = @request_queue.deq
- break if obj.equal? POISON
- begin
- @response_queue.enq func.call(obj, i)
- rescue Exception => e
- @response_queue.enq(WrappedException.new(e))
- end
- end
- end
- end
- end
-
- end
- end
-end
diff --git a/lib/bundler/parallel_workers/unix_worker.rb b/lib/bundler/parallel_workers/unix_worker.rb
deleted file mode 100644
index 94a07bf970..0000000000
--- a/lib/bundler/parallel_workers/unix_worker.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-module Bundler
- module ParallelWorkers
- # UnixWorker is used only on platforms where fork is available. The way
- # this code works is, it forks a preconfigured number of workers and then
- # It starts preconfigured number of threads that write to the connected pipe.
- class UnixWorker < Worker
-
- class JobHandler < Struct.new(:pid, :io_r, :io_w)
- def work(obj)
- Marshal.dump obj, io_w
- Marshal.load io_r
- rescue IOError, Errno::EPIPE
- nil
- end
- end
-
- def initialize(size, job)
- # Close the persistent connections for the main thread before forking
- Net::HTTP::Persistent.new('bundler', :ENV).shutdown
- super
- end
-
- private
-
- # Start forked workers for downloading gems. This version of worker
- # is only used on platforms where fork is available.
- #
- # @param size [Integer] Size of worker pool
- # @param func [Proc] Job that should be executed in the worker
- def prepare_workers(size, func)
- @workers = size.times.map do |num|
- child_read, parent_write = IO.pipe
- parent_read, child_write = IO.pipe
-
- pid = Process.fork do
- begin
- parent_read.close
- parent_write.close
-
- while !child_read.eof?
- obj = Marshal.load child_read
- Marshal.dump func.call(obj, num), child_write
- end
- rescue Exception => e
- begin
- Marshal.dump WrappedException.new(e), child_write
- rescue Errno::EPIPE
- nil
- end
- ensure
- child_read.close
- child_write.close
- end
- end
-
- child_read.close
- child_write.close
- JobHandler.new pid, parent_read, parent_write
- end
- end
-
- # Start the threads whose job is basically to wait for incoming messages
- # on request queue and write that message to the connected pipe. Also retrieve
- # messages from child worker via connected pipe and write the message to response queue
- #
- # @param size [Integer] Number of threads to be started
- def prepare_threads(size)
- @threads = size.times.map do |i|
- Thread.start do
- worker = @workers[i]
- loop do
- obj = @request_queue.deq
- break if obj.equal? POISON
- @response_queue.enq worker.work(obj)
- end
- end
- end
- end
-
- # Kill the forked workers by sending SIGINT to them
- def stop_workers
- @workers.each do |worker|
- worker.io_r.close unless worker.io_r.closed?
- worker.io_w.close unless worker.io_w.closed?
- begin
- Process.kill :INT, worker.pid
- rescue Errno::ESRCH
- nil
- end
- end
- @workers.each do |worker|
- begin
- Process.waitpid worker.pid
- rescue Errno::ECHILD
- nil
- end
- end
- end
- end
- end
-end
diff --git a/lib/bundler/parallel_workers/worker.rb b/lib/bundler/parallel_workers/worker.rb
deleted file mode 100644
index 0e101d1c5f..0000000000
--- a/lib/bundler/parallel_workers/worker.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-module Bundler
- module ParallelWorkers
- class Worker
- POISON = Object.new
-
- class WrappedException < StandardError
- attr_reader :exception
- def initialize(exn)
- @exception = exn
- end
- end
-
- # Creates a worker pool of specified size
- #
- # @param size [Integer] Size of pool
- # @param func [Proc] job to run in inside the worker pool
- def initialize(size, func)
- @request_queue = Queue.new
- @response_queue = Queue.new
- prepare_workers size, func
- prepare_threads size
- trap("INT") { @threads.each {|i| i.exit }; stop_workers; exit 1 }
- end
-
- # Enqueue a request to be executed in the worker pool
- #
- # @param obj [String] mostly it is name of spec that should be downloaded
- def enq(obj)
- @request_queue.enq obj
- end
-
- # Retrieves results of job function being executed in worker pool
- def deq
- result = @response_queue.deq
- if result.is_a?(WrappedException)
- raise result.exception
- end
- result
- end
-
- # Stop the forked workers and started threads
- def stop
- stop_threads
- stop_workers
- end
-
- private
- # Stop the worker threads by sending a poison object down the request queue
- # so as worker threads after retrieving it, shut themselves down
- def stop_threads
- @threads.each do
- @request_queue.enq POISON
- end
- @threads.each do |thread|
- thread.join
- end
- end
-
- # To be overridden by child classes
- def prepare_threads(size)
- end
-
- # To be overridden by child classes
- def stop_workers
- end
-
- end
- end
-end
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index a8d3d1a7ff..709ad67a34 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -141,6 +141,7 @@ module Bundler
@index = index
@deps_for = {}
@missing_gems = Hash.new(0)
+ @prereleases_cache = Hash.new { |h,k| h[k] = k.prerelease? }
@source_requirements = source_requirements
@iteration_counter = 0
@started_at = Time.now
@@ -269,7 +270,7 @@ module Bundler
reqs = reqs.sort_by do |a|
[ activated[a.name] ? 0 : 1,
- a.requirement.prerelease? ? 0 : 1,
+ @prereleases_cache[a.requirement] ? 0 : 1,
@errors[a.name] ? 0 : 1,
activated[a.name] ? 0 : @gems_size[a] ]
end
diff --git a/lib/bundler/ruby_version.rb b/lib/bundler/ruby_version.rb
index 862dd35a61..da6ebae080 100644
--- a/lib/bundler/ruby_version.rb
+++ b/lib/bundler/ruby_version.rb
@@ -38,7 +38,7 @@ module Bundler
patchlevel == other.patchlevel
end
- # Returns a tuple of thsee things:
+ # Returns a tuple of these things:
# [diff, this, other]
# The priority of attributes are
# 1. engine
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
index 659a04b11d..55f2139a59 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -149,6 +149,7 @@ module Gem
class Platform
JAVA = Gem::Platform.new('java') unless defined?(JAVA)
MSWIN = Gem::Platform.new('mswin32') unless defined?(MSWIN)
+ MSWIN64 = Gem::Platform.new('mswin64') unless defined?(MSWIN64)
MINGW = Gem::Platform.new('x86-mingw32') unless defined?(MINGW)
X64_MINGW = Gem::Platform.new('x64-mingw32') unless defined?(X64_MINGW)
diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb
index eb354605e7..0107663057 100644
--- a/lib/bundler/rubygems_integration.rb
+++ b/lib/bundler/rubygems_integration.rb
@@ -1,3 +1,4 @@
+require 'monitor'
require 'rubygems'
require 'rubygems/config_file'
@@ -134,6 +135,10 @@ module Bundler
Gem::DefaultUserInteraction.ui = obj
end
+ def ext_lock
+ @ext_lock ||= Monitor.new
+ end
+
def fetch_specs(all, pre, &blk)
specs = Gem::SpecFetcher.new.list(all, pre)
specs.each { yield } if block_given?
@@ -156,12 +161,14 @@ module Bundler
end
def with_build_args(args)
- old_args = self.build_args
- begin
- self.build_args = args
- yield
- ensure
- self.build_args = old_args
+ ext_lock.synchronize do
+ old_args = self.build_args
+ begin
+ self.build_args = args
+ yield
+ ensure
+ self.build_args = old_args
+ end
end
end
@@ -306,12 +313,12 @@ module Bundler
if exec_name
spec = specs.find { |s| s.executables.include?(exec_name) }
+ spec or raise Gem::Exception, "can't find executable #{exec_name}"
unless spec.name == name
warn "Bundler is using a binstub that was created for a different gem.\n" \
"This is deprecated, in future versions you may need to `bundle binstub #{name}` " \
"to work around a system/bundle conflict."
end
- spec or raise Gem::Exception, "can't find executable #{exec_name}"
else
spec = specs.find { |s| s.name == name }
exec_name = spec.default_executable or raise Gem::Exception, "no default executable for #{spec.full_name}"
@@ -554,9 +561,43 @@ module Bundler
end
end
+ class MoreFuture < Future
+ def initialize
+ super
+ backport_ext_builder_monitor
+ end
+
+ def backport_ext_builder_monitor
+ require 'rubygems/ext'
+
+ Gem::Ext::Builder.class_eval do
+ if !const_defined?(:CHDIR_MONITOR)
+ const_set(:CHDIR_MONITOR, Monitor.new)
+ end
+
+ if const_defined?(:CHDIR_MUTEX)
+ remove_const(:CHDIR_MUTEX)
+ const_set(:CHDIR_MUTEX, const_get(:CHDIR_MONITOR))
+ end
+ end
+ end
+
+ def ext_lock
+ Gem::Ext::Builder::CHDIR_MONITOR
+ end
+
+ def find_name(name)
+ Gem::Specification.stubs.find_all do |spec|
+ spec.name == name
+ end.map(&:to_spec)
+ end
+ end
+
end
- if RubygemsIntegration.provides?(">= 1.99.99")
+ if RubygemsIntegration.provides?(">= 2.1.0")
+ @rubygems = RubygemsIntegration::MoreFuture.new
+ elsif RubygemsIntegration.provides?(">= 1.99.99")
@rubygems = RubygemsIntegration::Future.new
elsif RubygemsIntegration.provides?('>= 1.8.20')
@rubygems = RubygemsIntegration::MoreModern.new
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index b09a8814e5..be61c2b15b 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -46,7 +46,7 @@ module Bundler
self
end
- REGEXPS = [
+ REQUIRE_ERRORS = [
/^no such file to load -- (.+)$/i,
/^Missing \w+ (?:file\s*)?([^\s]+.rb)$/i,
/^Missing API definition file in (.+)$/i,
@@ -76,18 +76,16 @@ module Bundler
Kernel.require file
end
rescue LoadError => e
- REGEXPS.find { |r| r =~ e.message }
+ REQUIRE_ERRORS.find { |r| r =~ e.message }
raise if dep.autorequire || $1 != required_file
if dep.autorequire.nil? && dep.name.include?('-')
begin
namespaced_file = dep.name.gsub('-', '/')
Kernel.require namespaced_file
- rescue LoadError
- REGEXPS.find { |r| r =~ e.message }
- regex_name = $1
- raise e if dep.autorequire || (regex_name && regex_name.gsub('-', '/') != namespaced_file)
- raise e if regex_name.nil?
+ rescue LoadError => e
+ REQUIRE_ERRORS.find { |r| r =~ e.message }
+ raise if $1 != namespaced_file
end
end
end
@@ -105,12 +103,13 @@ module Bundler
alias gems specs
def cache(custom_path = nil)
- cache_path = cache_path(custom_path)
+ cache_path = Bundler.app_cache(custom_path)
FileUtils.mkdir_p(cache_path) unless File.exist?(cache_path)
- Bundler.ui.info "Updating files in vendor/cache"
+ Bundler.ui.info "Updating files in #{Bundler.settings.app_cache_path}"
specs.each do |spec|
next if spec.name == 'bundler'
+ spec.source.send(:fetch_gem, spec) if Bundler.settings[:cache_all_platforms] && spec.source.respond_to?(:fetch_gem, true)
spec.source.cache(spec, custom_path) if spec.source.respond_to?(:cache)
end
@@ -119,15 +118,14 @@ module Bundler
FileUtils.touch(File.expand_path("../.bundlecache", git_dir))
end
- prune_cache(custom_path) unless Bundler.settings[:no_prune]
+ prune_cache(cache_path) unless Bundler.settings[:no_prune]
end
- def prune_cache(custom_path)
- cache_path = cache_path(custom_path)
+ def prune_cache(cache_path)
FileUtils.mkdir_p(cache_path) unless File.exist?(cache_path)
resolve = @definition.resolve
- prune_gem_cache(resolve, custom_path)
- prune_git_and_path_cache(resolve, custom_path)
+ prune_gem_cache(resolve, cache_path)
+ prune_git_and_path_cache(resolve, cache_path)
end
def clean(dry_run = false)
@@ -218,31 +216,16 @@ module Bundler
ENV["BUNDLE_BIN_PATH"] = File.expand_path("../../../bin/bundle", __FILE__)
end
- # Set PATH
- paths = (ENV["PATH"] || "").split(File::PATH_SEPARATOR)
- paths.unshift "#{Bundler.bundle_path}/bin"
- ENV["PATH"] = paths.uniq.join(File::PATH_SEPARATOR)
-
# Set BUNDLE_GEMFILE
ENV["BUNDLE_GEMFILE"] = default_gemfile.to_s
- # Set RUBYOPT
- rubyopt = [ENV["RUBYOPT"]].compact
- if rubyopt.empty? || rubyopt.first !~ /-rbundler\/setup/
- rubyopt.unshift %|-rbundler/setup|
- ENV["RUBYOPT"] = rubyopt.join(' ')
- end
-
- # Set RUBYLIB
- rubylib = (ENV["RUBYLIB"] || "").split(File::PATH_SEPARATOR)
- rubylib.unshift File.expand_path('../..', __FILE__)
- ENV["RUBYLIB"] = rubylib.uniq.join(File::PATH_SEPARATOR)
+ SharedHelpers.set_bundle_environment
end
private
- def prune_gem_cache(resolve, custom_path)
- cached = Dir["#{cache_path(custom_path)}/*.gem"]
+ def prune_gem_cache(resolve, cache_path)
+ cached = Dir["#{cache_path}/*.gem"]
cached = cached.delete_if do |path|
spec = Bundler.rubygems.spec_from_gem path
@@ -253,7 +236,7 @@ module Bundler
end
if cached.any?
- Bundler.ui.info "Removing outdated .gem files from vendor/cache"
+ Bundler.ui.info "Removing outdated .gem files from #{Bundler.settings.app_cache_path}"
cached.each do |path|
Bundler.ui.info " * #{File.basename(path)}"
@@ -262,8 +245,8 @@ module Bundler
end
end
- def prune_git_and_path_cache(resolve, custom_path)
- cached = Dir["#{cache_path(custom_path)}/*/.bundlecache"]
+ def prune_git_and_path_cache(resolve, cache_path)
+ cached = Dir["#{cache_path}/*/.bundlecache"]
cached = cached.delete_if do |path|
name = File.basename(File.dirname(path))
@@ -275,7 +258,7 @@ module Bundler
end
if cached.any?
- Bundler.ui.info "Removing outdated git and path gems from vendor/cache"
+ Bundler.ui.info "Removing outdated git and path gems from #{Bundler.settings.app_cache_path}"
cached.each do |path|
path = File.dirname(path)
@@ -302,9 +285,5 @@ module Bundler
end
end
- def cache_path(custom_path = nil)
- path = custom_path || root
- path.join("vendor/cache")
- end
end
end
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb
index d229ba8134..a29e7104c7 100644
--- a/lib/bundler/settings.rb
+++ b/lib/bundler/settings.rb
@@ -1,15 +1,24 @@
+require 'uri'
+
module Bundler
class Settings
+ BOOL_KEYS = %w(frozen cache_all no_prune disable_local_branch_check gem.mit gem.coc).freeze
+
def initialize(root = nil)
@root = root
@local_config = load_config(local_config_file)
@global_config = load_config(global_config_file)
end
- def [](key)
- the_key = key_for(key)
- value = (@local_config[the_key] || ENV[the_key] || @global_config[the_key])
- is_bool(key) ? to_bool(value) : value
+ def [](name)
+ key = key_for(name)
+ value = (@local_config[key] || ENV[key] || @global_config[key])
+
+ if !value.nil? && is_bool(name)
+ to_bool(value)
+ else
+ value
+ end
end
def []=(key, value)
@@ -115,18 +124,29 @@ module Bundler
ENV['BUNDLE_IGNORE_CONFIG']
end
+ def app_cache_path
+ @app_cache_path ||= begin
+ path = self[:cache_path] || "vendor/cache"
+ raise InvalidOption, "Cache path must be relative to the bundle path" if path.start_with?("/")
+ path
+ end
+ end
+
private
def key_for(key)
- key = key.to_s.sub(".", "__").upcase
+ if key.is_a?(String) && /https?:/ =~ key
+ key = normalize_uri(key).to_s
+ end
+ key = key.to_s.gsub(".", "__").upcase
"BUNDLE_#{key}"
end
def is_bool(key)
- %w(frozen cache_all no_prune disable_local_branch_check).include? key.to_s
+ BOOL_KEYS.include?(key.to_s)
end
def to_bool(value)
- !(value.nil? || value == '' || value =~ /^(false|f|no|n|0)$/i)
+ !(value.nil? || value == '' || value =~ /^(false|f|no|n|0)$/i || value == false)
end
def set_key(key, value, hash, file)
@@ -172,7 +192,9 @@ module Bundler
uri = uri.to_s
uri = "#{uri}/" unless uri =~ %r[/\Z]
uri = URI(uri)
- raise ArgumentError, "Gem mirror sources must be absolute URIs (configured: #{mirror_source})" unless uri.absolute?
+ unless uri.absolute?
+ raise ArgumentError, "Gem sources must be absolute. You provided '#{uri}'."
+ end
uri
end
diff --git a/lib/bundler/setup.rb b/lib/bundler/setup.rb
index 3059975d4e..6bf598337e 100644
--- a/lib/bundler/setup.rb
+++ b/lib/bundler/setup.rb
@@ -2,7 +2,8 @@ require 'bundler/shared_helpers'
if Bundler::SharedHelpers.in_bundle?
require 'bundler'
- if STDOUT.tty?
+
+ if STDOUT.tty? || ENV['BUNDLER_FORCE_TTY']
begin
Bundler.setup
rescue Bundler::BundlerError => e
diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb
index 20db09c3e5..cd4ad71737 100644
--- a/lib/bundler/shared_helpers.rb
+++ b/lib/bundler/shared_helpers.rb
@@ -1,4 +1,3 @@
-require 'monitor'
require 'pathname'
require 'rubygems'
@@ -19,7 +18,6 @@ end
module Bundler
module SharedHelpers
attr_accessor :gem_loaded
- CHDIR_MONITOR = Monitor.new
def default_gemfile
gemfile = find_gemfile
@@ -28,25 +26,36 @@ module Bundler
end
def default_lockfile
- Pathname.new("#{default_gemfile}.lock")
+ gemfile = default_gemfile
+
+ case gemfile.basename.to_s
+ when 'gems.rb' then Pathname.new(gemfile.sub(/.rb$/, '.locked'))
+ else Pathname.new("#{gemfile}.lock")
+ end
end
- def in_bundle?
- find_gemfile
+ def default_bundle_dir
+ bundle_dir = find_directory(".bundle")
+ return nil unless bundle_dir
+
+ global_bundle_dir = File.join(Bundler.rubygems.user_home, ".bundle")
+ return nil if bundle_dir == global_bundle_dir
+
+ Pathname.new(bundle_dir)
end
- def chdir_monitor
- CHDIR_MONITOR
+ def in_bundle?
+ find_gemfile
end
def chdir(dir, &blk)
- chdir_monitor.synchronize do
+ Bundler.rubygems.ext_lock.synchronize do
Dir.chdir dir, &blk
end
end
def pwd
- chdir_monitor.synchronize do
+ Bundler.rubygems.ext_lock.synchronize do
Dir.pwd
end
end
@@ -64,12 +73,47 @@ module Bundler
keys.each {|key| ENV[key] = old_env[key] }
end
+ def set_bundle_environment
+ # Set PATH
+ paths = (ENV["PATH"] || "").split(File::PATH_SEPARATOR)
+ paths.unshift "#{Bundler.bundle_path}/bin"
+ ENV["PATH"] = paths.uniq.join(File::PATH_SEPARATOR)
+
+ # Set RUBYOPT
+ rubyopt = [ENV["RUBYOPT"]].compact
+ if rubyopt.empty? || rubyopt.first !~ /-rbundler\/setup/
+ rubyopt.unshift %|-rbundler/setup|
+ ENV["RUBYOPT"] = rubyopt.join(' ')
+ end
+
+ # Set RUBYLIB
+ rubylib = (ENV["RUBYLIB"] || "").split(File::PATH_SEPARATOR)
+ rubylib.unshift File.expand_path('../..', __FILE__)
+ ENV["RUBYLIB"] = rubylib.uniq.join(File::PATH_SEPARATOR)
+ end
+
private
def find_gemfile
given = ENV['BUNDLE_GEMFILE']
return given if given && !given.empty?
+ find_file('Gemfile', 'gems.rb')
+ end
+
+ def find_file(*names)
+ search_up(*names) {|filename|
+ return filename if File.file?(filename)
+ }
+ end
+
+ def find_directory(*names)
+ search_up(*names) do |dirname|
+ return dirname if File.directory?(dirname)
+ end
+ end
+
+ def search_up(*names)
previous = nil
current = File.expand_path(SharedHelpers.pwd)
@@ -79,9 +123,10 @@ module Bundler
return nil if File.file?(File.join(current, 'bundler.gemspec'))
end
- # otherwise return the Gemfile if it's there
- filename = File.join(current, 'Gemfile')
- return filename if File.file?(filename)
+ names.each do |name|
+ filename = File.join(current, name)
+ yield filename
+ end
current, previous = File.expand_path("..", current), current
end
end
diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb
index 1f8cf2cbe7..b544451dc0 100644
--- a/lib/bundler/source.rb
+++ b/lib/bundler/source.rb
@@ -21,12 +21,16 @@ module Bundler
end
def version_message(spec)
- locked_spec = Bundler.locked_gems.specs.find { |s| s.name == spec.name } if Bundler.locked_gems
- locked_spec_version = locked_spec.version if locked_spec
message = "#{spec.name} #{spec.version}"
- if locked_spec_version && spec.version != locked_spec_version
- message << " (was #{locked_spec_version})"
+
+ if Bundler.locked_gems
+ locked_spec = Bundler.locked_gems.specs.find { |s| s.name == spec.name }
+ locked_spec_version = locked_spec.version if locked_spec
+ if locked_spec_version && spec.version != locked_spec_version
+ message << " (was #{locked_spec_version})"
+ end
end
+
message
end
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb
index 756b96dcc2..62d615088c 100644
--- a/lib/bundler/source/git.rb
+++ b/lib/bundler/source/git.rb
@@ -20,7 +20,7 @@ module Bundler
# Stringify options that could be set as symbols
%w(ref branch tag revision).each{|k| options[k] = options[k].to_s if options[k] }
- @uri = options["uri"]
+ @uri = options["uri"] || ''
@branch = options["branch"]
@ref = options["ref"] || options["branch"] || options["tag"] || 'master'
@submodules = options["submodules"]
@@ -46,6 +46,10 @@ module Bundler
out << " specs:\n"
end
+ def hash
+ [self.class, uri, ref, branch, name, version, submodules].hash
+ end
+
def eql?(o)
o.is_a?(Git) &&
uri == o.uri &&
diff --git a/lib/bundler/source/git/git_proxy.rb b/lib/bundler/source/git/git_proxy.rb
index 29100a1e74..89c784e0fa 100644
--- a/lib/bundler/source/git/git_proxy.rb
+++ b/lib/bundler/source/git/git_proxy.rb
@@ -60,6 +60,10 @@ module Bundler
end
end
+ def version
+ git("--version").sub("git version", "").strip
+ end
+
def checkout
if path.exist?
return if has_revision_cached?
diff --git a/lib/bundler/source/path.rb b/lib/bundler/source/path.rb
index 0d0d3ae683..59131a52b4 100644
--- a/lib/bundler/source/path.rb
+++ b/lib/bundler/source/path.rb
@@ -54,19 +54,19 @@ module Bundler
end
def hash
- self.class.hash
+ [self.class, expanded_path, version].hash
end
def eql?(o)
o.instance_of?(Path) &&
- expand(path) == expand(o.path) &&
+ expanded_path == expand(o.path) &&
version == o.version
end
alias == eql?
def name
- File.basename(expand(path).to_s)
+ File.basename(expanded_path.to_s)
end
def install(spec)
@@ -95,6 +95,7 @@ module Bundler
def specs
if has_app_cache?
@path = app_cache_path
+ @expanded_path = nil # Invalidate
end
local_specs
end
@@ -105,6 +106,10 @@ module Bundler
private
+ def expanded_path
+ @expanded_path ||= expand(path)
+ end
+
def expand(somepath)
somepath.expand_path(Bundler.root)
rescue ArgumentError => e
@@ -123,7 +128,6 @@ module Bundler
def load_spec_files
index = Index.new
- expanded_path = expand(path)
if File.directory?(expanded_path)
Dir["#{expanded_path}/#{@glob}"].each do |file|
@@ -168,8 +172,7 @@ module Bundler
end
def generate_bin(spec, disable_extensions = false)
- gem_dir = Pathname.new(spec.full_gem_path)
- gem_file = nil
+ gem_dir = Pathname.new(spec.full_gem_path)
# Some gem authors put absolute paths in their gemspec
# and we have to save them from themselves
@@ -183,8 +186,6 @@ module Bundler
end.compact
SharedHelpers.chdir(gem_dir) do
- gem_file = Bundler.rubygems.build_gem gem_dir, spec
-
installer = Path::Installer.new(spec, :env_shebang => false)
run_hooks(:pre_install, installer)
installer.build_extensions unless disable_extensions
@@ -204,10 +205,6 @@ module Bundler
end
Bundler.ui.warn "The validation message from Rubygems was:\n #{e.message}"
- ensure
- if gem_dir && gem_file
- FileUtils.rm_rf(gem_dir.join gem_file)
- end
end
def run_hooks(type, installer)
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index 99cea1fa05..0053688f38 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -5,8 +5,10 @@ require 'rubygems/spec_fetcher'
module Bundler
class Source
class Rubygems < Source
- # threshold for switching back to the modern index instead of fetching every spec
- API_REQUEST_LIMIT = 100
+ # Use the API when installing less than X gems
+ API_REQUEST_LIMIT = 500
+ # Ask for X gems per API request
+ API_REQUEST_SIZE = 50
attr_reader :remotes, :caches
@@ -97,49 +99,50 @@ module Bundler
spec.__swap__(s)
end
- path = cached_gem(spec)
- if Bundler.requires_sudo?
- install_path = Bundler.tmp(spec.full_name)
- bin_path = install_path.join("bin")
- else
- install_path = Bundler.rubygems.gem_dir
- bin_path = Bundler.system_bindir
- end
+ unless Bundler.settings[:no_install]
+ path = cached_gem(spec)
+ if Bundler.requires_sudo?
+ install_path = Bundler.tmp(spec.full_name)
+ bin_path = install_path.join("bin")
+ else
+ install_path = Bundler.rubygems.gem_dir
+ bin_path = Bundler.system_bindir
+ end
- installed_spec = nil
- Bundler.rubygems.preserve_paths do
- installed_spec = Bundler::GemInstaller.new(path,
- :install_dir => install_path.to_s,
- :bin_dir => bin_path.to_s,
- :ignore_dependencies => true,
- :wrappers => true,
- :env_shebang => true
- ).install
- end
+ installed_spec = nil
+ Bundler.rubygems.preserve_paths do
+ installed_spec = Bundler::GemInstaller.new(path,
+ :install_dir => install_path.to_s,
+ :bin_dir => bin_path.to_s,
+ :ignore_dependencies => true,
+ :wrappers => true,
+ :env_shebang => true
+ ).install
+ end
- # SUDO HAX
- if Bundler.requires_sudo?
- Bundler.rubygems.repository_subdirectories.each do |name|
- src = File.join(install_path, name, "*")
- dst = File.join(Bundler.rubygems.gem_dir, name)
- if name == "extensions" && Dir.glob(src).any?
- src = File.join(src, "*/*")
- ext_src = Dir.glob(src).first
- ext_src.gsub!(src[0..-6], '')
- dst = File.dirname(File.join(dst, ext_src))
+ # SUDO HAX
+ if Bundler.requires_sudo?
+ Bundler.rubygems.repository_subdirectories.each do |name|
+ src = File.join(install_path, name, "*")
+ dst = File.join(Bundler.rubygems.gem_dir, name)
+ if name == "extensions" && Dir.glob(src).any?
+ src = File.join(src, "*/*")
+ ext_src = Dir.glob(src).first
+ ext_src.gsub!(src[0..-6], '')
+ dst = File.dirname(File.join(dst, ext_src))
+ end
+ Bundler.mkdir_p dst
+ Bundler.sudo "cp -R #{src} #{dst}" if Dir[src].any?
end
- Bundler.mkdir_p dst
- Bundler.sudo "cp -R #{src} #{dst}" if Dir[src].any?
- end
- spec.executables.each do |exe|
- Bundler.mkdir_p Bundler.system_bindir
- Bundler.sudo "cp -R #{install_path}/bin/#{exe} #{Bundler.system_bindir}/"
+ spec.executables.each do |exe|
+ Bundler.mkdir_p Bundler.system_bindir
+ Bundler.sudo "cp -R #{install_path}/bin/#{exe} #{Bundler.system_bindir}/"
+ end
end
+ installed_spec.loaded_from = loaded_from(spec)
end
-
- spec.loaded_from = "#{Bundler.rubygems.gem_dir}/specifications/#{spec.full_name}.gemspec"
- installed_spec.loaded_from = spec.loaded_from
+ spec.loaded_from = loaded_from(spec)
["Installing #{version_message(spec)}", spec.post_install_message]
ensure
if install_path && Bundler.requires_sudo?
@@ -157,6 +160,9 @@ module Bundler
return if File.dirname(cached_path) == Bundler.app_cache.to_s
Bundler.ui.info " * #{File.basename(cached_path)}"
FileUtils.cp(cached_path, Bundler.app_cache(custom_path))
+ rescue Errno::EACCES => e
+ Bundler.ui.debug(e)
+ raise InstallError, e.message
end
def cached_built_in_gem(spec)
@@ -190,6 +196,12 @@ module Bundler
end
end
+ def fetchers
+ @fetchers ||= remotes.map do |uri|
+ Bundler::Fetcher.new(uri)
+ end
+ end
+
protected
def credless_remotes
@@ -199,12 +211,16 @@ module Bundler
private
def source_uris_for_spec(spec)
- specs.search_all(spec.name).inject([]) do |uris, spec|
- uris << spec.source_uri.without_credentials if spec.source_uri
+ specs.search_all(spec.name).inject([]) do |uris, s|
+ uris << s.source_uri.without_credentials if s.source_uri
uris
end
end
+ def loaded_from(spec)
+ "#{Bundler.rubygems.gem_dir}/specifications/#{spec.full_name}.gemspec"
+ end
+
def cached_gem(spec)
cached_gem = cached_path(spec)
unless cached_gem
@@ -281,12 +297,6 @@ module Bundler
idx
end
- def fetchers
- @fetchers ||= remotes.map do |url|
- Bundler::Fetcher.new(url)
- end
- end
-
def api_fetchers
fetchers.select{|f| f.use_api }
end
diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb
index 49a976ba6a..49efbf7a8e 100644
--- a/lib/bundler/source_list.rb
+++ b/lib/bundler/source_list.rb
@@ -74,6 +74,10 @@ module Bundler
all_sources.each(&:remote!)
end
+ def rubygems_primary_remotes
+ @rubygems_aggregate.remotes
+ end
+
private
def add_source_to_list(source, list)
diff --git a/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt b/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
new file mode 100644
index 0000000000..c5393d1403
--- /dev/null
+++ b/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
@@ -0,0 +1,13 @@
+# Contributor Code of Conduct
+
+As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
+
+We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
+
+Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
+
+This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
diff --git a/lib/bundler/templates/newgem/LICENSE.txt.tt b/lib/bundler/templates/newgem/LICENSE.txt.tt
index a9f52e6bbb..8fef84cd53 100644
--- a/lib/bundler/templates/newgem/LICENSE.txt.tt
+++ b/lib/bundler/templates/newgem/LICENSE.txt.tt
@@ -1,22 +1,21 @@
-Copyright (c) <%=Time.now.year%> <%=config[:author]%>
+The MIT License (MIT)
-MIT License
+Copyright (c) <%=Time.now.year%> <%=config[:author]%>
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/lib/bundler/templates/newgem/README.md.tt b/lib/bundler/templates/newgem/README.md.tt
index 8a65988cae..45d901738f 100644
--- a/lib/bundler/templates/newgem/README.md.tt
+++ b/lib/bundler/templates/newgem/README.md.tt
@@ -1,6 +1,8 @@
# <%=config[:constant_name]%>
-TODO: Write a gem description
+Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/<%=config[:namespaced_path]%>`. To experiment with that code, run `bin/console` for an interactive prompt.
+
+TODO: Delete this and the text above, and describe your gem
## Installation
@@ -22,6 +24,12 @@ Or install it yourself as:
TODO: Write usage instructions here
+## Development
+
+After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.<% if config[:bin] %> Run `bundle exec <%= config[:name] %>` to use the code located in this directory, ignoring other installed copies of this gem.<% end %>
+
+To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
+
## Contributing
1. Fork it ( https://github.com/[my-github-username]/<%=config[:name]%>/fork )
diff --git a/lib/bundler/templates/newgem/Rakefile.tt b/lib/bundler/templates/newgem/Rakefile.tt
index f4fc3c6ee9..d48487418c 100644
--- a/lib/bundler/templates/newgem/Rakefile.tt
+++ b/lib/bundler/templates/newgem/Rakefile.tt
@@ -18,6 +18,8 @@ task :default => :spec
<% if config[:ext] -%>
require "rake/extensiontask"
+task :build => :compile
+
Rake::ExtensionTask.new("<%=config[:underscored_name]%>") do |ext|
ext.lib_dir = "lib/<%=config[:namespaced_path]%>"
end
diff --git a/lib/bundler/templates/newgem/bin/console.tt b/lib/bundler/templates/newgem/bin/console.tt
new file mode 100644
index 0000000000..f402bd639e
--- /dev/null
+++ b/lib/bundler/templates/newgem/bin/console.tt
@@ -0,0 +1,14 @@
+#!/usr/bin/env ruby
+
+require "bundler/setup"
+require "<%= config[:namespaced_path] %>"
+
+# You can add fixtures and/or initialization code here to make experimenting
+# with your gem easier. You can also use a different console, if you like.
+
+# (If you use this, don't forget to add pry to your Gemfile!)
+# require "pry"
+# Pry.start
+
+require "irb"
+IRB.start
diff --git a/lib/bundler/templates/newgem/bin/newgem.tt b/lib/bundler/templates/newgem/bin/newgem.tt
deleted file mode 100644
index a005298815..0000000000
--- a/lib/bundler/templates/newgem/bin/newgem.tt
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-
-require '<%= config[:namespaced_path] %>'
diff --git a/lib/bundler/templates/newgem/bin/setup.tt b/lib/bundler/templates/newgem/bin/setup.tt
new file mode 100644
index 0000000000..b65ed50ff1
--- /dev/null
+++ b/lib/bundler/templates/newgem/bin/setup.tt
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+bundle install
+
+# Do any other automated setup that you need to do here
diff --git a/lib/bundler/templates/newgem/exe/newgem.tt b/lib/bundler/templates/newgem/exe/newgem.tt
new file mode 100644
index 0000000000..a8339bb79f
--- /dev/null
+++ b/lib/bundler/templates/newgem/exe/newgem.tt
@@ -0,0 +1,3 @@
+#!/usr/bin/env ruby
+
+require "<%= config[:namespaced_path] %>"
diff --git a/lib/bundler/templates/newgem/gitignore.tt b/lib/bundler/templates/newgem/gitignore.tt
index ae3fdc2989..ebff7ac53c 100644
--- a/lib/bundler/templates/newgem/gitignore.tt
+++ b/lib/bundler/templates/newgem/gitignore.tt
@@ -7,8 +7,10 @@
/pkg/
/spec/reports/
/tmp/
+<%- if config[:ext] -%>
*.bundle
*.so
*.o
*.a
mkmf.log
+<%- end -%>
diff --git a/lib/bundler/templates/newgem/lib/newgem/version.rb.tt b/lib/bundler/templates/newgem/lib/newgem/version.rb.tt
index fe9b5fc558..5874085d61 100644
--- a/lib/bundler/templates/newgem/lib/newgem/version.rb.tt
+++ b/lib/bundler/templates/newgem/lib/newgem/version.rb.tt
@@ -1,7 +1,7 @@
<%- config[:constant_array].each_with_index do |c,i| -%>
<%= ' '*i %>module <%= c %>
<%- end -%>
-<%= ' '*config[:constant_array].size %>VERSION = "0.0.1"
+<%= ' '*config[:constant_array].size %>VERSION = "0.1.0"
<%- (config[:constant_array].size-1).downto(0) do |i| -%>
<%= ' '*i %>end
<%- end -%>
diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt
index 74d253ec37..f20698bf94 100644
--- a/lib/bundler/templates/newgem/newgem.gemspec.tt
+++ b/lib/bundler/templates/newgem/newgem.gemspec.tt
@@ -8,25 +8,32 @@ Gem::Specification.new do |spec|
spec.version = <%=config[:constant_name]%>::VERSION
spec.authors = [<%=config[:author].inspect%>]
spec.email = [<%=config[:email].inspect%>]
-<% if config[:ext] -%>
- spec.extensions = ["ext/<%=config[:underscored_name]%>/extconf.rb"]
-<% end -%>
- spec.summary = %q{TODO: Write a short summary. Required.}
- spec.description = %q{TODO: Write a longer description. Optional.}
- spec.homepage = ""
+
+ spec.summary = %q{TODO: Write a short summary, because Rubygems requires one.}
+ spec.description = %q{TODO: Write a longer description or delete this line.}
+ spec.homepage = "TODO: Put your gem's website or public repo URL here."
+<%- if config[:mit] -%>
spec.license = "MIT"
+<%- end -%>
- spec.files = `git ls-files -z`.split("\x0")
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
+<%- if config[:ext] -%>
+ spec.extensions = ["ext/<%=config[:underscored_name]%>/extconf.rb"]
+<%- end -%>
+
+ if spec.respond_to?(:metadata)
+ spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com' to prevent pushes to rubygems.org, or delete to allow pushes to any server."
+ end
spec.add_development_dependency "bundler", "~> <%= Bundler::VERSION.split(".")[0..1].join(".") %>"
spec.add_development_dependency "rake", "~> 10.0"
-<% if config[:ext] -%>
+<%- if config[:ext] -%>
spec.add_development_dependency "rake-compiler"
-<% end -%>
-<% if config[:test] -%>
+<%- end -%>
+<%- if config[:test] && config[:test] != "false" -%>
spec.add_development_dependency "<%=config[:test]%>"
-<% end -%>
+<%- end -%>
end
diff --git a/lib/bundler/templates/newgem/test/test_newgem.rb.tt b/lib/bundler/templates/newgem/test/test_newgem.rb.tt
index 34cc473672..d50f7da243 100644
--- a/lib/bundler/templates/newgem/test/test_newgem.rb.tt
+++ b/lib/bundler/templates/newgem/test/test_newgem.rb.tt
@@ -1,6 +1,6 @@
require 'minitest_helper'
-class Test<%= config[:constant_name] %> < MiniTest::Unit::TestCase
+class Test<%= config[:constant_name] %> < Minitest::Test
def test_that_it_has_a_version_number
refute_nil ::<%= config[:constant_name] %>::VERSION
end
diff --git a/lib/bundler/ui/shell.rb b/lib/bundler/ui/shell.rb
index c7054e4e0a..6299c5e9d2 100644
--- a/lib/bundler/ui/shell.rb
+++ b/lib/bundler/ui/shell.rb
@@ -57,7 +57,7 @@ module Bundler
def trace(e, newline = nil)
return unless debug?
- msg = ["#{e.class}: #{e.message}", *e.backtrace].join("\n")
+ msg = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n ")}"
tell_me(msg, nil, newline)
end
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index ca77771043..4b2ee8ef86 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -2,5 +2,5 @@ module Bundler
# We're doing this because we might write tests that deal
# with other versions of bundler and we are unsure how to
# handle this better.
- VERSION = "1.7.15" unless defined?(::Bundler::VERSION)
+ VERSION = "1.8.8" unless defined?(::Bundler::VERSION)
end
diff --git a/lib/bundler/worker.rb b/lib/bundler/worker.rb
new file mode 100644
index 0000000000..4961588377
--- /dev/null
+++ b/lib/bundler/worker.rb
@@ -0,0 +1,73 @@
+require 'thread'
+
+module Bundler
+ class Worker
+ POISON = Object.new
+
+ class WrappedException < StandardError
+ attr_reader :exception
+ def initialize(exn)
+ @exception = exn
+ end
+ end
+
+ # Creates a worker pool of specified size
+ #
+ # @param size [Integer] Size of pool
+ # @param func [Proc] job to run in inside the worker pool
+ def initialize(size, func)
+ @request_queue = Queue.new
+ @response_queue = Queue.new
+ @func = func
+ @threads = size.times.map { |i| Thread.start { process_queue(i) } }
+ trap("INT") { abort_threads }
+ end
+
+ # Enqueue a request to be executed in the worker pool
+ #
+ # @param obj [String] mostly it is name of spec that should be downloaded
+ def enq(obj)
+ @request_queue.enq obj
+ end
+
+ # Retrieves results of job function being executed in worker pool
+ def deq
+ result = @response_queue.deq
+ raise result.exception if result.is_a?(WrappedException)
+ result
+ end
+
+ def stop
+ stop_threads
+ end
+
+ private
+
+ def process_queue(i)
+ loop do
+ obj = @request_queue.deq
+ break if obj.equal? POISON
+ @response_queue.enq apply_func(obj, i)
+ end
+ end
+
+ def apply_func(obj, i)
+ @func.call(obj, i)
+ rescue Exception => e
+ WrappedException.new(e)
+ end
+
+ # Stop the worker threads by sending a poison object down the request queue
+ # so as worker threads after retrieving it, shut themselves down
+ def stop_threads
+ @threads.each { @request_queue.enq POISON }
+ @threads.each { |thread| thread.join }
+ end
+
+ def abort_threads
+ @threads.each {|i| i.exit }
+ exit 1
+ end
+
+ end
+end
diff --git a/man/bundle-config.ronn b/man/bundle-config.ronn
index d158f5b02d..8bbc5140e1 100644
--- a/man/bundle-config.ronn
+++ b/man/bundle-config.ronn
@@ -70,6 +70,10 @@ The canonical form of this configuration is `"without"`. To convert the canonica
form to the environment variable form, capitalize it, and prepend `BUNDLE_`. The
environment variable form of `"without"` is `BUNDLE_WITHOUT`.
+Any periods in the configuration keys must be replaced with two underscores when
+setting it via environment variables. The configuration key `local.rack` becomes
+the environment variable `BUNDLE_LOCAL__RACK`.
+
## LIST OF AVAILABLE KEYS
The following is a list of all configuration keys and their purpose. You can
@@ -77,7 +81,7 @@ learn more about their operation in [bundle install(1)][bundle-install].
* `path` (`BUNDLE_PATH`):
The location on disk to install gems. Defaults to `$GEM_HOME` in development
- and `vendor/bundler` when `--deployment` is used
+ and `vendor/bundle` when `--deployment` is used
* `frozen` (`BUNDLE_FROZEN`):
Disallow changes to the `Gemfile`. Defaults to `true` when `--deployment`
is used.
@@ -86,6 +90,12 @@ learn more about their operation in [bundle install(1)][bundle-install].
* `bin` (`BUNDLE_BIN`):
Install executables from gems in the bundle to the specified directory.
Defaults to `false`.
+* `gemfile` (`BUNDLE_GEMFILE`):
+ The name of the file that bundler should use as the `Gemfile`. This location
+ of this file also sets the root of the project, which is used to resolve
+ relative paths in the `Gemfile`, among other things. By default, bundler
+ will search up from the current working directory until it finds a
+ `Gemfile`.
* `ssl_ca_cert` (`BUNDLE_SSL_CA_CERT`):
Path to a designated CA certificate file or folder containing multiple
certificates for trusted CAs in PEM format.
@@ -100,18 +110,6 @@ You can set them globally either via environment variables or `bundle config`,
whichever is preferable for your setup. If you use both, environment variables
will take preference over global settings.
-An additional setting is available only as an environment variable:
-
-* `BUNDLE_GEMFILE`:
- The name of the file that bundler should use as the `Gemfile`. This location
- of this file also sets the root of the project, which is used to resolve
- relative paths in the `Gemfile`, among other things. By default, bundler
- will search up from the current working directory until it finds a
- `Gemfile`.
-
-Bundler will ignore any `BUNDLE_GEMFILE` entries in local or global
-configuration files.
-
## LOCAL GIT REPOS
Bundler also allows you to work against a git repository locally
@@ -162,9 +160,13 @@ For example, to use a mirror of rubygems.org hosted at
Bundler allows you to configure credentials for any gem source, which allows
you to avoid putting secrets into your Gemfile.
- bundle config SOURCE_URL USERNAME:PASSWORD
+ bundle config SOURCE_HOSTNAME USERNAME:PASSWORD
For example, to save the credentials of user `claudette` for the gem source at
`gems.longerous.com`, you would run:
- bundle config https://gems.longerous.com/ claudette:s00pers3krit
+ bundle config gems.longerous.com claudette:s00pers3krit
+
+Or you can set the credentials as an environment variable like this:
+
+ export BUNDLE_GEMS__LONGEROUS__COM="claudette:s00pers3krit"
diff --git a/man/bundle-install.ronn b/man/bundle-install.ronn
index a4448333f8..e9706b51bd 100644
--- a/man/bundle-install.ronn
+++ b/man/bundle-install.ronn
@@ -3,128 +3,137 @@ bundle-install(1) -- Install the dependencies specified in your Gemfile
## SYNOPSIS
-`bundle install` [--gemfile=GEMFILE]
- [--path PATH] [--system]
- [--without=GROUP1[ GROUP2...]]
- [--local] [--deployment]
- [--binstubs[=DIRECTORY]]
- [--standalone[=GROUP1[ GROUP2...]]]
- [--trust-policy=POLICY]
- [--jobs=SIZE]
- [--retry=TRIES]
- [--no-cache]
- [--quiet]
+`bundle install` [--binstubs[=DIRECTORY]]
[--clean]
[--full-index]
+ [--gemfile=GEMFILE]
+ [--jobs=NUMBER]
+ [--local] [--deployment]
+ [--no-cache]
[--no-prune]
+ [--path PATH] [--system]
+ [--quiet]
+ [--retry=NUMBER]
[--shebang]
+ [--standalone[=GROUP[ GROUP...]]]
+ [--trust-policy=POLICY]
+ [--without=GROUP[ GROUP...]]
## DESCRIPTION
Install the gems specified in your Gemfile(5). If this is the first
time you run bundle install (and a `Gemfile.lock` does not exist),
-bundler will fetch all remote sources, resolve dependencies and
+Bundler will fetch all remote sources, resolve dependencies and
install all needed gems.
If a `Gemfile.lock` does exist, and you have not updated your Gemfile(5),
-bundler will fetch all remote sources, but use the dependencies
+Bundler will fetch all remote sources, but use the dependencies
specified in the `Gemfile.lock` instead of resolving dependencies.
If a `Gemfile.lock` does exist, and you have updated your Gemfile(5),
-bundler will use the dependencies in the `Gemfile.lock` for all gems
+Bundler will use the dependencies in the `Gemfile.lock` for all gems
that you did not update, but will re-resolve the dependencies of
gems that you did update. You can find more information about this
update process below under [CONSERVATIVE UPDATING][].
## OPTIONS
-* `--gemfile=<gemfile>`:
- The location of the Gemfile(5) that bundler should use. This defaults
- to a gemfile in the current working directory. In general, bundler
- will assume that the location of the Gemfile(5) is also the project
- root, and will look for the `Gemfile.lock` and `vendor/cache` relative
- to it.
+* `--binstubs[=<directory>]`:
+ Creates a directory (defaults to `~/bin`) and place any executables from the
+ gem there. These executables run in Bundler's context. If used, you might add
+ this directory to your environment's `PATH` variable. For instance, if the
+ `rails` gem comes with a `rails` executable, this flag will create a
+ `bin/rails` executable that ensures that all referred dependencies will be
+ resolved using the bundled gems.
-* `--path=<path>`:
- The location to install the gems in the bundle to. This defaults to
- Rubygems' gem home, which is also the default location where `gem
- install` installs gems. This means that, by default, gems installed
- without a `--path` setting will show up in `gem list`. This setting is
- a [remembered option][REMEMBERED OPTIONS].
+* `--clean`:
+ On finishing the installation Bundler is going to remove any gems not present
+ in the current Gemfile(5). Don't worry, gems currently in use will not be
+ removed.
-* `--system`:
- Installs the gems in the bundle to the system location. This
- overrides any previous [remembered][REMEMBERED OPTIONS] use of
- `--path`.
+* `--full-index`:
+ Bundler will not call Rubygems' API endpoint (default) but download and cache
+ a (currently big) index file of all gems. Performance can be improved for
+ large bundles that seldomly change by enabling this option.
-* `--without=<list>`:
- A space-separated list of groups to skip installing. This is a
- [remembered option][REMEMBERED OPTIONS].
+* `--gemfile=<gemfile>`:
+ The location of the Gemfile(5) which Bundler should use. This defaults
+ to a Gemfile(5) in the current working directory. In general, Bundler
+ will assume that the location of the Gemfile(5) is also the project's
+ root and will try to find `Gemfile.lock` and `vendor/cache` relative
+ to this location.
+
+* `--jobs=[<number>]`:
+ Install gems by starting <number> of workers parallely.
* `--local`:
- Do not attempt to connect to `rubygems.org`, instead using just
- the gems already present in Rubygems' cache or in `vendor/cache`.
- Note that if a more appropriate platform-specific gem exists on
- `rubygems.org`, it will not be found.
+ Do not attempt to connect to `rubygems.org`. Instead, Bundler will use the
+ gems already present in Rubygems' cache or in `vendor/cache`. Note that if a
+ appropriate platform-specific gem exists on `rubygems.org` it will not be
+ found.
* `--deployment`:
- Switches bundler's defaults into [deployment mode][DEPLOYMENT MODE].
- Do not use this flag on development machines.
+ In [deployment mode][DEPLOYMENT MODE], Bundler will 'roll-out' the bundle for
+ `production` use. Please check carefully if you want to have this option
+ enabled in `development` or `test` environments.
-* `--binstubs[=<directory>]`:
- Create a directory (defaults to `bin`) containing an executable
- that runs in the context of the bundle. For instance, if the
- `rails` gem comes with a `rails` executable, this flag will create
- a `bin/rails` executable that ensures that all dependencies used
- come from the bundled gems.
+* `--system`:
+ Installs the gems specified in the bundle to the system's Rubygems location.
+ This overrides any previous [remembered][REMEMBERED OPTIONS] use of `--path`.
-* `--shebang ruby-install-name`:
- Uses the ruby executable (usually `ruby`) provided to execute the scripts created
- with --binstubs. For instance, if you use --binstubs with `--shebang jruby`,
- all executables will be created to use jruby instead.
+* `--no-cache`:
+ Do not update the cache in `vendor/cache` with the newly bundled gems. This
+ does not remove any gems in the cache but keeps the newly bundled gems from
+ being cached during the install.
-* `--standalone[=<list>]`:
- Make a bundle that can work without Ruby Gems or Bundler at runtime.
- It takes a space separated list of groups to install. It creates a
- `bundle` directory and installs the bundle there. It also generates
- a `bundle/bundler/setup.rb` file to replace Bundler's own setup.
+* `--no-prune`:
+ Don't remove stale gems from the cache when the installation finishes.
-* `--trust-policy=[<policy>]`:
- Apply the Rubygems security policy named <policy>, where policy is one of
- HighSecurity, MediumSecurity, LowSecurity, AlmostNoSecurity, or NoSecurity.
- For more detail, see the Rubygems signing documentation, linked below in
- [SEE ALSO][].
+* `--path=<path>`:
+ The location to install the specified gems to. This defaults to Rubygems'
+ setting. Bundler shares this location with Rubygems, `gem install ...` will
+ have gem installed there, too. Therefore, gems installed without a
+ `--path ...` setting will show up by calling `gem list`. Accodingly, gems
+ installed to other locations will not get listed. This setting is a
+ [remembered option][REMEMBERED OPTIONS].
-* `--jobs=[<size>]`:
- Install gems parallely by starting <size> number of parallel workers.
+* `--quiet`:
+ Do not print progress information to the standard output. Instead, Bundler
+ will exit using a status code (`$?`).
-* `--retry[<tries]`:
- Retries failed network or git requests <tries> times.
+* `--retry=[<number>]`:
+ Retry failed network or git requests for <number> times.
-* `--no-cache`:
- Do not update the cache in `vendor/cache` with the newly bundled gems. This
- does not remove any existing cached gems, only stops the newly bundled gems
- from being cached during the install.
+* `--shebang=<ruby-executable>`:
+ Uses the specified ruby executable (usually `ruby`) to execute the scripts
+ created with `--binstubs`. In addition, if you use `--binstubs` together with
+ `--shebang jruby` these executables will be changed to execute `jruby`
+ instead.
-* `--quiet`:
- Do not print progress information to stdout. Instead, communicate the
- success of the install operation via exit status code.
+* `--standalone[=<list>]`:
+ Makes a bundle that can work without depending on Rubygems or Bundler at
+ runtime. A space separated list of groups to install has to be specified.
+ Bundler creates a directory named `bundle` and installs the bundle there. It
+ also generates a `bundle/bundler/setup.rb` file to replace Bundler's own setup
+ in the manner required.
-* `--clean`:
- Run bundle clean automatically after install.
+* `--trust-policy=[<policy>]`:
+ Apply the Rubygems security policy <policy>, where policy is one of
+ `HighSecurity`, `MediumSecurity`, `LowSecurity`, `AlmostNoSecurity`, or
+ `NoSecurity`. For more details, please see the Rubygems signing documentation
+ linked below in [SEE ALSO][].
-* `--full-index`:
- Use the rubygems modern index instead of the API endpoint.
+* `--without=<list>`:
+ A space-separated list of groups referencing gems to skip during installation.
+ This is a [remembered option][REMEMBERED OPTIONS].
-* `--no-prune`:
- Don't remove stale gems from the cache.
## DEPLOYMENT MODE
Bundler's defaults are optimized for development. To switch to
defaults optimized for deployment, use the `--deployment` flag.
Do not activate deployment mode on development machines, as it
-will cause in an error when the Gemfile is modified.
+will cause an error when the Gemfile(5) is modified.
1. A `Gemfile.lock` is required.
@@ -161,10 +170,10 @@ will cause in an error when the Gemfile is modified.
## SUDO USAGE
-By default, bundler installs gems to the same location as `gem install`.
+By default, Bundler installs gems to the same location as `gem install`.
In some cases, that location may not be writable by your Unix user. In
-that case, bundler will stage everything in a temporary directory,
+that case, Bundler will stage everything in a temporary directory,
then ask you for your `sudo` password in order to copy the gems into
their system location.
@@ -185,7 +194,7 @@ the current user. Therefore, git gems are downloaded and installed
into `~/.bundle` rather than $GEM_HOME or $BUNDLE_PATH.
As a result, you should run `bundle install` as the current user,
-and bundler will ask for your password if it is needed to put the
+and Bundler will ask for your password if it is needed to put the
gems into their final location.
## INSTALLING GROUPS
@@ -193,7 +202,7 @@ gems into their final location.
By default, `bundle install` will install all gems in all groups
in your Gemfile(5), except those declared for a different platform.
-However, you can explicitly tell bundler to skip installing
+However, you can explicitly tell Bundler to skip installing
certain groups with the `--without` option. This option takes
a space-separated list of groups.
@@ -214,21 +223,21 @@ third-party code being used in different environments.`
For a simple illustration, consider the following Gemfile(5):
- source "https://rubygems.org"
+ source 'https://rubygems.org'
- gem "sinatra"
+ gem 'sinatra'
group :production do
- gem "rack-perftools-profiler"
+ gem 'rack-perftools-profiler'
end
-In this case, `sinatra` depends on any version of Rack (`>= 1.0`, while
+In this case, `sinatra` depends on any version of Rack (`>= 1.0`), while
`rack-perftools-profiler` depends on 1.x (`~> 1.0`).
When you run `bundle install --without production` in development, we
look at the dependencies of `rack-perftools-profiler` as well. That way,
you do not spend all your time developing against Rack 2.0, using new
-APIs unavailable in Rack 1.x, only to have bundler switch to Rack 1.2
+APIs unavailable in Rack 1.x, only to have Bundler switch to Rack 1.2
when the `production` group _is_ used.
This should not cause any problems in practice, because we do not
@@ -310,10 +319,10 @@ same versions of all dependencies as it used before the update.
Let's take a look at an example. Here's your original Gemfile(5):
- source "https://rubygems.org"
+ source 'https://rubygems.org'
- gem "actionpack", "2.3.8"
- gem "activemerchant"
+ gem 'actionpack', '2.3.8'
+ gem 'activemerchant'
In this case, both `actionpack` and `activemerchant` depend on
`activesupport`. The `actionpack` gem depends on `activesupport 2.3.8`
@@ -326,10 +335,10 @@ gems in your Gemfile(5).
Next, you modify your Gemfile(5) to:
- source "https://rubygems.org"
+ source 'https://rubygems.org'
- gem "actionpack", "3.0.0.rc"
- gem "activemerchant"
+ gem 'actionpack', '3.0.0.rc'
+ gem 'activemerchant'
The `actionpack 3.0.0.rc` gem has a number of new dependencies,
and updates the `activesupport` dependency to `= 3.0.0.rc` and
@@ -351,7 +360,7 @@ you would not expect it to suddenly stop working after updating
dependency of actionpack requires updating one of its dependencies.
Even though `activemerchant` declares a very loose dependency
-that theoretically matches `activesupport 3.0.0.rc`, bundler treats
+that theoretically matches `activesupport 3.0.0.rc`, Bundler treats
gems in your Gemfile(5) that have not changed as an atomic unit
together with their dependencies. In this case, the `activemerchant`
dependency is treated as `activemerchant 1.7.1 + activesupport 2.3.8`,
diff --git a/man/bundle-package.ronn b/man/bundle-package.ronn
index 610f820487..8a6b439cd5 100644
--- a/man/bundle-package.ronn
+++ b/man/bundle-package.ronn
@@ -17,6 +17,13 @@ Since Bundler 1.2, the `bundle package` command can also package `:git` and
`:path` dependencies besides .gem files. This needs to be explicitly enabled
via the `--all` option. Once used, the `--all` option will be remembered.
+## SUPPORT FOR MULTIPLE PLATFORMS
+
+When using gems that have different packages for different platforms, Bundler
+1.8 and newer support caching of gems for other platforms in `vendor/cache`.
+This needs to be enabled via the `--all-platforms` option. This setting will be
+remembered in your local bundler configuration.
+
## REMOTE FETCHING
By default, if you simply run [bundle install(1)][bundle-install] after running
diff --git a/man/bundle-update.ronn b/man/bundle-update.ronn
index 3ac60c5715..b9900e3b50 100644
--- a/man/bundle-update.ronn
+++ b/man/bundle-update.ronn
@@ -3,7 +3,7 @@ bundle-update(1) -- Update your gems to the latest available versions
## SYNOPSIS
-`bundle update` <*gems> [--source=NAME] [--local]
+`bundle update` <*gems> [--group=NAME] [--source=NAME] [--local]
## DESCRIPTION
@@ -17,6 +17,12 @@ gem.
## OPTIONS
+* `--group=<name>`:
+ Only update the gems in the specified group. For instance, you can update all gems
+ in the development group with `bundle update --group development`. You can also
+ call `bundle update rails --group test` to update the rails gem and all gems in
+ the test group, for example.
+
* `--source=<name>`:
The name of a `:git` or `:path` source used in the Gemfile(5). For
instance, with a `:git` source of `http://github.com/rails/rails.git`,
@@ -41,37 +47,40 @@ Consider the following Gemfile(5):
When you run [bundle install(1)][bundle-install] the first time, bundler will resolve
all of the dependencies, all the way down, and install what you need:
- Fetching source index for https://rubygems.org/
- Installing rake (10.0.2)
- Installing abstract (1.0.0)
- Installing activesupport (3.0.0.rc)
- Installing builder (2.1.2)
- Installing i18n (0.4.1)
- Installing activemodel (3.0.0.rc)
- Installing erubis (2.6.6)
- Installing rack (1.2.1)
- Installing rack-mount (0.6.9)
- Installing rack-test (0.5.4)
- Installing tzinfo (0.3.22)
- Installing actionpack (3.0.0.rc)
- Installing mime-types (1.16)
- Installing polyglot (0.3.1)
- Installing treetop (1.4.8)
- Installing mail (2.2.5)
- Installing actionmailer (3.0.0.rc)
- Installing arel (0.4.0)
- Installing activerecord (3.0.0.rc)
- Installing activeresource (3.0.0.rc)
- Installing bundler (1.0.0.rc.3)
- Installing nokogiri (1.4.3.1) with native extensions
- Installing thor (0.14.0)
- Installing railties (3.0.0.rc)
- Installing rails (3.0.0.rc)
-
- Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
+ Fetching gem metadata from https://rubygems.org/.........
+ Resolving dependencies...
+ Installing builder 2.1.2
+ Installing abstract 1.0.0
+ Installing rack 1.2.8
+ Using bundler 1.7.6
+ Installing rake 10.4.0
+ Installing polyglot 0.3.5
+ Installing mime-types 1.25.1
+ Installing i18n 0.4.2
+ Installing mini_portile 0.6.1
+ Installing tzinfo 0.3.42
+ Installing rack-mount 0.6.14
+ Installing rack-test 0.5.7
+ Installing treetop 1.4.15
+ Installing thor 0.14.6
+ Installing activesupport 3.0.0.rc
+ Installing erubis 2.6.6
+ Installing activemodel 3.0.0.rc
+ Installing arel 0.4.0
+ Installing mail 2.2.20
+ Installing activeresource 3.0.0.rc
+ Installing actionpack 3.0.0.rc
+ Installing activerecord 3.0.0.rc
+ Installing actionmailer 3.0.0.rc
+ Installing railties 3.0.0.rc
+ Installing rails 3.0.0.rc
+ Installing nokogiri 1.6.5
+
+ Bundle complete! 2 Gemfile dependencies, 26 gems total.
+ Use `bundle show [gemname]` to see where a bundled gem is installed.
As you can see, even though you have just two gems in the Gemfile(5), your application
-actually needs 25 different gems in order to run. Bundler remembers the exact versions
+actually needs 26 different gems in order to run. Bundler remembers the exact versions
it installed in `Gemfile.lock`. The next time you run [bundle install(1)][bundle-install], bundler skips
the dependency resolution and installs the same gems as it installed last time.
diff --git a/man/bundle.ronn b/man/bundle.ronn
index 1167b0b5ec..7b69c6735c 100644
--- a/man/bundle.ronn
+++ b/man/bundle.ronn
@@ -82,6 +82,12 @@ We divide `bundle` subcommands into primary commands and utilities.
* `bundle clean(1)`:
Cleans up unused gems in your bundler directory
+## PLUGINS
+
+When running a command that isn't listed in PRIMARY COMMANDS or UTILITIES,
+Bundler will try to find an executable on your path named `bundler-<command>`
+and execute it, passing down any extra arguments to it.
+
## OBSOLETE
These commands are obsolete and should no longer be used
diff --git a/man/gemfile.5.ronn b/man/gemfile.5.ronn
index 88d6f0ffa7..876c927380 100644
--- a/man/gemfile.5.ronn
+++ b/man/gemfile.5.ronn
@@ -40,7 +40,7 @@ the username and password for any sources that need it. The command must be run
once on each computer that will install the Gemfile, but this keeps the
credentials from being stored in plain text in version control.
- bundle config https://gems.example.com/ user:password
+ bundle config gems.example.com user:password
For some sources, like a company Gemfury account, it may be easier to simply
include the credentials in the Gemfile as part of the source URL.
@@ -254,16 +254,26 @@ gem warning described above in
### GIT (:git)
If necessary, you can specify that a gem is located at a particular
-git repository. The repository can be public (`http://github.com/rails/rails.git`)
-or private (`git@github.com:rails/rails.git`). If the repository is private,
-the user that you use to run `bundle install` `MUST` have the appropriate
-keys available in their `$HOME/.ssh`.
+git repository using the `:git` parameter. The repository can be accessed via
+several protocols:
+
+ * `HTTP(S)`:
+ gem "rails", :git => "https://github.com/rails/rails.git"
+ * `SSH`:
+ gem "rails", :git => "git@github.com:rails/rails.git"
+ * `git`:
+ gem "rails", :git => "git://github.com/rails/rails.git"
-Git repositories are specified using the `:git` parameter. The `group`,
-`platforms`, and `require` options are available and behave exactly the same
-as they would for a normal gem.
+If using SSH, the user that you use to run `bundle install` `MUST` have the
+appropriate keys available in their `$HOME/.ssh`.
- gem "rails", :git => "git://github.com/rails/rails.git"
+`NOTE`: `http://` and `git://` URLs should be avoided if at all possible. These
+protocols are unauthenticated, so a man-in-the-middle attacker can deliver
+malicious code and compromise your system. HTTPS and SSH are strongly
+preferred.
+
+The `group`, `platforms`, and `require` options are available and behave
+exactly the same as they would for a normal gem.
A git repository `SHOULD` have at least one file, at the root of the
directory containing the gem, with the extension `.gemspec`. This file
@@ -280,7 +290,7 @@ to, a version specifier, if provided, means that the git repository is
only valid if the `.gemspec` specifies a version matching the version
specifier. If not, bundler will print a warning.
- gem "rails", "2.3.8", :git => "git://github.com/rails/rails.git"
+ gem "rails", "2.3.8", :git => "https://github.com/rails/rails.git"
# bundle install will fail, because the .gemspec in the rails
# repository's master branch specifies version 3.0.0
@@ -315,8 +325,25 @@ and then installs the resulting gem. The `gem build` command,
which comes standard with Rubygems, evaluates the `.gemspec` in
the context of the directory in which it is located.
+### GIT SOURCE (:git_source)
+
+A custom git source can be defined via the `git_source` method. Provide the source's name
+as an argument, and a block which receives a single argument and interpolates it into a
+string to return the full repo address:
+
+ git_source(:stash){ |repo_name| "https://stash.corp.acme.pl/#{repo_name}.git" }
+ gem 'rails', :stash => 'forks/rails'
+
+In addition, if you wish to choose a specific branch:
+
+ gem "rails", :stash => "forks/rails", :branch => "branch_name"
+
### GITHUB (:github)
+`NOTE`: This shorthand should be avoided until Bundler 2.0, since it
+currently expands to an insecure `git://` URL. This allows a
+man-in-the-middle attacker to compromise your system.
+
If the git repository you want to use is hosted on GitHub and is public, you can use the
:github shorthand to specify just the github username and repository name (without the
trailing ".git"), separated by a slash. If both the username and repository name are the
@@ -329,9 +356,36 @@ Are both equivalent to
gem "rails", :git => "git://github.com/rails/rails.git"
-In addition, if you wish to choose a specific branch:
+Since the `github` method is a specialization of `git_source`, it accepts a `:branch` named argument.
+
+### GIST (:gist)
+
+If the git repository you want to use is hosted as a Github Gist and is public, you can use
+the :gist shorthand to specify just the gist identifier (without the trailing ".git").
+
+ gem "the_hatch", :gist => "4815162342"
- gem "rails", :github => "rails/rails", :branch => "branch_name"
+Is equivalent to:
+
+ gem "the_hatch", :git => "https://gist.github.com/4815162342.git"
+
+Since the `gist` method is a specialization of `git_source`, it accepts a `:branch` named argument.
+
+### BITBUCKET (:bitbucket)
+
+If the git repository you want to use is hosted on Bitbucket and is public, you can use the
+:bitbucket shorthand to specify just the bitbucket username and repository name (without the
+trailing ".git"), separated by a slash. If both the username and repository name are the
+same, you can omit one.
+
+ gem "rails", :bitbucket => "rails/rails"
+ gem "rails", :bitbucket => "rails"
+
+Are both equivalent to
+
+ gem "rails", :git => "https://rails@bitbucket.org/rails/rails.git"
+
+Since the `bitbucket` method is a specialization of `git_source`, it accepts a `:branch` named argument.
### PATH (:path)
@@ -349,6 +403,13 @@ gems specified as paths.
gem "rails", :path => "vendor/rails"
+If you would like to use multiple local gems directly from the filesystem, you can set a global `path` option to the path containing the gem's files. This will automatically load gemspec files from subdirectories.
+
+ path 'components' do
+ gem 'admin_ui'
+ gem 'public_ui'
+ end
+
## BLOCK FORM OF SOURCE, GIT, PATH, GROUP and PLATFORMS
The `:source`, `:git`, `:path`, `:group`, and `:platforms` options may be
@@ -359,7 +420,7 @@ applied to a group of gems by using block form.
gem "another_internal_gem"
end
- git "git://github.com/rails/rails.git" do
+ git "https://github.com/rails/rails.git" do
gem "activesupport"
gem "actionpack"
end
diff --git a/spec/bundler/anonymizable_uri_spec.rb b/spec/bundler/anonymizable_uri_spec.rb
index e5d9faeb84..c444ea04d7 100644
--- a/spec/bundler/anonymizable_uri_spec.rb
+++ b/spec/bundler/anonymizable_uri_spec.rb
@@ -2,14 +2,22 @@ require 'spec_helper'
require 'bundler/anonymizable_uri'
describe Bundler::AnonymizableURI do
- let(:anonymizable_uri) { Bundler::AnonymizableURI.new(original_uri) }
+ def auri(uri, auth = nil)
+ Bundler::AnonymizableURI.new(uri, auth)
+ end
describe "#without_credentials" do
context "when the original URI has no credentials" do
let(:original_uri) { URI('https://rubygems.org') }
it "returns the original URI" do
- expect(anonymizable_uri.without_credentials).to eq(original_uri)
+ expect(auri(original_uri).without_credentials).to eq(original_uri)
+ end
+
+ it "applies given credentials" do
+ with_auth = original_uri.dup
+ with_auth.userinfo = "user:pass"
+ expect(auri(original_uri, "user:pass").original_uri).to eq(with_auth)
end
end
@@ -17,7 +25,11 @@ describe Bundler::AnonymizableURI do
let(:original_uri) { URI("https://username:password@gems.example.com") }
it "returns the URI without username and password" do
- expect(anonymizable_uri.without_credentials).to eq(URI("https://gems.example.com"))
+ expect(auri(original_uri).without_credentials).to eq(URI("https://gems.example.com"))
+ end
+
+ it "does not apply given credentials" do
+ expect(auri(original_uri, "other:stuff").original_uri).to eq(original_uri)
end
end
@@ -25,7 +37,7 @@ describe Bundler::AnonymizableURI do
let(:original_uri) { URI("https://SeCrEt-ToKeN@gem.fury.io/me/") }
it "returns the URI without username and password" do
- expect(anonymizable_uri.without_credentials).to eq(URI("https://gem.fury.io/me/"))
+ expect(auri(original_uri).without_credentials).to eq(URI("https://gem.fury.io/me/"))
end
end
end
diff --git a/spec/bundler/bundler_spec.rb b/spec/bundler/bundler_spec.rb
index 013dc29271..fa226002cc 100644
--- a/spec/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler_spec.rb
@@ -44,14 +44,13 @@ describe Bundler do
end
end
- context "with correct YAML file" do
+ context "with correct YAML file", :if => defined?(Encoding) do
it "can load a gemspec with unicode characters with default ruby encoding" do
# spec_helper forces the external encoding to UTF-8 but that's not the
- # ruby default.
- if defined?(Encoding)
- encoding = Encoding.default_external
- Encoding.default_external = "ASCII"
- end
+ # default until Ruby 2.0
+ verbose, $VERBOSE = $VERBOSE, false
+ encoding, Encoding.default_external = Encoding.default_external, "ASCII"
+ $VERBOSE = verbose
File.open(app_gemspec_path, "wb") do |file|
file.puts <<-GEMSPEC.gsub(/^\s+/, '')
@@ -64,7 +63,9 @@ describe Bundler do
expect(subject.author).to eq("André the Giant")
- Encoding.default_external = encoding if defined?(Encoding)
+ verbose, $VERBOSE = $VERBOSE, false
+ Encoding.default_external = encoding
+ $VERBOSE = verbose
end
end
diff --git a/spec/bundler/cli_spec.rb b/spec/bundler/cli_spec.rb
index ef4ec79656..7917726efe 100644
--- a/spec/bundler/cli_spec.rb
+++ b/spec/bundler/cli_spec.rb
@@ -5,12 +5,25 @@ describe "bundle executable" do
let(:source_uri) { "http://localgemserver.test" }
it "returns non-zero exit status when passed unrecognized options" do
- bundle '--invalid_argument', :exitstatus => true
- expect(exitstatus).to_not be_zero
+ bundle '--invalid_argument'
+ expect(exitstatus).to_not be_zero if exitstatus
end
it "returns non-zero exit status when passed unrecognized task" do
- bundle 'unrecognized-tast', :exitstatus => true
- expect(exitstatus).to_not be_zero
+ bundle 'unrecognized-tast'
+ expect(exitstatus).to_not be_zero if exitstatus
+ end
+
+ it "looks for a binary and executes it if it's named bundler-<task>" do
+ File.open(tmp('bundler-testtasks'), 'w', 0755) do |f|
+ f.puts "#!/usr/bin/env ruby\nputs 'Hello, world'\n"
+ end
+
+ with_path_as(tmp) do
+ bundle 'testtasks'
+ end
+
+ expect(exitstatus).to be_zero if exitstatus
+ expect(out).to eq('Hello, world')
end
end
diff --git a/spec/bundler/dsl_spec.rb b/spec/bundler/dsl_spec.rb
index 03db5d2033..e3ff2306e9 100644
--- a/spec/bundler/dsl_spec.rb
+++ b/spec/bundler/dsl_spec.rb
@@ -6,7 +6,7 @@ describe Bundler::Dsl do
allow(Bundler::Source::Rubygems).to receive(:new){ @rubygems }
end
- describe "#register_host" do
+ describe "#git_source" do
it "registers custom hosts" do
subject.git_source(:example){ |repo_name| "git@git.example.com:#{repo_name}.git" }
subject.git_source(:foobar){ |repo_name| "git@foobar.com:#{repo_name}.git" }
@@ -49,6 +49,18 @@ describe Bundler::Dsl do
github_uri = "git://github.com/rails/rails.git"
expect(subject.dependencies.first.source.uri).to eq(github_uri)
end
+
+ it "converts :bitbucket to :git" do
+ subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails")
+ bitbucket_uri = "https://mcorp@bitbucket.org/mcorp/flatlab-rails.git"
+ expect(subject.dependencies.first.source.uri).to eq(bitbucket_uri)
+ end
+
+ it "converts 'mcorp' to 'mcorp/mcorp'" do
+ subject.gem("not-really-a-gem", :bitbucket => "mcorp")
+ bitbucket_uri = "https://mcorp@bitbucket.org/mcorp/mcorp.git"
+ expect(subject.dependencies.first.source.uri).to eq(bitbucket_uri)
+ end
end
end
@@ -72,6 +84,95 @@ describe Bundler::Dsl do
end
end
+ describe "#gem" do
+ [:ruby, :ruby_18, :ruby_19, :ruby_20, :ruby_21, :ruby_22, :mri, :mri_18, :mri_19,
+ :mri_20, :mri_21, :jruby, :rbx].each do |platform|
+ it "allows #{platform} as a valid platform" do
+ subject.gem("foo", :platform => platform)
+ end
+ end
+
+ it "rejects invalid platforms" do
+ expect { subject.gem("foo", :platform => :bogus) }.
+ to raise_error(Bundler::GemfileError, /is not a valid platform/)
+ end
+
+ it "rejects with a leading space in the name" do
+ expect { subject.gem(" foo") }.
+ to raise_error(Bundler::GemfileError, /' foo' is not a valid gem name because it contains whitespace/)
+ end
+
+ it "rejects with a trailing space in the name" do
+ expect { subject.gem("foo ") }.
+ to raise_error(Bundler::GemfileError, /'foo ' is not a valid gem name because it contains whitespace/)
+ end
+
+ it "rejects with a space in the gem name" do
+ expect { subject.gem("fo o") }.
+ to raise_error(Bundler::GemfileError, /'fo o' is not a valid gem name because it contains whitespace/)
+ end
+
+ it "rejects with a tab in the gem name" do
+ expect { subject.gem("fo\to") }.
+ to raise_error(Bundler::GemfileError, /'fo\to' is not a valid gem name because it contains whitespace/)
+ end
+
+ it "rejects with a newline in the gem name" do
+ expect { subject.gem("fo\no") }.
+ to raise_error(Bundler::GemfileError, /'fo\no' is not a valid gem name because it contains whitespace/)
+ end
+
+ it "rejects with a carriage return in the gem name" do
+ expect { subject.gem("fo\ro") }.
+ to raise_error(Bundler::GemfileError, /'fo\ro' is not a valid gem name because it contains whitespace/)
+ end
+
+ it "rejects with a form feed in the gem name" do
+ expect { subject.gem("fo\fo") }.
+ to raise_error(Bundler::GemfileError, /'fo\fo' is not a valid gem name because it contains whitespace/)
+ end
+
+ it "rejects symbols as gem name" do
+ expect { subject.gem(:foo) }.
+ to raise_error(Bundler::GemfileError, /You need to specify gem names as Strings. Use 'gem "foo"' instead/)
+ end
+ end
+
+ context "can bundle groups of gems with" do
+ # git "https://github.com/rails/rails.git" do
+ # gem "railties"
+ # gem "action_pack"
+ # gem "active_model"
+ # end
+ describe "#git" do
+ it "from a single repo" do
+ rails_gems = ["railties", "action_pack", "active_model"]
+ subject.git "https://github.com/rails/rails.git" do
+ rails_gems.each { |rails_gem| subject.send :gem, rails_gem }
+ end
+ expect(subject.dependencies.map(&:name)).to match_array rails_gems
+ end
+ end
+
+ # github 'spree' do
+ # gem 'spree_core'
+ # gem 'spree_api'
+ # gem 'spree_backend'
+ # end
+ describe "#github" do
+ it "from github" do
+ spree_gems = ["spree_core", "spree_api", "spree_backend"]
+ subject.github "spree" do
+ spree_gems.each { |spree_gem| subject.send :gem, spree_gem }
+ end
+
+ subject.dependencies.each do |d|
+ expect(d.source.uri).to eq("git://github.com/spree/spree.git")
+ end
+ end
+ end
+ end
+
describe "syntax errors" do
it "will raise a Bundler::GemfileError" do
gemfile "gem 'foo', :path => /unquoted/string/syntax/error"
diff --git a/spec/bundler/fetcher_spec.rb b/spec/bundler/fetcher_spec.rb
new file mode 100644
index 0000000000..4640f63519
--- /dev/null
+++ b/spec/bundler/fetcher_spec.rb
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe Bundler::Fetcher do
+ before do
+ allow(Bundler).to receive(:root){ Pathname.new("root") }
+ end
+
+ describe "#user_agent" do
+ it "builds user_agent with current ruby version and Bundler settings" do
+ allow(Bundler.settings).to receive(:all).and_return(["foo", "bar"])
+ expect(described_class.user_agent).to match(/bundler\/(\d.)/)
+ expect(described_class.user_agent).to match(/rubygems\/(\d.)/)
+ expect(described_class.user_agent).to match(/ruby\/(\d.)/)
+ expect(described_class.user_agent).to match(/options\/foo,bar/)
+ end
+ end
+end
diff --git a/spec/bundler/gem_helper_spec.rb b/spec/bundler/gem_helper_spec.rb
index d3df2dc768..2b0f3d97aa 100644
--- a/spec/bundler/gem_helper_spec.rb
+++ b/spec/bundler/gem_helper_spec.rb
@@ -3,7 +3,7 @@ require 'rake'
require 'bundler/gem_helper'
describe Bundler::GemHelper do
- let(:app_name) { "test" }
+ let(:app_name) { "lorem__ipsum" }
let(:app_path) { bundled_app app_name }
let(:app_gemspec_path) { app_path.join("#{app_name}.gemspec") }
@@ -40,10 +40,10 @@ describe Bundler::GemHelper do
it "handles namespaces and converts them to CamelCase" do
bundle "gem #{app_name}-foo_bar"
- app_path = bundled_app "#{app_name}-foo_bar"
+ underscore_path = bundled_app "#{app_name}-foo_bar"
- lib = app_path.join("lib/#{app_name}/foo_bar.rb").read
- expect(lib).to include("module #{app_name.capitalize}")
+ lib = underscore_path.join("lib/#{app_name}/foo_bar.rb").read
+ expect(lib).to include("module LoremIpsum")
expect(lib).to include("module FooBar")
end
end
@@ -59,13 +59,14 @@ describe Bundler::GemHelper do
end
subject! { Bundler::GemHelper.new(app_path) }
- let(:app_version) { "0.0.1" }
+ let(:app_version) { "0.1.0" }
let(:app_gem_dir) { app_path.join("pkg") }
let(:app_gem_path) { app_gem_dir.join("#{app_name}-#{app_version}.gem") }
let(:app_gemspec_content) { File.read(app_gemspec_path) }
before(:each) do
content = app_gemspec_content.gsub("TODO: ", "")
+ content.sub!(/homepage\s+= ".*"/, 'homepage = ""')
File.open(app_gemspec_path, "w") { |file| file << content }
end
@@ -85,7 +86,8 @@ describe Bundler::GemHelper do
end
context "defines Rake tasks" do
- let(:task_names) { %w[build install release] }
+ let(:task_names) { %w[build install release
+ release:guard_clean release:source_control_push release:rubygem_push] }
context "before installation" do
it "raises an error with appropriate message" do
@@ -157,7 +159,18 @@ describe Bundler::GemHelper do
end
end
- describe "#release_gem" do
+ describe "rake release" do
+ let!(:rake_application) { Rake.application }
+
+ before(:each) do
+ Rake.application = Rake::Application.new
+ subject.install
+ end
+
+ after(:each) do
+ Rake.application = rake_application
+ end
+
before do
Dir.chdir(app_path) do
`git init`
@@ -169,13 +182,13 @@ describe Bundler::GemHelper do
context "fails" do
it "when there are unstaged files" do
- expect { subject.release_gem }.
+ expect { Rake.application["release"].invoke }.
to raise_error("There are files that need to be committed first.")
end
it "when there are uncommitted files" do
Dir.chdir(app_path) { `git add .` }
- expect { subject.release_gem }.
+ expect { Rake.application["release"].invoke }.
to raise_error("There are files that need to be committed first.")
end
@@ -185,7 +198,7 @@ describe Bundler::GemHelper do
allow(Bundler.ui).to receive(:error)
Dir.chdir(app_path) { `git commit -a -m "initial commit"` }
- expect { subject.release_gem }.to raise_error
+ expect { Rake.application["release"].invoke }.to raise_error
end
end
@@ -206,7 +219,7 @@ describe Bundler::GemHelper do
Dir.chdir(app_path) { sys_exec("git push -u origin master", true) }
- subject.release_gem
+ Rake.application["release"].invoke
end
it "even if tag already exists" do
@@ -218,7 +231,7 @@ describe Bundler::GemHelper do
`git tag -a -m \"Version #{app_version}\" v#{app_version}`
end
- subject.release_gem
+ Rake.application["release"].invoke
end
end
end
diff --git a/spec/bundler/settings_spec.rb b/spec/bundler/settings_spec.rb
index 44f40ce3d0..56ee87da6e 100644
--- a/spec/bundler/settings_spec.rb
+++ b/spec/bundler/settings_spec.rb
@@ -10,4 +10,44 @@ describe Bundler::Settings do
end
end
end
+
+ describe "URI normalization" do
+ let(:settings) { described_class.new(bundled_app) }
+
+ it "normalizes HTTP URIs in credentials configuration" do
+ settings["http://gemserver.example.org"] = "username:password"
+ expect(settings.all).to include("http://gemserver.example.org/")
+ end
+
+ it "normalizes HTTPS URIs in credentials configuration" do
+ settings["https://gemserver.example.org"] = "username:password"
+ expect(settings.all).to include("https://gemserver.example.org/")
+ end
+
+ it "normalizes HTTP URIs in mirror configuration" do
+ settings["mirror.http://rubygems.org"] = "http://rubygems-mirror.org"
+ expect(settings.all).to include("mirror.http://rubygems.org/")
+ end
+
+ it "normalizes HTTPS URIs in mirror configuration" do
+ settings["mirror.https://rubygems.org"] = "http://rubygems-mirror.org"
+ expect(settings.all).to include("mirror.https://rubygems.org/")
+ end
+
+ it "does not normalize other config keys that happen to contain 'http'" do
+ settings["local.httparty"] = home("httparty")
+ expect(settings.all).to include("local.httparty")
+ end
+
+ it "does not normalize other config keys that happen to contain 'https'" do
+ settings["local.httpsmarty"] = home("httpsmarty")
+ expect(settings.all).to include("local.httpsmarty")
+ end
+
+ it "reads older keys without trailing slashes" do
+ settings["mirror.https://rubygems.org"] = "http://rubygems-mirror.org"
+ expect(settings.gem_mirrors).to eq(URI("https://rubygems.org/") => URI("http://rubygems-mirror.org/"))
+ end
+
+ end
end
diff --git a/spec/bundler/source/rubygems_spec.rb b/spec/bundler/source/rubygems_spec.rb
index 68fc6c6ed4..6bcde3d328 100644
--- a/spec/bundler/source/rubygems_spec.rb
+++ b/spec/bundler/source/rubygems_spec.rb
@@ -22,4 +22,5 @@ describe Bundler::Source::Rubygems do
end
end
end
+
end
diff --git a/spec/bundler/source_list_spec.rb b/spec/bundler/source_list_spec.rb
index 4acaa9da5d..f5a8575ae8 100644
--- a/spec/bundler/source_list_spec.rb
+++ b/spec/bundler/source_list_spec.rb
@@ -117,19 +117,6 @@ describe Bundler::SourceList do
expect(source_list.all_sources).to include rubygems_aggregate
end
- it "returns path sources before git sources before rubygems sources before the aggregate" do
- source_list.add_git_source('uri' => 'git://host/path.git')
- source_list.add_rubygems_source('remotes' => ['https://rubygems.org'])
- source_list.add_path_source('path' => '/path/to/gem')
-
- expect(source_list.all_sources).to eq [
- Bundler::Source::Path.new('path' => '/path/to/gem'),
- Bundler::Source::Git.new('uri' => 'git://host/path.git'),
- Bundler::Source::Rubygems.new('remotes' => ['https://rubygems.org']),
- rubygems_aggregate,
- ]
- end
-
it "returns sources of the same type in the reverse order that they were added" do
source_list.add_git_source('uri' => 'git://third-git.org/path.git')
source_list.add_rubygems_source('remotes' => ['https://fifth-rubygems.org'])
diff --git a/spec/cache/cache_path_spec.rb b/spec/cache/cache_path_spec.rb
new file mode 100644
index 0000000000..c0e73ca588
--- /dev/null
+++ b/spec/cache/cache_path_spec.rb
@@ -0,0 +1,33 @@
+require "spec_helper"
+
+describe "bundle package" do
+ before do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+ end
+
+ context "with --cache-path" do
+ it "caches gems at given path" do
+ bundle :package, "cache-path" => "vendor/cache-foo"
+ expect(bundled_app("vendor/cache-foo/rack-1.0.0.gem")).to exist
+ end
+ end
+
+ context "with config cache_path" do
+ it "caches gems at given path" do
+ bundle "config cache_path vendor/cache-foo"
+ bundle :package
+ expect(bundled_app("vendor/cache-foo/rack-1.0.0.gem")).to exist
+ end
+ end
+
+ context "when given an absolute path" do
+ it "exits with non-zero status" do
+ bundle :package, "cache-path" => "/tmp/cache-foo"
+ expect(out).to match(/must be relative/)
+ expect(exitstatus).to eq(15) if exitstatus
+ end
+ end
+end
diff --git a/spec/cache/platform_spec.rb b/spec/cache/platform_spec.rb
index 0701d5d4fb..6b73f90f05 100644
--- a/spec/cache/platform_spec.rb
+++ b/spec/cache/platform_spec.rb
@@ -5,17 +5,13 @@ describe "bundle cache with multiple platforms" do
gemfile <<-G
source "file://#{gem_repo1}"
- platforms :ruby, :ruby_18, :ruby_19, :ruby_20, :ruby_21, :ruby_22 do
+ platforms :mri, :rbx do
gem "rack", "1.0.0"
end
platforms :jruby do
gem "activesupport", "2.3.5"
end
-
- platforms :mri, :mri_18, :mri_19, :mri_20, :mri_21, :mri_22 do
- gem "activerecord", "2.3.2"
- end
G
lockfile <<-G
@@ -24,7 +20,6 @@ describe "bundle cache with multiple platforms" do
specs:
rack (1.0.0)
activesupport (2.3.5)
- activerecord (2.3.2)
PLATFORMS
ruby
@@ -33,25 +28,26 @@ describe "bundle cache with multiple platforms" do
DEPENDENCIES
rack (1.0.0)
activesupport (2.3.5)
- activerecord (2.3.2)
G
- cache_gems "rack-1.0.0", "activesupport-2.3.5", "activerecord-2.3.2"
+ cache_gems "rack-1.0.0", "activesupport-2.3.5"
end
- it "ensures that bundle install does not delete gems for other platforms" do
+ it "ensures that a succesful bundle install does not delete gems for other platforms" do
bundle "install"
+ expect(exitstatus).to eq 0 if exitstatus
+
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/activesupport-2.3.5.gem")).to exist
- expect(bundled_app("vendor/cache/activerecord-2.3.2.gem")).to exist
end
- it "ensures that bundle update does not delete gems for other platforms" do
+ it "ensures that a succesful bundle update does not delete gems for other platforms" do
bundle "update"
+ expect(exitstatus).to eq 0 if exitstatus
+
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/activesupport-2.3.5.gem")).to exist
- expect(bundled_app("vendor/cache/activerecord-2.3.2.gem")).to exist
end
end
diff --git a/spec/commands/binstubs_spec.rb b/spec/commands/binstubs_spec.rb
index e307539f76..284913a354 100644
--- a/spec/commands/binstubs_spec.rb
+++ b/spec/commands/binstubs_spec.rb
@@ -45,8 +45,8 @@ describe "bundle binstubs <gem>" do
gem "rack"
G
- bundle "binstubs", :exitstatus => true
- expect(exitstatus).to eq(1)
+ bundle "binstubs"
+ expect(exitstatus).to eq(1) if exitstatus
expect(out).to eq("`bundle binstubs` needs at least one gem to run.")
end
@@ -111,9 +111,9 @@ describe "bundle binstubs <gem>" do
source "file://#{gem_repo1}"
G
- bundle "binstubs doesnt_exist", :exitstatus => true
+ bundle "binstubs doesnt_exist"
- expect(exitstatus).to eq(7)
+ expect(exitstatus).to eq(7) if exitstatus
expect(out).to eq("Could not find gem 'doesnt_exist'.")
end
end
@@ -216,4 +216,29 @@ describe "bundle binstubs <gem>" do
expect(out).to include('no executables for the gem with_development_dependency')
end
end
+
+ context "when BUNDLE_INSTALL is specified" do
+ it "performs an automatic bundle install" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ bundle "config auto_install 1"
+ bundle "binstubs rack"
+ expect(out).to include('Installing rack 1.0.0')
+ should_be_installed "rack 1.0.0"
+ end
+
+ it "does nothing when already up to date" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ bundle "config auto_install 1"
+ bundle "binstubs rack", :env => { "BUNDLE_INSTALL" => 1 }
+ expect(out).not_to include('Installing rack 1.0.0')
+ end
+ end
end
diff --git a/spec/commands/check_spec.rb b/spec/commands/check_spec.rb
index 248b5c2eed..6d047597d5 100644
--- a/spec/commands/check_spec.rb
+++ b/spec/commands/check_spec.rb
@@ -7,8 +7,8 @@ describe "bundle check" do
gem "rails"
G
- bundle :check, :exitstatus => true
- expect(@exitstatus).to eq(0)
+ bundle :check
+ expect(exitstatus).to eq(0) if exitstatus
expect(out).to eq("The Gemfile's dependencies are satisfied")
end
@@ -67,8 +67,8 @@ describe "bundle check" do
gem "rails"
G
- bundle :check, :exitstatus => true
- expect(@exitstatus).to be > 0
+ bundle :check
+ expect(exitstatus).to be > 0 if exitstatus
expect(out).to include("Bundler can't satisfy your Gemfile's dependencies.")
end
@@ -101,8 +101,8 @@ describe "bundle check" do
G
bundle "install --without foo"
- bundle "check", :exitstatus => true
- expect(@exitstatus).to eq(0)
+ bundle "check"
+ expect(exitstatus).to eq(0) if exitstatus
expect(out).to include("The Gemfile's dependencies are satisfied")
end
@@ -119,9 +119,9 @@ describe "bundle check" do
gem "rack"
G
- bundle "check", :exitstatus => true
+ bundle "check"
expect(out).to include("* rack (1.0.0)")
- expect(@exitstatus).to eq(1)
+ expect(exitstatus).to eq(1) if exitstatus
end
it "ignores missing gems restricted to other platforms" do
@@ -187,14 +187,14 @@ describe "bundle check" do
end
it "outputs an error when the default Gemfile is not found" do
- bundle :check, :exitstatus => true
- expect(@exitstatus).to eq(10)
+ bundle :check
+ expect(exitstatus).to eq(10) if exitstatus
expect(out).to include("Could not locate Gemfile")
end
it "does not output fatal error message" do
- bundle :check, :exitstatus => true
- expect(@exitstatus).to eq(10)
+ bundle :check
+ expect(exitstatus).to eq(10) if exitstatus
expect(out).not_to include("Unfortunately, a fatal error has occurred. ")
end
@@ -224,8 +224,8 @@ describe "bundle check" do
bundle "install --deployment"
FileUtils.rm(bundled_app("Gemfile.lock"))
- bundle :check, :exitstatus => true
- expect(exitstatus).not_to eq(0)
+ bundle :check
+ expect(exitstatus).not_to eq(0) if exitstatus
end
context "--path" do
@@ -240,15 +240,15 @@ describe "bundle check" do
end
it "returns success" do
- bundle "check --path vendor/bundle", :exitstatus => true
- expect(@exitstatus).to eq(0)
+ bundle "check --path vendor/bundle"
+ expect(exitstatus).to eq(0) if exitstatus
expect(out).to eq("The Gemfile's dependencies are satisfied")
end
it "should write to .bundle/config" do
- bundle "check --path vendor/bundle", :exitstatus => true
- bundle "check", :exitstatus => true
- expect(@exitstatus).to eq(0)
+ bundle "check --path vendor/bundle"
+ bundle "check"
+ expect(exitstatus).to eq(0) if exitstatus
end
end
@@ -263,8 +263,8 @@ describe "bundle check" do
it "returns success when the Gemfile is satisfied" do
bundle :install
- bundle :check, :exitstatus => true
- expect(@exitstatus).to eq(0)
+ bundle :check
+ expect(exitstatus).to eq(0) if exitstatus
expect(out).to eq("The Gemfile's dependencies are satisfied")
end
diff --git a/spec/commands/clean_spec.rb b/spec/commands/clean_spec.rb
index cee1312a5f..529c245912 100644
--- a/spec/commands/clean_spec.rb
+++ b/spec/commands/clean_spec.rb
@@ -270,8 +270,8 @@ describe "bundle clean" do
bundle "install --path vendor/bundle --without development"
- bundle :clean, :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle :clean
+ expect(exitstatus).to eq(0) if exitstatus
end
it "displays an error when used without --path" do
@@ -281,10 +281,10 @@ describe "bundle clean" do
gem "rack", "1.0.0"
G
- bundle :clean, :exitstatus => true
+ bundle :clean
- expect(exitstatus).to eq(1)
- expect(out).to eq("Can only use bundle clean when --path is set or --force is set")
+ expect(exitstatus).to eq(1) if exitstatus
+ expect(out).to include("--force")
end
# handling bundle clean upgrade path from the pre's
@@ -505,9 +505,9 @@ describe "bundle clean" do
bundle "clean --force"
- sys_status "foo"
+ sys_exec "foo"
- expect(exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
expect(out).to eq("1.0")
end
@@ -527,9 +527,9 @@ describe "bundle clean" do
G
bundle "install --path vendor/bundle"
- bundle :clean, :exitstatus => true
+ bundle :clean
- expect(exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
end
it "doesn't remove gems in dry-run mode" do
@@ -589,4 +589,28 @@ describe "bundle clean" do
expect(vendored_gems("bin/rackup")).to exist
end
+
+ it "performs an automatic bundle install" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ gem "thin"
+ gem "foo"
+ G
+
+ bundle "install --path vendor/bundle --no-clean"
+
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ gem "thin"
+ gem "weakling"
+ G
+
+ bundle "config auto_install 1"
+ bundle :clean
+ expect(out).to include('Installing weakling 0.0.3')
+ should_have_gems 'thin-1.0', 'rack-1.0.0', 'weakling-0.0.3'
+ should_not_have_gems 'foo-1.0'
+ end
end
diff --git a/spec/commands/config_spec.rb b/spec/commands/config_spec.rb
index aad00fa469..cd1f23e4a0 100644
--- a/spec/commands/config_spec.rb
+++ b/spec/commands/config_spec.rb
@@ -177,6 +177,13 @@ describe ".bundle/config" do
run "if Bundler.settings[:frozen]; puts 'true' else puts 'false' end"
expect(out).to eq("false")
end
+
+ it "can set properties with periods via the environment" do
+ ENV["BUNDLE_FOO__BAR"] = "baz"
+
+ run "puts Bundler.settings['foo.bar']"
+ expect(out).to eq("baz")
+ end
end
describe "gem mirrors" do
@@ -195,6 +202,10 @@ E
describe "quoting" do
before(:each) { gemfile "# no gems" }
+ let(:long_string) do
+ "--with-xml2-include=/usr/pkg/include/libxml2 --with-xml2-lib=/usr/pkg/lib " \
+ "--with-xslt-dir=/usr/pkg"
+ end
it "saves quotes" do
bundle "config foo something\\'"
@@ -225,7 +236,6 @@ E
end
it "doesn't duplicate quotes around long wrapped values" do
- long_string = "--with-xml2-include=/usr/pkg/include/libxml2 --with-xml2-lib=/usr/pkg/lib --with-xslt-dir=/usr/pkg"
bundle "config foo #{long_string}"
run "puts Bundler.settings[:foo]"
@@ -241,7 +251,12 @@ E
describe "very long lines" do
before(:each) { bundle :install }
let(:long_string) do
- "--with-xml2-include=/usr/pkg/include/libxml2 --with-xml2-lib=/usr/pkg/lib --with-xslt-dir=/usr/pkg"
+ "--with-xml2-include=/usr/pkg/include/libxml2 --with-xml2-lib=/usr/pkg/lib " \
+ "--with-xslt-dir=/usr/pkg"
+ end
+ let(:long_string_without_special_characters) do
+ "here is quite a long string that will wrap to a second line but will not be " \
+ "surrounded by quotes"
end
let(:long_string_without_special_characters) do
"here is quite a long string that will wrap to a second line but will not be surrounded by quotes"
@@ -259,5 +274,23 @@ E
expect(out).to match(long_string_without_special_characters)
end
end
+end
+
+describe "setting gemfile via config" do
+ context "when only the non-default Gemfile exists" do
+ it "persists the gemfile location to .bundle/config" do
+ File.open(bundled_app("NotGemfile"), "w") do |f|
+ f.write <<-G
+ source "file://#{gem_repo1}"
+ gem 'rack'
+ G
+ end
+ bundle "config --local gemfile #{bundled_app("NotGemfile")}"
+ expect(File.exist?(".bundle/config")).to eq(true)
+
+ bundle "config"
+ expect(out).to include("NotGemfile")
+ end
+ end
end
diff --git a/spec/commands/console_spec.rb b/spec/commands/console_spec.rb
index 75d6796c9d..f26fbcdba5 100644
--- a/spec/commands/console_spec.rb
+++ b/spec/commands/console_spec.rb
@@ -36,10 +36,9 @@ describe "bundle console" do
input.puts("__callee__")
input.puts("exit")
end
- expect(out).to include("irb")
+ expect(out).to include("IRB")
end
-
it "doesn't load any other groups" do
bundle "console" do |input|
input.puts("puts ACTIVESUPPORT")
@@ -73,4 +72,23 @@ describe "bundle console" do
expect(out).to include("NameError")
end
end
+
+ it "performs an automatic bundle install" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ gem "activesupport", :group => :test
+ gem "rack_middleware", :group => :development
+ gem "foo"
+ G
+
+ bundle "config auto_install 1"
+ bundle :console do |input|
+ input.puts("puts 'hello'")
+ input.puts("exit")
+ end
+ expect(out).to include("Installing foo 1.0")
+ expect(out).to include("hello")
+ should_be_installed "foo 1.0"
+ end
end
diff --git a/spec/commands/exec_spec.rb b/spec/commands/exec_spec.rb
index 52b93565de..835b0795f0 100644
--- a/spec/commands/exec_spec.rb
+++ b/spec/commands/exec_spec.rb
@@ -189,8 +189,8 @@ describe "bundle exec" do
gem "rack"
G
- bundle "exec foobarbaz", :exitstatus => true
- expect(exitstatus).to eq(127)
+ bundle "exec foobarbaz"
+ expect(exitstatus).to eq(127) if exitstatus
expect(out).to include("bundler: command not found: foobarbaz")
expect(out).to include("Install missing gem executables with `bundle install`")
end
@@ -201,8 +201,8 @@ describe "bundle exec" do
G
bundle "exec touch foo"
- bundle "exec ./foo", :exitstatus => true
- expect(exitstatus).to eq(126)
+ bundle "exec ./foo"
+ expect(exitstatus).to eq(126) if exitstatus
expect(out).to include("bundler: not executable: ./foo")
end
@@ -211,8 +211,8 @@ describe "bundle exec" do
gem "rack"
G
- bundle "exec", :exitstatus => true
- expect(exitstatus).to eq(128)
+ bundle "exec"
+ expect(exitstatus).to eq(128) if exitstatus
expect(out).to include("bundler: exec needs a command to run")
end
@@ -306,4 +306,16 @@ describe "bundle exec" do
end
end
end
+
+ it "performs an automatic bundle install" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack", "0.9.1"
+ gem "foo"
+ G
+
+ bundle "config auto_install 1"
+ bundle "exec rackup"
+ expect(out).to include("Installing foo 1.0")
+ end
end
diff --git a/spec/commands/licenses_spec.rb b/spec/commands/licenses_spec.rb
index c8d5ff739e..e2aba5a717 100644
--- a/spec/commands/licenses_spec.rb
+++ b/spec/commands/licenses_spec.rb
@@ -15,4 +15,17 @@ describe "bundle licenses" do
expect(out).to include("actionpack: Unknown")
expect(out).to include("with_license: MIT")
end
+
+ it "performs an automatic bundle install" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rails"
+ gem "with_license"
+ gem "foo"
+ G
+
+ bundle "config auto_install 1"
+ bundle :licenses
+ expect(out).to include("Installing foo 1.0")
+ end
end
diff --git a/spec/commands/newgem_spec.rb b/spec/commands/newgem_spec.rb
index 024ca0cabb..fc2f113e8a 100644
--- a/spec/commands/newgem_spec.rb
+++ b/spec/commands/newgem_spec.rb
@@ -1,6 +1,7 @@
require "spec_helper"
describe "bundle gem" do
+
def reset!
super
global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false"
@@ -15,7 +16,7 @@ describe "bundle gem" do
after do
`git config --global user.name "#{@git_name}"`
- `git config --global user.email #{@git_email}`
+ `git config --global user.email "#{@git_email}"`
end
shared_examples_for "git config is present" do
@@ -30,7 +31,7 @@ describe "bundle gem" do
end
end
- shared_examples_for "git config is absent" do |hoge|
+ shared_examples_for "git config is absent" do
it "sets gemspec author to default message if git user.name is not set or empty" do
expect(generated_gem.gemspec.authors.first).to eq("TODO: Write your name")
end
@@ -40,6 +41,72 @@ describe "bundle gem" do
end
end
+ it "generates a valid gemspec" do
+ system_gems ["rake-10.0.2"]
+
+ in_app_root
+ bundle "gem newgem --bin"
+
+ process_file(bundled_app('newgem', "newgem.gemspec")) do |line|
+ next line unless line =~ /TODO/
+ # Simulate replacing TODOs with real values
+ case line
+ when /spec\.metadata\['allowed_push_host'\]/, /spec\.homepage/
+ line.gsub(/\=.*$/, "= 'http://example.org'")
+ when /spec\.summary/
+ line.gsub(/\=.*$/, "= %q{A short summary of my new gem.}")
+ when /spec\.description/
+ line.gsub(/\=.*$/, "= %q{A longer description of my new gem.}")
+ else
+ line
+ end
+ end
+
+ Dir.chdir(bundled_app('newgem')) do
+ bundle "exec rake build"
+ end
+
+ expect(exitstatus).to be_zero if exitstatus
+ expect(out).not_to include("ERROR")
+ expect(err).not_to include("ERROR")
+ end
+
+ context "gem naming with relative paths" do
+ before do
+ reset!
+ in_app_root
+ end
+
+ it "resolves ." do
+ create_temporary_dir('tmp')
+
+ bundle 'gem .'
+
+ expect(bundled_app("tmp/lib/tmp.rb")).to exist
+ end
+
+ it "resolves .." do
+ create_temporary_dir('temp/empty_dir')
+
+ bundle 'gem ..'
+
+ expect(bundled_app("temp/lib/temp.rb")).to exist
+ end
+
+ it "resolves relative directory" do
+ create_temporary_dir('tmp/empty/tmp')
+
+ bundle 'gem ../../empty'
+
+ expect(bundled_app("tmp/empty/lib/empty.rb")).to exist
+ end
+
+ def create_temporary_dir(dir)
+ FileUtils.mkdir_p(dir)
+ Dir.chdir(dir)
+ end
+ end
+
context "gem naming with underscore" do
let(:gem_name) { 'test_gem' }
@@ -53,15 +120,15 @@ describe "bundle gem" do
it "generates a gem skeleton" do
expect(bundled_app("test_gem/test_gem.gemspec")).to exist
- expect(bundled_app("test_gem/LICENSE.txt")).to exist
expect(bundled_app("test_gem/Gemfile")).to exist
expect(bundled_app("test_gem/Rakefile")).to exist
expect(bundled_app("test_gem/lib/test_gem.rb")).to exist
expect(bundled_app("test_gem/lib/test_gem/version.rb")).to exist
+ expect(bundled_app("test_gem/.gitignore")).to exist
end
- it "starts with version 0.0.1" do
- expect(bundled_app("test_gem/lib/test_gem/version.rb").read).to match(/VERSION = "0.0.1"/)
+ it "starts with version 0.1.0" do
+ expect(bundled_app("test_gem/lib/test_gem/version.rb").read).to match(/VERSION = "0.1.0"/)
end
it "does not nest constants" do
@@ -83,8 +150,9 @@ describe "bundle gem" do
it_should_behave_like "git config is absent"
end
- it "sets gemspec license to MIT by default" do
- expect(generated_gem.gemspec.license).to eq("MIT")
+ it "sets gemspec metadata['allowed_push_host']", :rubygems => "2.0" do
+ expect(generated_gem.gemspec.metadata['allowed_push_host']).
+ to match("delete to allow pushes to any server")
end
it "requires the version file" do
@@ -117,11 +185,11 @@ describe "bundle gem" do
end
it "builds bin skeleton" do
- expect(bundled_app("test_gem/bin/test_gem")).to exist
+ expect(bundled_app("test_gem/exe/test_gem")).to exist
end
it "requires 'test-gem'" do
- expect(bundled_app("test_gem/bin/test_gem").read).to match(/require 'test_gem'/)
+ expect(bundled_app("test_gem/exe/test_gem").read).to match(/require "test_gem"/)
end
end
@@ -163,6 +231,35 @@ describe "bundle gem" do
end
end
+ context "gem.test setting set to rspec" do
+ before do
+ reset!
+ in_app_root
+ bundle "config gem.test rspec"
+ bundle "gem #{gem_name}"
+ end
+
+ it "builds spec skeleton" do
+ expect(bundled_app("test_gem/.rspec")).to exist
+ expect(bundled_app("test_gem/spec/test_gem_spec.rb")).to exist
+ expect(bundled_app("test_gem/spec/spec_helper.rb")).to exist
+ end
+ end
+
+ context "gem.test setting set to rspec and --test is set to minitest" do
+ before do
+ reset!
+ in_app_root
+ bundle "config gem.test rspec"
+ bundle "gem #{gem_name} --test=minitest"
+ end
+
+ it "builds spec skeleton" do
+ expect(bundled_app("test_gem/test/test_test_gem.rb")).to exist
+ expect(bundled_app("test_gem/test/minitest_helper.rb")).to exist
+ end
+ end
+
context "--test parameter set to minitest" do
before do
reset!
@@ -216,6 +313,47 @@ describe "bundle gem" do
end
end
+ context "with --mit option" do
+ let(:gem_name) { 'test-gem' }
+
+ before do
+ bundle "gem #{gem_name} --mit"
+ # reset gemspec cache for each test because of commit 3d4163a
+ Bundler.clear_gemspec_cache
+ end
+
+ it "generates a gem skeleton with MIT license" do
+ expect(bundled_app("test-gem/test-gem.gemspec")).to exist
+ expect(bundled_app("test-gem/LICENSE.txt")).to exist
+ expect(bundled_app("test-gem/Gemfile")).to exist
+ expect(bundled_app("test-gem/Rakefile")).to exist
+ expect(bundled_app("test-gem/lib/test/gem.rb")).to exist
+ expect(bundled_app("test-gem/lib/test/gem/version.rb")).to exist
+
+ skel = Bundler::GemHelper.new(bundled_app(gem_name).to_s)
+ expect(skel.gemspec.license).to eq("MIT")
+ end
+ end
+
+ context "with --coc option" do
+ let(:gem_name) { 'test-gem' }
+
+ before do
+ bundle "gem #{gem_name} --coc"
+ # reset gemspec cache for each test because of commit 3d4163a
+ Bundler.clear_gemspec_cache
+ end
+
+ it "generates a gem skeleton with Code of Conduct" do
+ expect(bundled_app("test-gem/test-gem.gemspec")).to exist
+ expect(bundled_app("test-gem/CODE_OF_CONDUCT.md")).to exist
+ expect(bundled_app("test-gem/Gemfile")).to exist
+ expect(bundled_app("test-gem/Rakefile")).to exist
+ expect(bundled_app("test-gem/lib/test/gem.rb")).to exist
+ expect(bundled_app("test-gem/lib/test/gem/version.rb")).to exist
+ end
+ end
+
context "gem naming with dashed" do
let(:gem_name) { 'test-gem' }
@@ -229,15 +367,15 @@ describe "bundle gem" do
it "generates a gem skeleton" do
expect(bundled_app("test-gem/test-gem.gemspec")).to exist
- expect(bundled_app("test-gem/LICENSE.txt")).to exist
+ # expect(bundled_app("test-gem/LICENSE.txt")).to exist
expect(bundled_app("test-gem/Gemfile")).to exist
expect(bundled_app("test-gem/Rakefile")).to exist
expect(bundled_app("test-gem/lib/test/gem.rb")).to exist
expect(bundled_app("test-gem/lib/test/gem/version.rb")).to exist
end
- it "starts with version 0.0.1" do
- expect(bundled_app("test-gem/lib/test/gem/version.rb").read).to match(/VERSION = "0.0.1"/)
+ it "starts with version 0.1.0" do
+ expect(bundled_app("test-gem/lib/test/gem/version.rb").read).to match(/VERSION = "0.1.0"/)
end
it "nests constants so they work" do
@@ -259,8 +397,9 @@ describe "bundle gem" do
it_should_behave_like "git config is absent"
end
- it "sets gemspec license to MIT by default" do
- expect(generated_gem.gemspec.license).to eq("MIT")
+ it "sets gemspec metadata['allowed_push_host']", :rubygems => "2.0" do
+ expect(generated_gem.gemspec.metadata['allowed_push_host']).
+ to match("delete to allow pushes to any server")
end
it "requires the version file" do
@@ -293,11 +432,11 @@ describe "bundle gem" do
end
it "builds bin skeleton" do
- expect(bundled_app("test-gem/bin/test-gem")).to exist
+ expect(bundled_app("test-gem/exe/test-gem")).to exist
end
it "requires 'test/gem'" do
- expect(bundled_app("test-gem/bin/test-gem").read).to match(/require 'test\/gem'/)
+ expect(bundled_app("test-gem/exe/test-gem").read).to match(/require "test\/gem"/)
end
end
@@ -423,6 +562,62 @@ describe "bundle gem" do
it "includes rake-compiler" do
expect(bundled_app("test_gem/test_gem.gemspec").read).to include('spec.add_development_dependency "rake-compiler"')
end
+
+ it "depends on compile task for build" do
+ rakefile = strip_whitespace <<-RAKEFILE
+ require "bundler/gem_tasks"
+
+ require "rake/extensiontask"
+
+ task :build => :compile
+
+ Rake::ExtensionTask.new("test_gem") do |ext|
+ ext.lib_dir = "lib/test_gem"
+ end
+ RAKEFILE
+
+ expect(bundled_app("test_gem/Rakefile").read).to eq(rakefile)
+ end
end
end
+
+ context "on first run" do
+ before do
+ in_app_root
+ end
+
+ it "asks about test framework" do
+ global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__COC" => "false"
+
+ bundle "gem foobar" do |input|
+ input.puts "rspec"
+ end
+
+ expect(bundled_app("foobar/spec/spec_helper.rb")).to exist
+ end
+
+ it "asks about MIT license" do
+ global_config "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false"
+
+ bundle :config
+
+ bundle "gem foobar" do |input|
+ input.puts "yes"
+ end
+
+ expect(bundled_app("foobar/LICENSE.txt")).to exist
+ end
+
+ it "asks about CoC" do
+ global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false"
+
+
+ bundle "gem foobar" do |input|
+ input.puts "yes"
+ end
+
+ expect(bundled_app("foobar/CODE_OF_CONDUCT.md")).to exist
+ end
+ end
+
end
diff --git a/spec/commands/open_spec.rb b/spec/commands/open_spec.rb
index e3a66ec1de..67ee40cfe5 100644
--- a/spec/commands/open_spec.rb
+++ b/spec/commands/open_spec.rb
@@ -65,4 +65,16 @@ describe "bundle open" do
expect(out).to match(/bundler_editor #{default_bundle_path('gems', 'activerecord-2.3.2')}\z/)
end
+
+ it "performs an automatic bundle install" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rails"
+ gem "foo"
+ G
+
+ bundle "config auto_install 1"
+ bundle "open rails", :env => {"EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => ""}
+ expect(out).to include("Installing foo 1.0")
+ end
end
diff --git a/spec/commands/outdated_spec.rb b/spec/commands/outdated_spec.rb
index da17a2eee8..4d8e6d5ce1 100644
--- a/spec/commands/outdated_spec.rb
+++ b/spec/commands/outdated_spec.rb
@@ -42,15 +42,15 @@ describe "bundle outdated" do
update_git "foo", :path => lib_path("foo")
end
- bundle "outdated", :exitstatus => true
+ bundle "outdated"
- expect(exitstatus).to_not be_zero
+ expect(exitstatus).to_not be_zero if exitstatus
end
it "returns success exit status if no outdated gems present" do
- bundle "outdated", :exitstatus => true
+ bundle "outdated"
- expect(exitstatus).to be_zero
+ expect(exitstatus).to be_zero if exitstatus
end
end
@@ -149,8 +149,20 @@ describe "bundle outdated" do
end
it "returns non-zero exit code" do
- bundle "outdated invalid_gem_name", :exitstatus => true
- expect(exitstatus).to_not be_zero
+ bundle "outdated invalid_gem_name"
+ expect(exitstatus).to_not be_zero if exitstatus
end
end
+
+ it "performs an automatic bundle install" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack", "0.9.1"
+ gem "foo"
+ G
+
+ bundle "config auto_install 1"
+ bundle :outdated
+ expect(out).to include("Installing foo 1.0")
+ end
end
diff --git a/spec/commands/package_spec.rb b/spec/commands/package_spec.rb
index e433b92094..d87ebc56bf 100644
--- a/spec/commands/package_spec.rb
+++ b/spec/commands/package_spec.rb
@@ -28,6 +28,32 @@ describe "bundle package" do
expect(bundled_app("test/vendor/cache/")).to exist
end
end
+
+ context "with --no-install" do
+ it "puts the gems in vendor/cache but does not install them" do
+ gemfile <<-D
+ source "file://#{gem_repo1}"
+ gem 'rack'
+ D
+
+ bundle "package --no-install"
+
+ should_not_be_installed "rack 1.0.0"
+ expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ end
+ end
+
+ context "with --all-platforms" do
+ it "puts the gems in vendor/cache even for other rubies", :ruby => "2.1" do
+ gemfile <<-D
+ source "file://#{gem_repo1}"
+ gem 'rack', :platforms => :ruby_19
+ D
+
+ bundle "package --all-platforms"
+ expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ end
+ end
end
describe "bundle install with gem sources" do
diff --git a/spec/commands/show_spec.rb b/spec/commands/show_spec.rb
index 01a2c2a50a..18105541c7 100644
--- a/spec/commands/show_spec.rb
+++ b/spec/commands/show_spec.rb
@@ -63,8 +63,10 @@ describe "bundle show" do
it "prints summary of gems" do
bundle "show --verbose"
- expect(out).to include(' - This is just a fake gem for testing')
- expect(out).to include(' - Ruby based make-like utility.')
+ expect(out).to include("* actionmailer (2.3.2)")
+ expect(out).to include("\tSummary: This is just a fake gem for testing")
+ expect(out).to include("\tHomepage: No website available.")
+ expect(out).to include("\tStatus: Up to date")
end
end
@@ -122,4 +124,29 @@ describe "bundle show" do
expect(err).to be_empty
end
end
+
+ it "performs an automatic bundle install" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "foo"
+ G
+
+ bundle "config auto_install 1"
+ bundle :show
+ expect(out).to include("Installing foo 1.0")
+ end
+
+ context "with an invalid regexp for gem name" do
+ it "does not find the gem" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rails"
+ G
+
+ invalid_regexp = '[]'
+
+ bundle "show #{invalid_regexp}"
+ expect(out).to include("Could not find gem '#{invalid_regexp}'.")
+ end
+ end
end
diff --git a/spec/install/deploy_spec.rb b/spec/install/deploy_spec.rb
index 25f5c5b5de..26d8abe295 100644
--- a/spec/install/deploy_spec.rb
+++ b/spec/install/deploy_spec.rb
@@ -20,8 +20,8 @@ describe "install with --deployment or --frozen" do
it "works after you try to deploy without a lock" do
bundle "install --deployment"
- bundle :install, :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle :install
+ expect(exitstatus).to eq(0) if exitstatus
should_be_installed "rack 1.0"
end
@@ -42,15 +42,15 @@ describe "install with --deployment or --frozen" do
end
G
bundle :install
- bundle "install --deployment --without test", :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle "install --deployment --without test"
+ expect(exitstatus).to eq(0) if exitstatus
end
it "works when you bundle exec bundle" do
bundle :install
bundle "install --deployment"
- bundle "exec bundle check", :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle "exec bundle check"
+ expect(exitstatus).to eq(0) if exitstatus
end
it "works when using path gems from the same path and the version is specified" do
@@ -62,9 +62,9 @@ describe "install with --deployment or --frozen" do
G
bundle :install
- bundle "install --deployment", :exitstatus => true
+ bundle "install --deployment"
- expect(exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
end
it "works when there are credentials in the source URL" do
@@ -74,9 +74,9 @@ describe "install with --deployment or --frozen" do
gem "rack-obama", ">= 1.0"
G
- bundle "install --deployment", :exitstatus => true, :artifice => "endpoint_strict_basic_authentication"
+ bundle "install --deployment", :artifice => "endpoint_strict_basic_authentication"
- expect(exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
end
it "works with sources given by a block" do
@@ -86,9 +86,9 @@ describe "install with --deployment or --frozen" do
end
G
- bundle "install --deployment", :exitstatus => true
+ bundle "install --deployment"
- expect(exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
should_be_installed "rack 1.0"
end
@@ -98,13 +98,13 @@ describe "install with --deployment or --frozen" do
end
it "works with the --deployment flag if you didn't change anything" do
- bundle "install --deployment", :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle "install --deployment"
+ expect(exitstatus).to eq(0) if exitstatus
end
it "works with the --frozen flag if you didn't change anything" do
- bundle "install --frozen", :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle "install --frozen"
+ expect(exitstatus).to eq(0) if exitstatus
end
it "explodes with the --deployment flag if you make a change and don't check in the lockfile" do
diff --git a/spec/install/gemfile/git_spec.rb b/spec/install/gemfile/git_spec.rb
index 5d954c4966..537ae8554f 100644
--- a/spec/install/gemfile/git_spec.rb
+++ b/spec/install/gemfile/git_spec.rb
@@ -297,7 +297,7 @@ describe "bundle install with git sources" do
bundle %|config local.rack #{lib_path('local-rack')}|
bundle %|config disable_local_branch_check true|
bundle :install
- expect(out).to match(/Your bundle is complete!/)
+ expect(out).to match(/Bundle complete!/)
end
it "explodes on different branches on install" do
@@ -655,8 +655,8 @@ describe "bundle install with git sources" do
G
bundle "install"
- bundle "install", :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle "install"
+ expect(exitstatus).to eq(0) if exitstatus
end
it "does not duplicate git gem sources" do
@@ -759,8 +759,8 @@ describe "bundle install with git sources" do
simulate_new_machine
- bundle "install --deployment", :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle "install --deployment"
+ expect(exitstatus).to eq(0) if exitstatus
end
end
@@ -921,14 +921,14 @@ describe "bundle install with git sources" do
ENV['GIT_DIR'] = 'bar'
ENV['GIT_WORK_TREE'] = 'bar'
- install_gemfile <<-G, :exitstatus => true
+ install_gemfile <<-G
source "file://#{gem_repo1}"
git "#{lib_path('xxxxxx-1.0')}" do
gem 'xxxxxx'
end
G
- expect(exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
expect(ENV['GIT_DIR']).to eq('bar')
expect(ENV['GIT_WORK_TREE']).to eq('bar')
end
@@ -959,9 +959,9 @@ describe "bundle install with git sources" do
bundle "package --all"
simulate_new_machine
- bundle "install", :env => {"PATH" => ""}, :exitstatus => true
+ bundle "install", :env => {"PATH" => ""}
expect(out).to_not include("You need to install git to be able to use gems from git repositories.")
- expect(exitstatus).to be_zero
+ expect(exitstatus).to be_zero if exitstatus
end
end
end
diff --git a/spec/install/gemfile/path_spec.rb b/spec/install/gemfile/path_spec.rb
index f88b6aa2a3..07449201c2 100644
--- a/spec/install/gemfile/path_spec.rb
+++ b/spec/install/gemfile/path_spec.rb
@@ -78,8 +78,8 @@ describe "bundle install with explicit source paths" do
gem 'foo', :path => File.expand_path("../foo-1.0", __FILE__)
G
- bundle "install --frozen", :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle "install --frozen"
+ expect(exitstatus).to eq(0) if exitstatus
end
it "installs dependencies from the path even if a newer gem is available elsewhere" do
@@ -199,11 +199,11 @@ describe "bundle install with explicit source paths" do
s.write "bar.gemspec"
end
- install_gemfile <<-G, :exitstatus => true
+ install_gemfile <<-G
gemspec :path => "#{lib_path("foo")}"
G
- expect(exitstatus).to eq(15)
+ expect(exitstatus).to eq(15) if exitstatus
expect(out).to match(/There are multiple gemspecs/)
end
@@ -212,7 +212,7 @@ describe "bundle install with explicit source paths" do
s.write "bar.gemspec"
end
- install_gemfile <<-G, :exitstatus => true
+ install_gemfile <<-G
gemspec :path => "#{lib_path("foo")}", :name => "foo"
G
diff --git a/spec/install/gemfile_spec.rb b/spec/install/gemfile_spec.rb
index 267a7f55db..bfe239396a 100644
--- a/spec/install/gemfile_spec.rb
+++ b/spec/install/gemfile_spec.rb
@@ -26,6 +26,32 @@ describe "bundle install" do
end
end
+ context "with gemfile set via config" do
+ before do
+ gemfile bundled_app("NotGemfile"), <<-G
+ source "file://#{gem_repo1}"
+ gem 'rack'
+ G
+
+ bundle "config --local gemfile #{bundled_app("NotGemfile")}"
+ end
+ it "uses the gemfile to install" do
+ bundle "install"
+ bundle "show"
+
+ expect(out).to include("rack (1.0.0)")
+ end
+ it "uses the gemfile while in a subdirectory" do
+ bundled_app("subdir").mkpath
+ Dir.chdir(bundled_app("subdir")) do
+ bundle "install"
+ bundle "show"
+
+ expect(out).to include("rack (1.0.0)")
+ end
+ end
+ end
+
context "with deprecated features" do
before :each do
in_app_root
diff --git a/spec/install/gems/dependency_api_spec.rb b/spec/install/gems/dependency_api_spec.rb
index e17612a2d9..7f20039e62 100644
--- a/spec/install/gems/dependency_api_spec.rb
+++ b/spec/install/gems/dependency_api_spec.rb
@@ -1,7 +1,8 @@
require "spec_helper"
describe "gemcutter's dependency API" do
- let(:source_uri) { "http://localgemserver.test" }
+ let(:source_hostname) { "localgemserver.test" }
+ let(:source_uri) { "http://#{source_hostname}" }
it "should use the API" do
gemfile <<-G
@@ -21,7 +22,7 @@ describe "gemcutter's dependency API" do
G
bundle :install, :artifice => "endpoint"
- expect(out).to include("Could not find gem ' sinatra")
+ expect(out).to include("' sinatra' is not a valid gem name because it contains whitespace.")
end
it "should handle nested dependencies" do
@@ -107,9 +108,9 @@ describe "gemcutter's dependency API" do
G
bundle "install", :artifice => "endpoint"
- bundle "install --deployment", :artifice => "endpoint", :exitstatus => true
+ bundle "install --deployment", :artifice => "endpoint"
- expect(exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
should_be_installed("foo 1.0")
end
@@ -532,7 +533,16 @@ describe "gemcutter's dependency API" do
G
end
- it "reads authentication details from bundle config" do
+ it "reads authentication details by host name from bundle config" do
+ bundle "config #{source_hostname} #{user}:#{password}"
+
+ bundle :install, :artifice => "endpoint_strict_basic_authentication"
+
+ expect(out).to include("Fetching gem metadata from #{source_uri}")
+ should_be_installed "rack 1.0.0"
+ end
+
+ it "reads authentication details by full url from bundle config" do
# The trailing slash is necessary here; Fetcher canonicalizes the URI.
bundle "config #{source_uri}/ #{user}:#{password}"
@@ -542,13 +552,20 @@ describe "gemcutter's dependency API" do
should_be_installed "rack 1.0.0"
end
+ it "should use the API" do
+ bundle "config #{source_hostname} #{user}:#{password}"
+ bundle :install, :artifice => "endpoint_strict_basic_authentication"
+ expect(out).to include("Fetching gem metadata from #{source_uri}")
+ should_be_installed "rack 1.0.0"
+ end
+
it "prefers auth supplied in the source uri" do
gemfile <<-G
source "#{basic_auth_source_uri}"
gem "rack"
G
- bundle "config #{source_uri}/ otheruser:wrong"
+ bundle "config #{source_hostname} otheruser:wrong"
bundle :install, :artifice => "endpoint_strict_basic_authentication"
should_be_installed "rack 1.0.0"
@@ -556,11 +573,11 @@ describe "gemcutter's dependency API" do
it "shows instructions if auth is not provided for the source" do
bundle :install, :artifice => "endpoint_strict_basic_authentication"
- expect(out).to include("bundle config #{source_uri}/ username:password")
+ expect(out).to include("bundle config #{source_hostname} username:password")
end
it "fails if authentication has already been provided, but failed" do
- bundle "config #{source_uri}/ #{user}:wrong"
+ bundle "config #{source_hostname} #{user}:wrong"
bundle :install, :artifice => "endpoint_strict_basic_authentication"
expect(out).to include("Bad username or password")
@@ -643,9 +660,9 @@ describe "gemcutter's dependency API" do
gem 'rack'
G
- bundle "install", :exitstatus => true, :artifice => "endpoint_marshal_fail"
+ bundle "install", :artifice => "endpoint_marshal_fail"
- expect(exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
end
end
diff --git a/spec/install/gems/groups_spec.rb b/spec/install/gems/groups_spec.rb
index afce362ad8..23af4aee65 100644
--- a/spec/install/gems/groups_spec.rb
+++ b/spec/install/gems/groups_spec.rb
@@ -41,14 +41,14 @@ describe "bundle install with groups" do
end
it "sets up everything if Bundler.setup is used with no groups" do
- out = run("require 'rack'; puts RACK")
- expect(out).to eq('1.0.0')
+ output = run("require 'rack'; puts RACK")
+ expect(output).to eq('1.0.0')
- out = run("require 'activesupport'; puts ACTIVESUPPORT")
- expect(out).to eq('2.3.5')
+ output = run("require 'activesupport'; puts ACTIVESUPPORT")
+ expect(output).to eq('2.3.5')
- out = run("require 'thin'; puts THIN")
- expect(out).to eq('1.0')
+ output = run("require 'thin'; puts THIN")
+ expect(output).to eq('1.0')
end
it "removes old groups when new groups are set up" do
@@ -62,12 +62,12 @@ describe "bundle install with groups" do
end
it "sets up old groups when they have previously been removed" do
- out = run <<-RUBY, :emo
+ output = run <<-RUBY, :emo
Bundler.setup(:default)
Bundler.setup(:default, :emo)
require 'thin'; puts THIN
RUBY
- expect(out).to eq('1.0')
+ expect(output).to eq('1.0')
end
end
diff --git a/spec/install/gems/platform_spec.rb b/spec/install/gems/platform_spec.rb
index 71603e1036..1d52858011 100644
--- a/spec/install/gems/platform_spec.rb
+++ b/spec/install/gems/platform_spec.rb
@@ -173,10 +173,36 @@ describe "bundle install with platform conditionals" do
end
G
- bundle :show, :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle :show
+ expect(exitstatus).to eq(0) if exitstatus
end
+ it "does not attempt to install gems from :rbx when using --local" do
+ simulate_platform "ruby"
+ simulate_ruby_engine "ruby"
+
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "some_gem", platform: :rbx
+ G
+
+ bundle "install --local"
+ expect(out).not_to match(/Could not find gem 'some_gem/)
+ end
+
+ it "does not attempt to install gems from other rubies when using --local" do
+ simulate_platform "ruby"
+ simulate_ruby_engine "ruby"
+ other_ruby_version_tag = RUBY_VERSION =~ /^1\.8/ ? :ruby_19 : :ruby_18
+
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "some_gem", platform: :#{other_ruby_version_tag}
+ G
+
+ bundle "install --local"
+ expect(out).not_to match(/Could not find gem 'some_gem/)
+ end
end
describe "when a gem has no architecture" do
diff --git a/spec/install/gems/simple_case_spec.rb b/spec/install/gems/simple_case_spec.rb
index aac70db6cf..759de0884f 100644
--- a/spec/install/gems/simple_case_spec.rb
+++ b/spec/install/gems/simple_case_spec.rb
@@ -16,7 +16,8 @@ describe "bundle install with gem sources" do
raise StandardError, "FAIL"
G
- expect(err).to match(/FAIL \(StandardError\)/)
+ expect(err).to eq ""
+ expect(out).to match(/StandardError: FAIL/)
expect(bundled_app("Gemfile.lock")).not_to exist
end
@@ -95,11 +96,11 @@ describe "bundle install with gem sources" do
end
it "raises an appropriate error when gems are specified using symbols" do
- status = install_gemfile(<<-G, :exitstatus => true)
+ install_gemfile(<<-G)
source "file://#{gem_repo1}"
gem :rack
G
- expect(status).to eq(4)
+ expect(exitstatus).to eq(4) if exitstatus
end
it "pulls in dependencies" do
@@ -318,24 +319,24 @@ describe "bundle install with gem sources" do
FileUtils.mkdir_p(bundled_app(".bundle"))
FileUtils.touch(bundled_app(".bundle/config"))
- install_gemfile(<<-G, :exitstatus => true)
+ install_gemfile(<<-G)
source "file://#{gem_repo1}"
gem 'foo'
G
- expect(exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
end
it "doesn't blow up when the global .bundle/config is empty" do
FileUtils.mkdir_p("#{Bundler.rubygems.user_home}/.bundle")
FileUtils.touch("#{Bundler.rubygems.user_home}/.bundle/config")
- install_gemfile(<<-G, :exitstatus => true)
+ install_gemfile(<<-G)
source "file://#{gem_repo1}"
gem 'foo'
G
- expect(exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
end
end
@@ -356,9 +357,9 @@ describe "bundle install with gem sources" do
file.puts gemfile
end
- bundle :install, :exitstatus => true
+ bundle :install
- expect(exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
end
end
diff --git a/spec/install/gems/sources_spec.rb b/spec/install/gems/sources_spec.rb
index 86d23c4ed2..731f1402e5 100644
--- a/spec/install/gems/sources_spec.rb
+++ b/spec/install/gems/sources_spec.rb
@@ -15,7 +15,7 @@ describe "bundle install with gems on multiple sources" do
end
end
- context "when the same version of the same gem is in multiple sources" do
+ context "with multiple toplevel sources" do
let(:repo3_rack_version) { "1.0.0" }
before do
@@ -30,10 +30,18 @@ describe "bundle install with gems on multiple sources" do
it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first" do
bundle :install
+ expect(out).to include("Warning: this Gemfile contains multiple primary sources.")
expect(out).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(out).to include("Installed from: file:#{gem_repo1}")
should_be_installed("rack-obama 1.0.0", "rack 1.0.0")
end
+
+ it "errors when disable_multisource is set" do
+ bundle "config disable_multisource true"
+ bundle :install
+ expect(out).to include("Each source after the first must include a block")
+ expect(exitstatus).to eq(14) if exitstatus
+ end
end
context "when different versions of the same gem are in multiple sources" do
@@ -51,6 +59,7 @@ describe "bundle install with gems on multiple sources" do
it "warns about ambiguous gems, but installs anyway" do
bundle :install
+ expect(out).to include("Warning: this Gemfile contains multiple primary sources.")
expect(out).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(out).to include("Installed from: file:#{gem_repo1}")
should_be_installed("rack-obama 1.0.0", "rack 1.0.0")
@@ -91,9 +100,9 @@ describe "bundle install with gems on multiple sources" do
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/rack-obama-1.0.gem")).to exist
- bundle "install --deployment", :exitstatus => true
+ bundle "install --deployment"
- expect(exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
should_be_installed("rack-obama 1.0.0", "rack 1.0.0")
end
end
@@ -214,6 +223,7 @@ describe "bundle install with gems on multiple sources" do
it "installs from the other source and warns about ambiguous gems" do
bundle :install
+ expect(out).to include("Warning: this Gemfile contains multiple primary sources.")
expect(out).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(out).to include("Installed from: file:#{gem_repo2}")
should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0")
@@ -305,6 +315,26 @@ describe "bundle install with gems on multiple sources" do
should_be_installed("rack 0.9.1")
end
end
+
+ context "with a path gem in the same Gemfile" do
+ before do
+ build_lib "foo"
+
+ gemfile <<-G
+ gem "rack", :source => "file://#{gem_repo1}"
+ gem "foo", :path => "#{lib_path('foo-1.0')}"
+ G
+ end
+
+ it "does not unlock the non-path gem after install" do
+ bundle :install
+
+ bundle %{exec ruby -e 'puts "OK"'}
+
+ expect(out).to include("OK")
+ expect(exitstatus).to eq(0) if exitstatus
+ end
+ end
end
context "when an older version of the same gem also ships with Ruby" do
diff --git a/spec/install/gems/standalone_spec.rb b/spec/install/gems/standalone_spec.rb
index c666120ad4..08a20a2a23 100644
--- a/spec/install/gems/standalone_spec.rb
+++ b/spec/install/gems/standalone_spec.rb
@@ -186,9 +186,9 @@ describe "bundle install --standalone" do
end
it "should run without errors" do
- bundle "install --standalone", :artifice => "endpoint", :exitstatus => true
+ bundle "install --standalone", :artifice => "endpoint"
- expect(@exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
end
it "still makes the gems available to normal bundler" do
diff --git a/spec/install/gems/win32_spec.rb b/spec/install/gems/win32_spec.rb
index 6224220281..6d1ac85675 100644
--- a/spec/install/gems/win32_spec.rb
+++ b/spec/install/gems/win32_spec.rb
@@ -16,11 +16,11 @@ describe "bundle install with win32-generated lockfile" do
f << " rack\r\n"
end
- install_gemfile <<-G, :exitstatus => true
+ install_gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
G
- expect(@exitstatus).to eq(0)
+ expect(exitstatus).to eq(0) if exitstatus
end
end
diff --git a/spec/install/path_spec.rb b/spec/install/path_spec.rb
index 2ddceb23d5..6c5e7e50ab 100644
--- a/spec/install/path_spec.rb
+++ b/spec/install/path_spec.rb
@@ -33,7 +33,7 @@ describe "bundle install" do
it "prints a warning to let the user know what has happened with bundle --path vendor/bundle" do
bundle "install --path vendor/bundle"
- expect(out).to include("It was installed into ./vendor")
+ expect(out).to include("gems are installed into ./vendor")
end
it "disallows --path vendor/bundle --system" do
diff --git a/spec/install/post_bundle_message_spec.rb b/spec/install/post_bundle_message_spec.rb
index 6bd4e8575d..78133d9283 100644
--- a/spec/install/post_bundle_message_spec.rb
+++ b/spec/install/post_bundle_message_spec.rb
@@ -14,9 +14,10 @@ describe "post bundle message" do
end
let(:bundle_show_message) {"Use `bundle show [gemname]` to see where a bundled gem is installed."}
- let(:bundle_deployment_message) {"It was installed into ./vendor"}
- let(:bundle_complete_message) {"Your bundle is complete!"}
- let(:bundle_updated_message) {"Your bundle is updated!"}
+ let(:bundle_deployment_message) {"Bundled gems are installed into ./vendor"}
+ let(:bundle_complete_message) {"Bundle complete!"}
+ let(:bundle_updated_message) {"Bundle updated!"}
+ let(:installed_gems_stats) {"4 Gemfile dependencies, 5 gems now installed."}
describe "for fresh bundle install" do
it "without any options" do
@@ -24,6 +25,7 @@ describe "post bundle message" do
expect(out).to include(bundle_show_message)
expect(out).not_to include("Gems in the group")
expect(out).to include(bundle_complete_message)
+ expect(out).to include(installed_gems_stats)
end
it "with --without one group" do
@@ -31,6 +33,7 @@ describe "post bundle message" do
expect(out).to include(bundle_show_message)
expect(out).to include("Gems in the group emo were not installed")
expect(out).to include(bundle_complete_message)
+ expect(out).to include(installed_gems_stats)
end
it "with --without two groups" do
@@ -38,6 +41,7 @@ describe "post bundle message" do
expect(out).to include(bundle_show_message)
expect(out).to include("Gems in the groups emo and test were not installed")
expect(out).to include(bundle_complete_message)
+ expect(out).to include("4 Gemfile dependencies, 3 gems now installed.")
end
it "with --without more groups" do
@@ -45,6 +49,7 @@ describe "post bundle message" do
expect(out).to include(bundle_show_message)
expect(out).to include("Gems in the groups emo, obama and test were not installed")
expect(out).to include(bundle_complete_message)
+ expect(out).to include("4 Gemfile dependencies, 2 gems now installed.")
end
describe "with --path and" do
@@ -84,6 +89,7 @@ describe "post bundle message" do
expect(out).to include(bundle_show_message)
expect(out).to_not include("Gems in the groups")
expect(out).to include(bundle_complete_message)
+ expect(out).to include(installed_gems_stats)
end
it "with --without one group" do
@@ -92,6 +98,7 @@ describe "post bundle message" do
expect(out).to include(bundle_show_message)
expect(out).to include("Gems in the group emo were not installed")
expect(out).to include(bundle_complete_message)
+ expect(out).to include(installed_gems_stats)
end
it "with --without two groups" do
diff --git a/spec/install/security_policy_spec.rb b/spec/install/security_policy_spec.rb
index 941e14de27..1f48cb9e5a 100644
--- a/spec/install/security_policy_spec.rb
+++ b/spec/install/security_policy_spec.rb
@@ -16,8 +16,8 @@ describe "policies with unsigned gems" do
it "will work after you try to deploy without a lock" do
bundle "install --deployment"
- bundle :install, :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle :install
+ expect(exitstatus).to eq(0) if exitstatus
should_be_installed "rack 1.0", "signed_gem 1.0"
end
@@ -38,8 +38,8 @@ describe "policies with unsigned gems" do
end
it "will succeed with no policy" do
- bundle "install", :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle "install"
+ expect(exitstatus).to eq(0) if exitstatus
end
end
@@ -64,14 +64,14 @@ describe "policies with signed gems and no CA" do
end
it "will succeed with Low Security setting, low security accepts self signed gem" do
- bundle "install --trust-policy=LowSecurity", :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle "install --trust-policy=LowSecurity"
+ expect(exitstatus).to eq(0) if exitstatus
should_be_installed "signed_gem 1.0"
end
it "will succeed with no policy" do
- bundle "install", :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle "install"
+ expect(exitstatus).to eq(0) if exitstatus
should_be_installed "signed_gem 1.0"
end
end
diff --git a/spec/lock/lockfile_spec.rb b/spec/lock/lockfile_spec.rb
index 588d64308c..364b97181a 100644
--- a/spec/lock/lockfile_spec.rb
+++ b/spec/lock/lockfile_spec.rb
@@ -75,6 +75,7 @@ describe "the lockfile format" do
install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true)
source "http://localgemserver.test/"
+ source "http://user:pass@othergemserver.test/"
gem "rack-obama", ">= 1.0"
G
@@ -82,6 +83,7 @@ describe "the lockfile format" do
lockfile_should_be <<-G
GEM
remote: http://localgemserver.test/
+ remote: http://user:pass@othergemserver.test/
specs:
rack (1.0.0)
rack-obama (1.0)
diff --git a/spec/other/bundle_ruby_spec.rb b/spec/other/bundle_ruby_spec.rb
index 08d24ee71a..739c3d0ffb 100644
--- a/spec/other/bundle_ruby_spec.rb
+++ b/spec/other/bundle_ruby_spec.rb
@@ -63,7 +63,7 @@ describe "bundle_ruby" do
G
bundle_ruby :exitstatus => true
- expect(exitstatus).not_to eq(0)
+ expect(exitstatus).not_to eq(0) if exitstatus
bundle_ruby
expect(out).to eq("Please define :engine_version")
@@ -78,7 +78,7 @@ describe "bundle_ruby" do
G
bundle_ruby :exitstatus => true
- expect(exitstatus).not_to eq(0)
+ expect(exitstatus).not_to eq(0) if exitstatus
bundle_ruby
expect(out).to eq("Please define :engine")
@@ -93,7 +93,7 @@ describe "bundle_ruby" do
G
bundle_ruby :exitstatus => true
- expect(exitstatus).not_to eq(0)
+ expect(exitstatus).not_to eq(0) if exitstatus
bundle_ruby
expect(out).to eq("ruby_version must match the :engine_version for MRI")
diff --git a/spec/other/platform_spec.rb b/spec/other/platform_spec.rb
index 619b5c7fb3..13b57c135e 100644
--- a/spec/other/platform_spec.rb
+++ b/spec/other/platform_spec.rb
@@ -151,9 +151,9 @@ G
gem "foo"
G
- bundle "platform", :exitstatus => true
+ bundle "platform"
- expect(exitstatus).not_to eq(0)
+ expect(exitstatus).not_to eq(0) if exitstatus
end
it "raises an error if engine_version is used but engine is not" do
@@ -164,9 +164,9 @@ G
gem "foo"
G
- bundle "platform", :exitstatus => true
+ bundle "platform"
- expect(exitstatus).not_to eq(0)
+ expect(exitstatus).not_to eq(0) if exitstatus
end
it "raises an error if engine version doesn't match ruby version for MRI" do
@@ -177,9 +177,9 @@ G
gem "foo"
G
- bundle "platform", :exitstatus => true
+ bundle "platform"
- expect(exitstatus).not_to eq(0)
+ expect(exitstatus).not_to eq(0) if exitstatus
end
it "should print if no ruby version is specified" do
@@ -205,30 +205,28 @@ G
let(:patchlevel_incorrect) { "#{ruby_version_correct}, :patchlevel => '#{not_local_patchlevel}'" }
let(:patchlevel_fixnum) { "#{ruby_version_correct}, :patchlevel => #{RUBY_PATCHLEVEL}1" }
- def should_be_ruby_version_incorrect(opts = {:exitstatus => true})
- expect(exitstatus).to eq(18) if opts[:exitstatus]
+ def should_be_ruby_version_incorrect
+ expect(exitstatus).to eq(18) if exitstatus
expect(out).to be_include("Your Ruby version is #{RUBY_VERSION}, but your Gemfile specified #{not_local_ruby_version}")
end
- def should_be_engine_incorrect(opts = {:exitstatus => true})
- expect(exitstatus).to eq(18) if opts[:exitstatus]
+ def should_be_engine_incorrect
+ expect(exitstatus).to eq(18) if exitstatus
expect(out).to be_include("Your Ruby engine is #{local_ruby_engine}, but your Gemfile specified #{not_local_tag}")
end
- def should_be_engine_version_incorrect(opts = {:exitstatus => true})
- expect(exitstatus).to eq(18) if opts[:exitstatus]
+ def should_be_engine_version_incorrect
+ expect(exitstatus).to eq(18) if exitstatus
expect(out).to be_include("Your #{local_ruby_engine} version is #{local_engine_version}, but your Gemfile specified #{local_ruby_engine} #{not_local_engine_version}")
end
- def should_be_patchlevel_incorrect(opts = {:exitstatus => true})
- expect(exitstatus).to eq(18) if opts[:exitstatus]
-
+ def should_be_patchlevel_incorrect
+ expect(exitstatus).to eq(18) if exitstatus
expect(out).to be_include("Your Ruby patchlevel is #{RUBY_PATCHLEVEL}, but your Gemfile specified #{not_local_patchlevel}")
end
- def should_be_patchlevel_fixnum(opts = {:exitstatus => true})
- expect(exitstatus).to eq(18) if opts[:exitstatus]
-
+ def should_be_patchlevel_fixnum
+ expect(exitstatus).to eq(18) if exitstatus
expect(out).to be_include("The Ruby patchlevel in your Gemfile must be a string")
end
@@ -269,7 +267,7 @@ G
end
it "doesn't install when the ruby version doesn't match" do
- install_gemfile <<-G, :exitstatus => true
+ install_gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
@@ -281,7 +279,7 @@ G
end
it "doesn't install when engine doesn't match" do
- install_gemfile <<-G, :exitstatus => true
+ install_gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
@@ -294,7 +292,7 @@ G
it "doesn't install when engine version doesn't match" do
simulate_ruby_engine "jruby" do
- install_gemfile <<-G, :exitstatus => true
+ install_gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
@@ -307,7 +305,7 @@ G
end
it "doesn't install when patchlevel doesn't match" do
- install_gemfile <<-G, :exitstatus => true
+ install_gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
@@ -333,8 +331,8 @@ G
#{ruby_version_correct}
G
- bundle :check, :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle :check
+ expect(exitstatus).to eq(0) if exitstatus
expect(out).to eq("The Gemfile's dependencies are satisfied")
end
@@ -352,8 +350,8 @@ G
#{ruby_version_correct_engineless}
G
- bundle :check, :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle :check
+ expect(exitstatus).to eq(0) if exitstatus
expect(out).to eq("The Gemfile's dependencies are satisfied")
end
end
@@ -371,7 +369,7 @@ G
#{ruby_version_incorrect}
G
- bundle :check, :exitstatus => true
+ bundle :check
should_be_ruby_version_incorrect
end
@@ -388,7 +386,7 @@ G
#{engine_incorrect}
G
- bundle :check, :exitstatus => true
+ bundle :check
should_be_engine_incorrect
end
@@ -406,13 +404,13 @@ G
#{engine_version_incorrect}
G
- bundle :check, :exitstatus => true
+ bundle :check
should_be_engine_version_incorrect
end
end
it "fails when patchlevel doesn't match" do
- install_gemfile <<-G, :exitstatus => true
+ install_gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
G
@@ -424,7 +422,7 @@ G
#{patchlevel_incorrect}
G
- bundle :check, :exitstatus => true
+ bundle :check
should_be_patchlevel_incorrect
end
end
@@ -486,7 +484,7 @@ G
build_gem "activesupport", "3.0"
end
- bundle :update, :exitstatus => true
+ bundle :update
should_be_ruby_version_incorrect
end
@@ -502,7 +500,7 @@ G
build_gem "activesupport", "3.0"
end
- bundle :update, :exitstatus => true
+ bundle :update
should_be_engine_incorrect
end
@@ -519,13 +517,13 @@ G
build_gem "activesupport", "3.0"
end
- bundle :update, :exitstatus => true
+ bundle :update
should_be_engine_version_incorrect
end
end
it "fails when patchlevel doesn't match" do
- gemfile <<-G, :exitstatus => true
+ gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
@@ -535,7 +533,7 @@ G
build_gem "activesupport", "3.0"
end
- bundle :update, :exitstatus => true
+ bundle :update
should_be_patchlevel_incorrect
end
end
@@ -582,7 +580,7 @@ G
#{ruby_version_incorrect}
G
- bundle "show rails", :exitstatus => true
+ bundle "show rails"
should_be_ruby_version_incorrect
end
@@ -594,7 +592,7 @@ G
#{engine_incorrect}
G
- bundle "show rails", :exitstatus => true
+ bundle "show rails"
should_be_engine_incorrect
end
@@ -607,13 +605,13 @@ G
#{engine_version_incorrect}
G
- bundle "show rails", :exitstatus => true
+ bundle "show rails"
should_be_engine_version_incorrect
end
end
it "fails when patchlevel doesn't match" do
- gemfile <<-G, :exitstatus => true
+ gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
@@ -623,7 +621,7 @@ G
build_gem "activesupport", "3.0"
end
- bundle "show rails", :exitstatus => true
+ bundle "show rails"
should_be_patchlevel_incorrect
end
end
@@ -668,7 +666,7 @@ G
#{ruby_version_incorrect}
G
- bundle :cache, :exitstatus => true
+ bundle :cache
should_be_ruby_version_incorrect
end
@@ -679,7 +677,7 @@ G
#{engine_incorrect}
G
- bundle :cache, :exitstatus => true
+ bundle :cache
should_be_engine_incorrect
end
@@ -691,20 +689,20 @@ G
#{engine_version_incorrect}
G
- bundle :cache, :exitstatus => true
+ bundle :cache
should_be_engine_version_incorrect
end
end
it "fails when patchlevel doesn't match" do
- gemfile <<-G, :exitstatus => true
+ gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
#{patchlevel_incorrect}
G
- bundle :cache, :exitstatus => true
+ bundle :cache
should_be_patchlevel_incorrect
end
end
@@ -749,7 +747,7 @@ G
#{ruby_version_incorrect}
G
- bundle :pack, :exitstatus => true
+ bundle :pack
should_be_ruby_version_incorrect
end
@@ -760,7 +758,7 @@ G
#{engine_incorrect}
G
- bundle :pack, :exitstatus => true
+ bundle :pack
should_be_engine_incorrect
end
@@ -772,26 +770,27 @@ G
#{engine_version_incorrect}
G
- bundle :pack, :exitstatus => true
+ bundle :pack
should_be_engine_version_incorrect
end
end
it "fails when patchlevel doesn't match" do
- gemfile <<-G, :exitstatus => true
+ gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
#{patchlevel_incorrect}
G
- bundle :pack, :exitstatus => true
+ bundle :pack
should_be_patchlevel_incorrect
end
end
context "bundle exec" do
before do
+ ENV["BUNDLER_FORCE_TTY"] = "true"
system_gems "rack-1.0.0", "rack-0.9.1"
end
@@ -826,7 +825,7 @@ G
#{ruby_version_incorrect}
G
- bundle "exec rackup", :exitstatus => true
+ bundle "exec rackup"
should_be_ruby_version_incorrect
end
@@ -837,32 +836,32 @@ G
#{engine_incorrect}
G
- bundle "exec rackup", :exitstatus => true
+ bundle "exec rackup"
should_be_engine_incorrect
end
- it "fails when the engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- gem "rack", "0.9.1"
-
- #{engine_version_incorrect}
- G
-
- bundle "exec rackup", :exitstatus => true
- should_be_engine_version_incorrect
- end
- end
+ # it "fails when the engine version doesn't match" do
+ # simulate_ruby_engine "jruby" do
+ # gemfile <<-G
+ # gem "rack", "0.9.1"
+ #
+ # #{engine_version_incorrect}
+ # G
+ #
+ # bundle "exec rackup"
+ # should_be_engine_version_incorrect
+ # end
+ # end
it "fails when patchlevel doesn't match" do
- gemfile <<-G, :exitstatus => true
+ gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
#{patchlevel_incorrect}
G
- bundle "exec rackup", :exitstatus => true
+ bundle "exec rackup"
should_be_patchlevel_incorrect
end
end
@@ -923,7 +922,7 @@ G
#{ruby_version_incorrect}
G
- bundle "console", :exitstatus => true
+ bundle "console"
should_be_ruby_version_incorrect
end
@@ -937,7 +936,7 @@ G
#{engine_incorrect}
G
- bundle "console", :exitstatus => true
+ bundle "console"
should_be_engine_incorrect
end
@@ -952,13 +951,13 @@ G
#{engine_version_incorrect}
G
- bundle "console", :exitstatus => true
+ bundle "console"
should_be_engine_version_incorrect
end
end
it "fails when patchlevel doesn't match" do
- gemfile <<-G, :exitstatus => true
+ gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
gem "activesupport", :group => :test
@@ -967,7 +966,7 @@ G
#{patchlevel_incorrect}
G
- bundle "console", :exitstatus => true
+ bundle "console"
should_be_patchlevel_incorrect
end
end
@@ -979,6 +978,8 @@ G
gem "yard"
gem "rack", :group => :test
G
+
+ ENV['BUNDLER_FORCE_TTY'] = "true"
end
it "makes a Gemfile.lock if setup succeeds" do
@@ -990,8 +991,6 @@ G
#{ruby_version_correct}
G
- File.read(bundled_app("Gemfile.lock"))
-
FileUtils.rm(bundled_app("Gemfile.lock"))
run "1"
@@ -1008,8 +1007,6 @@ G
#{ruby_version_correct_engineless}
G
- File.read(bundled_app("Gemfile.lock"))
-
FileUtils.rm(bundled_app("Gemfile.lock"))
run "1"
@@ -1026,23 +1023,15 @@ G
#{ruby_version_incorrect}
G
- File.read(bundled_app("Gemfile.lock"))
-
FileUtils.rm(bundled_app("Gemfile.lock"))
ruby <<-R
require 'rubygems'
- require 'bundler'
-
- begin
- Bundler.setup
- rescue Bundler::RubyVersionMismatch => e
- puts e.message
- end
+ require 'bundler/setup'
R
expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_ruby_version_incorrect(:exitstatus => false)
+ should_be_ruby_version_incorrect
end
it "fails when engine doesn't match" do
@@ -1054,23 +1043,15 @@ G
#{engine_incorrect}
G
- File.read(bundled_app("Gemfile.lock"))
-
FileUtils.rm(bundled_app("Gemfile.lock"))
ruby <<-R
require 'rubygems'
- require 'bundler'
-
- begin
- Bundler.setup
- rescue Bundler::RubyVersionMismatch => e
- puts e.message
- end
+ require 'bundler/setup'
R
expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_engine_incorrect(:exitstatus => false)
+ should_be_engine_incorrect
end
it "fails when engine version doesn't match" do
@@ -1083,23 +1064,15 @@ G
#{engine_version_incorrect}
G
- File.read(bundled_app("Gemfile.lock"))
-
FileUtils.rm(bundled_app("Gemfile.lock"))
ruby <<-R
require 'rubygems'
- require 'bundler'
-
- begin
- Bundler.setup
- rescue Bundler::RubyVersionMismatch => e
- puts e.message
- end
+ require 'bundler/setup'
R
expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_engine_version_incorrect(:exitstatus => false)
+ should_be_engine_version_incorrect
end
end
@@ -1112,24 +1085,15 @@ G
#{patchlevel_incorrect}
G
- puts File.read(bundled_app("Gemfile"))
- File.read(bundled_app("Gemfile.lock"))
-
FileUtils.rm(bundled_app("Gemfile.lock"))
ruby <<-R
require 'rubygems'
- require 'bundler'
-
- begin
- Bundler.setup
- rescue Bundler::RubyVersionMismatch => e
- puts e.message
- end
+ require 'bundler/setup'
R
expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_patchlevel_incorrect(:exitstatus => false)
+ should_be_patchlevel_incorrect
end
end
@@ -1200,7 +1164,7 @@ G
#{ruby_version_incorrect}
G
- bundle "outdated", :exitstatus => true
+ bundle "outdated"
should_be_ruby_version_incorrect
end
@@ -1218,7 +1182,7 @@ G
#{engine_incorrect}
G
- bundle "outdated", :exitstatus => true
+ bundle "outdated"
should_be_engine_incorrect
end
@@ -1237,7 +1201,7 @@ G
#{engine_version_incorrect}
G
- bundle "outdated", :exitstatus => true
+ bundle "outdated"
should_be_engine_version_incorrect
end
end
@@ -1257,7 +1221,7 @@ G
#{patchlevel_incorrect}
G
- bundle "outdated", :exitstatus => true
+ bundle "outdated"
should_be_patchlevel_incorrect
end
end
@@ -1277,7 +1241,7 @@ G
#{patchlevel_fixnum}
G
- bundle "outdated", :exitstatus => true
+ bundle "outdated"
should_be_patchlevel_fixnum
end
end
diff --git a/spec/quality_spec.rb b/spec/quality_spec.rb
index 59a8520066..de3bdc6a57 100644
--- a/spec/quality_spec.rb
+++ b/spec/quality_spec.rb
@@ -1,14 +1,15 @@
require "spec_helper"
-if defined?(Encoding) && Encoding.default_external != "UTF-8"
- Encoding.default_external = "UTF-8"
+if defined?(Encoding) && Encoding.default_external.name != "UTF-8"
+ # Poor man's ruby -E UTF-8, since it works on 1.8.7
+ Encoding.default_external = Encoding.find("UTF-8")
end
describe "The library itself" do
def check_for_spec_defs_with_single_quotes(filename)
failing_lines = []
- File.readlines(filename).each_with_index do |line,number|
+ File.readlines(filename).each_with_index do |line, number|
failing_lines << number + 1 if line =~ /^ *(describe|it|context) {1}'{1}/
end
@@ -19,7 +20,7 @@ describe "The library itself" do
def check_for_tab_characters(filename)
failing_lines = []
- File.readlines(filename).each_with_index do |line,number|
+ File.readlines(filename).each_with_index do |line, number|
failing_lines << number + 1 if line =~ /\t/
end
@@ -30,7 +31,7 @@ describe "The library itself" do
def check_for_extra_spaces(filename)
failing_lines = []
- File.readlines(filename).each_with_index do |line,number|
+ File.readlines(filename).each_with_index do |line, number|
next if line =~ /^\s+#.*\s+\n$/
next if %w(LICENCE.md).include?(line)
failing_lines << number + 1 if line =~ /\s+\n$/
@@ -85,4 +86,18 @@ describe "The library itself" do
system("rm bundler-#{Bundler::VERSION}.gem")
end
end
+
+ it "does not contain any warnings" do
+ Dir.chdir(root.join("lib"))
+ exclusions = /bundler\/capistrano\.rb|bundler\/vlad\.rb|bundler\/gem_tasks\.rb|tmp\/rubygems/
+ lib_files = `git ls-files -z -- **/*.rb`.split("\x0").reject{|f| f =~ exclusions }
+ sys_exec("ruby -w -I. ", :expect_err) do |input|
+ lib_files.each do |f|
+ input.puts "require '#{f.gsub(/\.rb$/, '')}'"
+ end
+ end
+
+ expect(@err).to eq("")
+ expect(@out).to eq("")
+ end
end
diff --git a/spec/realworld/edgecases_spec.rb b/spec/realworld/edgecases_spec.rb
index 38f8eaae72..15c7697564 100644
--- a/spec/realworld/edgecases_spec.rb
+++ b/spec/realworld/edgecases_spec.rb
@@ -206,7 +206,7 @@ describe "real world edgecases", :realworld => true do
activesupport!
L
- bundle :install, :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle :install
+ expect(exitstatus).to eq(0) if exitstatus
end
end
diff --git a/spec/realworld/parallel_spec.rb b/spec/realworld/parallel_spec.rb
index 9f65dbb705..d447786158 100644
--- a/spec/realworld/parallel_spec.rb
+++ b/spec/realworld/parallel_spec.rb
@@ -10,7 +10,12 @@ describe "parallel", :realworld => true do
G
bundle :install, :jobs => 4, :env => {"DEBUG" => "1"}
- expect(out).to match(/[1-3]: /)
+
+ if Bundler.rubygems.provides?(">= 2.1.0")
+ expect(out).to match(/[1-3]: /)
+ else
+ expect(out).to include("is not threadsafe")
+ end
bundle "show activesupport"
expect(out).to match(/activesupport/)
@@ -30,7 +35,12 @@ describe "parallel", :realworld => true do
G
bundle :install, :jobs => 4, :env => {"DEBUG" => "1"}
- expect(out).to match(/[1-3]: /)
+
+ if Bundler.rubygems.provides?(">= 2.1.0")
+ expect(out).to match(/[1-3]: /)
+ else
+ expect(out).to include("is not threadsafe")
+ end
bundle "show activesupport"
expect(out).to match(/activesupport/)
@@ -57,7 +67,12 @@ describe "parallel", :realworld => true do
G
bundle :update, :jobs => 4, :env => {"DEBUG" => "1"}
- expect(out).to match(/[1-3]: /)
+
+ if Bundler.rubygems.provides?(">= 2.1.0")
+ expect(out).to match(/[1-3]: /)
+ else
+ expect(out).to include("is not threadsafe")
+ end
bundle "show activesupport"
expect(out).to match(/activesupport-3\.2\.\d+/)
@@ -68,4 +83,23 @@ describe "parallel", :realworld => true do
bundle "config jobs"
expect(out).to match(/: "4"/)
end
+
+ it "works with --standalone" do
+ gemfile <<-G, :standalone => true
+ source "https://rubygems.org"
+ gem "diff-lcs"
+ G
+
+ bundle :install, :standalone => true, :jobs => 4
+
+ ruby <<-RUBY, :no_lib => true
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ require "diff/lcs"
+ puts Diff::LCS
+ RUBY
+
+ expect(out).to eq("Diff::LCS")
+ end
end
diff --git a/spec/runtime/load_spec.rb b/spec/runtime/load_spec.rb
index cc2cebf8e5..358e3021e8 100644
--- a/spec/runtime/load_spec.rb
+++ b/spec/runtime/load_spec.rb
@@ -34,7 +34,23 @@ describe "Bundler.load" do
Bundler.load
}.not_to raise_error()
end
+ end
+
+ describe "with a gems.rb file" do
+ before(:each) do
+ create_file "gems.rb", <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+ end
+ it "provides a list of the env dependencies" do
+ expect(Bundler.load.dependencies).to have_dep("rack", ">= 0")
+ end
+
+ it "provides a list of the resolved gems" do
+ expect(Bundler.load.gems).to have_gem("rack-1.0.0", "bundler-#{Bundler::VERSION}")
+ end
end
describe "without a gemfile" do
diff --git a/spec/runtime/require_spec.rb b/spec/runtime/require_spec.rb
index e1c93897a5..5e5e9db22f 100644
--- a/spec/runtime/require_spec.rb
+++ b/spec/runtime/require_spec.rb
@@ -98,6 +98,28 @@ describe "Bundler.require" do
expect(err).to eq("ZOMG LOAD ERROR")
end
+ it "doesn't swallow the error when the library has an unrelated error" do
+ build_lib "loadfuuu", "1.0.0" do |s|
+ s.write "lib/loadfuuu.rb", "raise LoadError.new(\"cannot load such file -- load-bar\")"
+ end
+
+ gemfile <<-G
+ path "#{lib_path}"
+ gem "loadfuuu"
+ G
+
+ cmd = <<-RUBY
+ begin
+ Bundler.require
+ rescue LoadError => e
+ $stderr.puts "ZOMG LOAD ERROR: \#{e.message}"
+ end
+ RUBY
+ run(cmd, :expect_err => true)
+
+ expect(err).to eq("ZOMG LOAD ERROR: cannot load such file -- load-bar")
+ end
+
describe "with namespaced gems" do
before :each do
build_lib "jquery-rails", "1.0.0" do |s|
@@ -170,8 +192,9 @@ describe "Bundler.require" do
it "doesn't swallow the error when the library has an unrelated error" do
build_lib "load-fuuu", "1.0.0" do |s|
- s.write "lib/load-fuuu.rb", "raise LoadError.new(\"cannot load such file -- load-bar\")"
+ s.write "lib/load/fuuu.rb", "raise LoadError.new(\"cannot load such file -- load-bar\")"
end
+ lib_path('load-fuuu-1.0.0/lib/load-fuuu.rb').rmtree
gemfile <<-G
path "#{lib_path}"
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index e55a72bcf0..d14f3005cd 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,12 +1,20 @@
$:.unshift File.expand_path('..', __FILE__)
$:.unshift File.expand_path('../../lib', __FILE__)
-# stdlib first
+
+require 'bundler/psyched_yaml'
+require 'fileutils'
require 'uri'
require 'digest/sha1'
-require 'fileutils'
-require 'bundler/psyched_yaml'
-require 'rubygems'
-require 'rspec'
+
+begin
+ require 'rubygems'
+ spec = Gem::Specification.load("bundler.gemspec")
+ gem 'rspec', spec.dependencies.last.requirement.to_s
+ require 'rspec'
+rescue LoadError
+ abort "Run rake spec:deps to install development dependencies"
+end
+
require 'bundler'
# Require the correct version of popen for the current platform
@@ -58,29 +66,12 @@ RSpec.configure do |config|
config.filter_run_excluding :realworld => true
end
- if RUBY_VERSION >= "1.9"
- config.filter_run_excluding :ruby => "1.8"
- else
- config.filter_run_excluding :ruby => "1.9"
- end
-
- if RUBY_VERSION >= "2.0"
- config.filter_run_excluding :ruby => "1.8"
- config.filter_run_excluding :ruby => "1.9"
- else
- config.filter_run_excluding :ruby => "2.0"
- config.filter_run_excluding :ruby => "2.1"
- end
-
- if Gem::VERSION < "2.2"
- config.filter_run_excluding :rubygems => "2.2"
- end
-
+ config.filter_run_excluding :ruby => LessThanProc.with(RUBY_VERSION)
+ config.filter_run_excluding :rubygems => LessThanProc.with(Gem::VERSION)
config.filter_run_excluding :rubygems_master => (ENV['RGV'] != "master")
config.filter_run :focused => true unless ENV['CI']
config.run_all_when_everything_filtered = true
- config.alias_example_to :fit, :focused => true
original_wd = Dir.pwd
original_path = ENV['PATH']
@@ -109,15 +100,15 @@ RSpec.configure do |config|
Dir.chdir(original_wd)
# Reset ENV
- ENV['PATH'] = original_path
- ENV['GEM_HOME'] = original_gem_home
- ENV['GEM_PATH'] = original_gem_home
- ENV['BUNDLE_PATH'] = nil
- ENV['BUNDLE_GEMFILE'] = nil
- ENV['BUNDLER_TEST'] = nil
- ENV['BUNDLE_FROZEN'] = nil
+ ENV['PATH'] = original_path
+ ENV['GEM_HOME'] = original_gem_home
+ ENV['GEM_PATH'] = original_gem_home
+ ENV['BUNDLE_PATH'] = nil
+ ENV['BUNDLE_GEMFILE'] = nil
+ ENV['BUNDLE_FROZEN'] = nil
+ ENV['BUNDLE_APP_CONFIG'] = nil
+ ENV['BUNDLER_TEST'] = nil
ENV['BUNDLER_SPEC_PLATFORM'] = nil
ENV['BUNDLER_SPEC_VERSION'] = nil
- ENV['BUNDLE_APP_CONFIG'] = nil
end
end
diff --git a/spec/support/builders.rb b/spec/support/builders.rb
index 1b2670b4ab..1a1c916779 100644
--- a/spec/support/builders.rb
+++ b/spec/support/builders.rb
@@ -636,7 +636,7 @@ module Spec
end
end
- TEST_CERT = <<-CERT.gsub /^\s*/, ''
+ TEST_CERT = <<-CERT.gsub(/^\s*/, '')
-----BEGIN CERTIFICATE-----
MIIDMjCCAhqgAwIBAgIBATANBgkqhkiG9w0BAQUFADAnMQwwCgYDVQQDDAN5b3Ux
FzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTE1MDIwODAwMTIyM1oXDTQyMDYy
@@ -659,7 +659,7 @@ module Spec
-----END CERTIFICATE-----
CERT
- TEST_PKEY = <<-PKEY.gsub /^\s*/, ''
+ TEST_PKEY = <<-PKEY.gsub(/^\s*/, '')
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA2W8V2k3jdzgMxL0mjTqbRruTdtDcdZDXKtiFkyLvsXUXvc2k
GSdgcjMOS1CkafqGz/hAUlPibjM0QEXjtQuMdTmdMrmuORLeeIZhSO+HdkTNV6j3
diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb
index 7eb2ebd979..e5774f12a3 100644
--- a/spec/support/helpers.rb
+++ b/spec/support/helpers.rb
@@ -4,10 +4,10 @@ module Spec
@in_p, @out_p, @err_p = nil, nil, nil
Dir["#{tmp}/{gems/*,*}"].each do |dir|
next if %(base remote1 gems rubygems).include?(File.basename(dir))
- unless ENV['BUNDLER_SUDO_TESTS']
- FileUtils.rm_rf(dir)
- else
+ if ENV['BUNDLER_SUDO_TESTS']
`sudo rm -rf #{dir}`
+ else
+ FileUtils.rm_rf(dir)
end
end
FileUtils.mkdir_p(tmp)
@@ -57,7 +57,6 @@ module Spec
def bundle(cmd, options = {})
expect_err = options.delete(:expect_err)
- exitstatus = options.delete(:exitstatus)
sudo = "sudo" if options.delete(:sudo)
options["no-color"] = true unless options.key?("no-color") || %w(exec conf).include?(cmd.to_s[0..3])
@@ -68,23 +67,17 @@ module Spec
requires << File.expand_path('../artifice/'+options.delete(:artifice)+'.rb', __FILE__) if options.key?(:artifice)
requires_str = requires.map{|r| "-r#{r}"}.join(" ")
- env = (options.delete(:env) || {}).map{|k,v| "#{k}='#{v}'"}.join(" ")
- args = options.map do |k,v|
+ env = (options.delete(:env) || {}).map{|k, v| "#{k}='#{v}'"}.join(" ")
+ args = options.map do |k, v|
v == true ? " --#{k}" : " --#{k} #{v}" if v
end.join
cmd = "#{env} #{sudo} #{Gem.ruby} -I#{lib} #{requires_str} #{bundle_bin} #{cmd}#{args}"
-
- if exitstatus
- sys_status(cmd)
- else
- sys_exec(cmd, expect_err){|i| yield i if block_given? }
- end
+ sys_exec(cmd, expect_err){|i| yield i if block_given? }
end
def bundle_ruby(options = {})
- expect_err = options.delete(:expect_err)
- exitstatus = options.delete(:exitstatus)
+ expect_err = options.delete(:expect_err)
options["no-color"] = true unless options.key?("no-color")
bundle_bin = File.expand_path('../../../bin/bundle_ruby', __FILE__)
@@ -94,19 +87,15 @@ module Spec
requires << File.expand_path('../artifice/'+options.delete(:artifice)+'.rb', __FILE__) if options.key?(:artifice)
requires_str = requires.map{|r| "-r#{r}"}.join(" ")
- env = (options.delete(:env) || {}).map{|k,v| "#{k}='#{v}' "}.join
+ env = (options.delete(:env) || {}).map{|k, v| "#{k}='#{v}' "}.join
cmd = "#{env}#{Gem.ruby} -I#{lib} #{requires_str} #{bundle_bin}"
- if exitstatus
- sys_status(cmd)
- else
- sys_exec(cmd, expect_err){|i| yield i if block_given? }
- end
+ sys_exec(cmd, expect_err){|i| yield i if block_given? }
end
def ruby(ruby, options = {})
expect_err = options.delete(:expect_err)
- env = (options.delete(:env) || {}).map{|k,v| "#{k}='#{v}' "}.join
+ env = (options.delete(:env) || {}).map{|k, v| "#{k}='#{v}' "}.join
ruby.gsub!(/["`\$]/) {|m| "\\#{m}" }
lib_option = options[:no_lib] ? "" : " -I#{lib}"
sys_exec(%{#{env}#{Gem.ruby}#{lib_option} -e "#{ruby}"}, expect_err)
@@ -133,7 +122,7 @@ module Spec
end
def sys_exec(cmd, expect_err = false)
- Open3.popen3(cmd.to_s) do |stdin, stdout, stderr|
+ Open3.popen3(cmd.to_s) do |stdin, stdout, stderr, wait_thr|
@in_p, @out_p, @err_p = stdin, stdout, stderr
yield @in_p if block_given?
@@ -141,18 +130,13 @@ module Spec
@out = @out_p.read_available_bytes.strip
@err = @err_p.read_available_bytes.strip
+ @exitstatus = wait_thr && wait_thr.value.exitstatus
end
puts @err unless expect_err || @err.empty? || !$show_err
@out
end
- def sys_status(cmd)
- @err = nil
- @out = %x{#{cmd}}.strip
- @exitstatus = $?.exitstatus
- end
-
def config(config = nil, path = bundled_app('.bundle/config'))
return YAML.load_file(path) unless config
FileUtils.mkdir_p(File.dirname(path))
@@ -166,14 +150,6 @@ module Spec
config(config, home(".bundle/config"))
end
- def gemfile(*args)
- create_file("Gemfile", *args)
- end
-
- def lockfile(*args)
- create_file("Gemfile.lock", *args)
- end
-
def create_file(*args)
path = bundled_app(args.shift)
path = args.shift if args.first.is_a?(Pathname)
@@ -184,6 +160,14 @@ module Spec
end
end
+ def gemfile(*args)
+ create_file("Gemfile", *args)
+ end
+
+ def lockfile(*args)
+ create_file("Gemfile.lock", *args)
+ end
+
def strip_whitespace(str)
# Trim the leading spaces
spaces = str[/\A\s+/, 0] || ""
@@ -217,6 +201,14 @@ module Spec
ENV['GEM_HOME'], ENV['GEM_PATH'] = gem_home, gem_path
end
+ def with_path_as(path)
+ old_path = ENV['PATH']
+ ENV['PATH'] = "#{path}:#{ENV['PATH']}"
+ yield
+ ensure
+ ENV['PATH'] = old_path
+ end
+
def break_git!
FileUtils.mkdir_p(tmp("broken_path"))
File.open(tmp("broken_path/git"), "w", 0755) do |f|
@@ -357,5 +349,12 @@ module Spec
ensure
Dir[pattern].each(&chmod[0755, 0644])
end
+
+ def process_file(pathname)
+ changed_lines = pathname.readlines.map do |line|
+ yield line
+ end
+ File.open(pathname, 'w') { |file| file.puts(changed_lines.join) }
+ end
end
end
diff --git a/spec/support/less_than_proc.rb b/spec/support/less_than_proc.rb
new file mode 100644
index 0000000000..af80d82c4e
--- /dev/null
+++ b/spec/support/less_than_proc.rb
@@ -0,0 +1,14 @@
+class LessThanProc < Proc
+ attr_accessor :present
+
+ def self.with(present)
+ pv = Gem::Version.new(present.dup)
+ lt = self.new { |required| pv < Gem::Version.new(required) }
+ lt.present = present
+ return lt
+ end
+
+ def inspect
+ "\"=< #{present.to_s}\""
+ end
+end
diff --git a/spec/update/gems_spec.rb b/spec/update/gems_spec.rb
index 856e922642..ed503e3607 100644
--- a/spec/update/gems_spec.rb
+++ b/spec/update/gems_spec.rb
@@ -58,11 +58,11 @@ describe "bundle update" do
describe "with an unknown dependency" do
it "should inform the user" do
- bundle "update halting-problem-solver", :expect_err=>true
+ bundle "update halting-problem-solver", :expect_err =>true
expect(out).to include "Could not find gem 'halting-problem-solver'"
end
it "should suggest alternatives" do
- bundle "update active-support", :expect_err=>true
+ bundle "update active-support", :expect_err =>true
expect(out).to include "Did you mean activesupport?"
end
end
@@ -194,8 +194,8 @@ describe "bundle update" do
gem "activesupport"
G
- bundle "update nonexisting", :exitstatus => true
+ bundle "update nonexisting"
expect(out).to include("This Bundle hasn't been installed yet. Run `bundle install` to update and install the bundled gems.")
- expect(@exitstatus).to eq(22)
+ expect(exitstatus).to eq(22) if exitstatus
end
end
diff --git a/spec/update/git_spec.rb b/spec/update/git_spec.rb
index 2452636c10..9f5e71b3e2 100644
--- a/spec/update/git_spec.rb
+++ b/spec/update/git_spec.rb
@@ -91,7 +91,7 @@ describe "bundle update" do
expect(err).to be_empty
expect(out).to include("Fetching #{lib_path}/foo_two")
- expect(out).to include("Your bundle is complete!")
+ expect(out).to include("Bundle complete!")
end
@@ -113,8 +113,8 @@ describe "bundle update" do
gem 'foo', :git => "#{@remote.path}", :tag => "fubar"
G
- bundle "update", :exitstatus => true
- expect(exitstatus).to eq(0)
+ bundle "update"
+ expect(exitstatus).to eq(0) if exitstatus
end
describe "with submodules" do
@@ -206,7 +206,7 @@ describe "bundle update" do
bundle %|config local.rack #{lib_path('local-rack')}|
bundle "update rack"
- expect(out).to include("Your bundle is updated!")
+ expect(out).to include("Bundle updated!")
end
it "shows the previous version of the gem" do