commit 6cfe2d1bf4ac89a6d937f7953551e6c34c8e56db Author: BOHUNG Date: Sun Oct 6 23:45:34 2019 +0800 original version diff --git a/bundler-1.7.2/.gitignore b/bundler-1.7.2/.gitignore new file mode 100644 index 0000000..874a3b8 --- /dev/null +++ b/bundler-1.7.2/.gitignore @@ -0,0 +1,25 @@ +# Please do not submit patches for including directives to ignore IDE/editor +# generated files. Use a global gitignore as described in +# 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 + +# rubinius bytecode +*.rbc +.rbx/ + +# output from ronn +lib/bundler/man/ + +# output from ci_reporter +spec/reports/ diff --git a/bundler-1.7.2/.rspec b/bundler-1.7.2/.rspec new file mode 100644 index 0000000..8c18f1a --- /dev/null +++ b/bundler-1.7.2/.rspec @@ -0,0 +1,2 @@ +--format documentation +--color diff --git a/bundler-1.7.2/.travis.yml b/bundler-1.7.2/.travis.yml new file mode 100644 index 0000000..a860fc6 --- /dev/null +++ b/bundler-1.7.2/.travis.yml @@ -0,0 +1,96 @@ +language: ruby +script: rake spec:travis +before_script: travis_retry rake spec:travis:deps +branches: + only: + - master + - 1-7-stable + - 1-6-stable + - 1-5-stable + - 1-3-stable + - 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: + on_success: change + on_failure: always + rooms: + # Bundler Ops + secure: MNTSGIySYwHia5gIgRiZxXtPMPDIP9KmzQk7Kq2ZoVvP3mIk8W1TMkvcyFkEf6uCasyVZZixzUBfY+E0BlHAz1ycQpTh1jvSpuIpEVYW48ShJldJ+8W8xfzafyOHii3z7VrDaomEffmMDdmHRsbQAfekMjdR4bTpXtT9V+wOXlg= +rvm: + - 2.1.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 +matrix: + include: + # Ruby 2.0.0, Rubygems 2.0 and up + - 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.1.11 + - rvm: 1.9.3 + env: RGV=v2.0.14 + - rvm: 1.9.3 + env: RGV=v1.8.29 + - rvm: 1.9.3 + env: RGV=v1.7.2 + - rvm: 1.9.3 + env: RGV=v1.6.2 + - rvm: 1.9.3 + env: RGV=v1.5.3 + # Ruby 1.8.7, Rubygems 1.3.6 and up + - rvm: 1.8.7 + env: RGV=v2.1.11 + - rvm: 1.8.7 + env: RGV=v2.0.14 + - rvm: 1.8.7 + env: RGV=v1.8.29 + - rvm: 1.8.7 + env: RGV=v1.7.2 + - rvm: 1.8.7 + env: RGV=v1.6.2 + - rvm: 1.8.7 + env: RGV=v1.5.3 + - rvm: 1.8.7 + env: RGV=v1.4.2 + - rvm: 1.8.7 + env: RGV=v1.3.7 + - rvm: 1.8.7 + env: RGV=v1.3.6 + + # ALLOWED FAILURES + # 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 + # 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: ruby-head + - rvm: 1.9.2 + - rvm: jruby + - rvm: rbx diff --git a/bundler-1.7.2/CHANGELOG.md b/bundler-1.7.2/CHANGELOG.md new file mode 100644 index 0000000..751baac --- /dev/null +++ b/bundler-1.7.2/CHANGELOG.md @@ -0,0 +1,1680 @@ +## 1.7.2 (2014-08-23) + +Bugfixes: + + - Revert gem source sorting in lock files (@indirect) + +## 1.7.1 (2014-08-20) + +Bugfixes: + + - Install gems from one source needed by gems in another source (@indirect) + - Install the same gem versions even after some are installed (@tmoore) + - Download specs only when installing from servers (@indirect) + +## 1.7.0 (2014-08-13) + +Security: + + - Fix for CVE-2013-0334, installing gems from an unexpected source (@tmoore) + +Features: + + - Gemfile `source` calls now take a block containing gems from that source (@tmoore) + - added the `:source` option to `gem` to specify a source (@tmoore) + +Bugfixes: + + - warn on ambiguous gems available from more than one source (@tmoore) + +## 1.6.5 (2014-07-23) + +Bugfixes: + + - require openssl explicitly to fix rare HTTPS request failures (@indirect, #3107) + +## 1.6.4 (2014-07-17) + +Bugfixes: + + - fix undefined constant error when can't find gem during binstubs (#3095, @jetaggart) + - work when installed git gems are not writable (#3092, @pmahoney) + - don't store configured source credentials in Gemfile.lock (#3045, @lhz) + - don't include config source credentials in the lockfile (Lars Haugseth) + - use threads for jobs on Rubinius (@YorickPeterse) + - skip dependencies from other platforms (@mvz) + - work when Rubygems was built without SSL (@andremedeiros) + +## 1.6.3 (2014-06-16) + +Bugfixes: + + - fix regression when resolving many conflicts (#2994, @Who828) + - use local gemspec for builtin gems during install --local (#3041, @Who828) + - don't warn about sudo when installing on Windows (#2984, @indirect) + - shell escape `bundle open` arguments (@indirect) + +## 1.6.2 (2014-04-13) + +Bugfixes: + + - fix an exception when using builtin gems (#2915, #2963, @gnufied) + - cache gems that are built in to the running ruby (#2975, @indirect) + - re-allow deploying cached git gems without git installed (#2968, @aughr) + - keep standalone working even with builtin gems (@indirect) + - don't update vendor/cache in deployment mode (#2921, @indirect) + +Features: + + - warn informatively when `bundle install` is run as root (#2936, @1337807) + +## 1.6.1 (2014-04-02) + +Bugfixes: + + - update C extensions when git gem versions change (#2948, @dylanahsmith) + +Features: + + - add support for C extensions in sudo mode on Rubygems 2.2 + +## 1.6.0 (2014-03-28) + +Bugfixes: + + - many Gemfiles that caused incorrect errors now resolve correctly (@Who828) + - redirects across hosts now work on rubies without OpenSSL (#2686, @grddev) + - gemspecs now handle filenames with newlines (#2634, @jasonmp85) + - support escaped characters in usernames and passwords (@punkie) + - no more exception on `update GEM` without lock file (@simi) + - allow long config values (#2823, @kgrz) + - cache successfully even locked to gems shipped with Ruby (#2869, @aughr) + - respect NO_PROXY even if a proxy is configured (#2878, @stlay) + - only retry git commands that hit the network (#2899, @timmoore) + - fix NameError regression when OpenSSL is not available (#2898, @timmoore) + - handle exception installing when build_info owned by root (@Who828) + - skip HTTP redirects from rubygems.org, huge speed boost (@Who828) + +Features: + + - resolver rewritten to avoid recursion (@Who828) + - add `git_source` for custom options like :github and :gist (@strzalek) + - HTTP auth may now be stored in `bundle config` (@smashwilson) + - some complex Gemfiles are resolved up to 10x faster (@Who828) + - add support for IRB alternatives such as Pry and Ripl (@joallard, @postmodern) + - highlight installed or updated gems (#2722, #2741, @yaotti, @simi) + - display the `post_install_message` for gems installed via :git (@phallstrom) + - `bundle outdated --strict` now only reports allowed updates (@davidblondeau) + - `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) + +Documentation: + + - Add missing switches for bundle-install(1) and bundle-update(1) (@as-cii) + +## 1.5.3 (2014-02-06) + +Bugfixes: + + - find "missing" gems that are actually present (#2780, #2818, #2854) + - use n-1 cores when given n jobs for parallel install (@jdickey) + +## 1.5.2 (2014-01-10) + +Bugfixes: + + - fix integration with Rubygems 1.8.0-1.8.19 + - handle ENETDOWN exception during network requests + - gracefully shut down after interrupt during parallel install (@Who828) + - allow Rails to run Thor without debug mode (@rafaelfranca) + - set git binstub permissions by umask (@v-yarotsky) + - remove parallel install debug log + +## 1.5.1 (2013-12-28) + +Bugfixes: + + - correctly find gems installed with Ruby by default + +## 1.5.0 (2013-12-26) + +Features: + + - install missing gems if their specs are present (@hone) + +Bugfixes: + + - use print for "Installing…" so messages are thread-safe (@TimMoore) + +## 1.5.0.rc.2 (2013-12-18) + +"Features": + + - Support threaded installation on Rubygems 2.0.7+ + - Debug installation logs in .bundle/install.log + +"Bugfixes": + + - Try to catch gem installation race conditions + +## 1.5.0.rc.1 (2013-11-09) + +Features: + + - bundle update also accepts --jobs (#2692, @mrkn) + - add fork URL to README for new `bundle gem` (#2665, @zzak) + - add `bundle outdated --strict` (#2685, @davidblondeau) + - warn if same gem/version is added twice (#2679, @jendiamond) + - don't redownload installed specs for `bundle install` (#2680, @cainlevy) + - override gem sources with mirrors (#2650, @danielsdeleo, @mkristian) + +Bugfixes: + + - fix sharing same SSL socket when forking workers for parallel install (#2632) + - fix msg typo in GitNotAllowedError (#2654, @joyicecloud) + - fix Bundler.which for directories (#2697, @rhysd) + - properly require `Capistrano::Version` (#2690, @steveklabnik) + - search for git.exe and git + - fix the bug that downloads every spec when API fetcher encouters an error + - only retry network requests + +## 1.4.0.rc.1 (2013-09-29) + +Features: + + - add support for the x64-mingw32 platform (#2356, #2590, @larskanis) + - add :patchlevel option to ruby DSL + - add `bundler` bin (#2598, @kirs) + - friendly ambiguous error messages (#2581, #2550, @jlsuttles, @jendiamond, @joyicecloud) + - add `:jruby_18` and `:jruby_19` platform options (@mcfiredrill) + - add X.509 client certificates for auth without passwords (@snackbandit) + - add `exec --keep-file-descriptors` for Ruby 1.9-like behavior on 2.0 (@steved555) + - print a better error when git is not installed (@joyicecloud) + - exit non-zero when `outdated` is run with an unknown gem (@joyicecloud) + - add `:ruby_21` platform option (@brandonblack) + - add `--retry` to retry failed network and git commands (@schneems) + - include command and versions in User-Agent (@indirect, @joyicecloud) + +Bugfixes: + + - allow passwordless Basic Auth (#2606, @rykov) + - don't suggest `gem install foo` when `foo` is a git gem that fails (@kirs) + - revert #2569, staying compatible with git: instead of https: for :github gems + - handle exceptions while installing gems in parallel (@gnufied) + +## 1.4.0.pre.1 (2013-08-04) + +Features: + + - retry network requests while installing gems (#2561, @ascherger) + - faster installs using gemspecs from the local system cache (#2497, @mipearson) + - add `bundle install -jN` for N parallel gem installations (#2481, @eagletmt) + - add `ENV['DEBUG_RESOLVER_TREE']` outputs resolver tree (@dblock) + - set $MANPATH so `bundle exec man name` works (#1624, @sunaku) + - use `man` instead of `groff` (#2579, @ixti, @simi) + - add Gemfile dependency info to bundle outdated output (#2487, @rahearn) + - allow `require: true` as an alias for `require: ` (#2538, @ndbroadbent) + - rescue and report Thor errors (#2478, @pjvds) + - detect cyclic dependencies (#2564, @gnufied) + - support multiple gems in `binstubs` (#2576, @lucasmazza) + - use https instead of git for :github gems (#2569, @fuadsaud) + - add quiet option to `bundle package` (#2573, @shtirlic) + - use RUBYLIB instead of RUBYOPT for better Windows support (#2536, @equinux) + +Bugfixes: + + - reduce stack size while resolving to fix JRuby overflow (#2510, @headius) + - display GitErrors while loading specs in --verbose mode (#2461) + - allow the same options hash to be passed to multiple gems (#2447) + - handle missing binaries without an exception (#2019, @luismreis) + +## 1.3.6 (8 January 2014) + +Bugfixes: + + - make gemspec path option preserve relative paths in lock file (@bwillis) + - use umask when creating binstubs (#1618, @v-yarotsky) + - warn if graphviz is not installed (#2435, @Agis-) + - show git errors while loading gemspecs + - don't mutate gem method options hash (#2447) + - print Thor errors (#2478, @pjvds) + - print Rubygems system exit errors (James Cook) + - more Pathnames into Strings for MacRuby (@kml) + - preserve original gemspec path (@bwillis) + - remove warning about deps with :git (#1651, @ixti) + - split git files on null (#2634, @jasonmp85) + - handle cross-host redirects without SSL (#2686, @grddev) + - handle Rubygems 2 security exception (@zzak) + - reinstall gems if they are missing with spec present + - set binstub permissions using umask (#1618, @v-yarotsky) + +## 1.3.5 (3 April 2013) + +Features: + + - progress indicator while resolver is running (@chief) + +Bugfixes: + + - update local overrides with orphaned revisions (@jamesferguson) + - revert to working quoting of RUBYOPT on Windows (@ogra) + - use basic auth even when SSL is not available (@jayniz) + - installing git gems without dependencies in deployment now works + +## 1.3.4 (15 March 2013) + +Bugfixes: + + - load YAML on Rubygems versions that define module YAML + - fix regression that broke --without on ruby 1.8.7 + +## 1.3.3 (13 March 2013) + +Features: + + - compatible with Rubygems 2.0.2 (higher and lower already work) + - mention skipped groups in bundle install and bundle update output (@simi) + - `gem` creates rake tasks for minitest (@coop) and rspec + +Bugfixes: + + - require rbconfig for standalone mode + +## 1.3.2 (7 March 2013) + +Features: + + - include rubygems.org CA chain + +Bugfixes: + + - don't store --dry-run as a Bundler setting + +## 1.3.1 (3 March 2013) + +Bugfixes: + + - include manpages in gem, restoring many help pages + - handle more SSL certificate verification failures + - check for the full version of SSL, which we need (@alup) + - gem rake task 'install' now depends on task 'build' (@sunaku) + +## 1.3.0 (24 February 2013) + +Features: + + - raise a useful error when the lockfile contains a merge conflict (@zofrex) + - ensure `rake release` checks for uncommitted as well as unstaged (@benmoss) + - allow environment variables to be negated with 'false' and '0' (@brettporter) + - set $MANPATH inside `exec` for gems with man pages (@sunaku) + - partial gem names for `open` and `update` now return a list (@takkanm) + +Bugfixes: + + - `update` now (again) finds gems that aren't listed in the Gemfile + - `install` now (again) updates cached gems that aren't in the Gemfile + - install Gemfiles with HTTP sources even without OpenSSL present + - display CerficateFailureError message in full + +## 1.3.0.pre.8 (12 February 2013) + +Security: + + - validate SSL certificate chain during HTTPS network requests + - don't send HTTP Basic Auth creds when redirected to other hosts (@perplexes) + - add `--trust-policy` to `install`, like `gem install -P` (@CosmicCat, #2293) + +Features: + + - optimize resolver when too new of a gem is already activated (@rykov, #2248) + - update Net::HTTP::Persistent for SSL cert validation and no_proxy ENV + - explain SSL cert validation failures + - generate gemspecs when installing git repos, removing shellouts + - add pager selection (@csgui) + - add `licenses` command (@bryanwoods, #1898) + - sort output from `outdated` (@richardkmichael, #1896) + - add a .travis.yml to `gem -t` (@ndbroadbent, #2143) + - inform users when the resolver starts + - disable reverse DNS to speed up API requests (@raggi) + +Bugfixes: + + - raise errors while requiring dashed gems (#1807) + - quote the Bundler path on Windows (@jgeiger, #1862, #1856) + - load gemspecs containing unicode (@gaffneyc, #2301) + - support any ruby version in --standalone + - resolve some ruby -w warnings (@chastell, #2193) + - don't scare users with an error message during API fallback + - `install --binstubs` is back to overwriting. thanks, SemVer. + +## 1.3.0.pre.7 (22 January 2013) + +Bugfixes: + + - stubs for gems with dev deps no longer cause exceptions (#2272) + - don't suggest binstubs to --binstubs users + +## 1.3.0.pre.6 (22 January 2013) + +Features: + + - `binstubs` lists child gem bins if a gem has no binstubs + - `bundle gem --edit` will open the new gemspec (@ndbroadbent) + - `bundle gem --test rspec` now makes working tests (@tricknotes) + - `bundle env` prints info about bundler's environment (@peeja) + - add `BUNDLE_IGNORE_CONFIG` environment variable support (@richo) + +Bugfixes: + + - don't overwrite custom binstubs during `install --binstubs` + - don't throw an exception if `binstubs` gem doesn't exist + - `bundle config` now works in directories without a Gemfile + +## 1.3.0.pre.5 (Jan 9, 2013) + +Features: + + - make `--standalone` require lines ruby engine/version agnostic + - add `--dry-run` to `bundle clean` (@wfarr, #2237) + +Bugfixes: + + - don't skip writing binstubs when doing `bundle install` + - distinguish between ruby 1.9/2.0 when using :platforms (@spastorino) + +## 1.3.0.pre.4 (Jan 3, 2013) + +Features: + + - `bundle binstubs ` to setup individual binstubs + - `bundle install --binstubs ""` will remove binstubs option + - `bundle clean --dry-run` will print out gems instead of removing them + +Bugfixes: + + - Avoid stack traces when Ctrl+C during bundle command (@mitchellh) + - fix YAML parsing in in ruby-preview2 + +## 1.3.0.pre.3 (Dec 21, 2012) + +Features: + + - pushing gems during `rake release` can be disabled (@trans) + - installing gems with `rake install` is much faster (@utkarshkukreti) + - added platforms :ruby_20 and :mri_20, since the ABI has changed + - added '--edit' option to open generated gemspec in editor + +Bugfixes: + + - :git gems with extensions now work with Rubygems >= 2.0 (@jeremy) + - revert SemVer breaking change to :github + - `outdated` exits non-zero if outdated gems found (@rohit, #2021) + - https Gist URLs for compatibility with Gist 2.0 (@NARKOZ) + - namespaced gems no longer generate a superfluous directory (@banyan) + +## 1.3.0.pre.2 (Dec 9, 2012) + +Features: + + - `config` expands local overrides like `local.rack .` (@gkop, #2205) + - `gem` generates files correctly for names like `jquery-rails` (@banyan, #2201) + - use gems from gists with the :gist option in the Gemfile (@jgaskins) + +Bugfixes: + + - Gemfile sources other than rubygems.org work even when .gemrc contains sources + - caching git gems now caches specs, fixing e.g. git ls-files (@bison, #2039) + - `show GEM` now warns if the directory has been deleted (@rohit, #2070) + - git output hidden when running in --quiet mode (@rohit) + +## 1.3.0.pre (Nov 29, 2012) + +Features: + + - compatibile with Ruby 2.0.0-preview2 + - compatibile with Rubygems 2.0.0.preview2 (@drbrain, @evanphx) + - ruby 2.0 added to the `:ruby19` ABI-compatible platform + - lazy load YAML, allowing Psych to be specified in the Gemfile + - significant performance improvements (@cheald, #2181) + - `inject` command for scripted Gemfile additions (Engine Yard) + - :github option uses slashless arguements as repo owner (@rking) + - `open` suggests gem names for typos (@jdelStrother) + - `update` reports non-existent gems (@jdelStrother) + - `gem` option --test can generate rspec stubs (@MafcoCinco) + - `gem` option --test can generate minitest stubs (@kcurtin) + - `gem` command generates MIT license (@BrentWheeldon) + - gem rake task 'release' resuses existing tags (@shtirlic) + +Bugfixes: + + - JRuby new works with HTTPS gem sources (@davidcelis) + - `install` installs both rake rake-built gems at once (@crowbot, #2107) + - handle Errno::ETIMEDOUT errors (@jmoses) + - handle Errno::EAGAIN errors on JRuby + - disable ANSI coloring when output is redirected (@tomykaira) + - raise LoadErrors correctly during Bundler.require (@Empact) + - do not swallow --verbose on `bundle exec` (@sol, #2102) + - `gem` generates gemspecs that block double-requires + - `gem` generates gemspecs that admit they depend on rake + +## 1.2.5 (Feb 24, 2013) + +Bugfixes: + + - install Gemfiles with HTTP sources even without OpenSSL present + - display CerficateFailureError message in full + +## 1.2.4 (Feb 12, 2013) + +Features: + + - warn about Ruby 2.0 and Rubygems 2.0 + - inform users when the resolver starts + - disable reverse DNS to speed up API requests (@raggi) + +Bugfixes: + + - don't send user/pass when redirected to another host (@perplexes) + - load gemspecs containing unicode (@gaffneyc, #2301) + - support any ruby version in --standalone + - resolve some ruby -w warnings (@chastell, #2193) + - don't scare users with an error message during API fallback + +## 1.2.3 (Nov 29, 2012) + +Bugfixes: + + - fix exceptions while loading some gemspecs + +## 1.2.2 (Nov 14, 2012) + +Bugfixes: + + - support new Psych::SyntaxError for Ruby 2.0.0 (@tenderlove, @sol) + - `bundle viz` works with git gems again (@hirochachacha) + - recognize more cases when OpenSSL is not present + +## 1.2.1 (Sep 19, 2012) + +Bugfixes: + + - `bundle clean` now works with BUNDLE_WITHOUT groups again + - have a net/http read timeout around the Gemcutter API Endpoint + +## 1.2.0 (Aug 30, 2012) + +Bugfixes: + + - raise original error message from LoadError's + +Documentation: + + - `platform` man pages + +## 1.2.0.rc.2 (Aug 8, 2012) + +Bugfixes: + + - `clean` doesn't remove gems that are included in the lockfile + +## 1.2.0.rc (Jul 17, 2012) + +Features: + + - `check` now has a `--dry-run` option (@svenfuchs, #1811) + - loosen ruby directive for engines + - prune git/path directories inside vendor/cache (@josevalim, #1988) + - update vendored thor to 0.15.2 (@sferik) + - add .txt to LICENSE (@postmodern, #2001) + - add `config disable_local_branch_check` (@josevalim, #1985) + - fall back on the full index when experiencing syck errors (#1419) + - handle syntax errors in Ruby gemspecs (#1974) + +Bugfixes: + + - fix `pack`/`cache` with `--all` (@josevalim, #1989) + - don't display warning message when `cache_all` is set + - check for `nil` PATH (#2006) + - Always try to keep original GEM_PATH (@drogus, #1920) + +## 1.2.0.pre.1 (May 27, 2012) + +Features: + + - Git gems import submodules of submodules recursively (@nwwatson, #1935) + +Bugfixes: + + - Exit from `check` with a non-zero status when frozen with no lock + - Use `latest_release` in Capistrano and Vlad integration (#1264) + - Work around a Ruby 1.9.3p194 bug in Psych when config files are empty + +Documentation: + + - Add instructions for local git repos to the `config` manpage + - Update the `Gemfile` manpage to include ruby versions (@stevenh512) + - When OpenSSL is missing, provide instructions for fixing (#1776 etc.) + - Unknown exceptions now link to ISSUES for help instead of a new ticket + - Correct inline help for `clean --force` (@dougbarth, #1911) + +## 1.2.0.pre (May 4, 2012) + +Features: + + - bundle package now accepts --all to package git and path dependencies + - bundle config now accepts --local, --global and --delete options + - It is possible to override a git repository via configuration. + For instance, if you have a git dependency on rack, you can force + it to use a local repo with `bundle config local.rack ~/path/to/rack` + - Cache gemspec loads for performance (@dekellum, #1635) + - add --full-index flag to `bundle update` (@fluxx, #1829) + - add --quiet flag to `bundle update` (@nashby, #1654) + - Add Bundler::GemHelper.gemspec (@knu, #1637) + - Graceful handling of Gemfile syntax errors (@koraktor, #1661) + - `bundle platform` command + - add ruby to DSL, to specify version of ruby + - error out if the ruby version doesn't match + +Performance: + + - bundle exec shouldn't run Bundler.setup just setting the right rubyopts options is enough (@spastorino, #1598) + +Bugfixes: + + - Avoid passing RUBYOPT changes in with_clean_env block (@eric1234, #1604) + - Use the same ruby to run subprocesses as is running rake (@brixen) + +Documentation: + + - Add :github documentation in DSL (@zofrex, #1848, #1851, #1852) + - Add docs for the --no-cache option (@fluxx, #1796) + - Add basic documentation for bin_path and bundle_path (@radar) + - Add documentation for the run method in Bundler::Installer + +## 1.1.5 (Jul 17, 2012) + +Features: + + - Special case `ruby` directive from 1.2.0, so you can install Gemfiles that use it + +## 1.1.4 (May 27, 2012) + +Bugfixes: + + - Use `latest_release` in Capistrano and Vlad integration (#1264) + - Unknown exceptions now link to ISSUES for help instead of a new ticket + - When OpenSSL is missing, provide instructions for fixing (#1776 etc.) + - Correct inline help for `clean --force` (@dougbarth, #1911) + - Work around a Ruby 1.9.3p194 bug in Psych when config files are empty + +## 1.1.3 (March 23, 2012) + +Bugfixes: + + - escape the bundler root path (@tenderlove, #1789) + +## 1.1.2 (March 20, 2012) + +Bugfixes: + + - Fix --deployment for multiple PATH sections of the same source (#1782) + +## 1.1.1 (March 14, 2012) + +Bugfixes: + + - Rescue EAGAIN so the fetcher works on JRuby on Windows + - Stop asking users to report gem installation errors + - Clarify "no sources" message + - Use $\ so `bundle gem` gemspecs work on Windows (@postmodern) + - URI-encode gem names for dependency API (@rohit, #1672) + - Fix `cache` edge case in rubygems 1.3.7 (#1202) + +Performance: + + - Reduce invocation of git ls-files in `bundle gem` gemspecs (@knu) + +## 1.1.0 (Mar 7, 2012) + +Bugfixes: + + - Clean up corrupted lockfiles on bundle installs + - Prevent duplicate GIT sources + - Fix post_install_message when uing the endpoint API + +## 1.1.rc.8 (Mar 3, 2012) + +Performance: + + - don't resolve if the Gemfile.lock and Gemfile haven't changed + +Bugfixes: + + - Load gemspecs from git even when a released gem has the same version (#1609) + - Declare an accurate Ruby version requirement of 1.8.7 or newer (#1619) + - handle gemspec development dependencies correctly (@raggi, #1639) + - Avoid passing RUBYOPT changes in with_clean_env block. (eric1234, #1604) + +## 1.1.rc.7 (Dec 29, 2011) + +Bugfixes: + + - Fix bug where `clean` would break when using :path with no gemspec + +## 1.1.rc.6 (Dec 22, 2011) + +Bugfixes: + + - Fix performance regression from 1.0 (@spastorino, #1511, #1591, #1592) + - Load gems correctly when GEM_HOME is blank + - Refresh gems so Bundler works from inside a bundle + - Handle empty .bundle/config files without an error + +## 1.1.rc.5 (Dec 14, 2011) + +Bugfixes: + + - Fix ASCII encoding errors with gem (rerelease with ruby 1.8) + +## 1.1.rc.4 (Dec 14, 2011) + +Features: + + - `bundle viz` has the option to output a DOT file instead of a PNG (@hirochachacha, #683) + +Bugfixes: + + - Ensure binstubs generated when using --standalone point to the standalonde bundle (@cowboyd, #1588) + - fix `bundle viz` (@hirochachacha, #1586) + +## 1.1.rc.3 (Dec 8, 2011) + +Bugfixes: + + - fix relative_path so it checks Bundler.root is actually in the beginning of the path (#1582) + - fix bundle outdated doesn't list all gems (@joelmoss, #1521) + +## 1.1.rc.2 (Dec 6, 2011) + +Features: + + - Added README.md to `newgem` (@ognevsky, #1574) + - Added LICENSE (MIT) to newgem (@ognevsky, #1571) + +Bugfixes: + + - only auto-namespace requires for implied requires (#1531) + - fix bundle clean output for git repos (#1473) + - use Gem.bindir for bundle clean (#1544, #1532) + - use `Gem.load_env_plugins` instead of `Gem.load_env_plugins` (#1500, #1543) + - differentiate Ruby 2.0 (trunk) from Ruby 1.9 (@tenderlove, #1539) + - `bundle clean` handles 7 length git hash for bundle clean (#1490, #1491) + - fix Psych loading issues + - Search $PATH for a binary rather than shelling out to `which` (@tenderlove, #1573) + - do not clear RG cache unless we actually modify GEM_PATH and GEM_HOME- use `Gem.load_env_plugins` instead of `Gem.load_env_plugins` (#1500, #1543) + - `newgem` now uses https://rubygems.org (#1562) + - `bundle init` now uses https://rubygems.org (@jjb, #1522) + - `bundle install/update` does not autoclean when using --path for semver + +Documentation: + + - added documentation for --shebang option for `bundle install` (@lunks, #1475, #1558) + +## 1.1.rc (Oct 3, 2011) + +Features: + + - add `--shebang` option to bundle install (@bensie, #1467) + - build passes on ruby 1.9.3rc1 (#1458, #1469) + - hide basic auth credentials for custom sources (#1440, #1463) + +Bugfixes: + + - fix index search result caching (#1446, #1466) + - fix fetcher prints multiple times during install (#1445, #1462) + - don't mention API errors from non-rubygems.org sources + - fix autoclean so it doesn't remove bins that are used (#1459, #1460) + +Documentation: + + - add :require => [...] to the gemfile(5) manpage (@nono, #1468) + +## 1.1.pre.10 (Sep 27, 2011) + +Features: + + - `config system_bindir foo` added, works like "-n foo" in your .gemrc file + +## 1.1.pre.9 (Sep 18, 2011) + +Features: + + - `clean` will now clean up all old .gem and .gemspec files, cleaning up older pres + - `clean` will be automatically run after bundle install and update when using `--path` (#1420, #1425) + - `clean` now takes a `--force` option (#1247, #1426) + - `clean` will clean up cached git dirs in bundle clean (#1390) + - remove deprecations from DSL (#1119) + - autorequire tries directories for gems with dashed names (#1205) + - adds a `--paths` flag to `bundle show` to list all the paths of bundled gems (@tiegz, #1360) + - load rubygems plugins in the bundle binary (@tpope, #1364) + - make `--standalone` respect `--path` (@cowboyd, #1361) + +Bugfixes: + + - Fix `clean` to handle nested gems in a git repo (#1329) + - Fix conflict from revert of benchmark tool (@boffbowsh, #1355) + - Fix fatal error when unable to connect to gem source (#1269) + - Fix `outdated` to find pre-release gems that are installed. (#1359) + - Fix color for ui. (#1374) + - Fix installing to user-owned system gems on OS X + - Fix caching issue in the resolver (#1353, #1421) + - Fix :github DSL option + +## 1.1.pre.8 (Aug 13, 2011) + +Bugfixes: + + - Fix `bundle check` to not print fatal error message (@cldwalker, #1347) + - Fix require_sudo when Gem.bindir isn't writeable (#1352) + - Fix not asking Gemcutter API for dependency chain of git gems in --deployment (#1254) + - Fix `install --binstubs` when using --path (#1332) + +## 1.1.pre.7 (Aug 8, 2011) + +Bugfixes: + + - Fixed invalid byte sequence error while installing gem on Ruby 1.9 (#1341) + - Fixed exception when sudo was needed to install gems (@spastorino) + +## 1.1.pre.6 (Aug 8, 2011) + +Bugfixes: + + - Fix cross repository dependencies (#1138) + - Fix git dependency fetching from API endpoint (#1254) + - Fixes for bundle outdated (@joelmoss, #1238) + - Fix bundle standalone when using the endpoint (#1240) + +Features: + + - Implement `to_ary` to avoid calls to method_missing (@tenderlove, #1274) + - bundle clean removes old .gem files (@cldwalker, #1293) + - Correcly identify missing child dependency in error message + - Run pre-install, post-build, and post-install gem hooks for git gems (@warhammerkid, #1120) + - create Gemfile.lock for empty Gemfile (#1218) + +## 1.1.pre.5 (June 11, 2011) + +Bugfixes: + + - Fix LazySpecification on Ruby 1.9 (@dpiddy, #1232) + - Fix HTTP proxy support (@leobessa, #878) + +Features: + + - Speed up `install --deployment` by using the API endpoint + - Support Basic HTTP Auth for the API endpoint (@dpiddy, #1229) + - Add `install --full-index` to disable the API endpoint, just in case + - Significantly speed up install by removing unneeded gemspec fetches + - `outdated` command shows outdated gems (@joelmoss, #1130) + - Print gem post install messages (@csquared, #1155) + - Reduce memory use by removing Specification.new inside method_missing (@tenderlove, #1222) + - Allow `check --path` + +## 1.1.pre.4 (May 5, 2011) + +Bugfixes: + + - Fix bug that could prevent installing new gems + +## 1.1.pre.3 (May 4, 2011) + +Features: + + - Add `bundle outdated` to show outdated gems (@joelmoss) + - Remove BUNDLE_* from `Bundler.with_clean_env` (@wuputah) + - Add Bundler.clean_system, and clean_exec (@wuputah) + - Use git config for gem author name and email (@krekoten) + +Bugfixes: + + - Fix error calling Bundler.rubygems.gem_path + - Fix error when Gem.path returns Gem::FS instead of String + +## 1.1.pre.2 (April 28, 2011) + +Features: + + - Add :github option to Gemfile DSL for easy git repos + - Merge all fixes from 1.0.12 and 1.0.13 + +## 1.1.pre.1 (February 2, 2011) + +Bugfixes: + + - Compatibility with changes made by Rubygems 1.5 + +## 1.1.pre (January 21, 2011) + +Features: + + - Add bundle clean. Removes unused gems from --path directory + - Initial Gemcutter Endpoint API work, BAI Fetching source index + - Added bundle install --standalone + - Ignore Gemfile.lock when buliding new gems + - Make it possible to override a .gemspec dependency's source in the + Gemfile + +Removed: + + - Removed bundle lock + - Removed bundle install + - Removed bundle install --production + - Removed bundle install --disable-shared-gems + +## 1.0.21 (September 30, 2011) + + - No changes from RC + +## 1.0.21.rc (September 29, 2011) + +Bugfixes: + + - Load Psych unless Syck is defined, because 1.9.2 defines YAML + +## 1.0.20 (September 27, 2011) + +Features: + + - Add platform :maglev (@timfel, #1444) + +Bugfixes: + + - Ensure YAML is required even if Psych is found + - Handle directory names that contain invalid regex characters + +## 1.0.20.rc (September 18, 2011) + +Features: + + - Rescue interrupts to `bundle` while loading bundler.rb (#1395) + - Allow clearing without groups by passing `--without ''` (#1259) + +Bugfixes: + + - Manually sort requirements in the lockfile (#1375) + - Remove several warnings generated by ruby -w (@stephencelis) + - Handle trailing slashes on names passed to `gem` (#1372) + - Name modules for gems like 'test-foo_bar' correctly (#1303) + - Don't require Psych if Syck is already loaded (#1239) + +## 1.0.19.rc (September 13, 2011) + +Features: + + - Compatability with Rubygems 1.8.10 installer changes + - Report gem installation failures clearly (@rwilcox, #1380) + - Useful error for cap and vlad on first deploy (@nexmat, @kirs) + +Bugfixes: + + - `exec` now works when the command contains 'exec' + - Only touch lock after changes on Windows (@robertwahler, #1358) + - Keep load paths when #setup is called multiple times (@radsaq, #1379) + +## 1.0.18 (August 16, 2011) + +Bugfixes: + + - Fix typo in DEBUG_RESOLVER (@geemus) + - Fixes rake 0.9.x warning (@mtylty, #1333) + - Fix `bundle cache` again for rubygems 1.3.x + +Features: + + - Run the bundle install earlier in a Capistrano deployment (@cgriego, #1300) + - Support hidden gemspec (@trans, @cldwalker, #827) + - Make fetch_specs faster (@zeha, #1294) + - Allow overriding development deps loaded by #gemspec (@lgierth, #1245) + +## 1.0.17 (August 8, 2011) + +Bugfixes: + + - Fix rake issues with rubygems 1.3.x (#1342) + - Fixed invalid byte sequence error while installing gem on Ruby 1.9 (#1341) + +## 1.0.16 (August 8, 2011) + +Features: + + - Performance fix for MRI 1.9 (@efficientcloud, #1288) + - Shortcuts (like `bundle i`) for all commands (@amatsuda) + - Correcly identify missing child dependency in error message + +Bugfixes: + + - Allow Windows network share paths with forward slashes (@mtscout6, #1253) + - Check for rubygems.org credentials so `rake release` doesn't hang (#980) + - Find cached prerelease gems on rubygems 1.3.x (@dburt, #1202) + - Fix `bundle install --without` on kiji (@tmm1, #1287) + - Get rid of warning in ruby 1.9.3 (@smartinez87, #1231) + +Documentation: + + - Documentation for `gem ..., :require => false` (@kmayer, #1292) + - Gems provide "executables", they are rarely also binaries (@fxn, #1242) + +## 1.0.15 (June 9, 2011) + +Features: + + - Improved Rubygems integration, removed many deprecation notices + +Bugfixes: + + - Escape URL arguments to git correctly on Windows (1.0.14 regression) + +## 1.0.14 (May 27, 2011) + +Features: + + - Rubinius platform :rbx (@rkbodenner) + - Include gem rake tasks with "require 'bundler/gem_tasks" (@indirect) + - Include user name and email from git config in new gemspec (@ognevsky) + +Bugfixes: + + - Set file permissions after checking out git repos (@tissak) + - Remove deprecated call to Gem::SourceIndex#all_gems (@mpj) + - Require the version file in new gemspecs (@rubiii) + - Allow relative paths from the Gemfile in gems with no gemspec (@mbirk) + - Install gems that contain 'bundler', e.g. guard-bundler (@hone) + - Display installed path correctly on Windows (@tadman) + - Escape quotes in git URIs (@mheffner) + - Improve Rake 0.9 support (@quix) + - Handle certain directories already existing (@raggi) + - Escape filenames containing regex characters (@indirect) + +## 1.0.13 (May 4, 2011) + +Features: + + - Compatibility with Rubygems master (soon to be v1.8) (@evanphx) + - Informative error when --path points to a broken symlink + - Support Rake 0.9 and greater (@e2) + - Output full errors for non-TTYs e.g. pow (@josh) + +Bugfixes: + + - Allow spaces in gem path names for gem tasks (@rslifka) + - Have cap run bundle install from release_path (@martinjagusch) + - Quote git refspec so zsh doesn't expand it (@goneflyin) + +## 1.0.12 (April 8, 2011) + +Features: + + - Add --no-deployment option to `install` for disabling it on dev machines + - Better error message when git fails and cache is present (@parndt) + - Honor :bundle_cmd in cap `rake` command (@voidlock, @cgriego) + +Bugfixes: + + - Compatibility with Rubygems 1.7 and Rails 2.3 and vendored gems (@evanphx) + - Fix changing gem order in lock (@gucki) + - Remove color escape sequences when displaying man pages (@bgreenlee) + - Fix creating GEM_HOME on both JRuby 1.5 and 1.6 (@nickseiger) + - Fix gems without a gemspec and directories in bin/ (@epall) + - Fix --no-prune option for `bundle install` (@cmeiklejohn) + +## 1.0.11 (April 1, 2011) + +Features: + + - Compatibility with Rubygems 1.6 and 1.7 + - Better error messages when a git command fails + +Bugfixes: + + - Don't always update gemspec gems (@carllerche) + - Remove ivar warnings (@jackdempsey) + - Fix occasional git failures in zsh (@jonah-carbonfive) + - Consistent lock for gems with double deps like Cap (@akahn) + +## 1.0.10 (February 1, 2011) + +Bugfixes: + + - Fix a regression loading YAML gemspecs from :git and :path gems + - Requires, namespaces, etc. to work with changes in Rubygems 1.5 + +## 1.0.9 (January 19, 2011) + +Bugfixes: + + - Fix a bug where Bundler.require could remove gems from the load + path. In Rails apps with a default application.rb, this removed + all gems in groups other than :default and Rails.env + +## 1.0.8 (January 18, 2011) + +Features: + + - Allow overriding gemspec() deps with :git deps + - Add --local option to `bundle update` + - Ignore Gemfile.lock in newly generated gems + - Use `less` as help pager instead of `more` + - Run `bundle exec rake` instead of `rake` in Capistrano tasks + +Bugfixes: + + - Fix --no-cache option for `bundle install` + - Allow Vlad deploys to work without Capistrano gem installed + - Fix group arguments to `bundle console` + - Allow groups to be loaded even if other groups were loaded + - Evaluate gemspec() gemspecs in their directory not the cwd + - Count on Rake to chdir to the right place in GemHelper + - Change Pathnames to Strings for MacRuby + - Check git process exit status correctly + - Fix some warnings in 1.9.3-trunk (thanks tenderlove) + +## 1.0.7 (November 17, 2010) + +Bugfixes: + + - Remove Bundler version from the lockfile because it broke + backwards compatibility with 1.0.0-1.0.5. Sorry. :( + +## 1.0.6 (November 16, 2010) + +Bugfixes: + + - Fix regression in `update` that caused long/wrong results + - Allow git gems on other platforms while installing (#579) + +Features: + + - Speed up `install` command using various optimizations + - Significantly increase performance of resolver + - Use upcoming Rubygems performance improvements (@tmm1) + - Warn if the lockfile was generated by a newer version + - Set generated gems' homepage to "", so Rubygems will warn + +## 1.0.5 (November 13, 2010) + +Bugfixes: + + - Fix regression disabling all operations that employ sudo + +## 1.0.4 (November 12, 2010) + +Bugfixes: + + - Expand relative :paths from Bundler.root (eg ./foogem) + - Allow git gems in --without groups while --frozen + - Allow gem :ref to be a symbol as well as a string + - Fix exception when Gemfile needs a newer Bundler version + - Explanation when the current Bundler version conflicts + - Explicit error message if Gemfile needs newer Bundler + - Ignore an empty string BUNDLE_GEMFILE + - Skeleton gemspec now works with older versions of git + - Fix shell quoting and ref fetching in GemHelper + - Disable colored output in --deployment + - Preserve line endings in lock file + +Features: + + - Add support for 'mingw32' platform (aka RubyInstaller) + - Large speed increase when Gemfile.lock is already present + - Huge speed increase when many (100+) system gems are present + - Significant expansion of ISSUES, man pages, and docs site + - Remove Open3 from GemHelper (now it works on Windows™®©) + - Allow setting roles in built-in cap and vlad tasks + +## 1.0.3 (October 15, 2010) + +Bugfixes: + + - Use bitwise or in #hash to reduce the chance of overflow + - `bundle update` now works with :git + :tag updates + - Record relative :path options in the Gemfile.lock + - :groups option on gem method in Gemfile now works + - Add #platform method and :platform option to Gemfile DSL + - --without now accepts a quoted, space-separated list + - Installing after --deployment with no lock is now possible + - Binstubs can now be symlinked + - Print warning if cache for --local install is missing gems + - Improve output when installing to a path + - The tests all pass! Yay! + +## 1.0.2 (October 2, 2010) + +Bugfix: + + - Actually include the man pages in the gem, so help works + +## 1.0.1 (October 1, 2010) + +Features: + + - Vlad deployment recipe, `require 'bundler/vlad'` + - Prettier bundle graphs + - Improved gem skeleton for `bundle gem` + - Prompt on file clashes when generating a gem + - Option to generate binary with gem skeleton + - Allow subclassing of GemHelper for custom tasks + - Chdir to gem directory during `bundle open` + +Bugfixes: + + - Allow gemspec requirements with a list of versions + - Accept lockfiles with windows line endings + - Respect BUNDLE_WITHOUT env var + - Allow `gem "foo", :platform => :jruby` + - Specify loaded_from path in fake gemspec + - Flesh out gem_helper tasks, raise errors correctly + - Respect RBConfig::CONFIG['ruby_install_name'] in binstubs + +## 1.0.0 (August 29, 2010) + +Features: + + - You can now define `:bundle_cmd` in the capistrano task + +Bugfixes: + + - Various bugfixes to the built-in rake helpers + - Fix a bug where shortrefs weren't unique enough and were + therfore colliding + - Fix a small bug involving checking whether a local git + clone is up to date + - Correctly handle explicit '=' dependencies with gems + pinned to a git source + - Fix an issue with Windows-generated lockfiles by reading + and writing the lockfile in binary mode + - Fix an issue with shelling out to git in Windows by + using double quotes around paths + - Detect new Rubygems sources in the Gemfile and update + the lockfile + +## 1.0.0.rc.6 (August 23, 2010) + +Features: + + - Much better documentation for most of the commands and Gemfile + format + +Bugfixes: + + - Don't attempt to create directories if they already exist + - Fix the capistrano task so that it actually runs + - Update the Gemfile template to reference rubygems.org instead + of :gemcutter + - bundle exec should exit with a non zero exit code when the gem + binary does not exist or the file is not executable. + - Expand paths in Gemfile relative to the Gemfile and not the current + working directory. + +## 1.0.0.rc.5 (August 10, 2010) + +Features: + + - Make the Capistrano task more concise. + +Bugfixes: + + - Fix a regression with determining whether or not to use sudo + - Allow using the --gemfile flag with the --deployment flag + +## 1.0.0.rc.4 (August 9, 2010) + +Features: + + - `bundle gem NAME` command to generate a new gem with Gemfile + - Bundle config file location can be specified by BUNDLE_APP_CONFIG + - Add --frozen to disable updating the Gemfile.lock at runtime + (default with --deployment) + - Basic Capistrano task now added as 'bundler/capistrano' + +Bugfixes: + + - Multiple bundler process no longer share a tmp directory + - `bundle update GEM` always updates dependencies of GEM as well + - Deleting the cache directory no longer causes errors + - Moving the bundle after installation no longer causes git errors + - Bundle path is now correctly remembered on a read-only filesystem + - Gem binaries are installed to Gem.bindir, not #{Gem.dir}/bin + - Fetch gems from vendor/cache, even without --local + - Sort lockfile by platform as well as spec + +## 1.0.0.rc.3 (August 3, 2010) + +Features: + + - Deprecate --production flag for --deployment, since the former + was causing confusion with the :production group + - Add --gemfile option to `bundle check` + - Reduce memory usage of `bundle install` by 2-4x + - Improve message from `bundle check` under various conditions + - Better error when a changed Gemfile conflicts with Gemfile.lock + +Bugfixes: + + - Create bin/ directory if it is missing, then install binstubs + - Error nicely on the edge case of a pinned gem with no spec + - Do not require gems for other platforms + - Update git sources along with the gems they contain + +## 1.0.0.rc.2 (July 29, 2010) + + - `bundle install path` was causing confusion, so we now print + a clarifying warning. The preferred way to install to a path + (which will not print the warning) is + `bundle install --path path/to/install`. + - `bundle install --system` installs to the default system + location ($BUNDLE_PATH or $GEM_HOME) even if you previously + used `bundle install --path` + - completely remove `--disable-shared-gems`. If you install to + system, you will not be isolated, while if you install to + another path, you will be isolated from gems installed to + the system. This was mostly an internal option whose naming + and semantics were extremely confusing. + - Add a `--production` option to `bundle install`: + - by default, installs to `vendor/bundle`. This can be + overridden with the `--path` option + - uses `--local` if `vendor/cache` is found. This will + guarantee that Bundler does not attempt to connect to + Rubygems and will use the gems cached in `vendor/cache` + instead + - Raises an exception if a Gemfile.lock is not found + - Raises an exception if you modify your Gemfile in development + but do not check in an updated Gemfile.lock + - Fixes a bug where switching a source from Rubygems to git + would always say "the git source is not checked out" when + running `bundle install` + +NOTE: We received several reports of "the git source has not +been checked out. Please run bundle install". As far as we +can tell, these problems have two possible causes: + +1. `bundle install ~/.bundle` in one user, but actually running + the application as another user. Never install gems to a + directory scoped to a user (`~` or `$HOME`) in deployment. +2. A bug that happened when changing a gem to a git source. + +To mitigate several common causes of `(1)`, please use the +new `--production` flag. This flag is simply a roll-up of +the best practices we have been encouraging people to use +for deployment. + +If you want to share gems across deployments, and you use +Capistrano, symlink release_path/current/vendor/bundle to +release_path/shared/bundle. This will keep deployments +snappy while maintaining the benefits of clean, deploy-time +isolation. + +## 1.0.0.rc.1 (July 26, 2010) + + - Fixed a bug with `bundle install` on multiple machines and git + +## 1.0.0.beta.10 (July 25, 2010) + + - Last release before 1.0.0.rc.1 + - Added :mri as a valid platform (platforms :mri { gem "ruby-debug" }) + - Fix `bundle install` immediately after modifying the :submodule option + - Don't write to Gemfile.lock if nothing has changed, fixing situations + where bundle install was run with a different user than the app + itself + - Fix a bug where other platforms were being wiped on `bundle update` + - Don't ask for root password on `bundle install` if not needed + - Avoid setting `$GEM_HOME` where not needed + - First solid pass of `bundle config` + - Add build options + - `bundle config build.mysql --with-mysql-config=/path/to/config` + +## 1.0.0.beta.9 (July 21, 2010) + + - Fix install failure when switching from a path to git source + - Fix `bundle exec bundle *` in a bundle with --disable-shared-gems + - Fix `bundle *` from inside a bundle with --disable-shared-gem + - Shim Gem.refresh. This is used by Unicorn + - Fix install failure when a path's dependencies changed + +## 1.0.0.beta.8 (July 20, 2010) + + - Fix a Beta 7 bug involving Ruby 1.9 + +## 1.0.0.beta.7 (July 20, 2010, yanked) + + - Running `bundle install` twice in a row with a git source always crashed + +## 1.0.0.beta.6 (July 20, 2010, yanked) + + - Create executables with bundle install --binstubs + - You can customize the location (default is app/bin) with --binstubs other/location + - Fix a bug where the Gemfile.lock would be deleted even if the update was exited + - Fix a bug where cached gems for other platforms were sometimes deleted + - Clean up output when nothing was deleted from cache (it previously said + "Removing outdated gems ...") + - Improve performance of bundle install if the git gem was already checked out, + and the revision being used already exists locally + - Fix bundle show bundler in some cases + - Fix bugs with bundle update + - Don't ever run git commands at runtime (fixes a number of common passenger issues) + - Fixes an obscure bug where switching the source of a gem could fail to correctly + change the source of its dependencies + - Support multiple version dependencies in the Gemfile + (gem "rails", ">= 3.0.0.beta1", "<= 3.0.0") + - Raise an exception for ambiguous uses of multiple declarations of the same gem + (for instance, with different versions or sources). + - Fix cases where the same dependency appeared several times in the Gemfile.lock + - Fix a bug where require errors were being swallowed during Bundler.require + +## 1.0.0.beta.1 + + - No `bundle lock` command. Locking happens automatically on install or update + - No .bundle/environment.rb. Require 'bundler/setup' instead. + - $BUNDLE_HOME defaults to $GEM_HOME instead of ~/.bundle + - Remove lockfiles generated by 0.9 + +## 0.9.26 + +Features: + + - error nicely on incompatible 0.10 lockfiles + +## 0.9.25 (May 3, 2010) + +Bugfixes: + + - explicitly coerce Pathname objects to Strings for Ruby 1.9 + - fix some newline weirdness in output from install command + +## 0.9.24 (April 22, 2010) + +Features: + + - fetch submodules for git sources + - limit the bundled version of bundler to the same as the one installing + - force relative paths in git gemspecs to avoid raising Gem::NameTooLong + - serialize GemCache sources correctly, so locking works + - raise Bundler::GemNotFound instead of calling exit! inside library code + - Rubygems 1.3.5 compatibility for the adventurous, not supported by me :) + +Bugfixes: + + - don't try to regenerate environment.rb if it is read-only + - prune outdated gems with the platform "ruby" + - prune cache without errors when there are directories or non-gem files + - don't re-write environment.rb if running after it has been loaded + - do not monkeypatch Specification#load_paths twice when inside a bundle + +## 0.9.23 (April 20, 2010) + +Bugfixes: + + - cache command no longer prunes gems created by an older rubygems version + - cache command no longer prunes gems that are for other platforms + +## 0.9.22 (April 20, 2010) + +Features: + + - cache command now prunes stale .gem files from vendor/cache + - init --gemspec command now generates development dependencies + - handle Polyglot's changes to Kernel#require with Bundler::ENV_LOADED (#287) + - remove .gem files generated after installing a gem from a :path (#286) + - improve install/lock messaging (#284) + +Bugfixes: + + - ignore cached gems that are for another platform (#288) + - install Windows gems that have no architecture set, like rcov (#277) + - exec command while locked now includes the bundler lib in $LOAD_PATH (#293) + - fix the `rake install` task + - add GemspecError so it can be raised without (further) error (#292) + - create a parent directory before cloning for git 1.5 compatibility (#285) + +## 0.9.21 (April 16, 2010) + +Bugfixes: + + - don't raise 'omg wtf' when lockfile is outdated + +## 0.9.20 (April 15, 2010) + +Features: + + - load YAML format gemspecs + - no backtraces when calling Bundler.setup if gems are missing + - no backtraces when trying to exec a file without the executable bit + +Bugfixes: + + - fix infinite recursion in Bundler.setup after loading a bundled Bundler gem + - request install instead of lock when env.rb is out of sync with Gemfile.lock + +## 0.9.19 (April 12, 2010) + +Features: + + - suggest `bundle install --relock` when the Gemfile has changed (#272) + - source support for Rubygems servers without prerelease gem indexes (#262) + +Bugfixes: + + - don't set up all groups every time Bundler.setup is called while locked (#263) + - fix #full_gem_path for git gems while locked (#268) + - eval gemspecs at the top level, not inside the Bundler class (#269) + + +## 0.9.18 (April 8, 2010) + +Features: + + - console command that runs irb with bundle (and optional group) already loaded + +Bugfixes: + + - Bundler.setup now fully disables system gems, even when unlocked (#266, #246) + - fixes Yard, which found plugins in Gem.source_index that it could not load + - makes behaviour of `Bundler.require` consistent between locked and unlocked loads + +## 0.9.17 (April 7, 2010) + +Features: + + - Bundler.require now calls Bundler.setup automatically + - Gem::Specification#add_bundler_dependencies added for gemspecs + +Bugfixes: + + - Gem paths are not longer duplicated while loading bundler + - exec no longer duplicates RUBYOPT if it is already set correctly + +## 0.9.16 (April 3, 2010) + +Features: + + - exit gracefully on INT signal + - resolver output now indicates whether remote sources were checked + - print error instead of backtrace when exec cannot find a binary (#241) + +Bugfixes: + + - show, check, and open commands work again while locked (oops) + - show command for git gems + - outputs branch names other than master + - gets the correct sha from the checkout + - doesn't print sha twice if :ref is set + - report errors from bundler/setup.rb without backtraces (#243) + - fix Gem::Spec#git_version to not error on unloaded specs + - improve deprecation, Gemfile, and command error messages (#242) + +## 0.9.15 (April 1, 2010) + +Features: + + - use the env_file if possible instead of doing a runtime resolve + - huge speedup when calling Bundler.setup while locked + - ensures bundle exec is fast while locked + - regenerates env_file if it was generated by an older version + - update cached/packed gems when you update gems via bundle install + +Bugfixes: + + - prep for Rubygems 1.3.7 changes + - install command now pulls git branches correctly (#211) + - raise errors on invalid options in the Gemfile + +## 0.9.14 (March 30, 2010) + +Features: + + - install command output vastly improved + - installation message now accurate, with 'using' and 'installing' + - bundler gems no longer listed as 'system gems' + - show command output now includes sha and branch name for git gems + - init command now takes --gemspec option for bootstrapping gem Gemfiles + - Bundler.with_clean_env for shelling out to ruby scripts + - show command now aliased as 'list' + - VISUAL env var respected for GUI editors + +Bugfixes: + + - exec command now finds binaries from gems with no gemspec + - note source of Gemfile resolver errors + - don't blow up if git urls are changed + +## 0.9.13 (March 23, 2010) + +Bugfixes: + + - exec command now finds binaries from gems installed via :path + - gem dependencies are pulled in even if their type is nil + - paths with spaces have double-quotes to work on Windows + - set GEM_PATH in environment.rb so generators work with Rails 2 + +## 0.9.12 (March 17, 2010) + + - refactoring, internal cleanup, more solid specs + +Features: + + - check command takes a --without option + - check command exits 1 if the check fails + +Bugfixes: + + - perform a topological sort on resolved gems (#191) + - gems from git work even when paths or repos have spaces (#196) + - Specification#loaded_from returns a String, like Gem::Specification (#197) + - specs eval from inside the gem directory, even when locked + - virtual gemspecs are now saved in environment.rb for use when loading + - unify the Installer's local index and the runtime index (#204) + +## 0.9.11 (March 9, 2010) + + - added roadmap with future development plans + +Features: + + - install command can take the path to the gemfile with --gemfile (#125) + - unknown command line options are now rejected (#163) + - exec command hugely sped up while locked (#177) + - show command prints the install path if you pass it a gem name (#148) + - open command edits an installed gem with $EDITOR (#148) + - Gemfile allows assigning an array of groups to a gem (#114) + - Gemfile allows :tag option on :git sources + - improve backtraces when a gemspec is invalid + - improve performance by installing gems from the cache if present + +Bugfixes: + + - normalize parameters to Bundler.require (#153) + - check now checks installed gems rather than cached gems (#162) + - don't update the gem index when installing after locking (#169) + - bundle parenthesises arguments for 1.8.6 (#179) + - gems can now be assigned to multiple groups without problems (#135) + - fix the warning when building extensions for a gem from git with Rubygems 1.3.6 + - fix a Dependency.to_yaml error due to accidentally including sources and groups + - don't reinstall packed gems + - fix gems with git sources that are private repositories + +## 0.9.10 (March 1, 2010) + + - depends on Rubygems 1.3.6 + +Bugfixes: + + - support locking after install --without + - don't reinstall gems from the cache if they're already in the bundle + - fixes for Ruby 1.8.7 and 1.9 + +## 0.9.9 (February 25, 2010) + +Bugfixes: + + - don't die if GEM_HOME is an empty string + - fixes for Ruby 1.8.6 and 1.9 + +## 0.9.8 (February 23, 2010) + +Features: + + - pack command which both caches and locks + - descriptive error if a cached gem is missing + - remember the --without option after installing + - expand paths given in the Gemfile via the :path option + - add block syntax to the git and group options in the Gemfile + - support gems with extensions that don't admit they depend on rake + - generate gems using gem build gemspec so git gems can have native extensions + - print a useful warning if building a gem fails + - allow manual configuration via BUNDLE_PATH + +Bugfixes: + + - eval gemspecs in the gem directory so relative paths work + - make default spec for git sources valid + - don't reinstall gems that are already packed + +## 0.9.7 (February 17, 2010) + +Bugfixes: + + - don't say that a gem from an excluded group is "installing" + - improve crippling rubygems in locked scenarios + +## 0.9.6 (February 16, 2010) + +Features: + + - allow String group names + - a number of improvements in the documentation and error messages + +Bugfixes: + + - set SourceIndex#spec_dirs to solve a problem involving Rails 2.3 in unlocked mode + - ensure Rubygems is fully loaded in Ruby 1.9 before patching it + - fix `bundle install` for a locked app without a .bundle directory + - require gems in the order that the resolver determines + - make the tests platform agnostic so we can confirm that they're green on JRuby + - fixes for Ruby 1.9 + +## 0.9.5 (Feburary 12, 2010) + +Features: + + - added support for :path => "relative/path" + - added support for older versions of git + - added `bundle install --disable-shared-gems` + - Bundler.require fails silently if a library does not have a file on the load path with its name + - Basic support for multiple rubies by namespacing the default bundle path using the version and engine + +Bugfixes: + + - if the bundle is locked and .bundle/environment.rb is not present when Bundler.setup is called, generate it + - same if it's not present with `bundle check` + - same if it's not present with `bundle install` diff --git a/bundler-1.7.2/CONTRIBUTING.md b/bundler-1.7.2/CONTRIBUTING.md new file mode 100644 index 0000000..a2fc0ce --- /dev/null +++ b/bundler-1.7.2/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing + +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. + +Thanks for helping us make Bundler better. + +# Troubleshooting + +If you're having a problem, please see [ISSUES](https://github.com/bundler/bundler/blob/master/ISSUES.md) for troubleshooting steps and a guide for how to submit a ticket that will help us solve the problem you are having as quickly as possible. + +# Requesting Features + +Head on over to the [Bundler features](https://github.com/bundler/bundler-features) project, or any of the lists or channels listed below. Feature-wise we consider Bundler stable, so the core team does not tend to work on feature suggestions. Pull requests welcome though! + +# Discussing Bundler + +If you'd like to discuss features, ask questions, or just engage in general Bundler-focused discussion, please see the [#bundler](irc://irc.freenode.net/#bundler) IRC channel on Freenode, and the [Bundler mailing list](http://groups.google.com/group/ruby-bundler) on Google Groups. diff --git a/bundler-1.7.2/DEVELOPMENT.md b/bundler-1.7.2/DEVELOPMENT.md new file mode 100644 index 0000000..dc52a99 --- /dev/null +++ b/bundler-1.7.2/DEVELOPMENT.md @@ -0,0 +1,117 @@ +Great to have you here! Here are a few ways you can help out with [Bundler](http://github.com/bundler/bundler). + +# 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. + +## Your first commits + +If you’re interested in contributing to Bundler, that’s awesome! We’d love your help. + +If you have any questions after reading this page, please feel free to contact either [@indirect](http://github.com/indirect) or [@hone](http://github.com/hone). They are both happy to provide help working through your first bugfix or thinking through the problem you’re trying to resolve. + +## Tackle some small problems + +We track [small +bugs](https://github.com/bundler/bundler/issues?labels=small&state=open) and [small features](https://github.com/bundler/bundler-features/issues?labels=small&state=open) so that anyone who wants to help can start with something that's not too overwhelming. If nothing on those lists looks good, though, just talk to us. + + +# Development setup + +Bundler doesn't use a Gemfile to list development dependencies, because when we tried it we couldn't tell if we were awake or it was just another level of dreams. To work on Bundler, you'll probably want to do a couple of things. + + 1. Install Bundler's development dependencies + + $ rake spec:deps + + 2. Run the test suite, to make sure things are working + + $ rake spec + + 3. Set up a shell alias to run Bundler from your clone, e.g. a Bash alias: + + $ alias dbundle='ruby -I /path/to/bundler/lib /path/to/bundler/bin/bundle' + + With that set up, you can test changes you've made to Bundler by running `dbundle`, without interfering with the regular `bundle` command. + + +# Bug triage + +Triage is the work of processing tickets that have been opened into actionable issues, feature requests, or bug reports. That includes verifying bugs, categorizing the ticket, and ensuring there's enough information to reproduce the bug for anyone who wants to try to fix it. + +We've created an [issues guide](https://github.com/bundler/bundler/blob/master/ISSUES.md) to walk Bundler users through the process of troubleshooting issues and reporting bugs. + +If you'd like to help, awesome! You can [report a new bug](https://github.com/bundler/bundler/issues/new) or browse our [existing open tickets](https://github.com/bundler/bundler/issues). + +Not every ticket will point to a bug in Bundler's code, but open tickets usually mean that there is something we could improve to help that user. Sometimes that means writing additional documentation, sometimes that means making error messages clearer, and sometimes that means explaining to a user that they need to install git to use git gems. + +When you're looking at a ticket, here are the main questions to ask: + + * Can I reproduce this bug myself? + * Are the steps to reproduce clearly stated in the ticket? + * Which versions of Bundler (1.1.x, 1.2.x, git, etc.) manifest this bug? + * Which operating systems (OS X, Windows, Ubuntu, CentOS, etc.) manifest this bug? + * Which rubies (MRI, JRuby, Rubinius, etc.) and which versions (1.8.7, 1.9.3, etc.) have this bug? + +If you can't reproduce an issue, chances are good that the bug has been fixed (hurrah!). That's a good time to post to the ticket explaining what you did and how it worked. + +If you can reproduce an issue, you're well on your way to fixing it. :) Fixing issues is similar to adding new features: + + 1. Discuss the fix on the existing issue. Coordinating with everyone else saves duplicate work and serves as a great way to get suggestions and ideas if you need any. + 2. Base your commits on the correct branch. Bugfixes for 1.x versions of Bundler should be based on the matching 1-x-stable branch. + 3. Commit the code and at least one test covering your changes to a named 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 “Bugfixes” heading. + 5. Send us a [pull request](https://help.github.com/articles/using-pull-requests) from your bugfix branch. + +Finally, the ticket may be a duplicate of another older ticket. If you notice a ticket is a duplicate, simply comment on the ticket noting the original ticket’s number. For example, you could say “This is a duplicate of issue #42, and can be closed”. + + +# Adding new features + +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. + 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. + 5. Send us a [pull request](https://help.github.com/articles/using-pull-requests) from your feature branch. + +If you don't hear back immediately, don’t get discouraged! We all have day jobs, but we respond to most tickets within a day or two. + + +# Beta testing + +Early releases require heavy testing, especially across various system setups. We :heart: testers, and are big fans of anyone who can run `gem install bundler --pre` and try out upcoming releases in their development and staging environments. + +There may not always be prereleases or beta versions of Bundler. That said, you are always welcome to try checking out master and building a gem yourself if you want to try out the latest changes. + + +# Translations + +We don't currently have any translations, but please reach out to us if you would like to help get this going. + + +# Documentation + +Code needs explanation, and sometimes those who know the code well have trouble explaining it to someone just getting into it. Because of that, we welcome documentation suggestions and patches from everyone, especially if they are brand new to using Bundler. + +Bundler has two main sources of documentation: the built-in help (including usage information and man pages) and the [Bundler documentation site](http://bundler.io). + +If you’d like to submit a patch to the man pages, follow the steps for adding a feature above. All of the man pages are located in the `man` directory. Just use the “Documentation” heading when you describe what you did in the changelog. + +If you have a suggestion or proposed change for [bundler.io](http://bundler.io), please open an issue or send a pull request to the [bundler-site](https://github.com/bundler/bundler-site) repository. + + +# Community + +Community is an important part of all we do. If you’d like to be part of the Bundler community, you can jump right in and start helping make Bundler better for everyone who uses it. + +It would be tremendously helpful to have more people answering questions about Bundler (and often simply about Rubygems or Ruby itself) in our [issue tracker](https://github.com/bundler/bundler/issues) or on [Stack Overflow](http://stackoverflow.com/questions/tagged/bundler). + +Additional documentation and explanation is always helpful, too. If you have any suggestions for the Bundler website [bundler.io](http://bundler.io), we would absolutely love it if you opened an issue or pull request on the [bundler-site](https://github.com/bundler/bundler-site) repository. + +Finally, sharing your experiences and discoveries by writing them up is a valuable way to help others who have similar problems or experiences in the future. You can write a blog post, create an example and commit it to Github, take screenshots, or make videos. + +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. diff --git a/bundler-1.7.2/ISSUES.md b/bundler-1.7.2/ISSUES.md new file mode 100644 index 0000000..560f650 --- /dev/null +++ b/bundler-1.7.2/ISSUES.md @@ -0,0 +1,96 @@ +# Bundler Issues + +So! You're having problems with Bundler. This file is here to help. If you're running into an error, try reading the rest of this file for help. If you can't figure out how to solve your problem, there are also instructions on how to report a bug. + +**Please use the [Bundler +Features](https://github.com/bundler/bundler-features) repo to suggest and +discuss features. The bundler issue tracker is only for bugs.** + +## Documentation + +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). + +## Troubleshooting + +### Heroku errors + +Please open a ticket with Heroku if you're having trouble deploying. They have a professional support team who can help you resolve Heroku issues far better than the Bundler team can. If the problem that you are having turns out to be a bug in Bundler itself, Heroku support can get the exact details to us. + +### Other problems + +First, figure out exactly what it is that you're trying to do. Then, go to the [Bundler documentation website](http://bundler.io) and see if we have instructions on how to do that. + +Second, check [the compatibility +list](http://bundler.io/compatibility.html), and make sure that the version of Bundler that you are +using works with the versions of Ruby and Rubygems that you are using. + +If the instructions don't work, or you can't find any instructions, you can try these troubleshooting steps: + + # remove user-specific gems and git repos + rm -rf ~/.bundle/ ~/.gem/bundler/ ~/.gems/cache/bundler/ + + # remove system-wide git repos and git checkouts + rm -rf $GEM_HOME/bundler/ $GEM_HOME/cache/bundler/ + + # remove project-specific settings + rm -rf .bundle/ + + # remove project-specific cached gems and repos + rm -rf vendor/cache/ + + # remove the saved resolve of the Gemfile + rm -rf Gemfile.lock + + # uninstall the rubygems-bundler and open_gem gems + rvm gemset use global # if using rvm + gem uninstall rubygems-bundler open_gem + + # try to install one more time + bundle install + +## Reporting unresolved problems + +Hopefully the troubleshooting steps above resolved your problem. If things still aren't working the way you expect them to, please let us know so that we can diagnose and hopefully fix the problem you're having. + +**The best way to report a bug is by providing a reproduction script.** See these examples: + +* [Git environment variables causing install to fail.](https://gist.github.com/xaviershay/6207550) +* [Multiple gems in a repository cannot be updated independently.](https://gist.github.com/xaviershay/6295889) + +A half working script with comments for the parts you were unable to automate is still appreciated. + +If you are unable to do that, please include the following information in your report: + + - What you're trying to accomplish + - The command you ran + - What you expected to happen + - What actually happened + - The exception backtrace(s), if any + - Everything output by running `bundle env` + +If your version of Bundler does not have the `bundle env` command, then please include: + + - Your Gemfile + - Your Gemfile.lock + - Your Bundler configuration settings (run `bundle config`) + - What version of bundler you are using (run `bundle -v`) + - What version of Ruby you are using (run `ruby -v`) + - What version of Rubygems you are using (run `gem -v`) + - Whether you are using RVM, and if so what version (run `rvm -v`) + - Whether you have the `rubygems-bundler` gem, which can break gem executables (run `gem list rubygems-bundler`) + - Whether you have the `open_gem` gem, which can cause rake activation conflicts (run `gem list open_gem`) + +If you are using Rails 2.3, please also include: + + - Your boot.rb file + - Your preinitializer.rb file + - Your environment.rb file + + +If you have either `rubygems-bundler` or `open_gem` installed, please try removing them and then following the troubleshooting steps above before opening a new ticket. + +[Create a gist](https://gist.github.com) containing all of that information, then visit the [Bundler issue tracker](https://github.com/bundler/bundler/issues) and [create a ticket](https://github.com/bundler/bundler/issues/new) describing your problem and linking to your gist. + +Thanks for reporting issues and helping make Bundler better! diff --git a/bundler-1.7.2/LICENSE.md b/bundler-1.7.2/LICENSE.md new file mode 100644 index 0000000..e356f59 --- /dev/null +++ b/bundler-1.7.2/LICENSE.md @@ -0,0 +1,23 @@ +Portions copyright (c) 2010 Andre Arko +Portions copyright (c) 2009 Engine Yard + +MIT License + +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 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/bundler-1.7.2/README.md b/bundler-1.7.2/README.md new file mode 100644 index 0000000..ef5a8fe --- /dev/null +++ b/bundler-1.7.2/README.md @@ -0,0 +1,40 @@ +[![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) + +# Bundler: a gem to bundle gems +Bundler keeps ruby applications running 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. + +### Installation and usage + +``` +gem install bundler +bundle init +echo "gem 'rails'" >> Gemfile +bundle install +bundle exec rails new myapp +``` + +See [bundler.io](http://bundler.io) for the full documentation. + +### Troubleshooting + +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). diff --git a/bundler-1.7.2/Rakefile b/bundler-1.7.2/Rakefile new file mode 100644 index 0000000..3775c3d --- /dev/null +++ b/bundler-1.7.2/Rakefile @@ -0,0 +1,256 @@ +# -*- encoding: utf-8 -*- +$:.unshift File.expand_path("../lib", __FILE__) +require 'rubygems' +require 'shellwords' +require 'benchmark' + +RUBYGEMS_REPO = File.expand_path("tmp/rubygems") + +def safe_task(&block) + yield + true +rescue + false +end + +# Benchmark task execution +module Rake + class Task + alias_method :real_invoke, :invoke + + def invoke(*args) + time = Benchmark.measure(@name) do + real_invoke(*args) + end + puts "#{@name} ran for #{time}" + end + end +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| + [d.name, d.requirement.to_s] + end] + + # JRuby can't build ronn or rdiscount, so we skip that + if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' + deps.delete("ronn") + deps.delete("rdiscount") + end + + deps.each do |name, version| + sh "#{Gem.ruby} -S gem list -i '^#{name}$' -v '#{version}' || " \ + "#{Gem.ruby} -S gem install #{name} -v '#{version}' --no-ri --no-rdoc" + end + + # Download and install gems used inside tests + $LOAD_PATH.unshift("./spec") + require 'support/rubygems_ext' + Spec::Rubygems.setup + end + + namespace :travis do + task :deps do + # Give the travis user a name so that git won't fatally error + system "sudo sed -i 's/1000::/1000:Travis:/g' /etc/passwd" + # Strip secure_path so that RVM paths transmit through sudo -E + system "sudo sed -i '/secure_path/d' /etc/sudoers" + # Install groff for the ronn gem + sh "sudo apt-get install groff -y" + if RUBY_VERSION < '1.9' + # Downgrade Rubygems on 1.8 so Ronn can be required + # https://github.com/rubygems/rubygems/issues/784 + sh "gem update --system 2.1.11" + else + # Downgrade Rubygems so RSpec 3 can be instaled + # https://github.com/rubygems/rubygems/issues/813 + sh "gem update --system 2.2.0" + end + # Install the other gem deps, etc. + Rake::Task["spec:deps"].invoke + end + end +end + +begin + 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 + task :spec => "man:build" + + namespace :spec do + task :clean do + rm_rf 'tmp' + end + + desc "Run the real-world spec suite (requires internet)" + task :realworld => ["set_realworld", "spec"] + + task :set_realworld do + ENV['BUNDLER_REALWORLD_TESTS'] = '1' + end + + desc "Run the spec suite with the sudo tests" + task :sudo => ["set_sudo", "spec", "clean_sudo"] + + task :set_sudo do + ENV['BUNDLER_SUDO_TESTS'] = '1' + end + + task :clean_sudo do + puts "Cleaning up sudo test files..." + system "sudo rm -rf #{File.expand_path('../tmp/sudo_gem_home', __FILE__)}" + end + + # Rubygems specs by version + namespace :rubygems do + 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) + (branches + releases).each do |rg| + desc "Run specs with Rubygems #{rg}" + RSpec::Core::RakeTask.new(rg) do |t| + t.rspec_opts = %w(--format documentation --color) + t.ruby_opts = %w(-w) + end + + # Create tasks like spec:rubygems:v1.8.3:sudo to run the sudo specs + namespace rg do + task :sudo => ["set_sudo", rg, "clean_sudo"] + task :realworld => ["set_realworld", rg] + end + + task "clone_rubygems_#{rg}" do + unless File.directory?("tmp/rubygems") + system("git clone https://github.com/rubygems/rubygems.git tmp/rubygems") + end + hash = nil + + Dir.chdir(RUBYGEMS_REPO) do + system("git remote update") + if rg == "master" + system("git checkout origin/master") + else + system("git checkout #{rg}") || raise("Unknown Rubygems ref #{rg}") + end + hash = `git rev-parse HEAD`.chomp + end + + puts "Checked out rubygems '#{rg}' at #{hash}" + ENV["RUBYOPT"] = "-I#{File.expand_path("tmp/rubygems/lib")} #{rubyopt}" + puts "RUBYOPT=#{ENV['RUBYOPT']}" + end + + task rg => ["man:build", "clone_rubygems_#{rg}"] + task "rubygems:all" => rg + end + + desc "Run specs under a Rubygems checkout (set RG=path)" + RSpec::Core::RakeTask.new("co") do |t| + t.rspec_opts = %w(--format documentation --color) + t.ruby_opts = %w(-w) + end + + task "setup_co" do + ENV["RUBYOPT"] = "-I#{File.expand_path ENV['RG']} #{rubyopt}" + end + + task "co" => "setup_co" + task "rubygems:all" => "co" + end + + desc "Run the tests on Travis CI against a rubygem version (using ENV['RGV'])" + task :travis do + rg = ENV['RGV'] || raise("Rubygems version is required on Travis!") + + puts "\n\e[1;33m[Travis CI] Running bundler specs against rubygems #{rg}\e[m\n\n" + specs = safe_task { Rake::Task["spec:rubygems:#{rg}"].invoke } + + Rake::Task["spec:rubygems:#{rg}"].reenable + + puts "\n\e[1;33m[Travis CI] Running bundler sudo specs against rubygems #{rg}\e[m\n\n" + sudos = system("sudo -E rake spec:rubygems:#{rg}:sudo") + # clean up by chowning the newly root-owned tmp directory back to the travis user + system("sudo chown -R #{ENV['USER']} #{File.join(File.dirname(__FILE__), 'tmp')}") + + Rake::Task["spec:rubygems:#{rg}"].reenable + + puts "\n\e[1;33m[Travis CI] Running bundler real world specs against rubygems #{rg}\e[m\n\n" + realworld = safe_task { Rake::Task["spec:rubygems:#{rg}:realworld"].invoke } + + {"specs" => specs, "sudo" => sudos, "realworld" => realworld}.each do |name, passed| + if passed + puts "\e[0;32m[Travis CI] #{name} passed\e[m" + else + puts "\e[0;31m[Travis CI] #{name} failed\e[m" + end + end + + unless specs && sudos && realworld + fail "Spec run failed, please review the log for more information" + end + end + end + +rescue LoadError + task :spec do + abort "Run `rake spec:deps` to be able to run the specs" + end +end + +begin + require 'ronn' + + namespace :man do + directory "lib/bundler/man" + + Dir["man/*.ronn"].each do |ronn| + basename = File.basename(ronn, ".ronn") + roff = "lib/bundler/man/#{basename}" + + file roff => ["lib/bundler/man", ronn] do + sh "#{Gem.ruby} -S ronn --roff --pipe #{ronn} > #{roff}" + end + + file "#{roff}.txt" => roff do + sh "groff -Wall -mtty-char -mandoc -Tascii #{roff} | col -b > #{roff}.txt" + end + + task :build_all_pages => "#{roff}.txt" + end + + desc "Build the man pages" + task :build => "man:build_all_pages" + + desc "Clean up from the built man pages" + task :clean do + rm_rf "lib/bundler/man" + end + 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!" } + end +end + +desc "Update vendored SSL certs to match the certs vendored by Rubygems" +task :update_certs => "spec:rubygems:clone_rubygems_master" do + require 'bundler/ssl_certs/certificate_manager' + Bundler::SSLCerts::CertificateManager.update_from!(RUBYGEMS_REPO) +end + +require 'bundler/gem_tasks' +task :build => ["man:clean", "man:build"] +task :release => ["man:clean", "man:build"] + +task :default => :spec diff --git a/bundler-1.7.2/UPGRADING.md b/bundler-1.7.2/UPGRADING.md new file mode 100644 index 0000000..665be21 --- /dev/null +++ b/bundler-1.7.2/UPGRADING.md @@ -0,0 +1,103 @@ +## Bundler 0.9 to 1.0 and above + +Upgrading from Bundler 0.9 to 1.0 is relatively painless. The +Gemfile API is the same, so your old Gemfiles should continue +to work. + +The "env" file that 0.9 created at `.bundle/environment.rb` has been +removed. As a side effect of this, Passenger will only find your +bundled gems if you install with `bundle install --deployment`. +Alternatively, you can tell Passenger where you gems are installed, +[something like this](http://andre.arko.net/2010/08/16/using-passengerpane-with-gem_home-set/). + +The `bundle lock` command is no longer needed, as the +Gemfile.lock file is now automatically generated by `bundle install`. +If you have not yet done so, add your Gemfile.lock to source control +and check it in. + +Running `bundle install` no longer updates the versions of your gems. +If you need to update just one gem, run `bundle update GEMNAME`. To +update all gems to the newest versions possible, run `bundle update`. + +Bundler now supports multiple platforms, using a block syntax to +declare platform-specific gems: + + platform :jruby do + gem "jruby-maven-plugins" + end + +Deploying using Bundler is even easier than it was before, as Bundler +now includes a Capistrano recipe. Simply add this line to the top of +your deploy.rb file to run Bundler automatically as part of deploying: + + require 'bundler/capistrano' + +For more details on deploying using bundler, see the documentation +for the bundler cap task, and the [documentation on deploying](http://bundler.io/deploying.html). + + +## Bundler 0.8 to 0.9 and above + +Upgrading to Bundler 0.9 from Bundler 0.8 requires upgrading several +API calls in your Gemfile, and some workarounds if you are using Rails 2.3. + +### Gemfile Removals + +Bundler 0.9 removes the following Bundler 0.8 Gemfile APIs: + +1. `disable_system_gems`: This is now the default (and only) option + for bundler. Bundler uses the system gems you have specified + in the Gemfile, and only the system gems you have specified + (and their dependencies) +2. `disable_rubygems`: This is no longer supported. We are looking + into ways to get the fastest performance out of each supported + scenario, and we will make speed the default where possible. +3. `clear_sources`: Bundler now defaults to an empty source + list. If you want to include Rubygems, you can add the source + via source "http://gemcutter.org". If you use bundle init, this + source will be automatically added for you in the generated + Gemfile +4. `bundle_path`: You can specify this setting when installing + via `bundle install /path/to/bundle`. Bundler will remember + where you installed the dependencies to on a particular + machine for future installs, loads, setups, etc. +5. `bin_path`: Bundler no longer generates executables in the root + of your app. You should use `bundle exec` to execute executables + in the current context. + +### Gemfile Changes + +Bundler 0.9 changes the following Bundler 0.8 Gemfile APIs: + +1. Bundler 0.8 supported :only and :except as APIs for describing + groups of gems. Bundler 0.9 supports a single `group` method, + which you can use to group gems together. See the above "Group" + section for more information. + + This means that `gem "foo", :only => :production` becomes + `gem "foo", :group => :production`, and + `only :production { gem "foo" }` becomes + `group :production { gem "foo" }` + + The short version is: group your gems together logically, and + use the available commands to make use of the groups you've + created. + +2. `:require_as` becomes `:require` + +3. `:vendored_at` is fully removed; you should use `:path` + +### API Changes + +1. `Bundler.require_env(:environment)` becomes + `Bundler.require(:multiple, :groups)`. You must + now specify the default group (the default group is the + group made up of the gems not assigned to any group) + explicitly. So `Bundler.require_env(:test)` becomes + `Bundler.require(:default, :test)` + +2. `require 'vendor/gems/environment'`: In unlocked + mode, where using system gems, this becomes + `Bundler.setup(:multiple, :groups)`. If you don't + specify any groups, this puts all groups on the load + path. In locked mode, it becomes `require '.bundle/environment'` diff --git a/bundler-1.7.2/bin/bundle b/bundler-1.7.2/bin/bundle new file mode 100644 index 0000000..63285e9 --- /dev/null +++ b/bundler-1.7.2/bin/bundle @@ -0,0 +1,21 @@ +#!/usr/bin/env ruby + +# Exit cleanly from an early interrupt +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 + 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`." + abort(err) + end +end + +require 'bundler/friendly_errors' +Bundler.with_friendly_errors do + require 'bundler/cli' + Bundler::CLI.start(ARGV, :debug => true) +end diff --git a/bundler-1.7.2/bin/bundle_ruby b/bundler-1.7.2/bin/bundle_ruby new file mode 100644 index 0000000..1e02c57 --- /dev/null +++ b/bundler-1.7.2/bin/bundle_ruby @@ -0,0 +1,56 @@ +#!/usr/bin/env ruby + +Signal.trap("INT") { exit 1 } + +require 'bundler/ruby_version' +require 'bundler/ruby_dsl' +require 'bundler/shared_helpers' + +module Bundler + class GemfileError < RuntimeError; end + class Dsl + include RubyDsl + + attr_accessor :ruby_version + + def initialize + @ruby_version = nil + end + + def eval_gemfile(gemfile, contents = nil) + contents ||= File.open(gemfile, "rb") { |f| f.read } + instance_eval(contents, gemfile.to_s, 1) + rescue SyntaxError => e + bt = e.message.split("\n")[1..-1] + raise GemfileError, ["Gemfile syntax error:", *bt].join("\n") + rescue ScriptError, RegexpError, NameError, ArgumentError => e + e.backtrace[0] = "#{e.backtrace[0]}: #{e.message} (#{e.class})" + STDERR.puts e.backtrace.join("\n ") + raise GemfileError, "There was an error in your Gemfile," \ + " and Bundler cannot continue." + end + + def source(source, options = {}) + end + + def gem(name, *args) + end + + def group(*args, &blk) + end + end +end + +dsl = Bundler::Dsl.new +begin + dsl.eval_gemfile(Bundler::SharedHelpers.default_gemfile) + ruby_version = dsl.ruby_version + if ruby_version + puts ruby_version + else + puts "No ruby version specified" + end +rescue Bundler::GemfileError => e + puts e.message + exit(-1) +end diff --git a/bundler-1.7.2/bin/bundler b/bundler-1.7.2/bin/bundler new file mode 100644 index 0000000..63285e9 --- /dev/null +++ b/bundler-1.7.2/bin/bundler @@ -0,0 +1,21 @@ +#!/usr/bin/env ruby + +# Exit cleanly from an early interrupt +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 + 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`." + abort(err) + end +end + +require 'bundler/friendly_errors' +Bundler.with_friendly_errors do + require 'bundler/cli' + Bundler::CLI.start(ARGV, :debug => true) +end diff --git a/bundler-1.7.2/bundler.gemspec b/bundler-1.7.2/bundler.gemspec new file mode 100644 index 0000000..dc8fbc8 --- /dev/null +++ b/bundler-1.7.2/bundler.gemspec @@ -0,0 +1,29 @@ +# coding: utf-8 +lib = File.expand_path('../lib/', __FILE__) +$:.unshift lib unless $:.include?(lib) +require 'bundler/version' + +Gem::Specification.new do |spec| + spec.name = 'bundler' + spec.version = Bundler::VERSION + spec.licenses = ['MIT'] + spec.authors = ["André Arko", "Terence Lee", "Carl Lerche", "Yehuda Katz"] + spec.email = ["andre@arko.net"] + spec.homepage = "http://bundler.io" + spec.summary = %q{The best way to manage your application's dependencies} + spec.description = %q{Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably} + + spec.required_ruby_version = '>= 1.8.7' + spec.required_rubygems_version = '>= 1.3.6' + + spec.add_development_dependency 'rdiscount', '~> 1.6' + spec.add_development_dependency 'ronn', '~> 0.7.3' + spec.add_development_dependency 'rspec', '~> 3.0' + + spec.files = `git ls-files -z`.split("\x0") + spec.files += Dir.glob('lib/bundler/man/**/*') # man/ is ignored by git + spec.test_files = spec.files.grep(%r{^spec/}) + + spec.executables = %w(bundle bundler) + spec.require_paths = ["lib"] +end diff --git a/bundler-1.7.2/lib/bundler.rb b/bundler-1.7.2/lib/bundler.rb new file mode 100644 index 0000000..1eaf194 --- /dev/null +++ b/bundler-1.7.2/lib/bundler.rb @@ -0,0 +1,428 @@ +require 'fileutils' +require 'pathname' +require 'rbconfig' +require 'bundler/gem_path_manipulation' +require 'bundler/rubygems_ext' +require 'bundler/rubygems_integration' +require 'bundler/version' +require 'bundler/constants' +require 'bundler/current_ruby' + +module Bundler + preserve_gem_path + ORIGINAL_ENV = ENV.to_hash + + autoload :Definition, 'bundler/definition' + autoload :Dependency, 'bundler/dependency' + autoload :DepProxy, 'bundler/dep_proxy' + autoload :Deprecate, 'bundler/deprecate' + autoload :Dsl, 'bundler/dsl' + autoload :EndpointSpecification, 'bundler/endpoint_specification' + autoload :Environment, 'bundler/environment' + autoload :Env, 'bundler/env' + autoload :Fetcher, 'bundler/fetcher' + autoload :GemHelper, 'bundler/gem_helper' + autoload :GemHelpers, 'bundler/gem_helpers' + autoload :GemInstaller, 'bundler/gem_installer' + autoload :Graph, 'bundler/graph' + autoload :Index, 'bundler/index' + autoload :Installer, 'bundler/installer' + autoload :Injector, 'bundler/injector' + autoload :LazySpecification, 'bundler/lazy_specification' + autoload :LockfileParser, 'bundler/lockfile_parser' + autoload :MatchPlatform, 'bundler/match_platform' + autoload :RemoteSpecification, 'bundler/remote_specification' + autoload :Resolver, 'bundler/resolver' + autoload :Retry, 'bundler/retry' + autoload :RubyVersion, 'bundler/ruby_version' + autoload :RubyDsl, 'bundler/ruby_dsl' + autoload :Runtime, 'bundler/runtime' + autoload :Settings, 'bundler/settings' + autoload :SharedHelpers, 'bundler/shared_helpers' + autoload :SpecSet, 'bundler/spec_set' + autoload :Source, 'bundler/source' + autoload :SourceList, 'bundler/source_list' + autoload :Specification, 'bundler/shared_helpers' + autoload :SystemRubyVersion, 'bundler/ruby_version' + autoload :UI, 'bundler/ui' + + class BundlerError < StandardError + def self.status_code(code) + define_method(:status_code) { code } + end + end + + class GemfileNotFound < BundlerError; status_code(10) ; end + class GemNotFound < BundlerError; status_code(7) ; end + class GemfileError < BundlerError; status_code(4) ; end + class InstallError < BundlerError; status_code(5) ; end + class InstallHookError < BundlerError; status_code(8) ; end + class PathError < BundlerError; status_code(13) ; end + class GitError < BundlerError; status_code(11) ; end + class DeprecatedError < BundlerError; status_code(12) ; end + class GemspecError < BundlerError; status_code(14) ; end + class InvalidOption < BundlerError; status_code(15) ; end + class ProductionError < BundlerError; status_code(16) ; end + class HTTPError < BundlerError; status_code(17) ; end + class RubyVersionMismatch < BundlerError; status_code(18) ; end + class SecurityError < BundlerError; status_code(19) ; end + class LockfileError < BundlerError; status_code(20) ; end + class CyclicDependencyError < BundlerError; status_code(21) ; end + class GemfileLockNotFound < BundlerError; status_code(22) ; end + + # Internal errors, should be rescued + class VersionConflict < BundlerError + attr_reader :conflicts + + def initialize(conflicts, msg = nil) + super(msg) + @conflicts = conflicts + end + + status_code(6) + end + + class MarshalError < StandardError; end + + class << self + attr_writer :ui, :bundle_path + + def configure + @configured ||= configure_gem_home_and_path + end + + def ui + @ui ||= UI::Silent.new + end + + # Returns absolute path of where gems are installed on the filesystem. + def bundle_path + @bundle_path ||= Pathname.new(settings.path).expand_path(root) + end + + # Returns absolute location of where binstubs are installed to. + def bin_path + @bin_path ||= begin + path = settings[:bin] || "bin" + path = Pathname.new(path).expand_path(root).expand_path + FileUtils.mkdir_p(path) + path + end + end + + def setup(*groups) + # Just return if all groups are already loaded + return @setup if defined?(@setup) + + definition.validate_ruby! + + if groups.empty? + # Load all groups, but only once + @setup = load.setup + else + @completed_groups ||= [] + # Figure out which groups haven't been loaded yet + unloaded = groups - @completed_groups + # Record groups that are now loaded + @completed_groups = groups + unloaded.any? ? load.setup(*groups) : load + end + end + + def require(*groups) + setup(*groups).require(*groups) + end + + def load + @load ||= Runtime.new(root, definition) + end + + def environment + Bundler::Environment.new(root, definition) + end + + # Returns an instance of Bundler::Definition for given Gemfile and lockfile + # + # @param unlock [Hash, Boolean, nil] Gems that have been requested + # to be updated or true if all gems should be updated + # @return [Bundler::Definition] + def definition(unlock = nil) + @definition = nil if unlock + @definition ||= begin + configure + upgrade_lockfile + Definition.build(default_gemfile, default_lockfile, unlock) + end + end + + def locked_gems + return @locked_gems if defined?(@locked_gems) + if Bundler.default_lockfile.exist? + lock = Bundler.read_file(Bundler.default_lockfile) + @locked_gems = LockfileParser.new(lock) + else + @locked_gems = nil + end + end + + def ruby_scope + "#{Bundler.rubygems.ruby_engine}/#{Bundler.rubygems.config_map[:ruby_version]}" + end + + def user_bundle_path + Pathname.new(Bundler.rubygems.user_home).join(".bundler") + end + + def home + bundle_path.join("bundler") + end + + def install_path + home.join("gems") + end + + def specs_path + bundle_path.join("specifications") + end + + def cache + bundle_path.join("cache/bundler") + end + + def root + @root ||= default_gemfile.dirname.expand_path + end + + def app_config_path + ENV['BUNDLE_APP_CONFIG'] ? + Pathname.new(ENV['BUNDLE_APP_CONFIG']).expand_path(root) : + root.join('.bundle') + end + + def app_cache(custom_path = nil) + path = custom_path || root + path.join("vendor/cache") + end + + def tmp(name = Process.pid.to_s) + @tmp ||= Pathname.new Dir.mktmpdir("bundler") + @tmp.join(name) + end + + def settings + @settings ||= begin + Settings.new(app_config_path) + rescue GemfileNotFound + Settings.new + end + end + + def with_original_env + bundled_env = ENV.to_hash + ENV.replace(ORIGINAL_ENV) + yield + ensure + ENV.replace(bundled_env.to_hash) + end + + def with_clean_env + with_original_env do + ENV['MANPATH'] = ENV['BUNDLE_ORIG_MANPATH'] + ENV.delete_if { |k,_| k[0,7] == 'BUNDLE_' } + if ENV.has_key? 'RUBYOPT' + ENV['RUBYOPT'] = ENV['RUBYOPT'].sub '-rbundler/setup', '' + ENV['RUBYOPT'] = ENV['RUBYOPT'].sub "-I#{File.expand_path('..', __FILE__)}", '' + end + yield + end + end + + def clean_system(*args) + with_clean_env { Kernel.system(*args) } + end + + def clean_exec(*args) + with_clean_env { Kernel.exec(*args) } + end + + def default_gemfile + SharedHelpers.default_gemfile + end + + def default_lockfile + SharedHelpers.default_lockfile + 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 + # install binstubs there instead. Unfortunately, Rubygems doesn't expose + # that directory at all, so rather than parse .gemrc ourselves, we allow + # the directory to be set as well, via `bundle config bindir foo`. + Bundler.settings[:system_bindir] || Bundler.rubygems.gem_bindir + end + + def requires_sudo? + return @requires_sudo if defined?(@requires_sudo_ran) + + if settings.allow_sudo? + sudo_present = which "sudo" + end + + if sudo_present + # the bundle path and subdirectories need to be writable for Rubygems + # to be able to unpack and install gems without exploding + path = bundle_path + path = path.parent until path.exist? + + # bins are written to a different location on OS X + bin_dir = Pathname.new(Bundler.system_bindir) + bin_dir = bin_dir.parent until bin_dir.exist? + + # if any directory is not writable, we need sudo + files = [path, bin_dir] | Dir[path.join('build_info/*').to_s] | Dir[path.join('*').to_s] + sudo_needed = files.any?{|f| !File.writable?(f) } + end + + @requires_sudo_ran = true + @requires_sudo = settings.allow_sudo? && sudo_present && sudo_needed + end + + def mkdir_p(path) + if requires_sudo? + sudo "mkdir -p '#{path}'" unless File.exist?(path) + else + FileUtils.mkdir_p(path) + end + end + + def which(executable) + if File.file?(executable) && File.executable?(executable) + executable + elsif ENV['PATH'] + path = ENV['PATH'].split(File::PATH_SEPARATOR).find do |p| + File.executable?(File.join(p, executable)) + end + path && File.expand_path(executable, path) + end + end + + def sudo(str) + prompt = "\n\n" + <<-PROMPT.gsub(/^ {6}/, '').strip + " " + Your user account isn't allowed to install to the system Rubygems. + You can cancel this installation and run: + + bundle install --path vendor/bundle + + to install the gems into ./vendor/bundle/, or you can enter your password + and install the bundled gems to Rubygems using sudo. + + Password: + PROMPT + + `sudo -p "#{prompt}" #{str}` + end + + def read_file(file) + File.open(file, "rb") { |f| f.read } + end + + def load_marshal(data) + Marshal.load(data) + rescue => e + raise MarshalError, "#{e.class}: #{e.message}" + end + + def load_gemspec(file) + @gemspec_cache ||= {} + key = File.expand_path(file) + spec = ( @gemspec_cache[key] ||= load_gemspec_uncached(file) ) + # Protect against caching side-effected gemspecs by returning a + # new instance each time. + spec.dup if spec + end + + def load_gemspec_uncached(file) + path = Pathname.new(file) + # Eval the gemspec from its parent directory, because some gemspecs + # depend on "./" relative paths. + SharedHelpers.chdir(path.dirname.to_s) do + contents = path.read + if contents[0..2] == "---" # YAML header + eval_yaml_gemspec(path, contents) + else + eval_gemspec(path, contents) + end + end + end + + def clear_gemspec_cache + @gemspec_cache = {} + end + + def git_present? + return @git_present if defined?(@git_present) + @git_present = Bundler.which("git") || Bundler.which("git.exe") + end + + def ruby_version + @ruby_version ||= SystemRubyVersion.new + end + + private + + def eval_yaml_gemspec(path, contents) + # If the YAML is invalid, Syck raises an ArgumentError, and Psych + # raises a Psych::SyntaxError. See psyched_yaml.rb for more info. + Gem::Specification.from_yaml(contents) + rescue YamlSyntaxError, ArgumentError, Gem::EndOfYAMLException, Gem::Exception + eval_gemspec(path, contents) + end + + def eval_gemspec(path, contents) + eval(contents, TOPLEVEL_BINDING, path.expand_path.to_s) + rescue ScriptError, StandardError => e + original_line = e.backtrace.find { |line| line.include?(path.to_s) } + msg = "There was a #{e.class} while loading #{path.basename}: \n#{e.message}" + msg << " from\n #{original_line}" if original_line + msg << "\n" + + if e.is_a?(LoadError) && RUBY_VERSION >= "1.9" + msg << "\nDoes it try to require a relative path? That's been removed in Ruby 1.9." + end + + raise GemspecError, msg + end + + def configure_gem_home_and_path + blank_home = ENV['GEM_HOME'].nil? || ENV['GEM_HOME'].empty? + if settings[:disable_shared_gems] + ENV['GEM_PATH'] = '' + elsif blank_home || Bundler.rubygems.gem_dir != bundle_path.to_s + possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path] + paths = possibles.flatten.compact.uniq.reject { |p| p.empty? } + ENV["GEM_PATH"] = paths.join(File::PATH_SEPARATOR) + end + + configure_gem_home + bundle_path + end + + def configure_gem_home + # TODO: This mkdir_p is only needed for JRuby <= 1.5 and should go away (GH #602) + FileUtils.mkdir_p bundle_path.to_s rescue nil + + ENV['GEM_HOME'] = File.expand_path(bundle_path, root) + Bundler.rubygems.clear_paths + end + + def upgrade_lockfile + lockfile = default_lockfile + if lockfile.exist? && lockfile.read(3) == "---" + Bundler.ui.warn "Detected Gemfile.lock generated by 0.9, deleting..." + lockfile.rmtree + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/capistrano.rb b/bundler-1.7.2/lib/bundler/capistrano.rb new file mode 100644 index 0000000..e372a1a --- /dev/null +++ b/bundler-1.7.2/lib/bundler/capistrano.rb @@ -0,0 +1,16 @@ +# Capistrano task for Bundler. +# +# Just add "require 'bundler/capistrano'" in your Capistrano deploy.rb, and +# Bundler will be activated after each new deployment. +require 'bundler/deployment' +require 'capistrano/version' + +if defined?(Capistrano::Version) && Gem::Version.new(Capistrano::Version).release >= Gem::Version.new("3.0") + raise "For Capistrano 3.x integration, please use http://github.com/capistrano/bundler" +end + +Capistrano::Configuration.instance(:must_exist).load do + before "deploy:finalize_update", "bundle:install" + Bundler::Deployment.define_task(self, :task, :except => { :no_release => true }) + set :rake, lambda { "#{fetch(:bundle_cmd, "bundle")} exec rake" } +end diff --git a/bundler-1.7.2/lib/bundler/cli.rb b/bundler-1.7.2/lib/bundler/cli.rb new file mode 100644 index 0000000..c3e5d8b --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli.rb @@ -0,0 +1,372 @@ +require 'bundler' +require 'bundler/vendored_thor' + +module Bundler + class CLI < Thor + include Thor::Actions + + def self.start(*) + super + rescue Exception => e + Bundler.ui = UI::Shell.new + raise e + end + + def initialize(*) + super + ENV['BUNDLE_GEMFILE'] = File.expand_path(options[:gemfile]) if options[:gemfile] + Bundler::Retry.attempts = options[:retry] || Bundler.settings[:retry] || Bundler::Retry::DEFAULT_ATTEMPTS + Bundler.rubygems.ui = UI::RGProxy.new(Bundler.ui) + rescue UnknownArgumentError => e + raise InvalidOption, e.message + ensure + self.options ||= {} + Bundler.ui = UI::Shell.new(options) + Bundler.ui.level = "debug" if options["verbose"] + end + + check_unknown_options!(:except => [:config, :exec]) + 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" + + def help(cli = nil) + case cli + when "gemfile" then command = "gemfile.5" + when nil then command = "bundle" + else command = "bundle-#{cli}" + end + + manpages = %w( + bundle + bundle-config + bundle-exec + bundle-install + bundle-package + bundle-update + bundle-platform + gemfile.5) + + if manpages.include?(command) + root = File.expand_path("../man", __FILE__) + + if Bundler.which("man") && root !~ %r{^file:/.+!/META-INF/jruby.home/.+} + Kernel.exec "man #{root}/#{command}" + else + puts File.read("#{root}/#{command}.txt") + end + else + super + end + 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 + Gemfile to a gem with a gemspec, the --gemspec option will automatically add each + dependency listed in the gemspec file to the newly created Gemfile. + D + method_option "gemspec", :type => :string, :banner => "Use the specified .gemspec to create the Gemfile" + def init + require 'bundler/cli/init' + Init.new(options.dup).run + end + + desc "check [OPTIONS]", "Checks if the dependencies listed in Gemfile are satisfied by currently installed gems" + long_desc <<-D + Check searches the local machine for each of the gems requested in the Gemfile. If + 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 "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 + end + + desc "install [OPTIONS]", "Install the current environment to the system" + long_desc <<-D + Install will install all of the gems in the current bundle, making them available + for use. In a freshly checked out repository, this command will give you the same + gem versions as the last person who updated the Gemfile and ran `bundle update`. + + Passing [DIR] to install (e.g. vendor) will cause the unpacked gems to be installed + into the [DIR] directory rather than into system gems. + + 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 "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 "no-cache", :type => :boolean, :banner => + "Don't update the existing gem cache." + 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 "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" + + def install + require 'bundler/cli/install' + Install.new(options.dup).run + end + + desc "update [OPTIONS]", "update the current environment" + long_desc <<-D + Update will install the newest versions of the gems listed in the Gemfile. Use + 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 "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" + def update(*gems) + require 'bundler/cli/update' + Update.new(options, gems).run + end + + desc "show GEM [OPTIONS]", "Shows all gems that are part of the bundle, or the path to a given gem" + long_desc <<-D + Show lists the names and versions of all gems that are required by your Gemfile. + Calling show with [GEM] will list the exact location of that gem on your machine. + D + method_option "paths", :type => :boolean, + :banner => "List the paths of all gems that are required by your Gemfile." + 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" + 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" + def binstubs(*gems) + require 'bundler/cli/binstubs' + Binstubs.new(options, gems).run + end + + desc "outdated GEM [OPTIONS]", "list installed gems with newer versions available" + long_desc <<-D + Outdated lists the names and versions of gems that have a newer version available + in the given source. Calling outdated with [GEM [GEM]] will only check for newer + 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 "strict", :type => :boolean, :banner => + "Only list newer versions allowed by your Gemfile requirements" + def outdated(*gems) + require 'bundler/cli/outdated' + Outdated.new(options, gems).run + 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)." + 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 "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" + 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 + control repository, others who check out your source will be able to install the + bundle without having to download any additional gems. + D + def package + require 'bundler/cli/package' + Package.new(options).run + end + map %w(pack) => :package + + desc "exec [OPTIONS]", "Run the command in context of the bundle" + method_option :keep_file_descriptors, :type => :boolean, :default => false + long_desc <<-D + Exec runs a command, providing it access to the gems in the bundle. While using + bundle exec you can require and call the bundled gems as if they were installed + into the system wide Rubygems repository. + D + def exec(*args) + require 'bundler/cli/exec' + Exec.new(options, args).run + end + + desc "config NAME [VALUE]", "retrieve or set a configuration value" + long_desc <<-D + Retrieves or sets a configuration value. If only one parameter is provided, retrieve the value. If two parameters are provided, replace the + existing value with the newly provided one. + + By default, setting a configuration value sets it for all projects + on the machine. + + If a global setting is superceded by local configuration, this command + will show the current value, as well as any superceded values and + where they were specified. + D + def config(*args) + require 'bundler/cli/config' + Config.new(options, args, self).run + end + + desc "open GEM", "Opens the source directory of the given bundled gem" + def open(name) + require 'bundler/cli/open' + 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 + end + + desc "version", "Prints the bundler's version information" + def version + Bundler.ui.info "Bundler version #{Bundler::VERSION}" + end + map %w(-v --version) => :version + + desc "licenses", "Prints the license of all gems in the bundle" + def licenses + Bundler.load.specs.sort_by { |s| s.license.to_s }.reverse.each do |s| + gem_name = s.name + license = s.license || s.licenses + + if license.empty? + Bundler.ui.warn "#{gem_name}: Unknown" + else + Bundler.ui.info "#{gem_name}: #{license}" + end + end + end + + desc 'viz [OPTIONS]', "Generates a visual dependency graph" + long_desc <<-D + Viz generates a PNG file of the current Gemfile as a dependency graph. + Viz requires the ruby-graphviz gem (and its dependencies). + 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 ..." + 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" + + def gem(name) + require 'bundler/cli/gem' + Gem.new(options, name, self).run + end + + def self.source_root + File.expand_path(File.join(File.dirname(__FILE__), 'templates')) + end + + 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" + method_option "force", :type => :boolean, :default => false, :banner => + "forces clean even if --path is not set" + def clean + require 'bundler/cli/clean' + Clean.new(options.dup).run + end + + desc "platform [OPTIONS]", "Displays platform compatibility information" + method_option "ruby", :type => :boolean, :default => false, :banner => + "only display ruby related platform information" + def platform + require 'bundler/cli/platform' + Platform.new(options).run + end + + desc "inject GEM VERSION ...", "Add the named gem(s), with version requirements, to the resolved Gemfile" + def inject(name, version, *gems) + require 'bundler/cli/inject' + Inject.new(options, name, version, gems).run + end + + desc "env", "Print information about the environment Bundler is running under" + def env + Env.new.write($stdout) + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/binstubs.rb b/bundler-1.7.2/lib/bundler/cli/binstubs.rb new file mode 100644 index 0000000..d5ff5b6 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/binstubs.rb @@ -0,0 +1,38 @@ +require "bundler/cli/common" + +module Bundler + class CLI::Binstubs + attr_reader :options, :gems + def initialize(options, gems) + @options = options + @gems = gems + end + + def run + Bundler.definition.validate_ruby! + Bundler.settings[:bin] = options["path"] if options["path"] + Bundler.settings[:bin] = nil if options["path"] && options["path"].empty? + installer = Installer.new(Bundler.root, Bundler.definition) + + if gems.empty? + Bundler.ui.error "`bundle binstubs` needs at least one gem to run." + exit 1 + end + + gems.each do |gem_name| + spec = installer.specs.find{|s| s.name == gem_name } + unless spec + raise GemNotFound, Bundler::CLI::Common.gem_not_found_message( + gem_name, Bundler.definition.specs) + end + + if spec.name == "bundler" + Bundler.ui.warn "Sorry, Bundler can only be run via Rubygems." + else + installer.generate_bundler_executable_stubs(spec, :force => options[:force], :binstubs_cmd => true) + end + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/cache.rb b/bundler-1.7.2/lib/bundler/cli/cache.rb new file mode 100644 index 0000000..653ead7 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/cache.rb @@ -0,0 +1,34 @@ +module Bundler + class CLI::Cache + attr_reader :options + def initialize(options) + @options = options + end + + def run + Bundler.definition.validate_ruby! + Bundler.definition.resolve_with_cache! + setup_cache_all + Bundler.load.cache + Bundler.settings[:no_prune] = true if options["no-prune"] + Bundler.load.lock + rescue GemNotFound => e + Bundler.ui.error(e.message) + Bundler.ui.warn "Run `bundle install` to install missing gems." + exit 1 + end + + private + + def setup_cache_all + Bundler.settings[:cache_all] = options[:all] if options.key?("all") + + if Bundler.definition.has_local_dependencies? && !Bundler.settings[:cache_all] + Bundler.ui.warn "Your Gemfile contains path and git dependencies. If you want " \ + "to package them as well, please pass the --all flag. This will be the default " \ + "on Bundler 2.0." + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/check.rb b/bundler-1.7.2/lib/bundler/cli/check.rb new file mode 100644 index 0000000..071bcc3 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/check.rb @@ -0,0 +1,35 @@ +module Bundler + class CLI::Check + attr_reader :options + def initialize(options) + @options = options + end + + def run + Bundler.settings[:path] = File.expand_path(options[:path]) if options[:path] + begin + definition = Bundler.definition + definition.validate_ruby! + not_installed = definition.missing_specs + rescue GemNotFound, VersionConflict + Bundler.ui.error "Bundler can't satisfy your Gemfile's dependencies." + Bundler.ui.warn "Install missing gems with `bundle install`." + exit 1 + end + + if not_installed.any? + Bundler.ui.error "The following gems are missing" + not_installed.each { |s| Bundler.ui.error " * #{s.name} (#{s.version})" } + Bundler.ui.warn "Install missing gems with `bundle install`" + exit 1 + elsif !Bundler.default_lockfile.exist? && Bundler.settings[:frozen] + Bundler.ui.error "This bundle has been frozen, but there is no Gemfile.lock present" + exit 1 + else + Bundler.load.lock unless options[:"dry-run"] + Bundler.ui.info "The Gemfile's dependencies are satisfied" + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/clean.rb b/bundler-1.7.2/lib/bundler/cli/clean.rb new file mode 100644 index 0000000..e7a4c01 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/clean.rb @@ -0,0 +1,19 @@ +module Bundler + class CLI::Clean + attr_reader :options + + def initialize(options) + @options = options + 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" + exit 1 + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/common.rb b/bundler-1.7.2/lib/bundler/cli/common.rb new file mode 100644 index 0000000..0548525 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/common.rb @@ -0,0 +1,54 @@ +module Bundler + module CLI::Common + def self.without_groups_message + groups = Bundler.settings.without + group_list = [groups[0...-1].join(", "), groups[-1..-1]]. + reject{|s| s.to_s.empty? }.join(" and ") + group_str = (groups.size == 1) ? "group" : "groups" + "Gems in the #{group_str} #{group_list} were not installed." + end + + def self.select_spec(name, regex_match = nil) + specs = [] + regexp = Regexp.new(name) if regex_match + + Bundler.definition.specs.each do |spec| + return spec if spec.name == name + specs << spec if regexp && spec.name =~ regexp + end + + case specs.count + when 0 + raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies) + when 1 + specs.first + else + ask_for_spec_from(specs) + end + end + + def self.ask_for_spec_from(specs) + if !$stdout.tty? && ENV['BUNDLE_SPEC_RUN'].nil? + raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies) + end + + specs.each_with_index do |spec, index| + Bundler.ui.info "#{index.succ} : #{spec.name}", true + end + Bundler.ui.info '0 : - exit -', true + + num = Bundler.ui.ask('> ').to_i + num > 0 ? specs[num - 1] : nil + end + + def self.gem_not_found_message(missing_gem_name, alternatives) + require 'bundler/similarity_detector' + message = "Could not find gem '#{missing_gem_name}'." + alternate_names = alternatives.map { |a| a.respond_to?(:name) ? a.name : a } + suggestions = SimilarityDetector.new(alternate_names).similar_word_list(missing_gem_name) + message += "\nDid you mean #{suggestions}?" if suggestions + message + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/config.rb b/bundler-1.7.2/lib/bundler/cli/config.rb new file mode 100644 index 0000000..cad67a5 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/config.rb @@ -0,0 +1,84 @@ +module Bundler + class CLI::Config + attr_reader :options, :thor + attr_accessor :args + + def initialize(options, args, thor) + @options = options + @args = args + @thor = thor + end + + def run + peek = args.shift + + if peek && peek =~ /^\-\-/ + name, scope = args.shift, $' + else + name, scope = peek, "global" + end + + unless name + Bundler.ui.confirm "Settings are listed in order of priority. The top value will be used.\n" + + Bundler.settings.all.each do |setting| + Bundler.ui.confirm "#{setting}" + thor.with_padding do + Bundler.settings.pretty_values_for(setting).each do |line| + Bundler.ui.info line + end + end + Bundler.ui.confirm "" + end + return + end + + case scope + when "delete" + Bundler.settings.set_local(name, nil) + Bundler.settings.set_global(name, nil) + when "local", "global" + if args.empty? + Bundler.ui.confirm "Settings for `#{name}` in order of priority. The top value will be used" + thor.with_padding do + Bundler.settings.pretty_values_for(name).each { |line| Bundler.ui.info line } + end + return + end + + locations = Bundler.settings.locations(name) + + if scope == "global" + if local = locations[:local] + Bundler.ui.info "Your application has set #{name} to #{local.inspect}. This will override the " \ + "global value you are currently setting" + end + + if env = locations[:env] + Bundler.ui.info "You have a bundler environment variable for #{name} set to #{env.inspect}. " \ + "This will take precedence over the global value you are setting" + end + + if global = locations[:global] + Bundler.ui.info "You are replacing the current global value of #{name}, which is currently #{global.inspect}" + end + end + + if scope == "local" && local = locations[:local] + Bundler.ui.info "You are replacing the current local value of #{name}, which is currently #{local.inspect}" + end + + if name.match(/\Alocal\./) + pathname = Pathname.new(args.join(" ")) + self.args = [pathname.expand_path.to_s] if pathname.directory? + end + + Bundler.settings.send("set_#{scope}", name, args.join(" ")) + else + Bundler.ui.error "Invalid scope --#{scope} given. Please use --local or --global." + exit 1 + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/console.rb b/bundler-1.7.2/lib/bundler/cli/console.rb new file mode 100644 index 0000000..bf00093 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/console.rb @@ -0,0 +1,42 @@ +module Bundler + class CLI::Console + attr_reader :options, :group, :consoles + def initialize(options, group, consoles) + @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 = begin + Object.const_get(constant) + rescue NameError => e + Bundler.ui.error e.inspect + Bundler.ui.error "Could not load the #{constant} console" + return + end + + console.start + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/exec.rb b/bundler-1.7.2/lib/bundler/cli/exec.rb new file mode 100644 index 0000000..1739ab6 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/exec.rb @@ -0,0 +1,37 @@ +module Bundler + class CLI::Exec + attr_reader :options, :args + + def initialize(options, args) + @options = options + @args = args + end + + def run + Bundler.definition.validate_ruby! + Bundler.load.setup_environment + + 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 + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/gem.rb b/bundler-1.7.2/lib/bundler/cli/gem.rb new file mode 100644 index 0000000..3666341 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/gem.rb @@ -0,0 +1,77 @@ +module Bundler + class CLI::Gem + attr_reader :options, :gem_name, :thor + def initialize(options, gem_name, thor) + @options = options + @gem_name = gem_name + @thor = thor + 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 + + 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 = 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 = { + :name => name, + :underscored_name => underscored_name, + :namespaced_path => namespaced_path, + :constant_name => constant_name, + :constant_array => constant_array, + :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] + } + 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) + 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) + end + if options[:test] + thor.template(File.join("newgem/.travis.yml.tt"), File.join(target, ".travis.yml"), opts) + end + 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) + 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 + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/init.rb b/bundler-1.7.2/lib/bundler/cli/init.rb new file mode 100644 index 0000000..d6b2e74 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/init.rb @@ -0,0 +1,33 @@ +module Bundler + class CLI::Init + attr_reader :options + def initialize(options) + @options = options + end + + def run + if File.exist?("Gemfile") + Bundler.ui.error "Gemfile already exists at #{Dir.pwd}/Gemfile" + exit 1 + end + + if options[:gemspec] + gemspec = File.expand_path(options[:gemspec]) + unless File.exist?(gemspec) + Bundler.ui.error "Gem specification #{gemspec} doesn't exist" + exit 1 + end + spec = Gem::Specification.load(gemspec) + puts "Writing new Gemfile to #{Dir.pwd}/Gemfile" + File.open('Gemfile', 'wb') do |file| + file << "# Generated from #{gemspec}\n" + file << spec.to_gemfile + end + else + puts "Writing new Gemfile to #{Dir.pwd}/Gemfile" + FileUtils.cp(File.expand_path('../../templates/Gemfile', __FILE__), 'Gemfile') + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/inject.rb b/bundler-1.7.2/lib/bundler/cli/inject.rb new file mode 100644 index 0000000..004e0a5 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/inject.rb @@ -0,0 +1,33 @@ +module Bundler + class CLI::Inject + attr_reader :options, :name, :version, :gems + def initialize(options, name, version, gems) + @options = options + @name = name + @version = version + @gems = gems + end + + def run + # The required arguments allow Thor to give useful feedback when the arguments + # are incorrect. This adds those first two arguments onto the list as a whole. + gems.unshift(version).unshift(name) + + # Build an array of Dependency objects out of the arguments + deps = [] + gems.each_slice(2) do |gem_name, gem_version| + deps << Bundler::Dependency.new(gem_name, gem_version) + end + + added = Injector.inject(deps) + + if added.any? + Bundler.ui.confirm "Added to Gemfile:" + Bundler.ui.confirm added.map{ |g| " #{g}" }.join("\n") + else + Bundler.ui.confirm "All injected gems were already present in the Gemfile" + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/install.rb b/bundler-1.7.2/lib/bundler/cli/install.rb new file mode 100644 index 0000000..9bb7f68 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/install.rb @@ -0,0 +1,141 @@ +module Bundler + class CLI::Install + attr_reader :options + def initialize(options) + @options = options.dup + end + + def run + warn_if_root + + if options[:without] + options[:without] = options[:without].map{|g| g.tr(' ', ':') } + end + + ENV['RB_USER_INSTALL'] = '1' if Bundler::FREEBSD + + # Just disable color in deployment mode + Bundler.ui.shell = Thor::Shell::Basic.new if options[:deployment] + + if (options[:path] || options[:deployment]) && options[:system] + Bundler.ui.error "You have specified both a path to install your gems to, \n" \ + "as well as --system. Please choose." + exit 1 + end + + if (options["trust-policy"]) + unless (Bundler.rubygems.security_policies.keys.include?(options["trust-policy"])) + Bundler.ui.error "Rubygems doesn't know about trust policy '#{options["trust-policy"]}'. " \ + "The known policies are: #{Bundler.rubygems.security_policies.keys.join(', ')}." + exit 1 + end + Bundler.settings["trust-policy"] = options["trust-policy"] + else + Bundler.settings["trust-policy"] = nil if Bundler.settings["trust-policy"] + end + + if options[:deployment] || options[:frozen] + unless Bundler.default_lockfile.exist? + flag = options[:deployment] ? '--deployment' : '--frozen' + raise ProductionError, "The #{flag} flag requires a Gemfile.lock. Please make " \ + "sure you have checked your Gemfile.lock into version control " \ + "before deploying." + end + + if Bundler.root.join("vendor/cache").exist? + options[:local] = true + end + + Bundler.settings[:frozen] = '1' + end + + # When install is called with --no-deployment, disable deployment mode + if options[:deployment] == false + Bundler.settings.delete(:frozen) + options[:system] = true + end + + Bundler.settings[:path] = nil if options[:system] + Bundler.settings[:path] = "vendor/bundle" if options[:deployment] + Bundler.settings[:path] = options["path"] if options["path"] + Bundler.settings[:path] ||= "bundle" if options["standalone"] + Bundler.settings[:bin] = options["binstubs"] if options["binstubs"] + Bundler.settings[:bin] = nil if options["binstubs"] && options["binstubs"].empty? + 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[:clean] = options["clean"] if options["clean"] + Bundler.settings.without = options[:without] + Bundler.ui.level = "warn" if options[:quiet] + Bundler::Fetcher.disable_endpoint = options["full-index"] + Bundler.settings[:disable_shared_gems] = Bundler.settings[:path] ? '1' : nil + + # rubygems plugins sometimes hook into the gem install process + Gem.load_env_plugins if Gem.respond_to?(:load_env_plugins) + + 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] + + 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}" + 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}" + Bundler.ui.error "Also found in:" + also_found_in_uris.each { |uri| Bundler.ui.error " * #{uri}" } + Bundler.ui.error "You should add a source requirement to restrict this gem to your preferred source." + Bundler.ui.error "For example:" + Bundler.ui.error " gem '#{name}', :source => '#{installed_from_uri}'" + end + + if Bundler.settings[:clean] && Bundler.settings[:path] + require "bundler/cli/clean" + Bundler::CLI::Clean.new(options).run + 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." + end + + unless Bundler.definition.has_rubygems_remotes? + Bundler.ui.warn <<-WARN, :wrap => true + Your Gemfile has no gem server sources. If you need gems that are \ + not already on your machine, add a line like this to your Gemfile: + source 'https://rubygems.org' + WARN + end + raise e + end + + private + + def warn_if_root + return if Bundler::WINDOWS || !Process.uid.zero? + Bundler.ui.warn "Don't run Bundler as root. Bundler can ask for sudo " \ + "if it is needed, and installing your bundle as root will break this " \ + "application for all non-root users on this machine.", :wrap => true + end + + def without_groups_messages + if Bundler.settings.without.any? + require "bundler/cli/common" + Bundler.ui.confirm Bundler::CLI::Common.without_groups_message + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/open.rb b/bundler-1.7.2/lib/bundler/cli/open.rb new file mode 100644 index 0000000..c6c6179 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/open.rb @@ -0,0 +1,23 @@ +require 'bundler/cli/common' +require 'shellwords' + +module Bundler + class CLI::Open + attr_reader :options, :name + def initialize(options, name) + @options = options + @name = name + end + + def run + editor = [ENV['BUNDLER_EDITOR'], ENV['VISUAL'], ENV['EDITOR']].find{|e| !e.nil? && !e.empty? } + return Bundler.ui.info("To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR") unless editor + path = Bundler::CLI::Common.select_spec(name, :regex_match).full_gem_path + Dir.chdir(path) do + command = Shellwords.split(editor) + [path] + system(*command) || Bundler.ui.info("Could not run '#{command.join(' ')}'") + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/outdated.rb b/bundler-1.7.2/lib/bundler/cli/outdated.rb new file mode 100644 index 0000000..ee6387a --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/outdated.rb @@ -0,0 +1,80 @@ +require 'bundler/cli/common' + +module Bundler + class CLI::Outdated + attr_reader :options, :gems + def initialize(options, gems) + @options = options + @gems = gems + end + + def run + sources = Array(options[:source]) + + gems.each do |gem_name| + Bundler::CLI::Common.select_spec(gem_name) + end + + Bundler.definition.validate_ruby! + current_specs = Bundler.ui.silence { Bundler.load.specs } + current_dependencies = {} + Bundler.ui.silence { Bundler.load.dependencies.each { |dep| current_dependencies[dep.name] = dep } } + + if gems.empty? && sources.empty? + # We're doing a full update + definition = Bundler.definition(true) + else + definition = Bundler.definition(:gems => gems, :sources => sources) + end + options["local"] ? definition.resolve_with_cache! : definition.resolve_remotely! + + Bundler.ui.info "" + + out_count = 0 + # Loop through the current specs + gemfile_specs, dependency_specs = current_specs.partition { |spec| current_dependencies.has_key? spec.name } + [gemfile_specs.sort_by(&:name), dependency_specs.sort_by(&:name)].flatten.each do |current_spec| + next if !gems.empty? && !gems.include?(current_spec.name) + + dependency = current_dependencies[current_spec.name] + + if options["strict"] + active_spec = definition.specs.detect { |spec| spec.name == current_spec.name } + else + active_spec = definition.index[current_spec.name].sort_by { |b| b.version } + if !current_spec.version.prerelease? && !options[:pre] && active_spec.size > 1 + active_spec = active_spec.delete_if { |b| b.respond_to?(:version) && b.version.prerelease? } + end + active_spec = active_spec.last + end + next if active_spec.nil? + + gem_outdated = Gem::Version.new(active_spec.version) > Gem::Version.new(current_spec.version) + git_outdated = current_spec.git_version != active_spec.git_version + if gem_outdated || git_outdated + if out_count == 0 + if options["pre"] + Bundler.ui.info "Outdated gems included in the bundle (including pre-releases):" + else + Bundler.ui.info "Outdated gems included in the bundle:" + end + end + + spec_version = "#{active_spec.version}#{active_spec.git_version}" + current_version = "#{current_spec.version}#{current_spec.git_version}" + dependency_version = %|Gemfile specifies "#{dependency.requirement}"| if dependency && dependency.specific? + Bundler.ui.info " * #{active_spec.name} (#{spec_version} > #{current_version}) #{dependency_version}".rstrip + out_count += 1 + end + Bundler.ui.debug "from #{active_spec.loaded_from}" + end + + if out_count.zero? + Bundler.ui.info "Your bundle is up to date!\n" + else + exit 1 + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/package.rb b/bundler-1.7.2/lib/bundler/cli/package.rb new file mode 100644 index 0000000..b294603 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/package.rb @@ -0,0 +1,36 @@ +module Bundler + class CLI::Package + attr_reader :options + + def initialize(options) + @options = options + end + + def run + Bundler.ui.level = "warn" if options[:quiet] + Bundler.settings[:path] = File.expand_path(options[:path]) if options[:path] + setup_cache_all + install + # TODO: move cache contents here now that all bundles are locked + custom_path = Pathname.new(options[:path]) if options[:path] + Bundler.load.cache(custom_path) + end + + private + + def install + require 'bundler/cli/install' + Bundler::CLI::Install.new(options.dup).run + end + + def setup_cache_all + Bundler.settings[:cache_all] = options[:all] if options.key?("all") + + if Bundler.definition.has_local_dependencies? && !Bundler.settings[:cache_all] + Bundler.ui.warn "Your Gemfile contains path and git dependencies. If you want " \ + "to package them as well, please pass the --all flag. This will be the default " \ + "on Bundler 2.0." + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/platform.rb b/bundler-1.7.2/lib/bundler/cli/platform.rb new file mode 100644 index 0000000..bc947cf --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/platform.rb @@ -0,0 +1,43 @@ +module Bundler + class CLI::Platform + attr_reader :options + def initialize(options) + @options = options + end + + def run + platforms, ruby_version = Bundler.ui.silence do + [ Bundler.definition.platforms.map {|p| "* #{p}" }, + Bundler.definition.ruby_version ] + end + output = [] + + if options[:ruby] + if ruby_version + output << ruby_version + else + output << "No ruby version specified" + end + else + output << "Your platform is: #{RUBY_PLATFORM}" + output << "Your app has gems that work on these platforms:\n#{platforms.join("\n")}" + + if ruby_version + output << "Your Gemfile specifies a Ruby version requirement:\n* #{ruby_version}" + + begin + Bundler.definition.validate_ruby! + output << "Your current platform satisfies the Ruby version requirement." + rescue RubyVersionMismatch => e + output << e.message + end + else + output << "Your Gemfile does not specify a Ruby version requirement." + end + end + + Bundler.ui.info output.join("\n\n") + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/show.rb b/bundler-1.7.2/lib/bundler/cli/show.rb new file mode 100644 index 0000000..07ff63d --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/show.rb @@ -0,0 +1,48 @@ +require 'bundler/cli/common' + +module Bundler + class CLI::Show + attr_reader :options, :gem_name + def initialize(options, gem_name) + @options = options + @gem_name = gem_name + end + + def run + Bundler.ui.silence do + Bundler.definition.validate_ruby! + Bundler.load.lock + end + + if gem_name + if gem_name == "bundler" + path = File.expand_path("../../../..", __FILE__) + else + spec = Bundler::CLI::Common.select_spec(gem_name, :regex_match) + return unless spec + path = spec.full_gem_path + if !File.directory?(path) + Bundler.ui.warn "The gem #{gem_name} has been deleted. It was installed at:" + end + end + return Bundler.ui.info(path) + end + + if options[:paths] + Bundler.load.specs.sort_by { |s| s.name }.map do |s| + Bundler.ui.info s.full_gem_path + end + else + 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.'}" + else + Bundler.ui.info desc + end + end + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/update.rb b/bundler-1.7.2/lib/bundler/cli/update.rb new file mode 100644 index 0000000..920221f --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/update.rb @@ -0,0 +1,73 @@ +module Bundler + class CLI::Update + attr_reader :options, :gems + def initialize(options, gems) + @options = options + @gems = gems + end + + def run + + sources = Array(options[:source]) + groups = Array(options[:group]).map(&:to_sym) + Bundler.ui.level = "warn" if options[:quiet] + + if gems.empty? && sources.empty? && groups.empty? + # We're doing a full update + Bundler.definition(true) + else + unless Bundler.default_lockfile.exist? + raise GemfileLockNotFound, "This Bundle hasn't been installed yet. " \ + "Run `bundle install` to update and install the bundled gems." + end + # cycle through the requested gems, just to make sure they exist + names = Bundler.locked_gems.specs.map{ |s| s.name } + gems.each do |g| + next if names.include?(g) + require "bundler/cli/common" + raise GemNotFound, Bundler::CLI::Common.gem_not_found_message(g, names) + end + + if groups.any? + specs = Bundler.definition.specs_for groups + sources.concat(specs.map(&:name)) + end + + Bundler.definition(:gems => gems, :sources => sources) + end + + Bundler::Fetcher.disable_endpoint = options["full-index"] + + opts = options.dup + opts["update"] = true + opts["local"] = options[:local] + + Bundler.settings[:jobs] = opts["jobs"] if opts["jobs"] + + # rubygems plugins sometimes hook into the gem install process + Gem.load_env_plugins if Gem.respond_to?(:load_env_plugins) + + Bundler.definition.validate_ruby! + Installer.install Bundler.root, Bundler.definition, opts + Bundler.load.cache if Bundler.root.join("vendor/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!" + without_groups_messages + end + + private + + def without_groups_messages + if Bundler.settings.without.any? + require "bundler/cli/common" + Bundler.ui.confirm Bundler::CLI::Common.without_groups_message + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/cli/viz.rb b/bundler-1.7.2/lib/bundler/cli/viz.rb new file mode 100644 index 0000000..c404ddb --- /dev/null +++ b/bundler-1.7.2/lib/bundler/cli/viz.rb @@ -0,0 +1,27 @@ +module Bundler + class CLI::Viz + attr_reader :options, :gem_name + def initialize(options) + @options = options + end + + 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.viz + rescue LoadError => e + Bundler.ui.error e.inspect + Bundler.ui.warn "Make sure you have the graphviz ruby gem. You can install it with:" + Bundler.ui.warn "`gem install ruby-graphviz`" + rescue StandardError => e + if e.message =~ /GraphViz not installed or dot not in PATH/ + Bundler.ui.error e.message + Bundler.ui.warn "Please install GraphViz. On a Mac with homebrew, you can run `brew install graphviz`." + else + raise + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/constants.rb b/bundler-1.7.2/lib/bundler/constants.rb new file mode 100644 index 0000000..d9bf683 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/constants.rb @@ -0,0 +1,5 @@ +module Bundler + WINDOWS = RbConfig::CONFIG["host_os"] =~ %r!(msdos|mswin|djgpp|mingw)! + FREEBSD = RbConfig::CONFIG["host_os"] =~ /bsd/ + NULL = WINDOWS ? "NUL" : "/dev/null" +end diff --git a/bundler-1.7.2/lib/bundler/current_ruby.rb b/bundler-1.7.2/lib/bundler/current_ruby.rb new file mode 100644 index 0000000..8d012a0 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/current_ruby.rb @@ -0,0 +1,123 @@ +module Bundler + # Returns current version of Ruby + # + # @return [CurrentRuby] Current version of Ruby + def self.current_ruby + @current_ruby ||= CurrentRuby.new + end + + class CurrentRuby + def on_18? + RUBY_VERSION =~ /^1\.8/ + end + + def on_19? + RUBY_VERSION =~ /^1\.9/ + end + + def on_20? + RUBY_VERSION =~ /^2\.0/ + end + + def on_21? + RUBY_VERSION =~ /^2\.1/ + end + + def ruby? + !mswin? && (!defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby" || RUBY_ENGINE == "rbx" || RUBY_ENGINE == "maglev") + end + + def ruby_18? + ruby? && on_18? + end + + def ruby_19? + ruby? && on_19? + end + + def ruby_20? + ruby? && on_20? + end + + def ruby_21? + ruby? && on_21? + end + + def mri? + !mswin? && (!defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby") + end + + def mri_18? + mri? && on_18? + end + + def mri_19? + mri? && on_19? + end + + def mri_20? + mri? && on_20? + end + + def mri_21? + mri? && on_21? + end + + def rbx? + ruby? && defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx" + end + + def jruby? + defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" + end + + def jruby_18? + jruby? && on_18? + end + + def jruby_19? + jruby? && on_19? + end + + def maglev? + defined?(RUBY_ENGINE) && RUBY_ENGINE == "maglev" + end + + def mswin? + Bundler::WINDOWS + end + + def mingw? + Bundler::WINDOWS && Gem::Platform.local.os == "mingw32" && Gem::Platform.local.cpu != 'x64' + end + + def mingw_18? + mingw? && on_18? + end + + def mingw_19? + mingw? && on_19? + end + + def mingw_20? + mingw? && on_20? + end + + def mingw_21? + mingw? && on_21? + end + + def x64_mingw? + Bundler::WINDOWS && Gem::Platform.local.os == "mingw32" && Gem::Platform.local.cpu == 'x64' + end + + def x64_mingw_20? + x64_mingw? && on_20? + end + + def x64_mingw_21? + x64_mingw? && on_21? + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/definition.rb b/bundler-1.7.2/lib/bundler/definition.rb new file mode 100644 index 0000000..0885394 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/definition.rb @@ -0,0 +1,610 @@ +require "digest/sha1" +require "set" + +module Bundler + class Definition + include GemHelpers + + attr_reader :dependencies, :platforms, :ruby_version, :locked_deps + + # Given a gemfile and lockfile creates a Bundler definition + # + # @param gemfile [Pathname] Path to Gemfile + # @param lockfile [Pathname,nil] Path to Gemfile.lock + # @param unlock [Hash, Boolean, nil] Gems that have been requested + # to be updated or true if all gems should be updated + # @return [Bundler::Definition] + def self.build(gemfile, lockfile, unlock) + unlock ||= {} + gemfile = Pathname.new(gemfile).expand_path + + unless gemfile.file? + raise GemfileNotFound, "#{gemfile} not found" + end + + Dsl.evaluate(gemfile, lockfile, unlock) + end + + + # + # How does the new system work? + # + # * Load information from Gemfile and Lockfile + # * Invalidate stale locked specs + # * All specs from stale source are stale + # * All specs that are reachable only through a stale + # dependency are stale. + # * If all fresh dependencies are satisfied by the locked + # specs, then we can try to resolve locally. + # + # @param lockfile [Pathname] Path to Gemfile.lock + # @param dependencies [Array(Bundler::Dependency)] array of dependencies from Gemfile + # @param sources [Bundler::SourceList] + # @param unlock [Hash, Boolean, nil] Gems that have been requested + # to be updated or true if all gems should be updated + # @param ruby_version [Bundler::RubyVersion, nil] Requested Ruby Version + def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil) + @unlocking = unlock == true || !unlock.empty? + + @dependencies, @sources, @unlock = dependencies, sources, unlock + @remote = false + @specs = nil + @lockfile_contents = "" + @ruby_version = ruby_version + + if lockfile && File.exist?(lockfile) + @lockfile_contents = Bundler.read_file(lockfile) + locked = LockfileParser.new(@lockfile_contents) + @platforms = locked.platforms + + if unlock != true + @locked_deps = locked.dependencies + @locked_specs = SpecSet.new(locked.specs) + @locked_sources = locked.sources + else + @unlock = {} + @locked_deps = [] + @locked_specs = SpecSet.new([]) + @locked_sources = [] + end + else + @unlock = {} + @platforms = [] + @locked_deps = [] + @locked_specs = SpecSet.new([]) + @locked_sources = [] + end + + @unlock[:gems] ||= [] + @unlock[:sources] ||= [] + + current_platform = Bundler.rubygems.platforms.map { |p| generic(p) }.compact.last + @new_platform = !@platforms.include?(current_platform) + @platforms |= [current_platform] + + @path_changes = converge_paths + eager_unlock = expand_dependencies(@unlock[:gems]) + @unlock[:gems] = @locked_specs.for(eager_unlock).map { |s| s.name } + + @source_changes = converge_sources + @dependency_changes = converge_dependencies + @local_changes = converge_locals + + fixup_dependency_types! + end + + def fixup_dependency_types! + # XXX This is a temporary workaround for a bug when using rubygems 1.8.15 + # where Gem::Dependency#== matches Gem::Dependency#type. As the lockfile + # doesn't carry a notion of the dependency type, if you use + # add_development_dependency in a gemspec that's loaded with the gemspec + # directive, the lockfile dependencies and resolved dependencies end up + # with a mismatch on #type. + # Test coverage to catch a regression on this is in gemspec_spec.rb + @dependencies.each do |d| + if ld = @locked_deps.find { |l| l.name == d.name } + ld.instance_variable_set(:@type, d.type) + end + end + end + + def resolve_with_cache! + raise "Specs already loaded" if @specs + sources.cached! + specs + end + + def resolve_remotely! + raise "Specs already loaded" if @specs + @remote = true + sources.remote! + specs + end + + # For given dependency list returns a SpecSet with Gemspec of all the required + # dependencies. + # 1. The method first resolves the dependencies specified in Gemfile + # 2. After that it tries and fetches gemspec of resolved dependencies + # + # @return [Bundler::SpecSet] + def specs + @specs ||= begin + specs = resolve.materialize(requested_dependencies) + + unless specs["bundler"].any? + local = Bundler.settings[:frozen] ? rubygems_index : index + bundler = local.search(Gem::Dependency.new('bundler', VERSION)).last + specs["bundler"] = bundler if bundler + end + + specs + end + end + + def new_specs + specs - @locked_specs + end + + def removed_specs + @locked_specs - specs + end + + def new_platform? + @new_platform + end + + def missing_specs + missing = [] + resolve.materialize(requested_dependencies, missing) + missing + end + + def requested_specs + @requested_specs ||= begin + groups = self.groups - Bundler.settings.without + groups.map! { |g| g.to_sym } + specs_for(groups) + end + end + + def current_dependencies + dependencies.reject { |d| !d.should_include? } + end + + def specs_for(groups) + deps = dependencies.select { |d| (d.groups & groups).any? } + deps.delete_if { |d| !d.should_include? } + specs.for(expand_dependencies(deps)) + end + + # Resolve all the dependencies specified in Gemfile. It ensures that + # dependencies that have been already resolved via locked file and are fresh + # are reused when resolving dependencies + # + # @return [SpecSet] resolved dependencies + def resolve + @resolve ||= begin + if Bundler.settings[:frozen] || (!@unlocking && nothing_changed?) + @locked_specs + else + last_resolve = converge_locked_specs + + # Run a resolve against the locally available gems + last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve) + end + end + end + + def index + @index ||= Index.build do |idx| + dependency_names = @dependencies.dup || [] + dependency_names.map! {|d| d.name } + + sources.all_sources.each do |s| + s.dependency_names = dependency_names + idx.add_source s.specs + dependency_names.push(*s.unmet_deps).uniq! + end + end + end + + # used when frozen is enabled so we can find the bundler + # spec, even if (say) a git gem is not checked out. + def rubygems_index + @rubygems_index ||= Index.build do |idx| + sources.rubygems_sources.each do |rubygems| + idx.add_source rubygems.specs + end + end + end + + def has_rubygems_remotes? + sources.rubygems_sources.any? {|s| s.remotes.any? } + end + + def has_local_dependencies? + !sources.path_sources.empty? || !sources.git_sources.empty? + end + + def spec_git_paths + sources.git_sources.map {|s| s.path.to_s } + end + + def groups + dependencies.map { |d| d.groups }.flatten.uniq + end + + def lock(file) + contents = to_lock + + # Convert to \r\n if the existing lock has them + # i.e., Windows with `git config core.autocrlf=true` + contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match("\r\n") + + return if @lockfile_contents == contents + + if Bundler.settings[:frozen] + Bundler.ui.error "Cannot write a changed lockfile while frozen." + return + end + + File.open(file, 'wb'){|f| f.puts(contents) } + rescue Errno::EACCES + raise Bundler::InstallError, + "There was an error while trying to write to Gemfile.lock. It is likely that \n" \ + "you need to allow write permissions for the file at path: \n" \ + "#{File.expand_path(file)}" + end + + def to_lock + out = "" + + sources.lock_sources.each do |source| + # Add the source header + out << source.to_lock + # Find all specs for this source + resolve. + select { |s| source.can_lock?(s) }. + # This needs to be sorted by full name so that + # gems with the same name, but different platform + # are ordered consistently + sort_by { |s| s.full_name }. + each do |spec| + next if spec.name == 'bundler' + out << spec.to_lock + end + out << "\n" + end + + out << "PLATFORMS\n" + + platforms.map { |p| p.to_s }.sort.each do |p| + out << " #{p}\n" + end + + out << "\n" + out << "DEPENDENCIES\n" + + handled = [] + dependencies. + sort_by { |d| d.to_s }. + each do |dep| + next if handled.include?(dep.name) + out << dep.to_lock + handled << dep.name + end + + out + end + + def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false) + changes = false + + msg = "You are trying to install in deployment mode after changing\n" \ + "your Gemfile. Run `bundle install` elsewhere and add the\n" \ + "updated Gemfile.lock to version control." + + unless explicit_flag + msg += "\n\nIf this is a development machine, remove the Gemfile " \ + "freeze \nby running `bundle install --no-deployment`." + end + + added = [] + deleted = [] + changed = [] + + gemfile_sources = sources.all_sources + if @locked_sources != gemfile_sources + new_sources = gemfile_sources - @locked_sources + deleted_sources = @locked_sources - gemfile_sources + + if new_sources.any? + added.concat new_sources.map { |source| "* source: #{source}" } + end + + if deleted_sources.any? + deleted.concat deleted_sources.map { |source| "* source: #{source}" } + end + + changes = true + end + + both_sources = Hash.new { |h,k| h[k] = ["no specified source", "no specified source"] } + @dependencies.each { |d| both_sources[d.name][0] = d.source if d.source } + @locked_deps.each { |d| both_sources[d.name][1] = d.source if d.source } + both_sources.delete_if { |k,v| v[0] == v[1] } + + if @dependencies != @locked_deps + new_deps = @dependencies - @locked_deps + deleted_deps = @locked_deps - @dependencies + + if new_deps.any? + added.concat new_deps.map { |d| "* #{pretty_dep(d)}" } + end + + if deleted_deps.any? + deleted.concat deleted_deps.map { |d| "* #{pretty_dep(d)}" } + end + + both_sources.each do |name, sources| + changed << "* #{name} from `#{sources[0]}` to `#{sources[1]}`" + end + + changes = true + end + + msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any? + msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any? + msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any? + msg << "\n" + + raise ProductionError, msg if added.any? || deleted.any? || changed.any? + end + + def validate_ruby! + return unless ruby_version + + if diff = ruby_version.diff(Bundler.ruby_version) + problem, expected, actual = diff + + msg = case problem + when :engine + "Your Ruby engine is #{actual}, but your Gemfile specified #{expected}" + when :version + "Your Ruby version is #{actual}, but your Gemfile specified #{expected}" + when :engine_version + "Your #{Bundler.ruby_version.engine} version is #{actual}, but your Gemfile specified #{ruby_version.engine} #{expected}" + when :patchlevel + if !expected.is_a?(String) + "The Ruby patchlevel in your Gemfile must be a string" + else + "Your Ruby patchlevel is #{actual}, but your Gemfile specified #{expected}" + end + end + + raise RubyVersionMismatch, msg + end + end + + private + + attr_reader :sources + + def nothing_changed? + !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes + end + + def pretty_dep(dep, source = false) + msg = "#{dep.name}" + msg << " (#{dep.requirement})" unless dep.requirement == Gem::Requirement.default + msg << " from the `#{dep.source}` source" if source && dep.source + msg + end + + # Check if the specs of the given source changed + # according to the locked source. A block should be + # in order to specify how the locked version of + # the source should be found. + def specs_changed?(source, &block) + locked = @locked_sources.find(&block) + + if locked + unlocking = @locked_specs.any? do |locked_spec| + locked_spec.source != locked + end + end + + !locked || unlocking || source.specs != locked.specs + end + + # Get all locals and override their matching sources. + # Return true if any of the locals changed (for example, + # they point to a new revision) or depend on new specs. + def converge_locals + locals = [] + + Bundler.settings.local_overrides.map do |k,v| + spec = @dependencies.find { |s| s.name == k } + source = spec && spec.source + if source && source.respond_to?(:local_override!) + source.unlock! if @unlock[:gems].include?(spec.name) + locals << [ source, source.local_override!(v) ] + end + end + + locals.any? do |source, changed| + changed || specs_changed?(source) { |o| source.class == o.class && source.uri == o.uri } + end + end + + def converge_paths + sources.path_sources.any? do |source| + specs_changed?(source) do |ls| + ls.class == source.class && ls.path == source.path + end + end + end + + def converge_sources + changes = false + + # Get the Rubygems sources from the Gemfile.lock + locked_gem_sources = @locked_sources.select { |s| s.kind_of?(Source::Rubygems) } + # Get the Rubygems sources from the Gemfile + actual_gem_sources = @sources.rubygems_sources + + # If there is a Rubygems source in both + unless locked_gem_sources.empty? && actual_gem_sources.empty? + actual_remotes = actual_gem_sources.map(&:remotes).flatten.uniq + locked_gem_sources.each do |locked_gem| + # Merge the remotes from the Gemfile into the Gemfile.lock + changes = changes | locked_gem.replace_remotes(actual_remotes) + end + end + + # Replace the sources from the Gemfile with the sources from the Gemfile.lock, + # if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent + # source in the Gemfile.lock, use the one from the Gemfile. + sources.replace_sources!(@locked_sources) + gemfile_sources = sources.all_sources + changes = changes | (Set.new(gemfile_sources) != Set.new(@locked_sources)) + + gemfile_sources.each do |source| + # If the source is unlockable and the current command allows an unlock of + # the source (for example, you are doing a `bundle update ` of a git-pinned + # gem), unlock it. For git sources, this means to unlock the revision, which + # will cause the `ref` used to be the most recent for the branch (or master) if + # an explicit `ref` is not used. + if source.respond_to?(:unlock!) && @unlock[:sources].include?(source.name) + source.unlock! + changes = true + end + end + + changes + end + + def converge_dependencies + (@dependencies + @locked_deps).each do |dep| + if dep.source + dep.source = sources.get(dep.source) + end + end + Set.new(@dependencies) != Set.new(@locked_deps) + end + + # Remove elements from the locked specs that are expired. This will most + # commonly happen if the Gemfile has changed since the lockfile was last + # generated + def converge_locked_specs + deps = [] + + # Build a list of dependencies that are the same in the Gemfile + # and Gemfile.lock. If the Gemfile modified a dependency, but + # the gem in the Gemfile.lock still satisfies it, this is fine + # too. + locked_deps_hash = @locked_deps.inject({}) { |hsh, dep| hsh[dep] = dep; hsh } + @dependencies.each do |dep| + locked_dep = locked_deps_hash[dep] + + if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep) + deps << dep + elsif dep.source.is_a?(Source::Path) && dep.current_platform? && (!locked_dep || dep.source != locked_dep.source) + @locked_specs.each do |s| + @unlock[:gems] << s.name if s.source == dep.source + end + + dep.source.unlock! if dep.source.respond_to?(:unlock!) + dep.source.specs.each { |s| @unlock[:gems] << s.name } + end + end + + converged = [] + @locked_specs.each do |s| + s.source = sources.get(s.source) + + # Don't add a spec to the list if its source is expired. For example, + # if you change a Git gem to Rubygems. + next if s.source.nil? || @unlock[:sources].include?(s.name) + # If the spec is from a path source and it doesn't exist anymore + # then we just unlock it. + + # Path sources have special logic + if s.source.instance_of?(Source::Path) + other = s.source.specs[s].first + + # If the spec is no longer in the path source, unlock it. This + # commonly happens if the version changed in the gemspec + next unless other + + deps2 = other.dependencies.select { |d| d.type != :development } + # If the dependencies of the path source have changed, unlock it + next unless s.dependencies.sort == deps2.sort + end + + converged << s + end + + resolve = SpecSet.new(converged) + resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems]) + diff = @locked_specs.to_a - resolve.to_a + + # Now, we unlock any sources that do not have anymore gems pinned to it + sources.all_sources.each do |source| + next unless source.respond_to?(:unlock!) + + unless resolve.any? { |s| s.source == source } + source.unlock! if !diff.empty? && diff.any? { |s| s.source == source } + end + end + + resolve + end + + def in_locked_deps?(dep, d) + d && dep.source == d.source + end + + def satisfies_locked_spec?(dep) + @locked_specs.any? { |s| s.satisfies?(dep) && (!dep.source || s.source == dep.source) } + end + + def expanded_dependencies + @expanded_dependencies ||= expand_dependencies(dependencies, @remote) + end + + def expand_dependencies(dependencies, remote = false) + deps = [] + dependencies.each do |dep| + dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name) + next unless remote || dep.current_platform? + dep.gem_platforms(@platforms).each do |p| + deps << DepProxy.new(dep, p) if remote || p == generic(Gem::Platform.local) + end + end + deps + end + + def requested_dependencies + groups = self.groups - Bundler.settings.without + groups.map! { |g| g.to_sym } + dependencies.reject { |d| !d.should_include? || (d.groups & groups).empty? } + end + + def source_requirements + # Load all specs from remote sources + index + + # Record the specs available in each gem's source, so that those + # specs will be available later when the resolver knows where to + # look for that gemspec (or its dependencies) + source_requirements = {} + dependencies.each do |dep| + next unless dep.source + source_requirements[dep.name] = dep.source.specs + end + source_requirements + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/dep_proxy.rb b/bundler-1.7.2/lib/bundler/dep_proxy.rb new file mode 100644 index 0000000..bc810dc --- /dev/null +++ b/bundler-1.7.2/lib/bundler/dep_proxy.rb @@ -0,0 +1,43 @@ +module Bundler + class DepProxy + + attr_reader :required_by, :__platform, :dep + + def initialize(dep, platform) + @dep, @__platform, @required_by = dep, platform, [] + end + + def hash + @hash ||= dep.hash + end + + def ==(o) + dep == o.dep && __platform == o.__platform + end + + alias eql? == + + def type + @dep.type + end + + def name + @dep.name + end + + def requirement + @dep.requirement + end + + def to_s + "#{name} (#{requirement}) #{__platform}" + end + + private + + def method_missing(*args) + @dep.send(*args) + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/dependency.rb b/bundler-1.7.2/lib/bundler/dependency.rb new file mode 100644 index 0000000..c0e8f8b --- /dev/null +++ b/bundler-1.7.2/lib/bundler/dependency.rb @@ -0,0 +1,99 @@ +require 'rubygems/dependency' +require 'bundler/shared_helpers' +require 'bundler/rubygems_ext' + +module Bundler + class Dependency < Gem::Dependency + attr_reader :autorequire + attr_reader :groups + attr_reader :platforms + + PLATFORM_MAP = { + :ruby => Gem::Platform::RUBY, + :ruby_18 => Gem::Platform::RUBY, + :ruby_19 => Gem::Platform::RUBY, + :ruby_20 => Gem::Platform::RUBY, + :ruby_21 => Gem::Platform::RUBY, + :mri => Gem::Platform::RUBY, + :mri_18 => Gem::Platform::RUBY, + :mri_19 => Gem::Platform::RUBY, + :mri_20 => Gem::Platform::RUBY, + :mri_21 => Gem::Platform::RUBY, + :rbx => Gem::Platform::RUBY, + :jruby => Gem::Platform::JAVA, + :jruby_18 => Gem::Platform::JAVA, + :jruby_19 => Gem::Platform::JAVA, + :mswin => Gem::Platform::MSWIN, + :mingw => Gem::Platform::MINGW, + :mingw_18 => Gem::Platform::MINGW, + :mingw_19 => Gem::Platform::MINGW, + :mingw_20 => Gem::Platform::MINGW, + :mingw_21 => Gem::Platform::MINGW, + :x64_mingw => Gem::Platform::X64_MINGW, + :x64_mingw_20 => Gem::Platform::X64_MINGW, + :x64_mingw_21 => Gem::Platform::X64_MINGW + }.freeze + + def initialize(name, version, options = {}, &blk) + type = options["type"] || :runtime + super(name, version, type) + + @autorequire = nil + @groups = Array(options["group"] || :default).map { |g| g.to_sym } + @source = options["source"] + @platforms = Array(options["platforms"]) + @env = options["env"] + + if options.key?('require') + @autorequire = Array(options['require'] || []) + end + end + + def gem_platforms(valid_platforms) + return valid_platforms if @platforms.empty? + + platforms = [] + @platforms.each do |p| + platform = PLATFORM_MAP[p] + next unless valid_platforms.include?(platform) + platforms |= [platform] + end + platforms + end + + def should_include? + current_env? && current_platform? + end + + def current_env? + return true unless @env + if @env.is_a?(Hash) + @env.all? do |key, val| + ENV[key.to_s] && (val.is_a?(String) ? ENV[key.to_s] == val : ENV[key.to_s] =~ val) + end + else + ENV[@env.to_s] + end + end + + def current_platform? + return true if @platforms.empty? + @platforms.any? { |p| + Bundler.current_ruby.send("#{p}?") + } + end + + def to_lock + out = super + out << '!' if source + out << "\n" + end + + + def specific? + super + rescue NoMethodError + requirement != ">= 0" + end + end +end diff --git a/bundler-1.7.2/lib/bundler/deployment.rb b/bundler-1.7.2/lib/bundler/deployment.rb new file mode 100644 index 0000000..44a1b86 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/deployment.rb @@ -0,0 +1,59 @@ +module Bundler + class Deployment + def self.define_task(context, task_method = :task, opts = {}) + if defined?(Capistrano) && context.is_a?(Capistrano::Configuration) + context_name = "capistrano" + role_default = "{:except => {:no_release => true}}" + error_type = ::Capistrano::CommandError + else + context_name = "vlad" + role_default = "[:app]" + error_type = ::Rake::CommandFailedError + end + + roles = context.fetch(:bundle_roles, false) + opts[:roles] = roles if roles + + context.send :namespace, :bundle do + send :desc, <<-DESC + Install the current Bundler environment. By default, gems will be \ + installed to the shared/bundle path. Gems in the development and \ + test group will not be installed. The install command is executed \ + with the --deployment and --quiet flags. If the bundle cmd cannot \ + be found then you can override the bundle_cmd variable to specify \ + which one it should use. The base path to the app is fetched from \ + the :latest_release variable. Set it for custom deploy layouts. + + You can override any of these defaults by setting the variables shown below. + + N.B. bundle_roles must be defined before you require 'bundler/#{context_name}' \ + in your deploy.rb file. + + set :bundle_gemfile, "Gemfile" + set :bundle_dir, File.join(fetch(:shared_path), 'bundle') + set :bundle_flags, "--deployment --quiet" + set :bundle_without, [:development, :test] + set :bundle_cmd, "bundle" # e.g. "/opt/ruby/bin/bundle" + set :bundle_roles, #{role_default} # e.g. [:app, :batch] + DESC + send task_method, :install, opts do + bundle_cmd = context.fetch(:bundle_cmd, "bundle") + bundle_flags = context.fetch(:bundle_flags, "--deployment --quiet") + bundle_dir = context.fetch(:bundle_dir, File.join(context.fetch(:shared_path), 'bundle')) + bundle_gemfile = context.fetch(:bundle_gemfile, "Gemfile") + bundle_without = [*context.fetch(:bundle_without, [:development, :test])].compact + app_path = context.fetch(:latest_release) + if app_path.to_s.empty? + raise error_type.new("Cannot detect current release path - make sure you have deployed at least once.") + end + args = ["--gemfile #{File.join(app_path, bundle_gemfile)}"] + args << "--path #{bundle_dir}" unless bundle_dir.to_s.empty? + args << bundle_flags.to_s + args << "--without #{bundle_without.join(" ")}" unless bundle_without.empty? + + run "cd #{app_path} && #{bundle_cmd} install #{args.join(' ')}" + end + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/deprecate.rb b/bundler-1.7.2/lib/bundler/deprecate.rb new file mode 100644 index 0000000..e6e15b6 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/deprecate.rb @@ -0,0 +1,15 @@ +module Bundler + + if defined? ::Deprecate + Deprecate = ::Deprecate + elsif defined? Gem::Deprecate + Deprecate = Gem::Deprecate + else + class Deprecate; end + end + + unless Deprecate.respond_to?(:skip_during) + def Deprecate.skip_during; yield; end + end + +end diff --git a/bundler-1.7.2/lib/bundler/dsl.rb b/bundler-1.7.2/lib/bundler/dsl.rb new file mode 100644 index 0000000..ef5c6fb --- /dev/null +++ b/bundler-1.7.2/lib/bundler/dsl.rb @@ -0,0 +1,294 @@ +require 'bundler/dependency' +require 'bundler/ruby_dsl' + +module Bundler + class Dsl + include RubyDsl + + def self.evaluate(gemfile, lockfile, unlock) + builder = new + builder.eval_gemfile(gemfile) + builder.to_definition(lockfile, unlock) + end + + VALID_PLATFORMS = Bundler::Dependency::PLATFORM_MAP.keys.freeze + + attr_accessor :dependencies + + def initialize + @source = nil + @sources = SourceList.new + @git_sources = {} + @dependencies = [] + @groups = [] + @platforms = [] + @env = nil + @ruby_version = nil + add_github_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 ') + raise GemfileError, "Gemfile syntax error #{syntax_msg}" + rescue ScriptError, RegexpError, NameError, ArgumentError => e + e.backtrace[0] = "#{e.backtrace[0]}: #{e.message} (#{e.class})" + Bundler.ui.warn e.backtrace.join("\n ") + raise GemfileError, "There was an error in your Gemfile," \ + " and Bundler cannot continue." + end + + def gemspec(opts = nil) + path = opts && opts[:path] || '.' + name = opts && opts[:name] || '{,*}' + development_group = opts && opts[:development_group] || :development + expanded_path = File.expand_path(path, Bundler.default_gemfile.dirname) + + gemspecs = Dir[File.join(expanded_path, "#{name}.gemspec")] + + case gemspecs.size + when 1 + spec = Bundler.load_gemspec(gemspecs.first) + raise InvalidOption, "There was an error loading the gemspec at #{gemspecs.first}." unless spec + gem spec.name, :path => path + group(development_group) do + spec.development_dependencies.each do |dep| + gem dep.name, *(dep.requirement.as_list + [:type => :development]) + end + end + when 0 + raise InvalidOption, "There are no gemspecs at #{expanded_path}." + else + raise InvalidOption, "There are multiple gemspecs at #{expanded_path}. Please use the :name option to specify which one." + end + end + + def gem(name, *args) + options = args.last.is_a?(Hash) ? args.pop.dup : {} + version = args || [">= 0"] + + normalize_options(name, version, options) + + dep = Dependency.new(name, version, options) + + # if there's already a dependency with this name we try to prefer one + if current = @dependencies.find { |d| d.name == dep.name } + if current.requirement != dep.requirement + if current.type == :development + @dependencies.delete current + elsif dep.type == :development + return + else + raise GemfileError, "You cannot specify the same gem twice with different version requirements.\n" \ + "You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})" + end + + else + Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \ + "You should probably keep only one of them.\n" \ + "While it's not a problem now, it could cause errors if you change the version of just one of them later." + end + + if current.source != dep.source + if current.type == :development + @dependencies.delete current + elsif dep.type == :development + return + else + raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \ + "You specified that #{dep.name} (#{dep.requirement}) should come from " \ + "#{current.source || 'an unspecified source'} and #{dep.source}\n" + end + end + end + + @dependencies << dep + end + + def source(source, &blk) + source = normalize_source(source) + if block_given? + with_source(@sources.add_rubygems_source("remotes" => source), &blk) + else + @sources.add_rubygems_remote(source) + end + end + + def git_source(name, &block) + unless block_given? + raise InvalidOption, "You need to pass a block to #git_source" + end + + if valid_keys.include?(name.to_s) + raise InvalidOption, "You cannot use #{name} as a git source. It " \ + "is a reserved key. Reserved keys are: #{valid_keys.join(", ")}" + end + + @git_sources[name.to_s] = block + end + + def path(path, options = {}, &blk) + with_source(@sources.add_path_source(normalize_hash(options).merge("path" => Pathname.new(path))), &blk) + end + + def git(uri, options = {}, &blk) + unless block_given? + msg = "You can no longer specify a git source by itself. Instead, \n" \ + "either use the :git option on a gem, or specify the gems that \n" \ + "bundler should find in the git source by passing a block to \n" \ + "the git method, like: \n\n" \ + " git 'git://github.com/rails/rails.git' do\n" \ + " gem 'rails'\n" \ + " end" + raise DeprecatedError, msg + end + + with_source(@sources.add_git_source(normalize_hash(options).merge("uri" => uri)), &blk) + end + + def to_definition(lockfile, unlock) + Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version) + end + + def group(*args, &blk) + @groups.concat args + yield + ensure + args.each { @groups.pop } + end + + def platforms(*platforms) + @platforms.concat platforms + yield + ensure + platforms.each { @platforms.pop } + end + alias_method :platform, :platforms + + def env(name) + @env, old = name, @env + yield + ensure + @env = old + end + + def method_missing(name, *args) + location = caller[0].split(':')[0..1].join(':') + raise GemfileError, "Undefined local variable or method `#{name}' for Gemfile\n" \ + " from #{location}" + end + + private + + def add_github_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" } + end + + def with_source(source) + if block_given? + @source = source + yield + end + source + ensure + @source = nil + end + + def normalize_hash(opts) + opts.keys.each do |k| + opts[k.to_s] = opts.delete(k) unless k.is_a?(String) + end + opts + end + + def valid_keys + @valid_keys ||= %w(group groups git path name branch ref tag require submodules platform platforms type source) + end + + 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.} + end + + normalize_hash(opts) + + git_names = @git_sources.keys.map(&:to_s) + + invalid_keys = opts.keys - (valid_keys + git_names) + if invalid_keys.any? + message = "You passed #{invalid_keys.map{|k| ':'+k }.join(", ")} " + message << if invalid_keys.size > 1 + "as options for gem '#{name}', but they are invalid." + else + "as an option for gem '#{name}', but it is invalid." + end + + message << " Valid options are: #{valid_keys.join(", ")}" + raise InvalidOption, message + end + + groups = @groups.dup + opts["group"] = opts.delete("groups") || opts["group"] + groups.concat Array(opts.delete("group")) + groups = [:default] if groups.empty? + + platforms = @platforms.dup + opts["platforms"] = opts["platform"] || opts["platforms"] + platforms.concat Array(opts.delete("platforms")) + platforms.map! { |p| p.to_sym } + platforms.each do |p| + next if VALID_PLATFORMS.include?(p) + raise GemfileError, "`#{p}` is not a valid platform. The available options are: #{VALID_PLATFORMS.inspect}" + end + + # Save sources passed in a key + if opts.has_key?("source") + source = normalize_source(opts["source"]) + opts["source"] = @sources.add_rubygems_source("remotes" => source) + end + + git_name = (git_names & opts.keys).last + if @git_sources[git_name] + opts["git"] = @git_sources[git_name].call(opts[git_name]) + end + + ["git", "path"].each do |type| + if param = opts[type] + if version.first && version.first =~ /^\s*=?\s*(\d[^\s]*)\s*$/ + options = opts.merge("name" => name, "version" => $1) + else + options = opts.dup + end + source = send(type, param, options) {} + opts["source"] = source + end + end + + opts["source"] ||= @source + opts["env"] ||= @env + opts["platforms"] = platforms.dup + opts["group"] = groups + end + + def normalize_source(source) + case source + when :gemcutter, :rubygems, :rubyforge + Bundler.ui.warn "The source :#{source} is deprecated because HTTP " \ + "requests are insecure.\nPlease change your source to 'https://" \ + "rubygems.org' if possible, or 'http://rubygems.org' if not." + "http://rubygems.org" + when String + source + else + raise GemfileError, "Unknown source '#{source}'" + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/endpoint_specification.rb b/bundler-1.7.2/lib/bundler/endpoint_specification.rb new file mode 100644 index 0000000..8566f26 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/endpoint_specification.rb @@ -0,0 +1,76 @@ +module Bundler + # used for Creating Specifications from the Gemcutter Endpoint + class EndpointSpecification < Gem::Specification + include MatchPlatform + + attr_reader :name, :version, :platform, :dependencies + attr_accessor :source, :source_uri + + def initialize(name, version, platform, dependencies) + @name = name + @version = version + @platform = platform + @dependencies = dependencies + end + + def fetch_platform + @platform + end + + # needed for standalone, load required_paths from local gemspec + # after the gem in installed + def require_paths + if @remote_specification + @remote_specification.require_paths + elsif _local_specification + _local_specification.require_paths + else + super + end + end + + # needed for binstubs + def executables + if @remote_specification + @remote_specification.executables + elsif _local_specification + _local_specification.executables + else + super + end + end + + # needed for bundle clean + def bindir + if @remote_specification + @remote_specification.bindir + elsif _local_specification + _local_specification.bindir + else + super + end + end + + # needed for post_install_messages during install + def post_install_message + if @remote_specification + @remote_specification.post_install_message + elsif _local_specification + _local_specification.post_install_message + end + end + + def _local_specification + eval(File.read(local_specification_path)) if @loaded_from && File.exist?(local_specification_path) + end + + def __swap__(spec) + @remote_specification = spec + end + + private + def local_specification_path + "#{base_dir}/specifications/#{full_name}.gemspec" + end + end +end diff --git a/bundler-1.7.2/lib/bundler/env.rb b/bundler-1.7.2/lib/bundler/env.rb new file mode 100644 index 0000000..0f6f315 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/env.rb @@ -0,0 +1,56 @@ +module Bundler + class Env + + def write(io) + io.write(report) + 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'] + + %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? + end + + out << "\nBundler settings\n" unless Bundler.settings.all.empty? + Bundler.settings.all.each do |setting| + out << " #{setting}\n" + Bundler.settings.pretty_values_for(setting).each do |line| + out << " " << line << "\n" + end + end + + out << "\n\n" << "Gemfile\n" + out << read_file("Gemfile") << "\n" + + out << "\n\n" << "Gemfile.lock\n" + out << read_file("Gemfile.lock") << "\n" + + out + end + + private + + def read_file(filename) + File.read(filename).strip + rescue Errno::ENOENT + "" + rescue => e + "#{e.class}: #{e.message}" + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/environment.rb b/bundler-1.7.2/lib/bundler/environment.rb new file mode 100644 index 0000000..76e2636 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/environment.rb @@ -0,0 +1,42 @@ +module Bundler + class Environment + attr_reader :root + + def initialize(root, definition) + @root = root + @definition = definition + + env_file = Bundler.app_config_path.join('environment.rb') + env_file.rmtree if env_file.exist? + end + + def inspect + @definition.to_lock.inspect + end + + def requested_specs + @definition.requested_specs + end + + def specs + @definition.specs + end + + def dependencies + @definition.dependencies + end + + def current_dependencies + @definition.current_dependencies + end + + def lock + @definition.lock(Bundler.default_lockfile) + end + + def update(*gems) + # Nothing + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/fetcher.rb b/bundler-1.7.2/lib/bundler/fetcher.rb new file mode 100644 index 0000000..8c8c868 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/fetcher.rb @@ -0,0 +1,399 @@ +require 'bundler/vendored_persistent' +require 'securerandom' +require 'cgi' + +module Bundler + + # Handles all the fetching with the rubygems server + class Fetcher + # 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 + class CertificateFailureError < HTTPError + def initialize(remote_uri) + super "Could not verify the SSL certificate for #{remote_uri}.\nThere" \ + " is a chance you are experiencing a man-in-the-middle attack, but" \ + " most likely your system doesn't have the CA certificates needed" \ + " for verification. For information about OpenSSL certificates, see" \ + " bit.ly/ruby-ssl. To connect without using SSL, edit your Gemfile" \ + " sources and change 'https' to 'http'." + end + end + # This is the error raised when a source is HTTPS and OpenSSL didn't load + class SSLError < HTTPError + def initialize(msg = nil) + super msg || "Could not load OpenSSL.\n" \ + "You must recompile Ruby with OpenSSL support or change the sources in your " \ + "Gemfile from 'https' to 'http'. Instructions for compiling with OpenSSL " \ + "using RVM are available at rvm.io/packages/openssl." + end + end + # This error is raised if HTTP authentication is required, but not provided. + class AuthenticationRequiredError < HTTPError + def initialize(remote_uri) + super "Authentication is required for #{remote_uri}.\n" \ + "Please supply credentials for this source. You can do this by running:\n" \ + " bundle config #{remote_uri} username:password" + end + end + # This error is raised if HTTP authentication is provided, but incorrect. + class BadAuthenticationError < HTTPError + def initialize(remote_uri) + super "Bad username or password for #{remote_uri}.\n" \ + "Please double-check your credentials and correct them." + end + end + + # Exceptions classes that should bypass retry attempts. If your password didn't work the + # first time, it's not going to the third time. + AUTH_ERRORS = [AuthenticationRequiredError, BadAuthenticationError] + + class << self + attr_accessor :disable_endpoint, :api_timeout, :redirect_limit, :max_retries + + def download_gem_from_uri(spec, uri) + spec.fetch_platform + + download_path = Bundler.requires_sudo? ? Bundler.tmp(spec.full_name) : Bundler.rubygems.gem_dir + gem_path = "#{Bundler.rubygems.gem_dir}/cache/#{spec.full_name}.gem" + + FileUtils.mkdir_p("#{download_path}/cache") + Bundler.rubygems.download_gem(spec, uri, download_path) + + if Bundler.requires_sudo? + Bundler.mkdir_p "#{Bundler.rubygems.gem_dir}/cache" + Bundler.sudo "mv #{Bundler.tmp(spec.full_name)}/cache/#{spec.full_name}.gem #{gem_path}" + end + + gem_path + end + + def user_agent + @user_agent ||= begin + ruby = Bundler.ruby_version + + agent = "bundler/#{Bundler::VERSION}" + 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}" + end + # add a random ID so we can consolidate runs server-side + agent << " " << SecureRandom.hex(8) + end + end + + end + + def initialize(remote_uri) + @redirect_limit = 5 # How many redirects to allow in one request + @api_timeout = 10 # How long to wait for each API call + @max_retries = 3 # How many retries for the API call + + @remote_uri = Bundler::Source.mirror_for(remote_uri) + @public_uri = @remote_uri.dup + @public_uri.user, @public_uri.password = nil, nil # don't print these + + Socket.do_not_reverse_lookup = true + connection # create persistent connection + end + + def connection + @connection ||= begin + needs_ssl = @remote_uri.scheme == "https" || + Bundler.settings[:ssl_verify_mode] || + Bundler.settings[:ssl_client_cert] + raise SSLError if needs_ssl && !defined?(OpenSSL::SSL) + + con = Net::HTTP::Persistent.new 'bundler', :ENV + + if @remote_uri.scheme == "https" + con.verify_mode = (Bundler.settings[:ssl_verify_mode] || + OpenSSL::SSL::VERIFY_PEER) + con.cert_store = bundler_cert_store + end + + if Bundler.settings[:ssl_client_cert] + pem = File.read(Bundler.settings[:ssl_client_cert]) + con.cert = OpenSSL::X509::Certificate.new(pem) + con.key = OpenSSL::PKey::RSA.new(pem) + end + + con.read_timeout = @api_timeout + con.override_headers["User-Agent"] = self.class.user_agent + con + end + end + + def uri + @public_uri + end + + # fetch a gem specification + def fetch_spec(spec) + spec = spec - [nil, 'ruby', ''] + spec_file_name = "#{spec.join '-'}.gemspec" + + uri = URI.parse("#{@remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz") + if uri.scheme == 'file' + Bundler.load_marshal Gem.inflate(Gem.read_binary(uri.path)) + elsif cached_spec_path = gemspec_cached_path(spec_file_name) + Bundler.load_gemspec(cached_spec_path) + else + Bundler.load_marshal Gem.inflate(fetch(uri)) + end + rescue MarshalError + raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \ + "Your network or your gem server is probably having issues right now." + end + + # cached gem specification path, if one exists + def gemspec_cached_path spec_file_name + paths = Bundler.rubygems.spec_cache_dirs.map { |dir| File.join(dir, spec_file_name) } + paths = paths.select {|path| File.file? path } + paths.first + end + + # return the specs in the bundler format as an index + def specs(gem_names, source) + old = Bundler.rubygems.sources + index = Index.new + + if gem_names && use_api + specs = fetch_remote_specs(gem_names) + end + + if specs.nil? + # API errors mean we should treat this as a non-API source + @use_api = false + + specs = Bundler::Retry.new("source fetch", AUTH_ERRORS).attempts do + fetch_all_remote_specs + end + end + + specs[@remote_uri].each do |name, version, platform, dependencies| + next if name == 'bundler' + spec = nil + if dependencies + spec = EndpointSpecification.new(name, version, platform, dependencies) + else + spec = RemoteSpecification.new(name, version, platform, self) + end + spec.source = source + spec.source_uri = @remote_uri + index << spec + end + + index + rescue CertificateFailureError => e + Bundler.ui.info "" if gem_names && use_api # newline after dots + raise e + ensure + Bundler.rubygems.sources = old + end + + # fetch index + def fetch_remote_specs(gem_names, full_dependency_list = [], last_spec_list = []) + query_list = gem_names - full_dependency_list + + # only display the message on the first run + if Bundler.ui.debug? + Bundler.ui.debug "Query List: #{query_list.inspect}" + else + Bundler.ui.info ".", false + end + + return {@remote_uri => last_spec_list} if query_list.empty? + + remote_specs = Bundler::Retry.new("dependency api", AUTH_ERRORS).attempts do + fetch_dependency_remote_specs(query_list) + end + + spec_list, deps_list = remote_specs + returned_gems = spec_list.map {|spec| spec.first }.uniq + fetch_remote_specs(deps_list, full_dependency_list + returned_gems, spec_list + last_spec_list) + rescue HTTPError, MarshalError, GemspecError + Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over + Bundler.ui.debug "could not fetch from the dependency API, trying the full index" + @use_api = false + return nil + end + + def use_api + return @use_api if defined?(@use_api) + + if @remote_uri.scheme == "file" || Bundler::Fetcher.disable_endpoint + @use_api = false + elsif fetch(dependency_api_uri) + @use_api = true + end + rescue HTTPError + @use_api = false + end + + def inspect + "#<#{self.class}:0x#{object_id} uri=#{uri}>" + end + + private + + HTTP_ERRORS = [ + Timeout::Error, EOFError, SocketError, Errno::ENETDOWN, + Errno::EINVAL, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EAGAIN, + Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, + Net::HTTP::Persistent::Error + ] + + def fetch(uri, counter = 0) + raise HTTPError, "Too many redirects" if counter >= @redirect_limit + + response = request(uri) + Bundler.ui.debug("HTTP #{response.code} #{response.message}") + + case response + when Net::HTTPRedirection + new_uri = URI.parse(response["location"]) + if new_uri.host == uri.host + new_uri.user = uri.user + new_uri.password = uri.password + end + fetch(new_uri, counter + 1) + when Net::HTTPSuccess + response.body + when Net::HTTPRequestEntityTooLarge + raise FallbackError, response.body + else + raise HTTPError, "#{response.class}: #{response.body}" + end + end + + def request(uri) + Bundler.ui.debug "HTTP GET #{uri}" + req = Net::HTTP::Get.new uri.request_uri + if uri.user + user = CGI.unescape(uri.user) + password = uri.password ? CGI.unescape(uri.password) : nil + req.basic_auth(user, password) + end + connection.request(uri, req) + rescue Net::HTTPUnauthorized, Net::HTTPForbidden + retry_with_auth { request(uri) } + rescue OpenSSL::SSL::SSLError + raise CertificateFailureError.new(uri) + rescue *HTTP_ERRORS => e + Bundler.ui.trace e + raise HTTPError, "Network error while fetching #{uri}" + end + + def dependency_api_uri(gem_names = []) + uri = fetch_uri + "api/v1/dependencies" + uri.query = "gems=#{URI.encode(gem_names.join(","))}" if gem_names.any? + uri + end + + # fetch from Gemcutter Dependency Endpoint API + def fetch_dependency_remote_specs(gem_names) + Bundler.ui.debug "Query Gemcutter Dependency Endpoint API: #{gem_names.join(',')}" + marshalled_deps = fetch dependency_api_uri(gem_names) + gem_list = Bundler.load_marshal(marshalled_deps) + deps_list = [] + + spec_list = gem_list.map do |s| + dependencies = s[:dependencies].map do |name, requirement| + dep = well_formed_dependency(name, requirement.split(", ")) + deps_list << dep.name + dep + end + + [s[:name], Gem::Version.new(s[:number]), s[:platform], dependencies] + end + + [spec_list, deps_list.uniq] + end + + # fetch from modern index: specs.4.8.gz + def fetch_all_remote_specs + old_sources = Bundler.rubygems.sources + Bundler.rubygems.sources = [@remote_uri.to_s] + Bundler.rubygems.fetch_all_remote_specs + rescue Gem::RemoteFetcher::FetchError, OpenSSL::SSL::SSLError => e + case e.message + when /certificate verify failed/ + raise CertificateFailureError.new(uri) + when /401|403/ + # Gemfury uses a 403 for unauthenticated requests instead of a 401, so retry auth + # on both. + retry_with_auth { fetch_all_remote_specs } + else + Bundler.ui.trace e + raise HTTPError, "Could not fetch specs from #{uri}" + end + ensure + Bundler.rubygems.sources = old_sources + end + + def well_formed_dependency(name, *requirements) + Gem::Dependency.new(name, *requirements) + rescue ArgumentError => e + illformed = 'Ill-formed requirement ["# e + Bundler.ui.error e.message, :wrap => true + Bundler.ui.trace e + exit e.status_code + rescue Thor::AmbiguousTaskError => e + Bundler.ui.error e.message + exit 15 + rescue Thor::UndefinedTaskError => e + Bundler.ui.error e.message + exit 15 + rescue Thor::Error => e + Bundler.ui.error e.message + exit 1 + rescue LoadError => e + raise e unless e.message =~ /cannot load such file -- openssl|openssl.so|libcrypto.so/ + Bundler.ui.error "\nCould not load OpenSSL." + Bundler.ui.warn <<-WARN, :wrap => true + You must recompile Ruby with OpenSSL support or change the sources in your \ + Gemfile from 'https' to 'http'. Instructions for compiling with OpenSSL \ + using RVM are available at http://rvm.io/packages/openssl. + WARN + Bundler.ui.trace e + exit 1 + rescue Interrupt => e + Bundler.ui.error "\nQuitting..." + Bundler.ui.trace e + exit 1 + 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 + end +end diff --git a/bundler-1.7.2/lib/bundler/gem_helper.rb b/bundler-1.7.2/lib/bundler/gem_helper.rb new file mode 100644 index 0000000..6b7a176 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/gem_helper.rb @@ -0,0 +1,169 @@ +require 'bundler/vendored_thor' unless defined?(Thor) +require 'bundler' + +module Bundler + class GemHelper + include Rake::DSL if defined? Rake::DSL + + class << self + # set when install'd. + attr_accessor :instance + + def install_tasks(opts = {}) + new(opts[:dir], opts[:name]).install + end + + def gemspec(&block) + gemspec = instance.gemspec + block.call(gemspec) if block + gemspec + end + end + + attr_reader :spec_path, :base, :gemspec + + def initialize(base = nil, name = nil) + Bundler.ui = UI::Shell.new + @base = (base ||= SharedHelpers.pwd) + gemspecs = name ? [File.join(base, "#{name}.gemspec")] : Dir[File.join(base, "{,*}.gemspec")] + raise "Unable to determine name from existing gemspec. Use :name => 'gemname' in #install_tasks to manually set it." unless gemspecs.size == 1 + @spec_path = gemspecs.first + @gemspec = Bundler.load_gemspec(@spec_path) + end + + def install + built_gem_path = nil + + desc "Build #{name}-#{version}.gem into the pkg directory." + task 'build' do + built_gem_path = build_gem + end + + desc "Build and install #{name}-#{version}.gem into system gems." + task 'install' => 'build' do + 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) + end + + GemHelper.instance = self + end + + def build_gem + file_name = nil + sh("gem build -V '#{spec_path}'") { |out, code| + file_name = File.basename(built_gem_path) + FileUtils.mkdir_p(File.join(base, 'pkg')) + FileUtils.mv(built_gem_path, 'pkg') + Bundler.ui.confirm "#{name} #{version} built to pkg/#{file_name}." + } + File.join(base, 'pkg', file_name) + end + + def install_gem(built_gem_path=nil) + built_gem_path ||= build_gem + out, _ = sh_with_code("gem install '#{built_gem_path}' --local") + raise "Couldn't install gem, run `gem install #{built_gem_path}' for more detailed output" unless out[/Successfully installed/] + 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? + sh("gem push '#{path}'") + Bundler.ui.confirm "Pushed #{name} #{version} to rubygems.org." + else + raise "Your rubygems.org credentials aren't set. Run `gem push` to set them." + end + end + + def built_gem_path + Dir[File.join(base, "#{name}-*.gem")].sort_by{|f| File.mtime(f)}.last + end + + def git_push + perform_git_push + perform_git_push ' --tags' + Bundler.ui.confirm "Pushed git commits and tags." + end + + def perform_git_push(options = '') + cmd = "git push #{options}" + out, code = sh_with_code(cmd) + raise "Couldn't git push. `#{cmd}' failed with the following output:\n\n#{out}\n" unless code == 0 + end + + def already_tagged? + if sh('git tag').split(/\n/).include?(version_tag) + Bundler.ui.confirm "Tag #{version_tag} has already been created." + true + end + end + + def guard_clean + clean? && committed? or raise("There are files that need to be committed first.") + end + + def clean? + sh_with_code("git diff --exit-code")[1] == 0 + end + + def committed? + sh_with_code("git diff-index --quiet --cached HEAD")[1] == 0 + end + + def tag_version + sh "git tag -a -m \"Version #{version}\" #{version_tag}" + Bundler.ui.confirm "Tagged #{version_tag}." + yield if block_given? + rescue + Bundler.ui.error "Untagging #{version_tag} due to error." + sh_with_code "git tag -d #{version_tag}" + raise + end + + def version + gemspec.version + end + + def version_tag + "v#{version}" + end + + def name + gemspec.name + end + + def sh(cmd, &block) + out, code = sh_with_code(cmd, &block) + code == 0 ? out : raise(out.empty? ? "Running `#{cmd}' failed. Run this command directly for more detailed output." : out) + end + + def sh_with_code(cmd, &block) + cmd << " 2>&1" + outbuf = '' + Bundler.ui.debug(cmd) + SharedHelpers.chdir(base) { + outbuf = `#{cmd}` + if $? == 0 + block.call(outbuf) if block + end + } + [outbuf, $?] + end + + def gem_push? + ! %w{n no nil false off 0}.include?(ENV['gem_push'].to_s.downcase) + end + end +end diff --git a/bundler-1.7.2/lib/bundler/gem_helpers.rb b/bundler-1.7.2/lib/bundler/gem_helpers.rb new file mode 100644 index 0000000..2040604 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/gem_helpers.rb @@ -0,0 +1,24 @@ +module Bundler + module GemHelpers + + GENERIC_CACHE = {} + GENERICS = [ + [Gem::Platform.new('java'), Gem::Platform.new('java')], + [Gem::Platform.new('mswin32'), Gem::Platform.new('mswin32')], + [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')] + ] + + def generic(p) + return p if p == Gem::Platform::RUBY + + GENERIC_CACHE[p] ||= begin + _, found = GENERICS.find do |match, _generic| + p.os == match.os && (!match.cpu || p.cpu == match.cpu) + end + found || Gem::Platform::RUBY + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/gem_installer.rb b/bundler-1.7.2/lib/bundler/gem_installer.rb new file mode 100644 index 0000000..7d84939 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/gem_installer.rb @@ -0,0 +1,9 @@ +require 'rubygems/installer' + +module Bundler + class GemInstaller < Gem::Installer + def check_executable_overwrite(filename) + # Bundler needs to install gems regardless of binstub overwriting + end + end +end diff --git a/bundler-1.7.2/lib/bundler/gem_path_manipulation.rb b/bundler-1.7.2/lib/bundler/gem_path_manipulation.rb new file mode 100644 index 0000000..628d954 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/gem_path_manipulation.rb @@ -0,0 +1,8 @@ +module Bundler + def self.preserve_gem_path + original_gem_path = ENV["_ORIGINAL_GEM_PATH"] + gem_path = ENV["GEM_PATH"] + ENV["_ORIGINAL_GEM_PATH"] = gem_path if original_gem_path.nil? || original_gem_path == "" + ENV["GEM_PATH"] = original_gem_path if gem_path.nil? || gem_path == "" + end +end diff --git a/bundler-1.7.2/lib/bundler/gem_tasks.rb b/bundler-1.7.2/lib/bundler/gem_tasks.rb new file mode 100644 index 0000000..bc75908 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/gem_tasks.rb @@ -0,0 +1,2 @@ +require 'bundler/gem_helper' +Bundler::GemHelper.install_tasks diff --git a/bundler-1.7.2/lib/bundler/graph.rb b/bundler-1.7.2/lib/bundler/graph.rb new file mode 100644 index 0000000..92f538b --- /dev/null +++ b/bundler-1.7.2/lib/bundler/graph.rb @@ -0,0 +1,166 @@ +require 'set' +module Bundler + class Graph + GRAPH_NAME = :Gemfile + + def initialize(env, output_file, show_version = false, show_requirements = false, output_format = "png") + @env = env + @output_file = output_file + @show_version = show_version + @show_requirements = show_requirements + @output_format = output_format + + @groups = [] + @relations = Hash.new {|h, k| h[k] = Set.new} + @node_options = {} + @edge_options = {} + + _patching_gem_dependency_class + _populate_relations + end + + attr_reader :groups, :relations, :node_options, :edge_options, :output_file, :output_format + + def viz + GraphVizClient.new(self).run + end + + private + + def _populate_relations + parent_dependencies = _groups.values.to_set.flatten + while true + if parent_dependencies.empty? + break + else + tmp = Set.new + parent_dependencies.each do |dependency| + child_dependencies = dependency.to_spec.runtime_dependencies.to_set + @relations[dependency.name] += child_dependencies.map(&:name).to_set + tmp += child_dependencies + + @node_options[dependency.name] = _make_label(dependency, :node) + child_dependencies.each do |c_dependency| + @edge_options["#{dependency.name}_#{c_dependency.name}"] = _make_label(c_dependency, :edge) + end + end + parent_dependencies = tmp + end + end + end + + def _groups + relations = Hash.new {|h, k| h[k] = Set.new} + @env.current_dependencies.each do |dependency| + dependency.groups.each do |group| + relations[group.to_s].add(dependency) + @relations[group.to_s].add(dependency.name) + + @node_options[group.to_s] ||= _make_label(group, :node) + @edge_options["#{group}_#{dependency.name}"] = _make_label(dependency, :edge) + end + end + @groups = relations.keys + relations + end + + def _make_label(symbol_or_string_or_dependency, element_type) + case element_type.to_sym + when :node + if symbol_or_string_or_dependency.is_a?(Gem::Dependency) + label = symbol_or_string_or_dependency.name.dup + label << "\n#{symbol_or_string_or_dependency.to_spec.version.to_s}" if @show_version + else + label = symbol_or_string_or_dependency.to_s + end + when :edge + label = nil + if symbol_or_string_or_dependency.respond_to?(:requirements_list) && @show_requirements + tmp = symbol_or_string_or_dependency.requirements_list.join(", ") + label = tmp if tmp != ">= 0" + end + else + raise ArgumentError, "2nd argument is invalid" + end + label.nil? ? {} : { :label => label } + end + + def _patching_gem_dependency_class + # method borrow from rubygems/dependency.rb + # redefinition of matching_specs will also redefine to_spec and to_specs + Gem::Dependency.class_eval do + def matching_specs platform_only = false + matches = Bundler.load.specs.select { |spec| + self.name == spec.name and + requirement.satisfied_by? spec.version + } + + if platform_only + matches.reject! { |spec| + not Gem::Platform.match spec.platform + } + end + + matches = matches.sort_by { |s| s.sort_obj } # HACK: shouldn't be needed + end + end + end + + class GraphVizClient + def initialize(graph_instance) + @graph_name = graph_instance.class::GRAPH_NAME + @groups = graph_instance.groups + @relations = graph_instance.relations + @node_options = graph_instance.node_options + @edge_options = graph_instance.edge_options + @output_file = graph_instance.output_file + @output_format = graph_instance.output_format + end + + def g + @g ||= ::GraphViz.digraph(@graph_name, {:concentrate => true, :normalize => true, :nodesep => 0.55}) do |g| + g.edge[:weight] = 2 + g.edge[:fontname] = g.node[:fontname] = 'Arial, Helvetica, SansSerif' + g.edge[:fontsize] = 12 + end + end + + def run + @groups.each do |group| + g.add_nodes( + group, + {:style => 'filled', + :fillcolor => '#B9B9D5', + :shape => "box3d", + :fontsize => 16}.merge(@node_options[group]) + ) + end + + @relations.each do |parent, children| + children.each do |child| + if @groups.include?(parent) + g.add_nodes(child, {:style => 'filled', :fillcolor => '#B9B9D5'}.merge(@node_options[child])) + g.add_edges(parent, child, {:constraint => false}.merge(@edge_options["#{parent}_#{child}"])) + else + g.add_nodes(child, @node_options[child]) + g.add_edges(parent, child, @edge_options["#{parent}_#{child}"]) + end + end + end + + if @output_format.to_s == "debug" + $stdout.puts g.output :none => String + Bundler.ui.info "debugging bundle viz..." + else + begin + g.output @output_format.to_sym => "#{@output_file}.#{@output_format}" + Bundler.ui.info "#{@output_file}.#{@output_format}" + rescue ArgumentError => e + $stderr.puts "Unsupported output format. See Ruby-Graphviz/lib/graphviz/constants.rb" + raise e + end + end + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/index.rb b/bundler-1.7.2/lib/bundler/index.rb new file mode 100644 index 0000000..104bf44 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/index.rb @@ -0,0 +1,203 @@ +require "set" + +module Bundler + class Index + include Enumerable + + def self.build + i = new + yield i + i + end + + attr_reader :specs, :all_specs, :sources + protected :specs, :all_specs + + def initialize + @sources = [] + @cache = {} + @specs = Hash.new { |h,k| h[k] = [] } + @all_specs = Hash.new { |h,k| h[k] = [] } + end + + def initialize_copy(o) + super + @sources = @sources.dup + @cache = {} + @specs = Hash.new { |h,k| h[k] = [] } + @all_specs = Hash.new { |h,k| h[k] = [] } + + o.specs.each do |name, array| + @specs[name] = array.dup + end + o.all_specs.each do |name, array| + @all_specs[name] = array.dup + end + end + + def inspect + "#<#{self.class}:0x#{object_id} sources=#{sources.map{|s| s.inspect}} specs.size=#{specs.size}>" + end + + def empty? + each { return false } + true + end + + def search_all(name) + all_matches = @all_specs[name] + local_search(name) + @sources.each do |source| + all_matches.concat(source.search_all(name)) + end + all_matches + end + + # Search this index's specs, and any source indexes that this index knows + # about, returning all of the results. + def search(query, base = nil) + results = local_search(query, base) + seen = Set.new(results.map { |spec| [spec.name, spec.version, spec.platform] }) + + @sources.each do |source| + source.search(query, base).each do |spec| + lookup = [spec.name, spec.version, spec.platform] + unless seen.include?(lookup) + results << spec + seen << lookup + end + end + end + + results.sort_by {|s| [s.version, s.platform.to_s == 'ruby' ? "\0" : s.platform.to_s] } + end + + def local_search(query, base = nil) + case query + when Gem::Specification, RemoteSpecification, LazySpecification, EndpointSpecification then search_by_spec(query) + when String then specs_by_name(query) + when Gem::Dependency then search_by_dependency(query, base) + else + raise "You can't search for a #{query.inspect}." + end + end + + def source_types + sources.map{|s| s.class }.uniq + end + + alias [] search + + def <<(spec) + arr = specs_by_name(spec.name) + + 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) + end + end + + # returns a list of the dependencies + def unmet_dependency_names + names = [] + each{|s| names.push *s.dependencies.map{|d| d.name } } + names.uniq! + names.delete_if{|n| n == "bundler" } + names.select{|n| search(n).empty? } + end + + def use(other, override_dupes = false) + return unless other + other.each do |s| + if (dupes = search_by_spec(s)) && dupes.any? + @all_specs[s.name] = [s] + dupes + next unless override_dupes + @specs[s.name] -= dupes + end + @specs[s.name] << s + end + self + end + + def size + @sources.inject(@specs.size) do |size, source| + size += source.size + end + end + + def ==(o) + all? do |spec| + other_spec = o[spec].first + (spec.dependencies & other_spec.dependencies).empty? && spec.source == other_spec.source + end + end + + def add_source(index) + if index.is_a?(Index) + @sources << index + @sources.uniq! # need to use uniq! here instead of checking for the item before adding + else + raise ArgumentError, "Source must be an index, not #{index.class}" + end + end + + private + + def specs_by_name(name) + @specs[name] + end + + def search_by_dependency(dependency, base = nil) + @cache[base || false] ||= {} + @cache[base || false][dependency] ||= begin + specs = specs_by_name(dependency.name) + (base || []) + found = specs.select do |spec| + if base # allow all platforms when searching from a lockfile + dependency.matches_spec?(spec) + else + dependency.matches_spec?(spec) && Gem::Platform.match(spec.platform) + end + end + + wants_prerelease = dependency.requirement.prerelease? + only_prerelease = specs.all? {|spec| spec.version.prerelease? } + + unless wants_prerelease || only_prerelease + found.reject! { |spec| spec.version.prerelease? } + end + + found + end + 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 + end + + if RUBY_VERSION < '1.9' + def same_version?(a, b) + regex = /^(.*?)(?:\.0)*$/ + a.to_s[regex, 1] == b.to_s[regex, 1] + end + else + def same_version?(a, b) + a == b + end + end + + def spec_satisfies_dependency?(spec, dep) + return false unless dep.name == spec.name + dep.requirement.satisfied_by?(spec.version) + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/injector.rb b/bundler-1.7.2/lib/bundler/injector.rb new file mode 100644 index 0000000..79350b5 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/injector.rb @@ -0,0 +1,64 @@ +module Bundler + class Injector + def self.inject(new_deps) + injector = new(new_deps) + injector.inject(Bundler.default_gemfile, Bundler.default_lockfile) + end + + def initialize(new_deps) + @new_deps = new_deps + end + + def inject(gemfile_path, lockfile_path) + if Bundler.settings[:frozen] + # ensure the lock and Gemfile are synced + Bundler.definition.ensure_equivalent_gemfile_and_lockfile(true) + # temporarily remove frozen while we inject + frozen = Bundler.settings.delete(:frozen) + end + + # evaluate the Gemfile we have now + builder = Dsl.new + builder.eval_gemfile(gemfile_path) + + # don't inject any gems that are already in the Gemfile + @new_deps -= builder.dependencies + + # add new deps to the end of the in-memory Gemfile + builder.eval_gemfile("injected gems", new_gem_lines) if @new_deps.any? + + # resolve to see if the new deps broke anything + definition = builder.to_definition(lockfile_path, {}) + definition.resolve_remotely! + + # since nothing broke, we can add those gems to the gemfile + append_to(gemfile_path) if @new_deps.any? + + # since we resolved successfully, write out the lockfile + definition.lock(Bundler.default_lockfile) + + # return an array of the deps that we added + return @new_deps + ensure + Bundler.settings[:frozen] = '1' if frozen + end + + private + + def new_gem_lines + @new_deps.map do |d| + %|gem '#{d.name}', '#{d.requirement}'| + end.join("\n") + end + + def append_to(gemfile_path) + gemfile_path.open("a") do |f| + f.puts + f.puts "# Added at #{Time.now} by #{`whoami`.chomp}:" + f.puts new_gem_lines + end + end + + + end +end diff --git a/bundler-1.7.2/lib/bundler/installer.rb b/bundler-1.7.2/lib/bundler/installer.rb new file mode 100644 index 0000000..a4747c6 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/installer.rb @@ -0,0 +1,334 @@ +require 'erb' +require 'rubygems/dependency_installer' +require 'bundler/parallel_workers' + +module Bundler + class Installer < Environment + class << self + attr_accessor :post_install_messages, :ambiguous_gems + + Installer.post_install_messages = {} + Installer.ambiguous_gems = [] + end + + # Begins the installation process for Bundler. + # For more information see the #run method on this class. + def self.install(root, definition, options = {}) + installer = new(root, definition) + installer.run(options) + installer + end + + # Runs the install procedures for a specific Gemfile. + # + # Firstly, this method will check to see if Bundler.bundle_path exists + # and if not then will create it. This is usually the location of gems + # on the system, be it RVM or at a system path. + # + # Secondly, it checks if Bundler has been configured to be "frozen" + # Frozen ensures that the Gemfile and the Gemfile.lock file are matching. + # This stops a situation where a developer may update the Gemfile but may not run + # `bundle install`, which leads to the Gemfile.lock file not being correctly updated. + # If this file is not correctly updated then any other developer running + # `bundle install` will potentially not install the correct gems. + # + # Thirdly, Bundler checks if there are any dependencies specified in the Gemfile using + # Bundler::Environment#dependencies. If there are no dependencies specified then + # Bundler returns a warning message stating so and this method returns. + # + # Fourthly, Bundler checks if the default lockfile (Gemfile.lock) exists, and if so + # then proceeds to set up a defintion based on the default gemfile (Gemfile) and the + # default lock file (Gemfile.lock). However, this is not the case if the platform is different + # to that which is specified in Gemfile.lock, or if there are any missing specs for the gems. + # + # Fifthly, Bundler resolves the dependencies either through a cache of gems or by remote. + # This then leads into the gems being installed, along with stubs for their executables, + # but only if the --binstubs option has been passed or Bundler.options[:bin] has been set + # earlier. + # + # Sixthly, a new Gemfile.lock is created from the installed gems to ensure that the next time + # that a user runs `bundle install` they will receive any updates from this process. + # + # Finally: TODO add documentation for how the standalone process works. + def run(options) + create_bundle_path + + if Bundler.settings[:frozen] + @definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment]) + end + + if dependencies.empty? + Bundler.ui.warn "The Gemfile specifies no dependencies" + lock + return + end + + if Bundler.default_lockfile.exist? && !options["update"] + local = Bundler.ui.silence do + begin + tmpdef = Definition.build(Bundler.default_gemfile, Bundler.default_lockfile, nil) + true unless tmpdef.new_platform? || tmpdef.missing_specs.any? + rescue BundlerError + end + end + end + + # Since we are installing, we can resolve the definition + # using remote specs + unless local + options["local"] ? @definition.resolve_with_cache! : @definition.resolve_remotely! + end + + # the order that the resolver provides is significant, since + # dependencies might actually affect the installation of a gem. + # 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? + install_in_parallel jobs, options[:standalone] + else + install_sequentially options[:standalone] + end + + lock unless Bundler.settings[:frozen] + generate_standalone(options[:standalone]) if options[:standalone] + end + + 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 + end + Bundler.ui.debug debug_message if debug_message + Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}" + end + + if Bundler.settings[:bin] && standalone + generate_standalone_bundler_executable_stubs(spec) + elsif Bundler.settings[:bin] + generate_bundler_executable_stubs(spec, :force => true) + end + + post_install_message + rescue Errno::ENOSPC + raise Bundler::InstallError, "Your disk is out of space. Free some " \ + "space to be able to install your bundle." + rescue Exception => e + # if install hook failed or gem signature is bad, just die + raise e if e.is_a?(Bundler::InstallHookError) || e.is_a?(Bundler::SecurityError) + + # other failure, likely a native extension build failure + Bundler.ui.info "" + Bundler.ui.warn "#{e.class}: #{e.message}" + msg = "An error occurred while installing #{spec.name} (#{spec.version})," + msg << " and Bundler cannot continue." + + unless spec.source.options["git"] + msg << "\nMake sure that `gem install" + msg << " #{spec.name} -v '#{spec.version}'` succeeds before bundling." + end + Bundler.ui.debug e.backtrace.join("\n") + raise Bundler::InstallError, msg + end + + def generate_bundler_executable_stubs(spec, options = {}) + if options[:binstubs_cmd] && spec.executables.empty? + options = {} + spec.runtime_dependencies.each do |dep| + bins = @definition.specs[dep].first.executables + options[dep.name] = bins unless bins.empty? + end + if options.any? + Bundler.ui.warn "#{spec.name} has no executables, but you may want " + + "one from a gem it depends on." + options.each{|name,bins| Bundler.ui.warn " #{name} has: #{bins.join(', ')}" } + else + Bundler.ui.warn "There are no executables for the gem #{spec.name}." + end + return + end + + # double-assignment to avoid warnings about variables that will be used by ERB + bin_path = bin_path = Bundler.bin_path + template = template = File.read(File.expand_path('../templates/Executable', __FILE__)) + relative_gemfile_path = relative_gemfile_path = Bundler.default_gemfile.relative_path_from(bin_path) + ruby_command = ruby_command = Thor::Util.ruby_command + + exists = [] + spec.executables.each do |executable| + next if executable == "bundle" + + binstub_path = "#{bin_path}/#{executable}" + if File.exist?(binstub_path) && !options[:force] + exists << executable + next + end + + File.open(binstub_path, 'w', 0777 & ~File.umask) do |f| + f.puts ERB.new(template, nil, '-').result(binding) + end + end + + if options[:binstubs_cmd] && exists.any? + case exists.size + when 1 + Bundler.ui.warn "Skipped #{exists[0]} since it already exists." + when 2 + Bundler.ui.warn "Skipped #{exists.join(' and ')} since they already exist." + else + items = exists[0...-1].empty? ? nil : exists[0...-1].join(', ') + skipped = [items, exists[-1]].compact.join(' and ') + Bundler.ui.warn "Skipped #{skipped} since they already exist." + end + Bundler.ui.warn "If you want to overwrite skipped stubs, use --force." + end + end + + private + + def can_install_parallely? + min_rubygems = "2.0.7" + if Bundler.current_ruby.mri? || Bundler.rubygems.provides?(">= #{min_rubygems}") + 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." + false + end + end + + def generate_standalone_bundler_executable_stubs(spec) + # double-assignment to avoid warnings about variables that will be used by ERB + bin_path = Bundler.bin_path + template = File.read(File.expand_path('../templates/Executable.standalone', __FILE__)) + ruby_command = ruby_command = Thor::Util.ruby_command + + spec.executables.each do |executable| + next if executable == "bundle" + standalone_path = standalone_path = Pathname(Bundler.settings[:path]).expand_path.relative_path_from(bin_path) + executable_path = executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path) + File.open "#{bin_path}/#{executable}", 'w', 0755 do |f| + f.puts ERB.new(template, nil, '-').result(binding) + end + end + end + + def generate_standalone(groups) + standalone_path = Bundler.settings[:path] + bundler_path = File.join(standalone_path, "bundler") + FileUtils.mkdir_p(bundler_path) + + paths = [] + + if groups.empty? + specs = @definition.requested_specs + else + specs = @definition.specs_for groups.map { |g| g.to_sym } + end + + specs.each do |spec| + next if spec.name == "bundler" + next if spec.require_paths.nil? # builtin gems + + spec.require_paths.each do |path| + full_path = File.join(spec.full_gem_path, path) + gem_path = Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)) + paths << gem_path.to_s.sub("#{Bundler.ruby_version.engine}/#{RbConfig::CONFIG['ruby_version']}", '#{ruby_engine}/#{ruby_version}') + end + end + + + File.open File.join(bundler_path, "setup.rb"), "w" do |file| + file.puts "require 'rbconfig'" + file.puts "# ruby 1.8.7 doesn't define RUBY_ENGINE" + file.puts "ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'" + 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}")} + end + end + end + + def install_sequentially(standalone) + specs.each do |spec| + message = install_gem_from_spec spec, standalone, 0 + if message + Installer.post_install_messages[spec.name] = message + end + end + end + + def install_in_parallel(size, standalone) + name2spec = {} + remains = {} + enqueued = {} + specs.each do |spec| + name2spec[spec.name] = spec + remains[spec.name] = true + end + + worker_pool = ParallelWorkers.worker_pool size, lambda { |name, worker| + spec = name2spec[name] + message = install_gem_from_spec spec, standalone, worker + { :name => spec.name, :post_install => message } + } + + # Keys in the remains hash represent uninstalled gems specs. + # We enqueue all gem specs that do not have any dependencies. + # Later we call this lambda again to install specs that depended on + # previously installed specifications. We continue until all specs + # are installed. + enqueue_remaining_specs = lambda do + remains.keys.each do |name| + next if enqueued[name] + spec = name2spec[name] + if ready_to_install?(spec, remains) + worker_pool.enq name + enqueued[name] = true + end + end + end + enqueue_remaining_specs.call + + until remains.empty? + message = worker_pool.deq + remains.delete message[:name] + if message[:post_install] + Installer.post_install_messages[message[:name]] = message[:post_install] + end + enqueue_remaining_specs.call + end + message + ensure + worker_pool && worker_pool.stop + end + + # We only want to install a gem spec if all its dependencies are met. + # If the dependency is no longer in the `remains` hash then it has been met. + # If a dependency is only development or is self referential it can be ignored. + def ready_to_install?(spec, remains) + spec.dependencies.none? do |dep| + next if dep.type == :development || dep.name == spec.name + remains[dep.name] + end + end + + def create_bundle_path + Bundler.mkdir_p(Bundler.bundle_path.to_s) unless Bundler.bundle_path.exist? + rescue Errno::EEXIST + raise PathError, "Could not install to path `#{Bundler.settings[:path]}` " + + "because of an invalid symlink. Remove the symlink so the directory can be created." + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/lazy_specification.rb b/bundler-1.7.2/lib/bundler/lazy_specification.rb new file mode 100644 index 0000000..bdcf2df --- /dev/null +++ b/bundler-1.7.2/lib/bundler/lazy_specification.rb @@ -0,0 +1,83 @@ +require "uri" +require "rubygems/spec_fetcher" +require "bundler/match_platform" + +module Bundler + class LazySpecification + include MatchPlatform + + attr_reader :name, :version, :dependencies, :platform + attr_accessor :source, :source_uri + + def initialize(name, version, platform, source = nil) + @name = name + @version = version + @dependencies = [] + @platform = platform + @source = source + @specification = nil + end + + def full_name + if platform == Gem::Platform::RUBY or platform.nil? then + "#{@name}-#{@version}" + else + "#{@name}-#{@version}-#{platform}" + end + end + + def ==(other) + identifier == other.identifier + end + + def satisfies?(dependency) + @name == dependency.name && dependency.requirement.satisfied_by?(Gem::Version.new(@version)) + end + + def to_lock + if platform == Gem::Platform::RUBY or platform.nil? + out = " #{name} (#{version})\n" + else + out = " #{name} (#{version}-#{platform})\n" + end + + dependencies.sort_by {|d| d.to_s }.each do |dep| + next if dep.type == :development + out << " #{dep.to_lock}\n" + end + + out + end + + def __materialize__ + @specification = source.specs.search(Gem::Dependency.new(name, version)).last + end + + def respond_to?(*args) + super || @specification.respond_to?(*args) + end + + def to_s + @__to_s ||= "#{name} (#{version})" + end + + def identifier + @__identifier ||= [name, version, source, platform, dependencies].hash + end + + private + + def to_ary + nil + end + + def method_missing(method, *args, &blk) + raise "LazySpecification has not been materialized yet (calling :#{method} #{args.inspect})" unless @specification + + return super unless respond_to?(method) + + @specification.send(method, *args, &blk) + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/lockfile_parser.rb b/bundler-1.7.2/lib/bundler/lockfile_parser.rb new file mode 100644 index 0000000..32eb43a --- /dev/null +++ b/bundler-1.7.2/lib/bundler/lockfile_parser.rb @@ -0,0 +1,157 @@ +require "strscan" + +# Some versions of the Bundler 1.1 RC series introduced corrupted +# lockfiles. There were two major problems: +# +# * multiple copies of the same GIT section appeared in the lockfile +# * when this happened, those sections got multiple copies of gems +# in those sections. +# +# As a result, Bundler 1.1 contains code that fixes the earlier +# corruption. We will remove this fix-up code in Bundler 1.2. + +module Bundler + class LockfileParser + attr_reader :sources, :dependencies, :specs, :platforms + + DEPENDENCIES = "DEPENDENCIES" + PLATFORMS = "PLATFORMS" + GIT = "GIT" + GEM = "GEM" + PATH = "PATH" + SPECS = " specs:" + OPTIONS = /^ ([a-z]+): (.*)$/i + + def initialize(lockfile) + @platforms = [] + @sources = [] + @dependencies = [] + @state = :source + @specs = {} + + @rubygems_aggregate = Source::Rubygems.new + + if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/) + raise LockfileError, "Your Gemfile.lock contains merge conflicts.\n" \ + "Run `git checkout HEAD -- Gemfile.lock` first to get a clean lock." + end + + lockfile.split(/(?:\r?\n)+/).each do |line| + if line == DEPENDENCIES + @state = :dependency + elsif line == PLATFORMS + @state = :platform + else + send("parse_#{@state}", line) + end + end + @sources << @rubygems_aggregate + @specs = @specs.values + end + + private + + TYPES = { + "GIT" => Bundler::Source::Git, + "GEM" => Bundler::Source::Rubygems, + "PATH" => Bundler::Source::Path + } + + def parse_source(line) + case line + when GIT, GEM, PATH + @current_source = nil + @opts, @type = {}, line + when SPECS + case @type + when "PATH" + @current_source = TYPES[@type].from_lock(@opts) + @sources << @current_source + when "GIT" + @current_source = TYPES[@type].from_lock(@opts) + # Strip out duplicate GIT sections + if @type == "GIT" && @sources.include?(@current_source) + @current_source = @sources.find { |s| s == @current_source } + else + @sources << @current_source + end + when "GEM" + Array(@opts["remote"]).each do |url| + @rubygems_aggregate.add_remote(url) + end + @current_source = @rubygems_aggregate + end + when OPTIONS + value = $2 + value = true if value == "true" + value = false if value == "false" + + key = $1 + + if @opts[key] + @opts[key] = Array(@opts[key]) + @opts[key] << value + else + @opts[key] = value + end + else + parse_spec(line) + end + end + + NAME_VERSION = '(?! )(.*?)(?: \(([^-]*)(?:-(.*))?\))?' + NAME_VERSION_2 = %r{^ {2}#{NAME_VERSION}(!)?$} + NAME_VERSION_4 = %r{^ {4}#{NAME_VERSION}$} + NAME_VERSION_6 = %r{^ {6}#{NAME_VERSION}$} + + def parse_dependency(line) + if line =~ NAME_VERSION_2 + name, version, pinned = $1, $2, $4 + version = version.split(",").map { |d| d.strip } if version + + dep = Bundler::Dependency.new(name, version) + + if pinned && dep.name != 'bundler' + spec = @specs.find {|k, v| v.name == dep.name } + dep.source = spec.last.source if spec + + # Path sources need to know what the default name / version + # to use in the case that there are no gemspecs present. A fake + # gemspec is created based on the version set on the dependency + # TODO: Use the version from the spec instead of from the dependency + if version && version.size == 1 && version.first =~ /^\s*= (.+)\s*$/ && dep.source.is_a?(Bundler::Source::Path) + dep.source.name = name + dep.source.version = $1 + end + end + + @dependencies << dep + end + end + + def parse_spec(line) + if line =~ NAME_VERSION_4 + name, version = $1, Gem::Version.new($2) + platform = $3 ? Gem::Platform.new($3) : Gem::Platform::RUBY + @current_spec = LazySpecification.new(name, version, platform) + @current_spec.source = @current_source + + # Avoid introducing multiple copies of the same spec (caused by + # duplicate GIT sections) + @specs[@current_spec.identifier] ||= @current_spec + elsif line =~ NAME_VERSION_6 + name, version = $1, $2 + version = version.split(',').map { |d| d.strip } if version + dep = Gem::Dependency.new(name, version) + @current_spec.dependencies << dep + end + end + + def parse_platform(line) + if line =~ /^ (.*)$/ + @platforms << Gem::Platform.new($1) + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/match_platform.rb b/bundler-1.7.2/lib/bundler/match_platform.rb new file mode 100644 index 0000000..523dafb --- /dev/null +++ b/bundler-1.7.2/lib/bundler/match_platform.rb @@ -0,0 +1,13 @@ +require 'bundler/gem_helpers' + +module Bundler + module MatchPlatform + include GemHelpers + + def match_platform(p) + Gem::Platform::RUBY == platform or + platform.nil? or p == platform or + generic(Gem::Platform.new(platform)) == p + end + end +end diff --git a/bundler-1.7.2/lib/bundler/parallel_workers.rb b/bundler-1.7.2/lib/bundler/parallel_workers.rb new file mode 100644 index 0000000..b28f630 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/parallel_workers.rb @@ -0,0 +1,18 @@ +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/bundler-1.7.2/lib/bundler/parallel_workers/thread_worker.rb b/bundler-1.7.2/lib/bundler/parallel_workers/thread_worker.rb new file mode 100644 index 0000000..ef2c9ec --- /dev/null +++ b/bundler-1.7.2/lib/bundler/parallel_workers/thread_worker.rb @@ -0,0 +1,30 @@ +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/bundler-1.7.2/lib/bundler/parallel_workers/unix_worker.rb b/bundler-1.7.2/lib/bundler/parallel_workers/unix_worker.rb new file mode 100644 index 0000000..94a07bf --- /dev/null +++ b/bundler-1.7.2/lib/bundler/parallel_workers/unix_worker.rb @@ -0,0 +1,101 @@ +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/bundler-1.7.2/lib/bundler/parallel_workers/worker.rb b/bundler-1.7.2/lib/bundler/parallel_workers/worker.rb new file mode 100644 index 0000000..0e101d1 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/parallel_workers/worker.rb @@ -0,0 +1,69 @@ +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/bundler-1.7.2/lib/bundler/psyched_yaml.rb b/bundler-1.7.2/lib/bundler/psyched_yaml.rb new file mode 100644 index 0000000..7ce3bb9 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/psyched_yaml.rb @@ -0,0 +1,26 @@ +# Psych could be a gem, so try to ask for it +begin + gem 'psych' +rescue LoadError +end if defined?(gem) + +# Psych could just be in the stdlib +# but it's too late if Syck is already loaded +begin + require 'psych' unless defined?(Syck) +rescue LoadError + # Apparently Psych wasn't available. Oh well. +end + +# At least load the YAML stdlib, whatever that may be +require 'yaml' unless defined?(YAML.dump) + +module Bundler + # On encountering invalid YAML, + # Psych raises Psych::SyntaxError + if defined?(::Psych::SyntaxError) + YamlSyntaxError = ::Psych::SyntaxError + else # Syck raises ArgumentError + YamlSyntaxError = ::ArgumentError + end +end diff --git a/bundler-1.7.2/lib/bundler/remote_specification.rb b/bundler-1.7.2/lib/bundler/remote_specification.rb new file mode 100644 index 0000000..d08bd9d --- /dev/null +++ b/bundler-1.7.2/lib/bundler/remote_specification.rb @@ -0,0 +1,57 @@ +require "uri" +require "rubygems/spec_fetcher" + +module Bundler + # Represents a lazily loaded gem specification, where the full specification + # is on the source server in rubygems' "quick" index. The proxy object is to + # be seeded with what we're given from the source's abbreviated index - the + # full specification will only be fetched when necessary. + class RemoteSpecification + include MatchPlatform + + attr_reader :name, :version, :platform + attr_accessor :source, :source_uri + + def initialize(name, version, platform, spec_fetcher) + @name = name + @version = version + @platform = platform + @spec_fetcher = spec_fetcher + end + + # Needed before installs, since the arch matters then and quick + # specs don't bother to include the arch in the platform string + def fetch_platform + @platform = _remote_specification.platform + end + + def full_name + if platform == Gem::Platform::RUBY or platform.nil? then + "#{@name}-#{@version}" + else + "#{@name}-#{@version}-#{platform}" + end + end + + # Because Rubyforge cannot be trusted to provide valid specifications + # once the remote gem is downloaded, the backend specification will + # be swapped out. + def __swap__(spec) + @specification = spec + end + + private + + def _remote_specification + @specification ||= @spec_fetcher.fetch_spec([@name, @version, @platform]) + end + + def method_missing(method, *args, &blk) + if Gem::Specification.new.respond_to?(method) + _remote_specification.send(method, *args, &blk) + else + super + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/resolver.rb b/bundler-1.7.2/lib/bundler/resolver.rb new file mode 100644 index 0000000..7c4a104 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/resolver.rb @@ -0,0 +1,534 @@ +require 'set' +# This is the latest iteration of the gem dependency resolving algorithm. As of now, +# it can resolve (as a success or failure) any set of gem dependencies we throw at it +# in a reasonable amount of time. The most iterations I've seen it take is about 150. +# The actual implementation of the algorithm is not as good as it could be yet, but that +# can come later. + +# Extending Gem classes to add necessary tracking information +module Gem + class Specification + def required_by + @required_by ||= [] + end + end + class Dependency + def required_by + @required_by ||= [] + end + end +end + +module Bundler + class Resolver + + ALL = Bundler::Dependency::PLATFORM_MAP.values.uniq.freeze + + class SpecGroup < Array + include GemHelpers + + attr_reader :activated, :required_by + + def initialize(a) + super + @required_by = [] + @activated = [] + @dependencies = nil + @specs = {} + + ALL.each do |p| + @specs[p] = reverse.find { |s| s.match_platform(p) } + end + end + + def initialize_copy(o) + super + @required_by = o.required_by.dup + @activated = o.activated.dup + end + + def to_specs + specs = {} + + @activated.each do |p| + if s = @specs[p] + platform = generic(Gem::Platform.new(s.platform)) + next if specs[platform] + + lazy_spec = LazySpecification.new(name, version, platform, source) + lazy_spec.dependencies.replace s.dependencies + specs[platform] = lazy_spec + end + end + specs.values + end + + def activate_platform(platform) + unless @activated.include?(platform) + @activated << platform + return __dependencies[platform] || [] + end + [] + end + + def name + @name ||= first.name + end + + def version + @version ||= first.version + end + + def source + @source ||= first.source + end + + def for?(platform) + @specs[platform] + end + + def to_s + "#{name} (#{version})" + end + + private + + def __dependencies + @dependencies ||= begin + dependencies = {} + ALL.each do |p| + if spec = @specs[p] + dependencies[p] = [] + spec.dependencies.each do |dep| + next if dep.type == :development + dependencies[p] << DepProxy.new(dep, p) + end + end + end + dependencies + end + end + end + + attr_reader :errors, :started_at, :iteration_rate, :iteration_counter + + # Figures out the best possible configuration of gems that satisfies + # the list of passed dependencies and any child dependencies without + # causing any gem activation errors. + # + # ==== Parameters + # *dependencies:: The list of dependencies to resolve + # + # ==== Returns + # ,nil:: If the list of dependencies can be resolved, a + # collection of gemspecs is returned. Otherwise, nil is returned. + def self.resolve(requirements, index, source_requirements = {}, base = []) + Bundler.ui.info "Resolving dependencies...", false + base = SpecSet.new(base) unless base.is_a?(SpecSet) + resolver = new(index, source_requirements, base) + result = resolver.start(requirements) + Bundler.ui.info "" # new line now that dots are done + SpecSet.new(result) + rescue => e + Bundler.ui.info "" # new line before the error + raise e + end + + def initialize(index, source_requirements, base) + @errors = {} + @base = base + @index = index + @deps_for = {} + @missing_gems = Hash.new(0) + @source_requirements = source_requirements + @iteration_counter = 0 + @started_at = Time.now + end + + def debug + if ENV['DEBUG_RESOLVER'] + debug_info = yield + debug_info = debug_info.inspect unless debug_info.is_a?(String) + $stderr.puts debug_info + end + end + + def successify(activated) + activated.values.map { |s| s.to_specs }.flatten.compact + end + + def start(reqs) + activated = {} + @gems_size = Hash[reqs.map { |r| [r, gems_size(r)] }] + + resolve(reqs, activated) + end + + class State < Struct.new(:reqs, :activated, :requirement, :possibles, :depth, :conflicts) + def name + requirement.name + end + end + + def handle_conflict(current, states, existing=nil) + until current.nil? && existing.nil? + current_state = find_state(current, states) + existing_state = find_state(existing, states) + return current if state_any?(current_state) + return existing if state_any?(existing_state) + existing = existing.required_by.last if existing + current = current.required_by.last if current + end + end + + def state_any?(state) + state && state.possibles.any? + end + + def find_state(current, states) + states.detect { |i| current && current.name == i.name } + end + + def other_possible?(conflict, states) + return unless conflict + state = states.detect { |i| i.name == conflict.name } + state && state.possibles.any? + end + + def find_conflict_state(conflict, states) + return unless conflict + until states.empty? do + state = states.pop + return state if conflict.name == state.name + end + end + + def activate_gem(reqs, activated, requirement, current) + requirement.required_by.replace current.required_by + requirement.required_by << current + activated[requirement.name] = requirement + + debug { " Activating: #{requirement.name} (#{requirement.version})" } + debug { requirement.required_by.map { |d| " * #{d.name} (#{d.requirement})" }.join("\n") } + + dependencies = requirement.activate_platform(current.__platform) + + debug { " Dependencies"} + dependencies.each do |dep| + next if dep.type == :development + dep.required_by.replace(current.required_by) + dep.required_by << current + @gems_size[dep] ||= gems_size(dep) + reqs << dep + end + end + + def resolve_for_conflict(state) + raise version_conflict if state.nil? || state.possibles.empty? + reqs, activated, depth, conflicts = state.reqs.dup, state.activated.dup, state.depth, state.conflicts.dup + requirement = state.requirement + possible = state.possibles.pop + + activate_gem(reqs, activated, possible, requirement) + + return reqs, activated, depth, conflicts + end + + def resolve_conflict(current, states) + # Find the state where the conflict has occurred + state = find_conflict_state(current, states) + + debug { " -> Going to: #{current.name} state" } if current + + # Resolve the conflicts by rewinding the state + # when the conflicted gem was activated + reqs, activated, depth, conflicts = resolve_for_conflict(state) + + # Keep the state around if it still has other possibilities + states << state unless state.possibles.empty? + clear_search_cache + + return reqs, activated, depth, conflicts + end + + def resolve(reqs, activated) + states = [] + depth = 0 + conflicts = Set.new + + until reqs.empty? + + indicate_progress + + debug { print "\e[2J\e[f" ; "==== Iterating ====\n\n" } + + reqs = reqs.sort_by do |a| + [ activated[a.name] ? 0 : 1, + a.requirement.prerelease? ? 0 : 1, + @errors[a.name] ? 0 : 1, + activated[a.name] ? 0 : @gems_size[a] ] + end + + debug { "Activated:\n" + activated.values.map {|a| " #{a}" }.join("\n") } + debug { "Requirements:\n" + reqs.map {|r| " #{r}"}.join("\n") } + + current = reqs.shift + + $stderr.puts "#{' ' * depth}#{current}" if ENV['DEBUG_RESOLVER_TREE'] + + debug { "Attempting:\n #{current}"} + + existing = activated[current.name] + + + if existing || current.name == 'bundler' + # Force the current + if current.name == 'bundler' && !existing + existing = search(DepProxy.new(Gem::Dependency.new('bundler', VERSION), Gem::Platform::RUBY)).first + raise GemNotFound, %Q{Bundler could not find gem "bundler" (#{VERSION})} unless existing + existing.required_by << existing + activated['bundler'] = existing + end + + if current.requirement.satisfied_by?(existing.version) + debug { " * [SUCCESS] Already activated" } + @errors.delete(existing.name) + dependencies = existing.activate_platform(current.__platform) + reqs.concat dependencies + + dependencies.each do |dep| + next if dep.type == :development + @gems_size[dep] ||= gems_size(dep) + end + + depth += 1 + next + else + debug { " * [FAIL] Already activated" } + @errors[existing.name] = [existing, current] + + conflicts << current.name + + parent = current.required_by.last + if existing.respond_to?(:required_by) + parent = handle_conflict(current, states, existing.required_by[-2]) unless other_possible?(parent, states) + else + parent = handle_conflict(current, states) unless other_possible?(parent, states) + end + + if parent.nil? && !conflicts.empty? + parent = states.reverse.detect { |i| conflicts.include?(i.name) && state_any?(i)} + end + + raise version_conflict if parent.nil? || parent.name == 'bundler' + + reqs, activated, depth, conflicts = resolve_conflict(parent, states) + end + else + matching_versions = search(current) + + # If we found no versions that match the current requirement + if matching_versions.empty? + # If this is a top-level Gemfile requirement + if current.required_by.empty? + if base = @base[current.name] and !base.empty? + version = base.first.version + message = "You have requested:\n" \ + " #{current.name} #{current.requirement}\n\n" \ + "The bundle currently has #{current.name} locked at #{version}.\n" \ + "Try running `bundle update #{current.name}`" + elsif current.source + name = current.name + versions = @source_requirements[name][name].map { |s| s.version } + message = "Could not find gem '#{current}' in #{current.source}.\n" + if versions.any? + message << "Source contains '#{name}' at: #{versions.join(', ')}" + else + message << "Source does not contain any versions of '#{current}'" + end + else + message = "Could not find gem '#{current}' " + if @index.source_types.include?(Bundler::Source::Rubygems) + message << "in any of the gem sources listed in your Gemfile." + else + message << "in the gems available on this machine." + end + end + raise GemNotFound, message + # This is not a top-level Gemfile requirement + else + @errors[current.name] = [nil, current] + parent = handle_conflict(current, states) + reqs, activated, depth = resolve_conflict(parent, states) + next + end + end + + state = State.new(reqs.dup, activated.dup, current, matching_versions, depth, conflicts) + states << state + requirement = state.possibles.pop + activate_gem(reqs, activated, requirement, current) + end + end + successify(activated) + end + + def gems_size(dep) + search(dep).size + end + + def clear_search_cache + @deps_for = {} + end + + def search(dep) + if base = @base[dep.name] and base.any? + reqs = [dep.requirement.as_list, base.first.version.to_s].flatten.compact + d = Gem::Dependency.new(base.first.name, *reqs) + else + d = dep.dep + end + + @deps_for[d.hash] ||= begin + index = @source_requirements[d.name] || @index + results = index.search(d, @base[d.name]) + + if results.any? + version = results.first.version + nested = [[]] + results.each do |spec| + if spec.version != version + nested << [] + version = spec.version + end + nested.last << spec + end + deps = nested.map{|a| SpecGroup.new(a) }.select{|sg| sg.for?(dep.__platform) } + else + deps = [] + end + end + end + + def clean_req(req) + if req.to_s.include?(">= 0") + req.to_s.gsub(/ \(.*?\)$/, '') + else + req.to_s.gsub(/\, (runtime|development)\)$/, ')') + end + end + + def version_conflict + VersionConflict.new(errors.keys, error_message) + end + + # For a given conflicted requirement, print out what exactly went wrong + def gem_message(requirement, required_by=[]) + m = "" + + # A requirement that is required by itself is actually in the Gemfile, and does + # not "depend on" itself + if requirement.required_by.first && requirement.required_by.first.name != requirement.name + dependency_tree(m, required_by) + m << "#{clean_req(requirement)}\n" + else + m << " #{clean_req(requirement)}\n" + end + m << "\n" + end + + def dependency_tree(m, requirements) + requirements.each_with_index do |i, j| + m << " " << (" " * j) + m << "#{clean_req(i)}" + m << " depends on\n" + end + m << " " << (" " * requirements.size) + end + + def error_message + errors.inject("") do |o, (conflict, (origin, requirement))| + + # origin is the SpecSet of specs from the Gemfile that is conflicted with + if origin + + o << %{Bundler could not find compatible versions for gem "#{origin.name}":\n} + o << " In Gemfile:\n" + + required_by = requirement.required_by + o << gem_message(requirement, required_by) + + # If the origin is "bundler", the conflict is us + if origin.name == "bundler" + o << " Current Bundler version:\n" + other_bundler_required = !requirement.requirement.satisfied_by?(origin.version) + # If the origin is a LockfileParser, it does not respond_to :required_by + elsif !origin.respond_to?(:required_by) || !(origin.required_by.first) + o << " In snapshot (Gemfile.lock):\n" + end + + required_by = origin.required_by[0..-2] + o << gem_message(origin, required_by) + + # If the bundle wants a newer bundler than the running bundler, explain + if origin.name == "bundler" && other_bundler_required + o << "This Gemfile requires a different version of Bundler.\n" + o << "Perhaps you need to update Bundler by running `gem install bundler`?" + end + + # origin is nil if the required gem and version cannot be found in any of + # the specified sources + else + + # if the gem cannot be found because of a version conflict between lockfile and gemfile, + # print a useful error that suggests running `bundle update`, which may fix things + # + # @base is a SpecSet of the gems in the lockfile + # conflict is the name of the gem that could not be found + if locked = @base[conflict].first + o << "Bundler could not find compatible versions for gem #{conflict.inspect}:\n" + o << " In snapshot (Gemfile.lock):\n" + o << " #{clean_req(locked)}\n\n" + + o << " In Gemfile:\n" + + required_by = requirement.required_by + o << gem_message(requirement, required_by) + o << "Running `bundle update` will rebuild your snapshot from scratch, using only\n" + o << "the gems in your Gemfile, which may resolve the conflict.\n" + + # the rest of the time, the gem cannot be found because it does not exist in the known sources + else + if requirement.required_by.first + o << "Could not find gem '#{clean_req(requirement)}', which is required by " + o << "gem '#{clean_req(requirement.required_by.first)}', in any of the sources." + else + o << "Could not find gem '#{clean_req(requirement)} in any of the sources\n" + end + end + + end + o + end + end + + private + + # Indicates progress by writing a '.' every iteration_rate time which is + # approximately every second. iteration_rate is calculated in the first + # second of resolve running. + def indicate_progress + @iteration_counter += 1 + + if iteration_rate.nil? + if ((Time.now - started_at) % 3600).round >= 1 + @iteration_rate = iteration_counter + end + else + if ((iteration_counter % iteration_rate) == 0) + Bundler.ui.info ".", false + end + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/retry.rb b/bundler-1.7.2/lib/bundler/retry.rb new file mode 100644 index 0000000..ea4d757 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/retry.rb @@ -0,0 +1,60 @@ +module Bundler + # General purpose class for retrying code that may fail + class Retry + DEFAULT_ATTEMPTS = 2 + attr_accessor :name, :total_runs, :current_run + + class << self + attr_accessor :attempts + end + + def initialize(name, exceptions = nil, attempts = nil) + @name = name + attempts ||= default_attempts + @exceptions = Array(exceptions) || [] + @total_runs = attempts.next # will run once, then upto attempts.times + end + + def default_attempts + return Integer(self.class.attempts) if self.class.attempts + DEFAULT_ATTEMPTS + end + + def attempt(&block) + @current_run = 0 + @failed = false + @error = nil + while keep_trying? do + run(&block) + end + @result + end + alias :attempts :attempt + + private + def run(&block) + @failed = false + @current_run += 1 + @result = block.call + rescue => e + fail(e) + end + + def fail(e) + @failed = true + raise e if last_attempt? || @exceptions.any?{ |k| e.is_a?(k) } + return true unless name + Bundler.ui.warn "Retrying#{" #{name}" if name} due to error (#{current_run.next}/#{total_runs}): #{e.class} #{e.message}" + end + + def keep_trying? + return true if current_run.zero? + return false if last_attempt? + return true if @failed + end + + def last_attempt? + current_run >= total_runs + end + end +end diff --git a/bundler-1.7.2/lib/bundler/ruby_dsl.rb b/bundler-1.7.2/lib/bundler/ruby_dsl.rb new file mode 100644 index 0000000..b29fc01 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/ruby_dsl.rb @@ -0,0 +1,11 @@ +module Bundler + module RubyDsl + def ruby(ruby_version, options = {}) + raise GemfileError, "Please define :engine_version" if options[:engine] && options[:engine_version].nil? + raise GemfileError, "Please define :engine" if options[:engine_version] && options[:engine].nil? + + raise GemfileError, "ruby_version must match the :engine_version for MRI" if options[:engine] == "ruby" && options[:engine_version] && ruby_version != options[:engine_version] + @ruby_version = RubyVersion.new(ruby_version, options[:patchlevel], options[:engine], options[:engine_version]) + end + end +end diff --git a/bundler-1.7.2/lib/bundler/ruby_version.rb b/bundler-1.7.2/lib/bundler/ruby_version.rb new file mode 100644 index 0000000..862dd35 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/ruby_version.rb @@ -0,0 +1,117 @@ +module Bundler + class RubyVersion + attr_reader :version, :patchlevel, :engine, :engine_version + + def initialize(version, patchlevel, engine, engine_version) + # The parameters to this method must satisfy the + # following constraints, which are verified in + # the DSL: + # + # * If an engine is specified, an engine version + # must also be specified + # * If an engine version is specified, an engine + # must also be specified + # * If the engine is "ruby", the engine version + # must not be specified, or the engine version + # specified must match the version. + + @version = version + @engine = engine || "ruby" + # keep track of the engine specified by the user + @input_engine = engine + @engine_version = engine_version || version + @patchlevel = patchlevel + end + + def to_s + output = "ruby #{version}" + output << "p#{patchlevel}" if patchlevel + output << " (#{engine} #{engine_version})" unless engine == "ruby" + + output + end + + def ==(other) + version == other.version && + engine == other.engine && + engine_version == other.engine_version && + patchlevel == other.patchlevel + end + + # Returns a tuple of thsee things: + # [diff, this, other] + # The priority of attributes are + # 1. engine + # 2. ruby_version + # 3. engine_version + def diff(other) + if engine != other.engine && @input_engine + [ :engine, engine, other.engine ] + elsif version != other.version + [ :version, version, other.version ] + elsif engine_version != other.engine_version && @input_engine + [ :engine_version, engine_version, other.engine_version ] + elsif patchlevel != other.patchlevel && @patchlevel + [ :patchlevel, patchlevel, other.patchlevel ] + else + nil + end + end + + def host + @host ||= [ + RbConfig::CONFIG["host_cpu"], + RbConfig::CONFIG["host_vendor"], + RbConfig::CONFIG["host_os"] + ].join("-") + end + end + + # A subclass of RubyVersion that implements version, + # engine and engine_version based upon the current + # information in the system. It can be used anywhere + # a RubyVersion object is expected, and can be + # compared with a RubyVersion object. + class SystemRubyVersion < RubyVersion + def initialize(*) + # override the default initialize, because + # we will implement version, engine and + # engine_version dynamically + end + + def version + RUBY_VERSION.dup + end + + def gem_version + @gem_version ||= Gem::Version.new(version) + end + + def engine + if defined?(RUBY_ENGINE) + RUBY_ENGINE.dup + else + # not defined in ruby 1.8.7 + "ruby" + end + end + + def engine_version + case engine + when "ruby" + RUBY_VERSION.dup + when "rbx" + Rubinius::VERSION.dup + when "jruby" + JRUBY_VERSION.dup + else + raise BundlerError, "RUBY_ENGINE value #{RUBY_ENGINE} is not recognized" + nil + end + end + + def patchlevel + RUBY_PATCHLEVEL.to_s + end + end +end diff --git a/bundler-1.7.2/lib/bundler/rubygems_ext.rb b/bundler-1.7.2/lib/bundler/rubygems_ext.rb new file mode 100644 index 0000000..dccb6fb --- /dev/null +++ b/bundler-1.7.2/lib/bundler/rubygems_ext.rb @@ -0,0 +1,167 @@ +require 'pathname' + +if defined?(Gem::QuickLoader) + # Gem Prelude makes me a sad panda :'( + Gem::QuickLoader.load_full_rubygems_library +end + +require 'rubygems' +require 'rubygems/specification' +require 'bundler/match_platform' + +module Gem + @loaded_stacks = Hash.new { |h,k| h[k] = [] } + + class Specification + attr_accessor :source_uri, :location, :relative_loaded_from + + remove_method :source if instance_methods(false).include?(:source) + attr_accessor :source + + alias_method :rg_full_gem_path, :full_gem_path + alias_method :rg_loaded_from, :loaded_from + + def full_gem_path + source.respond_to?(:path) ? + Pathname.new(loaded_from).dirname.expand_path(Bundler.root).to_s : + rg_full_gem_path + end + + def loaded_from + relative_loaded_from ? + source.path.join(relative_loaded_from).to_s : + rg_loaded_from + end + + def load_paths + return full_require_paths if respond_to?(:full_require_paths) + + require_paths.map do |require_path| + if require_path.include?(full_gem_path) + require_path + else + File.join(full_gem_path, require_path) + end + end + end + + if method_defined?(:extension_dir) + alias_method :rg_extension_dir, :extension_dir + def extension_dir + @extension_dir ||= source.respond_to?(:extension_dir_name) ? + File.expand_path(File.join(extensions_dir, source.extension_dir_name)) : + rg_extension_dir + end + end + + # RubyGems 1.8+ used only. + remove_method :gem_dir if instance_methods(false).include?(:gem_dir) + def gem_dir + full_gem_path + end + + def groups + @groups ||= [] + end + + def git_version + return unless loaded_from && source.is_a?(Bundler::Source::Git) + " #{source.revision[0..6]}" + end + + def to_gemfile(path = nil) + gemfile = "source :gemcutter\n" + gemfile << dependencies_to_gemfile(nondevelopment_dependencies) + unless development_dependencies.empty? + gemfile << "\n" + gemfile << dependencies_to_gemfile(development_dependencies, :development) + end + gemfile + end + + def nondevelopment_dependencies + dependencies - development_dependencies + end + + private + + def dependencies_to_gemfile(dependencies, group = nil) + gemfile = '' + if dependencies.any? + gemfile << "group :#{group} do\n" if group + dependencies.each do |dependency| + gemfile << ' ' if group + gemfile << %|gem "#{dependency.name}"| + req = dependency.requirements_list.first + gemfile << %|, "#{req}"| if req + gemfile << "\n" + end + gemfile << "end\n" if group + end + gemfile + end + + end + + class Dependency + attr_accessor :source, :groups + + alias eql? == + + def encode_with(coder) + to_yaml_properties.each do |ivar| + coder[ivar.to_s.sub(/^@/, '')] = instance_variable_get(ivar) + end + end + + def to_yaml_properties + instance_variables.reject { |p| ["@source", "@groups"].include?(p.to_s) } + end + + def to_lock + out = " #{name}" + unless requirement == Gem::Requirement.default + reqs = requirement.requirements.map{|o,v| "#{o} #{v}" }.sort.reverse + out << " (#{reqs.join(', ')})" + end + out + end + + # Backport of performance enhancement added to Rubygems 1.4 + def matches_spec?(spec) + # name can be a Regexp, so use === + return false unless name === spec.name + return true if requirement.none? + + requirement.satisfied_by?(spec.version) + end unless allocate.respond_to?(:matches_spec?) + end + + class Requirement + # Backport of performance enhancement added to Rubygems 1.4 + def none? + @none ||= (to_s == ">= 0") + end unless allocate.respond_to?(:none?) + end + + class Platform + JAVA = Gem::Platform.new('java') unless defined?(JAVA) + MSWIN = Gem::Platform.new('mswin32') unless defined?(MSWIN) + MINGW = Gem::Platform.new('x86-mingw32') unless defined?(MINGW) + X64_MINGW = Gem::Platform.new('x64-mingw32') unless defined?(X64_MINGW) + + undef_method :hash if method_defined? :hash + def hash + @cpu.hash ^ @os.hash ^ @version.hash + end + + undef_method :eql? if method_defined? :eql? + alias eql? == + end +end + +module Gem + class Specification + include ::Bundler::MatchPlatform + end +end diff --git a/bundler-1.7.2/lib/bundler/rubygems_integration.rb b/bundler-1.7.2/lib/bundler/rubygems_integration.rb new file mode 100644 index 0000000..e73c202 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/rubygems_integration.rb @@ -0,0 +1,578 @@ +require 'rubygems' +require 'rubygems/config_file' + +module Bundler + class RubygemsIntegration + + def self.version + @version ||= Gem::Version.new(Gem::VERSION) + end + + def self.provides?(req_str) + Gem::Requirement.new(req_str).satisfied_by?(version) + end + + def version + self.class.version + end + + def provides?(req_str) + self.class.provides?(req_str) + end + + def build_args + Gem::Command.build_args + end + + def build_args=(args) + Gem::Command.build_args = args + end + + def loaded_specs(name) + Gem.loaded_specs[name] + end + + def mark_loaded(spec) + Gem.loaded_specs[spec.name] = spec + end + + def path(obj) + obj.to_s + end + + def platforms + Gem.platforms + end + + def configuration + Gem.configuration + rescue Gem::SystemExitException => e + Bundler.ui.error "#{e.class}: #{e.message}" + Bundler.ui.trace e + raise Gem::SystemExitException + end + + def ruby_engine + Gem.ruby_engine + end + + def read_binary(path) + Gem.read_binary(path) + end + + def inflate(obj) + Gem.inflate(obj) + end + + def sources=(val) + # Gem.configuration creates a new Gem::ConfigFile, which by default will read ~/.gemrc + # If that file exists, its settings (including sources) will overwrite the values we + # are about to set here. In order to avoid that, we force memoizing the config file now. + configuration + + Gem.sources = val + end + + def sources + Gem.sources + end + + def gem_dir + Gem.dir + end + + def gem_bindir + Gem.bindir + end + + def user_home + Gem.user_home + end + + def gem_path + Gem.path + end + + def gem_cache + gem_path.map{|p| File.expand_path("cache", p) } + end + + def spec_cache_dirs + @spec_cache_dirs ||= begin + dirs = gem_path.map {|dir| File.join(dir, 'specifications')} + dirs << Gem.spec_cache_dir if Gem.respond_to?(:spec_cache_dir) # Not in Rubygems 2.0.3 or earlier + dirs.uniq.select {|dir| File.directory? dir} + end + end + + def marshal_spec_dir + Gem::MARSHAL_SPEC_DIR + end + + def config_map + Gem::ConfigMap + end + + def repository_subdirectories + %w[cache doc gems specifications] + end + + def clear_paths + Gem.clear_paths + end + + def bin_path(gem, bin, ver) + Gem.bin_path(gem, bin, ver) + end + + def preserve_paths + # this is a no-op outside of Rubygems 1.8 + yield + end + + def ui=(obj) + Gem::DefaultUserInteraction.ui = obj + end + + def fetch_specs(all, pre, &blk) + specs = Gem::SpecFetcher.new.list(all, pre) + specs.each { yield } if block_given? + specs + end + + def fetch_prerelease_specs + fetch_specs(false, true) + rescue Gem::RemoteFetcher::FetchError + [] # if we can't download them, there aren't any + end + + def fetch_all_remote_specs + # Fetch all specs, minus prerelease specs + spec_list = fetch_specs(true, false) + # Then fetch the prerelease specs + fetch_prerelease_specs.each {|k, v| spec_list[k] += v } + + return spec_list + end + + def with_build_args(args) + old_args = self.build_args + begin + self.build_args = args + yield + ensure + self.build_args = old_args + end + end + + def gem_from_path(path, policy = nil) + require 'rubygems/format' + Gem::Format.from_file_by_path(path, policy) + end + + def spec_from_gem(path, policy = nil) + require 'rubygems/security' + gem_from_path(path, security_policies[policy]).spec + rescue Gem::Package::FormatError + raise GemspecError, "Could not read gem at #{path}. It may be corrupted." + rescue Exception, Gem::Exception, Gem::Security::Exception => e + if e.is_a?(Gem::Security::Exception) || + e.message =~ /unknown trust policy|unsigned gem/i || + e.message =~ /couldn't verify (meta)?data signature/i + raise SecurityError, + "The gem #{File.basename(path, '.gem')} can't be installed because " \ + "the security policy didn't allow it, with the message: #{e.message}" + else + raise e + end + end + + def build(spec, skip_validation = false) + require 'rubygems/builder' + Gem::Builder.new(spec).build + end + + def build_gem(gem_dir, spec) + SharedHelpers.chdir(gem_dir) { build(spec) } + end + + def download_gem(spec, uri, path) + uri = Bundler::Source.mirror_for(uri) + fetcher = Gem::RemoteFetcher.new(configuration[:http_proxy]) + fetcher.download(spec, uri, path) + end + + def security_policy_keys + %w{High Medium Low AlmostNo No}.map { |level| "#{level}Security" } + end + + def security_policies + @security_policies ||= begin + require 'rubygems/security' + Gem::Security::Policies + rescue LoadError, NameError + {} + end + end + + def reverse_rubygems_kernel_mixin + # Disable rubygems' gem activation system + ::Kernel.class_eval do + if private_method_defined?(:gem_original_require) + alias rubygems_require require + alias require gem_original_require + end + + undef gem + end + end + + def replace_gem(specs) + reverse_rubygems_kernel_mixin + + executables = specs.map { |s| s.executables }.flatten + + ::Kernel.send(:define_method, :gem) do |dep, *reqs| + if executables.include? File.basename(caller.first.split(':').first) + return + end + reqs.pop if reqs.last.is_a?(Hash) + + unless dep.respond_to?(:name) && dep.respond_to?(:requirement) + dep = Gem::Dependency.new(dep, reqs) + end + + spec = specs.find { |s| s.name == dep.name } + + if spec.nil? + + e = Gem::LoadError.new "#{dep.name} is not part of the bundle. Add it to Gemfile." + e.name = dep.name + if e.respond_to?(:requirement=) + e.requirement = dep.requirement + else + e.version_requirement = dep.requirement + end + raise e + elsif dep !~ spec + e = Gem::LoadError.new "can't activate #{dep}, already activated #{spec.full_name}. " \ + "Make sure all dependencies are added to Gemfile." + e.name = dep.name + if e.respond_to?(:requirement=) + e.requirement = dep.requirement + else + e.version_requirement = dep.requirement + end + raise e + end + + true + end + end + + def stub_source_index(specs) + Gem::SourceIndex.send(:alias_method, :old_initialize, :initialize) + redefine_method(Gem::SourceIndex, :initialize) do |*args| + @gems = {} + # You're looking at this thinking: Oh! This is how I make those + # rubygems deprecations go away! + # + # You'd be correct BUT using of this method in production code + # must be approved by the rubygems team itself! + # + # This is your warning. If you use this and don't have approval + # we can't protect you. + # + Deprecate.skip_during do + self.spec_dirs = *args + add_specs(*specs) + end + end + end + + # Used to make bin stubs that are not created by bundler work + # under bundler. The new Gem.bin_path only considers gems in + # +specs+ + def replace_bin_path(specs) + gem_class = (class << Gem ; self ; end) + redefine_method(gem_class, :bin_path) do |name, *args| + exec_name = args.first + + if exec_name == 'bundle' + return ENV['BUNDLE_BIN_PATH'] + end + + spec = nil + + if exec_name + spec = specs.find { |s| s.executables.include?(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}" + end + + gem_bin = File.join(spec.full_gem_path, spec.bindir, exec_name) + gem_from_path_bin = File.join(File.dirname(spec.loaded_from), spec.bindir, exec_name) + File.exist?(gem_bin) ? gem_bin : gem_from_path_bin + end + end + + # Because Bundler has a static view of what specs are available, + # we don't #refresh, so stub it out. + def replace_refresh + gem_class = (class << Gem ; self ; end) + redefine_method(gem_class, :refresh) { } + end + + # Replace or hook into Rubygems to provide a bundlerized view + # of the world. + def replace_entrypoints(specs) + replace_gem(specs) + + stub_rubygems(specs) + + replace_bin_path(specs) + replace_refresh + + Gem.clear_paths + end + + # This backports the correct segment generation code from Rubygems 1.4+ + # by monkeypatching it into the method in Rubygems 1.3.6 and 1.3.7. + def backport_segment_generation + redefine_method(Gem::Version, :segments) do + @segments ||= @version.scan(/[0-9]+|[a-z]+/i).map do |s| + /^\d+$/ =~ s ? s.to_i : s + end + end + end + + # This backport fixes the marshaling of @segments. + def backport_yaml_initialize + redefine_method(Gem::Version, :yaml_initialize) do |tag, map| + @version = map['version'] + @segments = nil + @hash = nil + end + end + + # This backports base_dir which replaces installation path + # Rubygems 1.8+ + def backport_base_dir + redefine_method(Gem::Specification, :base_dir) do + return Gem.dir unless loaded_from + File.dirname File.dirname loaded_from + end + end + + def backport_cache_file + redefine_method(Gem::Specification, :cache_dir) do + @cache_dir ||= File.join base_dir, "cache" + end + + redefine_method(Gem::Specification, :cache_file) do + @cache_file ||= File.join cache_dir, "#{full_name}.gem" + end + end + + def backport_spec_file + redefine_method(Gem::Specification, :spec_dir) do + @spec_dir ||= File.join base_dir, "specifications" + end + + redefine_method(Gem::Specification, :spec_file) do + @spec_file ||= File.join spec_dir, "#{full_name}.gemspec" + end + end + + def redefine_method(klass, method, &block) + if klass.instance_methods(false).include?(method) + klass.send(:remove_method, method) + end + klass.send(:define_method, method, &block) + end + + # Rubygems 1.4 through 1.6 + class Legacy < RubygemsIntegration + def initialize + super + backport_base_dir + backport_cache_file + backport_spec_file + backport_yaml_initialize + end + + def stub_rubygems(specs) + # Rubygems versions lower than 1.7 use SourceIndex#from_gems_in + source_index_class = (class << Gem::SourceIndex ; self ; end) + source_index_class.send(:define_method, :from_gems_in) do |*args| + source_index = Gem::SourceIndex.new + source_index.spec_dirs = *args + source_index.add_specs(*specs) + source_index + end + end + + def all_specs + Gem.source_index.gems.values + end + + def find_name(name) + Gem.source_index.find_name(name) + end + end + + # Rubygems versions 1.3.6 and 1.3.7 + class Ancient < Legacy + def initialize + super + backport_segment_generation + end + end + + # Rubygems 1.7 + class Transitional < Legacy + def stub_rubygems(specs) + stub_source_index(specs) + end + end + + # Rubygems 1.8.5-1.8.19 + class Modern < RubygemsIntegration + def stub_rubygems(specs) + Gem::Specification.all = specs + + Gem.post_reset { + Gem::Specification.all = specs + } + + stub_source_index(specs) + end + + def all_specs + Gem::Specification.to_a + end + + def find_name(name) + Gem::Specification.find_all_by_name name + end + end + + # Rubygems 1.8.0 to 1.8.4 + class AlmostModern < Modern + # Rubygems [>= 1.8.0, < 1.8.5] has a bug that changes Gem.dir whenever + # you call Gem::Installer#install with an :install_dir set. We have to + # change it back for our sudo mode to work. + def preserve_paths + old_dir, old_path = gem_dir, gem_path + yield + Gem.use_paths(old_dir, old_path) + end + end + + # Rubygems 1.8.20+ + class MoreModern < Modern + # Rubygems 1.8.20 and adds the skip_validation parameter, so that's + # when we start passing it through. + def build(spec, skip_validation = false) + require 'rubygems/builder' + Gem::Builder.new(spec).build(skip_validation) + end + end + + # Rubygems 2.0 + class Future < RubygemsIntegration + def stub_rubygems(specs) + Gem::Specification.all = specs + + Gem.post_reset do + Gem::Specification.all = specs + end + end + + def all_specs + Gem::Specification.to_a + end + + def find_name(name) + Gem::Specification.find_all_by_name name + end + + def fetch_specs(source, name) + path = source + "#{name}.#{Gem.marshal_version}.gz" + string = Gem::RemoteFetcher.fetcher.fetch_path(path) + Bundler.load_marshal(string) + rescue Gem::RemoteFetcher::FetchError => e + # it's okay for prerelease to fail + raise e unless name == "prerelease_specs" + end + + def fetch_all_remote_specs + # Since SpecFetcher now returns NameTuples, we just fetch directly + # and unmarshal the array ourselves. + hash = {} + + Gem.sources.each do |source| + source = URI.parse(source.to_s) unless source.is_a?(URI) + hash[source] = fetch_specs(source, "specs") + + pres = fetch_specs(source, "prerelease_specs") + hash[source].push(*pres) if pres && !pres.empty? + end + + hash + end + + def download_gem(spec, uri, path) + require 'resolv' + uri = Bundler::Source.mirror_for(uri) + proxy, dns = configuration[:http_proxy], Resolv::DNS.new + fetcher = Gem::RemoteFetcher.new(proxy, dns) + fetcher.download(spec, uri, path) + end + + def gem_from_path(path, policy = nil) + require 'rubygems/package' + p = Gem::Package.new(path) + p.security_policy = policy if policy + return p + end + + def build(spec, skip_validation = false) + require 'rubygems/package' + Gem::Package.build(spec, skip_validation) + end + + def repository_subdirectories + Gem::REPOSITORY_SUBDIRECTORIES + end + end + + end + + if RubygemsIntegration.provides?(">= 1.99.99") + @rubygems = RubygemsIntegration::Future.new + elsif RubygemsIntegration.provides?('>= 1.8.20') + @rubygems = RubygemsIntegration::MoreModern.new + elsif RubygemsIntegration.provides?('>= 1.8.5') + @rubygems = RubygemsIntegration::Modern.new + elsif RubygemsIntegration.provides?('>= 1.8.0') + @rubygems = RubygemsIntegration::AlmostModern.new + elsif RubygemsIntegration.provides?('>= 1.7.0') + @rubygems = RubygemsIntegration::Transitional.new + elsif RubygemsIntegration.provides?('>= 1.4.0') + @rubygems = RubygemsIntegration::Legacy.new + else # Rubygems 1.3.6 and 1.3.7 + @rubygems = RubygemsIntegration::Ancient.new + end + + class << self + attr_reader :rubygems + end +end diff --git a/bundler-1.7.2/lib/bundler/runtime.rb b/bundler-1.7.2/lib/bundler/runtime.rb new file mode 100644 index 0000000..b09a881 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/runtime.rb @@ -0,0 +1,310 @@ +require "digest/sha1" + +module Bundler + class Runtime < Environment + include SharedHelpers + + def setup(*groups) + groups.map! { |g| g.to_sym } + + # Has to happen first + clean_load_path + + specs = groups.any? ? @definition.specs_for(groups) : requested_specs + + setup_environment + Bundler.rubygems.replace_entrypoints(specs) + + # Activate the specs + specs.each do |spec| + unless spec.loaded_from + raise GemNotFound, "#{spec.full_name} is missing. Run `bundle` to get it." + end + + if activated_spec = Bundler.rubygems.loaded_specs(spec.name) and activated_spec.version != spec.version + e = Gem::LoadError.new "You have already activated #{activated_spec.name} #{activated_spec.version}, " \ + "but your Gemfile requires #{spec.name} #{spec.version}. Prepending " \ + "`bundle exec` to your command may solve this." + e.name = spec.name + if e.respond_to?(:requirement=) + e.requirement = Gem::Requirement.new(spec.version.to_s) + else + e.version_requirement = Gem::Requirement.new(spec.version.to_s) + end + raise e + end + + Bundler.rubygems.mark_loaded(spec) + load_paths = spec.load_paths.reject {|path| $LOAD_PATH.include?(path)} + $LOAD_PATH.unshift(*load_paths) + end + + setup_manpath + + lock + + self + end + + REGEXPS = [ + /^no such file to load -- (.+)$/i, + /^Missing \w+ (?:file\s*)?([^\s]+.rb)$/i, + /^Missing API definition file in (.+)$/i, + /^cannot load such file -- (.+)$/i, + /^dlopen\([^)]*\): Library not loaded: (.+)$/i, + ] + + def require(*groups) + groups.map! { |g| g.to_sym } + groups = [:default] if groups.empty? + + @definition.dependencies.each do |dep| + # Skip the dependency if it is not in any of the requested + # groups + next unless ((dep.groups & groups).any? && dep.current_platform?) + + required_file = nil + + begin + # Loop through all the specified autorequires for the + # dependency. If there are none, use the dependency's name + # as the autorequire. + Array(dep.autorequire || dep.name).each do |file| + # Allow `require: true` as an alias for `require: ` + file = dep.name if file == true + required_file = file + Kernel.require file + end + rescue LoadError => e + REGEXPS.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? + end + end + end + end + end + + def dependencies_for(*groups) + if groups.empty? + dependencies + else + dependencies.select { |d| (groups & d.groups).any? } + end + end + + alias gems specs + + def cache(custom_path = nil) + cache_path = cache_path(custom_path) + FileUtils.mkdir_p(cache_path) unless File.exist?(cache_path) + + Bundler.ui.info "Updating files in vendor/cache" + specs.each do |spec| + next if spec.name == 'bundler' + spec.source.cache(spec, custom_path) if spec.source.respond_to?(:cache) + end + + Dir[cache_path.join("*/.git")].each do |git_dir| + FileUtils.rm_rf(git_dir) + FileUtils.touch(File.expand_path("../.bundlecache", git_dir)) + end + + prune_cache(custom_path) unless Bundler.settings[:no_prune] + end + + def prune_cache(custom_path) + cache_path = cache_path(custom_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) + end + + def clean(dry_run = false) + gem_bins = Dir["#{Gem.dir}/bin/*"] + git_dirs = Dir["#{Gem.dir}/bundler/gems/*"] + git_cache_dirs = Dir["#{Gem.dir}/cache/bundler/git/*"] + gem_dirs = Dir["#{Gem.dir}/gems/*"] + gem_files = Dir["#{Gem.dir}/cache/*.gem"] + gemspec_files = Dir["#{Gem.dir}/specifications/*.gemspec"] + spec_gem_paths = [] + # need to keep git sources around + spec_git_paths = @definition.spec_git_paths + spec_git_cache_dirs = [] + spec_gem_executables = [] + spec_cache_paths = [] + spec_gemspec_paths = [] + specs.each do |spec| + spec_gem_paths << spec.full_gem_path + # need to check here in case gems are nested like for the rails git repo + md = %r{(.+bundler/gems/.+-[a-f0-9]{7,12})}.match(spec.full_gem_path) + spec_git_paths << md[1] if md + spec_gem_executables << spec.executables.collect do |executable| + e = "#{Bundler.rubygems.gem_bindir}/#{executable}" + [e, "#{e}.bat"] + end + spec_cache_paths << spec.cache_file + spec_gemspec_paths << spec.spec_file + spec_git_cache_dirs << spec.source.cache_path.to_s if spec.source.is_a?(Bundler::Source::Git) + end + spec_gem_paths.uniq! + spec_gem_executables.flatten! + + stale_gem_bins = gem_bins - spec_gem_executables + stale_git_dirs = git_dirs - spec_git_paths + stale_git_cache_dirs = git_cache_dirs - spec_git_cache_dirs + stale_gem_dirs = gem_dirs - spec_gem_paths + stale_gem_files = gem_files - spec_cache_paths + stale_gemspec_files = gemspec_files - spec_gemspec_paths + + output = stale_gem_dirs.collect do |gem_dir| + full_name = Pathname.new(gem_dir).basename.to_s + + parts = full_name.split('-') + name = parts[0..-2].join('-') + version = parts.last + output = "#{name} (#{version})" + + if dry_run + Bundler.ui.info "Would have removed #{output}" + else + Bundler.ui.info "Removing #{output}" + FileUtils.rm_rf(gem_dir) + end + + output + end + stale_git_dirs.collect do |gem_dir| + full_name = Pathname.new(gem_dir).basename.to_s + + parts = full_name.split('-') + name = parts[0..-2].join('-') + revision = parts[-1] + output = "#{name} (#{revision})" + + if dry_run + Bundler.ui.info "Would have removed #{output}" + else + Bundler.ui.info "Removing #{output}" + FileUtils.rm_rf(gem_dir) + end + + output + end + + unless dry_run + stale_gem_bins.each { |bin| FileUtils.rm(bin) if File.exist?(bin) } + stale_gem_files.each { |file| FileUtils.rm(file) if File.exist?(file) } + stale_gemspec_files.each { |file| FileUtils.rm(file) if File.exist?(file) } + stale_git_cache_dirs.each { |dir| FileUtils.rm_rf(dir) if File.exist?(dir) } + end + + output + end + + def setup_environment + begin + ENV["BUNDLE_BIN_PATH"] = Bundler.rubygems.bin_path("bundler", "bundle", VERSION) + rescue Gem::GemNotFoundException + 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) + end + + private + + def prune_gem_cache(resolve, custom_path) + cached = Dir["#{cache_path(custom_path)}/*.gem"] + + cached = cached.delete_if do |path| + spec = Bundler.rubygems.spec_from_gem path + + resolve.any? do |s| + s.name == spec.name && s.version == spec.version && !s.source.is_a?(Bundler::Source::Git) + end + end + + if cached.any? + Bundler.ui.info "Removing outdated .gem files from vendor/cache" + + cached.each do |path| + Bundler.ui.info " * #{File.basename(path)}" + File.delete(path) + end + end + end + + def prune_git_and_path_cache(resolve, custom_path) + cached = Dir["#{cache_path(custom_path)}/*/.bundlecache"] + + cached = cached.delete_if do |path| + name = File.basename(File.dirname(path)) + + resolve.any? do |s| + source = s.source + source.respond_to?(:app_cache_dirname) && source.app_cache_dirname == name + end + end + + if cached.any? + Bundler.ui.info "Removing outdated git and path gems from vendor/cache" + + cached.each do |path| + path = File.dirname(path) + Bundler.ui.info " * #{File.basename(path)}" + FileUtils.rm_rf(path) + end + end + end + + def setup_manpath + # Store original MANPATH for restoration later in with_clean_env() + ENV['BUNDLE_ORIG_MANPATH'] = ENV['MANPATH'] + + # Add man/ subdirectories from activated bundles to MANPATH for man(1) + manuals = $LOAD_PATH.map do |path| + man_subdir = path.sub(/lib$/, 'man') + man_subdir unless Dir[man_subdir + '/man?/'].empty? + end.compact + + unless manuals.empty? + ENV['MANPATH'] = manuals.concat( + ENV['MANPATH'].to_s.split(File::PATH_SEPARATOR) + ).uniq.join(File::PATH_SEPARATOR) + end + end + + def cache_path(custom_path = nil) + path = custom_path || root + path.join("vendor/cache") + end + end +end diff --git a/bundler-1.7.2/lib/bundler/settings.rb b/bundler-1.7.2/lib/bundler/settings.rb new file mode 100644 index 0000000..ff269c9 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/settings.rb @@ -0,0 +1,176 @@ +module Bundler + class Settings + 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 + end + + def []=(key, value) + local_config_file or raise GemfileNotFound, "Could not locate Gemfile" + set_key(key, value, @local_config, local_config_file) + end + + alias :set_local :[]= + + def delete(key) + @local_config.delete(key_for(key)) + end + + def set_global(key, value) + set_key(key, value, @global_config, global_config_file) + end + + def all + env_keys = ENV.keys.select { |k| k =~ /BUNDLE_.*/ } + + keys = @global_config.keys | @local_config.keys | env_keys + + keys.map do |key| + key.sub(/^BUNDLE_/, '').gsub(/__/, ".").downcase + end + end + + def local_overrides + repos = {} + all.each do |k| + if k =~ /^local\./ + repos[$'] = self[k] + end + end + repos + end + + def gem_mirrors + all.inject({}) do |h, k| + if k =~ /^mirror\./ + uri = normalize_uri($') + h[uri] = normalize_uri(self[k]) + end + h + end + end + + def locations(key) + key = key_for(key) + locations = {} + locations[:local] = @local_config[key] if @local_config.key?(key) + locations[:env] = ENV[key] if ENV[key] + locations[:global] = @global_config[key] if @global_config.key?(key) + locations + end + + def pretty_values_for(exposed_key) + key = key_for(exposed_key) + + locations = [] + if @local_config.key?(key) + locations << "Set for your local app (#{local_config_file}): #{@local_config[key].inspect}" + end + + if value = ENV[key] + locations << "Set via #{key}: #{value.inspect}" + end + + if @global_config.key?(key) + locations << "Set for the current user (#{global_config_file}): #{@global_config[key].inspect}" + end + + return ["You have not configured a value for `#{exposed_key}`"] if locations.empty? + locations + end + + def without=(array) + self[:without] = (array.empty? ? nil : array.join(":")) if array + end + + def without + self[:without] ? self[:without].split(":").map { |w| w.to_sym } : [] + end + + # @local_config["BUNDLE_PATH"] should be prioritized over ENV["BUNDLE_PATH"] + def path + key = key_for(:path) + path = ENV[key] || @global_config[key] + return path if path && !@local_config.key?(key) + + if path = self[:path] + "#{path}/#{Bundler.ruby_scope}" + else + Bundler.rubygems.gem_dir + end + end + + def allow_sudo? + !@local_config.key?(key_for(:path)) + end + + def ignore_config? + ENV['BUNDLE_IGNORE_CONFIG'] + end + + private + def key_for(key) + key = key.to_s.sub(".", "__").upcase + "BUNDLE_#{key}" + end + + def is_bool(key) + %w(frozen cache_all no_prune disable_local_branch_check).include? key.to_s + end + + def to_bool(value) + !(value.nil? || value == '' || value =~ /^(false|f|no|n|0)$/i) + end + + def set_key(key, value, hash, file) + key = key_for(key) + + unless hash[key] == value + hash[key] = value + hash.delete(key) if value.nil? + FileUtils.mkdir_p(file.dirname) + require 'bundler/psyched_yaml' + File.open(file, "w") { |f| f.puts YAML.dump(hash) } + end + value + end + + def global_config_file + file = ENV["BUNDLE_CONFIG"] || File.join(Bundler.rubygems.user_home, ".bundle/config") + Pathname.new(file) + end + + def local_config_file + Pathname.new(@root).join("config") if @root + end + + def load_config(config_file) + valid_file = config_file && config_file.exist? && !config_file.size.zero? + if !ignore_config? && valid_file + config_regex =/^(BUNDLE_.+): (?:['"](.*)['"]|(.+(?:\n(?!BUNDLE).+))|(.+))$/ + config_pairs = config_file.read.scan(config_regex).map{|m| m.compact.map { |n| n.gsub(/\n\s?/, "") } } + Hash[config_pairs] + else + {} + end + end + + # TODO: duplicates Rubygems#normalize_uri + # TODO: is this the correct place to validate mirror URIs? + def normalize_uri(uri) + 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? + uri + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/setup.rb b/bundler-1.7.2/lib/bundler/setup.rb new file mode 100644 index 0000000..3059975 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/setup.rb @@ -0,0 +1,23 @@ +require 'bundler/shared_helpers' + +if Bundler::SharedHelpers.in_bundle? + require 'bundler' + if STDOUT.tty? + begin + Bundler.setup + rescue Bundler::BundlerError => e + puts "\e[31m#{e.message}\e[0m" + puts e.backtrace.join("\n") if ENV["DEBUG"] + if e.is_a?(Bundler::GemNotFound) + puts "\e[33mRun `bundle install` to install missing gems.\e[0m" + end + exit e.status_code + end + else + Bundler.setup + end + + # Add bundler to the load path after disabling system gems + bundler_lib = File.expand_path("../..", __FILE__) + $LOAD_PATH.unshift(bundler_lib) unless $LOAD_PATH.include?(bundler_lib) +end diff --git a/bundler-1.7.2/lib/bundler/shared_helpers.rb b/bundler-1.7.2/lib/bundler/shared_helpers.rb new file mode 100644 index 0000000..7e53518 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/shared_helpers.rb @@ -0,0 +1,110 @@ +require 'pathname' +require 'rubygems' + +require 'bundler/constants' +require 'bundler/rubygems_integration' +require 'bundler/current_ruby' + +module Gem + class Dependency + if !instance_methods.map { |m| m.to_s }.include?("requirement") + def requirement + version_requirements + end + end + end +end + +module Bundler + module SharedHelpers + attr_accessor :gem_loaded + + def default_gemfile + gemfile = find_gemfile + raise GemfileNotFound, "Could not locate Gemfile" unless gemfile + Pathname.new(gemfile) + end + + def default_lockfile + Pathname.new("#{default_gemfile}.lock") + end + + def in_bundle? + find_gemfile + end + + if Bundler.current_ruby.mswin? || Bundler.current_ruby.jruby? + require 'monitor' + @chdir_monitor = Monitor.new + def chdir(dir, &blk) + @chdir_monitor.synchronize do + Dir.chdir dir, &blk + end + end + + def pwd + @chdir_monitor.synchronize do + Dir.pwd + end + end + else + def chdir(dir, &blk) + Dir.chdir dir, &blk + end + + def pwd + Dir.pwd + end + end + + def with_clean_git_env(&block) + keys = %w[GIT_DIR GIT_WORK_TREE] + old_env = keys.inject({}) do |h, k| + h.update(k => ENV[k]) + end + + keys.each {|key| ENV.delete(key) } + + block.call + ensure + keys.each {|key| ENV[key] = old_env[key] } + end + + private + + def find_gemfile + given = ENV['BUNDLE_GEMFILE'] + return given if given && !given.empty? + + previous = nil + current = File.expand_path(SharedHelpers.pwd) + + until !File.directory?(current) || current == previous + if ENV['BUNDLE_SPEC_RUN'] + # avoid stepping above the tmp directory when testing + 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) + current, previous = File.expand_path("..", current), current + end + end + + def clean_load_path + # handle 1.9 where system gems are always on the load path + if defined?(::Gem) + me = File.expand_path("../../", __FILE__) + $LOAD_PATH.reject! do |p| + next if File.expand_path(p) =~ /^#{Regexp.escape(me)}/ + p != File.dirname(__FILE__) && + Bundler.rubygems.gem_path.any?{|gp| p =~ /^#{Regexp.escape(gp)}/ } + end + $LOAD_PATH.uniq! + end + end + + extend self + end +end diff --git a/bundler-1.7.2/lib/bundler/similarity_detector.rb b/bundler-1.7.2/lib/bundler/similarity_detector.rb new file mode 100644 index 0000000..9bb1e8d --- /dev/null +++ b/bundler-1.7.2/lib/bundler/similarity_detector.rb @@ -0,0 +1,63 @@ +module Bundler + class SimilarityDetector + SimilarityScore = Struct.new(:string, :distance) + + # initialize with an array of words to be matched against + def initialize(corpus) + @corpus = corpus + end + + # return an array of words similar to 'word' from the corpus + def similar_words(word, limit=3) + words_by_similarity = @corpus.map{|w| SimilarityScore.new(w, levenshtein_distance(word, w))} + words_by_similarity.select{|s| s.distance<=limit}.sort_by(&:distance).map(&:string) + end + + # return the result of 'similar_words', concatenated into a list + # (eg "a, b, or c") + def similar_word_list(word, limit=3) + words = similar_words(word,limit) + if words.length==1 + words[0] + elsif words.length>1 + [words[0..-2].join(', '), words[-1]].join(' or ') + end + end + + + protected + # http://www.informit.com/articles/article.aspx?p=683059&seqNum=36 + def levenshtein_distance(this, that, ins=2, del=2, sub=1) + # ins, del, sub are weighted costs + return nil if this.nil? + return nil if that.nil? + dm = [] # distance matrix + + # Initialize first row values + dm[0] = (0..this.length).collect { |i| i * ins } + fill = [0] * (this.length - 1) + + # Initialize first column values + for i in 1..that.length + dm[i] = [i * del, fill.flatten] + end + + # populate matrix + for i in 1..that.length + for j in 1..this.length + # critical comparison + dm[i][j] = [ + dm[i-1][j-1] + + (this[j-1] == that[i-1] ? 0 : sub), + dm[i][j-1] + ins, + dm[i-1][j] + del + ].min + end + end + + # The last value in matrix is the Levenshtein distance between the strings + dm[that.length][this.length] + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/source.rb b/bundler-1.7.2/lib/bundler/source.rb new file mode 100644 index 0000000..04643b4 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/source.rb @@ -0,0 +1,37 @@ +module Bundler + class Source + autoload :Rubygems, 'bundler/source/rubygems' + autoload :Path, 'bundler/source/path' + autoload :Git, 'bundler/source/git' + + def self.mirror_for(uri) + uri = URI(uri.to_s) unless uri.is_a?(URI) + + # Settings keys are all downcased + mirrors = Bundler.settings.gem_mirrors + normalized_key = URI(uri.to_s.downcase) + + mirrors[normalized_key] || uri + end + + attr_accessor :dependency_names + + def unmet_deps + specs.unmet_dependency_names + 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})" + end + message + end + + def can_lock?(spec) + spec.source == self + end + end +end diff --git a/bundler-1.7.2/lib/bundler/source/git.rb b/bundler-1.7.2/lib/bundler/source/git.rb new file mode 100644 index 0000000..1f720f5 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/source/git.rb @@ -0,0 +1,290 @@ +require 'fileutils' +require 'uri' +require 'digest/sha1' + +module Bundler + class Source + + class Git < Path + autoload :GitProxy, 'bundler/source/git/git_proxy' + + attr_reader :uri, :ref, :branch, :options, :submodules + + def initialize(options) + @options = options + @glob = options["glob"] || DEFAULT_GLOB + + @allow_cached = false + @allow_remote = false + + # 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"] + @branch = options["branch"] + @ref = options["ref"] || options["branch"] || options["tag"] || 'master' + @submodules = options["submodules"] + @name = options["name"] + @version = options["version"] + + @copied = false + @local = false + end + + def self.from_lock(options) + new(options.merge("uri" => options.delete("remote"))) + end + + def to_lock + out = "GIT\n" + out << " remote: #{@uri}\n" + out << " revision: #{revision}\n" + %w(ref branch tag submodules).each do |opt| + out << " #{opt}: #{options[opt]}\n" if options[opt] + end + out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB + out << " specs:\n" + end + + def eql?(o) + o.is_a?(Git) && + uri == o.uri && + ref == o.ref && + branch == o.branch && + name == o.name && + version == o.version && + submodules == o.submodules + end + + alias == eql? + + def to_s + at = if local? + path + elsif options["ref"] + shortref_for_display(options["ref"]) + else + ref + end + "#{uri} (at #{at})" + end + + def name + File.basename(@uri, '.git') + end + + # This is the path which is going to contain a specific + # checkout of the git repository. When using local git + # repos, this is set to the local repo. + def install_path + @install_path ||= begin + git_scope = "#{base_name}-#{shortref_for_path(revision)}" + path = Bundler.install_path.join(git_scope) + + if !path.exist? && Bundler.requires_sudo? + Bundler.user_bundle_path.join(Bundler.ruby_scope).join(git_scope) + else + path + end + end + end + + alias :path :install_path + + def extension_dir_name + "#{base_name}-#{shortref_for_path(revision)}" + end + + def unlock! + git_proxy.revision = nil + @unlocked = true + end + + def local_override!(path) + return false if local? + + path = Pathname.new(path) + path = path.expand_path(Bundler.root) unless path.relative? + + unless options["branch"] || Bundler.settings[:disable_local_branch_check] + raise GitError, "Cannot use local override for #{name} at #{path} because " \ + ":branch is not specified in Gemfile. Specify a branch or use " \ + "`bundle config --delete` to remove the local override" + end + + unless path.exist? + raise GitError, "Cannot use local override for #{name} because #{path} " \ + "does not exist. Check `bundle config --delete` to remove the local override" + end + + set_local!(path) + + # Create a new git proxy without the cached revision + # so the Gemfile.lock always picks up the new revision. + @git_proxy = GitProxy.new(path, uri, ref) + + if git_proxy.branch != options["branch"] && !Bundler.settings[:disable_local_branch_check] + raise GitError, "Local override for #{name} at #{path} is using branch " \ + "#{git_proxy.branch} but Gemfile specifies #{options["branch"]}" + end + + changed = cached_revision && cached_revision != git_proxy.revision + + if changed && !@unlocked && !git_proxy.contains?(cached_revision) + raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(cached_revision)} " \ + "but the current branch in your local override for #{name} does not contain such commit. " \ + "Please make sure your branch is up to date." + end + + changed + end + + # TODO: actually cache git specs + def specs(*) + if has_app_cache? && !local? + set_local!(app_cache_path) + end + + if requires_checkout? && !@copied + git_proxy.checkout + git_proxy.copy_to(install_path, submodules) + serialize_gemspecs_in(install_path) + @copied = true + end + + local_specs + end + + def install(spec) + debug = nil + if requires_checkout? && !@copied + debug = " * Checking out revision: #{ref}" + git_proxy.copy_to(install_path, submodules) + serialize_gemspecs_in(install_path) + @copied = true + end + generate_bin(spec) + if requires_checkout? && spec.post_install_message + Installer.post_install_messages[spec.name] = spec.post_install_message + end + ["Using #{version_message(spec)} from #{to_s}", nil, debug] + end + + def cache(spec, custom_path = nil) + app_cache_path = app_cache_path(custom_path) + return unless Bundler.settings[:cache_all] + return if path == app_cache_path + cached! + FileUtils.rm_rf(app_cache_path) + git_proxy.checkout if requires_checkout? + git_proxy.copy_to(app_cache_path, @submodules) + serialize_gemspecs_in(app_cache_path) + end + + def load_spec_files + super + rescue PathError => e + Bundler.ui.trace e + raise GitError, "#{to_s} is not yet checked out. Run `bundle install` first." + end + + # This is the path which is going to contain a cache + # of the git repository. When using the same git repository + # across different projects, this cache will be shared. + # When using local git repos, this is set to the local repo. + def cache_path + @cache_path ||= begin + git_scope = "#{base_name}-#{uri_hash}" + + if Bundler.requires_sudo? + Bundler.user_bundle_path.join("cache/git", git_scope) + else + Bundler.cache.join("git", git_scope) + end + end + end + + def app_cache_dirname + "#{base_name}-#{shortref_for_path(cached_revision || revision)}" + end + + def revision + git_proxy.revision + end + + def allow_git_ops? + @allow_remote || @allow_cached + end + + private + + def serialize_gemspecs_in(destination) + expanded_path = destination.expand_path(Bundler.root) + Dir["#{expanded_path}/#{@glob}"].each do |spec_path| + # Evaluate gemspecs and cache the result. Gemspecs + # in git might require git or other dependencies. + # The gemspecs we cache should already be evaluated. + spec = Bundler.load_gemspec(spec_path) + next unless spec + File.open(spec_path, 'wb') {|file| file.write(spec.to_ruby) } + end + end + + def set_local!(path) + @local = true + @local_specs = @git_proxy = nil + @cache_path = @install_path = path + end + + def has_app_cache? + cached_revision && super + end + + def local? + @local + end + + def requires_checkout? + allow_git_ops? && !local? + end + + def base_name + File.basename(uri.sub(%r{^(\w+://)?([^/:]+:)?(//\w*/)?(\w*/)*},''),".git") + end + + def shortref_for_display(ref) + ref[0..6] + end + + def shortref_for_path(ref) + ref[0..11] + end + + def uri_hash + if uri =~ %r{^\w+://(\w+@)?} + # Downcase the domain component of the URI + # and strip off a trailing slash, if one is present + input = URI.parse(uri).normalize.to_s.sub(%r{/$},'') + else + # If there is no URI scheme, assume it is an ssh/git URI + input = uri + end + Digest::SHA1.hexdigest(input) + end + + def cached_revision + options["revision"] + end + + def cached? + cache_path.exist? + end + + def git_proxy + @git_proxy ||= GitProxy.new(cache_path, uri, ref, cached_revision, self) + end + + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/source/git/git_proxy.rb b/bundler-1.7.2/lib/bundler/source/git/git_proxy.rb new file mode 100644 index 0000000..29100a1 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/source/git/git_proxy.rb @@ -0,0 +1,158 @@ +module Bundler + class Source + class Git < Path + + class GitNotInstalledError < GitError + def initialize + msg = "You need to install git to be able to use gems from git repositories. " + msg << "For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git" + super msg + end + end + + class GitNotAllowedError < GitError + def initialize(command) + msg = "Bundler is trying to run a `git #{command}` at runtime. You probably need to run `bundle install`. However, " + msg << "this error message could probably be more useful. Please submit a ticket at http://github.com/bundler/bundler/issues " + msg << "with steps to reproduce as well as the following\n\nCALLER: #{caller.join("\n")}" + super msg + end + end + + class GitCommandError < GitError + def initialize(command, path = nil) + msg = "Git error: command `git #{command}` in directory #{Dir.pwd} has failed." + msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path && path.exist? + super msg + end + end + + # The GitProxy is responsible to interact with git repositories. + # All actions required by the Git source is encapsulated in this + # object. + class GitProxy + attr_accessor :path, :uri, :ref + attr_writer :revision + + def initialize(path, uri, ref, revision = nil, git = nil) + @path = path + @uri = uri + @ref = ref + @revision = revision + @git = git + raise GitNotInstalledError.new if allow? && !Bundler.git_present? + end + + def revision + @revision ||= allowed_in_path { git("rev-parse #{ref}").strip } + end + + def branch + @branch ||= allowed_in_path do + git("branch") =~ /^\* (.*)$/ && $1.strip + end + end + + def contains?(commit) + allowed_in_path do + result = git_null("branch --contains #{commit}") + $? == 0 && result =~ /^\* (.*)$/ + end + end + + def checkout + if path.exist? + return if has_revision_cached? + Bundler.ui.confirm "Updating #{uri}" + in_path do + git_retry %|fetch --force --quiet --tags #{uri_escaped} "refs/heads/*:refs/heads/*"| + end + else + Bundler.ui.info "Fetching #{uri}" + FileUtils.mkdir_p(path.dirname) + git_retry %|clone #{uri_escaped} "#{path}" --bare --no-hardlinks --quiet| + end + end + + def copy_to(destination, submodules=false) + unless File.exist?(destination.join(".git")) + FileUtils.mkdir_p(destination.dirname) + FileUtils.rm_rf(destination) + git_retry %|clone --no-checkout --quiet "#{path}" "#{destination}"| + File.chmod((0777 & ~File.umask), destination) + end + + SharedHelpers.chdir(destination) do + git_retry %|fetch --force --quiet --tags "#{path}"| + git "reset --hard #{@revision}" + + if submodules + git_retry "submodule update --init --recursive" + end + end + end + + private + + # TODO: Do not rely on /dev/null. + # Given that open3 is not cross platform until Ruby 1.9.3, + # the best solution is to pipe to /dev/null if it exists. + # If it doesn't, everything will work fine, but the user + # will get the $stderr messages as well. + def git_null(command) + git("#{command} 2>#{Bundler::NULL}", false) + end + + def git_retry(command) + Bundler::Retry.new("git #{command}", GitNotAllowedError).attempts do + git(command) + end + end + + def git(command, check_errors=true) + raise GitNotAllowedError.new(command) unless allow? + out = SharedHelpers.with_clean_git_env { %x{git #{command}} } + raise GitCommandError.new(command, path) if check_errors && !$?.success? + out + end + + def has_revision_cached? + return unless @revision + in_path { git("cat-file -e #{@revision}") } + true + rescue GitError + false + end + + # Escape the URI for git commands + def uri_escaped + if Bundler::WINDOWS + # Windows quoting requires double quotes only, with double quotes + # inside the string escaped by being doubled. + '"' + uri.gsub('"') {|s| '""'} + '"' + else + # Bash requires single quoted strings, with the single quotes escaped + # by ending the string, escaping the quote, and restarting the string. + "'" + uri.gsub("'") {|s| "'\\''"} + "'" + end + end + + def allow? + @git ? @git.allow_git_ops? : true + end + + def in_path(&blk) + checkout unless path.exist? + SharedHelpers.chdir(path, &blk) + end + + def allowed_in_path + return in_path { yield } if allow? + raise GitError, "The git source #{uri} is not yet checked out. Please run `bundle install` before trying to start your application" + end + + end + + end + end +end diff --git a/bundler-1.7.2/lib/bundler/source/path.rb b/bundler-1.7.2/lib/bundler/source/path.rb new file mode 100644 index 0000000..398ed60 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/source/path.rb @@ -0,0 +1,225 @@ +module Bundler + class Source + + class Path < Source + autoload :Installer, 'bundler/source/path/installer' + + attr_reader :path, :options + attr_writer :name + attr_accessor :version + + DEFAULT_GLOB = "{,*,*/*}.gemspec" + + def initialize(options) + @options = options + @glob = options["glob"] || DEFAULT_GLOB + + @allow_cached = false + @allow_remote = false + + if options["path"] + @path = Pathname.new(options["path"]) + @path = expand(@path) unless @path.relative? + end + + @name = options["name"] + @version = options["version"] + + # Stores the original path. If at any point we move to the + # cached directory, we still have the original path to copy from. + @original_path = @path + end + + def remote! + @allow_remote = true + end + + def cached! + @allow_cached = true + end + + def self.from_lock(options) + new(options.merge("path" => options.delete("remote"))) + end + + def to_lock + out = "PATH\n" + out << " remote: #{relative_path}\n" + out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB + out << " specs:\n" + end + + def to_s + "source at #{@path}" + end + + def hash + self.class.hash + end + + def eql?(o) + o.instance_of?(Path) && + expand(path) == expand(o.path) && + version == o.version + end + + alias == eql? + + def name + File.basename(expand(path).to_s) + end + + def install(spec) + generate_bin(spec, :disable_extensions) + ["Using #{version_message(spec)} from #{to_s}", nil] + end + + def cache(spec, custom_path = nil) + app_cache_path = app_cache_path(custom_path) + return unless Bundler.settings[:cache_all] + return if expand(@original_path).to_s.index(Bundler.root.to_s) == 0 + + unless @original_path.exist? + raise GemNotFound, "Can't cache gem #{version_message(spec)} because #{to_s} is missing!" + end + + FileUtils.rm_rf(app_cache_path) + FileUtils.cp_r("#{@original_path}/.", app_cache_path) + FileUtils.touch(app_cache_path.join(".bundlecache")) + end + + def local_specs(*) + @local_specs ||= load_spec_files + end + + def specs + if has_app_cache? + @path = app_cache_path + end + local_specs + end + + def app_cache_dirname + name + end + + private + + def expand(somepath) + somepath.expand_path(Bundler.root) + rescue ArgumentError => e + Bundler.ui.debug(e) + raise PathError, "There was an error while trying to use the path " \ + "`#{somepath}`.\nThe error message was: #{e.message}." + end + + def app_cache_path(custom_path = nil) + @app_cache_path ||= Bundler.app_cache(custom_path).join(app_cache_dirname) + end + + def has_app_cache? + SharedHelpers.in_bundle? && app_cache_path.exist? + end + + def load_spec_files + index = Index.new + expanded_path = expand(path) + + if File.directory?(expanded_path) + Dir["#{expanded_path}/#{@glob}"].each do |file| + spec = Bundler.load_gemspec(file) + if spec + spec.loaded_from = file.to_s + spec.source = self + index << spec + end + end + + if index.empty? && @name && @version + index << Gem::Specification.new do |s| + s.name = @name + s.source = self + s.version = Gem::Version.new(@version) + s.platform = Gem::Platform::RUBY + s.summary = "Fake gemspec for #{@name}" + s.relative_loaded_from = "#{@name}.gemspec" + s.authors = ["no one"] + if expanded_path.join("bin").exist? + executables = expanded_path.join("bin").children + executables.reject!{|p| File.directory?(p) } + s.executables = executables.map{|c| c.basename.to_s } + end + end + end + elsif File.exist?(expanded_path) + raise PathError, "The path `#{expanded_path}` is not a directory." + else + raise PathError, "The path `#{expanded_path}` does not exist." + end + + index + end + + def relative_path + if path.to_s.match(%r{^#{Regexp.escape Bundler.root.to_s}}) + return path.relative_path_from(Bundler.root) + end + path + end + + def generate_bin(spec, disable_extensions = false) + 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 + spec.files = spec.files.map do |p| + next if File.directory?(p) + begin + Pathname.new(p).relative_path_from(gem_dir).to_s + rescue ArgumentError + p + end + end.compact + + 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 + run_hooks(:post_build, installer) + installer.generate_bin + run_hooks(:post_install, installer) + rescue Gem::InvalidSpecificationException => e + Bundler.ui.warn "\n#{spec.name} at #{spec.full_gem_path} did not have a valid gemspec.\n" \ + "This prevents bundler from installing bins or native extensions, but " \ + "that may not affect its functionality." + + if !spec.extensions.empty? && !spec.email.empty? + Bundler.ui.warn "If you need to use this package without installing it from a gem " \ + "repository, please contact #{spec.email} and ask them " \ + "to modify their .gemspec so it can work with `gem build`." + 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) + hooks_meth = "#{type}_hooks" + return unless Gem.respond_to?(hooks_meth) + Gem.send(hooks_meth).each do |hook| + result = hook.call(installer) + if result == false + location = " at #{$1}" if hook.inspect =~ /@(.*:\d+)/ + message = "#{type} hook#{location} failed for #{installer.spec.full_name}" + raise InstallHookError, message + end + end + end + end + + end +end diff --git a/bundler-1.7.2/lib/bundler/source/path/installer.rb b/bundler-1.7.2/lib/bundler/source/path/installer.rb new file mode 100644 index 0000000..28e6987 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/source/path/installer.rb @@ -0,0 +1,38 @@ +module Bundler + class Source + class Path + + class Installer < Bundler::GemInstaller + def initialize(spec, options = {}) + @spec = spec + @tmp_bin_dir = "#{Bundler.tmp(spec.full_name)}/bin" + @gem_bin_dir = "#{Bundler.rubygems.gem_dir}/bin" + @bin_dir = Bundler.requires_sudo? ? @tmp_bin_dir : @gem_bin_dir + @gem_dir = Bundler.rubygems.path(spec.full_gem_path) + @wrappers = options[:wrappers] || true + @env_shebang = options[:env_shebang] || true + @format_executable = options[:format_executable] || false + @build_args = options[:build_args] || Bundler.rubygems.build_args + end + + def generate_bin + return if spec.executables.nil? || spec.executables.empty? + + if Bundler.requires_sudo? + FileUtils.mkdir_p(@tmp_bin_dir) unless File.exist?(@tmp_bin_dir) + end + + super + + if Bundler.requires_sudo? + Bundler.mkdir_p @gem_bin_dir + spec.executables.each do |exe| + Bundler.sudo "cp -R #{@tmp_bin_dir}/#{exe} #{@gem_bin_dir}" + end + end + end + end + + end + end +end diff --git a/bundler-1.7.2/lib/bundler/source/rubygems.rb b/bundler-1.7.2/lib/bundler/source/rubygems.rb new file mode 100644 index 0000000..f3b8b7c --- /dev/null +++ b/bundler-1.7.2/lib/bundler/source/rubygems.rb @@ -0,0 +1,350 @@ +require 'uri' +require 'rubygems/user_interaction' +require 'rubygems/spec_fetcher' + +module Bundler + class Source + class Rubygems < Source + API_REQUEST_LIMIT = 100 # threshold for switching back to the modern index instead of fetching every spec + + attr_reader :remotes, :caches + + def initialize(options = {}) + @options = options + @remotes = [] + @dependency_names = [] + @allow_remote = false + @allow_cached = false + @caches = [Bundler.app_cache, *Bundler.rubygems.gem_cache] + + Array(options["remotes"] || []).reverse_each{|r| add_remote(r) } + end + + def remote! + @allow_remote = true + end + + def cached! + @allow_cached = true + end + + def hash + @remotes.hash + end + + def eql?(o) + o.is_a?(Rubygems) && remotes_equal?(o.remotes) + end + + alias == eql? + + def can_lock?(spec) + spec.source.is_a?(Rubygems) + end + + def options + { "remotes" => @remotes.map { |r| r.to_s } } + end + + def self.from_lock(options) + new(options) + end + + def to_lock + out = "GEM\n" + out << remotes.map { |remote| + " remote: #{suppress_configured_credentials remote}\n" + }.join + out << " specs:\n" + end + + def to_s + remote_names = self.remotes.map { |r| r.to_s }.join(', ') + "rubygems repository #{remote_names}" + end + alias_method :name, :to_s + + def specs + @specs ||= begin + # remote_specs usually generates a way larger Index than the other + # sources, and large_idx.use small_idx is way faster than + # small_idx.use large_idx. + idx = @allow_remote ? remote_specs.dup : Index.new + idx.use(cached_specs, :override_dupes) if @allow_cached || @allow_remote + idx.use(installed_specs, :override_dupes) + idx + end + end + + def install(spec) + return ["Using #{version_message(spec)}", nil] if installed_specs[spec].any? + + # Download the gem to get the spec, because some specs that are returned + # by rubygems.org are broken and wrong. + if spec.source_uri + # Check for this spec from other sources + uris = [spec.source_uri] + uris += source_uris_for_spec(spec) + uris.compact! + uris.uniq! + Installer.ambiguous_gems << [spec.name, *uris] if uris.length > 1 + + s = Bundler.rubygems.spec_from_gem(fetch_gem(spec), Bundler.settings["trust-policy"]) + 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 + + 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)) + 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}/" + end + end + + spec.loaded_from = "#{Bundler.rubygems.gem_dir}/specifications/#{spec.full_name}.gemspec" + installed_spec.loaded_from = spec.loaded_from + ["Installing #{version_message(spec)}", spec.post_install_message] + ensure + if install_path && Bundler.requires_sudo? + FileUtils.remove_entry_secure(install_path) + end + end + + def cache(spec, custom_path = nil) + if builtin_gem?(spec) + cached_path = cached_built_in_gem(spec) + else + cached_path = cached_gem(spec) + end + raise GemNotFound, "Missing gem file '#{spec.full_name}.gem'." unless cached_path + 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)) + end + + def cached_built_in_gem(spec) + cached_path = cached_path(spec) + if cached_path.nil? + remote_spec = remote_specs.search(spec).first + cached_path = fetch_gem(remote_spec) + end + cached_path + end + + def add_remote(source) + uri = normalize_uri(source) + @remotes.unshift(uri) unless @remotes.include?(uri) + end + + def replace_remotes(other_remotes) + return false if other_remotes == @remotes + + @remotes = [] + other_remotes.reverse_each do |r| + add_remote r.to_s + end + end + + def unmet_deps + if @allow_remote && api_fetchers.any? + remote_specs.unmet_dependency_names + else + [] + end + end + + protected + + def source_uris_for_spec(spec) + specs.search_all(spec.name).map{|s| s.source_uri } + end + + private + + def cached_gem(spec) + cached_gem = cached_path(spec) + unless cached_gem + raise Bundler::GemNotFound, "Could not find #{spec.file_name} for installation" + end + cached_gem + end + + def cached_path(spec) + possibilities = @caches.map { |p| "#{p}/#{spec.file_name}" } + possibilities.find { |p| File.exist?(p) } + end + + def normalize_uri(uri) + uri = uri.to_s + uri = "#{uri}/" unless uri =~ %r'/$' + uri = URI(uri) + raise ArgumentError, "The source must be an absolute URI" unless uri.absolute? + uri + end + + def suppress_configured_credentials(remote) + remote_nouser = remote.dup.tap { |uri| uri.user = uri.password = nil }.to_s + if remote.userinfo && remote.userinfo == Bundler.settings[remote_nouser] + remote_nouser + else + remote + end + end + + def installed_specs + @installed_specs ||= begin + idx = Index.new + have_bundler = false + Bundler.rubygems.all_specs.reverse.each do |spec| + next if spec.name == 'bundler' && spec.version.to_s != VERSION + have_bundler = true if spec.name == 'bundler' + spec.source = self + idx << spec + end + + # Always have bundler locally + unless have_bundler + # We're running bundler directly from the source + # so, let's create a fake gemspec for it (it's a path) + # gemspec + bundler = Gem::Specification.new do |s| + s.name = 'bundler' + s.version = VERSION + s.platform = Gem::Platform::RUBY + s.source = self + s.authors = ["bundler team"] + s.loaded_from = File.expand_path("..", __FILE__) + end + idx << bundler + end + idx + end + end + + def cached_specs + @cached_specs ||= begin + idx = installed_specs.dup + + path = Bundler.app_cache + Dir["#{path}/*.gem"].each do |gemfile| + next if gemfile =~ /^bundler\-[\d\.]+?\.gem/ + s ||= Bundler.rubygems.spec_from_gem(gemfile) + s.source = self + idx << s + end + end + + 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 + + def remote_specs + @remote_specs ||= Index.build do |idx| + index_fetchers = fetchers - api_fetchers + + # gather lists from non-api sites + index_fetchers.each do |f| + Bundler.ui.info "Fetching source index from #{f.uri}" + idx.use f.specs(nil, self) + end + + # because ensuring we have all the gems we need involves downloading + # the gemspecs of those gems, if the non-api sites contain more than + # about 100 gems, we just treat all sites as non-api for speed. + allow_api = idx.size < API_REQUEST_LIMIT && dependency_names.size < API_REQUEST_LIMIT + + if allow_api + api_fetchers.each do |f| + Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug? + idx.use f.specs(dependency_names, self) + Bundler.ui.info "" if !Bundler.ui.debug? # new line now that the dots are over + end + + if api_fetchers.any? && api_fetchers.all?{|f| f.use_api } + # it's possible that gems from one source depend on gems from some + # other source, so now we download gemspecs and iterate over those + # dependencies, looking for gems we don't have info on yet. + unmet = idx.unmet_dependency_names + + # if there are any cross-site gems we missed, get them now + api_fetchers.each do |f| + Bundler.ui.info "Fetching additional metadata from #{f.uri}", Bundler.ui.debug? + idx.use f.specs(unmet, self) + Bundler.ui.info "" if !Bundler.ui.debug? # new line now that the dots are over + end if unmet.any? + else + allow_api = false + end + end + + if !allow_api + api_fetchers.each do |f| + Bundler.ui.info "Fetching source index from #{f.uri}" + idx.use f.specs(nil, self) + end + end + end + end + + def fetch_gem(spec) + return false unless spec.source_uri + Fetcher.download_gem_from_uri(spec, spec.source_uri) + end + + def builtin_gem?(spec) + # Ruby 2.1, where all included gems have this summary + return true if spec.summary =~ /is bundled with Ruby/ + + # Ruby 2.0, where gemspecs are stored in specifications/default/ + spec.loaded_from && spec.loaded_from.include?("specifications/default/") + end + + def remotes_equal?(other_remotes) + remotes.map(&method(:suppress_configured_credentials)) == other_remotes.map(&method(:suppress_configured_credentials)) + end + + end + end +end diff --git a/bundler-1.7.2/lib/bundler/source_list.rb b/bundler-1.7.2/lib/bundler/source_list.rb new file mode 100644 index 0000000..0d9fb51 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/source_list.rb @@ -0,0 +1,80 @@ +module Bundler + class SourceList + attr_reader :path_sources, + :git_sources, + :rubygems_sources + + def initialize + @path_sources = [] + @git_sources = [] + @rubygems_aggregate = Source::Rubygems.new + @rubygems_sources = [@rubygems_aggregate] + end + + def add_path_source(options = {}) + add_source_to_list Source::Path.new(options), path_sources + end + + def add_git_source(options = {}) + add_source_to_list Source::Git.new(options), git_sources + end + + def add_rubygems_source(options = {}) + add_source_to_list Source::Rubygems.new(options), @rubygems_sources + end + + def add_rubygems_remote(uri) + @rubygems_aggregate.add_remote(uri) + @rubygems_aggregate + end + + def all_sources + path_sources + git_sources + rubygems_sources + end + + def get(source) + source_list_for(source).find { |s| source == s } + end + + def lock_sources + lock_sources = (path_sources + git_sources).sort_by(&:to_s) + lock_sources << combine_rubygems_sources + end + + def replace_sources!(replacement_sources) + [path_sources, git_sources, rubygems_sources].each do |source_list| + source_list.map! do |source| + replacement_sources.find { |s| s == source } || source + end + end + end + + def cached! + all_sources.each(&:cached!) + end + + def remote! + all_sources.each(&:remote!) + end + + private + + def add_source_to_list(source, list) + list.unshift(source).uniq! + source + end + + def source_list_for(source) + case source + when Source::Git then git_sources + when Source::Path then path_sources + when Source::Rubygems then rubygems_sources + else raise ArgumentError, "Invalid source: #{source.inspect}" + end + end + + def combine_rubygems_sources + Source::Rubygems.new("remotes" => rubygems_sources.map(&:remotes).flatten.uniq.reverse) + end + end +end diff --git a/bundler-1.7.2/lib/bundler/spec_set.rb b/bundler-1.7.2/lib/bundler/spec_set.rb new file mode 100644 index 0000000..1746f6d --- /dev/null +++ b/bundler-1.7.2/lib/bundler/spec_set.rb @@ -0,0 +1,154 @@ +require 'tsort' +require 'forwardable' + +module Bundler + class SpecSet + extend Forwardable + include TSort, Enumerable + + def_delegators :@specs, :<<, :length, :add, :remove + def_delegators :sorted, :each + + def initialize(specs) + @specs = specs.sort_by { |s| s.name } + end + + def for(dependencies, skip = [], check = false, match_current_platform = false) + handled, deps, specs = {}, dependencies.dup, [] + skip << 'bundler' + + until deps.empty? + dep = deps.shift + next if handled[dep] || skip.include?(dep.name) + + spec = lookup[dep.name].find do |s| + if match_current_platform + Gem::Platform.match(s.platform) + else + s.match_platform(dep.__platform) + end + end + + handled[dep] = true + + if spec + specs << spec + + spec.dependencies.each do |d| + next if d.type == :development + d = DepProxy.new(d, dep.__platform) unless match_current_platform + deps << d + end + elsif check + return false + end + end + + if spec = lookup['bundler'].first + specs << spec + end + + check ? true : SpecSet.new(specs) + end + + def valid_for?(deps) + self.for(deps, [], true) + end + + def [](key) + key = key.name if key.respond_to?(:name) + lookup[key].reverse + end + + def []=(key, value) + @specs << value + @lookup = nil + @sorted = nil + value + end + + def sort! + self + end + + def to_a + sorted.dup + end + + def to_hash + lookup.dup + end + + def materialize(deps, missing_specs = nil) + materialized = self.for(deps, [], false, true).to_a + deps = materialized.map {|s| s.name }.uniq + materialized.map! do |s| + next s unless s.is_a?(LazySpecification) + s.source.dependency_names = deps if s.source.respond_to?(:dependency_names=) + spec = s.__materialize__ + if missing_specs + missing_specs << s unless spec + else + raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec + end + spec if spec + end + SpecSet.new(materialized.compact) + end + + def merge(set) + arr = sorted.dup + set.each do |s| + next if arr.any? { |s2| s2.name == s.name && s2.version == s.version && s2.platform == s.platform } + arr << s + end + SpecSet.new(arr) + end + + private + + def sorted + rake = @specs.find { |s| s.name == 'rake' } + begin + @sorted ||= ([rake] + tsort).compact.uniq + rescue TSort::Cyclic => error + cgems = extract_circular_gems(error) + raise CyclicDependencyError, "Your Gemfile requires gems that depend" \ + " depend on each other, creating an infinite loop. Please remove" \ + " either gem '#{cgems[1]}' or gem '#{cgems[0]}' and try again." + end + end + + def extract_circular_gems(error) + if Bundler.current_ruby.mri? && Bundler.current_ruby.on_19? + error.message.scan(/(\w+) \([^)]/).flatten + else + error.message.scan(/@name="(.*?)"/).flatten + end + end + + def lookup + @lookup ||= begin + lookup = Hash.new { |h,k| h[k] = [] } + specs = @specs.sort_by do |s| + s.platform.to_s == 'ruby' ? "\0" : s.platform.to_s + end + specs.reverse_each do |s| + lookup[s.name] << s + end + lookup + end + end + + def tsort_each_node + @specs.each { |s| yield s } + end + + def tsort_each_child(s) + s.dependencies.sort_by { |d| d.name }.each do |d| + next if d.type == :development + lookup[d.name].each { |s2| yield s2 } + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/ssl_certs/.document b/bundler-1.7.2/lib/bundler/ssl_certs/.document new file mode 100644 index 0000000..fb66f13 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/ssl_certs/.document @@ -0,0 +1 @@ +# Ignore all files in this directory diff --git a/bundler-1.7.2/lib/bundler/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem b/bundler-1.7.2/lib/bundler/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem new file mode 100644 index 0000000..87676ac --- /dev/null +++ b/bundler-1.7.2/lib/bundler/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do +lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc +AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k +-----END CERTIFICATE----- diff --git a/bundler-1.7.2/lib/bundler/ssl_certs/DigiCertHighAssuranceEVRootCA.pem b/bundler-1.7.2/lib/bundler/ssl_certs/DigiCertHighAssuranceEVRootCA.pem new file mode 100644 index 0000000..9e6810a --- /dev/null +++ b/bundler-1.7.2/lib/bundler/ssl_certs/DigiCertHighAssuranceEVRootCA.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- diff --git a/bundler-1.7.2/lib/bundler/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem b/bundler-1.7.2/lib/bundler/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem new file mode 100644 index 0000000..4b8939c --- /dev/null +++ b/bundler-1.7.2/lib/bundler/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 +MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE +ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j +b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg +U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ +I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 +wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC +AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb +oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 +BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p +dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk +MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 +MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi +E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa +MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI +hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN +95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd +2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +-----END CERTIFICATE----- diff --git a/bundler-1.7.2/lib/bundler/ssl_certs/GeoTrustGlobalCA.pem b/bundler-1.7.2/lib/bundler/ssl_certs/GeoTrustGlobalCA.pem new file mode 100644 index 0000000..bcb2529 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/ssl_certs/GeoTrustGlobalCA.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE----- diff --git a/bundler-1.7.2/lib/bundler/ssl_certs/certificate_manager.rb b/bundler-1.7.2/lib/bundler/ssl_certs/certificate_manager.rb new file mode 100644 index 0000000..dea184d --- /dev/null +++ b/bundler-1.7.2/lib/bundler/ssl_certs/certificate_manager.rb @@ -0,0 +1,41 @@ +require 'fileutils' + +module Bundler + module SSLCerts + class CertificateManager + attr_reader :bundler_cert_path, :bundler_certs, :rubygems_certs + + def self.update_from!(rubygems_path) + new(rubygems_path).update! + end + + def initialize(rubygems_path) + rubygems_certs = File.join(rubygems_path, 'lib/rubygems/ssl_certs') + @rubygems_certs = certificates_in(rubygems_certs) + + @bundler_cert_path = File.expand_path("..", __FILE__) + @bundler_certs = certificates_in(bundler_cert_path) + end + + def up_to_date? + bundler_certs.zip(rubygems_certs).all? do |bc, rc| + File.basename(bc) == File.basename(rc) && FileUtils.compare_file(bc, rc) + end + end + + def update! + return if up_to_date? + + FileUtils.rm bundler_certs + FileUtils.cp rubygems_certs, bundler_cert_path + end + + private + + def certificates_in(path) + Dir[File.join(path, "*.pem")].sort + end + + end + end +end diff --git a/bundler-1.7.2/lib/bundler/templates/Executable b/bundler-1.7.2/lib/bundler/templates/Executable new file mode 100644 index 0000000..5c60c28 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/Executable @@ -0,0 +1,16 @@ +#!/usr/bin/env <%= Bundler.settings[:shebang] || RbConfig::CONFIG['ruby_install_name'] %> +# +# This file was generated by Bundler. +# +# The application '<%= executable %>' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../<%= relative_gemfile_path %>", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('<%= spec.name %>', '<%= executable %>') diff --git a/bundler-1.7.2/lib/bundler/templates/Executable.standalone b/bundler-1.7.2/lib/bundler/templates/Executable.standalone new file mode 100644 index 0000000..c4f2703 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/Executable.standalone @@ -0,0 +1,12 @@ +#!/usr/bin/env <%= Bundler.settings[:shebang] || RbConfig::CONFIG['ruby_install_name'] %> +# +# This file was generated by Bundler. +# +# The application '<%= executable %>' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +$:.unshift File.expand_path '../<%= standalone_path %>', __FILE__ + +require 'bundler/setup' +load File.expand_path '../<%= executable_path %>', __FILE__ diff --git a/bundler-1.7.2/lib/bundler/templates/Gemfile b/bundler-1.7.2/lib/bundler/templates/Gemfile new file mode 100644 index 0000000..8d5b66e --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/Gemfile @@ -0,0 +1,4 @@ +# A sample Gemfile +source "https://rubygems.org" + +# gem "rails" diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/.travis.yml.tt b/bundler-1.7.2/lib/bundler/templates/newgem/.travis.yml.tt new file mode 100644 index 0000000..4c7eba6 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/.travis.yml.tt @@ -0,0 +1,3 @@ +language: ruby +rvm: + - <%= RUBY_VERSION %> diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/Gemfile.tt b/bundler-1.7.2/lib/bundler/templates/newgem/Gemfile.tt new file mode 100644 index 0000000..d24b852 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/Gemfile.tt @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +# Specify your gem's dependencies in <%=config[:name]%>.gemspec +gemspec diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/LICENSE.txt.tt b/bundler-1.7.2/lib/bundler/templates/newgem/LICENSE.txt.tt new file mode 100644 index 0000000..a9f52e6 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/LICENSE.txt.tt @@ -0,0 +1,22 @@ +Copyright (c) <%=Time.now.year%> <%=config[:author]%> + +MIT License + +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 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/bundler-1.7.2/lib/bundler/templates/newgem/README.md.tt b/bundler-1.7.2/lib/bundler/templates/newgem/README.md.tt new file mode 100644 index 0000000..8a65988 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/README.md.tt @@ -0,0 +1,31 @@ +# <%=config[:constant_name]%> + +TODO: Write a gem description + +## Installation + +Add this line to your application's Gemfile: + +```ruby +gem '<%=config[:name]%>' +``` + +And then execute: + + $ bundle + +Or install it yourself as: + + $ gem install <%=config[:name]%> + +## Usage + +TODO: Write usage instructions here + +## Contributing + +1. Fork it ( https://github.com/[my-github-username]/<%=config[:name]%>/fork ) +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Add some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create a new Pull Request diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/Rakefile.tt b/bundler-1.7.2/lib/bundler/templates/newgem/Rakefile.tt new file mode 100644 index 0000000..f4fc3c6 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/Rakefile.tt @@ -0,0 +1,24 @@ +require "bundler/gem_tasks" +<% if config[:test] == 'minitest' -%> +require "rake/testtask" + +Rake::TestTask.new(:test) do |t| + t.libs << "test" +end + +task :default => :test +<% elsif config[:test] == 'rspec' -%> +require "rspec/core/rake_task" + +RSpec::Core::RakeTask.new(:spec) + +task :default => :spec +<% end -%> + +<% if config[:ext] -%> +require "rake/extensiontask" + +Rake::ExtensionTask.new("<%=config[:underscored_name]%>") do |ext| + ext.lib_dir = "lib/<%=config[:namespaced_path]%>" +end +<% end -%> diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/bin/newgem.tt b/bundler-1.7.2/lib/bundler/templates/newgem/bin/newgem.tt new file mode 100644 index 0000000..a005298 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/bin/newgem.tt @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby + +require '<%= config[:namespaced_path] %>' diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt b/bundler-1.7.2/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt new file mode 100644 index 0000000..3fd8181 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt @@ -0,0 +1,3 @@ +require "mkmf" + +create_makefile(<%=config[:underscored_name].inspect%>) diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt b/bundler-1.7.2/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt new file mode 100644 index 0000000..5dad364 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt @@ -0,0 +1,9 @@ +#include "<%=config[:underscored_name]%>.h" + +VALUE rb_m<%=config[:constant_array].join%>; + +void +Init_<%=config[:underscored_name]%>(void) +{ + rb_m<%=config[:constant_array].join%> = rb_define_module(<%=config[:constant_name].inspect%>); +} diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt b/bundler-1.7.2/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt new file mode 100644 index 0000000..960fdfb --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt @@ -0,0 +1,6 @@ +#ifndef <%=config[:underscored_name].upcase%>_H +#define <%=config[:underscored_name].upcase%>_H 1 + +#include "ruby.h" + +#endif /* <%=config[:underscored_name].upcase%>_H */ diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/gitignore.tt b/bundler-1.7.2/lib/bundler/templates/newgem/gitignore.tt new file mode 100644 index 0000000..ae3fdc2 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/gitignore.tt @@ -0,0 +1,14 @@ +/.bundle/ +/.yardoc +/Gemfile.lock +/_yardoc/ +/coverage/ +/doc/ +/pkg/ +/spec/reports/ +/tmp/ +*.bundle +*.so +*.o +*.a +mkmf.log diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/lib/newgem.rb.tt b/bundler-1.7.2/lib/bundler/templates/newgem/lib/newgem.rb.tt new file mode 100644 index 0000000..b3f816b --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/lib/newgem.rb.tt @@ -0,0 +1,12 @@ +require "<%=config[:namespaced_path]%>/version" +<%- if config[:ext] -%> +require "<%=config[:namespaced_path]%>/<%=config[:underscored_name]%>" +<%- end -%> + +<%- config[:constant_array].each_with_index do |c,i| -%> +<%= ' '*i %>module <%= c %> +<%- end -%> +<%= ' '*config[:constant_array].size %># Your code goes here... +<%- (config[:constant_array].size-1).downto(0) do |i| -%> +<%= ' '*i %>end +<%- end -%> diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/lib/newgem/version.rb.tt b/bundler-1.7.2/lib/bundler/templates/newgem/lib/newgem/version.rb.tt new file mode 100644 index 0000000..fe9b5fc --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/lib/newgem/version.rb.tt @@ -0,0 +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-1).downto(0) do |i| -%> +<%= ' '*i %>end +<%- end -%> diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/newgem.gemspec.tt b/bundler-1.7.2/lib/bundler/templates/newgem/newgem.gemspec.tt new file mode 100644 index 0000000..74d253e --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/newgem.gemspec.tt @@ -0,0 +1,32 @@ +# coding: utf-8 +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require '<%=config[:namespaced_path]%>/version' + +Gem::Specification.new do |spec| + spec.name = <%=config[:name].inspect%> + 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.license = "MIT" + + 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.require_paths = ["lib"] + + spec.add_development_dependency "bundler", "~> <%= Bundler::VERSION.split(".")[0..1].join(".") %>" + spec.add_development_dependency "rake", "~> 10.0" +<% if config[:ext] -%> + spec.add_development_dependency "rake-compiler" +<% end -%> +<% if config[:test] -%> + spec.add_development_dependency "<%=config[:test]%>" +<% end -%> +end diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/rspec.tt b/bundler-1.7.2/lib/bundler/templates/newgem/rspec.tt new file mode 100644 index 0000000..8c18f1a --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/rspec.tt @@ -0,0 +1,2 @@ +--format documentation +--color diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt b/bundler-1.7.2/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt new file mode 100644 index 0000000..2549af4 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe <%= config[:constant_name] %> do + it 'has a version number' do + expect(<%= config[:constant_name] %>::VERSION).not_to be nil + end + + it 'does something useful' do + expect(false).to eq(true) + end +end diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/spec/spec_helper.rb.tt b/bundler-1.7.2/lib/bundler/templates/newgem/spec/spec_helper.rb.tt new file mode 100644 index 0000000..212c747 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/spec/spec_helper.rb.tt @@ -0,0 +1,2 @@ +$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) +require '<%= config[:namespaced_path] %>' diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/test/minitest_helper.rb.tt b/bundler-1.7.2/lib/bundler/templates/newgem/test/minitest_helper.rb.tt new file mode 100644 index 0000000..49a56c1 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/test/minitest_helper.rb.tt @@ -0,0 +1,4 @@ +$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) +require '<%= config[:namespaced_path] %>' + +require 'minitest/autorun' diff --git a/bundler-1.7.2/lib/bundler/templates/newgem/test/test_newgem.rb.tt b/bundler-1.7.2/lib/bundler/templates/newgem/test/test_newgem.rb.tt new file mode 100644 index 0000000..34cc473 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/templates/newgem/test/test_newgem.rb.tt @@ -0,0 +1,11 @@ +require 'minitest_helper' + +class Test<%= config[:constant_name] %> < MiniTest::Unit::TestCase + def test_that_it_has_a_version_number + refute_nil ::<%= config[:constant_name] %>::VERSION + end + + def test_it_does_something_useful + assert false + end +end diff --git a/bundler-1.7.2/lib/bundler/ui.rb b/bundler-1.7.2/lib/bundler/ui.rb new file mode 100644 index 0000000..af325af --- /dev/null +++ b/bundler-1.7.2/lib/bundler/ui.rb @@ -0,0 +1,7 @@ +module Bundler + module UI + autoload :RGProxy, 'bundler/ui/rg_proxy' + autoload :Shell, 'bundler/ui/shell' + autoload :Silent, 'bundler/ui/silent' + end +end diff --git a/bundler-1.7.2/lib/bundler/ui/rg_proxy.rb b/bundler-1.7.2/lib/bundler/ui/rg_proxy.rb new file mode 100644 index 0000000..1b62001 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/ui/rg_proxy.rb @@ -0,0 +1,21 @@ +require 'bundler/ui' +require 'rubygems/user_interaction' + +module Bundler + module UI + class RGProxy < ::Gem::SilentUI + def initialize(ui) + @ui = ui + super() + end + + def say(message) + if message =~ /native extensions/ + @ui.info "with native extensions " + else + @ui.debug(message) + end + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/ui/shell.rb b/bundler-1.7.2/lib/bundler/ui/shell.rb new file mode 100644 index 0000000..c7054e4 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/ui/shell.rb @@ -0,0 +1,95 @@ +module Bundler + module UI + class Shell + LEVELS = %w(silent error warn confirm info debug) + + attr_writer :shell + + def initialize(options = {}) + if options["no-color"] || !STDOUT.tty? + Thor::Base.shell = Thor::Shell::Basic + end + @shell = Thor::Base.shell.new + @level = ENV['DEBUG'] ? "debug" : "info" + end + + def info(msg, newline = nil) + tell_me(msg, nil, newline) if level("info") + end + + def confirm(msg, newline = nil) + tell_me(msg, :green, newline) if level("confirm") + end + + def warn(msg, newline = nil) + tell_me(msg, :yellow, newline) if level("warn") + end + + def error(msg, newline = nil) + tell_me(msg, :red, newline) if level("error") + end + + def debug(msg, newline = nil) + tell_me(msg, nil, newline) if level("debug") + end + + def debug? + # needs to be false instead of nil to be newline param to other methods + level("debug") + end + + def quiet? + LEVELS.index(@level) <= LEVELS.index("warn") + end + + def ask(msg) + @shell.ask(msg) + end + + def level=(level) + raise ArgumentError unless LEVELS.include?(level.to_s) + @level = level + end + + def level(name = nil) + name ? LEVELS.index(name) <= LEVELS.index(@level) : @level + end + + def trace(e, newline = nil) + return unless debug? + msg = ["#{e.class}: #{e.message}", *e.backtrace].join("\n") + tell_me(msg, nil, newline) + end + + def silence + old_level, @level = @level, "silent" + yield + ensure + @level = old_level + end + + private + + # valimism + def tell_me(msg, color = nil, newline = nil) + msg = word_wrap(msg) if newline.is_a?(Hash) && newline[:wrap] + if newline.nil? + @shell.say(msg, color) + else + @shell.say(msg, color, newline) + end + end + + def strip_leading_spaces(text) + spaces = text[/\A\s+/, 0] + spaces ? text.gsub(/#{spaces}/, '') : text + end + + def word_wrap(text, line_width = @shell.terminal_width) + strip_leading_spaces(text).split("\n").collect do |line| + line.length > line_width ? line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip : line + end * "\n" + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/ui/silent.rb b/bundler-1.7.2/lib/bundler/ui/silent.rb new file mode 100644 index 0000000..3eb3199 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/ui/silent.rb @@ -0,0 +1,44 @@ +module Bundler + module UI + class Silent + def info(message, newline = nil) + end + + def confirm(message, newline = nil) + end + + def warn(message, newline = nil) + end + + def error(message, newline = nil) + end + + def debug(message, newline = nil) + end + + def debug? + false + end + + def quiet? + false + end + + def ask(message) + end + + def level=(name) + end + + def level(name = nil) + end + + def trace(message, newline = nil) + end + + def silence + yield + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/.document b/bundler-1.7.2/lib/bundler/vendor/.document new file mode 100644 index 0000000..e69de29 diff --git a/bundler-1.7.2/lib/bundler/vendor/net/http/faster.rb b/bundler-1.7.2/lib/bundler/vendor/net/http/faster.rb new file mode 100644 index 0000000..74b94d1 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/net/http/faster.rb @@ -0,0 +1,26 @@ +require 'net/protocol' + +## +# Aaron Patterson's monkeypatch (accepted into 1.9.1) to fix Net::HTTP's speed +# problems. +# +# http://gist.github.com/251244 + +class Net::BufferedIO #:nodoc: + alias :old_rbuf_fill :rbuf_fill + + def rbuf_fill + if @io.respond_to? :read_nonblock then + begin + @rbuf << @io.read_nonblock(65536) + rescue Errno::EWOULDBLOCK, Errno::EAGAIN => e + retry if IO.select [@io], nil, nil, @read_timeout + raise Timeout::Error, e.message + end + else # SSL sockets do not have read_nonblock + timeout @read_timeout do + @rbuf << @io.sysread(65536) + end + end + end +end if RUBY_VERSION < '1.9' diff --git a/bundler-1.7.2/lib/bundler/vendor/net/http/persistent.rb b/bundler-1.7.2/lib/bundler/vendor/net/http/persistent.rb new file mode 100644 index 0000000..e2805b1 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/net/http/persistent.rb @@ -0,0 +1,1230 @@ +require 'net/http' +begin + require 'net/https' +rescue LoadError + # net/https or openssl +end if RUBY_VERSION < '1.9' # but only for 1.8 +require 'net/http/faster' +require 'uri' +require 'cgi' # for escaping + +begin + require 'net/http/pipeline' +rescue LoadError +end + +autoload :OpenSSL, 'openssl' + +## +# Persistent connections for Net::HTTP +# +# Net::HTTP::Persistent maintains persistent connections across all the +# servers you wish to talk to. For each host:port you communicate with a +# single persistent connection is created. +# +# Multiple Net::HTTP::Persistent objects will share the same set of +# connections. +# +# For each thread you start a new connection will be created. A +# Net::HTTP::Persistent connection will not be shared across threads. +# +# You can shut down the HTTP connections when done by calling #shutdown. You +# should name your Net::HTTP::Persistent object if you intend to call this +# method. +# +# Example: +# +# require 'net/http/persistent' +# +# uri = URI 'http://example.com/awesome/web/service' +# +# http = Net::HTTP::Persistent.new 'my_app_name' +# +# # perform a GET +# response = http.request uri +# +# # or +# +# get = Net::HTTP::Get.new uri.request_uri +# response = http.request get +# +# # create a POST +# post_uri = uri + 'create' +# post = Net::HTTP::Post.new post_uri.path +# post.set_form_data 'some' => 'cool data' +# +# # perform the POST, the URI is always required +# response http.request post_uri, post +# +# Note that for GET, HEAD and other requests that do not have a body you want +# to use URI#request_uri not URI#path. The request_uri contains the query +# params which are sent in the body for other requests. +# +# == SSL +# +# SSL connections are automatically created depending upon the scheme of the +# URI. SSL connections are automatically verified against the default +# certificate store for your computer. You can override this by changing +# verify_mode or by specifying an alternate cert_store. +# +# Here are the SSL settings, see the individual methods for documentation: +# +# #certificate :: This client's certificate +# #ca_file :: The certificate-authority +# #cert_store :: An SSL certificate store +# #private_key :: The client's SSL private key +# #reuse_ssl_sessions :: Reuse a previously opened SSL session for a new +# connection +# #ssl_version :: Which specific SSL version to use +# #verify_callback :: For server certificate verification +# #verify_mode :: How connections should be verified +# +# == Proxies +# +# A proxy can be set through #proxy= or at initialization time by providing a +# second argument to ::new. The proxy may be the URI of the proxy server or +# :ENV which will consult environment variables. +# +# See #proxy= and #proxy_from_env for details. +# +# == Headers +# +# Headers may be specified for use in every request. #headers are appended to +# any headers on the request. #override_headers replace existing headers on +# the request. +# +# The difference between the two can be seen in setting the User-Agent. Using +# http.headers['User-Agent'] = 'MyUserAgent' will send "Ruby, +# MyUserAgent" while http.override_headers['User-Agent'] = +# 'MyUserAgent' will send "MyUserAgent". +# +# == Tuning +# +# === Segregation +# +# By providing an application name to ::new you can separate your connections +# from the connections of other applications. +# +# === Idle Timeout +# +# If a connection hasn't been used for this number of seconds it will automatically be +# reset upon the next use to avoid attempting to send to a closed connection. +# The default value is 5 seconds. nil means no timeout. Set through #idle_timeout. +# +# Reducing this value may help avoid the "too many connection resets" error +# when sending non-idempotent requests while increasing this value will cause +# fewer round-trips. +# +# === Read Timeout +# +# The amount of time allowed between reading two chunks from the socket. Set +# through #read_timeout +# +# === Max Requests +# +# The number of requests that should be made before opening a new connection. +# Typically many keep-alive capable servers tune this to 100 or less, so the +# 101st request will fail with ECONNRESET. If unset (default), this value has no +# effect, if set, connections will be reset on the request after max_requests. +# +# === Open Timeout +# +# The amount of time to wait for a connection to be opened. Set through +# #open_timeout. +# +# === Socket Options +# +# Socket options may be set on newly-created connections. See #socket_options +# for details. +# +# === Non-Idempotent Requests +# +# By default non-idempotent requests will not be retried per RFC 2616. By +# setting retry_change_requests to true requests will automatically be retried +# once. +# +# Only do this when you know that retrying a POST or other non-idempotent +# request is safe for your application and will not create duplicate +# resources. +# +# The recommended way to handle non-idempotent requests is the following: +# +# require 'net/http/persistent' +# +# uri = URI 'http://example.com/awesome/web/service' +# post_uri = uri + 'create' +# +# http = Net::HTTP::Persistent.new 'my_app_name' +# +# post = Net::HTTP::Post.new post_uri.path +# # ... fill in POST request +# +# begin +# response = http.request post_uri, post +# rescue Net::HTTP::Persistent::Error +# +# # POST failed, make a new request to verify the server did not process +# # the request +# exists_uri = uri + '...' +# response = http.get exists_uri +# +# # Retry if it failed +# retry if response.code == '404' +# end +# +# The method of determining if the resource was created or not is unique to +# the particular service you are using. Of course, you will want to add +# protection from infinite looping. +# +# === Connection Termination +# +# If you are done using the Net::HTTP::Persistent instance you may shut down +# all the connections in the current thread with #shutdown. This is not +# recommended for normal use, it should only be used when it will be several +# minutes before you make another HTTP request. +# +# If you are using multiple threads, call #shutdown in each thread when the +# thread is done making requests. If you don't call shutdown, that's OK. +# Ruby will automatically garbage collect and shutdown your HTTP connections +# when the thread terminates. + +class Net::HTTP::Persistent + + ## + # The beginning of Time + + EPOCH = Time.at 0 # :nodoc: + + ## + # Is OpenSSL available? This test works with autoload + + HAVE_OPENSSL = defined? OpenSSL::SSL # :nodoc: + + ## + # The version of Net::HTTP::Persistent you are using + + VERSION = '2.9.3' + + ## + # Exceptions rescued for automatic retry on ruby 2.0.0. This overlaps with + # the exception list for ruby 1.x. + + RETRIED_EXCEPTIONS = [ # :nodoc: + (Net::ReadTimeout if Net.const_defined? :ReadTimeout), + IOError, + EOFError, + Errno::ECONNRESET, + Errno::ECONNABORTED, + Errno::EPIPE, + (OpenSSL::SSL::SSLError if HAVE_OPENSSL), + Timeout::Error, + ].compact + + ## + # Error class for errors raised by Net::HTTP::Persistent. Various + # SystemCallErrors are re-raised with a human-readable message under this + # class. + + class Error < StandardError; end + + ## + # Use this method to detect the idle timeout of the host at +uri+. The + # value returned can be used to configure #idle_timeout. +max+ controls the + # maximum idle timeout to detect. + # + # After + # + # Idle timeout detection is performed by creating a connection then + # performing a HEAD request in a loop until the connection terminates + # waiting one additional second per loop. + # + # NOTE: This may not work on ruby > 1.9. + + def self.detect_idle_timeout uri, max = 10 + uri = URI uri unless uri.is_a?(URI::Generic) + uri += '/' + + req = Net::HTTP::Head.new uri.request_uri + + http = new 'net-http-persistent detect_idle_timeout' + + connection = http.connection_for uri + + sleep_time = 0 + + loop do + response = connection.request req + + $stderr.puts "HEAD #{uri} => #{response.code}" if $DEBUG + + unless response.is_a?(Net::HTTPOK) then + raise Error, "bad response code #{response.code} detecting idle timeout" + end + + break if sleep_time >= max + + sleep_time += 1 + + $stderr.puts "sleeping #{sleep_time}" if $DEBUG + sleep sleep_time + end + rescue + # ignore StandardErrors, we've probably found the idle timeout. + ensure + http.shutdown + + return sleep_time unless $! + end + + ## + # This client's OpenSSL::X509::Certificate + + attr_reader :certificate + + # For Net::HTTP parity + alias cert certificate + + ## + # An SSL certificate authority. Setting this will set verify_mode to + # VERIFY_PEER. + + attr_reader :ca_file + + ## + # An SSL certificate store. Setting this will override the default + # certificate store. See verify_mode for more information. + + attr_reader :cert_store + + ## + # Sends debug_output to this IO via Net::HTTP#set_debug_output. + # + # Never use this method in production code, it causes a serious security + # hole. + + attr_accessor :debug_output + + ## + # Current connection generation + + attr_reader :generation # :nodoc: + + ## + # Where this instance's connections live in the thread local variables + + attr_reader :generation_key # :nodoc: + + ## + # Headers that are added to every request using Net::HTTP#add_field + + attr_reader :headers + + ## + # Maps host:port to an HTTP version. This allows us to enable version + # specific features. + + attr_reader :http_versions + + ## + # Maximum time an unused connection can remain idle before being + # automatically closed. + + attr_accessor :idle_timeout + + ## + # Maximum number of requests on a connection before it is considered expired + # and automatically closed. + + attr_accessor :max_requests + + ## + # The value sent in the Keep-Alive header. Defaults to 30. Not needed for + # HTTP/1.1 servers. + # + # This may not work correctly for HTTP/1.0 servers + # + # This method may be removed in a future version as RFC 2616 does not + # require this header. + + attr_accessor :keep_alive + + ## + # A name for this connection. Allows you to keep your connections apart + # from everybody else's. + + attr_reader :name + + ## + # Seconds to wait until a connection is opened. See Net::HTTP#open_timeout + + attr_accessor :open_timeout + + ## + # Headers that are added to every request using Net::HTTP#[]= + + attr_reader :override_headers + + ## + # This client's SSL private key + + attr_reader :private_key + + # For Net::HTTP parity + alias key private_key + + ## + # The URL through which requests will be proxied + + attr_reader :proxy_uri + + ## + # List of host suffixes which will not be proxied + + attr_reader :no_proxy + + ## + # Seconds to wait until reading one block. See Net::HTTP#read_timeout + + attr_accessor :read_timeout + + ## + # Where this instance's request counts live in the thread local variables + + attr_reader :request_key # :nodoc: + + ## + # By default SSL sessions are reused to avoid extra SSL handshakes. Set + # this to false if you have problems communicating with an HTTPS server + # like: + # + # SSL_connect [...] read finished A: unexpected message (OpenSSL::SSL::SSLError) + + attr_accessor :reuse_ssl_sessions + + ## + # An array of options for Socket#setsockopt. + # + # By default the TCP_NODELAY option is set on sockets. + # + # To set additional options append them to this array: + # + # http.socket_options << [Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1] + + attr_reader :socket_options + + ## + # Current SSL connection generation + + attr_reader :ssl_generation # :nodoc: + + ## + # Where this instance's SSL connections live in the thread local variables + + attr_reader :ssl_generation_key # :nodoc: + + ## + # SSL version to use. + # + # By default, the version will be negotiated automatically between client + # and server. Ruby 1.9 and newer only. + + attr_reader :ssl_version if RUBY_VERSION > '1.9' + + ## + # Where this instance's last-use times live in the thread local variables + + attr_reader :timeout_key # :nodoc: + + ## + # SSL verification callback. Used when ca_file is set. + + attr_reader :verify_callback + + ## + # HTTPS verify mode. Defaults to OpenSSL::SSL::VERIFY_PEER which verifies + # the server certificate. + # + # If no ca_file or cert_store is set the default system certificate store is + # used. + # + # You can use +verify_mode+ to override any default values. + + attr_reader :verify_mode + + ## + # Enable retries of non-idempotent requests that change data (e.g. POST + # requests) when the server has disconnected. + # + # This will in the worst case lead to multiple requests with the same data, + # but it may be useful for some applications. Take care when enabling + # this option to ensure it is safe to POST or perform other non-idempotent + # requests to the server. + + attr_accessor :retry_change_requests + + ## + # Creates a new Net::HTTP::Persistent. + # + # Set +name+ to keep your connections apart from everybody else's. Not + # required currently, but highly recommended. Your library name should be + # good enough. This parameter will be required in a future version. + # + # +proxy+ may be set to a URI::HTTP or :ENV to pick up proxy options from + # the environment. See proxy_from_env for details. + # + # In order to use a URI for the proxy you may need to do some extra work + # beyond URI parsing if the proxy requires a password: + # + # proxy = URI 'http://proxy.example' + # proxy.user = 'AzureDiamond' + # proxy.password = 'hunter2' + + def initialize name = nil, proxy = nil + @name = name + + @debug_output = nil + @proxy_uri = nil + @no_proxy = [] + @headers = {} + @override_headers = {} + @http_versions = {} + @keep_alive = 30 + @open_timeout = nil + @read_timeout = nil + @idle_timeout = 5 + @max_requests = nil + @socket_options = [] + + @socket_options << [Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1] if + Socket.const_defined? :TCP_NODELAY + + key = ['net_http_persistent', name].compact + @generation_key = [key, 'generations' ].join('_').intern + @ssl_generation_key = [key, 'ssl_generations'].join('_').intern + @request_key = [key, 'requests' ].join('_').intern + @timeout_key = [key, 'timeouts' ].join('_').intern + + @certificate = nil + @ca_file = nil + @private_key = nil + @ssl_version = nil + @verify_callback = nil + @verify_mode = nil + @cert_store = nil + + @generation = 0 # incremented when proxy URI changes + @ssl_generation = 0 # incremented when SSL session variables change + + if HAVE_OPENSSL then + @verify_mode = OpenSSL::SSL::VERIFY_PEER + @reuse_ssl_sessions = OpenSSL::SSL.const_defined? :Session + end + + @retry_change_requests = false + + @ruby_1 = RUBY_VERSION < '2' + @retried_on_ruby_2 = !@ruby_1 + + self.proxy = proxy if proxy + end + + ## + # Sets this client's OpenSSL::X509::Certificate + + def certificate= certificate + @certificate = certificate + + reconnect_ssl + end + + # For Net::HTTP parity + alias cert= certificate= + + ## + # Sets the SSL certificate authority file. + + def ca_file= file + @ca_file = file + + reconnect_ssl + end + + ## + # Overrides the default SSL certificate store used for verifying + # connections. + + def cert_store= store + @cert_store = store + + reconnect_ssl + end + + ## + # Finishes all connections on the given +thread+ that were created before + # the given +generation+ in the threads +generation_key+ list. + # + # See #shutdown for a bunch of scary warning about misusing this method. + + def cleanup(generation, thread = Thread.current, + generation_key = @generation_key) # :nodoc: + timeouts = thread[@timeout_key] + + (0...generation).each do |old_generation| + next unless thread[generation_key] + + conns = thread[generation_key].delete old_generation + + conns.each_value do |conn| + finish conn, thread + + timeouts.delete conn.object_id if timeouts + end if conns + end + end + + ## + # Creates a new connection for +uri+ + + def connection_for uri + Thread.current[@generation_key] ||= Hash.new { |h,k| h[k] = {} } + Thread.current[@ssl_generation_key] ||= Hash.new { |h,k| h[k] = {} } + Thread.current[@request_key] ||= Hash.new 0 + Thread.current[@timeout_key] ||= Hash.new EPOCH + + use_ssl = uri.scheme.downcase == 'https' + + if use_ssl then + raise Net::HTTP::Persistent::Error, 'OpenSSL is not available' unless + HAVE_OPENSSL + + ssl_generation = @ssl_generation + + ssl_cleanup ssl_generation + + connections = Thread.current[@ssl_generation_key][ssl_generation] + else + generation = @generation + + cleanup generation + + connections = Thread.current[@generation_key][generation] + end + + net_http_args = [uri.host, uri.port] + connection_id = net_http_args.join ':' + + if @proxy_uri and not proxy_bypass? uri.host, uri.port then + connection_id << @proxy_connection_id + net_http_args.concat @proxy_args + end + + connection = connections[connection_id] + + unless connection = connections[connection_id] then + connections[connection_id] = http_class.new(*net_http_args) + connection = connections[connection_id] + ssl connection if use_ssl + else + reset connection if expired? connection + end + + start connection unless connection.started? + + connection.read_timeout = @read_timeout if @read_timeout + connection.keep_alive_timeout = @idle_timeout if @idle_timeout && connection.respond_to?(:keep_alive_timeout=) + + connection + rescue Errno::ECONNREFUSED + address = connection.proxy_address || connection.address + port = connection.proxy_port || connection.port + + raise Error, "connection refused: #{address}:#{port}" + rescue Errno::EHOSTDOWN + address = connection.proxy_address || connection.address + port = connection.proxy_port || connection.port + + raise Error, "host down: #{address}:#{port}" + end + + ## + # Returns an error message containing the number of requests performed on + # this connection + + def error_message connection + requests = Thread.current[@request_key][connection.object_id] - 1 # fixup + last_use = Thread.current[@timeout_key][connection.object_id] + + age = Time.now - last_use + + "after #{requests} requests on #{connection.object_id}, " \ + "last used #{age} seconds ago" + end + + ## + # URI::escape wrapper + + def escape str + CGI.escape str if str + end + + ## + # URI::unescape wrapper + + def unescape str + CGI.unescape str if str + end + + + ## + # Returns true if the connection should be reset due to an idle timeout, or + # maximum request count, false otherwise. + + def expired? connection + requests = Thread.current[@request_key][connection.object_id] + return true if @max_requests && requests >= @max_requests + return false unless @idle_timeout + return true if @idle_timeout.zero? + + last_used = Thread.current[@timeout_key][connection.object_id] + + Time.now - last_used > @idle_timeout + end + + ## + # Starts the Net::HTTP +connection+ + + def start connection + connection.set_debug_output @debug_output if @debug_output + connection.open_timeout = @open_timeout if @open_timeout + + connection.start + + socket = connection.instance_variable_get :@socket + + if socket then # for fakeweb + @socket_options.each do |option| + socket.io.setsockopt(*option) + end + end + end + + ## + # Finishes the Net::HTTP +connection+ + + def finish connection, thread = Thread.current + if requests = thread[@request_key] then + requests.delete connection.object_id + end + + connection.finish + rescue IOError + end + + def http_class # :nodoc: + if RUBY_VERSION > '2.0' then + Net::HTTP + elsif [:Artifice, :FakeWeb, :WebMock].any? { |klass| + Object.const_defined?(klass) + } or not @reuse_ssl_sessions then + Net::HTTP + else + Net::HTTP::Persistent::SSLReuse + end + end + + ## + # Returns the HTTP protocol version for +uri+ + + def http_version uri + @http_versions["#{uri.host}:#{uri.port}"] + end + + ## + # Is +req+ idempotent according to RFC 2616? + + def idempotent? req + case req + when Net::HTTP::Delete, Net::HTTP::Get, Net::HTTP::Head, + Net::HTTP::Options, Net::HTTP::Put, Net::HTTP::Trace then + true + end + end + + ## + # Is the request +req+ idempotent or is retry_change_requests allowed. + # + # If +retried_on_ruby_2+ is true, true will be returned if we are on ruby, + # retry_change_requests is allowed and the request is not idempotent. + + def can_retry? req, retried_on_ruby_2 = false + return @retry_change_requests && !idempotent?(req) if retried_on_ruby_2 + + @retry_change_requests || idempotent?(req) + end + + if RUBY_VERSION > '1.9' then + ## + # Workaround for missing Net::HTTPHeader#connection_close? on Ruby 1.8 + + def connection_close? header + header.connection_close? + end + + ## + # Workaround for missing Net::HTTPHeader#connection_keep_alive? on Ruby 1.8 + + def connection_keep_alive? header + header.connection_keep_alive? + end + else + ## + # Workaround for missing Net::HTTPRequest#connection_close? on Ruby 1.8 + + def connection_close? header + header['connection'] =~ /close/ or header['proxy-connection'] =~ /close/ + end + + ## + # Workaround for missing Net::HTTPRequest#connection_keep_alive? on Ruby + # 1.8 + + def connection_keep_alive? header + header['connection'] =~ /keep-alive/ or + header['proxy-connection'] =~ /keep-alive/ + end + end + + ## + # Deprecated in favor of #expired? + + def max_age # :nodoc: + return Time.now + 1 unless @idle_timeout + + Time.now - @idle_timeout + end + + ## + # Adds "http://" to the String +uri+ if it is missing. + + def normalize_uri uri + (uri =~ /^https?:/) ? uri : "http://#{uri}" + end + + ## + # Pipelines +requests+ to the HTTP server at +uri+ yielding responses if a + # block is given. Returns all responses recieved. + # + # See + # Net::HTTP::Pipeline[http://docs.seattlerb.org/net-http-pipeline/Net/HTTP/Pipeline.html] + # for further details. + # + # Only if net-http-pipeline was required before + # net-http-persistent #pipeline will be present. + + def pipeline uri, requests, &block # :yields: responses + connection = connection_for uri + + connection.pipeline requests, &block + end + + ## + # Sets this client's SSL private key + + def private_key= key + @private_key = key + + reconnect_ssl + end + + # For Net::HTTP parity + alias key= private_key= + + ## + # Sets the proxy server. The +proxy+ may be the URI of the proxy server, + # the symbol +:ENV+ which will read the proxy from the environment or nil to + # disable use of a proxy. See #proxy_from_env for details on setting the + # proxy from the environment. + # + # If the proxy URI is set after requests have been made, the next request + # will shut-down and re-open all connections. + # + # The +no_proxy+ query parameter can be used to specify hosts which shouldn't + # be reached via proxy; if set it should be a comma separated list of + # hostname suffixes, optionally with +:port+ appended, for example + # example.com,some.host:8080. + + def proxy= proxy + @proxy_uri = case proxy + when :ENV then proxy_from_env + when URI::HTTP then proxy + when nil then # ignore + else raise ArgumentError, 'proxy must be :ENV or a URI::HTTP' + end + + @no_proxy.clear + + if @proxy_uri then + @proxy_args = [ + @proxy_uri.host, + @proxy_uri.port, + unescape(@proxy_uri.user), + unescape(@proxy_uri.password), + ] + + @proxy_connection_id = [nil, *@proxy_args].join ':' + + if @proxy_uri.query then + @no_proxy = CGI.parse(@proxy_uri.query)['no_proxy'].join(',').downcase.split(',').map { |x| x.strip }.reject { |x| x.empty? } + end + end + + reconnect + reconnect_ssl + end + + ## + # Creates a URI for an HTTP proxy server from ENV variables. + # + # If +HTTP_PROXY+ is set a proxy will be returned. + # + # If +HTTP_PROXY_USER+ or +HTTP_PROXY_PASS+ are set the URI is given the + # indicated user and password unless HTTP_PROXY contains either of these in + # the URI. + # + # The +NO_PROXY+ ENV variable can be used to specify hosts which shouldn't + # be reached via proxy; if set it should be a comma separated list of + # hostname suffixes, optionally with +:port+ appended, for example + # example.com,some.host:8080. When set to * no proxy will + # be returned. + # + # For Windows users, lowercase ENV variables are preferred over uppercase ENV + # variables. + + def proxy_from_env + env_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY'] + + return nil if env_proxy.nil? or env_proxy.empty? + + uri = URI normalize_uri env_proxy + + env_no_proxy = ENV['no_proxy'] || ENV['NO_PROXY'] + + # '*' is special case for always bypass + return nil if env_no_proxy == '*' + + if env_no_proxy then + uri.query = "no_proxy=#{escape(env_no_proxy)}" + end + + unless uri.user or uri.password then + uri.user = escape ENV['http_proxy_user'] || ENV['HTTP_PROXY_USER'] + uri.password = escape ENV['http_proxy_pass'] || ENV['HTTP_PROXY_PASS'] + end + + uri + end + + ## + # Returns true when proxy should by bypassed for host. + + def proxy_bypass? host, port + host = host.downcase + host_port = [host, port].join ':' + + @no_proxy.each do |name| + return true if host[-name.length, name.length] == name or + host_port[-name.length, name.length] == name + end + + false + end + + ## + # Forces reconnection of HTTP connections. + + def reconnect + @generation += 1 + end + + ## + # Forces reconnection of SSL connections. + + def reconnect_ssl + @ssl_generation += 1 + end + + ## + # Finishes then restarts the Net::HTTP +connection+ + + def reset connection + Thread.current[@request_key].delete connection.object_id + Thread.current[@timeout_key].delete connection.object_id + + finish connection + + start connection + rescue Errno::ECONNREFUSED + e = Error.new "connection refused: #{connection.address}:#{connection.port}" + e.set_backtrace $@ + raise e + rescue Errno::EHOSTDOWN + e = Error.new "host down: #{connection.address}:#{connection.port}" + e.set_backtrace $@ + raise e + end + + ## + # Makes a request on +uri+. If +req+ is nil a Net::HTTP::Get is performed + # against +uri+. + # + # If a block is passed #request behaves like Net::HTTP#request (the body of + # the response will not have been read). + # + # +req+ must be a Net::HTTPRequest subclass (see Net::HTTP for a list). + # + # If there is an error and the request is idempotent according to RFC 2616 + # it will be retried automatically. + + def request uri, req = nil, &block + retried = false + bad_response = false + + req = request_setup req || uri + + connection = connection_for uri + connection_id = connection.object_id + + begin + Thread.current[@request_key][connection_id] += 1 + response = connection.request req, &block + + if connection_close?(req) or + (response.http_version <= '1.0' and + not connection_keep_alive?(response)) or + connection_close?(response) then + connection.finish + end + rescue Net::HTTPBadResponse => e + message = error_message connection + + finish connection + + raise Error, "too many bad responses #{message}" if + bad_response or not can_retry? req + + bad_response = true + retry + rescue *RETRIED_EXCEPTIONS => e # retried on ruby 2 + request_failed e, req, connection if + retried or not can_retry? req, @retried_on_ruby_2 + + reset connection + + retried = true + retry + rescue Errno::EINVAL, Errno::ETIMEDOUT => e # not retried on ruby 2 + request_failed e, req, connection if retried or not can_retry? req + + reset connection + + retried = true + retry + rescue Exception => e + finish connection + + raise + ensure + Thread.current[@timeout_key][connection_id] = Time.now + end + + @http_versions["#{uri.host}:#{uri.port}"] ||= response.http_version + + response + end + + ## + # Raises an Error for +exception+ which resulted from attempting the request + # +req+ on the +connection+. + # + # Finishes the +connection+. + + def request_failed exception, req, connection # :nodoc: + due_to = "(due to #{exception.message} - #{exception.class})" + message = "too many connection resets #{due_to} #{error_message connection}" + + finish connection + + + raise Error, message, exception.backtrace + end + + ## + # Creates a GET request if +req_or_uri+ is a URI and adds headers to the + # request. + # + # Returns the request. + + def request_setup req_or_uri # :nodoc: + req = if req_or_uri.is_a?(URI) then + Net::HTTP::Get.new req_or_uri.request_uri + else + req_or_uri + end + + @headers.each do |pair| + req.add_field(*pair) + end + + @override_headers.each do |name, value| + req[name] = value + end + + unless req['Connection'] then + req.add_field 'Connection', 'keep-alive' + req.add_field 'Keep-Alive', @keep_alive + end + + req + end + + ## + # Shuts down all connections for +thread+. + # + # Uses the current thread by default. + # + # If you've used Net::HTTP::Persistent across multiple threads you should + # call this in each thread when you're done making HTTP requests. + # + # *NOTE*: Calling shutdown for another thread can be dangerous! + # + # If the thread is still using the connection it may cause an error! It is + # best to call #shutdown in the thread at the appropriate time instead! + + def shutdown thread = Thread.current + generation = reconnect + cleanup generation, thread, @generation_key + + ssl_generation = reconnect_ssl + cleanup ssl_generation, thread, @ssl_generation_key + + thread[@request_key] = nil + thread[@timeout_key] = nil + end + + ## + # Shuts down all connections in all threads + # + # *NOTE*: THIS METHOD IS VERY DANGEROUS! + # + # Do not call this method if other threads are still using their + # connections! Call #shutdown at the appropriate time instead! + # + # Use this method only as a last resort! + + def shutdown_in_all_threads + Thread.list.each do |thread| + shutdown thread + end + + nil + end + + ## + # Enables SSL on +connection+ + + def ssl connection + connection.use_ssl = true + + connection.ssl_version = @ssl_version if @ssl_version + + connection.verify_mode = @verify_mode + + if OpenSSL::SSL::VERIFY_PEER == OpenSSL::SSL::VERIFY_NONE and + not Object.const_defined?(:I_KNOW_THAT_OPENSSL_VERIFY_PEER_EQUALS_VERIFY_NONE_IS_WRONG) then + warn <<-WARNING + !!!SECURITY WARNING!!! + +The SSL HTTP connection to: + + #{connection.address}:#{connection.port} + + !!!MAY NOT BE VERIFIED!!! + +On your platform your OpenSSL implementation is broken. + +There is no difference between the values of VERIFY_NONE and VERIFY_PEER. + +This means that attempting to verify the security of SSL connections may not +work. This exposes you to man-in-the-middle exploits, snooping on the +contents of your connection and other dangers to the security of your data. + +To disable this warning define the following constant at top-level in your +application: + + I_KNOW_THAT_OPENSSL_VERIFY_PEER_EQUALS_VERIFY_NONE_IS_WRONG = nil + + WARNING + end + + if @ca_file then + connection.ca_file = @ca_file + connection.verify_mode = OpenSSL::SSL::VERIFY_PEER + connection.verify_callback = @verify_callback if @verify_callback + end + + if @certificate and @private_key then + connection.cert = @certificate + connection.key = @private_key + end + + connection.cert_store = if @cert_store then + @cert_store + else + store = OpenSSL::X509::Store.new + store.set_default_paths + store + end + end + + ## + # Finishes all connections that existed before the given SSL parameter + # +generation+. + + def ssl_cleanup generation # :nodoc: + cleanup generation, Thread.current, @ssl_generation_key + end + + ## + # SSL version to use + + def ssl_version= ssl_version + @ssl_version = ssl_version + + reconnect_ssl + end if RUBY_VERSION > '1.9' + + ## + # Sets the HTTPS verify mode. Defaults to OpenSSL::SSL::VERIFY_PEER. + # + # Setting this to VERIFY_NONE is a VERY BAD IDEA and should NEVER be used. + # Securely transfer the correct certificate and update the default + # certificate store or set the ca file instead. + + def verify_mode= verify_mode + @verify_mode = verify_mode + + reconnect_ssl + end + + ## + # SSL verification callback. + + def verify_callback= callback + @verify_callback = callback + + reconnect_ssl + end + +end + +require 'net/http/persistent/ssl_reuse' diff --git a/bundler-1.7.2/lib/bundler/vendor/net/http/persistent/ssl_reuse.rb b/bundler-1.7.2/lib/bundler/vendor/net/http/persistent/ssl_reuse.rb new file mode 100644 index 0000000..d73aa54 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/net/http/persistent/ssl_reuse.rb @@ -0,0 +1,128 @@ +## +# This Net::HTTP subclass adds SSL session reuse and Server Name Indication +# (SNI) RFC 3546. +# +# DO NOT DEPEND UPON THIS CLASS +# +# This class is an implementation detail and is subject to change or removal +# at any time. + +class Net::HTTP::Persistent::SSLReuse < Net::HTTP + + @is_proxy_class = false + @proxy_addr = nil + @proxy_port = nil + @proxy_user = nil + @proxy_pass = nil + + def initialize address, port = nil # :nodoc: + super + + @ssl_session = nil + end + + ## + # From ruby trunk r33086 including http://redmine.ruby-lang.org/issues/5341 + + def connect # :nodoc: + D "opening connection to #{conn_address()}..." + s = timeout(@open_timeout) { TCPSocket.open(conn_address(), conn_port()) } + D "opened" + if use_ssl? + ssl_parameters = Hash.new + iv_list = instance_variables + SSL_ATTRIBUTES.each do |name| + ivname = "@#{name}".intern + if iv_list.include?(ivname) and + value = instance_variable_get(ivname) + ssl_parameters[name] = value + end + end + unless @ssl_context then + @ssl_context = OpenSSL::SSL::SSLContext.new + @ssl_context.set_params(ssl_parameters) + end + s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context) + s.sync_close = true + end + @socket = Net::BufferedIO.new(s) + @socket.read_timeout = @read_timeout + @socket.continue_timeout = @continue_timeout if + @socket.respond_to? :continue_timeout + @socket.debug_output = @debug_output + if use_ssl? + begin + if proxy? + @socket.writeline sprintf('CONNECT %s:%s HTTP/%s', + @address, @port, HTTPVersion) + @socket.writeline "Host: #{@address}:#{@port}" + if proxy_user + credential = ["#{proxy_user}:#{proxy_pass}"].pack('m') + credential.delete!("\r\n") + @socket.writeline "Proxy-Authorization: Basic #{credential}" + end + @socket.writeline '' + Net::HTTPResponse.read_new(@socket).value + end + s.session = @ssl_session if @ssl_session + # Server Name Indication (SNI) RFC 3546 + s.hostname = @address if s.respond_to? :hostname= + timeout(@open_timeout) { s.connect } + if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE + s.post_connection_check(@address) + end + @ssl_session = s.session + rescue => exception + D "Conn close because of connect error #{exception}" + @socket.close if @socket and not @socket.closed? + raise exception + end + end + on_connect + end if RUBY_VERSION > '1.9' + + ## + # From ruby_1_8_7 branch r29865 including a modified + # http://redmine.ruby-lang.org/issues/5341 + + def connect # :nodoc: + D "opening connection to #{conn_address()}..." + s = timeout(@open_timeout) { TCPSocket.open(conn_address(), conn_port()) } + D "opened" + if use_ssl? + unless @ssl_context.verify_mode + warn "warning: peer certificate won't be verified in this SSL session" + @ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE + end + s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context) + s.sync_close = true + end + @socket = Net::BufferedIO.new(s) + @socket.read_timeout = @read_timeout + @socket.debug_output = @debug_output + if use_ssl? + if proxy? + @socket.writeline sprintf('CONNECT %s:%s HTTP/%s', + @address, @port, HTTPVersion) + @socket.writeline "Host: #{@address}:#{@port}" + if proxy_user + credential = ["#{proxy_user}:#{proxy_pass}"].pack('m') + credential.delete!("\r\n") + @socket.writeline "Proxy-Authorization: Basic #{credential}" + end + @socket.writeline '' + Net::HTTPResponse.read_new(@socket).value + end + s.session = @ssl_session if @ssl_session + s.connect + if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE + s.post_connection_check(@address) + end + @ssl_session = s.session + end + on_connect + end if RUBY_VERSION < '1.9' + + private :connect + +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor.rb b/bundler-1.7.2/lib/bundler/vendor/thor.rb new file mode 100644 index 0000000..e315a38 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor.rb @@ -0,0 +1,480 @@ +require 'set' +require 'thor/base' + +class Thor # rubocop:disable ClassLength + class << self + # Allows for custom "Command" package naming. + # + # === Parameters + # name + # options + # + def package_name(name, options = {}) + @package_name = name.nil? || name == '' ? nil : name + end + + # Sets the default command when thor is executed without an explicit command to be called. + # + # ==== Parameters + # meth:: name of the default command + # + def default_command(meth = nil) + if meth + @default_command = meth == :none ? 'help' : meth.to_s + else + @default_command ||= from_superclass(:default_command, 'help') + end + end + alias_method :default_task, :default_command + + # Registers another Thor subclass as a command. + # + # ==== Parameters + # klass:: Thor subclass to register + # command:: Subcommand name to use + # usage:: Short usage for the subcommand + # description:: Description for the subcommand + def register(klass, subcommand_name, usage, description, options = {}) + if klass <= Thor::Group + desc usage, description, options + define_method(subcommand_name) { |*args| invoke(klass, args) } + else + desc usage, description, options + subcommand subcommand_name, klass + end + end + + # Defines the usage and the description of the next command. + # + # ==== Parameters + # usage + # description + # options + # + def desc(usage, description, options = {}) + if options[:for] + command = find_and_refresh_command(options[:for]) + command.usage = usage if usage + command.description = description if description + else + @usage, @desc, @hide = usage, description, options[:hide] || false + end + end + + # Defines the long description of the next command. + # + # ==== Parameters + # long description + # + def long_desc(long_description, options = {}) + if options[:for] + command = find_and_refresh_command(options[:for]) + command.long_description = long_description if long_description + else + @long_desc = long_description + end + end + + # Maps an input to a command. If you define: + # + # map "-T" => "list" + # + # Running: + # + # thor -T + # + # Will invoke the list command. + # + # ==== Parameters + # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given command. + # + def map(mappings = nil) + @map ||= from_superclass(:map, {}) + + if mappings + mappings.each do |key, value| + if key.respond_to?(:each) + key.each { |subkey| @map[subkey] = value } + else + @map[key] = value + end + end + end + + @map + end + + # Declares the options for the next command to be declared. + # + # ==== Parameters + # Hash[Symbol => Object]:: The hash key is the name of the option and the value + # is the type of the option. Can be :string, :array, :hash, :boolean, :numeric + # or :required (string). If you give a value, the type of the value is used. + # + def method_options(options = nil) + @method_options ||= {} + build_options(options, @method_options) if options + @method_options + end + + alias_method :options, :method_options + + # Adds an option to the set of method options. If :for is given as option, + # it allows you to change the options from a previous defined command. + # + # def previous_command + # # magic + # end + # + # method_option :foo => :bar, :for => :previous_command + # + # def next_command + # # magic + # end + # + # ==== Parameters + # name:: The name of the argument. + # options:: Described below. + # + # ==== Options + # :desc - Description for the argument. + # :required - If the argument is required or not. + # :default - Default value for this argument. It cannot be required and have default values. + # :aliases - Aliases for this option. + # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean. + # :banner - String to show on usage notes. + # :hide - If you want to hide this option from the help. + # + def method_option(name, options = {}) + scope = if options[:for] + find_and_refresh_command(options[:for]).options + else + method_options + end + + build_option(name, options, scope) + end + alias_method :option, :method_option + + # Prints help information for the given command. + # + # ==== Parameters + # shell + # command_name + # + def command_help(shell, command_name) + meth = normalize_command_name(command_name) + command = all_commands[meth] + handle_no_command_error(meth) unless command + + shell.say 'Usage:' + shell.say " #{banner(command)}" + shell.say + class_options_help(shell, nil => command.options.map { |_, o| o }) + if command.long_description + shell.say 'Description:' + shell.print_wrapped(command.long_description, :indent => 2) + else + shell.say command.description + end + end + alias_method :task_help, :command_help + + # Prints help information for this class. + # + # ==== Parameters + # shell + # + def help(shell, subcommand = false) + list = printable_commands(true, subcommand) + Thor::Util.thor_classes_in(self).each do |klass| + list += klass.printable_commands(false) + end + list.sort! { |a, b| a[0] <=> b[0] } + + if defined?(@package_name) && @package_name + shell.say "#{@package_name} commands:" + else + shell.say 'Commands:' + end + + shell.print_table(list, :indent => 2, :truncate => true) + shell.say + class_options_help(shell) + end + + # Returns commands ready to be printed. + def printable_commands(all = true, subcommand = false) + (all ? all_commands : commands).map do |_, command| + next if command.hidden? + item = [] + item << banner(command, false, subcommand) + item << (command.description ? "# #{command.description.gsub(/\s+/m, ' ')}" : '') + item + end.compact + end + alias_method :printable_tasks, :printable_commands + + def subcommands + @subcommands ||= from_superclass(:subcommands, []) + end + alias_method :subtasks, :subcommands + + def subcommand(subcommand, subcommand_class) + subcommands << subcommand.to_s + subcommand_class.subcommand_help subcommand + + define_method(subcommand) do |*args| + args, opts = Thor::Arguments.split(args) + args.unshift("help") if opts.include? "--help" or opts.include? "-h" + invoke subcommand_class, args, opts, :invoked_via_subcommand => true, :class_options => options + end + end + alias_method :subtask, :subcommand + + # Extend check unknown options to accept a hash of conditions. + # + # === Parameters + # options: A hash containing :only and/or :except keys + def check_unknown_options!(options = {}) + @check_unknown_options ||= {} + options.each do |key, value| + if value + @check_unknown_options[key] = Array(value) + else + @check_unknown_options.delete(key) + end + end + @check_unknown_options + end + + # Overwrite check_unknown_options? to take subcommands and options into account. + def check_unknown_options?(config) #:nodoc: + options = check_unknown_options + return false unless options + + command = config[:current_command] + return true unless command + + name = command.name + + if subcommands.include?(name) + false + elsif options[:except] + !options[:except].include?(name.to_sym) + elsif options[:only] + options[:only].include?(name.to_sym) + else + true + end + end + + # Stop parsing of options as soon as an unknown option or a regular + # argument is encountered. All remaining arguments are passed to the command. + # This is useful if you have a command that can receive arbitrary additional + # options, and where those additional options should not be handled by + # Thor. + # + # ==== Example + # + # To better understand how this is useful, let's consider a command that calls + # an external command. A user may want to pass arbitrary options and + # arguments to that command. The command itself also accepts some options, + # which should be handled by Thor. + # + # class_option "verbose", :type => :boolean + # stop_on_unknown_option! :exec + # check_unknown_options! :except => :exec + # + # desc "exec", "Run a shell command" + # def exec(*args) + # puts "diagnostic output" if options[:verbose] + # Kernel.exec(*args) + # end + # + # Here +exec+ can be called with +--verbose+ to get diagnostic output, + # e.g.: + # + # $ thor exec --verbose echo foo + # diagnostic output + # foo + # + # But if +--verbose+ is given after +echo+, it is passed to +echo+ instead: + # + # $ thor exec echo --verbose foo + # --verbose foo + # + # ==== Parameters + # Symbol ...:: A list of commands that should be affected. + def stop_on_unknown_option!(*command_names) + stop_on_unknown_option.merge(command_names) + end + + def stop_on_unknown_option?(command) #:nodoc: + command && stop_on_unknown_option.include?(command.name.to_sym) + end + + protected + def stop_on_unknown_option #:nodoc: + @stop_on_unknown_option ||= Set.new + end + + # The method responsible for dispatching given the args. + def dispatch(meth, given_args, given_opts, config) #:nodoc: # rubocop:disable MethodLength + # There is an edge case when dispatching from a subcommand. + # A problem occurs invoking the default command. This case occurs + # when arguments are passed and a default command is defined, and + # the first given_args does not match the default command. + # Thor use "help" by default so we skip that case. + # Note the call to retrieve_command_name. It's called with + # given_args.dup since that method calls args.shift. Then lookup + # the command normally. If the first item in given_args is not + # a command then use the default command. The given_args will be + # intact later since dup was used. + if config[:invoked_via_subcommand] && given_args.size >= 1 && default_command != 'help' && given_args.first != default_command + meth ||= retrieve_command_name(given_args.dup) + command = all_commands[normalize_command_name(meth)] + command ||= all_commands[normalize_command_name(default_command)] + else + meth ||= retrieve_command_name(given_args) + command = all_commands[normalize_command_name(meth)] + end + + if command + args, opts = Thor::Options.split(given_args) + if stop_on_unknown_option?(command) && !args.empty? + # given_args starts with a non-option, so we treat everything as + # ordinary arguments + args.concat opts + opts.clear + end + else + args, opts = given_args, nil + command = dynamic_command_class.new(meth) + end + + opts = given_opts || opts || [] + config.merge!(:current_command => command, :command_options => command.options) + + instance = new(args, opts, config) + yield instance if block_given? + args = instance.args + trailing = args[Range.new(arguments.size, -1)] + instance.invoke_command(command, trailing || []) + end + + # The banner for this class. You can customize it if you are invoking the + # thor class by another ways which is not the Thor::Runner. It receives + # the command that is going to be invoked and a boolean which indicates if + # the namespace should be displayed as arguments. + # + def banner(command, namespace = nil, subcommand = false) + "#{basename} #{command.formatted_usage(self, $thor_runner, subcommand)}" + end + + def baseclass #:nodoc: + Thor + end + + def dynamic_command_class #:nodoc: + Thor::DynamicCommand + end + + def create_command(meth) #:nodoc: + @usage ||= nil + @desc ||= nil + @long_desc ||= nil + + if @usage && @desc + base_class = @hide ? Thor::HiddenCommand : Thor::Command + commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options) + @usage, @desc, @long_desc, @method_options, @hide = nil + true + elsif all_commands[meth] || meth == 'method_missing' + true + else + puts "[WARNING] Attempted to create command #{meth.inspect} without usage or description. " << + 'Call desc if you want this method to be available as command or declare it inside a ' << + "no_commands{} block. Invoked from #{caller[1].inspect}." + false + end + end + alias_method :create_task, :create_command + + def initialize_added #:nodoc: + class_options.merge!(method_options) + @method_options = nil + end + + # Retrieve the command name from given args. + def retrieve_command_name(args) #:nodoc: + meth = args.first.to_s unless args.empty? + if meth && (map[meth] || meth !~ /^\-/) + args.shift + else + nil + end + end + alias_method :retrieve_task_name, :retrieve_command_name + + # receives a (possibly nil) command name and returns a name that is in + # the commands hash. In addition to normalizing aliases, this logic + # will determine if a shortened command is an unambiguous substring of + # a command or alias. + # + # +normalize_command_name+ also converts names like +animal-prison+ + # into +animal_prison+. + def normalize_command_name(meth) #:nodoc: + return default_command.to_s.gsub('-', '_') unless meth + + possibilities = find_command_possibilities(meth) + if possibilities.size > 1 + fail AmbiguousTaskError, "Ambiguous command #{meth} matches [#{possibilities.join(', ')}]" + elsif possibilities.size < 1 + meth = meth || default_command + elsif map[meth] + meth = map[meth] + else + meth = possibilities.first + end + + meth.to_s.gsub('-', '_') # treat foo-bar as foo_bar + end + alias_method :normalize_task_name, :normalize_command_name + + # this is the logic that takes the command name passed in by the user + # and determines whether it is an unambiguous substrings of a command or + # alias name. + def find_command_possibilities(meth) + len = meth.to_s.length + possibilities = all_commands.merge(map).keys.select { |n| meth == n[0, len] }.sort + unique_possibilities = possibilities.map { |k| map[k] || k }.uniq + + if possibilities.include?(meth) + [meth] + elsif unique_possibilities.size == 1 + unique_possibilities + else + possibilities + end + end + alias_method :find_task_possibilities, :find_command_possibilities + + def subcommand_help(cmd) + desc 'help [COMMAND]', 'Describe subcommands or one specific subcommand' + class_eval " + def help(command = nil, subcommand = true); super; end +" + end + alias_method :subtask_help, :subcommand_help + end + + include Thor::Base + + map HELP_MAPPINGS => :help + + desc 'help [COMMAND]', 'Describe available commands or one specific command' + def help(command = nil, subcommand = false) + command ? self.class.command_help(shell, command) : self.class.help(shell, subcommand) + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/actions.rb b/bundler-1.7.2/lib/bundler/vendor/thor/actions.rb new file mode 100644 index 0000000..617cceb --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/actions.rb @@ -0,0 +1,319 @@ +require 'fileutils' +require 'uri' +require 'thor/core_ext/io_binary_read' +require 'thor/actions/create_file' +require 'thor/actions/create_link' +require 'thor/actions/directory' +require 'thor/actions/empty_directory' +require 'thor/actions/file_manipulation' +require 'thor/actions/inject_into_file' + +class Thor + module Actions + attr_accessor :behavior + + def self.included(base) #:nodoc: + base.extend ClassMethods + end + + module ClassMethods + # Hold source paths for one Thor instance. source_paths_for_search is the + # method responsible to gather source_paths from this current class, + # inherited paths and the source root. + # + def source_paths + @_source_paths ||= [] + end + + # Stores and return the source root for this class + def source_root(path = nil) + @_source_root = path if path + @_source_root ||= nil + end + + # Returns the source paths in the following order: + # + # 1) This class source paths + # 2) Source root + # 3) Parents source paths + # + def source_paths_for_search + paths = [] + paths += source_paths + paths << source_root if source_root + paths += from_superclass(:source_paths, []) + paths + end + + # Add runtime options that help actions execution. + # + def add_runtime_options! + class_option :force, :type => :boolean, :aliases => '-f', :group => :runtime, + :desc => 'Overwrite files that already exist' + + class_option :pretend, :type => :boolean, :aliases => '-p', :group => :runtime, + :desc => 'Run but do not make any changes' + + class_option :quiet, :type => :boolean, :aliases => '-q', :group => :runtime, + :desc => 'Suppress status output' + + class_option :skip, :type => :boolean, :aliases => '-s', :group => :runtime, + :desc => 'Skip files that already exist' + end + end + + # Extends initializer to add more configuration options. + # + # ==== Configuration + # behavior:: The actions default behavior. Can be :invoke or :revoke. + # It also accepts :force, :skip and :pretend to set the behavior + # and the respective option. + # + # destination_root:: The root directory needed for some actions. + # + def initialize(args = [], options = {}, config = {}) + self.behavior = case config[:behavior].to_s + when 'force', 'skip' + _cleanup_options_and_set(options, config[:behavior]) + :invoke + when 'revoke' + :revoke + else + :invoke + end + super + self.destination_root = config[:destination_root] + end + + # Wraps an action object and call it accordingly to the thor class behavior. + # + def action(instance) #:nodoc: + if behavior == :revoke + instance.revoke! + else + instance.invoke! + end + end + + # Returns the root for this thor class (also aliased as destination root). + # + def destination_root + @destination_stack.last + end + + # Sets the root for this thor class. Relatives path are added to the + # directory where the script was invoked and expanded. + # + def destination_root=(root) + @destination_stack ||= [] + @destination_stack[0] = File.expand_path(root || '') + end + + # Returns the given path relative to the absolute root (ie, root where + # the script started). + # + def relative_to_original_destination_root(path, remove_dot = true) + path = path.dup + if path.gsub!(@destination_stack[0], '.') + remove_dot ? (path[2..-1] || '') : path + else + path + end + end + + # Holds source paths in instance so they can be manipulated. + # + def source_paths + @source_paths ||= self.class.source_paths_for_search + end + + # Receives a file or directory and search for it in the source paths. + # + def find_in_source_paths(file) # rubocop:disable MethodLength + possible_files = [file, file + TEMPLATE_EXTNAME] + relative_root = relative_to_original_destination_root(destination_root, false) + + source_paths.each do |source| + possible_files.each do |f| + source_file = File.expand_path(f, File.join(source, relative_root)) + return source_file if File.exist?(source_file) + end + end + + message = "Could not find #{file.inspect} in any of your source paths. " + + unless self.class.source_root + message << "Please invoke #{self.class.name}.source_root(PATH) with the PATH containing your templates. " + end + + if source_paths.empty? + message << 'Currently you have no source paths.' + else + message << "Your current source paths are: \n#{source_paths.join("\n")}" + end + + fail Error, message + end + + # Do something in the root or on a provided subfolder. If a relative path + # is given it's referenced from the current root. The full path is yielded + # to the block you provide. The path is set back to the previous path when + # the method exits. + # + # ==== Parameters + # dir:: the directory to move to. + # config:: give :verbose => true to log and use padding. + # + def inside(dir = '', config = {}, &block) + verbose = config.fetch(:verbose, false) + pretend = options[:pretend] + + say_status :inside, dir, verbose + shell.padding += 1 if verbose + @destination_stack.push File.expand_path(dir, destination_root) + + # If the directory doesnt exist and we're not pretending + if !File.exist?(destination_root) && !pretend + FileUtils.mkdir_p(destination_root) + end + + if pretend + # In pretend mode, just yield down to the block + block.arity == 1 ? yield(destination_root) : yield + else + FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield } + end + + @destination_stack.pop + shell.padding -= 1 if verbose + end + + # Goes to the root and execute the given block. + # + def in_root + inside(@destination_stack.first) { yield } + end + + # Loads an external file and execute it in the instance binding. + # + # ==== Parameters + # path:: The path to the file to execute. Can be a web address or + # a relative path from the source root. + # + # ==== Examples + # + # apply "http://gist.github.com/103208" + # + # apply "recipes/jquery.rb" + # + def apply(path, config = {}) + verbose = config.fetch(:verbose, true) + is_uri = path =~ %r{^https?\://} + path = find_in_source_paths(path) unless is_uri + + say_status :apply, path, verbose + shell.padding += 1 if verbose + + if is_uri + contents = open(path, 'Accept' => 'application/x-thor-template') { |io| io.read } + else + contents = open(path) { |io| io.read } + end + + instance_eval(contents, path) + shell.padding -= 1 if verbose + end + + # Executes a command returning the contents of the command. + # + # ==== Parameters + # command:: the command to be executed. + # config:: give :verbose => false to not log the status, :capture => true to hide to output. Specify :with + # to append an executable to command execution. + # + # ==== Example + # + # inside('vendor') do + # run('ln -s ~/edge rails') + # end + # + def run(command, config = {}) + return unless behavior == :invoke + + destination = relative_to_original_destination_root(destination_root, false) + desc = "#{command} from #{destination.inspect}" + + if config[:with] + desc = "#{File.basename(config[:with].to_s)} #{desc}" + command = "#{config[:with]} #{command}" + end + + say_status :run, desc, config.fetch(:verbose, true) + + unless options[:pretend] + config[:capture] ? `#{command}` : system("#{command}") + end + end + + # Executes a ruby script (taking into account WIN32 platform quirks). + # + # ==== Parameters + # command:: the command to be executed. + # config:: give :verbose => false to not log the status. + # + def run_ruby_script(command, config = {}) + return unless behavior == :invoke + run command, config.merge(:with => Thor::Util.ruby_command) + end + + # Run a thor command. A hash of options can be given and it's converted to + # switches. + # + # ==== Parameters + # command:: the command to be invoked + # args:: arguments to the command + # config:: give :verbose => false to not log the status, :capture => true to hide to output. + # Other options are given as parameter to Thor. + # + # + # ==== Examples + # + # thor :install, "http://gist.github.com/103208" + # #=> thor install http://gist.github.com/103208 + # + # thor :list, :all => true, :substring => 'rails' + # #=> thor list --all --substring=rails + # + def thor(command, *args) + config = args.last.is_a?(Hash) ? args.pop : {} + verbose = config.key?(:verbose) ? config.delete(:verbose) : true + pretend = config.key?(:pretend) ? config.delete(:pretend) : false + capture = config.key?(:capture) ? config.delete(:capture) : false + + args.unshift(command) + args.push Thor::Options.to_switches(config) + command = args.join(' ').strip + + run command, :with => :thor, :verbose => verbose, :pretend => pretend, :capture => capture + end + + protected + + # Allow current root to be shared between invocations. + # + def _shared_configuration #:nodoc: + super.merge!(:destination_root => destination_root) + end + + def _cleanup_options_and_set(options, key) #:nodoc: + case options + when Array + %w(--force -f --skip -s).each { |i| options.delete(i) } + options << "--#{key}" + when Hash + [:force, :skip, 'force', 'skip'].each { |i| options.delete(i) } + options.merge!(key => true) + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/actions/create_file.rb b/bundler-1.7.2/lib/bundler/vendor/thor/actions/create_file.rb new file mode 100644 index 0000000..0436e67 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/actions/create_file.rb @@ -0,0 +1,103 @@ +require 'thor/actions/empty_directory' + +class Thor + module Actions + # Create a new file relative to the destination root with the given data, + # which is the return value of a block or a data string. + # + # ==== Parameters + # destination:: the relative path to the destination root. + # data:: the data to append to the file. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # create_file "lib/fun_party.rb" do + # hostname = ask("What is the virtual hostname I should use?") + # "vhost.name = #{hostname}" + # end + # + # create_file "config/apache.conf", "your apache config" + # + def create_file(destination, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + data = args.first + action CreateFile.new(self, destination, block || data.to_s, config) + end + alias_method :add_file, :create_file + + # CreateFile is a subset of Template, which instead of rendering a file with + # ERB, it gets the content from the user. + # + class CreateFile < EmptyDirectory #:nodoc: + attr_reader :data + + def initialize(base, destination, data, config = {}) + @data = data + super(base, destination, config) + end + + # Checks if the content of the file at the destination is identical to the rendered result. + # + # ==== Returns + # Boolean:: true if it is identical, false otherwise. + # + def identical? + exists? && File.binread(destination) == render + end + + # Holds the content to be added to the file. + # + def render + @render ||= if data.is_a?(Proc) + data.call + else + data + end + end + + def invoke! + invoke_with_conflict_check do + FileUtils.mkdir_p(File.dirname(destination)) + File.open(destination, 'wb') { |f| f.write render } + end + given_destination + end + + protected + + # Now on conflict we check if the file is identical or not. + # + def on_conflict_behavior(&block) + if identical? + say_status :identical, :blue + else + options = base.options.merge(config) + force_or_skip_or_conflict(options[:force], options[:skip], &block) + end + end + + # If force is true, run the action, otherwise check if it's not being + # skipped. If both are false, show the file_collision menu, if the menu + # returns true, force it, otherwise skip. + # + def force_or_skip_or_conflict(force, skip, &block) + if force + say_status :force, :yellow + block.call unless pretend? + elsif skip + say_status :skip, :yellow + else + say_status :conflict, :red + force_or_skip_or_conflict(force_on_collision?, true, &block) + end + end + + # Shows the file collision menu to the user and gets the result. + # + def force_on_collision? + base.shell.file_collision(destination) { render } + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/actions/create_link.rb b/bundler-1.7.2/lib/bundler/vendor/thor/actions/create_link.rb new file mode 100644 index 0000000..799e5a2 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/actions/create_link.rb @@ -0,0 +1,59 @@ +require 'thor/actions/create_file' + +class Thor + module Actions + # Create a new file relative to the destination root from the given source. + # + # ==== Parameters + # destination:: the relative path to the destination root. + # source:: the relative path to the source root. + # config:: give :verbose => false to not log the status. + # :: give :symbolic => false for hard link. + # + # ==== Examples + # + # create_link "config/apache.conf", "/etc/apache.conf" + # + def create_link(destination, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + source = args.first + action CreateLink.new(self, destination, source, config) + end + alias_method :add_link, :create_link + + # CreateLink is a subset of CreateFile, which instead of taking a block of + # data, just takes a source string from the user. + # + class CreateLink < CreateFile #:nodoc: + attr_reader :data + + # Checks if the content of the file at the destination is identical to the rendered result. + # + # ==== Returns + # Boolean:: true if it is identical, false otherwise. + # + def identical? + exists? && File.identical?(render, destination) + end + + def invoke! + invoke_with_conflict_check do + FileUtils.mkdir_p(File.dirname(destination)) + # Create a symlink by default + config[:symbolic] = true if config[:symbolic].nil? + File.unlink(destination) if exists? + if config[:symbolic] + File.symlink(render, destination) + else + File.link(render, destination) + end + end + given_destination + end + + def exists? + super || File.symlink?(destination) + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/actions/directory.rb b/bundler-1.7.2/lib/bundler/vendor/thor/actions/directory.rb new file mode 100644 index 0000000..32d9c8d --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/actions/directory.rb @@ -0,0 +1,118 @@ +require 'thor/actions/empty_directory' + +class Thor + module Actions + # Copies recursively the files from source directory to root directory. + # If any of the files finishes with .tt, it's considered to be a template + # and is placed in the destination without the extension .tt. If any + # empty directory is found, it's copied and all .empty_directory files are + # ignored. If any file name is wrapped within % signs, the text within + # the % signs will be executed as a method and replaced with the returned + # value. Let's suppose a doc directory with the following files: + # + # doc/ + # components/.empty_directory + # README + # rdoc.rb.tt + # %app_name%.rb + # + # When invoked as: + # + # directory "doc" + # + # It will create a doc directory in the destination with the following + # files (assuming that the `app_name` method returns the value "blog"): + # + # doc/ + # components/ + # README + # rdoc.rb + # blog.rb + # + # Encoded path note: Since Thor internals use Object#respond_to? to check if it can + # expand %something%, this `something` should be a public method in the class calling + # #directory. If a method is private, Thor stack raises PrivateMethodEncodedError. + # + # ==== Parameters + # source:: the relative path to the source root. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # If :recursive => false, does not look for paths recursively. + # If :mode => :preserve, preserve the file mode from the source. + # If :exclude_pattern => /regexp/, prevents copying files that match that regexp. + # + # ==== Examples + # + # directory "doc" + # directory "doc", "docs", :recursive => false + # + def directory(source, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + destination = args.first || source + action Directory.new(self, source, destination || source, config, &block) + end + + class Directory < EmptyDirectory #:nodoc: + attr_reader :source + + def initialize(base, source, destination = nil, config = {}, &block) + @source = File.expand_path(base.find_in_source_paths(source.to_s)) + @block = block + super(base, destination, {:recursive => true}.merge(config)) + end + + def invoke! + base.empty_directory given_destination, config + execute! + end + + def revoke! + execute! + end + + protected + + def execute! # rubocop:disable MethodLength + lookup = Util.escape_globs(source) + lookup = config[:recursive] ? File.join(lookup, '**') : lookup + lookup = file_level_lookup(lookup) + + files(lookup).sort.each do |file_source| + next if File.directory?(file_source) + next if config[:exclude_pattern] && file_source.match(config[:exclude_pattern]) + file_destination = File.join(given_destination, file_source.gsub(source, '.')) + file_destination.gsub!('/./', '/') + + case file_source + when /\.empty_directory$/ + dirname = File.dirname(file_destination).gsub(/\/\.$/, '') + next if dirname == given_destination + base.empty_directory(dirname, config) + when /#{TEMPLATE_EXTNAME}$/ + base.template(file_source, file_destination[0..-4], config, &@block) + else + base.copy_file(file_source, file_destination, config, &@block) + end + end + end + + if RUBY_VERSION < '2.0' + def file_level_lookup(previous_lookup) + File.join(previous_lookup, '{*,.[a-z]*}') + end + + def files(lookup) + Dir[lookup] + end + else + def file_level_lookup(previous_lookup) + File.join(previous_lookup, '*') + end + + def files(lookup) + Dir.glob(lookup, File::FNM_DOTMATCH) + end + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/actions/empty_directory.rb b/bundler-1.7.2/lib/bundler/vendor/thor/actions/empty_directory.rb new file mode 100644 index 0000000..281d8fb --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/actions/empty_directory.rb @@ -0,0 +1,135 @@ +class Thor + module Actions + # Creates an empty directory. + # + # ==== Parameters + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # empty_directory "doc" + # + def empty_directory(destination, config = {}) + action EmptyDirectory.new(self, destination, config) + end + + # Class which holds create directory logic. This is the base class for + # other actions like create_file and directory. + # + # This implementation is based in Templater actions, created by Jonas Nicklas + # and Michael S. Klishin under MIT LICENSE. + # + class EmptyDirectory #:nodoc: + attr_reader :base, :destination, :given_destination, :relative_destination, :config + + # Initializes given the source and destination. + # + # ==== Parameters + # base:: A Thor::Base instance + # source:: Relative path to the source of this file + # destination:: Relative path to the destination of this file + # config:: give :verbose => false to not log the status. + # + def initialize(base, destination, config = {}) + @base, @config = base, {:verbose => true}.merge(config) + self.destination = destination + end + + # Checks if the destination file already exists. + # + # ==== Returns + # Boolean:: true if the file exists, false otherwise. + # + def exists? + ::File.exist?(destination) + end + + def invoke! + invoke_with_conflict_check do + ::FileUtils.mkdir_p(destination) + end + end + + def revoke! + say_status :remove, :red + ::FileUtils.rm_rf(destination) if !pretend? && exists? + given_destination + end + + protected + + # Shortcut for pretend. + # + def pretend? + base.options[:pretend] + end + + # Sets the absolute destination value from a relative destination value. + # It also stores the given and relative destination. Let's suppose our + # script is being executed on "dest", it sets the destination root to + # "dest". The destination, given_destination and relative_destination + # are related in the following way: + # + # inside "bar" do + # empty_directory "baz" + # end + # + # destination #=> dest/bar/baz + # relative_destination #=> bar/baz + # given_destination #=> baz + # + def destination=(destination) + if destination + @given_destination = convert_encoded_instructions(destination.to_s) + @destination = ::File.expand_path(@given_destination, base.destination_root) + @relative_destination = base.relative_to_original_destination_root(@destination) + end + end + + # Filenames in the encoded form are converted. If you have a file: + # + # %file_name%.rb + # + # It calls #file_name from the base and replaces %-string with the + # return value (should be String) of #file_name: + # + # user.rb + # + # The method referenced can be either public or private. + # + def convert_encoded_instructions(filename) + filename.gsub(/%(.*?)%/) do |initial_string| + method = $1.strip + base.respond_to?(method, true) ? base.send(method) : initial_string + end + end + + # Receives a hash of options and just execute the block if some + # conditions are met. + # + def invoke_with_conflict_check(&block) + if exists? + on_conflict_behavior(&block) + else + say_status :create, :green + block.call unless pretend? + end + + destination + end + + # What to do when the destination file already exists. + # + def on_conflict_behavior(&block) + say_status :exist, :blue + end + + # Shortcut to say_status shell method. + # + def say_status(status, color) + base.shell.say_status status, relative_destination, color if config[:verbose] + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/actions/file_manipulation.rb b/bundler-1.7.2/lib/bundler/vendor/thor/actions/file_manipulation.rb new file mode 100644 index 0000000..6ccc345 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/actions/file_manipulation.rb @@ -0,0 +1,316 @@ +require 'erb' +require 'open-uri' + +class Thor + module Actions + # Copies the file from the relative source to the relative destination. If + # the destination is not given it's assumed to be equal to the source. + # + # ==== Parameters + # source:: the relative path to the source root. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status, and + # :mode => :preserve, to preserve the file mode from the source. + + # + # ==== Examples + # + # copy_file "README", "doc/README" + # + # copy_file "doc/README" + # + def copy_file(source, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + destination = args.first || source + source = File.expand_path(find_in_source_paths(source.to_s)) + + create_file destination, nil, config do + content = File.binread(source) + content = block.call(content) if block + content + end + if config[:mode] == :preserve + mode = File.stat(source).mode + chmod(destination, mode, config) + end + end + + # Links the file from the relative source to the relative destination. If + # the destination is not given it's assumed to be equal to the source. + # + # ==== Parameters + # source:: the relative path to the source root. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # link_file "README", "doc/README" + # + # link_file "doc/README" + # + def link_file(source, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + destination = args.first || source + source = File.expand_path(find_in_source_paths(source.to_s)) + + create_link destination, source, config + end + + # Gets the content at the given address and places it at the given relative + # destination. If a block is given instead of destination, the content of + # the url is yielded and used as location. + # + # ==== Parameters + # source:: the address of the given content. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # get "http://gist.github.com/103208", "doc/README" + # + # get "http://gist.github.com/103208" do |content| + # content.split("\n").first + # end + # + def get(source, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + destination = args.first + + source = File.expand_path(find_in_source_paths(source.to_s)) unless source =~ %r{^https?\://} + render = open(source) { |input| input.binmode.read } + + destination ||= if block_given? + block.arity == 1 ? block.call(render) : block.call + else + File.basename(source) + end + + create_file destination, render, config + end + + # Gets an ERB template at the relative source, executes it and makes a copy + # at the relative destination. If the destination is not given it's assumed + # to be equal to the source removing .tt from the filename. + # + # ==== Parameters + # source:: the relative path to the source root. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # template "README", "doc/README" + # + # template "doc/README" + # + def template(source, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + destination = args.first || source.sub(/#{TEMPLATE_EXTNAME}$/, '') + + source = File.expand_path(find_in_source_paths(source.to_s)) + context = instance_eval('binding') + + create_file destination, nil, config do + content = ERB.new(::File.binread(source), nil, '-', '@output_buffer').result(context) + content = block.call(content) if block + content + end + end + + # Changes the mode of the given file or directory. + # + # ==== Parameters + # mode:: the file mode + # path:: the name of the file to change mode + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # chmod "script/server", 0755 + # + def chmod(path, mode, config = {}) + return unless behavior == :invoke + path = File.expand_path(path, destination_root) + say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true) + FileUtils.chmod_R(mode, path) unless options[:pretend] + end + + # Prepend text to a file. Since it depends on insert_into_file, it's reversible. + # + # ==== Parameters + # path:: path of the file to be changed + # data:: the data to prepend to the file, can be also given as a block. + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # prepend_to_file 'config/environments/test.rb', 'config.gem "rspec"' + # + # prepend_to_file 'config/environments/test.rb' do + # 'config.gem "rspec"' + # end + # + def prepend_to_file(path, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + config.merge!(:after => /\A/) + insert_into_file(path, *(args << config), &block) + end + alias_method :prepend_file, :prepend_to_file + + # Append text to a file. Since it depends on insert_into_file, it's reversible. + # + # ==== Parameters + # path:: path of the file to be changed + # data:: the data to append to the file, can be also given as a block. + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # append_to_file 'config/environments/test.rb', 'config.gem "rspec"' + # + # append_to_file 'config/environments/test.rb' do + # 'config.gem "rspec"' + # end + # + def append_to_file(path, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + config.merge!(:before => /\z/) + insert_into_file(path, *(args << config), &block) + end + alias_method :append_file, :append_to_file + + # Injects text right after the class definition. Since it depends on + # insert_into_file, it's reversible. + # + # ==== Parameters + # path:: path of the file to be changed + # klass:: the class to be manipulated + # data:: the data to append to the class, can be also given as a block. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # inject_into_class "app/controllers/application_controller.rb", ApplicationController, " filter_parameter :password\n" + # + # inject_into_class "app/controllers/application_controller.rb", ApplicationController do + # " filter_parameter :password\n" + # end + # + def inject_into_class(path, klass, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + config.merge!(:after => /class #{klass}\n|class #{klass} .*\n/) + insert_into_file(path, *(args << config), &block) + end + + # Run a regular expression replacement on a file. + # + # ==== Parameters + # path:: path of the file to be changed + # flag:: the regexp or string to be replaced + # replacement:: the replacement, can be also given as a block + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1' + # + # gsub_file 'README', /rake/, :green do |match| + # match << " no more. Use thor!" + # end + # + def gsub_file(path, flag, *args, &block) + return unless behavior == :invoke + config = args.last.is_a?(Hash) ? args.pop : {} + + path = File.expand_path(path, destination_root) + say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true) + + unless options[:pretend] + content = File.binread(path) + content.gsub!(flag, *args, &block) + File.open(path, 'wb') { |file| file.write(content) } + end + end + + # Uncomment all lines matching a given regex. It will leave the space + # which existed before the comment hash in tact but will remove any spacing + # between the comment hash and the beginning of the line. + # + # ==== Parameters + # path:: path of the file to be changed + # flag:: the regexp or string used to decide which lines to uncomment + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # uncomment_lines 'config/initializers/session_store.rb', /active_record/ + # + def uncomment_lines(path, flag, *args) + flag = flag.respond_to?(:source) ? flag.source : flag + + gsub_file(path, /^(\s*)#[[:blank:]]*(.*#{flag})/, '\1\2', *args) + end + + # Comment all lines matching a given regex. It will leave the space + # which existed before the beginning of the line in tact and will insert + # a single space after the comment hash. + # + # ==== Parameters + # path:: path of the file to be changed + # flag:: the regexp or string used to decide which lines to comment + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # comment_lines 'config/initializers/session_store.rb', /cookie_store/ + # + def comment_lines(path, flag, *args) + flag = flag.respond_to?(:source) ? flag.source : flag + + gsub_file(path, /^(\s*)([^#|\n]*#{flag})/, '\1# \2', *args) + end + + # Removes a file at the given location. + # + # ==== Parameters + # path:: path of the file to be changed + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # remove_file 'README' + # remove_file 'app/controllers/application_controller.rb' + # + def remove_file(path, config = {}) + return unless behavior == :invoke + path = File.expand_path(path, destination_root) + + say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true) + ::FileUtils.rm_rf(path) if !options[:pretend] && File.exist?(path) + end + alias_method :remove_dir, :remove_file + + attr_accessor :output_buffer + private :output_buffer, :output_buffer= + + private + + def concat(string) + @output_buffer.concat(string) + end + + def capture(*args, &block) + with_output_buffer { block.call(*args) } + end + + def with_output_buffer(buf = '') #:nodoc: + self.output_buffer, old_buffer = buf, output_buffer + yield + output_buffer + ensure + self.output_buffer = old_buffer + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/actions/inject_into_file.rb b/bundler-1.7.2/lib/bundler/vendor/thor/actions/inject_into_file.rb new file mode 100644 index 0000000..3cdd18b --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/actions/inject_into_file.rb @@ -0,0 +1,107 @@ +require 'thor/actions/empty_directory' + +class Thor + module Actions + # Injects the given content into a file. Different from gsub_file, this + # method is reversible. + # + # ==== Parameters + # destination:: Relative path to the destination root + # data:: Data to add to the file. Can be given as a block. + # config:: give :verbose => false to not log the status and the flag + # for injection (:after or :before) or :force => true for + # insert two or more times the same content. + # + # ==== Examples + # + # insert_into_file "config/environment.rb", "config.gem :thor", :after => "Rails::Initializer.run do |config|\n" + # + # insert_into_file "config/environment.rb", :after => "Rails::Initializer.run do |config|\n" do + # gems = ask "Which gems would you like to add?" + # gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n") + # end + # + def insert_into_file(destination, *args, &block) + if block_given? + data, config = block, args.shift + else + data, config = args.shift, args.shift + end + action InjectIntoFile.new(self, destination, data, config) + end + alias_method :inject_into_file, :insert_into_file + + class InjectIntoFile < EmptyDirectory #:nodoc: + attr_reader :replacement, :flag, :behavior + + def initialize(base, destination, data, config) + super(base, destination, {:verbose => true}.merge(config)) + + @behavior, @flag = if @config.key?(:after) + [:after, @config.delete(:after)] + else + [:before, @config.delete(:before)] + end + + @replacement = data.is_a?(Proc) ? data.call : data + @flag = Regexp.escape(@flag) unless @flag.is_a?(Regexp) + end + + def invoke! + say_status :invoke + + content = if @behavior == :after + '\0' + replacement + else + replacement + '\0' + end + + replace!(/#{flag}/, content, config[:force]) + end + + def revoke! + say_status :revoke + + regexp = if @behavior == :after + content = '\1\2' + /(#{flag})(.*)(#{Regexp.escape(replacement)})/m + else + content = '\2\3' + /(#{Regexp.escape(replacement)})(.*)(#{flag})/m + end + + replace!(regexp, content, true) + end + + protected + + def say_status(behavior) + status = if behavior == :invoke + if flag == /\A/ + :prepend + elsif flag == /\z/ + :append + else + :insert + end + else + :subtract + end + + super(status, config[:verbose]) + end + + # Adds the content to the file. + # + def replace!(regexp, string, force) + unless base.options[:pretend] + content = File.binread(destination) + if force || !content.include?(replacement) + content.gsub!(regexp, string) + File.open(destination, 'wb') { |file| file.write(content) } + end + end + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/base.rb b/bundler-1.7.2/lib/bundler/vendor/thor/base.rb new file mode 100644 index 0000000..d42ff4d --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/base.rb @@ -0,0 +1,656 @@ +require 'thor/command' +require 'thor/core_ext/hash_with_indifferent_access' +require 'thor/core_ext/ordered_hash' +require 'thor/error' +require 'thor/invocation' +require 'thor/parser' +require 'thor/shell' +require 'thor/line_editor' +require 'thor/util' + +class Thor + autoload :Actions, 'thor/actions' + autoload :RakeCompat, 'thor/rake_compat' + autoload :Group, 'thor/group' + + # Shortcuts for help. + HELP_MAPPINGS = %w(-h -? --help -D) + + # Thor methods that should not be overwritten by the user. + THOR_RESERVED_WORDS = %w(invoke shell options behavior root destination_root relative_root + action add_file create_file in_root inside run run_ruby_script) + + TEMPLATE_EXTNAME = '.tt' + + module Base + attr_accessor :options, :parent_options, :args + + # It receives arguments in an Array and two hashes, one for options and + # other for configuration. + # + # Notice that it does not check if all required arguments were supplied. + # It should be done by the parser. + # + # ==== Parameters + # args:: An array of objects. The objects are applied to their + # respective accessors declared with argument. + # + # options:: An options hash that will be available as self.options. + # The hash given is converted to a hash with indifferent + # access, magic predicates (options.skip?) and then frozen. + # + # config:: Configuration for this Thor class. + # + def initialize(args = [], local_options = {}, config = {}) # rubocop:disable MethodLength + parse_options = self.class.class_options + + # The start method splits inbound arguments at the first argument + # that looks like an option (starts with - or --). It then calls + # new, passing in the two halves of the arguments Array as the + # first two parameters. + + command_options = config.delete(:command_options) # hook for start + parse_options = parse_options.merge(command_options) if command_options + if local_options.is_a?(Array) + array_options, hash_options = local_options, {} + else + # Handle the case where the class was explicitly instantiated + # with pre-parsed options. + array_options, hash_options = [], local_options + end + + # Let Thor::Options parse the options first, so it can remove + # declared options from the array. This will leave us with + # a list of arguments that weren't declared. + stop_on_unknown = self.class.stop_on_unknown_option? config[:current_command] + opts = Thor::Options.new(parse_options, hash_options, stop_on_unknown) + self.options = opts.parse(array_options) + self.options = config[:class_options].merge(options) if config[:class_options] + + # If unknown options are disallowed, make sure that none of the + # remaining arguments looks like an option. + opts.check_unknown! if self.class.check_unknown_options?(config) + + # Add the remaining arguments from the options parser to the + # arguments passed in to initialize. Then remove any positional + # arguments declared using #argument (this is primarily used + # by Thor::Group). Tis will leave us with the remaining + # positional arguments. + to_parse = args + to_parse += opts.remaining unless self.class.strict_args_position?(config) + + thor_args = Thor::Arguments.new(self.class.arguments) + thor_args.parse(to_parse).each { |k, v| __send__("#{k}=", v) } + @args = thor_args.remaining + end + + class << self + def included(base) #:nodoc: + base.extend ClassMethods + base.send :include, Invocation + base.send :include, Shell + end + + # Returns the classes that inherits from Thor or Thor::Group. + # + # ==== Returns + # Array[Class] + # + def subclasses + @subclasses ||= [] + end + + # Returns the files where the subclasses are kept. + # + # ==== Returns + # Hash[path => Class] + # + def subclass_files + @subclass_files ||= Hash.new { |h, k| h[k] = [] } + end + + # Whenever a class inherits from Thor or Thor::Group, we should track the + # class and the file on Thor::Base. This is the method responsible for it. + # + def register_klass_file(klass) #:nodoc: + file = caller[1].match(/(.*):\d+/)[1] + Thor::Base.subclasses << klass unless Thor::Base.subclasses.include?(klass) + + file_subclasses = Thor::Base.subclass_files[File.expand_path(file)] + file_subclasses << klass unless file_subclasses.include?(klass) + end + end + + module ClassMethods + def attr_reader(*) #:nodoc: + no_commands { super } + end + + def attr_writer(*) #:nodoc: + no_commands { super } + end + + def attr_accessor(*) #:nodoc: + no_commands { super } + end + + # If you want to raise an error for unknown options, call check_unknown_options! + # This is disabled by default to allow dynamic invocations. + def check_unknown_options! + @check_unknown_options = true + end + + def check_unknown_options #:nodoc: + @check_unknown_options ||= from_superclass(:check_unknown_options, false) + end + + def check_unknown_options?(config) #:nodoc: + !!check_unknown_options + end + + # If true, option parsing is suspended as soon as an unknown option or a + # regular argument is encountered. All remaining arguments are passed to + # the command as regular arguments. + def stop_on_unknown_option?(command_name) #:nodoc: + false + end + + # If you want only strict string args (useful when cascading thor classes), + # call strict_args_position! This is disabled by default to allow dynamic + # invocations. + def strict_args_position! + @strict_args_position = true + end + + def strict_args_position #:nodoc: + @strict_args_position ||= from_superclass(:strict_args_position, false) + end + + def strict_args_position?(config) #:nodoc: + !!strict_args_position + end + + # Adds an argument to the class and creates an attr_accessor for it. + # + # Arguments are different from options in several aspects. The first one + # is how they are parsed from the command line, arguments are retrieved + # from position: + # + # thor command NAME + # + # Instead of: + # + # thor command --name=NAME + # + # Besides, arguments are used inside your code as an accessor (self.argument), + # while options are all kept in a hash (self.options). + # + # Finally, arguments cannot have type :default or :boolean but can be + # optional (supplying :optional => :true or :required => false), although + # you cannot have a required argument after a non-required argument. If you + # try it, an error is raised. + # + # ==== Parameters + # name:: The name of the argument. + # options:: Described below. + # + # ==== Options + # :desc - Description for the argument. + # :required - If the argument is required or not. + # :optional - If the argument is optional or not. + # :type - The type of the argument, can be :string, :hash, :array, :numeric. + # :default - Default value for this argument. It cannot be required and have default values. + # :banner - String to show on usage notes. + # + # ==== Errors + # ArgumentError:: Raised if you supply a required argument after a non required one. + # + def argument(name, options = {}) # rubocop:disable MethodLength + is_thor_reserved_word?(name, :argument) + no_commands { attr_accessor name } + + required = if options.key?(:optional) + !options[:optional] + elsif options.key?(:required) + options[:required] + else + options[:default].nil? + end + + remove_argument name + + arguments.each do |argument| + next if argument.required? + fail ArgumentError, "You cannot have #{name.to_s.inspect} as required argument after " << + "the non-required argument #{argument.human_name.inspect}." + end if required + + options[:required] = required + + arguments << Thor::Argument.new(name, options) + end + + # Returns this class arguments, looking up in the ancestors chain. + # + # ==== Returns + # Array[Thor::Argument] + # + def arguments + @arguments ||= from_superclass(:arguments, []) + end + + # Adds a bunch of options to the set of class options. + # + # class_options :foo => false, :bar => :required, :baz => :string + # + # If you prefer more detailed declaration, check class_option. + # + # ==== Parameters + # Hash[Symbol => Object] + # + def class_options(options = nil) + @class_options ||= from_superclass(:class_options, {}) + build_options(options, @class_options) if options + @class_options + end + + # Adds an option to the set of class options + # + # ==== Parameters + # name:: The name of the argument. + # options:: Described below. + # + # ==== Options + # :desc:: -- Description for the argument. + # :required:: -- If the argument is required or not. + # :default:: -- Default value for this argument. + # :group:: -- The group for this options. Use by class options to output options in different levels. + # :aliases:: -- Aliases for this option. Note: Thor follows a convention of one-dash-one-letter options. Thus aliases like "-something" wouldn't be parsed; use either "\--something" or "-s" instead. + # :type:: -- The type of the argument, can be :string, :hash, :array, :numeric or :boolean. + # :banner:: -- String to show on usage notes. + # :hide:: -- If you want to hide this option from the help. + # + def class_option(name, options = {}) + build_option(name, options, class_options) + end + + # Removes a previous defined argument. If :undefine is given, undefine + # accessors as well. + # + # ==== Parameters + # names:: Arguments to be removed + # + # ==== Examples + # + # remove_argument :foo + # remove_argument :foo, :bar, :baz, :undefine => true + # + def remove_argument(*names) + options = names.last.is_a?(Hash) ? names.pop : {} + + names.each do |name| + arguments.delete_if { |a| a.name == name.to_s } + undef_method name, "#{name}=" if options[:undefine] + end + end + + # Removes a previous defined class option. + # + # ==== Parameters + # names:: Class options to be removed + # + # ==== Examples + # + # remove_class_option :foo + # remove_class_option :foo, :bar, :baz + # + def remove_class_option(*names) + names.each do |name| + class_options.delete(name) + end + end + + # Defines the group. This is used when thor list is invoked so you can specify + # that only commands from a pre-defined group will be shown. Defaults to standard. + # + # ==== Parameters + # name + # + def group(name = nil) + if name + @group = name.to_s + else + @group ||= from_superclass(:group, 'standard') + end + end + + # Returns the commands for this Thor class. + # + # ==== Returns + # OrderedHash:: An ordered hash with commands names as keys and Thor::Command + # objects as values. + # + def commands + @commands ||= Thor::CoreExt::OrderedHash.new + end + alias_method :tasks, :commands + + # Returns the commands for this Thor class and all subclasses. + # + # ==== Returns + # OrderedHash:: An ordered hash with commands names as keys and Thor::Command + # objects as values. + # + def all_commands + @all_commands ||= from_superclass(:all_commands, Thor::CoreExt::OrderedHash.new) + @all_commands.merge(commands) + end + alias_method :all_tasks, :all_commands + + # Removes a given command from this Thor class. This is usually done if you + # are inheriting from another class and don't want it to be available + # anymore. + # + # By default it only remove the mapping to the command. But you can supply + # :undefine => true to undefine the method from the class as well. + # + # ==== Parameters + # name:: The name of the command to be removed + # options:: You can give :undefine => true if you want commands the method + # to be undefined from the class as well. + # + def remove_command(*names) + options = names.last.is_a?(Hash) ? names.pop : {} + + names.each do |name| + commands.delete(name.to_s) + all_commands.delete(name.to_s) + undef_method name if options[:undefine] + end + end + alias_method :remove_task, :remove_command + + # All methods defined inside the given block are not added as commands. + # + # So you can do: + # + # class MyScript < Thor + # no_commands do + # def this_is_not_a_command + # end + # end + # end + # + # You can also add the method and remove it from the command list: + # + # class MyScript < Thor + # def this_is_not_a_command + # end + # remove_command :this_is_not_a_command + # end + # + def no_commands + @no_commands = true + yield + ensure + @no_commands = false + end + alias_method :no_tasks, :no_commands + + # Sets the namespace for the Thor or Thor::Group class. By default the + # namespace is retrieved from the class name. If your Thor class is named + # Scripts::MyScript, the help method, for example, will be called as: + # + # thor scripts:my_script -h + # + # If you change the namespace: + # + # namespace :my_scripts + # + # You change how your commands are invoked: + # + # thor my_scripts -h + # + # Finally, if you change your namespace to default: + # + # namespace :default + # + # Your commands can be invoked with a shortcut. Instead of: + # + # thor :my_command + # + def namespace(name = nil) + if name + @namespace = name.to_s + else + @namespace ||= Thor::Util.namespace_from_thor_class(self) + end + end + + # Parses the command and options from the given args, instantiate the class + # and invoke the command. This method is used when the arguments must be parsed + # from an array. If you are inside Ruby and want to use a Thor class, you + # can simply initialize it: + # + # script = MyScript.new(args, options, config) + # script.invoke(:command, first_arg, second_arg, third_arg) + # + def start(given_args = ARGV, config = {}) + config[:shell] ||= Thor::Base.shell.new + dispatch(nil, given_args.dup, nil, config) + rescue Thor::Error => e + config[:debug] || ENV['THOR_DEBUG'] == '1' ? (raise e) : config[:shell].error(e.message) + exit(1) if exit_on_failure? + rescue Errno::EPIPE + # This happens if a thor command is piped to something like `head`, + # which closes the pipe when it's done reading. This will also + # mean that if the pipe is closed, further unnecessary + # computation will not occur. + exit(0) + end + + # Allows to use private methods from parent in child classes as commands. + # + # ==== Parameters + # names:: Method names to be used as commands + # + # ==== Examples + # + # public_command :foo + # public_command :foo, :bar, :baz + # + def public_command(*names) + names.each do |name| + class_eval "def #{name}(*); super end" + end + end + alias_method :public_task, :public_command + + def handle_no_command_error(command, has_namespace = $thor_runner) #:nodoc: + if has_namespace + fail UndefinedCommandError, "Could not find command #{command.inspect} in #{namespace.inspect} namespace." + else + fail UndefinedCommandError, "Could not find command #{command.inspect}." + end + end + alias_method :handle_no_task_error, :handle_no_command_error + + def handle_argument_error(command, error, args, arity) #:nodoc: + msg = "ERROR: \"#{basename} #{command.name}\" was called with " + msg << 'no arguments' if args.empty? + msg << 'arguments ' << args.inspect unless args.empty? + msg << "\nUsage: #{banner(command).inspect}" + fail InvocationError, msg + end + + protected + + # Prints the class options per group. If an option does not belong to + # any group, it's printed as Class option. + # + def class_options_help(shell, groups = {}) #:nodoc: + # Group options by group + class_options.each do |_, value| + groups[value.group] ||= [] + groups[value.group] << value + end + + # Deal with default group + global_options = groups.delete(nil) || [] + print_options(shell, global_options) + + # Print all others + groups.each do |group_name, options| + print_options(shell, options, group_name) + end + end + + # Receives a set of options and print them. + def print_options(shell, options, group_name = nil) + return if options.empty? + + list = [] + padding = options.map { |o| o.aliases.size }.max.to_i * 4 + + options.each do |option| + unless option.hide + item = [option.usage(padding)] + item.push(option.description ? "# #{option.description}" : '') + + list << item + list << ['', "# Default: #{option.default}"] if option.show_default? + list << ['', "# Possible values: #{option.enum.join(', ')}"] if option.enum + end + end + + shell.say(group_name ? "#{group_name} options:" : 'Options:') + shell.print_table(list, :indent => 2) + shell.say '' + end + + # Raises an error if the word given is a Thor reserved word. + def is_thor_reserved_word?(word, type) #:nodoc: + return false unless THOR_RESERVED_WORDS.include?(word.to_s) + fail "#{word.inspect} is a Thor reserved word and cannot be defined as #{type}" + end + + # Build an option and adds it to the given scope. + # + # ==== Parameters + # name:: The name of the argument. + # options:: Described in both class_option and method_option. + # scope:: Options hash that is being built up + def build_option(name, options, scope) #:nodoc: + scope[name] = Thor::Option.new(name, options) + end + + # Receives a hash of options, parse them and add to the scope. This is a + # fast way to set a bunch of options: + # + # build_options :foo => true, :bar => :required, :baz => :string + # + # ==== Parameters + # Hash[Symbol => Object] + def build_options(options, scope) #:nodoc: + options.each do |key, value| + scope[key] = Thor::Option.parse(key, value) + end + end + + # Finds a command with the given name. If the command belongs to the current + # class, just return it, otherwise dup it and add the fresh copy to the + # current command hash. + def find_and_refresh_command(name) #:nodoc: + if commands[name.to_s] + commands[name.to_s] + elsif command = all_commands[name.to_s] # rubocop:disable AssignmentInCondition + commands[name.to_s] = command.clone + else + fail ArgumentError, "You supplied :for => #{name.inspect}, but the command #{name.inspect} could not be found." + end + end + alias_method :find_and_refresh_task, :find_and_refresh_command + + # Everytime someone inherits from a Thor class, register the klass + # and file into baseclass. + def inherited(klass) + Thor::Base.register_klass_file(klass) + klass.instance_variable_set(:@no_commands, false) + end + + # Fire this callback whenever a method is added. Added methods are + # tracked as commands by invoking the create_command method. + def method_added(meth) + meth = meth.to_s + + if meth == 'initialize' + initialize_added + return + end + + # Return if it's not a public instance method + return unless public_method_defined?(meth.to_sym) + + @no_commands ||= false + return if @no_commands || !create_command(meth) + + is_thor_reserved_word?(meth, :command) + Thor::Base.register_klass_file(self) + end + + # Retrieves a value from superclass. If it reaches the baseclass, + # returns default. + def from_superclass(method, default = nil) + if self == baseclass || !superclass.respond_to?(method, true) + default + else + value = superclass.send(method) + + # Ruby implements `dup` on Object, but raises a `TypeError` + # if the method is called on immediates. As a result, we + # don't have a good way to check whether dup will succeed + # without calling it and rescuing the TypeError. + begin + value.dup + rescue TypeError + value + end + + end + end + + # A flag that makes the process exit with status 1 if any error happens. + def exit_on_failure? + false + end + + # + # The basename of the program invoking the thor class. + # + def basename + File.basename($PROGRAM_NAME).split(' ').first + end + + # SIGNATURE: Sets the baseclass. This is where the superclass lookup + # finishes. + def baseclass #:nodoc: + end + + # SIGNATURE: Creates a new command if valid_command? is true. This method is + # called when a new method is added to the class. + def create_command(meth) #:nodoc: + end + alias_method :create_task, :create_command + + # SIGNATURE: Defines behavior when the initialize method is added to the + # class. + def initialize_added #:nodoc: + end + + # SIGNATURE: The hook invoked by start. + def dispatch(command, given_args, given_opts, config) #:nodoc: + fail NotImplementedError + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/command.rb b/bundler-1.7.2/lib/bundler/vendor/thor/command.rb new file mode 100644 index 0000000..cada32b --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/command.rb @@ -0,0 +1,133 @@ +class Thor + class Command < Struct.new(:name, :description, :long_description, :usage, :options) + FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/ + + def initialize(name, description, long_description, usage, options = nil) + super(name.to_s, description, long_description, usage, options || {}) + end + + def initialize_copy(other) #:nodoc: + super(other) + self.options = other.options.dup if other.options + end + + def hidden? + false + end + + # By default, a command invokes a method in the thor class. You can change this + # implementation to create custom commands. + def run(instance, args = []) + arity = nil + + if private_method?(instance) + instance.class.handle_no_command_error(name) + elsif public_method?(instance) + arity = instance.method(name).arity + instance.__send__(name, *args) + elsif local_method?(instance, :method_missing) + instance.__send__(:method_missing, name.to_sym, *args) + else + instance.class.handle_no_command_error(name) + end + rescue ArgumentError => e + handle_argument_error?(instance, e, caller) ? instance.class.handle_argument_error(self, e, args, arity) : (raise e) + rescue NoMethodError => e + handle_no_method_error?(instance, e, caller) ? instance.class.handle_no_command_error(name) : (fail e) + end + + # Returns the formatted usage by injecting given required arguments + # and required options into the given usage. + def formatted_usage(klass, namespace = true, subcommand = false) + if namespace + namespace = klass.namespace + formatted = "#{namespace.gsub(/^(default)/, '')}:" + end + formatted = "#{klass.namespace.split(':').last} " if subcommand + + formatted ||= '' + + # Add usage with required arguments + formatted << if klass && !klass.arguments.empty? + usage.to_s.gsub(/^#{name}/) do |match| + match << ' ' << klass.arguments.map { |a| a.usage }.compact.join(' ') + end + else + usage.to_s + end + + # Add required options + formatted << " #{required_options}" + + # Strip and go! + formatted.strip + end + + protected + + def not_debugging?(instance) + !(instance.class.respond_to?(:debugging) && instance.class.debugging) + end + + def required_options + @required_options ||= options.map { |_, o| o.usage if o.required? }.compact.sort.join(' ') + end + + # Given a target, checks if this class name is a public method. + def public_method?(instance) #:nodoc: + !(instance.public_methods & [name.to_s, name.to_sym]).empty? + end + + def private_method?(instance) + !(instance.private_methods & [name.to_s, name.to_sym]).empty? + end + + def local_method?(instance, name) + methods = instance.public_methods(false) + instance.private_methods(false) + instance.protected_methods(false) + !(methods & [name.to_s, name.to_sym]).empty? + end + + def sans_backtrace(backtrace, caller) #:nodoc: + saned = backtrace.reject { |frame| frame =~ FILE_REGEXP || (frame =~ /\.java:/ && RUBY_PLATFORM =~ /java/) } + saned - caller + end + + def handle_argument_error?(instance, error, caller) + not_debugging?(instance) && error.message =~ /wrong number of arguments/ && begin + saned = sans_backtrace(error.backtrace, caller) + # Ruby 1.9 always include the called method in the backtrace + saned.empty? || (saned.size == 1 && RUBY_VERSION >= '1.9') + end + end + + def handle_no_method_error?(instance, error, caller) + not_debugging?(instance) && + error.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/ + end + end + Task = Command # rubocop:disable ConstantName + + # A command that is hidden in help messages but still invocable. + class HiddenCommand < Command + def hidden? + true + end + end + HiddenTask = HiddenCommand # rubocop:disable ConstantName + + # A dynamic command that handles method missing scenarios. + class DynamicCommand < Command + def initialize(name, options = nil) + super(name.to_s, 'A dynamically-generated command', name.to_s, name.to_s, options) + end + + def run(instance, args = []) + if (instance.methods & [name.to_s, name.to_sym]).empty? + super + else + instance.class.handle_no_command_error(name) + end + end + end + DynamicTask = DynamicCommand # rubocop:disable ConstantName +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/core_ext/hash_with_indifferent_access.rb b/bundler-1.7.2/lib/bundler/vendor/thor/core_ext/hash_with_indifferent_access.rb new file mode 100644 index 0000000..35dbf07 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/core_ext/hash_with_indifferent_access.rb @@ -0,0 +1,77 @@ +class Thor + module CoreExt #:nodoc: + # A hash with indifferent access and magic predicates. + # + # hash = Thor::CoreExt::HashWithIndifferentAccess.new 'foo' => 'bar', 'baz' => 'bee', 'force' => true + # + # hash[:foo] #=> 'bar' + # hash['foo'] #=> 'bar' + # hash.foo? #=> true + # + class HashWithIndifferentAccess < ::Hash #:nodoc: + def initialize(hash = {}) + super() + hash.each do |key, value| + self[convert_key(key)] = value + end + end + + def [](key) + super(convert_key(key)) + end + + def []=(key, value) + super(convert_key(key), value) + end + + def delete(key) + super(convert_key(key)) + end + + def values_at(*indices) + indices.map { |key| self[convert_key(key)] } + end + + def merge(other) + dup.merge!(other) + end + + def merge!(other) + other.each do |key, value| + self[convert_key(key)] = value + end + self + end + + # Convert to a Hash with String keys. + def to_hash + Hash.new(default).merge!(self) + end + + protected + + def convert_key(key) + key.is_a?(Symbol) ? key.to_s : key + end + + # Magic predicates. For instance: + # + # options.force? # => !!options['force'] + # options.shebang # => "/usr/lib/local/ruby" + # options.test_framework?(:rspec) # => options[:test_framework] == :rspec + # + def method_missing(method, *args, &block) + method = method.to_s + if method =~ /^(\w+)\?$/ + if args.empty? + !!self[$1] + else + self[$1] == args.first + end + else + self[method] + end + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/core_ext/io_binary_read.rb b/bundler-1.7.2/lib/bundler/vendor/thor/core_ext/io_binary_read.rb new file mode 100644 index 0000000..496446f --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/core_ext/io_binary_read.rb @@ -0,0 +1,10 @@ +class IO #:nodoc: + class << self + def binread(file, *args) + fail ArgumentError, "wrong number of arguments (#{1 + args.size} for 1..3)" unless args.size < 3 + File.open(file, 'rb') do |f| + f.read(*args) + end + end unless method_defined? :binread + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/core_ext/ordered_hash.rb b/bundler-1.7.2/lib/bundler/vendor/thor/core_ext/ordered_hash.rb new file mode 100644 index 0000000..8ddeb9e --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/core_ext/ordered_hash.rb @@ -0,0 +1,98 @@ +class Thor + module CoreExt #:nodoc: + if RUBY_VERSION >= '1.9' + class OrderedHash < ::Hash + end + else + # This class is based on the Ruby 1.9 ordered hashes. + # + # It keeps the semantics and most of the efficiency of normal hashes + # while also keeping track of the order in which elements were set. + # + class OrderedHash #:nodoc: + include Enumerable + + Node = Struct.new(:key, :value, :next, :prev) + + def initialize + @hash = {} + end + + def [](key) + @hash[key] && @hash[key].value + end + + def []=(key, value) + if node = @hash[key] # rubocop:disable AssignmentInCondition + node.value = value + else + node = Node.new(key, value) + + if !defined?(@first) || @first.nil? + @first = @last = node + else + node.prev = @last + @last.next = node + @last = node + end + end + + @hash[key] = node + value + end + + def delete(key) + if node = @hash[key] # rubocop:disable AssignmentInCondition + prev_node = node.prev + next_node = node.next + + next_node.prev = prev_node if next_node + prev_node.next = next_node if prev_node + + @first = next_node if @first == node + @last = prev_node if @last == node + + value = node.value + end + + @hash.delete(key) + value + end + + def keys + map { |k, v| k } + end + + def values + map { |k, v| v } + end + + def each + return unless defined?(@first) && @first + yield [@first.key, @first.value] + node = @first + yield [node.key, node.value] while node = node.next # rubocop:disable AssignmentInCondition + self + end + + def merge(other) + hash = self.class.new + + each do |key, value| + hash[key] = value + end + + other.each do |key, value| + hash[key] = value + end + + hash + end + + def empty? + @hash.empty? + end + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/error.rb b/bundler-1.7.2/lib/bundler/vendor/thor/error.rb new file mode 100644 index 0000000..c53be49 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/error.rb @@ -0,0 +1,32 @@ +class Thor + # Thor::Error is raised when it's caused by wrong usage of thor classes. Those + # errors have their backtrace suppressed and are nicely shown to the user. + # + # Errors that are caused by the developer, like declaring a method which + # overwrites a thor keyword, it SHOULD NOT raise a Thor::Error. This way, we + # ensure that developer errors are shown with full backtrace. + class Error < StandardError + end + + # Raised when a command was not found. + class UndefinedCommandError < Error + end + UndefinedTaskError = UndefinedCommandError # rubocop:disable ConstantName + + class AmbiguousCommandError < Error + end + AmbiguousTaskError = AmbiguousCommandError # rubocop:disable ConstantName + + # Raised when a command was found, but not invoked properly. + class InvocationError < Error + end + + class UnknownArgumentError < Error + end + + class RequiredArgumentMissingError < InvocationError + end + + class MalformattedArgumentError < InvocationError + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/group.rb b/bundler-1.7.2/lib/bundler/vendor/thor/group.rb new file mode 100644 index 0000000..231f8b1 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/group.rb @@ -0,0 +1,281 @@ +require 'thor/base' + +# Thor has a special class called Thor::Group. The main difference to Thor class +# is that it invokes all commands at once. It also include some methods that allows +# invocations to be done at the class method, which are not available to Thor +# commands. +class Thor::Group # rubocop:disable ClassLength + class << self + # The description for this Thor::Group. If none is provided, but a source root + # exists, tries to find the USAGE one folder above it, otherwise searches + # in the superclass. + # + # ==== Parameters + # description:: The description for this Thor::Group. + # + def desc(description = nil) + if description + @desc = description + else + @desc ||= from_superclass(:desc, nil) + end + end + + # Prints help information. + # + # ==== Options + # short:: When true, shows only usage. + # + def help(shell) + shell.say 'Usage:' + shell.say " #{banner}\n" + shell.say + class_options_help(shell) + shell.say desc if desc + end + + # Stores invocations for this class merging with superclass values. + # + def invocations #:nodoc: + @invocations ||= from_superclass(:invocations, {}) + end + + # Stores invocation blocks used on invoke_from_option. + # + def invocation_blocks #:nodoc: + @invocation_blocks ||= from_superclass(:invocation_blocks, {}) + end + + # Invoke the given namespace or class given. It adds an instance + # method that will invoke the klass and command. You can give a block to + # configure how it will be invoked. + # + # The namespace/class given will have its options showed on the help + # usage. Check invoke_from_option for more information. + # + def invoke(*names, &block) # rubocop:disable MethodLength + options = names.last.is_a?(Hash) ? names.pop : {} + verbose = options.fetch(:verbose, true) + + names.each do |name| + invocations[name] = false + invocation_blocks[name] = block if block_given? + + class_eval <<-METHOD, __FILE__, __LINE__ + def _invoke_#{name.to_s.gsub(/\W/, '_')} + klass, command = self.class.prepare_for_invocation(nil, #{name.inspect}) + + if klass + say_status :invoke, #{name.inspect}, #{verbose.inspect} + block = self.class.invocation_blocks[#{name.inspect}] + _invoke_for_class_method klass, command, &block + else + say_status :error, %(#{name.inspect} [not found]), :red + end + end + METHOD + end + end + + # Invoke a thor class based on the value supplied by the user to the + # given option named "name". A class option must be created before this + # method is invoked for each name given. + # + # ==== Examples + # + # class GemGenerator < Thor::Group + # class_option :test_framework, :type => :string + # invoke_from_option :test_framework + # end + # + # ==== Boolean options + # + # In some cases, you want to invoke a thor class if some option is true or + # false. This is automatically handled by invoke_from_option. Then the + # option name is used to invoke the generator. + # + # ==== Preparing for invocation + # + # In some cases you want to customize how a specified hook is going to be + # invoked. You can do that by overwriting the class method + # prepare_for_invocation. The class method must necessarily return a klass + # and an optional command. + # + # ==== Custom invocations + # + # You can also supply a block to customize how the option is going to be + # invoked. The block receives two parameters, an instance of the current + # class and the klass to be invoked. + # + def invoke_from_option(*names, &block) # rubocop:disable MethodLength + options = names.last.is_a?(Hash) ? names.pop : {} + verbose = options.fetch(:verbose, :white) + + names.each do |name| + unless class_options.key?(name) + fail ArgumentError, "You have to define the option #{name.inspect} " << + 'before setting invoke_from_option.' + end + + invocations[name] = true + invocation_blocks[name] = block if block_given? + + class_eval <<-METHOD, __FILE__, __LINE__ + def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')} + return unless options[#{name.inspect}] + + value = options[#{name.inspect}] + value = #{name.inspect} if value.is_a?(TrueClass) + klass, command = self.class.prepare_for_invocation(#{name.inspect}, value) + + if klass + say_status :invoke, value, #{verbose.inspect} + block = self.class.invocation_blocks[#{name.inspect}] + _invoke_for_class_method klass, command, &block + else + say_status :error, %(\#{value} [not found]), :red + end + end + METHOD + end + end + + # Remove a previously added invocation. + # + # ==== Examples + # + # remove_invocation :test_framework + # + def remove_invocation(*names) + names.each do |name| + remove_command(name) + remove_class_option(name) + invocations.delete(name) + invocation_blocks.delete(name) + end + end + + # Overwrite class options help to allow invoked generators options to be + # shown recursively when invoking a generator. + # + def class_options_help(shell, groups = {}) #:nodoc: + get_options_from_invocations(groups, class_options) do |klass| + klass.send(:get_options_from_invocations, groups, class_options) + end + super(shell, groups) + end + + # Get invocations array and merge options from invocations. Those + # options are added to group_options hash. Options that already exists + # in base_options are not added twice. + # + def get_options_from_invocations(group_options, base_options) #:nodoc: # rubocop:disable MethodLength + invocations.each do |name, from_option| + value = if from_option + option = class_options[name] + option.type == :boolean ? name : option.default + else + name + end + next unless value + + klass, _ = prepare_for_invocation(name, value) + next unless klass && klass.respond_to?(:class_options) + + value = value.to_s + human_name = value.respond_to?(:classify) ? value.classify : value + + group_options[human_name] ||= [] + group_options[human_name] += klass.class_options.values.select do |class_option| + base_options[class_option.name.to_sym].nil? && class_option.group.nil? && + !group_options.values.flatten.any? { |i| i.name == class_option.name } + end + + yield klass if block_given? + end + end + + # Returns commands ready to be printed. + def printable_commands(*) + item = [] + item << banner + item << (desc ? "# #{desc.gsub(/\s+/m, ' ')}" : '') + [item] + end + alias_method :printable_tasks, :printable_commands + + def handle_argument_error(command, error, args, arity) #:nodoc: + msg = "#{basename} #{command.name} takes #{arity} argument" + msg << 's' if arity > 1 + msg << ', but it should not.' + fail error, msg + end + + protected + + # The method responsible for dispatching given the args. + def dispatch(command, given_args, given_opts, config) #:nodoc: + if Thor::HELP_MAPPINGS.include?(given_args.first) + help(config[:shell]) + return + end + + args, opts = Thor::Options.split(given_args) + opts = given_opts || opts + + instance = new(args, opts, config) + yield instance if block_given? + + if command + instance.invoke_command(all_commands[command]) + else + instance.invoke_all + end + end + + # The banner for this class. You can customize it if you are invoking the + # thor class by another ways which is not the Thor::Runner. + def banner + "#{basename} #{self_command.formatted_usage(self, false)}" + end + + # Represents the whole class as a command. + def self_command #:nodoc: + Thor::DynamicCommand.new(namespace, class_options) + end + alias_method :self_task, :self_command + + def baseclass #:nodoc: + Thor::Group + end + + def create_command(meth) #:nodoc: + commands[meth.to_s] = Thor::Command.new(meth, nil, nil, nil, nil) + true + end + alias_method :create_task, :create_command + end + + include Thor::Base + +protected + + # Shortcut to invoke with padding and block handling. Use internally by + # invoke and invoke_from_option class methods. + def _invoke_for_class_method(klass, command = nil, *args, &block) #:nodoc: + with_padding do + if block + case block.arity + when 3 + block.call(self, klass, command) + when 2 + block.call(self, klass) + when 1 + instance_exec(klass, &block) + end + else + invoke klass, command, *args + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/invocation.rb b/bundler-1.7.2/lib/bundler/vendor/thor/invocation.rb new file mode 100644 index 0000000..afe4cab --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/invocation.rb @@ -0,0 +1,173 @@ +class Thor + module Invocation + def self.included(base) #:nodoc: + base.extend ClassMethods + end + + module ClassMethods + # This method is responsible for receiving a name and find the proper + # class and command for it. The key is an optional parameter which is + # available only in class methods invocations (i.e. in Thor::Group). + def prepare_for_invocation(key, name) #:nodoc: + case name + when Symbol, String + Thor::Util.find_class_and_command_by_namespace(name.to_s, !key) + else + name + end + end + end + + # Make initializer aware of invocations and the initialization args. + def initialize(args = [], options = {}, config = {}, &block) #:nodoc: + @_invocations = config[:invocations] || Hash.new { |h, k| h[k] = [] } + @_initializer = [args, options, config] + super + end + + # Receives a name and invokes it. The name can be a string (either "command" or + # "namespace:command"), a Thor::Command, a Class or a Thor instance. If the + # command cannot be guessed by name, it can also be supplied as second argument. + # + # You can also supply the arguments, options and configuration values for + # the command to be invoked, if none is given, the same values used to + # initialize the invoker are used to initialize the invoked. + # + # When no name is given, it will invoke the default command of the current class. + # + # ==== Examples + # + # class A < Thor + # def foo + # invoke :bar + # invoke "b:hello", ["Erik"] + # end + # + # def bar + # invoke "b:hello", ["Erik"] + # end + # end + # + # class B < Thor + # def hello(name) + # puts "hello #{name}" + # end + # end + # + # You can notice that the method "foo" above invokes two commands: "bar", + # which belongs to the same class and "hello" which belongs to the class B. + # + # By using an invocation system you ensure that a command is invoked only once. + # In the example above, invoking "foo" will invoke "b:hello" just once, even + # if it's invoked later by "bar" method. + # + # When class A invokes class B, all arguments used on A initialization are + # supplied to B. This allows lazy parse of options. Let's suppose you have + # some rspec commands: + # + # class Rspec < Thor::Group + # class_option :mock_framework, :type => :string, :default => :rr + # + # def invoke_mock_framework + # invoke "rspec:#{options[:mock_framework]}" + # end + # end + # + # As you noticed, it invokes the given mock framework, which might have its + # own options: + # + # class Rspec::RR < Thor::Group + # class_option :style, :type => :string, :default => :mock + # end + # + # Since it's not rspec concern to parse mock framework options, when RR + # is invoked all options are parsed again, so RR can extract only the options + # that it's going to use. + # + # If you want Rspec::RR to be initialized with its own set of options, you + # have to do that explicitly: + # + # invoke "rspec:rr", [], :style => :foo + # + # Besides giving an instance, you can also give a class to invoke: + # + # invoke Rspec::RR, [], :style => :foo + # + def invoke(name = nil, *args) + if name.nil? + warn "[Thor] Calling invoke() without argument is deprecated. Please use invoke_all instead.\n#{caller.join("\n")}" + return invoke_all + end + + args.unshift(nil) if args.first.is_a?(Array) || args.first.nil? + command, args, opts, config = args + + klass, command = _retrieve_class_and_command(name, command) + fail "Missing Thor class for invoke #{name}" unless klass + fail "Expected Thor class, got #{klass}" unless klass <= Thor::Base + + args, opts, config = _parse_initialization_options(args, opts, config) + klass.send(:dispatch, command, args, opts, config) do |instance| + instance.parent_options = options + end + end + + # Invoke the given command if the given args. + def invoke_command(command, *args) #:nodoc: + current = @_invocations[self.class] + + unless current.include?(command.name) + current << command.name + command.run(self, *args) + end + end + alias_method :invoke_task, :invoke_command + + # Invoke all commands for the current instance. + def invoke_all #:nodoc: + self.class.all_commands.map { |_, command| invoke_command(command) } + end + + # Invokes using shell padding. + def invoke_with_padding(*args) + with_padding { invoke(*args) } + end + + protected + + # Configuration values that are shared between invocations. + def _shared_configuration #:nodoc: + {:invocations => @_invocations} + end + + # This method simply retrieves the class and command to be invoked. + # If the name is nil or the given name is a command in the current class, + # use the given name and return self as class. Otherwise, call + # prepare_for_invocation in the current class. + def _retrieve_class_and_command(name, sent_command = nil) #:nodoc: + case + when name.nil? + [self.class, nil] + when self.class.all_commands[name.to_s] + [self.class, name.to_s] + else + klass, command = self.class.prepare_for_invocation(nil, name) + [klass, command || sent_command] + end + end + alias_method :_retrieve_class_and_task, :_retrieve_class_and_command + + # Initialize klass using values stored in the @_initializer. + def _parse_initialization_options(args, opts, config) #:nodoc: + stored_args, stored_opts, stored_config = @_initializer + + args ||= stored_args.dup + opts ||= stored_opts.dup + + config ||= {} + config = stored_config.merge(_shared_configuration).merge!(config) + + [args, opts, config] + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/line_editor.rb b/bundler-1.7.2/lib/bundler/vendor/thor/line_editor.rb new file mode 100644 index 0000000..021c926 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/line_editor.rb @@ -0,0 +1,17 @@ +require 'thor/line_editor/basic' +require 'thor/line_editor/readline' + +class Thor + module LineEditor + def self.readline(prompt, options={}) + best_available.new(prompt, options).readline + end + + def self.best_available + [ + Thor::LineEditor::Readline, + Thor::LineEditor::Basic + ].detect(&:available?) + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/line_editor/basic.rb b/bundler-1.7.2/lib/bundler/vendor/thor/line_editor/basic.rb new file mode 100644 index 0000000..0084059 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/line_editor/basic.rb @@ -0,0 +1,35 @@ +class Thor + module LineEditor + class Basic + attr_reader :prompt, :options + + def self.available? + true + end + + def initialize(prompt, options) + @prompt = prompt + @options = options + end + + def readline + $stdout.print(prompt) + get_input + end + + private + + def get_input + if echo? + $stdin.gets + else + $stdin.noecho(&:gets) + end + end + + def echo? + options.fetch(:echo, true) + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/line_editor/readline.rb b/bundler-1.7.2/lib/bundler/vendor/thor/line_editor/readline.rb new file mode 100644 index 0000000..c7973fa --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/line_editor/readline.rb @@ -0,0 +1,88 @@ +begin + require 'readline' +rescue LoadError +end + +class Thor + module LineEditor + class Readline < Basic + def self.available? + Object.const_defined?(:Readline) + end + + def readline + if echo? + ::Readline.completion_append_character = nil + # Ruby 1.8.7 does not allow Readline.completion_proc= to receive nil. + if complete = completion_proc + ::Readline.completion_proc = complete + end + ::Readline.readline(prompt, add_to_history?) + else + super + end + end + + private + + def add_to_history? + options.fetch(:add_to_history, true) + end + + def completion_proc + if use_path_completion? + Proc.new { |text| PathCompletion.new(text).matches } + elsif completion_options.any? + Proc.new do |text| + completion_options.select { |option| option.start_with?(text) } + end + end + end + + def completion_options + options.fetch(:limited_to, []) + end + + def use_path_completion? + options.fetch(:path, false) + end + + class PathCompletion + attr_reader :text + private :text + + def initialize(text) + @text = text + end + + def matches + relative_matches + end + + private + + def relative_matches + absolute_matches.map { |path| path.sub(base_path, '') } + end + + def absolute_matches + Dir[glob_pattern].map do |path| + if File.directory?(path) + "#{path}/" + else + path + end + end + end + + def glob_pattern + "#{base_path}#{text}*" + end + + def base_path + "#{Dir.pwd}/" + end + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/parser.rb b/bundler-1.7.2/lib/bundler/vendor/thor/parser.rb new file mode 100644 index 0000000..57a3f6e --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/parser.rb @@ -0,0 +1,4 @@ +require 'thor/parser/argument' +require 'thor/parser/arguments' +require 'thor/parser/option' +require 'thor/parser/options' diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/parser/argument.rb b/bundler-1.7.2/lib/bundler/vendor/thor/parser/argument.rb new file mode 100644 index 0000000..baa75e4 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/parser/argument.rb @@ -0,0 +1,73 @@ +class Thor + class Argument #:nodoc: + VALID_TYPES = [:numeric, :hash, :array, :string] + + attr_reader :name, :description, :enum, :required, :type, :default, :banner + alias_method :human_name, :name + + def initialize(name, options = {}) + class_name = self.class.name.split('::').last + + type = options[:type] + + fail ArgumentError, "#{class_name} name can't be nil." if name.nil? + fail ArgumentError, "Type :#{type} is not valid for #{class_name.downcase}s." if type && !valid_type?(type) + + @name = name.to_s + @description = options[:desc] + @required = options.key?(:required) ? options[:required] : true + @type = (type || :string).to_sym + @default = options[:default] + @banner = options[:banner] || default_banner + @enum = options[:enum] + + validate! # Trigger specific validations + end + + def usage + required? ? banner : "[#{banner}]" + end + + def required? + required + end + + def show_default? + case default + when Array, String, Hash + !default.empty? + else + default + end + end + + protected + + def validate! + if required? && !default.nil? + fail ArgumentError, 'An argument cannot be required and have default value.' + elsif @enum && !@enum.is_a?(Array) + fail ArgumentError, 'An argument cannot have an enum other than an array.' + end + end + + def valid_type?(type) + self.class::VALID_TYPES.include?(type.to_sym) + end + + def default_banner + case type + when :boolean + nil + when :string, :default + human_name.upcase + when :numeric + 'N' + when :hash + 'key:value' + when :array + 'one two three' + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/parser/arguments.rb b/bundler-1.7.2/lib/bundler/vendor/thor/parser/arguments.rb new file mode 100644 index 0000000..1cdddcc --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/parser/arguments.rb @@ -0,0 +1,175 @@ +class Thor + class Arguments #:nodoc: # rubocop:disable ClassLength + NUMERIC = /(\d*\.\d+|\d+)/ + + # Receives an array of args and returns two arrays, one with arguments + # and one with switches. + # + def self.split(args) + arguments = [] + + args.each do |item| + break if item =~ /^-/ + arguments << item + end + + [arguments, args[Range.new(arguments.size, -1)]] + end + + def self.parse(*args) + to_parse = args.pop + new(*args).parse(to_parse) + end + + # Takes an array of Thor::Argument objects. + # + def initialize(arguments = []) + @assigns, @non_assigned_required = {}, [] + @switches = arguments + + arguments.each do |argument| + if !argument.default.nil? + @assigns[argument.human_name] = argument.default + elsif argument.required? + @non_assigned_required << argument + end + end + end + + def parse(args) + @pile = args.dup + + @switches.each do |argument| + break unless peek + @non_assigned_required.delete(argument) + @assigns[argument.human_name] = send(:"parse_#{argument.type}", argument.human_name) + end + + check_requirement! + @assigns + end + + def remaining # rubocop:disable TrivialAccessors + @pile + end + + private + + def no_or_skip?(arg) + arg =~ /^--(no|skip)-([-\w]+)$/ + $2 + end + + def last? + @pile.empty? + end + + def peek + @pile.first + end + + def shift + @pile.shift + end + + def unshift(arg) + if arg.kind_of?(Array) + @pile = arg + @pile + else + @pile.unshift(arg) + end + end + + def current_is_value? + peek && peek.to_s !~ /^-/ + end + + # Runs through the argument array getting strings that contains ":" and + # mark it as a hash: + # + # [ "name:string", "age:integer" ] + # + # Becomes: + # + # { "name" => "string", "age" => "integer" } + # + def parse_hash(name) + return shift if peek.is_a?(Hash) + hash = {} + + while current_is_value? && peek.include?(':') + key, value = shift.split(':', 2) + hash[key] = value + end + hash + end + + # Runs through the argument array getting all strings until no string is + # found or a switch is found. + # + # ["a", "b", "c"] + # + # And returns it as an array: + # + # ["a", "b", "c"] + # + def parse_array(name) + return shift if peek.is_a?(Array) + array = [] + array << shift while current_is_value? + array + end + + # Check if the peek is numeric format and return a Float or Integer. + # Check if the peek is included in enum if enum is provided. + # Otherwise raises an error. + # + def parse_numeric(name) + return shift if peek.is_a?(Numeric) + + unless peek =~ NUMERIC && $& == peek + fail MalformattedArgumentError, "Expected numeric value for '#{name}'; got #{peek.inspect}" + end + + value = $&.index('.') ? shift.to_f : shift.to_i + if @switches.is_a?(Hash) && switch = @switches[name] + if switch.enum && !switch.enum.include?(value) + raise MalformattedArgumentError, "Expected '#{name}' to be one of #{switch.enum.join(', ')}; got #{value}" + end + end + value + end + + # Parse string: + # for --string-arg, just return the current value in the pile + # for --no-string-arg, nil + # Check if the peek is included in enum if enum is provided. Otherwise raises an error. + # + def parse_string(name) + if no_or_skip?(name) + nil + else + value = shift + if @switches.is_a?(Hash) && switch = @switches[name] # rubocop:disable AssignmentInCondition + if switch.enum && !switch.enum.include?(value) + fail MalformattedArgumentError, "Expected '#{name}' to be one of #{switch.enum.join(', ')}; got #{value}" + end + end + value + end + end + + # Raises an error if @non_assigned_required array is not empty. + # + def check_requirement! + unless @non_assigned_required.empty? + names = @non_assigned_required.map do |o| + o.respond_to?(:switch_name) ? o.switch_name : o.human_name + end.join("', '") + + class_name = self.class.name.split('::').last.downcase + fail RequiredArgumentMissingError, "No value provided for required #{class_name} '#{names}'" + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/parser/option.rb b/bundler-1.7.2/lib/bundler/vendor/thor/parser/option.rb new file mode 100644 index 0000000..a076045 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/parser/option.rb @@ -0,0 +1,121 @@ +class Thor + class Option < Argument #:nodoc: + attr_reader :aliases, :group, :lazy_default, :hide + + VALID_TYPES = [:boolean, :numeric, :hash, :array, :string] + + def initialize(name, options = {}) + options[:required] = false unless options.key?(:required) + super + @lazy_default = options[:lazy_default] + @group = options[:group].to_s.capitalize if options[:group] + @aliases = Array(options[:aliases]) + @hide = options[:hide] + end + + # This parse quick options given as method_options. It makes several + # assumptions, but you can be more specific using the option method. + # + # parse :foo => "bar" + # #=> Option foo with default value bar + # + # parse [:foo, :baz] => "bar" + # #=> Option foo with default value bar and alias :baz + # + # parse :foo => :required + # #=> Required option foo without default value + # + # parse :foo => 2 + # #=> Option foo with default value 2 and type numeric + # + # parse :foo => :numeric + # #=> Option foo without default value and type numeric + # + # parse :foo => true + # #=> Option foo with default value true and type boolean + # + # The valid types are :boolean, :numeric, :hash, :array and :string. If none + # is given a default type is assumed. This default type accepts arguments as + # string (--foo=value) or booleans (just --foo). + # + # By default all options are optional, unless :required is given. + # + def self.parse(key, value) # rubocop:disable MethodLength + if key.is_a?(Array) + name, *aliases = key + else + name, aliases = key, [] + end + + name = name.to_s + default = value + + type = case value + when Symbol + default = nil + if VALID_TYPES.include?(value) + value + elsif required = (value == :required) # rubocop:disable AssignmentInCondition + :string + end + when TrueClass, FalseClass + :boolean + when Numeric + :numeric + when Hash, Array, String + value.class.name.downcase.to_sym + end + new(name.to_s, :required => required, :type => type, :default => default, :aliases => aliases) + end + + def switch_name + @switch_name ||= dasherized? ? name : dasherize(name) + end + + def human_name + @human_name ||= dasherized? ? undasherize(name) : name + end + + def usage(padding = 0) + sample = if banner && !banner.to_s.empty? + "#{switch_name}=#{banner}" + else + switch_name + end + + sample = "[#{sample}]" unless required? + + if aliases.empty? + (' ' * padding) << sample + else + "#{aliases.join(', ')}, #{sample}" + end + end + + VALID_TYPES.each do |type| + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{type}? + self.type == #{type.inspect} + end + RUBY + end + + protected + + def validate! + fail ArgumentError, 'An option cannot be boolean and required.' if boolean? && required? + end + + def dasherized? + name.index('-') == 0 + end + + def undasherize(str) + str.sub(/^-{1,2}/, '') + end + + def dasherize(str) + (str.length > 1 ? '--' : '-') + str.gsub('_', '-') + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/parser/options.rb b/bundler-1.7.2/lib/bundler/vendor/thor/parser/options.rb new file mode 100644 index 0000000..fb3fd1e --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/parser/options.rb @@ -0,0 +1,218 @@ +class Thor + class Options < Arguments #:nodoc: # rubocop:disable ClassLength + LONG_RE = /^(--\w+(?:-\w+)*)$/ + SHORT_RE = /^(-[a-z])$/i + EQ_RE = /^(--\w+(?:-\w+)*|-[a-z])=(.*)$/i + SHORT_SQ_RE = /^-([a-z]{2,})$/i # Allow either -x -v or -xv style for single char args + SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i + OPTS_END = '--'.freeze + + # Receives a hash and makes it switches. + def self.to_switches(options) + options.map do |key, value| + case value + when true + "--#{key}" + when Array + "--#{key} #{value.map { |v| v.inspect }.join(' ')}" + when Hash + "--#{key} #{value.map { |k, v| "#{k}:#{v}" }.join(' ')}" + when nil, false + '' + else + "--#{key} #{value.inspect}" + end + end.join(' ') + end + + # Takes a hash of Thor::Option and a hash with defaults. + # + # If +stop_on_unknown+ is true, #parse will stop as soon as it encounters + # an unknown option or a regular argument. + def initialize(hash_options = {}, defaults = {}, stop_on_unknown = false) + @stop_on_unknown = stop_on_unknown + options = hash_options.values + super(options) + + # Add defaults + defaults.each do |key, value| + @assigns[key.to_s] = value + @non_assigned_required.delete(hash_options[key]) + end + + @shorts, @switches, @extra = {}, {}, [] + + options.each do |option| + @switches[option.switch_name] = option + + option.aliases.each do |short| + name = short.to_s.sub(/^(?!\-)/, '-') + @shorts[name] ||= option.switch_name + end + end + end + + def remaining # rubocop:disable TrivialAccessors + @extra + end + + def peek + return super unless @parsing_options + + result = super + if result == OPTS_END + shift + @parsing_options = false + super + else + result + end + end + + def parse(args) # rubocop:disable MethodLength + @pile = args.dup + @parsing_options = true + + while peek + if parsing_options? + match, is_switch = current_is_switch? + shifted = shift + + if is_switch + case shifted + when SHORT_SQ_RE + unshift($1.split('').map { |f| "-#{f}" }) + next + when EQ_RE, SHORT_NUM + unshift($2) + switch = $1 + when LONG_RE, SHORT_RE + switch = $1 + end + + switch = normalize_switch(switch) + option = switch_option(switch) + @assigns[option.human_name] = parse_peek(switch, option) + elsif @stop_on_unknown + @parsing_options = false + @extra << shifted + @extra << shift while peek + break + elsif match + @extra << shifted + @extra << shift while peek && peek !~ /^-/ + else + @extra << shifted + end + else + @extra << shift + end + end + + check_requirement! + + assigns = Thor::CoreExt::HashWithIndifferentAccess.new(@assigns) + assigns.freeze + assigns + end + + def check_unknown! + # an unknown option starts with - or -- and has no more --'s afterward. + unknown = @extra.select { |str| str =~ /^--?(?:(?!--).)*$/ } + fail UnknownArgumentError, "Unknown switches '#{unknown.join(', ')}'" unless unknown.empty? + end + + protected + + # Check if the current value in peek is a registered switch. + # + # Two booleans are returned. The first is true if the current value + # starts with a hyphen; the second is true if it is a registered switch. + def current_is_switch? + case peek + when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM + [true, switch?($1)] + when SHORT_SQ_RE + [true, $1.split('').any? { |f| switch?("-#{f}") }] + else + [false, false] + end + end + + def current_is_switch_formatted? + case peek + when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM, SHORT_SQ_RE + true + else + false + end + end + + def current_is_value? + peek && (!parsing_options? || super) + end + + def switch?(arg) + switch_option(normalize_switch(arg)) + end + + def switch_option(arg) + if match = no_or_skip?(arg) # rubocop:disable AssignmentInCondition + @switches[arg] || @switches["--#{match}"] + else + @switches[arg] + end + end + + # Check if the given argument is actually a shortcut. + # + def normalize_switch(arg) + (@shorts[arg] || arg).tr('_', '-') + end + + def parsing_options? + peek + @parsing_options + end + + # Parse boolean values which can be given as --foo=true, --foo or --no-foo. + # + def parse_boolean(switch) + if current_is_value? + if ['true', 'TRUE', 't', 'T', true].include?(peek) + shift + true + elsif ['false', 'FALSE', 'f', 'F', false].include?(peek) + shift + false + else + true + end + else + @switches.key?(switch) || !no_or_skip?(switch) + end + end + + # Parse the value at the peek analyzing if it requires an input or not. + # + def parse_peek(switch, option) + if parsing_options? && (current_is_switch_formatted? || last?) + if option.boolean? + # No problem for boolean types + elsif no_or_skip?(switch) + return nil # User set value to nil + elsif option.string? && !option.required? + # Return the default if there is one, else the human name + return option.lazy_default || option.default || option.human_name + elsif option.lazy_default + return option.lazy_default + else + fail MalformattedArgumentError, "No value provided for option '#{switch}'" + end + end + + @non_assigned_required.delete(option) + send(:"parse_#{option.type}", switch) + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/rake_compat.rb b/bundler-1.7.2/lib/bundler/vendor/thor/rake_compat.rb new file mode 100644 index 0000000..d347672 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/rake_compat.rb @@ -0,0 +1,71 @@ +require 'rake' +require 'rake/dsl_definition' + +class Thor + # Adds a compatibility layer to your Thor classes which allows you to use + # rake package tasks. For example, to use rspec rake tasks, one can do: + # + # require 'thor/rake_compat' + # require 'rspec/core/rake_task' + # + # class Default < Thor + # include Thor::RakeCompat + # + # RSpec::Core::RakeTask.new(:spec) do |t| + # t.spec_opts = ['--options', './.rspec'] + # t.spec_files = FileList['spec/**/*_spec.rb'] + # end + # end + # + module RakeCompat + include Rake::DSL if defined?(Rake::DSL) + + def self.rake_classes + @rake_classes ||= [] + end + + def self.included(base) + # Hack. Make rakefile point to invoker, so rdoc task is generated properly. + rakefile = File.basename(caller[0].match(/(.*):\d+/)[1]) + Rake.application.instance_variable_set(:@rakefile, rakefile) + rake_classes << base + end + end +end + +# override task on (main), for compatibility with Rake 0.9 +instance_eval do + alias rake_namespace namespace + + def task(*) + task = super + + if klass = Thor::RakeCompat.rake_classes.last # rubocop:disable AssignmentInCondition + non_namespaced_name = task.name.split(':').last + + description = non_namespaced_name + description << task.arg_names.map { |n| n.to_s.upcase }.join(' ') + description.strip! + + klass.desc description, Rake.application.last_description || non_namespaced_name + Rake.application.last_description = nil + klass.send :define_method, non_namespaced_name do |*args| + Rake::Task[task.name.to_sym].invoke(*args) + end + end + + task + end + + def namespace(name) + if klass = Thor::RakeCompat.rake_classes.last # rubocop:disable AssignmentInCondition + const_name = Thor::Util.camel_case(name.to_s).to_sym + klass.const_set(const_name, Class.new(Thor)) + new_klass = klass.const_get(const_name) + Thor::RakeCompat.rake_classes << new_klass + end + + super + Thor::RakeCompat.rake_classes.pop + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/runner.rb b/bundler-1.7.2/lib/bundler/vendor/thor/runner.rb new file mode 100644 index 0000000..761b7b3 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/runner.rb @@ -0,0 +1,322 @@ +require 'thor' +require 'thor/group' +require 'thor/core_ext/io_binary_read' + +require 'fileutils' +require 'open-uri' +require 'yaml' +require 'digest/md5' +require 'pathname' + +class Thor::Runner < Thor #:nodoc: # rubocop:disable ClassLength + map '-T' => :list, '-i' => :install, '-u' => :update, '-v' => :version + + # Override Thor#help so it can give information about any class and any method. + # + def help(meth = nil) + if meth && !self.respond_to?(meth) + initialize_thorfiles(meth) + klass, command = Thor::Util.find_class_and_command_by_namespace(meth) + self.class.handle_no_command_error(command, false) if klass.nil? + klass.start(['-h', command].compact, :shell => shell) + else + super + end + end + + # If a command is not found on Thor::Runner, method missing is invoked and + # Thor::Runner is then responsible for finding the command in all classes. + # + def method_missing(meth, *args) + meth = meth.to_s + initialize_thorfiles(meth) + klass, command = Thor::Util.find_class_and_command_by_namespace(meth) + self.class.handle_no_command_error(command, false) if klass.nil? + args.unshift(command) if command + klass.start(args, :shell => shell) + end + + desc 'install NAME', 'Install an optionally named Thor file into your system commands' + method_options :as => :string, :relative => :boolean, :force => :boolean + def install(name) # rubocop:disable MethodLength + initialize_thorfiles + + # If a directory name is provided as the argument, look for a 'main.thor' + # command in said directory. + begin + if File.directory?(File.expand_path(name)) + base, package = File.join(name, 'main.thor'), :directory + contents = open(base) { |input| input.read } + else + base, package = name, :file + contents = open(name) { |input| input.read } + end + rescue OpenURI::HTTPError + raise Error, "Error opening URI '#{name}'" + rescue Errno::ENOENT + fail Error, "Error opening file '#{name}'" + end + + say 'Your Thorfile contains:' + say contents + + unless options['force'] + return false if no?('Do you wish to continue [y/N]?') + end + + as = options['as'] || begin + first_line = contents.split("\n")[0] + (match = first_line.match(/\s*#\s*module:\s*([^\n]*)/)) ? match[1].strip : nil + end + + unless as + basename = File.basename(name) + as = ask("Please specify a name for #{name} in the system repository [#{basename}]:") + as = basename if as.empty? + end + + location = if options[:relative] || name =~ %r{^https?://} + name + else + File.expand_path(name) + end + + thor_yaml[as] = { + :filename => Digest::MD5.hexdigest(name + as), + :location => location, + :namespaces => Thor::Util.namespaces_in_content(contents, base) + } + + save_yaml(thor_yaml) + say 'Storing thor file in your system repository' + destination = File.join(thor_root, thor_yaml[as][:filename]) + + if package == :file + File.open(destination, 'w') { |f| f.puts contents } + else + FileUtils.cp_r(name, destination) + end + + thor_yaml[as][:filename] # Indicate success + end + + desc 'version', 'Show Thor version' + def version + require 'thor/version' + say "Thor #{Thor::VERSION}" + end + + desc 'uninstall NAME', 'Uninstall a named Thor module' + def uninstall(name) + fail Error, "Can't find module '#{name}'" unless thor_yaml[name] + say "Uninstalling #{name}." + FileUtils.rm_rf(File.join(thor_root, "#{thor_yaml[name][:filename]}")) + + thor_yaml.delete(name) + save_yaml(thor_yaml) + + puts 'Done.' + end + + desc 'update NAME', 'Update a Thor file from its original location' + def update(name) + fail Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location] + + say "Updating '#{name}' from #{thor_yaml[name][:location]}" + + old_filename = thor_yaml[name][:filename] + self.options = options.merge('as' => name) + + if File.directory? File.expand_path(name) + FileUtils.rm_rf(File.join(thor_root, old_filename)) + + thor_yaml.delete(old_filename) + save_yaml(thor_yaml) + + filename = install(name) + else + filename = install(thor_yaml[name][:location]) + end + + unless filename == old_filename + File.delete(File.join(thor_root, old_filename)) + end + end + + desc 'installed', 'List the installed Thor modules and commands' + method_options :internal => :boolean + def installed + initialize_thorfiles(nil, true) + display_klasses(true, options['internal']) + end + + desc 'list [SEARCH]', 'List the available thor commands (--substring means .*SEARCH)' + method_options :substring => :boolean, :group => :string, :all => :boolean, :debug => :boolean + def list(search = '') + initialize_thorfiles + + search = ".*#{search}" if options['substring'] + search = /^#{search}.*/i + group = options[:group] || 'standard' + + klasses = Thor::Base.subclasses.select do |k| + (options[:all] || k.group == group) && k.namespace =~ search + end + + display_klasses(false, false, klasses) + end + +private + + def self.banner(command, all = false, subcommand = false) + 'thor ' + command.formatted_usage(self, all, subcommand) + end + + def thor_root + Thor::Util.thor_root + end + + def thor_yaml + @thor_yaml ||= begin + yaml_file = File.join(thor_root, 'thor.yml') + yaml = YAML.load_file(yaml_file) if File.exist?(yaml_file) + yaml || {} + end + end + + # Save the yaml file. If none exists in thor root, creates one. + # + def save_yaml(yaml) + yaml_file = File.join(thor_root, 'thor.yml') + + unless File.exist?(yaml_file) + FileUtils.mkdir_p(thor_root) + yaml_file = File.join(thor_root, 'thor.yml') + FileUtils.touch(yaml_file) + end + + File.open(yaml_file, 'w') { |f| f.puts yaml.to_yaml } + end + + def self.exit_on_failure? + true + end + + # Load the Thorfiles. If relevant_to is supplied, looks for specific files + # in the thor_root instead of loading them all. + # + # By default, it also traverses the current path until find Thor files, as + # described in thorfiles. This look up can be skipped by supplying + # skip_lookup true. + # + def initialize_thorfiles(relevant_to = nil, skip_lookup = false) + thorfiles(relevant_to, skip_lookup).each do |f| + Thor::Util.load_thorfile(f, nil, options[:debug]) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f)) + end + end + + # Finds Thorfiles by traversing from your current directory down to the root + # directory of your system. If at any time we find a Thor file, we stop. + # + # We also ensure that system-wide Thorfiles are loaded first, so local + # Thorfiles can override them. + # + # ==== Example + # + # If we start at /Users/wycats/dev/thor ... + # + # 1. /Users/wycats/dev/thor + # 2. /Users/wycats/dev + # 3. /Users/wycats <-- we find a Thorfile here, so we stop + # + # Suppose we start at c:\Documents and Settings\james\dev\thor ... + # + # 1. c:\Documents and Settings\james\dev\thor + # 2. c:\Documents and Settings\james\dev + # 3. c:\Documents and Settings\james + # 4. c:\Documents and Settings + # 5. c:\ <-- no Thorfiles found! + # + def thorfiles(relevant_to = nil, skip_lookup = false) + thorfiles = [] + + unless skip_lookup + Pathname.pwd.ascend do |path| + thorfiles = Thor::Util.globs_for(path).map { |g| Dir[g] }.flatten + break unless thorfiles.empty? + end + end + + files = (relevant_to ? thorfiles_relevant_to(relevant_to) : Thor::Util.thor_root_glob) + files += thorfiles + files -= ["#{thor_root}/thor.yml"] + + files.map! do |file| + File.directory?(file) ? File.join(file, 'main.thor') : file + end + end + + # Load Thorfiles relevant to the given method. If you provide "foo:bar" it + # will load all thor files in the thor.yaml that has "foo" e "foo:bar" + # namespaces registered. + # + def thorfiles_relevant_to(meth) + lookup = [meth, meth.split(':')[0...-1].join(':')] + + files = thor_yaml.select do |k, v| + v[:namespaces] && !(v[:namespaces] & lookup).empty? + end + + files.map { |k, v| File.join(thor_root, "#{v[:filename]}") } + end + + # Display information about the given klasses. If with_module is given, + # it shows a table with information extracted from the yaml file. + # + def display_klasses(with_modules = false, show_internal = false, klasses = Thor::Base.subclasses) + klasses -= [Thor, Thor::Runner, Thor::Group] unless show_internal + + fail Error, 'No Thor commands available' if klasses.empty? + show_modules if with_modules && !thor_yaml.empty? + + list = Hash.new { |h, k| h[k] = [] } + groups = klasses.select { |k| k.ancestors.include?(Thor::Group) } + + # Get classes which inherit from Thor + (klasses - groups).each { |k| list[k.namespace.split(':').first] += k.printable_commands(false) } + + # Get classes which inherit from Thor::Base + groups.map! { |k| k.printable_commands(false).first } + list['root'] = groups + + # Order namespaces with default coming first + list = list.sort { |a, b| a[0].sub(/^default/, '') <=> b[0].sub(/^default/, '') } + list.each { |n, commands| display_commands(n, commands) unless commands.empty? } + end + + def display_commands(namespace, list) #:nodoc: + list.sort! { |a, b| a[0] <=> b[0] } + + say shell.set_color(namespace, :blue, true) + say '-' * namespace.size + + print_table(list, :truncate => true) + say + end + alias_method :display_tasks, :display_commands + + def show_modules #:nodoc: + info = [] + labels = %w[Modules Namespaces] + + info << labels + info << ['-' * labels[0].size, '-' * labels[1].size] + + thor_yaml.each do |name, hash| + info << [name, hash[:namespaces].join(', ')] + end + + print_table info + say '' + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/shell.rb b/bundler-1.7.2/lib/bundler/vendor/thor/shell.rb new file mode 100644 index 0000000..848dc9a --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/shell.rb @@ -0,0 +1,81 @@ +require 'rbconfig' + +class Thor + module Base + class << self + attr_writer :shell + + # Returns the shell used in all Thor classes. If you are in a Unix platform + # it will use a colored log, otherwise it will use a basic one without color. + # + def shell + @shell ||= if ENV['THOR_SHELL'] && ENV['THOR_SHELL'].size > 0 + Thor::Shell.const_get(ENV['THOR_SHELL']) + elsif RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ && !ENV['ANSICON'] + Thor::Shell::Basic + else + Thor::Shell::Color + end + end + end + end + + module Shell + SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width] + attr_writer :shell + + autoload :Basic, 'thor/shell/basic' + autoload :Color, 'thor/shell/color' + autoload :HTML, 'thor/shell/html' + + # Add shell to initialize config values. + # + # ==== Configuration + # shell:: An instance of the shell to be used. + # + # ==== Examples + # + # class MyScript < Thor + # argument :first, :type => :numeric + # end + # + # MyScript.new [1.0], { :foo => :bar }, :shell => Thor::Shell::Basic.new + # + def initialize(args = [], options = {}, config = {}) + super + self.shell = config[:shell] + shell.base ||= self if shell.respond_to?(:base) + end + + # Holds the shell for the given Thor instance. If no shell is given, + # it gets a default shell from Thor::Base.shell. + def shell + @shell ||= Thor::Base.shell.new + end + + # Common methods that are delegated to the shell. + SHELL_DELEGATED_METHODS.each do |method| + module_eval <<-METHOD, __FILE__, __LINE__ + def #{method}(*args,&block) + shell.#{method}(*args,&block) + end + METHOD + end + + # Yields the given block with padding. + def with_padding + shell.padding += 1 + yield + ensure + shell.padding -= 1 + end + + protected + + # Allow shell to be shared between invocations. + # + def _shared_configuration #:nodoc: + super.merge!(:shell => shell) + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/shell/basic.rb b/bundler-1.7.2/lib/bundler/vendor/thor/shell/basic.rb new file mode 100644 index 0000000..1f45020 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/shell/basic.rb @@ -0,0 +1,420 @@ +require 'tempfile' + +class Thor + module Shell + class Basic # rubocop:disable ClassLength + attr_accessor :base + attr_reader :padding + + # Initialize base, mute and padding to nil. + # + def initialize #:nodoc: + @base, @mute, @padding, @always_force = nil, false, 0, false + end + + # Mute everything that's inside given block + # + def mute + @mute = true + yield + ensure + @mute = false + end + + # Check if base is muted + # + def mute? # rubocop:disable TrivialAccessors + @mute + end + + # Sets the output padding, not allowing less than zero values. + # + def padding=(value) + @padding = [0, value].max + end + + # Asks something to the user and receives a response. + # + # If asked to limit the correct responses, you can pass in an + # array of acceptable answers. If one of those is not supplied, + # they will be shown a message stating that one of those answers + # must be given and re-asked the question. + # + # If asking for sensitive information, the :echo option can be set + # to false to mask user input from $stdin. + # + # If the required input is a path, then set the path option to + # true. This will enable tab completion for file paths relative + # to the current working directory on systems that support + # Readline. + # + # ==== Example + # ask("What is your name?") + # + # ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"]) + # + # ask("What is your password?", :echo => false) + # + # ask("Where should the file be saved?", :path => true) + # + def ask(statement, *args) + options = args.last.is_a?(Hash) ? args.pop : {} + color = args.first + + if options[:limited_to] + ask_filtered(statement, color, options) + else + ask_simply(statement, color, options) + end + end + + # Say (print) something to the user. If the sentence ends with a whitespace + # or tab character, a new line is not appended (print + flush). Otherwise + # are passed straight to puts (behavior got from Highline). + # + # ==== Example + # say("I know you knew that.") + # + def say(message = '', color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/)) + buffer = prepare_message(message, *color) + buffer << "\n" if force_new_line && !message.end_with?("\n") + + stdout.print(buffer) + stdout.flush + end + + # Say a status with the given color and appends the message. Since this + # method is used frequently by actions, it allows nil or false to be given + # in log_status, avoiding the message from being shown. If a Symbol is + # given in log_status, it's used as the color. + # + def say_status(status, message, log_status = true) + return if quiet? || log_status == false + spaces = ' ' * (padding + 1) + color = log_status.is_a?(Symbol) ? log_status : :green + + status = status.to_s.rjust(12) + status = set_color status, color, true if color + + buffer = "#{status}#{spaces}#{message}" + buffer << "\n" unless buffer.end_with?("\n") + + stdout.print(buffer) + stdout.flush + end + + # Make a question the to user and returns true if the user replies "y" or + # "yes". + # + def yes?(statement, color = nil) + !!(ask(statement, color, :add_to_history => false) =~ is?(:yes)) + end + + # Make a question the to user and returns true if the user replies "n" or + # "no". + # + def no?(statement, color = nil) + !!(ask(statement, color, :add_to_history => false) =~ is?(:no)) + end + + # Prints values in columns + # + # ==== Parameters + # Array[String, String, ...] + # + def print_in_columns(array) + return if array.empty? + colwidth = (array.map { |el| el.to_s.size }.max || 0) + 2 + array.each_with_index do |value, index| + # Don't output trailing spaces when printing the last column + if ((((index + 1) % (terminal_width / colwidth))).zero? && !index.zero?) || index + 1 == array.length + stdout.puts value + else + stdout.printf("%-#{colwidth}s", value) + end + end + end + + # Prints a table. + # + # ==== Parameters + # Array[Array[String, String, ...]] + # + # ==== Options + # indent:: Indent the first column by indent value. + # colwidth:: Force the first column to colwidth spaces wide. + # + def print_table(array, options = {}) # rubocop:disable MethodLength + return if array.empty? + + formats, indent, colwidth = [], options[:indent].to_i, options[:colwidth] + options[:truncate] = terminal_width if options[:truncate] == true + + formats << "%-#{colwidth + 2}s" if colwidth + start = colwidth ? 1 : 0 + + colcount = array.max { |a, b| a.size <=> b.size }.size + + maximas = [] + + start.upto(colcount - 1) do |index| + maxima = array.map { |row| row[index] ? row[index].to_s.size : 0 }.max + maximas << maxima + if index == colcount - 1 + # Don't output 2 trailing spaces when printing the last column + formats << '%-s' + else + formats << "%-#{maxima + 2}s" + end + end + + formats[0] = formats[0].insert(0, ' ' * indent) + formats << '%s' + + array.each do |row| + sentence = '' + + row.each_with_index do |column, index| + maxima = maximas[index] + + if column.is_a?(Numeric) + if index == row.size - 1 + # Don't output 2 trailing spaces when printing the last column + f = "%#{maxima}s" + else + f = "%#{maxima}s " + end + else + f = formats[index] + end + sentence << f % column.to_s + end + + sentence = truncate(sentence, options[:truncate]) if options[:truncate] + stdout.puts sentence + end + end + + # Prints a long string, word-wrapping the text to the current width of the + # terminal display. Ideal for printing heredocs. + # + # ==== Parameters + # String + # + # ==== Options + # indent:: Indent each line of the printed paragraph by indent value. + # + def print_wrapped(message, options = {}) + indent = options[:indent] || 0 + width = terminal_width - indent + paras = message.split("\n\n") + + paras.map! do |unwrapped| + unwrapped.strip.gsub(/\n/, ' ').squeeze(' ').gsub(/.{1,#{width}}(?:\s|\Z)/) { ($& + 5.chr).gsub(/\n\005/, "\n").gsub(/\005/, "\n") } + end + + paras.each do |para| + para.split("\n").each do |line| + stdout.puts line.insert(0, ' ' * indent) + end + stdout.puts unless para == paras.last + end + end + + # Deals with file collision and returns true if the file should be + # overwritten and false otherwise. If a block is given, it uses the block + # response as the content for the diff. + # + # ==== Parameters + # destination:: the destination file to solve conflicts + # block:: an optional block that returns the value to be used in diff + # + def file_collision(destination) # rubocop:disable MethodLength + return true if @always_force + options = block_given? ? '[Ynaqdh]' : '[Ynaqh]' + + loop do + answer = ask( + %[Overwrite #{destination}? (enter "h" for help) #{options}], + :add_to_history => false + ) + + case answer + when is?(:yes), is?(:force), '' + return true + when is?(:no), is?(:skip) + return false + when is?(:always) + return @always_force = true + when is?(:quit) + say 'Aborting...' + fail SystemExit + when is?(:diff) + show_diff(destination, yield) if block_given? + say 'Retrying...' + else + say file_collision_help + end + end + end + + # This code was copied from Rake, available under MIT-LICENSE + # Copyright (c) 2003, 2004 Jim Weirich + def terminal_width + if ENV['THOR_COLUMNS'] + result = ENV['THOR_COLUMNS'].to_i + else + result = unix? ? dynamic_width : 80 + end + result < 10 ? 80 : result + rescue + 80 + end + + # Called if something goes wrong during the execution. This is used by Thor + # internally and should not be used inside your scripts. If something went + # wrong, you can always raise an exception. If you raise a Thor::Error, it + # will be rescued and wrapped in the method below. + # + def error(statement) + stderr.puts statement + end + + # Apply color to the given string with optional bold. Disabled in the + # Thor::Shell::Basic class. + # + def set_color(string, *args) #:nodoc: + string + end + + protected + + def prepare_message(message, *color) + spaces = " " * padding + spaces + set_color(message.to_s, *color) + end + + def can_display_colors? + false + end + + def lookup_color(color) + return color unless color.is_a?(Symbol) + self.class.const_get(color.to_s.upcase) + end + + def stdout + $stdout + end + + def stderr + $stderr + end + + def is?(value) #:nodoc: + value = value.to_s + + if value.size == 1 + /\A#{value}\z/i + else + /\A(#{value}|#{value[0, 1]})\z/i + end + end + + def file_collision_help #:nodoc: + <<-HELP + Y - yes, overwrite + n - no, do not overwrite + a - all, overwrite this and all others + q - quit, abort + d - diff, show the differences between the old and the new + h - help, show this help + HELP + end + + def show_diff(destination, content) #:nodoc: + diff_cmd = ENV['THOR_DIFF'] || ENV['RAILS_DIFF'] || 'diff -u' + + Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp| + temp.write content + temp.rewind + system %(#{diff_cmd} "#{destination}" "#{temp.path}") + end + end + + def quiet? #:nodoc: + mute? || (base && base.options[:quiet]) + end + + # Calculate the dynamic width of the terminal + def dynamic_width + @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput) + end + + def dynamic_width_stty + %x{stty size 2>/dev/null}.split[1].to_i + end + + def dynamic_width_tput + %x{tput cols 2>/dev/null}.to_i + end + + def unix? + RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i + end + + def truncate(string, width) + as_unicode do + chars = string.chars.to_a + if chars.length <= width + chars.join + else + ( chars[0, width - 3].join) + '...' + end + end + end + + if ''.respond_to?(:encode) + def as_unicode + yield + end + else + def as_unicode + old, $KCODE = $KCODE, 'U' + yield + ensure + $KCODE = old + end + end + + def ask_simply(statement, color, options) + default = options[:default] + message = [statement, ("(#{default})" if default), nil].uniq.join(' ') + message = prepare_message(message, color) + result = Thor::LineEditor.readline(message, options) + + return unless result + + result.strip! + + if default && result == '' + default + else + result + end + end + + def ask_filtered(statement, color, options) + answer_set = options[:limited_to] + correct_answer = nil + until correct_answer + answers = answer_set.join(', ') + answer = ask_simply("#{statement} [#{answers}]", color, options) + correct_answer = answer_set.include?(answer) ? answer : nil + say("Your response must be one of: [#{answers}]. Please try again.") unless correct_answer + end + correct_answer + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/shell/color.rb b/bundler-1.7.2/lib/bundler/vendor/thor/shell/color.rb new file mode 100644 index 0000000..db3dcfc --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/shell/color.rb @@ -0,0 +1,149 @@ +require 'thor/shell/basic' + +class Thor + module Shell + # Inherit from Thor::Shell::Basic and add set_color behavior. Check + # Thor::Shell::Basic to see all available methods. + # + class Color < Basic + # Embed in a String to clear all previous ANSI sequences. + CLEAR = "\e[0m" + # The start of an ANSI bold sequence. + BOLD = "\e[1m" + + # Set the terminal's foreground ANSI color to black. + BLACK = "\e[30m" + # Set the terminal's foreground ANSI color to red. + RED = "\e[31m" + # Set the terminal's foreground ANSI color to green. + GREEN = "\e[32m" + # Set the terminal's foreground ANSI color to yellow. + YELLOW = "\e[33m" + # Set the terminal's foreground ANSI color to blue. + BLUE = "\e[34m" + # Set the terminal's foreground ANSI color to magenta. + MAGENTA = "\e[35m" + # Set the terminal's foreground ANSI color to cyan. + CYAN = "\e[36m" + # Set the terminal's foreground ANSI color to white. + WHITE = "\e[37m" + + # Set the terminal's background ANSI color to black. + ON_BLACK = "\e[40m" + # Set the terminal's background ANSI color to red. + ON_RED = "\e[41m" + # Set the terminal's background ANSI color to green. + ON_GREEN = "\e[42m" + # Set the terminal's background ANSI color to yellow. + ON_YELLOW = "\e[43m" + # Set the terminal's background ANSI color to blue. + ON_BLUE = "\e[44m" + # Set the terminal's background ANSI color to magenta. + ON_MAGENTA = "\e[45m" + # Set the terminal's background ANSI color to cyan. + ON_CYAN = "\e[46m" + # Set the terminal's background ANSI color to white. + ON_WHITE = "\e[47m" + + # Set color by using a string or one of the defined constants. If a third + # option is set to true, it also adds bold to the string. This is based + # on Highline implementation and it automatically appends CLEAR to the end + # of the returned String. + # + # Pass foreground, background and bold options to this method as + # symbols. + # + # Example: + # + # set_color "Hi!", :red, :on_white, :bold + # + # The available colors are: + # + # :bold + # :black + # :red + # :green + # :yellow + # :blue + # :magenta + # :cyan + # :white + # :on_black + # :on_red + # :on_green + # :on_yellow + # :on_blue + # :on_magenta + # :on_cyan + # :on_white + def set_color(string, *colors) + if colors.compact.empty? || !can_display_colors? + string + elsif colors.all? { |color| color.is_a?(Symbol) || color.is_a?(String) } + ansi_colors = colors.map { |color| lookup_color(color) } + "#{ansi_colors.join}#{string}#{CLEAR}" + else + # The old API was `set_color(color, bold=boolean)`. We + # continue to support the old API because you should never + # break old APIs unnecessarily :P + foreground, bold = colors + foreground = self.class.const_get(foreground.to_s.upcase) if foreground.is_a?(Symbol) + + bold = bold ? BOLD : '' + "#{bold}#{foreground}#{string}#{CLEAR}" + end + end + + protected + + def can_display_colors? + stdout.tty? + end + + # Overwrite show_diff to show diff with colors if Diff::LCS is + # available. + # + def show_diff(destination, content) #:nodoc: + if diff_lcs_loaded? && ENV['THOR_DIFF'].nil? && ENV['RAILS_DIFF'].nil? + actual = File.binread(destination).to_s.split("\n") + content = content.to_s.split("\n") + + Diff::LCS.sdiff(actual, content).each do |diff| + output_diff_line(diff) + end + else + super + end + end + + def output_diff_line(diff) #:nodoc: + case diff.action + when '-' + say "- #{diff.old_element.chomp}", :red, true + when '+' + say "+ #{diff.new_element.chomp}", :green, true + when '!' + say "- #{diff.old_element.chomp}", :red, true + say "+ #{diff.new_element.chomp}", :green, true + else + say " #{diff.old_element.chomp}", nil, true + end + end + + # Check if Diff::LCS is loaded. If it is, use it to create pretty output + # for diff. + # + def diff_lcs_loaded? #:nodoc: + return true if defined?(Diff::LCS) + return @diff_lcs_loaded unless @diff_lcs_loaded.nil? + + @diff_lcs_loaded = begin + require 'diff/lcs' + true + rescue LoadError + false + end + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/shell/html.rb b/bundler-1.7.2/lib/bundler/vendor/thor/shell/html.rb new file mode 100644 index 0000000..296293b --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/shell/html.rb @@ -0,0 +1,126 @@ +require 'thor/shell/basic' + +class Thor + module Shell + # Inherit from Thor::Shell::Basic and add set_color behavior. Check + # Thor::Shell::Basic to see all available methods. + # + class HTML < Basic + # The start of an HTML bold sequence. + BOLD = 'font-weight: bold' + + # Set the terminal's foreground HTML color to black. + BLACK = 'color: black' + # Set the terminal's foreground HTML color to red. + RED = 'color: red' + # Set the terminal's foreground HTML color to green. + GREEN = 'color: green' + # Set the terminal's foreground HTML color to yellow. + YELLOW = 'color: yellow' + # Set the terminal's foreground HTML color to blue. + BLUE = 'color: blue' + # Set the terminal's foreground HTML color to magenta. + MAGENTA = 'color: magenta' + # Set the terminal's foreground HTML color to cyan. + CYAN = 'color: cyan' + # Set the terminal's foreground HTML color to white. + WHITE = 'color: white' + + # Set the terminal's background HTML color to black. + ON_BLACK = 'background-color: black' + # Set the terminal's background HTML color to red. + ON_RED = 'background-color: red' + # Set the terminal's background HTML color to green. + ON_GREEN = 'background-color: green' + # Set the terminal's background HTML color to yellow. + ON_YELLOW = 'background-color: yellow' + # Set the terminal's background HTML color to blue. + ON_BLUE = 'background-color: blue' + # Set the terminal's background HTML color to magenta. + ON_MAGENTA = 'background-color: magenta' + # Set the terminal's background HTML color to cyan. + ON_CYAN = 'background-color: cyan' + # Set the terminal's background HTML color to white. + ON_WHITE = 'background-color: white' + + # Set color by using a string or one of the defined constants. If a third + # option is set to true, it also adds bold to the string. This is based + # on Highline implementation and it automatically appends CLEAR to the end + # of the returned String. + # + def set_color(string, *colors) + if colors.all? { |color| color.is_a?(Symbol) || color.is_a?(String) } + html_colors = colors.map { |color| lookup_color(color) } + "#{string}" + else + color, bold = colors + html_color = self.class.const_get(color.to_s.upcase) if color.is_a?(Symbol) + styles = [html_color] + styles << BOLD if bold + "#{string}" + end + end + + # Ask something to the user and receives a response. + # + # ==== Example + # ask("What is your name?") + # + # TODO: Implement #ask for Thor::Shell::HTML + def ask(statement, color = nil) + fail NotImplementedError, 'Implement #ask for Thor::Shell::HTML' + end + + protected + + def can_display_colors? + true + end + + # Overwrite show_diff to show diff with colors if Diff::LCS is + # available. + # + def show_diff(destination, content) #:nodoc: + if diff_lcs_loaded? && ENV['THOR_DIFF'].nil? && ENV['RAILS_DIFF'].nil? + actual = File.binread(destination).to_s.split("\n") + content = content.to_s.split("\n") + + Diff::LCS.sdiff(actual, content).each do |diff| + output_diff_line(diff) + end + else + super + end + end + + def output_diff_line(diff) #:nodoc: + case diff.action + when '-' + say "- #{diff.old_element.chomp}", :red, true + when '+' + say "+ #{diff.new_element.chomp}", :green, true + when '!' + say "- #{diff.old_element.chomp}", :red, true + say "+ #{diff.new_element.chomp}", :green, true + else + say " #{diff.old_element.chomp}", nil, true + end + end + + # Check if Diff::LCS is loaded. If it is, use it to create pretty output + # for diff. + # + def diff_lcs_loaded? #:nodoc: + return true if defined?(Diff::LCS) + return @diff_lcs_loaded unless @diff_lcs_loaded.nil? + + @diff_lcs_loaded = begin + require 'diff/lcs' + true + rescue LoadError + false + end + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/util.rb b/bundler-1.7.2/lib/bundler/vendor/thor/util.rb new file mode 100644 index 0000000..a551b7d --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/util.rb @@ -0,0 +1,267 @@ +require 'rbconfig' + +class Thor + module Sandbox #:nodoc: + end + + # This module holds several utilities: + # + # 1) Methods to convert thor namespaces to constants and vice-versa. + # + # Thor::Util.namespace_from_thor_class(Foo::Bar::Baz) #=> "foo:bar:baz" + # + # 2) Loading thor files and sandboxing: + # + # Thor::Util.load_thorfile("~/.thor/foo") + # + module Util + class << self + # Receives a namespace and search for it in the Thor::Base subclasses. + # + # ==== Parameters + # namespace:: The namespace to search for. + # + def find_by_namespace(namespace) + namespace = "default#{namespace}" if namespace.empty? || namespace =~ /^:/ + Thor::Base.subclasses.detect { |klass| klass.namespace == namespace } + end + + # Receives a constant and converts it to a Thor namespace. Since Thor + # commands can be added to a sandbox, this method is also responsable for + # removing the sandbox namespace. + # + # This method should not be used in general because it's used to deal with + # older versions of Thor. On current versions, if you need to get the + # namespace from a class, just call namespace on it. + # + # ==== Parameters + # constant:: The constant to be converted to the thor path. + # + # ==== Returns + # String:: If we receive Foo::Bar::Baz it returns "foo:bar:baz" + # + def namespace_from_thor_class(constant) + constant = constant.to_s.gsub(/^Thor::Sandbox::/, '') + constant = snake_case(constant).squeeze(':') + constant + end + + # Given the contents, evaluate it inside the sandbox and returns the + # namespaces defined in the sandbox. + # + # ==== Parameters + # contents + # + # ==== Returns + # Array[Object] + # + def namespaces_in_content(contents, file = __FILE__) + old_constants = Thor::Base.subclasses.dup + Thor::Base.subclasses.clear + + load_thorfile(file, contents) + + new_constants = Thor::Base.subclasses.dup + Thor::Base.subclasses.replace(old_constants) + + new_constants.map! { |c| c.namespace } + new_constants.compact! + new_constants + end + + # Returns the thor classes declared inside the given class. + # + def thor_classes_in(klass) + stringfied_constants = klass.constants.map { |c| c.to_s } + Thor::Base.subclasses.select do |subclass| + next unless subclass.name + stringfied_constants.include?(subclass.name.gsub("#{klass.name}::", '')) + end + end + + # Receives a string and convert it to snake case. SnakeCase returns snake_case. + # + # ==== Parameters + # String + # + # ==== Returns + # String + # + def snake_case(str) + return str.downcase if str =~ /^[A-Z_]+$/ + str.gsub(/\B[A-Z]/, '_\&').squeeze('_') =~ /_*(.*)/ + $+.downcase + end + + # Receives a string and convert it to camel case. camel_case returns CamelCase. + # + # ==== Parameters + # String + # + # ==== Returns + # String + # + def camel_case(str) + return str if str !~ /_/ && str =~ /[A-Z]+.*/ + str.split('_').map { |i| i.capitalize }.join + end + + # Receives a namespace and tries to retrieve a Thor or Thor::Group class + # from it. It first searches for a class using the all the given namespace, + # if it's not found, removes the highest entry and searches for the class + # again. If found, returns the highest entry as the class name. + # + # ==== Examples + # + # class Foo::Bar < Thor + # def baz + # end + # end + # + # class Baz::Foo < Thor::Group + # end + # + # Thor::Util.namespace_to_thor_class("foo:bar") #=> Foo::Bar, nil # will invoke default command + # Thor::Util.namespace_to_thor_class("baz:foo") #=> Baz::Foo, nil + # Thor::Util.namespace_to_thor_class("foo:bar:baz") #=> Foo::Bar, "baz" + # + # ==== Parameters + # namespace + # + def find_class_and_command_by_namespace(namespace, fallback = true) + if namespace.include?(':') # look for a namespaced command + pieces = namespace.split(':') + command = pieces.pop + klass = Thor::Util.find_by_namespace(pieces.join(':')) + end + unless klass # look for a Thor::Group with the right name + klass, command = Thor::Util.find_by_namespace(namespace), nil + end + if !klass && fallback # try a command in the default namespace + command = namespace + klass = Thor::Util.find_by_namespace('') + end + [klass, command] + end + alias_method :find_class_and_task_by_namespace, :find_class_and_command_by_namespace + + # Receives a path and load the thor file in the path. The file is evaluated + # inside the sandbox to avoid namespacing conflicts. + # + def load_thorfile(path, content = nil, debug = false) + content ||= File.binread(path) + + begin + Thor::Sandbox.class_eval(content, path) + rescue StandardError => e + $stderr.puts("WARNING: unable to load thorfile #{path.inspect}: #{e.message}") + if debug + $stderr.puts(*e.backtrace) + else + $stderr.puts(e.backtrace.first) + end + end + end + + def user_home # rubocop:disable MethodLength + @@user_home ||= if ENV['HOME'] + ENV['HOME'] + elsif ENV['USERPROFILE'] + ENV['USERPROFILE'] + elsif ENV['HOMEDRIVE'] && ENV['HOMEPATH'] + File.join(ENV['HOMEDRIVE'], ENV['HOMEPATH']) + elsif ENV['APPDATA'] + ENV['APPDATA'] + else + begin + File.expand_path('~') + rescue + if File::ALT_SEPARATOR + 'C:/' + else + '/' + end + end + end + end + + # Returns the root where thor files are located, depending on the OS. + # + def thor_root + File.join(user_home, '.thor').gsub(/\\/, '/') + end + + # Returns the files in the thor root. On Windows thor_root will be something + # like this: + # + # C:\Documents and Settings\james\.thor + # + # If we don't #gsub the \ character, Dir.glob will fail. + # + def thor_root_glob + files = Dir["#{escape_globs(thor_root)}/*"] + + files.map! do |file| + File.directory?(file) ? File.join(file, 'main.thor') : file + end + end + + # Where to look for Thor files. + # + def globs_for(path) + path = escape_globs(path) + ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"] + end + + # Return the path to the ruby interpreter taking into account multiple + # installations and windows extensions. + # + def ruby_command # rubocop:disable MethodLength + @ruby_command ||= begin + ruby_name = RbConfig::CONFIG['ruby_install_name'] + ruby = File.join(RbConfig::CONFIG['bindir'], ruby_name) + ruby << RbConfig::CONFIG['EXEEXT'] + + # avoid using different name than ruby (on platforms supporting links) + if ruby_name != 'ruby' && File.respond_to?(:readlink) + begin + alternate_ruby = File.join(RbConfig::CONFIG['bindir'], 'ruby') + alternate_ruby << RbConfig::CONFIG['EXEEXT'] + + # ruby is a symlink + if File.symlink? alternate_ruby + linked_ruby = File.readlink alternate_ruby + + # symlink points to 'ruby_install_name' + ruby = alternate_ruby if linked_ruby == ruby_name || linked_ruby == ruby + end + rescue NotImplementedError # rubocop:disable HandleExceptions + # just ignore on windows + end + end + + # escape string in case path to ruby executable contain spaces. + ruby.sub!(/.*\s.*/m, '"\&"') + ruby + end + end + + # Returns a string that has had any glob characters escaped. + # The glob characters are `* ? { } [ ]`. + # + # ==== Examples + # + # Thor::Util.escape_globs('[apps]') # => '\[apps\]' + # + # ==== Parameters + # String + # + # ==== Returns + # String + # + def escape_globs(path) + path.to_s.gsub(/[*?{}\[\]]/, '\\\\\\&') + end + end + end +end diff --git a/bundler-1.7.2/lib/bundler/vendor/thor/version.rb b/bundler-1.7.2/lib/bundler/vendor/thor/version.rb new file mode 100644 index 0000000..41784aa --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendor/thor/version.rb @@ -0,0 +1,3 @@ +class Thor + VERSION = '0.18.1' +end diff --git a/bundler-1.7.2/lib/bundler/vendored_persistent.rb b/bundler-1.7.2/lib/bundler/vendored_persistent.rb new file mode 100644 index 0000000..8ed4ce8 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendored_persistent.rb @@ -0,0 +1,11 @@ +# We forcibly require OpenSSL, because net/http/persistent will only autoload +# it. On some Rubies, autoload fails but explicit require succeeds. +begin + require 'openssl' +rescue LoadError + # some Ruby builds don't have OpenSSL +end + +vendor = File.expand_path('../vendor', __FILE__) +$:.unshift(vendor) unless $:.include?(vendor) +require 'net/http/persistent' diff --git a/bundler-1.7.2/lib/bundler/vendored_thor.rb b/bundler-1.7.2/lib/bundler/vendored_thor.rb new file mode 100644 index 0000000..a643426 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vendored_thor.rb @@ -0,0 +1,8 @@ +if defined?(Thor) + Bundler.ui.warn "Thor has already been required. " + + "This may cause Bundler to malfunction in unexpected ways." +end +vendor = File.expand_path('../vendor', __FILE__) +$:.unshift(vendor) unless $:.include?(vendor) +require 'thor' +require 'thor/actions' diff --git a/bundler-1.7.2/lib/bundler/version.rb b/bundler-1.7.2/lib/bundler/version.rb new file mode 100644 index 0000000..8374d41 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/version.rb @@ -0,0 +1,6 @@ +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.2" unless defined?(::Bundler::VERSION) +end diff --git a/bundler-1.7.2/lib/bundler/vlad.rb b/bundler-1.7.2/lib/bundler/vlad.rb new file mode 100644 index 0000000..aaf7145 --- /dev/null +++ b/bundler-1.7.2/lib/bundler/vlad.rb @@ -0,0 +1,11 @@ +# Vlad task for Bundler. +# +# Just add "require 'bundler/vlad'" in your Vlad deploy.rb, and +# include the vlad:bundle:install task in your vlad:deploy task. +require 'bundler/deployment' + +include Rake::DSL if defined? Rake::DSL + +namespace :vlad do + Bundler::Deployment.define_task(Rake::RemoteTask, :remote_task, :roles => :app) +end diff --git a/bundler-1.7.2/man/bundle-config.ronn b/bundler-1.7.2/man/bundle-config.ronn new file mode 100644 index 0000000..d6dfaf5 --- /dev/null +++ b/bundler-1.7.2/man/bundle-config.ronn @@ -0,0 +1,155 @@ +bundle-config(1) -- Set bundler configuration options +===================================================== + +## SYNOPSIS + +`bundle config` [ []] + +## DESCRIPTION + +This command allows you to interact with bundler's configuration system. +Bundler retrieves its configuration from the local application (`app/.bundle/config`), +environment variables, and the user's home directory (`~/.bundle/config`), +in that order of priority. + +Executing `bundle config` with no parameters will print a list of all +bundler configuration for the current bundle, and where that configuration +was set. + +Executing `bundle config ` will print the value of that configuration +setting, and where it was set. + +Executing `bundle config ` will set that configuration to the +value specified for all bundles executed as the current user. The configuration +will be stored in `~/.bundle/config`. If already is set, will be +overridden and user will be warned. + +Executing `bundle config --global ` works the same as above. + +Executing `bundle config --local ` will set that configuration to +the local application. The configuration will be stored in `app/.bundle/config`. + +Executing `bundle config --delete ` will delete the configuration in both +local and global sources. Not compatible with --global or --local flag. + +Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will +cause it to ignore all configuration. + +## BUILD OPTIONS + +You can use `bundle config` to give bundler the flags to pass to the gem +installer every time bundler tries to install a particular gem. + +A very common example, the `mysql` gem, requires Snow Leopard users to +pass configuration flags to `gem install` to specify where to find the +`mysql_config` executable. + + gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config + +Since the specific location of that executable can change from machine +to machine, you can specify these flags on a per-machine basis. + + bundle config build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config + +After running this command, every time bundler needs to install the +`mysql` gem, it will pass along the flags you specified. + +## CONFIGURATION KEYS + +Configuration keys in bundler have two forms: the canonical form and the +environment variable form. + +For instance, passing the `--without` flag to [bundle install(1)][bundle-install] +prevents Bundler from installing certain groups specified in the Gemfile(5). Bundler +persists this value in `app/.bundle/config` so that calls to `Bundler.setup` +do not try to find gems from the `Gemfile` that you didn't install. Additionally, +subsequent calls to [bundle install(1)][bundle-install] remember this setting and skip those +groups. + +The canonical form of this configuration is `"without"`. To convert the canonical +form to the environment variable form, capitalize it, and prepend `BUNDLE_`. The +environment variable form of `"without"` is `BUNDLE_WITHOUT`. + +## LIST OF AVAILABLE KEYS + +The following is a list of all configuration keys and their purpose. You can +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 +* `frozen` (`BUNDLE_FROZEN`): + Disallow changes to the `Gemfile`. Defaults to `true` when `--deployment` + is used. +* `without` (`BUNDLE_WITHOUT`): + A `:`-separated list of groups whose gems bundler should not install +* `bin` (`BUNDLE_BIN`): + Install executables from gems in the bundle to the specified directory. + Defaults to `false`. +* `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. +* `ssl_client_cert` (`BUNDLE_SSL_CLIENT_CERT`): + Path to a designated file containing a X.509 client certificate + and key in PEM format. + +In general, you should set these settings per-application by using the applicable +flag to the [bundle install(1)][bundle-install] command. + +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 +instead of using the remote version. This can be achieved by setting +up a local override: + + bundle config local.GEM_NAME /path/to/local/git/repository + +For example, in order to use a local Rack repository, a developer could call: + + bundle config local.rack ~/Work/git/rack + +Now instead of checking out the remote git repository, the local +override will be used. Similar to a path source, every time the local +git repository change, changes will be automatically picked up by +Bundler. This means a commit in the local git repo will update the +revision in the `Gemfile.lock` to the local git repo revision. This +requires the same attention as git submodules. Before pushing to +the remote, you need to ensure the local override was pushed, otherwise +you may point to a commit that only exists in your local machine. + +Bundler does many checks to ensure a developer won't work with +invalid references. Particularly, we force a developer to specify +a branch in the `Gemfile` in order to use this feature. If the branch +specified in the `Gemfile` and the current branch in the local git +repository do not match, Bundler will abort. This ensures that +a developer is always working against the correct branches, and prevents +accidental locking to a different branch. + +Finally, Bundler also ensures that the current revision in the +`Gemfile.lock` exists in the local git repository. By doing this, Bundler +forces you to fetch the latest changes in the remotes. + +## MIRRORS OF GEM REPOSITORIES + +Bundler supports overriding gem sources with mirrors. This allows you to +configure rubygems.org as the gem source in your Gemfile while still using your +mirror to fetch gems. + + bundle config mirror.http://rubygems.org http://rubygems-mirror.org + diff --git a/bundler-1.7.2/man/bundle-exec.ronn b/bundler-1.7.2/man/bundle-exec.ronn new file mode 100644 index 0000000..ba6844c --- /dev/null +++ b/bundler-1.7.2/man/bundle-exec.ronn @@ -0,0 +1,136 @@ +bundle-exec(1) -- Execute a command in the context of the bundle +================================================================ + +## SYNOPSIS + +`bundle exec` [--keep-file-descriptors] + +## DESCRIPTION + +This command executes the command, making all gems specified in the +`Gemfile(5)` available to `require` in Ruby programs. + +Essentially, if you would normally have run something like +`rspec spec/my_spec.rb`, and you want to use the gems specified +in the `Gemfile(5)` and installed via [bundle install(1)][bundle-install], you +should run `bundle exec rspec spec/my_spec.rb`. + +Note that `bundle exec` does not require that an executable is +available on your shell's `$PATH`. + +## OPTIONS + +* `--keep-file-descriptors`: + Exec in Ruby 2.0 began discarding non-standard file descriptors. When this + flag is passed, exec will revert to the 1.9 behaviour of passing all file + descriptors to the new process. + +## BUNDLE INSTALL --BINSTUBS + +If you use the `--binstubs` flag in [bundle install(1)][bundle-install], Bundler will +automatically create a directory (which defaults to `app_root/bin`) +containing all of the executables available from gems in the bundle. + +After using `--binstubs`, `bin/rspec spec/my_spec.rb` is identical +to `bundle exec rspec spec/my_spec.rb`. + +## ENVIRONMENT MODIFICATIONS + +`bundle exec` makes a number of changes to the shell environment, +then executes the command you specify in full. + +* make sure that it's still possible to shell out to `bundle` + from inside a command invoked by `bundle exec` (using + `$BUNDLE_BIN_PATH`) +* put the directory containing executables (like `rails`, `rspec`, + `rackup`) for your bundle on `$PATH` +* make sure that if bundler is invoked in the subshell, it uses + the same `Gemfile` (by setting `BUNDLE_GEMFILE`) +* add `-rbundler/setup` to `$RUBYOPT`, which makes sure that + Ruby programs invoked in the subshell can see the gems in + the bundle + +It also modifies Rubygems: + +* disallow loading additional gems not in the bundle +* modify the `gem` method to be a no-op if a gem matching + the requirements is in the bundle, and to raise a + `Gem::LoadError` if it's not +* Define `Gem.refresh` to be a no-op, since the source + index is always frozen when using bundler, and to + prevent gems from the system leaking into the environment +* Override `Gem.bin_path` to use the gems in the bundle, + making system executables work +* Add all gems in the bundle into Gem.loaded_specs + +### Shelling out + +Any Ruby code that opens a subshell (like `system`, backticks, or `%x{}`) will +automatically use the current Bundler environment. If you need to shell out to +a Ruby command that is not part of your current bundle, use the +`with_clean_env` method with a block. Any subshells created inside the block +will be given the environment present before Bundler was activated. For +example, Homebrew commands run Ruby, but don't work inside a bundle: + + Bundler.with_clean_env do + `brew install wget` + end + +Using `with_clean_env` is also necessary if you are shelling out to a different +bundle. Any Bundler commands run in a subshell will inherit the current +Gemfile, so commands that need to run in the context of a different bundle also +need to use `with_clean_env`. + + Bundler.with_clean_env do + Dir.chdir "/other/bundler/project" do + `bundle exec ./script` + end + end + +Bundler provides convenience helpers that wrap `system` and `exec`, and they +can be used like this: + + Bundler.clean_system('brew install wget') + Bundler.clean_exec('brew install wget') + + +## RUBYGEMS PLUGINS + +At present, the Rubygems plugin system requires all files +named `rubygems_plugin.rb` on the load path of _any_ installed +gem when any Ruby code requires `rubygems.rb`. This includes +executables installed into the system, like `rails`, `rackup`, +and `rspec`. + +Since Rubygems plugins can contain arbitrary Ruby code, they +commonly end up activating themselves or their dependencies. + +For instance, the `gemcutter 0.5` gem depended on `json_pure`. +If you had that version of gemcutter installed (even if +you _also_ had a newer version without this problem), Rubygems +would activate `gemcutter 0.5` and `json_pure `. + +If your Gemfile(5) also contained `json_pure` (or a gem +with a dependency on `json_pure`), the latest version on +your system might conflict with the version in your +Gemfile(5), or the snapshot version in your `Gemfile.lock`. + +If this happens, bundler will say: + + You have already activated json_pure 1.4.6 but your Gemfile + requires json_pure 1.4.3. Consider using bundle exec. + +In this situation, you almost certainly want to remove the +underlying gem with the problematic gem plugin. In general, +the authors of these plugins (in this case, the `gemcutter` +gem) have released newer versions that are more careful in +their plugins. + +You can find a list of all the gems containing gem plugins +by running + + ruby -rubygems -e "puts Gem.find_files('rubygems_plugin.rb')" + +At the very least, you should remove all but the newest +version of each gem plugin, and also remove all gem plugins +that you aren't using (`gem uninstall gem_name`). diff --git a/bundler-1.7.2/man/bundle-install.ronn b/bundler-1.7.2/man/bundle-install.ronn new file mode 100644 index 0000000..a444833 --- /dev/null +++ b/bundler-1.7.2/man/bundle-install.ronn @@ -0,0 +1,372 @@ +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] + [--clean] + [--full-index] + [--no-prune] + [--shebang] + +## 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 +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 +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 +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=`: + 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. + +* `--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]. + +* `--system`: + Installs the gems in the bundle to the system location. This + overrides any previous [remembered][REMEMBERED OPTIONS] use of + `--path`. + +* `--without=`: + A space-separated list of groups to skip installing. This is a + [remembered option][REMEMBERED OPTIONS]. + +* `--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. + +* `--deployment`: + Switches bundler's defaults into [deployment mode][DEPLOYMENT MODE]. + Do not use this flag on development machines. + +* `--binstubs[=]`: + 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. + +* `--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. + +* `--standalone[=]`: + 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. + +* `--trust-policy=[]`: + Apply the Rubygems security policy named , where policy is one of + HighSecurity, MediumSecurity, LowSecurity, AlmostNoSecurity, or NoSecurity. + For more detail, see the Rubygems signing documentation, linked below in + [SEE ALSO][]. + +* `--jobs=[]`: + Install gems parallely by starting number of parallel workers. + +* `--retry[ 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. + +* `--quiet`: + Do not print progress information to stdout. Instead, communicate the + success of the install operation via exit status code. + +* `--clean`: + Run bundle clean automatically after install. + +* `--full-index`: + Use the rubygems modern index instead of the API endpoint. + +* `--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. + +1. A `Gemfile.lock` is required. + + To ensure that the same versions of the gems you developed with + and tested with are also used in deployments, a `Gemfile.lock` + is required. + + This is mainly to ensure that you remember to check your + `Gemfile.lock` into version control. + +2. The `Gemfile.lock` must be up to date + + In development, you can modify your Gemfile(5) and re-run + `bundle install` to [conservatively update][CONSERVATIVE UPDATING] + your `Gemfile.lock` snapshot. + + In deployment, your `Gemfile.lock` should be up-to-date with + changes made in your Gemfile(5). + +3. Gems are installed to `vendor/bundle` not your default system location + + In development, it's convenient to share the gems used in your + application with other applications and other scripts run on + the system. + + In deployment, isolation is a more important default. In addition, + the user deploying the application may not have permission to install + gems to the system, or the web server may not have permission to + read them. + + As a result, `bundle install --deployment` installs gems to + the `vendor/bundle` directory in the application. This may be + overridden using the `--path` option. + +## SUDO USAGE + +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, +then ask you for your `sudo` password in order to copy the gems into +their system location. + +From your perspective, this is identical to installing them gems +directly into the system. + +You should never use `sudo bundle install`. This is because several +other steps in `bundle install` must be performed as the current user: + +* Updating your `Gemfile.lock` +* Updating your `vendor/cache`, if necessary +* Checking out private git repositories using your user's SSH keys + +Of these three, the first two could theoretically be performed by +`chown`ing the resulting files to `$SUDO_USER`. The third, however, +can only be performed by actually invoking the `git` command as +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 +gems into their final location. + +## INSTALLING GROUPS + +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 +certain groups with the `--without` option. This option takes +a space-separated list of groups. + +While the `--without` option will skip _installing_ the gems in the +specified groups, it will still _download_ those gems and use them to +resolve the dependencies of every gem in your Gemfile(5). + +This is so that installing a different set of groups on another + machine (such as a production server) will not change the +gems and versions that you have already developed and tested against. + +`Bundler offers a rock-solid guarantee that the third-party +code you are running in development and testing is also the +third-party code you are running in production. You can choose +to exclude some of that code in different environments, but you +will never be caught flat-footed by different versions of +third-party code being used in different environments.` + +For a simple illustration, consider the following Gemfile(5): + + source "https://rubygems.org" + + gem "sinatra" + + group :production do + gem "rack-perftools-profiler" + end + +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 +when the `production` group _is_ used. + +This should not cause any problems in practice, because we do not +attempt to `install` the gems in the excluded groups, and only evaluate +as part of the dependency resolution process. + +This also means that you cannot include different versions of the same +gem in different groups, because doing so would result in different +sets of dependencies used in development and production. Because of +the vagaries of the dependency resolution process, this usually +affects more than just the gems you list in your Gemfile(5), and can +(surprisingly) radically change the gems you are using. + +## REMEMBERED OPTIONS + +Some options (marked above in the [OPTIONS][] section) are remembered +between calls to `bundle install`, and by the Bundler runtime. + +For instance, if you run `bundle install --without test`, a subsequent +call to `bundle install` that does not include a `--without` flag will +remember your previous choice. + +In addition, a call to `Bundler.setup` will not attempt to make the +gems in those groups available on the Ruby load path, as they were +not installed. + +The settings that are remembered are: + +* `--deployment`: + At runtime, this remembered setting will also result in Bundler + raising an exception if the `Gemfile.lock` is out of date. + +* `--path`: + Subsequent calls to `bundle install` will install gems to the + directory originally passed to `--path`. The Bundler runtime + will look for gems in that location. You can revert this + option by running `bundle install --system`. + +* `--binstubs`: + Bundler will update the executables every subsequent call to + `bundle install`. + +* `--without`: + As described above, Bundler will skip the gems specified by + `--without` in subsequent calls to `bundle install`. The + Bundler runtime will also not try to make the gems in the + skipped groups available. + +## THE GEMFILE.LOCK + +When you run `bundle install`, Bundler will persist the full names +and versions of all gems that you used (including dependencies of +the gems specified in the Gemfile(5)) into a file called `Gemfile.lock`. + +Bundler uses this file in all subsequent calls to `bundle install`, +which guarantees that you always use the same exact code, even +as your application moves across machines. + +Because of the way dependency resolution works, even a +seemingly small change (for instance, an update to a point-release +of a dependency of a gem in your Gemfile(5)) can result in radically +different gems being needed to satisfy all dependencies. + +As a result, you `SHOULD` check your `Gemfile.lock` into version +control. If you do not, every machine that checks out your +repository (including your production server) will resolve all +dependencies again, which will result in different versions of +third-party code being used if `any` of the gems in the Gemfile(5) +or any of their dependencies have been updated. + +## CONSERVATIVE UPDATING + +When you make a change to the Gemfile(5) and then run `bundle install`, +Bundler will update only the gems that you modified. + +In other words, if a gem that you `did not modify` worked before +you called `bundle install`, it will continue to use the exact +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" + + 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` +and `rack ~> 1.1.0`, while the `activemerchant` gem depends on +`activesupport >= 2.3.2`, `braintree >= 2.0.0`, and `builder >= 2.0.0`. + +When the dependencies are first resolved, Bundler will select +`activesupport 2.3.8`, which satisfies the requirements of both +gems in your Gemfile(5). + +Next, you modify your Gemfile(5) to: + + source "https://rubygems.org" + + 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 +the `rack` dependency to `~> 1.2.1`. + +When you run `bundle install`, Bundler notices that you changed +the `actionpack` gem, but not the `activemerchant` gem. It +evaluates the gems currently being used to satisfy its requirements: + + * `activesupport 2.3.8`: + also used to satisfy a dependency in `activemerchant`, + which is not being updated + * `rack ~> 1.1.0`: + not currently being used to satisfy another dependency + +Because you did not explicitly ask to update `activemerchant`, +you would not expect it to suddenly stop working after updating +`actionpack`. However, satisfying the new `activesupport 3.0.0.rc` +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 +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`, +so `bundle install` will report that it cannot update `actionpack`. + +To explicitly update `actionpack`, including its dependencies +which other gems in the Gemfile(5) still depend on, run +`bundle update actionpack` (see `bundle update(1)`). + +`Summary`: In general, after making a change to the Gemfile(5) , you +should first try to run `bundle install`, which will guarantee that no +other gems in the Gemfile(5) are impacted by the change. If that +does not work, run [bundle update(1)][bundle-update]. + +## SEE ALSO + +* Gem install docs: http://guides.rubygems.org/rubygems-basics/#installing-gems +* Rubygems signing docs: http://guides.rubygems.org/security/ diff --git a/bundler-1.7.2/man/bundle-package.ronn b/bundler-1.7.2/man/bundle-package.ronn new file mode 100644 index 0000000..610f820 --- /dev/null +++ b/bundler-1.7.2/man/bundle-package.ronn @@ -0,0 +1,59 @@ +bundle-package(1) -- Package your needed `.gem` files into your application +=========================================================================== + +## SYNOPSIS + +`bundle package` + +## DESCRIPTION + +Copy all of the `.gem` files needed to run the application into the +`vendor/cache` directory. In the future, when running [bundle install(1)][bundle-install], +use the gems in the cache in preference to the ones on `rubygems.org`. + +## GIT AND PATH GEMS + +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. + +## REMOTE FETCHING + +By default, if you simply run [bundle install(1)][bundle-install] after running +[bundle package(1)][bundle-package], bundler will still connect to `rubygems.org` +to check whether a platform-specific gem exists for any of the gems +in `vendor/cache`. + +For instance, consider this Gemfile(5): + + source "https://rubygems.org" + + gem "nokogiri" + +If you run `bundle package` under C Ruby, bundler will retrieve +the version of `nokogiri` for the `"ruby"` platform. If you deploy +to JRuby and run `bundle install`, bundler is forced to check to +see whether a `"java"` platformed `nokogiri` exists. + +Even though the `nokogiri` gem for the Ruby platform is +_technically_ acceptable on JRuby, it actually has a C extension +that does not run on JRuby. As a result, bundler will, by default, +still connect to `rubygems.org` to check whether it has a version +of one of your gems more specific to your platform. + +This problem is also not just limited to the `"java"` platform. +A similar (common) problem can happen when developing on Windows +and deploying to Linux, or even when developing on OSX and +deploying to Linux. + +If you know for sure that the gems packaged in `vendor/cache` +are appropriate for the platform you are on, you can run +`bundle install --local` to skip checking for more appropriate +gems, and just use the ones in `vendor/cache`. + +One way to be sure that you have the right platformed versions +of all your gems is to run `bundle package` on an identical +machine and check in the gems. For instance, you can run +`bundle package` on an identical staging box during your +staging process, and check in the `vendor/cache` before +deploying to production. diff --git a/bundler-1.7.2/man/bundle-platform.ronn b/bundler-1.7.2/man/bundle-platform.ronn new file mode 100644 index 0000000..922a9f1 --- /dev/null +++ b/bundler-1.7.2/man/bundle-platform.ronn @@ -0,0 +1,42 @@ +bundle-platform(1) -- Displays platform compatibility information +================================================================= + +## SYNOPSIS + +`bundle platform` [--ruby] + +## DESCRIPTION + +`platform` will display information from your Gemfile, Gemfile.lock, and Ruby +VM about your platform. + +For instance, using this Gemfile(5): + + source "https://rubygems.org" + + ruby "1.9.3" + + gem "rack" + +If you run `bundle platform` on Ruby 1.9.3, it will display the following output: + + Your platform is: x86_64-linux + + Your app has gems that work on these platforms: + * ruby + + Your Gemfile specifies a Ruby version requirement: + * ruby 1.9.3 + + Your current platform satisfies the Ruby version requirement. + +`platform` will list all the platforms in your `Gemfile.lock` as well as the +`ruby` directive if applicable from your Gemfile(5). It will also let you know +if the `ruby` directive requirement has been met. If `ruby` directive doesn't +match the running Ruby VM, it will tell you what part does not. + +## OPTIONS + +* `--ruby`: + It will just display the ruby directive information, so you don't have to + parse it from the Gemfile(5). diff --git a/bundler-1.7.2/man/bundle-update.ronn b/bundler-1.7.2/man/bundle-update.ronn new file mode 100644 index 0000000..3ac60c5 --- /dev/null +++ b/bundler-1.7.2/man/bundle-update.ronn @@ -0,0 +1,179 @@ +bundle-update(1) -- Update your gems to the latest available versions +===================================================================== + +## SYNOPSIS + +`bundle update` <*gems> [--source=NAME] [--local] + +## DESCRIPTION + +Update the gems specified (all gems, if none are specified), ignoring +the previously installed gems specified in the `Gemfile.lock`. In +general, you should use [bundle install(1)][bundle-install] to install the same exact +gems and versions across machines. + +You would use `bundle update` to explicitly update the version of a +gem. + +## OPTIONS + +* `--source=`: + 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`, + you would call `bundle update --source rails` + +* `--local`: + Do not attempt to fetch gems remotely and use the gem cache instead. + +## UPDATING ALL GEMS + +If you run `bundle update` with no parameters, bundler will ignore +any previously installed gems and resolve all dependencies again +based on the latest versions of all gems available in the sources. + +Consider the following Gemfile(5): + + source "https://rubygems.org" + + gem "rails", "3.0.0.rc" + gem "nokogiri" + +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. + +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 +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. + +After checking in the `Gemfile.lock` into version control and cloning it on another +machine, running [bundle install(1)][bundle-install] will _still_ install the gems that you installed +last time. You don't need to worry that a new release of `erubis` or `mail` changes +the gems you use. + +However, from time to time, you might want to update the gems you are using to the +newest versions that still match the gems in your Gemfile(5). + +To do this, run `bundle update`, which will ignore the `Gemfile.lock`, and resolve +all the dependencies again. Keep in mind that this process can result in a significantly +different set of the 25 gems, based on the requirements of new gems that the gem +authors released since the last time you ran `bundle update`. + +## UPDATING A LIST OF GEMS + +Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of the +gems that you specified locked to the versions in the `Gemfile.lock`. + +For instance, in the scenario above, imagine that `nokogiri` releases version `1.4.4`, and +you want to update it _without_ updating Rails and all of its dependencies. To do this, +run `bundle update nokogiri`. + +Bundler will update `nokogiri` and any of its dependencies, but leave alone Rails and +its dependencies. + +## OVERLAPPING DEPENDENCIES + +Sometimes, multiple gems declared in your Gemfile(5) are satisfied by the same +second-level dependency. For instance, consider the case of `thin` and +`rack-perftools-profiler`. + + source "https://rubygems.org" + + gem "thin" + gem "rack-perftools-profiler" + +The `thin` gem depends on `rack >= 1.0`, while `rack-perftools-profiler` depends +on `rack ~> 1.0`. If you run bundle install, you get: + + Fetching source index for https://rubygems.org/ + Installing daemons (1.1.0) + Installing eventmachine (0.12.10) with native extensions + Installing open4 (1.0.1) + Installing perftools.rb (0.4.7) with native extensions + Installing rack (1.2.1) + Installing rack-perftools_profiler (0.0.2) + Installing thin (1.2.7) with native extensions + Using bundler (1.0.0.rc.3) + +In this case, the two gems have their own set of dependencies, but they share +`rack` in common. If you run `bundle update thin`, bundler will update `daemons`, +`eventmachine` and `rack`, which are dependencies of `thin`, but not `open4` or +`perftools.rb`, which are dependencies of `rack-perftools_profiler`. Note that +`bundle update thin` will update `rack` even though it's _also_ a dependency of +`rack-perftools_profiler`. + +`In short`, when you update a gem using `bundle update`, bundler will update all +dependencies of that gem, including those that are also dependencies of another gem. + +In this scenario, updating the `thin` version manually in the Gemfile(5), +and then running [bundle install(1)][bundle-install] will only update `daemons` and `eventmachine`, +but not `rack`. For more information, see the `CONSERVATIVE UPDATING` section +of [bundle install(1)][bundle-install]. + +## RECOMMENDED WORKFLOW + +In general, when working with an application managed with bundler, you should +use the following workflow: + +* After you create your Gemfile(5) for the first time, run + + $ bundle install + +* Check the resulting `Gemfile.lock` into version control + + $ git add Gemfile.lock + +* When checking out this repository on another development machine, run + + $ bundle install + +* When checking out this repository on a deployment machine, run + + $ bundle install --deployment + +* After changing the Gemfile(5) to reflect a new or update dependency, run + + $ bundle install + +* Make sure to check the updated `Gemfile.lock` into version control + + $ git add Gemfile.lock + +* If [bundle install(1)][bundle-install] reports a conflict, manually update the specific + gems that you changed in the Gemfile(5) + + $ bundle update rails thin + +* If you want to update all the gems to the latest possible versions that + still match the gems listed in the Gemfile(5), run + + $ bundle update diff --git a/bundler-1.7.2/man/bundle.ronn b/bundler-1.7.2/man/bundle.ronn new file mode 100644 index 0000000..1167b0b --- /dev/null +++ b/bundler-1.7.2/man/bundle.ronn @@ -0,0 +1,92 @@ +bundle(1) -- Ruby Dependency Management +======================================= + +## SYNOPSIS + +`bundle` COMMAND [--no-color] [--verbose] [ARGS] + +## DESCRIPTION + +Bundler manages an `application's dependencies` through its entire life +across many machines systematically and repeatably. + +See [the bundler website](http://bundler.io) for information on getting +started, and Gemfile(5) for more information on the `Gemfile` format. + +## OPTIONS + +* `--no-color`: + Prints all output without color + +* `--verbose`: + Prints out additional logging information + +## BUNDLE COMMANDS + +We divide `bundle` subcommands into primary commands and utilities. + +## PRIMARY COMMANDS + +* [bundle install(1)][bundle-install]: + Install the gems specified by the `Gemfile` or `Gemfile.lock` + +* [bundle update(1)][bundle-update]: + Update dependencies to their latest versions + +* [bundle package(1)][bundle-package]: + Package the .gem files required by your application into the + `vendor/cache` directory + +* [bundle exec(1)][bundle-exec]: + Execute a script in the context of the current bundle + +* [bundle config(1)][bundle-config]: + Specify and read configuration options for bundler + +* `bundle help(1)`: + Displays detailed help for each subcommand + +## UTILITIES + +* `bundle check(1)`: + Determine whether the requirements for your application are installed + and available to bundler + +* `bundle list(1)`: + Show all of the gems in the current bundle + +* `bundle show(1)`: + Show the source location of a particular gem in the bundle + +* `bundle outdated(1)`: + Show all of the outdated gems in the current bundle + +* `bundle console(1)`: + Start an IRB session in the context of the current bundle + +* `bundle open(1)`: + Open an installed gem in the editor + +* `bundle viz(1)`: + Generate a visual representation of your dependencies + +* `bundle init(1)`: + Generate a simple `Gemfile`, placed in the current directory + +* `bundle gem(1)`: + Create a simple gem, suitable for development with bundler + +* [bundle platform(1)][bundle-platform]: + Displays platform compatibility information + +* `bundle clean(1)`: + Cleans up unused gems in your bundler directory + +## OBSOLETE + +These commands are obsolete and should no longer be used + +* `bundle lock(1)` +* `bundle unlock(1)` +* `bundle cache(1)` + diff --git a/bundler-1.7.2/man/gemfile.5.ronn b/bundler-1.7.2/man/gemfile.5.ronn new file mode 100644 index 0000000..f94273a --- /dev/null +++ b/bundler-1.7.2/man/gemfile.5.ronn @@ -0,0 +1,387 @@ +Gemfile(5) -- A format for describing gem dependencies for Ruby programs +======================================================================== + +## SYNOPSIS + +A `Gemfile` describes the gem dependencies required to execute associated +Ruby code. + +Place the `Gemfile` in the root of the directory containing the associated +code. For instance, in a Rails application, place the `Gemfile` in the same +directory as the `Rakefile`. + +## SYNTAX + +A `Gemfile` is evaluated as Ruby code, in a context which makes available +a number of methods used to describe the gem requirements. + +## GLOBAL SOURCES (#source) + +At the top of the `Gemfile`, add a line for the `Rubygems` source that contains +the gems listed in the `Gemfile`. + + source "https://rubygems.org" + +It is possible, but not recommended as of Bundler 1.7, to add multiple global +`source` lines. Each of these `source`s `MUST` be a valid Rubygems repository. + +Sources are checked for gems following the heuristics described in +[SOURCE PRIORITY][]. If a gem is found in more than one global source, Bundler +will print a warning after installing the gem indicating which source was used, +and listing the other sources where the gem is available. A specific source can +be selected for gems that need to use a non-standard repository, suppressing +this warning, by using the [`:source` option](#SOURCE-source-) or a +[`source` block](#BLOCK-FORM-OF-SOURCE-GIT-PATH-GROUP-and-PLATFORMS). + +## RUBY (#ruby) + +If your application requires a specific Ruby version or engine, specify your +requirements using the `ruby` method, with the following arguments. +All parameters are `OPTIONAL` unless otherwise specified. + +### VERSION (required) + +The version of Ruby that your application requires. If your application +requires an alternate Ruby engine, such as JRuby or Rubinius, this should be +the Ruby version that the engine is compatible with. + + ruby "1.9.3" + +### ENGINE (:engine) + +Each application _may_ specify a Ruby engine. If an engine is specified, an +engine version _must_ also be specified. + +### ENGINE VERSION (:engine_version) + +Each application _may_ specify a Ruby engine version. If an engine version is +specified, an engine _must_ also be specified. If the engine is "ruby" the +engine version specified _must_ match the Ruby version. + + ruby "1.8.7", :engine => "jruby", :engine_version => "1.6.7" + +### PATCHLEVEL (:patchlevel) + +Each application _may_ specify a Ruby patchlevel. + + ruby "2.0.0", :patchlevel => "247" + +## GEMS (#gem) + +Specify gem requirements using the `gem` method, with the following arguments. +All parameters are `OPTIONAL` unless otherwise specified. + +### NAME (required) + +For each gem requirement, list a single _gem_ line. + + gem "nokogiri" + +### VERSION + +Each _gem_ `MAY` have one or more version specifiers. + + gem "nokogiri", ">= 1.4.2" + gem "RedCloth", ">= 4.1.0", "< 4.2.0" + +### REQUIRE AS (:require) + +Each _gem_ `MAY` specify files that should be used when autorequiring via +`Bundler.require`. You may pass an array with multiple files or `true` if file +you want `required` has same name as _gem_ or `false` to +prevent any file from being autorequired. + + gem "redis", :require => ["redis/connection/hiredis", "redis"] + gem "webmock", :require => false + gem "debugger", :require => true + +The argument defaults to the name of the gem. For example, these are identical: + + gem "nokogiri" + gem "nokogiri", :require => "nokogiri" + gem "nokogiri", :require => true + +### GROUPS (:group or :groups) + +Each _gem_ `MAY` specify membership in one or more groups. Any _gem_ that does +not specify membership in any group is placed in the `default` group. + + gem "rspec", :group => :test + gem "wirble", :groups => [:development, :test] + +The Bundler runtime allows its two main methods, `Bundler.setup` and +`Bundler.require`, to limit their impact to particular groups. + + # setup adds gems to Ruby's load path + Bundler.setup # defaults to all groups + require "bundler/setup" # same as Bundler.setup + Bundler.setup(:default) # only set up the _default_ group + Bundler.setup(:test) # only set up the _test_ group (but `not` _default_) + Bundler.setup(:default, :test) # set up the _default_ and _test_ groups, but no others + + # require requires all of the gems in the specified groups + Bundler.require # defaults to just the _default_ group + Bundler.require(:default) # identical + Bundler.require(:default, :test) # requires the _default_ and _test_ groups + Bundler.require(:test) # requires just the _test_ group + +The Bundler CLI allows you to specify a list of groups whose gems `bundle install` should +not install with the `--without` option. To specify multiple groups to ignore, specify a +list of groups separated by spaces. + + bundle install --without test + bundle install --without development test + +After running `bundle install --without test`, bundler will remember that you excluded +the test group in the last installation. The next time you run `bundle install`, +without any `--without option`, bundler will recall it. + +Also, calling `Bundler.setup` with no parameters, or calling `require "bundler/setup"` +will setup all groups except for the ones you excluded via `--without` (since they +are obviously not available). + +Note that on `bundle install`, bundler downloads and evaluates all gems, in order to +create a single canonical list of all of the required gems and their dependencies. +This means that you cannot list different versions of the same gems in different +groups. For more details, see [Understanding Bundler](http://bundler.io/rationale.html). + +### PLATFORMS (:platforms) + +If a gem should only be used in a particular platform or set of platforms, you can +specify them. Platforms are essentially identical to groups, except that you do not +need to use the `--without` install-time flag to exclude groups of gems for other +platforms. + +There are a number of `Gemfile` platforms: + + * `ruby`: + C Ruby (MRI) or Rubinius, but `NOT` Windows + * `ruby_18`: + _ruby_ `AND` version 1.8 + * `ruby_19`: + _ruby_ `AND` version 1.9 + * `ruby_20`: + _ruby_ `AND` version 2.0 + * `ruby_21`: + _ruby_ `AND` version 2.1 + * `mri`: + Same as _ruby_, but not Rubinius + * `mri_18`: + _mri_ `AND` version 1.8 + * `mri_19`: + _mri_ `AND` version 1.9 + * `mri_20`: + _mri_ `AND` version 2.0 + * `mri_21`: + _mri_ `AND` version 2.1 + * `rbx`: + Same as _ruby_, but only Rubinius (not MRI) + * `jruby`: + JRuby + * `mswin`: + Windows + * `mingw`: + Windows 32 bit 'mingw32' platform (aka RubyInstaller) + * `mingw_18`: + _mingw_ `AND` version 1.8 + * `mingw_19`: + _mingw_ `AND` version 1.9 + * `mingw_20`: + _mingw_ `AND` version 2.0 + * `mingw_21`: + _mingw_ `AND` version 2.1 + * `x64_mingw`: + Windows 64 bit 'mingw32' platform (aka RubyInstaller x64) + * `x64_mingw_20`: + _x64_mingw_ `AND` version 2.0 + * `x64_mingw_21`: + _x64_mingw_ `AND` version 2.1 + +As with groups, you can specify one or more platforms: + + gem "weakling", :platforms => :jruby + gem "ruby-debug", :platforms => :mri_18 + gem "nokogiri", :platforms => [:mri_18, :jruby] + +All operations involving groups (`bundle install`, `Bundler.setup`, +`Bundler.require`) behave exactly the same as if any groups not +matching the current platform were explicitly excluded. + +### SOURCE (:source) + +You can select an alternate Rubygems repository for a gem using the ':source' +option. + + gem "some_internal_gem", :source => "https://gems.example.com" + +This forces the gem to be loaded from this source and ignores any global sources +declared at the top level of the file. If the gem does not exist in this source, +it will not be installed. + +Bundler will search for child dependencies of this gem by first looking in the +source selected for the parent, but if they are not found there, it will fall +back on global sources using the ordering described in [SOURCE PRIORITY][]. + +Selecting a specific source repository this way also suppresses the ambiguous +gem warning described above in +[GLOBAL SOURCES (#source)](#GLOBAL-SOURCES-source-). + +### 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 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. + + gem "rails", :git => "git://github.com/rails/rails.git" + +A git repository `SHOULD` have at least one file, at the root of the +directory containing the gem, with the extension `.gemspec`. This file +`MUST` contain a valid gem specification, as expected by the `gem build` +command. + +If a git repository does not have a `.gemspec`, bundler will attempt to +create one, but it will not contain any dependencies, executables, or +C extension compilation instructions. As a result, it may fail to properly +integrate into your application. + +If a git repository does have a `.gemspec` for the gem you attached it +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" + # bundle install will fail, because the .gemspec in the rails + # repository's master branch specifies version 3.0.0 + +If a git repository does `not` have a `.gemspec` for the gem you attached +it to, a version specifier `MUST` be provided. Bundler will use this +version in the simple `.gemspec` it creates. + +Git repositories support a number of additional options. + + * `branch`, `tag`, and `ref`: + You `MUST` only specify at most one of these options. The default + is `:branch => "master"` + * `submodules`: + Specify `:submodules => true` to cause bundler to expand any + submodules included in the git repository + +If a git repository contains multiple `.gemspecs`, each `.gemspec` +represents a gem located at the same place in the file system as +the `.gemspec`. + + |~rails [git root] + | |-rails.gemspec [rails gem located here] + |~actionpack + | |-actionpack.gemspec [actionpack gem located here] + |~activesupport + | |-activesupport.gemspec [activesupport gem located here] + |... + +To install a gem located in a git repository, bundler changes to +the directory containing the gemspec, runs `gem build name.gemspec` +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. + +### GITHUB (:github) + +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 +same, you can omit one. + + gem "rails", :github => "rails/rails" + gem "rails", :github => "rails" + +Are both equivalent to + + gem "rails", :git => "git://github.com/rails/rails.git" + +In addition, if you wish to choose a specific branch: + + gem "rails", :github => "rails/rails", :branch => "branch_name" + +### PATH (:path) + +You can specify that a gem is located in a particular location +on the file system. Relative paths are resolved relative to the +directory containing the `Gemfile`. + +Similar to the semantics of the `:git` option, the `:path` +option requires that the directory in question either contains +a `.gemspec` for the gem, or that you specify an explicit +version that bundler should use. + +Unlike `:git`, bundler does not compile C extensions for +gems specified as paths. + + gem "rails", :path => "vendor/rails" + +## BLOCK FORM OF SOURCE, GIT, PATH, GROUP and PLATFORMS + +The `:source`, `:git`, `:path`, `:group`, and `:platforms` options may be +applied to a group of gems by using block form. + + source "https://gems.example.com" do + gem "some_internal_gem" + gem "another_internal_gem" + end + + git "git://github.com/rails/rails.git" do + gem "activesupport" + gem "actionpack" + end + + platforms :ruby do + gem "ruby-debug" + gem "sqlite3" + end + + group :development do + gem "wirble" + gem "faker" + end + +In the case of the `git` block form, the `:ref`, `:branch`, `:tag`, +and `:submodules` options may be passed to the `git` method, and +all gems in the block will inherit those options. + +## GEMSPEC (#gemspec) + +If you wish to use Bundler to help install dependencies for a gem while it is +being developed, use the `gemspec` method to pull in the dependencies listed in +the `.gemspec` file. + +The `gemspec` method adds any runtime dependencies as gem requirements in the +default group. It also adds development dependencies as gem requirements in the +`development` group. Finally, it adds a gem requirement on your project (`:path +=> '.'`). In conjunction with `Bundler.setup`, this allows you to require project +files in your test code as you would if the project were installed as a gem; you +need not manipulate the load path manually or require project files via relative +paths. + +The `gemspec` method supports optional `:path`, `:name`, and `:development_group` +options, which control where bundler looks for the `.gemspec`, what named +`.gemspec` it uses (if more than one is present), and which group development +dependencies are included in. + +## SOURCE PRIORITY + +When attempting to locate a gem to satisfy a gem requirement, +bundler uses the following priority order: + + 1. The source explicitly attached to the gem (using `:source`, `:path`, or + `:git`) + 2. For implicit gems (dependencies of explicit gems), any source, git, or path + repository declared on the parent. This results in bundler prioritizing the + ActiveSupport gem from the Rails git repository over ones from + `rubygems.org` + 3. The sources specified via global `source` lines, searching each source in + your `Gemfile` from last added to first added. diff --git a/bundler-1.7.2/man/index.txt b/bundler-1.7.2/man/index.txt new file mode 100644 index 0000000..e31afb7 --- /dev/null +++ b/bundler-1.7.2/man/index.txt @@ -0,0 +1,7 @@ +Gemfile(5) gemfile.5 +bundle-install bundle-install.1 +bundle-update bundle-update.1 +bundle-package bundle-package.1 +bundle-exec bundle-exec.1 +bundle-config bundle-config.1 +bundle-platform bundle-platform.1 diff --git a/bundler-1.7.2/spec/bundler/bundler_spec.rb b/bundler-1.7.2/spec/bundler/bundler_spec.rb new file mode 100644 index 0000000..60168dd --- /dev/null +++ b/bundler-1.7.2/spec/bundler/bundler_spec.rb @@ -0,0 +1,74 @@ +# encoding: utf-8 +require 'spec_helper' +require 'bundler' + +describe Bundler do + describe "#load_gemspec_uncached" do + let(:app_gemspec_path) { tmp("test.gemspec") } + subject { Bundler.load_gemspec_uncached(app_gemspec_path) } + + context "with incorrect YAML file" do + before do + File.open(app_gemspec_path, "wb") do |f| + f.write strip_whitespace(<<-GEMSPEC) + --- + {:!00 ao=gu\g1= 7~f + GEMSPEC + end + end + + context "on Ruby 1.8", :ruby => "1.8" do + it "catches YAML syntax errors" do + expect { subject }.to raise_error(Bundler::GemspecError) + end + end + + context "on Ruby 1.9", :ruby => "1.9" do + context "with Syck as YAML::Engine" do + it "raises a GemspecError after YAML load throws ArgumentError" do + orig_yamler, YAML::ENGINE.yamler = YAML::ENGINE.yamler, 'syck' + + expect { subject }.to raise_error(Bundler::GemspecError) + + YAML::ENGINE.yamler = orig_yamler + end + end + + context "with Psych as YAML::Engine" do + it "raises a GemspecError after YAML load throws Psych::SyntaxError" do + orig_yamler, YAML::ENGINE.yamler = YAML::ENGINE.yamler, 'psych' + + expect { subject }.to raise_error(Bundler::GemspecError) + + YAML::ENGINE.yamler = orig_yamler + end + end + end + end + + context "with correct YAML file" 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 + + File.open(app_gemspec_path, "wb") do |file| + file.puts <<-GEMSPEC.gsub(/^\s+/, '') + # -*- encoding: utf-8 -*- + Gem::Specification.new do |gem| + gem.author = "André the Giant" + end + GEMSPEC + end + + expect(subject.author).to eq("André the Giant") + + Encoding.default_external = encoding if defined?(Encoding) + end + end + + end +end diff --git a/bundler-1.7.2/spec/bundler/cli_spec.rb b/bundler-1.7.2/spec/bundler/cli_spec.rb new file mode 100644 index 0000000..ef4ec79 --- /dev/null +++ b/bundler-1.7.2/spec/bundler/cli_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' +require 'bundler/cli' + +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 + end + + it "returns non-zero exit status when passed unrecognized task" do + bundle 'unrecognized-tast', :exitstatus => true + expect(exitstatus).to_not be_zero + end +end diff --git a/bundler-1.7.2/spec/bundler/definition_spec.rb b/bundler-1.7.2/spec/bundler/definition_spec.rb new file mode 100644 index 0000000..0f18416 --- /dev/null +++ b/bundler-1.7.2/spec/bundler/definition_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' +require 'bundler/definition' + +describe Bundler::Definition do + before do + allow(Bundler).to receive(:settings){ Bundler::Settings.new(".") } + allow(Bundler).to receive(:default_gemfile){ Pathname.new("Gemfile") } + end + + describe "#lock" do + context "when it's not possible to write to the file" do + subject{ Bundler::Definition.new(nil, [], Bundler::SourceList.new, []) } + + it "raises an InstallError with explanation" do + expect(File).to receive(:open).with("Gemfile.lock", "wb"). + and_raise(Errno::EACCES) + expect{ subject.lock("Gemfile.lock") }. + to raise_error(Bundler::InstallError) + end + end + end +end diff --git a/bundler-1.7.2/spec/bundler/dsl_spec.rb b/bundler-1.7.2/spec/bundler/dsl_spec.rb new file mode 100644 index 0000000..03db5d2 --- /dev/null +++ b/bundler-1.7.2/spec/bundler/dsl_spec.rb @@ -0,0 +1,82 @@ +require 'spec_helper' + +describe Bundler::Dsl do + before do + @rubygems = double("rubygems") + allow(Bundler::Source::Rubygems).to receive(:new){ @rubygems } + end + + describe "#register_host" 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" } + subject.gem("dobry-pies", :example => "strzalek/dobry-pies") + example_uri = "git@git.example.com:strzalek/dobry-pies.git" + expect(subject.dependencies.first.source.uri).to eq(example_uri) + end + + it "raises expection on invalid hostname" do + expect { + subject.git_source(:group){ |repo_name| "git@git.example.com:#{repo_name}.git" } + }.to raise_error(Bundler::InvalidOption) + end + + it "expects block passed" do + expect{ subject.git_source(:example) }.to raise_error(Bundler::InvalidOption) + end + + context "default hosts (git, gist)" do + it "converts :github to :git" do + subject.gem("sparks", :github => "indirect/sparks") + github_uri = "git://github.com/indirect/sparks.git" + expect(subject.dependencies.first.source.uri).to eq(github_uri) + end + + it "converts numeric :gist to :git" do + subject.gem("not-really-a-gem", :gist => 2859988) + github_uri = "https://gist.github.com/2859988.git" + expect(subject.dependencies.first.source.uri).to eq(github_uri) + end + + it "converts :gist to :git" do + subject.gem("not-really-a-gem", :gist => "2859988") + github_uri = "https://gist.github.com/2859988.git" + expect(subject.dependencies.first.source.uri).to eq(github_uri) + end + + it "converts 'rails' to 'rails/rails'" do + subject.gem("rails", :github => "rails") + github_uri = "git://github.com/rails/rails.git" + expect(subject.dependencies.first.source.uri).to eq(github_uri) + end + end + end + + describe "#method_missing" do + it "raises an error for unknown DSL methods" do + expect(Bundler).to receive(:read_file).with("Gemfile"). + and_return("unknown") + + error_msg = "Undefined local variable or method `unknown'" \ + " for Gemfile\\s+from Gemfile:1" + expect { subject.eval_gemfile("Gemfile") }. + to raise_error(Bundler::GemfileError, Regexp.new(error_msg)) + end + end + + describe "#eval_gemfile" do + it "handles syntax errors with a useful message" do + expect(Bundler).to receive(:read_file).with("Gemfile").and_return("}") + expect { subject.eval_gemfile("Gemfile") }. + to raise_error(Bundler::GemfileError, /Gemfile syntax error/) + end + end + + describe "syntax errors" do + it "will raise a Bundler::GemfileError" do + gemfile "gem 'foo', :path => /unquoted/string/syntax/error" + expect { Bundler::Dsl.evaluate(bundled_app("Gemfile"), nil, true) }. + to raise_error(Bundler::GemfileError, /Gemfile syntax error/) + end + end +end diff --git a/bundler-1.7.2/spec/bundler/friendly_errors_spec.rb b/bundler-1.7.2/spec/bundler/friendly_errors_spec.rb new file mode 100644 index 0000000..96c333a --- /dev/null +++ b/bundler-1.7.2/spec/bundler/friendly_errors_spec.rb @@ -0,0 +1,13 @@ +require "spec_helper" +require "bundler" +require "bundler/friendly_errors" + +describe Bundler, "friendly errors" do + it "rescues Thor::AmbiguousTaskError and raises SystemExit" do + expect { + Bundler.with_friendly_errors do + raise Thor::AmbiguousTaskError.new("") + end + }.to raise_error(SystemExit) + end +end diff --git a/bundler-1.7.2/spec/bundler/gem_helper_spec.rb b/bundler-1.7.2/spec/bundler/gem_helper_spec.rb new file mode 100644 index 0000000..791a78b --- /dev/null +++ b/bundler-1.7.2/spec/bundler/gem_helper_spec.rb @@ -0,0 +1,224 @@ +require "spec_helper" +require 'rake' +require 'bundler/gem_helper' + +describe Bundler::GemHelper do + let(:app_name) { "test" } + let(:app_path) { bundled_app app_name } + let(:app_gemspec_path) { app_path.join("#{app_name}.gemspec") } + + before(:each) do + bundle "gem #{app_name}" + end + + context "determining gemspec" do + subject { Bundler::GemHelper.new(app_path) } + + context "fails" do + it "when there is no gemspec" do + FileUtils.rm app_gemspec_path + expect { subject }.to raise_error(/Unable to determine name/) + end + + it "when there are two gemspecs and the name isn't specified" do + FileUtils.touch app_path.join("#{app_name}-2.gemspec") + expect { subject }.to raise_error(/Unable to determine name/) + end + end + + context "interpolates the name" do + it "when there is only one gemspec" do + expect(subject.gemspec.name).to eq(app_name) + end + + it "for a hidden gemspec" do + FileUtils.mv app_gemspec_path, app_path.join(".gemspec") + expect(subject.gemspec.name).to eq(app_name) + end + end + + it "handles namespaces and converts them to CamelCase" do + bundle "gem #{app_name}-foo_bar" + app_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}") + expect(lib).to include("module FooBar") + end + end + + context "gem management" do + def mock_confirm_message(message) + expect(Bundler.ui).to receive(:confirm).with(message) + end + + def mock_build_message(name, version) + message = "#{name} #{version} built to pkg/#{name}-#{version}.gem." + mock_confirm_message message + end + + subject! { Bundler::GemHelper.new(app_path) } + let(:app_version) { "0.0.1" } + 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: ", "") + File.open(app_gemspec_path, "w") { |file| file << content } + end + + it "uses a shell UI for output" do + expect(Bundler.ui).to be_a(Bundler::UI::Shell) + end + + describe "#install" do + let!(:rake_application) { Rake.application } + + before(:each) do + Rake.application = Rake::Application.new + end + + after(:each) do + Rake.application = rake_application + end + + context "defines Rake tasks" do + let(:task_names) { %w[build install release] } + + context "before installation" do + it "raises an error with appropriate message" do + task_names.each do |name| + expect { Rake.application[name] }. + to raise_error("Don't know how to build task '#{name}'") + end + end + end + + context "after installation" do + before do + subject.install + end + + it "adds Rake tasks successfully" do + task_names.each do |name| + expect { Rake.application[name] }.not_to raise_error + expect(Rake.application[name]).to be_instance_of Rake::Task + end + end + + it "provides a way to access the gemspec object" do + expect(subject.gemspec.name).to eq(app_name) + end + end + end + end + + describe "#build_gem" do + context "when build failed" do + it "raises an error with appropriate message" do + # break the gemspec by adding back the TODOs + File.open(app_gemspec_path, "w"){ |file| file << app_gemspec_content } + expect { subject.build_gem }.to raise_error(/TODO/) + end + end + + context "when build was successful" do + it "creates .gem file" do + mock_build_message app_name, app_version + subject.build_gem + expect(app_gem_path).to exist + end + end + end + + describe "#install_gem" do + context "when installation was successful" do + it "gem is installed" do + mock_build_message app_name, app_version + mock_confirm_message "#{app_name} (#{app_version}) installed." + subject.install_gem + expect(app_gem_path).to exist + expect(`gem list`).to include("#{app_name} (#{app_version})") + end + end + + context "when installation fails" do + it "raises an error with appropriate message" do + # create empty gem file in order to simulate install failure + allow(subject).to receive(:build_gem) do + FileUtils.mkdir_p(app_gem_dir) + FileUtils.touch app_gem_path + app_gem_path + end + expect { subject.install_gem }.to raise_error(/Couldn't install gem/) + end + end + end + + describe "#release_gem" do + before do + Dir.chdir(app_path) do + `git init` + `git config user.email "you@example.com"` + `git config user.name "name"` + end + end + + context "fails" do + it "when there are unstaged files" do + expect { subject.release_gem }. + 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 }. + to raise_error("There are files that need to be committed first.") + end + + it "when there is no git remote" do + # silence messages + allow(Bundler.ui).to receive(:confirm) + allow(Bundler.ui).to receive(:error) + + Dir.chdir(app_path) { `git commit -a -m "initial commit"` } + expect { subject.release_gem }.to raise_error + end + end + + context "succeeds" do + before do + Dir.chdir(gem_repo1) { `git init --bare` } + Dir.chdir(app_path) do + `git remote add origin file://#{gem_repo1}` + `git commit -a -m "initial commit"` + end + end + + it "on releasing" do + mock_build_message app_name, app_version + mock_confirm_message "Tagged v#{app_version}." + mock_confirm_message "Pushed git commits and tags." + expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s) + + Dir.chdir(app_path) { sys_exec("git push origin master", true) } + + subject.release_gem + end + + it "even if tag already exists" do + mock_build_message app_name, app_version + mock_confirm_message "Tag v#{app_version} has already been created." + expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s) + + Dir.chdir(app_path) do + `git tag -a -m \"Version #{app_version}\" v#{app_version}` + end + + subject.release_gem + end + end + end + end +end diff --git a/bundler-1.7.2/spec/bundler/psyched_yaml_spec.rb b/bundler-1.7.2/spec/bundler/psyched_yaml_spec.rb new file mode 100644 index 0000000..5f3c47b --- /dev/null +++ b/bundler-1.7.2/spec/bundler/psyched_yaml_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' +require 'bundler/psyched_yaml' + +describe Bundler::YamlSyntaxError do + it "is raised on YAML parse errors" do + expect{ YAML.parse "{foo" }.to raise_error(Bundler::YamlSyntaxError) + end +end diff --git a/bundler-1.7.2/spec/bundler/retry_spec.rb b/bundler-1.7.2/spec/bundler/retry_spec.rb new file mode 100644 index 0000000..8e35a10 --- /dev/null +++ b/bundler-1.7.2/spec/bundler/retry_spec.rb @@ -0,0 +1,59 @@ +require 'spec_helper' + +describe Bundler::Retry do + it "return successful result if no errors" do + attempts = 0 + result = Bundler::Retry.new(nil, nil, 3).attempt do + attempts += 1 + :success + end + expect(result).to eq(:success) + expect(attempts).to eq(1) + end + + it "defaults to retrying twice" do + attempts = 0 + expect { + Bundler::Retry.new(nil).attempt do + attempts += 1 + raise "nope" + end + }.to raise_error("nope") + expect(attempts).to eq(3) + end + + it "returns the first valid result" do + jobs = [Proc.new{ raise "foo" }, Proc.new{ :bar }, Proc.new{ raise "foo" }] + attempts = 0 + result = Bundler::Retry.new(nil, nil, 3).attempt do + attempts += 1 + jobs.shift.call + end + expect(result).to eq(:bar) + expect(attempts).to eq(2) + end + + it "raises the last error" do + errors = [StandardError, StandardError, StandardError, Bundler::GemfileNotFound] + attempts = 0 + expect { + Bundler::Retry.new(nil, nil, 3).attempt do + attempts += 1 + raise errors.shift + end + }.to raise_error(Bundler::GemfileNotFound) + expect(attempts).to eq(4) + end + + it "raises exceptions" do + error = Bundler::GemfileNotFound + attempts = 0 + expect { + Bundler::Retry.new(nil, error).attempt do + attempts += 1 + raise error + end + }.to raise_error(error) + expect(attempts).to eq(1) + end +end diff --git a/bundler-1.7.2/spec/bundler/settings_spec.rb b/bundler-1.7.2/spec/bundler/settings_spec.rb new file mode 100644 index 0000000..44f40ce --- /dev/null +++ b/bundler-1.7.2/spec/bundler/settings_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' +require 'bundler/settings' + +describe Bundler::Settings do + describe "#set_local" do + context "when the local config file is not found" do + it "raises a GemfileNotFound error with explanation" do + expect{ subject.set_local("foo", "bar") }. + to raise_error(Bundler::GemfileNotFound, "Could not locate Gemfile") + end + end + end +end diff --git a/bundler-1.7.2/spec/bundler/source/rubygems_spec.rb b/bundler-1.7.2/spec/bundler/source/rubygems_spec.rb new file mode 100644 index 0000000..68fc6c6 --- /dev/null +++ b/bundler-1.7.2/spec/bundler/source/rubygems_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe Bundler::Source::Rubygems do + before do + allow(Bundler).to receive(:root){ Pathname.new("root") } + end + + describe "caches" do + it "includes Bundler.app_cache" do + expect(subject.caches).to include(Bundler.app_cache) + end + + it "includes GEM_PATH entries" do + Gem.path.each do |path| + expect(subject.caches).to include(File.expand_path("#{path}/cache")) + end + end + + it "is an array of strings or pathnames" do + subject.caches.each do |cache| + expect([String, Pathname]).to include(cache.class) + end + end + end +end diff --git a/bundler-1.7.2/spec/bundler/source_list_spec.rb b/bundler-1.7.2/spec/bundler/source_list_spec.rb new file mode 100644 index 0000000..67d4ef6 --- /dev/null +++ b/bundler-1.7.2/spec/bundler/source_list_spec.rb @@ -0,0 +1,361 @@ +require 'spec_helper' + +describe Bundler::SourceList do + before do + allow(Bundler).to receive(:root) { Pathname.new '/' } + end + + subject(:source_list) { Bundler::SourceList.new } + + let(:rubygems_aggregate) { Bundler::Source::Rubygems.new } + + describe "adding sources" do + before do + source_list.add_path_source('path' => '/existing/path/to/gem') + source_list.add_git_source('uri' => 'git://existing-git.org/path.git') + source_list.add_rubygems_source('remotes' => ['https://existing-rubygems.org']) + end + + describe "#add_path_source" do + before do + @duplicate = source_list.add_path_source('path' => '/path/to/gem') + @new_source = source_list.add_path_source('path' => '/path/to/gem') + end + + it "returns the new path source" do + expect(@new_source).to be_instance_of(Bundler::Source::Path) + end + + it "passes the provided options to the new source" do + expect(@new_source.options).to eq('path' => '/path/to/gem') + end + + it "adds the source to the beginning of path_sources" do + expect(source_list.path_sources.first).to equal(@new_source) + end + + it "removes existing duplicates" do + expect(source_list.path_sources).not_to include equal(@duplicate) + end + end + + describe "#add_git_source" do + before do + @duplicate = source_list.add_git_source('uri' => 'git://host/path.git') + @new_source = source_list.add_git_source('uri' => 'git://host/path.git') + end + + it "returns the new git source" do + expect(@new_source).to be_instance_of(Bundler::Source::Git) + end + + it "passes the provided options to the new source" do + expect(@new_source.options).to eq('uri' => 'git://host/path.git') + end + + it "adds the source to the beginning of git_sources" do + expect(source_list.git_sources.first).to equal(@new_source) + end + + it "removes existing duplicates" do + expect(source_list.git_sources).not_to include equal(@duplicate) + end + end + + describe "#add_rubygems_source" do + before do + @duplicate = source_list.add_rubygems_source('remotes' => ['https://rubygems.org/']) + @new_source = source_list.add_rubygems_source('remotes' => ['https://rubygems.org/']) + end + + it "returns the new rubygems source" do + expect(@new_source).to be_instance_of(Bundler::Source::Rubygems) + end + + it "passes the provided options to the new source" do + expect(@new_source.options).to eq('remotes' => ['https://rubygems.org/']) + end + + it "adds the source to the beginning of rubygems_sources" do + expect(source_list.rubygems_sources.first).to equal(@new_source) + end + + it "removes duplicates" do + expect(source_list.rubygems_sources).not_to include equal(@duplicate) + end + end + + describe "#add_rubygems_remote" do + before do + @returned_source = source_list.add_rubygems_remote('https://rubygems.org/') + end + + it "returns the aggregate rubygems source" do + expect(@returned_source).to be_instance_of(Bundler::Source::Rubygems) + end + + it "adds the provided remote to the beginning of the aggregate source" do + source_list.add_rubygems_remote('https://othersource.org') + expect(@returned_source.remotes.first).to eq(URI('https://othersource.org/')) + end + end + end + + describe "#all_sources" do + it "includes the aggregate rubygems source when rubygems sources have been added" 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 include rubygems_aggregate + end + + it "includes the aggregate rubygems source when no rubygems sources have been added" do + source_list.add_git_source('uri' => 'git://host/path.git') + source_list.add_path_source('path' => '/path/to/gem') + + 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']) + source_list.add_path_source('path' => '/third/path/to/gem') + source_list.add_rubygems_source('remotes' => ['https://fourth-rubygems.org']) + source_list.add_path_source('path' => '/second/path/to/gem') + source_list.add_rubygems_source('remotes' => ['https://third-rubygems.org']) + source_list.add_git_source('uri' => 'git://second-git.org/path.git') + source_list.add_rubygems_source('remotes' => ['https://second-rubygems.org']) + source_list.add_path_source('path' => '/first/path/to/gem') + source_list.add_rubygems_source('remotes' => ['https://first-rubygems.org']) + source_list.add_git_source('uri' => 'git://first-git.org/path.git') + + expect(source_list.all_sources).to eq [ + Bundler::Source::Path.new('path' => '/first/path/to/gem'), + Bundler::Source::Path.new('path' => '/second/path/to/gem'), + Bundler::Source::Path.new('path' => '/third/path/to/gem'), + Bundler::Source::Git.new('uri' => 'git://first-git.org/path.git'), + Bundler::Source::Git.new('uri' => 'git://second-git.org/path.git'), + Bundler::Source::Git.new('uri' => 'git://third-git.org/path.git'), + Bundler::Source::Rubygems.new('remotes' => ['https://first-rubygems.org']), + Bundler::Source::Rubygems.new('remotes' => ['https://second-rubygems.org']), + Bundler::Source::Rubygems.new('remotes' => ['https://third-rubygems.org']), + Bundler::Source::Rubygems.new('remotes' => ['https://fourth-rubygems.org']), + Bundler::Source::Rubygems.new('remotes' => ['https://fifth-rubygems.org']), + rubygems_aggregate, + ] + end + end + + describe "#path_sources" do + it "returns an empty array when no path sources have been added" do + source_list.add_rubygems_remote('https://rubygems.org') + source_list.add_git_source('uri' => 'git://host/path.git') + expect(source_list.path_sources).to be_empty + end + + it "returns path sources 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_remote('https://fifth-rubygems.org') + source_list.add_path_source('path' => '/third/path/to/gem') + source_list.add_rubygems_remote('https://fourth-rubygems.org') + source_list.add_path_source('path' => '/second/path/to/gem') + source_list.add_rubygems_remote('https://third-rubygems.org') + source_list.add_git_source('uri' => 'git://second-git.org/path.git') + source_list.add_rubygems_remote('https://second-rubygems.org') + source_list.add_path_source('path' => '/first/path/to/gem') + source_list.add_rubygems_remote('https://first-rubygems.org') + source_list.add_git_source('uri' => 'git://first-git.org/path.git') + + expect(source_list.path_sources).to eq [ + Bundler::Source::Path.new('path' => '/first/path/to/gem'), + Bundler::Source::Path.new('path' => '/second/path/to/gem'), + Bundler::Source::Path.new('path' => '/third/path/to/gem'), + ] + end + end + + describe "#git_sources" do + it "returns an empty array when no git sources have been added" do + source_list.add_rubygems_remote('https://rubygems.org') + source_list.add_path_source('path' => '/path/to/gem') + + expect(source_list.git_sources).to be_empty + end + + it "returns git sources 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_remote('https://fifth-rubygems.org') + source_list.add_path_source('path' => '/third/path/to/gem') + source_list.add_rubygems_remote('https://fourth-rubygems.org') + source_list.add_path_source('path' => '/second/path/to/gem') + source_list.add_rubygems_remote('https://third-rubygems.org') + source_list.add_git_source('uri' => 'git://second-git.org/path.git') + source_list.add_rubygems_remote('https://second-rubygems.org') + source_list.add_path_source('path' => '/first/path/to/gem') + source_list.add_rubygems_remote('https://first-rubygems.org') + source_list.add_git_source('uri' => 'git://first-git.org/path.git') + + expect(source_list.git_sources).to eq [ + Bundler::Source::Git.new('uri' => 'git://first-git.org/path.git'), + Bundler::Source::Git.new('uri' => 'git://second-git.org/path.git'), + Bundler::Source::Git.new('uri' => 'git://third-git.org/path.git'), + ] + end + end + + describe "#rubygems_sources" do + it "includes the aggregate rubygems source when rubygems sources have been added" 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.rubygems_sources).to include rubygems_aggregate + end + + it "returns only the aggregate rubygems source when no rubygems sources have been added" do + source_list.add_git_source('uri' => 'git://host/path.git') + source_list.add_path_source('path' => '/path/to/gem') + + expect(source_list.rubygems_sources).to eq [rubygems_aggregate] + end + + it "returns rubygems sources 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']) + source_list.add_path_source('path' => '/third/path/to/gem') + source_list.add_rubygems_source('remotes' => ['https://fourth-rubygems.org']) + source_list.add_path_source('path' => '/second/path/to/gem') + source_list.add_rubygems_source('remotes' => ['https://third-rubygems.org']) + source_list.add_git_source('uri' => 'git://second-git.org/path.git') + source_list.add_rubygems_source('remotes' => ['https://second-rubygems.org']) + source_list.add_path_source('path' => '/first/path/to/gem') + source_list.add_rubygems_source('remotes' => ['https://first-rubygems.org']) + source_list.add_git_source('uri' => 'git://first-git.org/path.git') + + expect(source_list.rubygems_sources).to eq [ + Bundler::Source::Rubygems.new('remotes' => ['https://first-rubygems.org']), + Bundler::Source::Rubygems.new('remotes' => ['https://second-rubygems.org']), + Bundler::Source::Rubygems.new('remotes' => ['https://third-rubygems.org']), + Bundler::Source::Rubygems.new('remotes' => ['https://fourth-rubygems.org']), + Bundler::Source::Rubygems.new('remotes' => ['https://fifth-rubygems.org']), + rubygems_aggregate, + ] + end + end + + describe "#get" do + context "when it includes an equal source" do + let(:rubygems_source) { Bundler::Source::Rubygems.new('remotes' => ['https://rubygems.org']) } + before { @equal_source = source_list.add_rubygems_remote('https://rubygems.org') } + + it "returns the equal source" do + expect(source_list.get(rubygems_source)).to be @equal_source + end + end + + context "when it does not include an equal source" do + let(:path_source) { Bundler::Source::Path.new('path' => '/path/to/gem') } + + it "returns nil" do + expect(source_list.get(path_source)).to be_nil + end + end + end + + describe "#lock_sources" do + it "combines the rubygems sources into a single instance, removing duplicate remotes from the front" do + source_list.add_git_source('uri' => 'git://third-git.org/path.git') + source_list.add_rubygems_source('remotes' => ['https://fourth-rubygems.org']) # intentional duplicate + source_list.add_path_source('path' => '/third/path/to/gem') + source_list.add_rubygems_source('remotes' => ['https://first-rubygems.org']) + source_list.add_path_source('path' => '/second/path/to/gem') + source_list.add_rubygems_source('remotes' => ['https://second-rubygems.org']) + source_list.add_git_source('uri' => 'git://second-git.org/path.git') + source_list.add_rubygems_source('remotes' => ['https://third-rubygems.org']) + source_list.add_path_source('path' => '/first/path/to/gem') + source_list.add_rubygems_source('remotes' => ['https://fourth-rubygems.org']) + source_list.add_git_source('uri' => 'git://first-git.org/path.git') + + expect(source_list.lock_sources).to eq [ + Bundler::Source::Git.new('uri' => 'git://first-git.org/path.git'), + Bundler::Source::Git.new('uri' => 'git://second-git.org/path.git'), + Bundler::Source::Git.new('uri' => 'git://third-git.org/path.git'), + Bundler::Source::Path.new('path' => '/first/path/to/gem'), + Bundler::Source::Path.new('path' => '/second/path/to/gem'), + Bundler::Source::Path.new('path' => '/third/path/to/gem'), + Bundler::Source::Rubygems.new('remotes' => [ + 'https://first-rubygems.org', + 'https://second-rubygems.org', + 'https://third-rubygems.org', + 'https://fourth-rubygems.org', + ]), + ] + end + end + + describe "replace_sources!" do + let(:existing_locked_source) { Bundler::Source::Path.new('path' => '/existing/path') } + let(:removed_locked_source) { Bundler::Source::Path.new('path' => '/removed/path') } + + let(:locked_sources) { [existing_locked_source, removed_locked_source] } + + before do + @existing_source = source_list.add_path_source('path' => '/existing/path') + @new_source = source_list.add_path_source('path' => '/new/path') + source_list.replace_sources!(locked_sources) + end + + it "maintains the order and number of sources" do + expect(source_list.path_sources).to eq [@new_source, @existing_source] + end + + it "retains the same instance of the new source" do + expect(source_list.path_sources[0]).to be @new_source + end + + it "replaces the instance of the existing source" do + expect(source_list.path_sources[1]).to be existing_locked_source + end + end + + describe "#cached!" do + let(:rubygems_source) { source_list.add_rubygems_remote('https://rubygems.org') } + let(:git_source) { source_list.add_git_source('uri' => 'git://host/path.git') } + let(:path_source) { source_list.add_path_source('path' => '/path/to/gem') } + + it "calls #cached! on all the sources" do + expect(rubygems_source).to receive(:cached!) + expect(git_source).to receive(:cached!) + expect(path_source).to receive(:cached!) + source_list.cached! + end + end + + describe "#remote!" do + let(:rubygems_source) { source_list.add_rubygems_remote('https://rubygems.org') } + let(:git_source) { source_list.add_git_source('uri' => 'git://host/path.git') } + let(:path_source) { source_list.add_path_source('path' => '/path/to/gem') } + + it "calls #remote! on all the sources" do + expect(rubygems_source).to receive(:remote!) + expect(git_source).to receive(:remote!) + expect(path_source).to receive(:remote!) + source_list.remote! + end + end + +end diff --git a/bundler-1.7.2/spec/cache/gems_spec.rb b/bundler-1.7.2/spec/cache/gems_spec.rb new file mode 100644 index 0000000..b70f627 --- /dev/null +++ b/bundler-1.7.2/spec/cache/gems_spec.rb @@ -0,0 +1,284 @@ +require "spec_helper" + +describe "bundle cache" do + + describe "when there are only gemsources" do + before :each do + gemfile <<-G + gem 'rack' + G + + system_gems "rack-1.0.0" + bundle :cache + end + + it "copies the .gem file to vendor/cache" do + expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist + end + + it "uses the cache as a source when installing gems" do + build_gem "omg", :path => bundled_app('vendor/cache') + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "omg" + G + + should_be_installed "omg 1.0.0" + end + + it "uses the cache as a source when installing gems with --local" do + system_gems [] + bundle "install --local" + + should_be_installed("rack 1.0.0") + end + + it "does not reinstall gems from the cache if they exist on the system" do + build_gem "rack", "1.0.0", :path => bundled_app('vendor/cache') do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" + end + + install_gemfile <<-G + gem "rack" + G + + should_be_installed("rack 1.0.0") + end + + it "does not reinstall gems from the cache if they exist in the bundle" do + system_gems "rack-1.0.0" + + gemfile <<-G + gem "rack" + G + + build_gem "rack", "1.0.0", :path => bundled_app('vendor/cache') do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" + end + + bundle "install --local" + should_be_installed("rack 1.0.0") + end + + it "creates a lockfile" do + cache_gems "rack-1.0.0" + + gemfile <<-G + gem "rack" + G + + bundle "cache" + + expect(bundled_app("Gemfile.lock")).to exist + end + end + + describe "when there is a built-in gem", :ruby => "2.0" do + before :each do + build_repo2 do + build_gem "builtin_gem", "1.0.2" + end + + build_gem "builtin_gem", "1.0.2", :to_system => true do |s| + s.summary = "This builtin_gem is bundled with Ruby" + end + + FileUtils.rm("#{system_gem_path}/cache/builtin_gem-1.0.2.gem") + end + + it "uses builtin gems" do + install_gemfile %|gem 'builtin_gem', '1.0.2'| + should_be_installed("builtin_gem 1.0.2") + end + + it "caches remote and builtin gems" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem 'builtin_gem', '1.0.2' + gem 'rack', '1.0.0' + G + + bundle :cache + expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist + expect(bundled_app("vendor/cache/builtin_gem-1.0.2.gem")).to exist + end + + it "doesn't make remote request after caching the gem" do + build_gem "builtin_gem_2", "1.0.2", :path => bundled_app('vendor/cache') do |s| + s.summary = "This builtin_gem is bundled with Ruby" + end + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem 'builtin_gem_2', '1.0.2' + G + + bundle "install --local" + should_be_installed("builtin_gem_2 1.0.2") + end + end + + describe "when there are also git sources" do + before do + build_git "foo" + system_gems "rack-1.0.0" + + install_gemfile <<-G + source "file://#{gem_repo1}" + git "#{lib_path("foo-1.0")}" do + gem 'foo' + end + gem 'rack' + G + end + + it "still works" do + bundle :cache + + system_gems [] + bundle "install --local" + + should_be_installed("rack 1.0.0", "foo 1.0") + end + + it "should not explode if the lockfile is not present" do + FileUtils.rm(bundled_app("Gemfile.lock")) + + bundle :cache + + expect(bundled_app("Gemfile.lock")).to exist + end + end + + describe "when previously cached" do + before :each do + build_repo2 + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack" + gem "actionpack" + G + bundle :cache + expect(cached_gem("rack-1.0.0")).to exist + expect(cached_gem("actionpack-2.3.2")).to exist + expect(cached_gem("activesupport-2.3.2")).to exist + end + + it "re-caches during install" do + cached_gem("rack-1.0.0").rmtree + bundle :install + expect(out).to include("Updating files in vendor/cache") + expect(cached_gem("rack-1.0.0")).to exist + end + + it "adds and removes when gems are updated" do + update_repo2 + bundle 'update' + expect(cached_gem("rack-1.2")).to exist + expect(cached_gem("rack-1.0.0")).not_to exist + end + + it "adds new gems and dependencies" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rails" + G + expect(cached_gem("rails-2.3.2")).to exist + expect(cached_gem("activerecord-2.3.2")).to exist + end + + it "removes .gems for removed gems and dependencies" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack" + G + expect(cached_gem("rack-1.0.0")).to exist + expect(cached_gem("actionpack-2.3.2")).not_to exist + expect(cached_gem("activesupport-2.3.2")).not_to exist + end + + it "removes .gems when gem changes to git source" do + build_git "rack" + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack", :git => "#{lib_path("rack-1.0")}" + gem "actionpack" + G + expect(cached_gem("rack-1.0.0")).not_to exist + expect(cached_gem("actionpack-2.3.2")).to exist + expect(cached_gem("activesupport-2.3.2")).to exist + end + + + it "doesn't remove gems that are for another platform" do + simulate_platform "java" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "platform_specific" + G + + bundle :cache + expect(cached_gem("platform_specific-1.0-java")).to exist + end + + simulate_new_machine + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "platform_specific" + G + + expect(cached_gem("platform_specific-1.0-#{Gem::Platform.local}")).to exist + expect(cached_gem("platform_specific-1.0-java")).to exist + end + + it "doesn't remove gems with mismatched :rubygems_version or :date" do + cached_gem("rack-1.0.0").rmtree + build_gem "rack", "1.0.0", + :path => bundled_app('vendor/cache'), + :rubygems_version => "1.3.2" + simulate_new_machine + + bundle :install + expect(cached_gem("rack-1.0.0")).to exist + end + + it "handles directories and non .gem files in the cache" do + bundled_app("vendor/cache/foo").mkdir + File.open(bundled_app("vendor/cache/bar"), 'w'){|f| f.write("not a gem") } + bundle :cache + end + + it "does not say that it is removing gems when it isn't actually doing so" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + bundle "cache" + bundle "install" + expect(out).not_to match(/removing/i) + end + + it "does not warn about all if it doesn't have any git/path dependency" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + bundle "cache" + expect(out).not_to match(/\-\-all/) + end + + it "should install gems with the name bundler in them (that aren't bundler)" do + build_gem "foo-bundler", "1.0", + :path => bundled_app('vendor/cache') + + install_gemfile <<-G + gem "foo-bundler" + G + + should_be_installed "foo-bundler 1.0" + end + end + +end diff --git a/bundler-1.7.2/spec/cache/git_spec.rb b/bundler-1.7.2/spec/cache/git_spec.rb new file mode 100644 index 0000000..b369504 --- /dev/null +++ b/bundler-1.7.2/spec/cache/git_spec.rb @@ -0,0 +1,188 @@ +require "spec_helper" + +describe "git base name" do + it "base_name should strip private repo uris" do + source = Bundler::Source::Git.new("uri" => "git@github.com:bundler.git") + expect(source.send(:base_name)).to eq("bundler") + end + + it "base_name should strip network share paths" do + source = Bundler::Source::Git.new("uri" => "//MachineName/ShareFolder") + expect(source.send(:base_name)).to eq("ShareFolder") + end +end + +%w(cache package).each do |cmd| + describe "bundle #{cmd} with git" do + it "copies repository to vendor cache and uses it" do + git = build_git "foo" + ref = git.ref_for("master", 11) + + install_gemfile <<-G + gem "foo", :git => '#{lib_path("foo-1.0")}' + G + + bundle "#{cmd} --all" + expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist + expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.git")).not_to exist + expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.bundlecache")).to be_file + + FileUtils.rm_rf lib_path("foo-1.0") + should_be_installed "foo 1.0" + end + + it "copies repository to vendor cache and uses it even when installed with bundle --path" do + git = build_git "foo" + ref = git.ref_for("master", 11) + + install_gemfile <<-G + gem "foo", :git => '#{lib_path("foo-1.0")}' + G + + bundle "install --path vendor/bundle" + bundle "#{cmd} --all" + + expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist + expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.git")).not_to exist + + FileUtils.rm_rf lib_path("foo-1.0") + should_be_installed "foo 1.0" + end + + it "runs twice without exploding" do + build_git "foo" + + install_gemfile <<-G + gem "foo", :git => '#{lib_path("foo-1.0")}' + G + + bundle "#{cmd} --all" + bundle "#{cmd} --all" + + expect(err).to eq("") + FileUtils.rm_rf lib_path("foo-1.0") + should_be_installed "foo 1.0" + end + + it "tracks updates" do + git = build_git "foo" + old_ref = git.ref_for("master", 11) + + install_gemfile <<-G + gem "foo", :git => '#{lib_path("foo-1.0")}' + G + + bundle "#{cmd} --all" + + update_git "foo" do |s| + s.write "lib/foo.rb", "puts :CACHE" + end + + ref = git.ref_for("master", 11) + expect(ref).not_to eq(old_ref) + + bundle "update" + bundle "#{cmd} --all" + + expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist + expect(bundled_app("vendor/cache/foo-1.0-#{old_ref}")).not_to exist + + FileUtils.rm_rf lib_path("foo-1.0") + run "require 'foo'" + expect(out).to eq("CACHE") + end + + it "uses the local repository to generate the cache" do + git = build_git "foo" + ref = git.ref_for("master", 11) + + gemfile <<-G + gem "foo", :git => '#{lib_path("foo-invalid")}', :branch => :master + G + + bundle %|config local.foo #{lib_path('foo-1.0')}| + bundle "install" + bundle "#{cmd} --all" + + expect(bundled_app("vendor/cache/foo-invalid-#{ref}")).to exist + + # Updating the local still uses the local. + update_git "foo" do |s| + s.write "lib/foo.rb", "puts :LOCAL" + end + + run "require 'foo'" + expect(out).to eq("LOCAL") + end + + it "copies repository to vendor cache, including submodules" do + build_git "submodule", "1.0" + + git = build_git "has_submodule", "1.0" do |s| + s.add_dependency "submodule" + end + + Dir.chdir(lib_path('has_submodule-1.0')) do + `git submodule add #{lib_path('submodule-1.0')} submodule-1.0` + `git commit -m "submodulator"` + end + + install_gemfile <<-G + git "#{lib_path('has_submodule-1.0')}", :submodules => true do + gem "has_submodule" + end + G + + ref = git.ref_for("master", 11) + bundle "#{cmd} --all" + + expect(bundled_app("vendor/cache/has_submodule-1.0-#{ref}")).to exist + expect(bundled_app("vendor/cache/has_submodule-1.0-#{ref}/submodule-1.0")).to exist + should_be_installed "has_submodule 1.0" + end + + it "displays warning message when detecting git repo in Gemfile" do + build_git "foo" + + install_gemfile <<-G + gem "foo", :git => '#{lib_path("foo-1.0")}' + G + + bundle "#{cmd}" + + expect(out).to include("Your Gemfile contains path and git dependencies.") + end + + it "does not display warning message if cache_all is set in bundle config" do + build_git "foo" + + install_gemfile <<-G + gem "foo", :git => '#{lib_path("foo-1.0")}' + G + + bundle "#{cmd} --all" + bundle "#{cmd}" + + expect(out).not_to include("Your Gemfile contains path and git dependencies.") + end + + it "caches pre-evaluated gemspecs" do + git = build_git "foo" + + # Insert a gemspec method that shells out + spec_lines = lib_path("foo-1.0/foo.gemspec").read.split("\n") + spec_lines.insert(-2, "s.description = `echo bob`") + update_git("foo"){ |s| s.write "foo.gemspec", spec_lines.join("\n") } + + install_gemfile <<-G + gem "foo", :git => '#{lib_path("foo-1.0")}' + G + bundle "#{cmd} --all" + + ref = git.ref_for("master", 11) + gemspec = bundled_app("vendor/cache/foo-1.0-#{ref}/foo.gemspec").read + expect(gemspec).to_not match("`echo bob`") + end + + end +end diff --git a/bundler-1.7.2/spec/cache/path_spec.rb b/bundler-1.7.2/spec/cache/path_spec.rb new file mode 100644 index 0000000..324e1f1 --- /dev/null +++ b/bundler-1.7.2/spec/cache/path_spec.rb @@ -0,0 +1,121 @@ +require "spec_helper" + +%w(cache package).each do |cmd| + describe "bundle #{cmd} with path" do + it "is no-op when the path is within the bundle" do + build_lib "foo", :path => bundled_app("lib/foo") + + install_gemfile <<-G + gem "foo", :path => '#{bundled_app("lib/foo")}' + G + + bundle "#{cmd} --all" + expect(bundled_app("vendor/cache/foo-1.0")).not_to exist + should_be_installed "foo 1.0" + end + + it "copies when the path is outside the bundle " do + build_lib "foo" + + install_gemfile <<-G + gem "foo", :path => '#{lib_path("foo-1.0")}' + G + + bundle "#{cmd} --all" + expect(bundled_app("vendor/cache/foo-1.0")).to exist + expect(bundled_app("vendor/cache/foo-1.0/.bundlecache")).to be_file + + FileUtils.rm_rf lib_path("foo-1.0") + should_be_installed "foo 1.0" + end + + it "updates the path on each cache" do + build_lib "foo" + + install_gemfile <<-G + gem "foo", :path => '#{lib_path("foo-1.0")}' + G + + bundle "#{cmd} --all" + + build_lib "foo" do |s| + s.write "lib/foo.rb", "puts :CACHE" + end + + bundle "#{cmd} --all" + + expect(bundled_app("vendor/cache/foo-1.0")).to exist + FileUtils.rm_rf lib_path("foo-1.0") + + run "require 'foo'" + expect(out).to eq("CACHE") + end + + it "removes stale entries cache" do + build_lib "foo" + + install_gemfile <<-G + gem "foo", :path => '#{lib_path("foo-1.0")}' + G + + bundle "#{cmd} --all" + + install_gemfile <<-G + gem "bar", :path => '#{lib_path("bar-1.0")}' + G + + bundle "#{cmd} --all" + expect(bundled_app("vendor/cache/bar-1.0")).not_to exist + end + + it "raises a warning without --all" do + build_lib "foo" + + install_gemfile <<-G + gem "foo", :path => '#{lib_path("foo-1.0")}' + G + + bundle cmd + expect(out).to match(/please pass the \-\-all flag/) + expect(bundled_app("vendor/cache/foo-1.0")).not_to exist + end + + it "stores the given flag" do + build_lib "foo" + + install_gemfile <<-G + gem "foo", :path => '#{lib_path("foo-1.0")}' + G + + bundle "#{cmd} --all" + build_lib "bar" + + install_gemfile <<-G + gem "foo", :path => '#{lib_path("foo-1.0")}' + gem "bar", :path => '#{lib_path("bar-1.0")}' + G + + bundle cmd + expect(bundled_app("vendor/cache/bar-1.0")).to exist + end + + it "can rewind chosen configuration" do + build_lib "foo" + + install_gemfile <<-G + gem "foo", :path => '#{lib_path("foo-1.0")}' + G + + bundle "#{cmd} --all" + build_lib "baz" + + gemfile <<-G + gem "foo", :path => '#{lib_path("foo-1.0")}' + gem "baz", :path => '#{lib_path("baz-1.0")}' + G + + bundle "#{cmd} --no-all" + expect(bundled_app("vendor/cache/baz-1.0")).not_to exist + end + end +end diff --git a/bundler-1.7.2/spec/cache/platform_spec.rb b/bundler-1.7.2/spec/cache/platform_spec.rb new file mode 100644 index 0000000..0ced663 --- /dev/null +++ b/bundler-1.7.2/spec/cache/platform_spec.rb @@ -0,0 +1,57 @@ +require "spec_helper" + +describe "bundle cache with multiple platforms" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + + platforms :ruby, :ruby_18, :ruby_19, :ruby_20, :ruby_21 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 do + gem "activerecord", "2.3.2" + end + G + + lockfile <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + activesupport (2.3.5) + activerecord (2.3.2) + + PLATFORMS + ruby + java + + 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" + end + + it "ensures that bundle install does not delete gems for other platforms" do + bundle "install" + + 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 + bundle "update" + + 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/bundler-1.7.2/spec/commands/binstubs_spec.rb b/bundler-1.7.2/spec/commands/binstubs_spec.rb new file mode 100644 index 0000000..e307539 --- /dev/null +++ b/bundler-1.7.2/spec/commands/binstubs_spec.rb @@ -0,0 +1,219 @@ +require "spec_helper" + +describe "bundle binstubs " do + context "when the gem exists in the lockfile" do + it "sets up the binstub" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + bundle "binstubs rack" + + expect(bundled_app("bin/rackup")).to exist + end + + it "does not install other binstubs" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "rails" + G + + bundle "binstubs rails" + + expect(bundled_app("bin/rackup")).not_to exist + expect(bundled_app("bin/rails")).to exist + end + + it "does install multiple binstubs" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "rails" + G + + bundle "binstubs rails rack" + + expect(bundled_app("bin/rackup")).to exist + expect(bundled_app("bin/rails")).to exist + end + + it "displays an error when used without any gem" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + bundle "binstubs", :exitstatus => true + expect(exitstatus).to eq(1) + expect(out).to eq("`bundle binstubs` needs at least one gem to run.") + end + + it "does not bundle the bundler binary" do + install_gemfile <<-G + source "file://#{gem_repo1}" + G + + bundle "binstubs bundler" + + expect(bundled_app("bin/bundle")).not_to exist + expect(out).to eq("Sorry, Bundler can only be run via Rubygems.") + end + + it "installs binstubs from git gems" do + FileUtils.mkdir_p(lib_path("foo/bin")) + FileUtils.touch(lib_path("foo/bin/foo")) + build_git "foo", "1.0", :path => lib_path("foo") do |s| + s.executables = %w(foo) + end + install_gemfile <<-G + gem "foo", :git => "#{lib_path('foo')}" + G + + bundle "binstubs foo" + + expect(bundled_app("bin/foo")).to exist + end + + it "installs binstubs from path gems" do + FileUtils.mkdir_p(lib_path("foo/bin")) + FileUtils.touch(lib_path("foo/bin/foo")) + build_lib "foo" , "1.0", :path => lib_path("foo") do |s| + s.executables = %w(foo) + end + install_gemfile <<-G + gem "foo", :path => "#{lib_path('foo')}" + G + + bundle "binstubs foo" + + expect(bundled_app("bin/foo")).to exist + end + + it "sets correct permissions for binstubs" do + with_umask(0002) do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + bundle "binstubs rack" + binary = bundled_app("bin/rackup") + expect(File.stat(binary).mode.to_s(8)).to eq("100775") + end + end + end + + context "when the gem doesn't exist" do + it "displays an error with correct status" do + install_gemfile <<-G + source "file://#{gem_repo1}" + G + + bundle "binstubs doesnt_exist", :exitstatus => true + + expect(exitstatus).to eq(7) + expect(out).to eq("Could not find gem 'doesnt_exist'.") + end + end + + context "--path" do + it "sets the binstubs dir" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + bundle "binstubs rack --path exec" + + expect(bundled_app("exec/rackup")).to exist + end + + it "setting is saved for bundle install" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "rails" + G + + bundle "binstubs rack --path exec" + bundle :install + + expect(bundled_app("exec/rails")).to exist + end + end + + context "when the bin already exists" do + it "doesn't overwrite and warns" do + FileUtils.mkdir_p(bundled_app("bin")) + File.open(bundled_app("bin/rackup"), 'wb') do |file| + file.print "OMG" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + bundle "binstubs rack" + + expect(bundled_app("bin/rackup")).to exist + expect(File.read(bundled_app("bin/rackup"))).to eq("OMG") + expect(out).to include("Skipped rackup") + expect(out).to include("overwrite skipped stubs, use --force") + end + + context "when using --force" do + it "overwrites the binstub" do + FileUtils.mkdir_p(bundled_app("bin")) + File.open(bundled_app("bin/rackup"), 'wb') do |file| + file.print "OMG" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + bundle "binstubs rack --force" + + expect(bundled_app("bin/rackup")).to exist + expect(File.read(bundled_app("bin/rackup"))).not_to eq("OMG") + end + end + end + + context "when the gem has no bins" do + it "suggests child gems if they have bins" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack-obama" + G + + bundle "binstubs rack-obama" + expect(out).to include('rack-obama has no executables') + expect(out).to include('rack has: rackup') + end + + it "works if child gems don't have bins" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "actionpack" + G + + bundle "binstubs actionpack" + expect(out).to include('no executables for the gem actionpack') + end + + it "works if the gem has development dependencies" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "with_development_dependency" + G + + bundle "binstubs with_development_dependency" + expect(out).to include('no executables for the gem with_development_dependency') + end + end +end diff --git a/bundler-1.7.2/spec/commands/check_spec.rb b/bundler-1.7.2/spec/commands/check_spec.rb new file mode 100644 index 0000000..248b5c2 --- /dev/null +++ b/bundler-1.7.2/spec/commands/check_spec.rb @@ -0,0 +1,278 @@ +require "spec_helper" + +describe "bundle check" do + it "returns success when the Gemfile is satisfied" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + G + + bundle :check, :exitstatus => true + expect(@exitstatus).to eq(0) + expect(out).to eq("The Gemfile's dependencies are satisfied") + end + + it "works with the --gemfile flag when not in the directory" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + G + + Dir.chdir tmp + bundle "check --gemfile bundled_app/Gemfile" + expect(out).to eq("The Gemfile's dependencies are satisfied") + end + + it "creates a Gemfile.lock by default if one does not exist" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + G + + FileUtils.rm("Gemfile.lock") + + bundle "check" + + expect(bundled_app("Gemfile.lock")).to exist + end + + it "does not create a Gemfile.lock if --dry-run was passed" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + G + + FileUtils.rm("Gemfile.lock") + + bundle "check --dry-run" + + expect(bundled_app("Gemfile.lock")).not_to exist + end + + it "prints a generic error if the missing gems are unresolvable" do + system_gems ["rails-2.3.2"] + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + G + + bundle :check + expect(out).to include("Bundler can't satisfy your Gemfile's dependencies.") + end + + it "prints a generic error if a Gemfile.lock does not exist and a toplevel dependency does not exist" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + G + + bundle :check, :exitstatus => true + expect(@exitstatus).to be > 0 + expect(out).to include("Bundler can't satisfy your Gemfile's dependencies.") + end + + it "prints a generic message if you changed your lockfile" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem 'rails' + G + install_gemfile <<-G + source "file://#{gem_repo1}" + gem 'rails_fail' + G + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + gem "rails_fail" + G + + bundle :check + expect(out).to include("Bundler can't satisfy your Gemfile's dependencies.") + end + + it "remembers --without option from install" do + gemfile <<-G + source "file://#{gem_repo1}" + group :foo do + gem "rack" + end + G + + bundle "install --without foo" + bundle "check", :exitstatus => true + expect(@exitstatus).to eq(0) + expect(out).to include("The Gemfile's dependencies are satisfied") + end + + it "ensures that gems are actually installed and not just cached" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :group => :foo + G + + bundle "install --without foo" + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + bundle "check", :exitstatus => true + expect(out).to include("* rack (1.0.0)") + expect(@exitstatus).to eq(1) + end + + it "ignores missing gems restricted to other platforms" do + system_gems "rack-1.0.0" + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + platforms :#{not_local_tag} do + gem "activesupport" + end + G + + lockfile <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + activesupport (2.3.5) + rack (1.0.0) + + PLATFORMS + #{local} + #{not_local} + + DEPENDENCIES + rack + activesupport + G + + bundle :check + expect(out).to eq("The Gemfile's dependencies are satisfied") + end + + it "works with env conditionals" do + system_gems "rack-1.0.0" + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + env :NOT_GOING_TO_BE_SET do + gem "activesupport" + end + G + + lockfile <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + activesupport (2.3.5) + rack (1.0.0) + + PLATFORMS + #{local} + #{not_local} + + DEPENDENCIES + rack + activesupport + G + + bundle :check + expect(out).to eq("The Gemfile's dependencies are satisfied") + end + + it "outputs an error when the default Gemfile is not found" do + bundle :check, :exitstatus => true + expect(@exitstatus).to eq(10) + 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) + expect(out).not_to include("Unfortunately, a fatal error has occurred. ") + end + + it "should not crash when called multiple times on a new machine" do + gemfile <<-G + gem 'rails', '3.0.0.beta3' + gem 'paperclip', :git => 'git://github.com/thoughtbot/paperclip.git' + G + + simulate_new_machine + bundle "check" + last_out = out + 3.times do |i| + bundle :check + expect(out).to eq(last_out) + expect(err).to be_empty + end + end + + it "fails when there's no lock file and frozen is set" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "foo" + G + + bundle "install" + bundle "install --deployment" + FileUtils.rm(bundled_app("Gemfile.lock")) + + bundle :check, :exitstatus => true + expect(exitstatus).not_to eq(0) + end + + context "--path" do + before do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + G + bundle "install --path vendor/bundle" + + FileUtils.rm_rf(bundled_app(".bundle")) + end + + it "returns success" do + bundle "check --path vendor/bundle", :exitstatus => true + expect(@exitstatus).to eq(0) + 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) + end + end + + describe "when locked" do + before :each do + system_gems "rack-1.0.0" + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "1.0" + G + end + + it "returns success when the Gemfile is satisfied" do + bundle :install + bundle :check, :exitstatus => true + expect(@exitstatus).to eq(0) + expect(out).to eq("The Gemfile's dependencies are satisfied") + end + + it "shows what is missing with the current Gemfile if it is not satisfied" do + simulate_new_machine + bundle :check + expect(out).to match(/The following gems are missing/) + expect(out).to include("* rack (1.0") + end + end +end diff --git a/bundler-1.7.2/spec/commands/clean_spec.rb b/bundler-1.7.2/spec/commands/clean_spec.rb new file mode 100644 index 0000000..cee1312 --- /dev/null +++ b/bundler-1.7.2/spec/commands/clean_spec.rb @@ -0,0 +1,592 @@ +require "spec_helper" + +describe "bundle clean" do + def should_have_gems(*gems) + gems.each do |g| + expect(vendored_gems("gems/#{g}")).to exist + expect(vendored_gems("specifications/#{g}.gemspec")).to exist + expect(vendored_gems("cache/#{g}.gem")).to exist + end + end + + def should_not_have_gems(*gems) + gems.each do |g| + expect(vendored_gems("gems/#{g}")).not_to exist + expect(vendored_gems("specifications/#{g}.gemspec")).not_to exist + expect(vendored_gems("cache/#{g}.gem")).not_to exist + end + end + + it "removes unused gems that are different" 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" + G + bundle "install" + + bundle :clean + + expect(out).to eq("Removing foo (1.0)") + + should_have_gems 'thin-1.0', 'rack-1.0.0' + should_not_have_gems 'foo-1.0' + + expect(vendored_gems("bin/rackup")).to exist + end + + it "removes old version of gem if unused" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack", "0.9.1" + gem "foo" + G + + bundle "install --path vendor/bundle --no-clean" + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack", "1.0.0" + gem "foo" + G + bundle "install" + + bundle :clean + + expect(out).to eq("Removing rack (0.9.1)") + + should_have_gems 'foo-1.0', 'rack-1.0.0' + should_not_have_gems 'rack-0.9.1' + + expect(vendored_gems("bin/rackup")).to exist + end + + it "removes new version of gem if unused" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack", "1.0.0" + gem "foo" + G + + bundle "install --path vendor/bundle --no-clean" + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack", "0.9.1" + gem "foo" + G + bundle "install" + + bundle :clean + + expect(out).to eq("Removing rack (1.0.0)") + + should_have_gems 'foo-1.0', 'rack-0.9.1' + should_not_have_gems 'rack-1.0.0' + + expect(vendored_gems("bin/rackup")).to exist + end + + it "removes gems in bundle without groups" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "foo" + + group :test_group do + gem "rack", "1.0.0" + end + G + + bundle "install --path vendor/bundle" + bundle "install --without test_group" + bundle :clean + + expect(out).to eq("Removing rack (1.0.0)") + + should_have_gems 'foo-1.0' + should_not_have_gems 'rack-1.0.0' + + expect(vendored_gems("bin/rackup")).to_not exist + end + + it "does not remove cached git dir if it's being used" do + build_git "foo" + revision = revision_for(lib_path("foo-1.0")) + git_path = lib_path('foo-1.0') + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack", "1.0.0" + git "#{git_path}", :ref => "#{revision}" do + gem "foo" + end + G + + bundle "install --path vendor/bundle" + + bundle :clean + + digest = Digest::SHA1.hexdigest(git_path.to_s) + expect(vendored_gems("cache/bundler/git/foo-1.0-#{digest}")).to exist + end + + it "removes unused git gems" do + build_git "foo", :path => lib_path("foo") + git_path = lib_path('foo') + revision = revision_for(git_path) + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack", "1.0.0" + git "#{git_path}", :ref => "#{revision}" do + gem "foo" + end + G + + bundle "install --path vendor/bundle" + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack", "1.0.0" + G + bundle "install" + + bundle :clean + + expect(out).to eq("Removing foo (#{revision[0..11]})") + + expect(vendored_gems("gems/rack-1.0.0")).to exist + expect(vendored_gems("bundler/gems/foo-#{revision[0..11]}")).not_to exist + digest = Digest::SHA1.hexdigest(git_path.to_s) + expect(vendored_gems("cache/bundler/git/foo-#{digest}")).not_to exist + + expect(vendored_gems("specifications/rack-1.0.0.gemspec")).to exist + + expect(vendored_gems("bin/rackup")).to exist + end + + it "removes old git gems" do + build_git "foo-bar", :path => lib_path("foo-bar") + revision = revision_for(lib_path("foo-bar")) + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack", "1.0.0" + git "#{lib_path('foo-bar')}" do + gem "foo-bar" + end + G + + bundle "install --path vendor/bundle" + + update_git "foo", :path => lib_path("foo-bar") + revision2 = revision_for(lib_path("foo-bar")) + + bundle "update" + bundle :clean + + expect(out).to eq("Removing foo-bar (#{revision[0..11]})") + + expect(vendored_gems("gems/rack-1.0.0")).to exist + expect(vendored_gems("bundler/gems/foo-bar-#{revision[0..11]}")).not_to exist + expect(vendored_gems("bundler/gems/foo-bar-#{revision2[0..11]}")).to exist + + expect(vendored_gems("specifications/rack-1.0.0.gemspec")).to exist + + expect(vendored_gems("bin/rackup")).to exist + end + + it "does not remove nested gems in a git repo" do + build_lib "activesupport", "3.0", :path => lib_path("rails/activesupport") + build_git "rails", "3.0", :path => lib_path("rails") do |s| + s.add_dependency "activesupport", "= 3.0" + end + revision = revision_for(lib_path("rails")) + + gemfile <<-G + gem "activesupport", :git => "#{lib_path('rails')}", :ref => '#{revision}' + G + + bundle "install --path vendor/bundle" + bundle :clean + expect(out).to eq("") + + expect(vendored_gems("bundler/gems/rails-#{revision[0..11]}")).to exist + end + + it "does not remove git sources that are in without groups" do + build_git "foo", :path => lib_path("foo") + git_path = lib_path('foo') + revision = revision_for(git_path) + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack", "1.0.0" + group :test do + git "#{git_path}", :ref => "#{revision}" do + gem "foo" + end + end + G + bundle "install --path vendor/bundle --without test" + + bundle :clean + + expect(out).to eq("") + expect(vendored_gems("bundler/gems/foo-#{revision[0..11]}")).to exist + digest = Digest::SHA1.hexdigest(git_path.to_s) + expect(vendored_gems("cache/bundler/git/foo-#{digest}")).to_not exist + end + + it "does not blow up when using without groups" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack" + + group :development do + gem "foo" + end + G + + bundle "install --path vendor/bundle --without development" + + bundle :clean, :exitstatus => true + expect(exitstatus).to eq(0) + end + + it "displays an error when used without --path" do + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack", "1.0.0" + G + + bundle :clean, :exitstatus => true + + expect(exitstatus).to eq(1) + expect(out).to eq("Can only use bundle clean when --path is set or --force is set") + end + + # handling bundle clean upgrade path from the pre's + it "removes .gem/.gemspec file even if there's no corresponding gem dir" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "thin" + gem "foo" + G + + bundle "install --path vendor/bundle" + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "foo" + G + bundle "install" + + FileUtils.rm(vendored_gems("bin/rackup")) + FileUtils.rm_rf(vendored_gems("gems/thin-1.0")) + FileUtils.rm_rf(vendored_gems("gems/rack-1.0.0")) + + bundle :clean + + should_not_have_gems 'thin-1.0', 'rack-1.0' + should_have_gems 'foo-1.0' + + expect(vendored_gems("bin/rackup")).not_to exist + end + + it "does not call clean automatically when using system gems" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "thin" + gem "rack" + G + bundle :install + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack" + G + bundle :install + + sys_exec "gem list" + expect(out).to include("rack (1.0.0)") + expect(out).to include("thin (1.0)") + end + + it "--clean should override the bundle setting on install" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "thin" + gem "rack" + G + bundle "install --path vendor/bundle --clean" + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack" + G + bundle "install" + + should_have_gems 'rack-1.0.0' + should_not_have_gems 'thin-1.0' + end + + it "--clean should override the bundle setting on update" do + build_repo2 + + gemfile <<-G + source "file://#{gem_repo2}" + + gem "foo" + G + bundle "install --path vendor/bundle --clean" + + update_repo2 do + build_gem 'foo', '1.0.1' + end + + bundle "update" + + should_have_gems 'foo-1.0.1' + should_not_have_gems 'foo-1.0' + end + + it "does not clean automatically on --path" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "thin" + gem "rack" + G + bundle "install --path vendor/bundle" + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack" + G + bundle "install" + + should_have_gems 'rack-1.0.0', 'thin-1.0' + end + + it "does not clean on bundle update with --path" do + build_repo2 + + gemfile <<-G + source "file://#{gem_repo2}" + + gem "foo" + G + bundle "install --path vendor/bundle" + + update_repo2 do + build_gem 'foo', '1.0.1' + end + + bundle :update + should_have_gems 'foo-1.0', 'foo-1.0.1' + end + + it "does not clean on bundle update when using --system" do + build_repo2 + + gemfile <<-G + source "file://#{gem_repo2}" + + gem "foo" + G + bundle "install" + + update_repo2 do + build_gem 'foo', '1.0.1' + end + bundle :update + + sys_exec "gem list" + expect(out).to include("foo (1.0.1, 1.0)") + end + + it "cleans system gems when --force is used" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "foo" + gem "rack" + G + bundle :install + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack" + G + bundle :install + bundle "clean --force" + + expect(out).to eq("Removing foo (1.0)") + sys_exec "gem list" + expect(out).not_to include("foo (1.0)") + expect(out).to include("rack (1.0.0)") + end + + it "cleans git gems with a 7 length git revision" do + build_git "foo" + revision = revision_for(lib_path("foo-1.0")) + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + + bundle "install --path vendor/bundle" + + # mimic 7 length git revisions in Gemfile.lock + gemfile_lock = File.read(bundled_app('Gemfile.lock')).split("\n") + gemfile_lock.each_with_index do |line, index| + gemfile_lock[index] = line[0..(11 + 7)] if line.include?(" revision:") + end + File.open(bundled_app('Gemfile.lock'), 'w') do |file| + file.print gemfile_lock.join("\n") + end + + bundle "install --path vendor/bundle" + + bundle :clean + + expect(out).not_to include("Removing foo (1.0 #{revision[0..6]})") + + expect(vendored_gems("bundler/gems/foo-1.0-#{revision[0..6]}")).to exist + end + + it "when using --force on system gems, it doesn't remove binaries" do + build_repo2 + update_repo2 do + build_gem 'bindir' do |s| + s.bindir = "exe" + s.executables = "foo" + end + end + + gemfile <<-G + source "file://#{gem_repo2}" + + gem "bindir" + G + bundle :install + + bundle "clean --force" + + sys_status "foo" + + expect(exitstatus).to eq(0) + expect(out).to eq("1.0") + end + + it "doesn't blow up on path gems without a .gempsec" do + relative_path = "vendor/private_gems/bar-1.0" + absolute_path = bundled_app(relative_path) + FileUtils.mkdir_p("#{absolute_path}/lib/bar") + File.open("#{absolute_path}/lib/bar/bar.rb", 'wb') do |file| + file.puts "module Bar; end" + end + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "foo" + gem "bar", "1.0", :path => "#{relative_path}" + G + + bundle "install --path vendor/bundle" + bundle :clean, :exitstatus => true + + expect(exitstatus).to eq(0) + end + + it "doesn't remove gems in dry-run mode" 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" + G + + bundle :install + + bundle "clean --dry-run" + + expect(out).not_to eq("Removing foo (1.0)") + expect(out).to eq("Would have removed foo (1.0)") + + should_have_gems 'thin-1.0', 'rack-1.0.0', 'foo-1.0' + + expect(vendored_gems("bin/rackup")).to exist + end + + it "doesn't store dry run as a config setting" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "thin" + gem "foo" + G + + bundle "install --path vendor/bundle --no-clean" + bundle "config dry_run false" + + gemfile <<-G + source "file://#{gem_repo1}" + + gem "thin" + G + + bundle :install + + bundle "clean" + + expect(out).to eq("Removing foo (1.0)") + expect(out).not_to eq("Would have removed foo (1.0)") + + should_have_gems 'thin-1.0', 'rack-1.0.0' + should_not_have_gems 'foo-1.0' + + expect(vendored_gems("bin/rackup")).to exist + end +end diff --git a/bundler-1.7.2/spec/commands/config_spec.rb b/bundler-1.7.2/spec/commands/config_spec.rb new file mode 100644 index 0000000..964e1d8 --- /dev/null +++ b/bundler-1.7.2/spec/commands/config_spec.rb @@ -0,0 +1,227 @@ +require "spec_helper" + +describe ".bundle/config" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "1.0.0" + G + end + + describe "BUNDLE_APP_CONFIG" do + it "can be moved with an environment variable" do + ENV['BUNDLE_APP_CONFIG'] = tmp('foo/bar').to_s + bundle "install --path vendor/bundle" + + expect(bundled_app('.bundle')).not_to exist + expect(tmp('foo/bar/config')).to exist + should_be_installed "rack 1.0.0" + end + + it "can provide a relative path with the environment variable" do + FileUtils.mkdir_p bundled_app('omg') + Dir.chdir bundled_app('omg') + + ENV['BUNDLE_APP_CONFIG'] = "../foo" + bundle "install --path vendor/bundle" + + expect(bundled_app(".bundle")).not_to exist + expect(bundled_app("../foo/config")).to exist + should_be_installed "rack 1.0.0" + end + + it "removes environment.rb from BUNDLE_APP_CONFIG's path" do + FileUtils.mkdir_p(tmp('foo/bar')) + ENV['BUNDLE_APP_CONFIG'] = tmp('foo/bar').to_s + bundle "install" + FileUtils.touch tmp('foo/bar/environment.rb') + should_be_installed "rack 1.0.0" + expect(tmp('foo/bar/environment.rb')).not_to exist + end + end + + describe "global" do + before(:each) { bundle :install } + + it "is the default" do + bundle "config foo global" + run "puts Bundler.settings[:foo]" + expect(out).to eq("global") + end + + it "can also be set explicitly" do + bundle "config --global foo global" + run "puts Bundler.settings[:foo]" + expect(out).to eq("global") + end + + it "has lower precedence than local" do + bundle "config --local foo local" + + bundle "config --global foo global" + expect(out).to match(/Your application has set foo to "local"/) + + run "puts Bundler.settings[:foo]" + expect(out).to eq("local") + end + + it "has lower precedence than env" do + begin + ENV["BUNDLE_FOO"] = "env" + + bundle "config --global foo global" + expect(out).to match(/You have a bundler environment variable for foo set to "env"/) + + run "puts Bundler.settings[:foo]" + expect(out).to eq("env") + ensure + ENV.delete("BUNDLE_FOO") + end + end + + it "can be deleted" do + bundle "config --global foo global" + bundle "config --delete foo" + + run "puts Bundler.settings[:foo] == nil" + expect(out).to eq("true") + end + + it "warns when overriding" do + bundle "config --global foo previous" + bundle "config --global foo global" + expect(out).to match(/You are replacing the current global value of foo/) + + run "puts Bundler.settings[:foo]" + expect(out).to eq("global") + end + + it "expands the path at time of setting" do + bundle "config --global local.foo .." + run "puts Bundler.settings['local.foo']" + expect(out).to eq(File.expand_path(Dir.pwd + "/..")) + end + end + + describe "local" do + before(:each) { bundle :install } + + it "can also be set explicitly" do + bundle "config --local foo local" + run "puts Bundler.settings[:foo]" + expect(out).to eq("local") + end + + it "has higher precedence than env" do + begin + ENV["BUNDLE_FOO"] = "env" + bundle "config --local foo local" + + run "puts Bundler.settings[:foo]" + expect(out).to eq("local") + ensure + ENV.delete("BUNDLE_FOO") + end + end + + it "can be deleted" do + bundle "config --local foo local" + bundle "config --delete foo" + + run "puts Bundler.settings[:foo] == nil" + expect(out).to eq("true") + end + + it "warns when overriding" do + bundle "config --local foo previous" + bundle "config --local foo local" + expect(out).to match(/You are replacing the current local value of foo/) + + run "puts Bundler.settings[:foo]" + expect(out).to eq("local") + end + + it "expands the path at time of setting" do + bundle "config --local local.foo .." + run "puts Bundler.settings['local.foo']" + expect(out).to eq(File.expand_path(Dir.pwd + "/..")) + end + end + + describe "env" do + before(:each) { bundle :install } + + it "can set boolean properties via the environment" do + ENV["BUNDLE_FROZEN"] = "true" + + run "if Bundler.settings[:frozen]; puts 'true' else puts 'false' end" + expect(out).to eq("true") + end + + it "can set negative boolean properties via the environment" do + run "if Bundler.settings[:frozen]; puts 'true' else puts 'false' end" + expect(out).to eq("false") + + ENV["BUNDLE_FROZEN"] = "false" + + run "if Bundler.settings[:frozen]; puts 'true' else puts 'false' end" + expect(out).to eq("false") + + ENV["BUNDLE_FROZEN"] = "0" + + run "if Bundler.settings[:frozen]; puts 'true' else puts 'false' end" + expect(out).to eq("false") + + ENV["BUNDLE_FROZEN"] = "" + + run "if Bundler.settings[:frozen]; puts 'true' else puts 'false' end" + expect(out).to eq("false") + end + end + + describe "gem mirrors" do + before(:each) { bundle :install } + + it "configures mirrors using keys with `mirror.`" do + bundle "config --local mirror.http://gems.example.org http://gem-mirror.example.org" + run(<<-E) +Bundler.settings.gem_mirrors.each do |k, v| + puts "\#{k} => \#{v}" +end +E + expect(out).to eq("http://gems.example.org/ => http://gem-mirror.example.org/") + end + end + + describe "quoting" do + before(:each) { bundle :install } + + it "saves quotes" do + bundle "config foo something\\'" + run "puts Bundler.settings[:foo]" + expect(out).to eq("something'") + end + + it "doesn't return quotes around values", :ruby => "1.9" do + bundle "config foo '1'" + run "puts Bundler.settings.send(:global_config_file).read" + expect(out).to include("'1'") + run "puts Bundler.settings[:foo]" + expect(out).to eq("1") + end + end + + 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" + end + + it "doesn't wrap values" do + bundle "config foo #{long_string}" + run "puts Bundler.settings[:foo]" + expect(out).to match(long_string) + end + end + +end diff --git a/bundler-1.7.2/spec/commands/console_spec.rb b/bundler-1.7.2/spec/commands/console_spec.rb new file mode 100644 index 0000000..75d6796 --- /dev/null +++ b/bundler-1.7.2/spec/commands/console_spec.rb @@ -0,0 +1,76 @@ +require "spec_helper" + +describe "bundle console" do + before :each do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "activesupport", :group => :test + gem "rack_middleware", :group => :development + G + end + + it "starts IRB with the default group loaded" do + bundle "console" do |input| + input.puts("puts RACK") + input.puts("exit") + end + expect(out).to include("0.9.1") + end + + it "starts another REPL if configured as such" do + bundle "config console pry" + + bundle "console" do |input| + input.puts("__callee__") + input.puts("exit") + end + expect(out).to include("pry") + end + + it "falls back to IRB if the other REPL isn't available" do + bundle "config console pry" + # make sure pry isn't there + + bundle "console" do |input| + input.puts("__callee__") + input.puts("exit") + end + expect(out).to include("irb") + end + + + it "doesn't load any other groups" do + bundle "console" do |input| + input.puts("puts ACTIVESUPPORT") + input.puts("exit") + end + expect(out).to include("NameError") + end + + describe "when given a group" do + it "loads the given group" do + bundle "console test" do |input| + input.puts("puts ACTIVESUPPORT") + input.puts("exit") + end + expect(out).to include("2.3.5") + end + + it "loads the default group" do + bundle "console test" do |input| + input.puts("puts RACK") + input.puts("exit") + end + expect(out).to include("0.9.1") + end + + it "doesn't load other groups" do + bundle "console test" do |input| + input.puts("puts RACK_MIDDLEWARE") + input.puts("exit") + end + expect(out).to include("NameError") + end + end +end diff --git a/bundler-1.7.2/spec/commands/exec_spec.rb b/bundler-1.7.2/spec/commands/exec_spec.rb new file mode 100644 index 0000000..52b9356 --- /dev/null +++ b/bundler-1.7.2/spec/commands/exec_spec.rb @@ -0,0 +1,309 @@ +require "spec_helper" + +describe "bundle exec" do + before :each do + system_gems "rack-1.0.0", "rack-0.9.1" + end + + it "activates the correct gem" do + gemfile <<-G + gem "rack", "0.9.1" + G + + bundle "exec rackup" + expect(out).to eq("0.9.1") + end + + it "works when the bins are in ~/.bundle" do + install_gemfile <<-G + gem "rack" + G + + bundle "exec rackup" + expect(out).to eq("1.0.0") + end + + it "works when running from a random directory" do + install_gemfile <<-G + gem "rack" + G + + bundle "exec 'cd #{tmp('gems')} && rackup'" + + expect(out).to eq("1.0.0") + end + + it "works when exec'ing something else" do + install_gemfile 'gem "rack"' + bundle "exec echo exec" + expect(out).to eq("exec") + end + + it "works when exec'ing to ruby" do + install_gemfile 'gem "rack"' + bundle "exec ruby -e 'puts %{hi}'" + expect(out).to eq("hi") + end + + it "accepts --verbose" do + install_gemfile 'gem "rack"' + bundle "exec --verbose echo foobar" + expect(out).to eq("foobar") + end + + it "passes --verbose to command if it is given after the command" do + install_gemfile 'gem "rack"' + bundle "exec echo --verbose" + expect(out).to eq("--verbose") + end + + it "handles --keep-file-descriptors" do + require 'tempfile' + + bundle_bin = File.expand_path('../../../bin/bundle', __FILE__) + + command = Tempfile.new("io-test") + command.sync = true + command.write <<-G + if ARGV[0] + IO.for_fd(ARGV[0].to_i) + else + require 'tempfile' + io = Tempfile.new("io-test-fd") + args = %W[#{Gem.ruby} -I#{lib} #{bundle_bin} exec --keep-file-descriptors #{Gem.ruby} #{command.path} \#{io.to_i}] + args << { io.to_i => io } if RUBY_VERSION >= "2.0" + exec(*args) + end + G + + install_gemfile '' + sys_exec("#{Gem.ruby} #{command.path}") + + if RUBY_VERSION >= "2.0" + expect(out).to eq("") + else + expect(out).to eq("Ruby version #{RUBY_VERSION} defaults to keeping non-standard file descriptors on Kernel#exec.") + end + + expect(err).to eq("") + end + + it "accepts --keep-file-descriptors" do + install_gemfile '' + bundle "exec --keep-file-descriptors echo foobar" + + expect(err).to eq("") + end + + it "can run a command named --verbose" do + install_gemfile 'gem "rack"' + File.open("--verbose", 'w') do |f| + f.puts "#!/bin/sh" + f.puts "echo foobar" + end + File.chmod(0744, "--verbose") + ENV['PATH'] = "." + bundle "exec -- --verbose" + expect(out).to eq("foobar") + end + + it "handles different versions in different bundles" do + build_repo2 do + build_gem "rack_two", "1.0.0" do |s| + s.executables = "rackup" + end + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "0.9.1" + G + + Dir.chdir bundled_app2 do + install_gemfile bundled_app2('Gemfile'), <<-G + source "file://#{gem_repo2}" + gem "rack_two", "1.0.0" + G + end + + bundle "exec rackup" + + expect(out).to eq("0.9.1") + expect(err).to match("deprecated") + + Dir.chdir bundled_app2 do + bundle "exec rackup" + expect(out).to eq("1.0.0") + end + end + + it "handles gems installed with --without" do + install_gemfile <<-G, :without => :middleware + source "file://#{gem_repo1}" + gem "rack" # rack 0.9.1 and 1.0 exist + + group :middleware do + gem "rack_middleware" # rack_middleware depends on rack 0.9.1 + end + G + + bundle "exec rackup" + + expect(out).to eq("0.9.1") + should_not_be_installed "rack_middleware 1.0" + end + + it "does not duplicate already exec'ed RUBYOPT" do + install_gemfile <<-G + gem "rack" + G + + rubyopt = ENV['RUBYOPT'] + rubyopt = "-rbundler/setup #{rubyopt}" + + bundle "exec 'echo $RUBYOPT'" + expect(out).to have_rubyopts(rubyopt) + + bundle "exec 'echo $RUBYOPT'", :env => {"RUBYOPT" => rubyopt} + expect(out).to have_rubyopts(rubyopt) + end + + it "does not duplicate already exec'ed RUBYLIB" do + install_gemfile <<-G + gem "rack" + G + + rubylib = ENV['RUBYLIB'] + rubylib = "#{rubylib}".split(File::PATH_SEPARATOR).unshift "#{bundler_path}" + rubylib = rubylib.uniq.join(File::PATH_SEPARATOR) + + bundle "exec 'echo $RUBYLIB'" + expect(out).to eq(rubylib) + + bundle "exec 'echo $RUBYLIB'", :env => {"RUBYLIB" => rubylib} + expect(out).to eq(rubylib) + end + + it "errors nicely when the argument doesn't exist" do + install_gemfile <<-G + gem "rack" + G + + bundle "exec foobarbaz", :exitstatus => true + expect(exitstatus).to eq(127) + expect(out).to include("bundler: command not found: foobarbaz") + expect(out).to include("Install missing gem executables with `bundle install`") + end + + it "errors nicely when the argument is not executable" do + install_gemfile <<-G + gem "rack" + G + + bundle "exec touch foo" + bundle "exec ./foo", :exitstatus => true + expect(exitstatus).to eq(126) + expect(out).to include("bundler: not executable: ./foo") + end + + it "errors nicely when no arguments are passed" do + install_gemfile <<-G + gem "rack" + G + + bundle "exec", :exitstatus => true + expect(exitstatus).to eq(128) + expect(out).to include("bundler: exec needs a command to run") + end + + describe "with gem executables" do + describe "run from a random directory" do + before(:each) do + install_gemfile <<-G + gem "rack" + G + end + + it "works when unlocked" do + bundle "exec 'cd #{tmp('gems')} && rackup'" + expect(out).to eq("1.0.0") + end + + it "works when locked" do + should_be_locked + bundle "exec 'cd #{tmp('gems')} && rackup'" + expect(out).to eq("1.0.0") + end + end + + describe "from gems bundled via :path" do + before(:each) do + build_lib "fizz", :path => home("fizz") do |s| + s.executables = "fizz" + end + + install_gemfile <<-G + gem "fizz", :path => "#{File.expand_path(home("fizz"))}" + G + end + + it "works when unlocked" do + bundle "exec fizz" + expect(out).to eq("1.0") + end + + it "works when locked" do + should_be_locked + + bundle "exec fizz" + expect(out).to eq("1.0") + end + end + + describe "from gems bundled via :git" do + before(:each) do + build_git "fizz_git" do |s| + s.executables = "fizz_git" + end + + install_gemfile <<-G + gem "fizz_git", :git => "#{lib_path('fizz_git-1.0')}" + G + end + + it "works when unlocked" do + bundle "exec fizz_git" + expect(out).to eq("1.0") + end + + it "works when locked" do + should_be_locked + bundle "exec fizz_git" + expect(out).to eq("1.0") + end + end + + describe "from gems bundled via :git with no gemspec" do + before(:each) do + build_git "fizz_no_gemspec", :gemspec => false do |s| + s.executables = "fizz_no_gemspec" + end + + install_gemfile <<-G + gem "fizz_no_gemspec", "1.0", :git => "#{lib_path('fizz_no_gemspec-1.0')}" + G + end + + it "works when unlocked" do + bundle "exec fizz_no_gemspec" + expect(out).to eq("1.0") + end + + it "works when locked" do + should_be_locked + bundle "exec fizz_no_gemspec" + expect(out).to eq("1.0") + end + end + end +end diff --git a/bundler-1.7.2/spec/commands/help_spec.rb b/bundler-1.7.2/spec/commands/help_spec.rb new file mode 100644 index 0000000..739f622 --- /dev/null +++ b/bundler-1.7.2/spec/commands/help_spec.rb @@ -0,0 +1,39 @@ +require "spec_helper" + +describe "bundle help" do + # Rubygems 1.4+ no longer load gem plugins so this test is no longer needed + rubygems_under_14 = Gem::Requirement.new("< 1.4").satisfied_by?(Gem::Version.new(Gem::VERSION)) + it "complains if older versions of bundler are installed", :if => rubygems_under_14 do + system_gems "bundler-0.8.1" + + bundle "help", :expect_err => true + expect(err).to include("older than 0.9") + expect(err).to include("running `gem cleanup bundler`.") + end + + it "uses mann when available" do + fake_man! + + bundle "help gemfile" + expect(out).to eq(%|["#{root}/lib/bundler/man/gemfile.5"]|) + end + + it "prefixes bundle commands with bundle- when finding the groff files" do + fake_man! + + bundle "help install" + expect(out).to eq(%|["#{root}/lib/bundler/man/bundle-install"]|) + end + + it "simply outputs the txt file when there is no man on the path" do + kill_path! + + bundle "help install", :expect_err => true + expect(out).to match(/BUNDLE-INSTALL/) + end + + it "still outputs the old help for commands that do not have man pages yet" do + bundle "help check" + expect(out).to include("Check searches the local machine") + end +end diff --git a/bundler-1.7.2/spec/commands/init_spec.rb b/bundler-1.7.2/spec/commands/init_spec.rb new file mode 100644 index 0000000..8bd566d --- /dev/null +++ b/bundler-1.7.2/spec/commands/init_spec.rb @@ -0,0 +1,39 @@ +require "spec_helper" + +describe "bundle init" do + it "generates a Gemfile" do + bundle :init + expect(bundled_app("Gemfile")).to exist + end + + it "does not change existing Gemfiles" do + gemfile <<-G + gem "rails" + G + + expect { + bundle :init + }.not_to change { File.read(bundled_app("Gemfile")) } + end + + it "should generate from an existing gemspec" do + spec_file = tmp.join('test.gemspec') + File.open(spec_file, 'w') do |file| + file << <<-S + Gem::Specification.new do |s| + s.name = 'test' + s.add_dependency 'rack', '= 1.0.1' + s.add_development_dependency 'rspec', '1.2' + end + S + end + + bundle :init, :gemspec => spec_file + + gemfile = bundled_app("Gemfile").read + expect(gemfile).to match(/source :gemcutter/) + expect(gemfile.scan(/gem "rack", "= 1.0.1"/).size).to eq(1) + expect(gemfile.scan(/gem "rspec", "= 1.2"/).size).to eq(1) + expect(gemfile.scan(/group :development/).size).to eq(1) + end +end diff --git a/bundler-1.7.2/spec/commands/inject_spec.rb b/bundler-1.7.2/spec/commands/inject_spec.rb new file mode 100644 index 0000000..2737b1a --- /dev/null +++ b/bundler-1.7.2/spec/commands/inject_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' + +describe "bundle inject" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + end + + context "without a lockfile" do + it "locks with the injected gems" do + expect(bundled_app("Gemfile.lock")).not_to exist + bundle "inject 'rack-obama' '> 0'" + expect(bundled_app("Gemfile.lock").read).to match(/rack-obama/) + end + end + + context "with a lockfile" do + before do + bundle "install" + end + + it "adds the injected gems to the Gemfile" do + expect(bundled_app("Gemfile").read).not_to match(/rack-obama/) + bundle "inject 'rack-obama' '> 0'" + expect(bundled_app("Gemfile").read).to match(/rack-obama/) + end + + it "locks with the injected gems" do + expect(bundled_app("Gemfile.lock").read).not_to match(/rack-obama/) + bundle "inject 'rack-obama' '> 0'" + expect(bundled_app("Gemfile.lock").read).to match(/rack-obama/) + end + end + + context "with injected gems already in the Gemfile" do + it "doesn't add existing gems" do + bundle "inject 'rack' '> 0'" + expect(out).to match(/cannot specify the same gem twice/i) + end + end + + context "when frozen" do + before do + bundle "install" + bundle "config --local frozen 1" + end + + it "injects anyway" do + bundle "inject 'rack-obama' '> 0'" + expect(bundled_app("Gemfile").read).to match(/rack-obama/) + end + + it "locks with the injected gems" do + expect(bundled_app("Gemfile.lock").read).not_to match(/rack-obama/) + bundle "inject 'rack-obama' '> 0'" + expect(bundled_app("Gemfile.lock").read).to match(/rack-obama/) + end + + it "restores frozen afterwards" do + bundle "inject 'rack-obama' '> 0'" + config = YAML.load(bundled_app(".bundle/config").read) + expect(config["BUNDLE_FROZEN"]).to eq("1") + end + + it "doesn't allow Gemfile changes" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack-obama" + G + bundle "inject 'rack' '> 0'" + expect(out).to match(/trying to install in deployment mode after changing/) + + expect(bundled_app("Gemfile.lock").read).not_to match(/rack-obama/) + end + end +end diff --git a/bundler-1.7.2/spec/commands/licenses_spec.rb b/bundler-1.7.2/spec/commands/licenses_spec.rb new file mode 100644 index 0000000..c8d5ff7 --- /dev/null +++ b/bundler-1.7.2/spec/commands/licenses_spec.rb @@ -0,0 +1,18 @@ +require "spec_helper" + +describe "bundle licenses" do + before :each do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + gem "with_license" + G + end + + it "prints license information for all gems in the bundle" do + bundle "licenses" + + expect(out).to include("actionpack: Unknown") + expect(out).to include("with_license: MIT") + end +end diff --git a/bundler-1.7.2/spec/commands/newgem_spec.rb b/bundler-1.7.2/spec/commands/newgem_spec.rb new file mode 100644 index 0000000..fc0e782 --- /dev/null +++ b/bundler-1.7.2/spec/commands/newgem_spec.rb @@ -0,0 +1,423 @@ +require "spec_helper" + +describe "bundle gem" do + before do + @git_name = `git config --global user.name`.chomp + `git config --global user.name "Bundler User"` + @git_email = `git config --global user.email`.chomp + `git config --global user.email user@example.com` + end + + after do + `git config --global user.name "#{@git_name}"` + `git config --global user.email #{@git_email}` + end + + shared_examples_for "git config is present" do + context "git config user.{name,email} present" do + it "sets gemspec author to git user.name if available" do + expect(generated_gem.gemspec.authors.first).to eq("Bundler User") + end + + it "sets gemspec email to git user.email if available" do + expect(generated_gem.gemspec.email.first).to eq("user@example.com") + end + end + end + + shared_examples_for "git config is absent" do |hoge| + 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 + + it "sets gemspec email to default message if git user.email is not set or empty" do + expect(generated_gem.gemspec.email.first).to eq("TODO: Write your email address") + end + end + + context "gem naming with underscore" do + let(:gem_name) { 'test_gem' } + + before do + bundle "gem #{gem_name}" + # reset gemspec cache for each test because of commit 3d4163a + Bundler.clear_gemspec_cache + end + + let(:generated_gem) { Bundler::GemHelper.new(bundled_app(gem_name).to_s) } + + 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 + 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"/) + end + + it "does not nest constants" do + expect(bundled_app("test_gem/lib/test_gem/version.rb").read).to match(/module TestGem/) + expect(bundled_app("test_gem/lib/test_gem.rb").read).to match(/module TestGem/) + end + + it_should_behave_like "git config is present" + + context "git config user.{name,email} is not set" do + before do + `git config --global --unset user.name` + `git config --global --unset user.email` + reset! + in_app_root + bundle "gem #{gem_name}" + end + + 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") + end + + it "requires the version file" do + expect(bundled_app("test_gem/lib/test_gem.rb").read).to match(/require "test_gem\/version"/) + end + + it "runs rake without problems" do + system_gems ["rake-10.0.2"] + + rakefile = strip_whitespace <<-RAKEFILE + task :default do + puts 'SUCCESS' + end + RAKEFILE + File.open(bundled_app("test_gem/Rakefile"), 'w') do |file| + file.puts rakefile + end + + Dir.chdir(bundled_app(gem_name)) do + sys_exec("rake") + expect(out).to include("SUCCESS") + end + end + + context "--bin parameter set" do + before do + reset! + in_app_root + bundle "gem #{gem_name} --bin" + end + + it "builds bin skeleton" do + expect(bundled_app("test_gem/bin/test_gem")).to exist + end + + it "requires 'test-gem'" do + expect(bundled_app("test_gem/bin/test_gem").read).to match(/require 'test_gem'/) + end + end + + context "no --test parameter" do + before do + reset! + in_app_root + bundle "gem #{gem_name}" + end + + it "doesn't create any spec/test file" do + expect(bundled_app("test_gem/.rspec")).to_not exist + expect(bundled_app("test_gem/spec/test_gem_spec.rb")).to_not exist + expect(bundled_app("test_gem/spec/spec_helper.rb")).to_not exist + expect(bundled_app("test_gem/test/test_test_gem.rb")).to_not exist + expect(bundled_app("test_gem/test/minitest_helper.rb")).to_not exist + end + end + + context "--test parameter set to rspec" do + before do + reset! + in_app_root + bundle "gem #{gem_name} --test=rspec" + 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 + + it "requires 'test-gem'" do + expect(bundled_app("test_gem/spec/spec_helper.rb").read).to include("require 'test_gem'") + end + + it "creates a default test which fails" do + expect(bundled_app("test_gem/spec/test_gem_spec.rb").read).to include("expect(false).to eq(true)") + end + end + + context "--test parameter set to minitest" do + before do + reset! + in_app_root + 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 + + it "requires 'test-gem'" do + expect(bundled_app("test_gem/test/minitest_helper.rb").read).to include("require 'test_gem'") + end + + it "requires 'minitest_helper'" do + expect(bundled_app("test_gem/test/test_test_gem.rb").read).to include("require 'minitest_helper'") + end + + it "creates a default test which fails" do + expect(bundled_app("test_gem/test/test_test_gem.rb").read).to include("assert false") + end + end + + context "--test with no arguments" do + before do + reset! + in_app_root + bundle "gem #{gem_name} --test" + end + + it "defaults to rspec" do + expect(bundled_app("test_gem/spec/spec_helper.rb")).to exist + expect(bundled_app("test_gem/test/minitest_helper.rb")).to_not exist + end + + it "creates a .travis.yml file to test the library against the current Ruby version on Travis CI" do + expect(bundled_app("test_gem/.travis.yml").read).to match(%r(- #{RUBY_VERSION})) + end + end + + context "--edit option" do + it "opens the generated gemspec in the user's text editor" do + reset! + in_app_root + output = bundle "gem #{gem_name} --edit=echo" + gemspec_path = File.join(Dir.pwd, gem_name, "#{gem_name}.gemspec") + expect(output).to include("echo \"#{gemspec_path}\"") + end + end + end + + context "gem naming with dashed" do + let(:gem_name) { 'test-gem' } + + before do + bundle "gem #{gem_name}" + # reset gemspec cache for each test because of commit 3d4163a + Bundler.clear_gemspec_cache + end + + let(:generated_gem) { Bundler::GemHelper.new(bundled_app(gem_name).to_s) } + + 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 + 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"/) + end + + it "nests constants so they work" do + expect(bundled_app("test-gem/lib/test/gem/version.rb").read).to match(/module Test\n module Gem/) + expect(bundled_app("test-gem/lib/test/gem.rb").read).to match(/module Test\n module Gem/) + end + + it_should_behave_like "git config is present" + + context "git config user.{name,email} is not set" do + before do + `git config --global --unset user.name` + `git config --global --unset user.email` + reset! + in_app_root + bundle "gem #{gem_name}" + end + + 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") + end + + it "requires the version file" do + expect(bundled_app("test-gem/lib/test/gem.rb").read).to match(/require "test\/gem\/version"/) + end + + it "runs rake without problems" do + system_gems ["rake-10.0.2"] + + rakefile = strip_whitespace <<-RAKEFILE + task :default do + puts 'SUCCESS' + end + RAKEFILE + File.open(bundled_app("test-gem/Rakefile"), 'w') do |file| + file.puts rakefile + end + + Dir.chdir(bundled_app(gem_name)) do + sys_exec("rake") + expect(out).to include("SUCCESS") + end + end + + context "--bin parameter set" do + before do + reset! + in_app_root + bundle "gem #{gem_name} --bin" + end + + it "builds bin skeleton" do + expect(bundled_app("test-gem/bin/test-gem")).to exist + end + + it "requires 'test/gem'" do + expect(bundled_app("test-gem/bin/test-gem").read).to match(/require 'test\/gem'/) + end + end + + context "no --test parameter" do + before do + reset! + in_app_root + bundle "gem #{gem_name}" + end + + it "doesn't create any spec/test file" do + expect(bundled_app("test-gem/.rspec")).to_not exist + expect(bundled_app("test-gem/spec/test/gem_spec.rb")).to_not exist + expect(bundled_app("test-gem/spec/spec_helper.rb")).to_not exist + expect(bundled_app("test-gem/test/test_test/gem.rb")).to_not exist + expect(bundled_app("test-gem/test/minitest_helper.rb")).to_not exist + end + end + + context "--test parameter set to rspec" do + before do + reset! + in_app_root + bundle "gem #{gem_name} --test=rspec" + 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 + + it "requires 'test/gem'" do + expect(bundled_app("test-gem/spec/spec_helper.rb").read).to include("require 'test/gem'") + end + + it "creates a default test which fails" do + expect(bundled_app("test-gem/spec/test/gem_spec.rb").read).to include("expect(false).to eq(true)") + end + + it "creates a default rake task to run the specs" do + rakefile = strip_whitespace <<-RAKEFILE + require "bundler/gem_tasks" + require "rspec/core/rake_task" + + RSpec::Core::RakeTask.new(:spec) + + task :default => :spec + + RAKEFILE + + expect(bundled_app("test-gem/Rakefile").read).to eq(rakefile) + end + end + + context "--test parameter set to minitest" do + before do + reset! + in_app_root + 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 + + it "requires 'test/gem'" do + expect(bundled_app("test-gem/test/minitest_helper.rb").read).to match(/require 'test\/gem'/) + end + + it "requires 'minitest_helper'" do + expect(bundled_app("test-gem/test/test_test/gem.rb").read).to match(/require 'minitest_helper'/) + end + + it "creates a default test which fails" do + expect(bundled_app("test-gem/test/test_test/gem.rb").read).to match(/assert false/) + end + + it "creates a default rake task to run the test suite" do + rakefile = strip_whitespace <<-RAKEFILE + require "bundler/gem_tasks" + require "rake/testtask" + + Rake::TestTask.new(:test) do |t| + t.libs << "test" + end + + task :default => :test + + RAKEFILE + + expect(bundled_app("test-gem/Rakefile").read).to eq(rakefile) + end + end + + context "--test with no arguments" do + before do + reset! + in_app_root + bundle "gem #{gem_name} --test" + end + + it "defaults to rspec" do + expect(bundled_app("test-gem/spec/spec_helper.rb")).to exist + expect(bundled_app("test-gem/test/minitest_helper.rb")).to_not exist + end + end + + context "--ext parameter set" do + before do + reset! + in_app_root + bundle "gem test_gem --ext" + end + + it "builds ext skeleton" do + expect(bundled_app("test_gem/ext/test_gem/extconf.rb")).to exist + expect(bundled_app("test_gem/ext/test_gem/test_gem.h")).to exist + expect(bundled_app("test_gem/ext/test_gem/test_gem.c")).to exist + end + + it "includes rake-compiler" do + expect(bundled_app("test_gem/test_gem.gemspec").read).to include('spec.add_development_dependency "rake-compiler"') + end + end + end +end diff --git a/bundler-1.7.2/spec/commands/open_spec.rb b/bundler-1.7.2/spec/commands/open_spec.rb new file mode 100644 index 0000000..e3a66ec --- /dev/null +++ b/bundler-1.7.2/spec/commands/open_spec.rb @@ -0,0 +1,68 @@ +require "spec_helper" + +describe "bundle open" do + before :each do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + G + end + + it "opens the gem with BUNDLER_EDITOR as highest priority" do + bundle "open rails", :env => {"EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor"} + expect(out).to eq("bundler_editor #{default_bundle_path('gems', 'rails-2.3.2')}") + end + + it "opens the gem with VISUAL as 2nd highest priority" do + bundle "open rails", :env => {"EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => ""} + expect(out).to eq("visual #{default_bundle_path('gems', 'rails-2.3.2')}") + end + + it "opens the gem with EDITOR as 3rd highest priority" do + bundle "open rails", :env => {"EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => ""} + expect(out).to eq("editor #{default_bundle_path('gems', 'rails-2.3.2')}") + end + + it "complains if no EDITOR is set" do + bundle "open rails", :env => {"EDITOR" => "", "VISUAL" => "", "BUNDLER_EDITOR" => ""} + expect(out).to eq("To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR") + end + + it "complains if gem not in bundle" do + bundle "open missing", :env => {"EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => ""} + expect(out).to match(/could not find gem 'missing'/i) + end + + it "does not blow up if the gem to open does not have a Gemfile" do + git = build_git "foo" + ref = git.ref_for("master", 11) + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem 'foo', :git => "#{lib_path("foo-1.0")}" + G + + bundle "open foo", :env => {"EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => ""} + expect(out).to match("editor #{default_bundle_path.join("bundler/gems/foo-1.0-#{ref}")}") + end + + it "suggests alternatives for similar-sounding gems" do + bundle "open Rails", :env => {"EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => ""} + expect(out).to match(/did you mean rails\?/i) + end + + it "opens the gem with short words" do + bundle "open rec" , :env => {"EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor"} + + expect(out).to eq("bundler_editor #{default_bundle_path('gems', 'activerecord-2.3.2')}") + end + + it "select the gem from many match gems" do + env = {"EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor"} + bundle "open active" , :env => env do |input| + input.puts '2' + end + + expect(out).to match(/bundler_editor #{default_bundle_path('gems', 'activerecord-2.3.2')}\z/) + end +end diff --git a/bundler-1.7.2/spec/commands/outdated_spec.rb b/bundler-1.7.2/spec/commands/outdated_spec.rb new file mode 100644 index 0000000..da17a2e --- /dev/null +++ b/bundler-1.7.2/spec/commands/outdated_spec.rb @@ -0,0 +1,156 @@ +require "spec_helper" + +describe "bundle outdated" do + before :each do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "zebra", :git => "#{lib_path('zebra')}" + gem "foo", :git => "#{lib_path('foo')}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + G + end + + describe "with no arguments" do + it "returns a sorted list of outdated gems" do + update_repo2 do + build_gem "activesupport", "3.0" + build_gem "weakling", "0.2" + update_git "foo", :path => lib_path("foo") + update_git "zebra", :path => lib_path("zebra") + end + + bundle "outdated" + + expect(out).to include("activesupport (3.0 > 2.3.5) Gemfile specifies \"= 2.3.5\"") + expect(out).to include("weakling (0.2 > 0.0.3) Gemfile specifies \"~> 0.0.1\"") + expect(out).to include("foo (1.0") + + # Gem names are one per-line, between "*" and their parenthesized version. + gem_list = out.split("\n").map { |g| g[ /\* (.*) \(/, 1] }.compact + expect(gem_list).to eq(gem_list.sort) + end + + it "returns non zero exit status if outdated gems present" do + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end + + bundle "outdated", :exitstatus => true + + expect(exitstatus).to_not be_zero + end + + it "returns success exit status if no outdated gems present" do + bundle "outdated", :exitstatus => true + + expect(exitstatus).to be_zero + end + end + + describe "with --local option" do + it "doesn't hit repo2" do + FileUtils.rm_rf(gem_repo2) + + bundle "outdated --local" + expect(out).not_to match(/Fetching/) + end + end + + describe "with specified gems" do + it "returns list of outdated gems" do + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end + + bundle "outdated foo" + expect(out).not_to include("activesupport (3.0 > 2.3.5)") + expect(out).to include("foo (1.0") + end + end + + describe "pre-release gems" do + context "without the --pre option" do + it "ignores pre-release versions" do + update_repo2 do + build_gem "activesupport", "3.0.0.beta" + end + + bundle "outdated" + expect(out).not_to include("activesupport (3.0.0.beta > 2.3.5)") + end + end + + context "with the --pre option" do + it "includes pre-release versions" do + update_repo2 do + build_gem "activesupport", "3.0.0.beta" + end + + bundle "outdated --pre" + expect(out).to include("activesupport (3.0.0.beta > 2.3.5) Gemfile specifies \"= 2.3.5\"") + end + end + + context "when current gem is a pre-release" do + it "includes the gem" do + update_repo2 do + build_gem "activesupport", "3.0.0.beta.1" + build_gem "activesupport", "3.0.0.beta.2" + end + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport", "3.0.0.beta.1" + G + + bundle "outdated" + expect(out).to include("activesupport (3.0.0.beta.2 > 3.0.0.beta.1) Gemfile specifies \"= 3.0.0.beta.1\"") + end + end + end + + describe "with --strict option" do + it "only reports gems that have a newer version that matches the specified dependency version requirements" do + update_repo2 do + build_gem "activesupport", "3.0" + build_gem "weakling", "0.0.5" + end + + bundle "outdated --strict" + + expect(out).to_not include("activesupport (3.0 > 2.3.5) Gemfile specifies \"= 2.3.5\"") + expect(out).to include("weakling (0.0.5 > 0.0.3) Gemfile specifies \"~> 0.0.1\"") + end + + it "only reports gem dependencies when they can actually be updated" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack_middleware", "1.0" + G + + bundle "outdated --strict" + + expect(out).to_not include("rack (1.2 > 0.9.1)") + end + end + + describe "with invalid gem name" do + it "returns could not find gem name" do + bundle "outdated invalid_gem_name" + expect(out).to include("Could not find gem 'invalid_gem_name'.") + end + + it "returns non-zero exit code" do + bundle "outdated invalid_gem_name", :exitstatus => true + expect(exitstatus).to_not be_zero + end + end +end diff --git a/bundler-1.7.2/spec/commands/package_spec.rb b/bundler-1.7.2/spec/commands/package_spec.rb new file mode 100644 index 0000000..e433b92 --- /dev/null +++ b/bundler-1.7.2/spec/commands/package_spec.rb @@ -0,0 +1,114 @@ +require "spec_helper" + +describe "bundle package" do + context "with --gemfile" do + it "finds the gemfile" do + gemfile bundled_app("NotGemfile"), <<-G + source "file://#{gem_repo1}" + gem 'rack' + G + + bundle "package --gemfile=NotGemfile" + + ENV['BUNDLE_GEMFILE'] = "NotGemfile" + should_be_installed "rack 1.0.0" + end + end + + context "with --path" do + it "sets root directory for gems" do + gemfile <<-D + source "file://#{gem_repo1}" + gem 'rack' + D + + bundle "package --path=#{bundled_app('test')}" + + should_be_installed "rack 1.0.0" + expect(bundled_app("test/vendor/cache/")).to exist + end + end +end + +describe "bundle install with gem sources" do + describe "when cached and locked" do + it "does not hit the remote at all" do + build_repo2 + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack" + G + + bundle :pack + simulate_new_machine + FileUtils.rm_rf gem_repo2 + + bundle "install --local" + should_be_installed "rack 1.0.0" + end + + it "does not hit the remote at all" do + build_repo2 + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack" + G + + bundle :pack + simulate_new_machine + FileUtils.rm_rf gem_repo2 + + bundle "install --deployment" + should_be_installed "rack 1.0.0" + end + + it "does not reinstall already-installed gems" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + bundle :pack + + build_gem "rack", "1.0.0", :path => bundled_app('vendor/cache') do |s| + s.write "lib/rack.rb", "raise 'omg'" + end + + bundle :install + expect(err).to be_empty + should_be_installed "rack 1.0" + end + + it "ignores cached gems for the wrong platform" do + simulate_platform "java" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "platform_specific" + G + bundle :pack + end + + simulate_new_machine + + simulate_platform "ruby" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "platform_specific" + G + run "require 'platform_specific' ; puts PLATFORM_SPECIFIC" + expect(out).to eq("1.0.0 RUBY") + end + end + + it "does not update the cache if --no-cache is passed" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + bundled_app("vendor/cache").mkpath + expect(bundled_app("vendor/cache").children).to be_empty + + bundle "install --no-cache" + expect(bundled_app("vendor/cache").children).to be_empty + end + end +end diff --git a/bundler-1.7.2/spec/commands/show_spec.rb b/bundler-1.7.2/spec/commands/show_spec.rb new file mode 100644 index 0000000..01a2c2a --- /dev/null +++ b/bundler-1.7.2/spec/commands/show_spec.rb @@ -0,0 +1,125 @@ +require "spec_helper" + +describe "bundle show" do + context "with a standard Gemfile" do + before :each do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + G + end + + it "creates a Gemfile.lock if one did not exist" do + FileUtils.rm("Gemfile.lock") + + bundle "show" + + expect(bundled_app("Gemfile.lock")).to exist + end + + it "creates a Gemfile.lock when invoked with a gem name" do + FileUtils.rm("Gemfile.lock") + + bundle "show rails" + + expect(bundled_app("Gemfile.lock")).to exist + end + + it "prints path if gem exists in bundle" do + bundle "show rails" + expect(out).to eq(default_bundle_path('gems', 'rails-2.3.2').to_s) + end + + it "warns if path no longer exists on disk" do + FileUtils.rm_rf("#{system_gem_path}/gems/rails-2.3.2") + + bundle "show rails" + + expect(out).to match(/has been deleted/i) + expect(out).to include(default_bundle_path('gems', 'rails-2.3.2').to_s) + end + + it "prints the path to the running bundler" do + bundle "show bundler" + expect(out).to eq(File.expand_path('../../../', __FILE__)) + end + + it "complains if gem not in bundle" do + bundle "show missing" + expect(out).to match(/could not find gem 'missing'/i) + end + + it "prints path of all gems in bundle sorted by name" do + bundle "show --paths" + + expect(out).to include(default_bundle_path('gems', 'rake-10.0.2').to_s) + expect(out).to include(default_bundle_path('gems', 'rails-2.3.2').to_s) + + # Gem names are the last component of their path. + gem_list = out.split.map { |p| p.split('/').last } + expect(gem_list).to eq(gem_list.sort) + end + + 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.') + end + end + + context "with a git repo in the Gemfile" do + before :each do + @git = build_git "foo", "1.0" + end + + it "prints out git info" do + install_gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + should_be_installed "foo 1.0" + + bundle :show + expect(out).to include("foo (1.0 #{@git.ref_for('master', 6)}") + end + + it "prints out branch names other than master" do + update_git "foo", :branch => "omg" do |s| + s.write "lib/foo.rb", "FOO = '1.0.omg'" + end + @revision = revision_for(lib_path("foo-1.0"))[0...6] + + install_gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}", :branch => "omg" + G + should_be_installed "foo 1.0.omg" + + bundle :show + expect(out).to include("foo (1.0 #{@git.ref_for('omg', 6)}") + end + + it "doesn't print the branch when tied to a ref" do + sha = revision_for(lib_path("foo-1.0")) + install_gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}", :ref => "#{sha}" + G + + bundle :show + expect(out).to include("foo (1.0 #{sha[0..6]})") + end + end + + context "in a fresh gem in a blank git repo" do + before :each do + build_git "foo", :path => lib_path("foo") + in_app_root_custom lib_path("foo") + File.open('Gemfile', 'w') {|f| f.puts "gemspec" } + sys_exec 'rm -rf .git && git init' + end + + it "does not output git errors" do + bundle :show + expect(err).to be_empty + end + end +end diff --git a/bundler-1.7.2/spec/install/binstubs_spec.rb b/bundler-1.7.2/spec/install/binstubs_spec.rb new file mode 100644 index 0000000..9a76c52 --- /dev/null +++ b/bundler-1.7.2/spec/install/binstubs_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe "bundle install" do + + describe "when system_bindir is set" do + # On OS X, Gem.bindir defaults to /usr/bin, so system_bindir is useful if + # you want to avoid sudo installs for system gems with OS X's default ruby + it "overrides Gem.bindir" do + expect(Pathname.new("/usr/bin")).not_to be_writable unless Process::euid == 0 + gemfile <<-G + require 'rubygems' + def Gem.bindir; "/usr/bin"; end + source "file://#{gem_repo1}" + gem "rack" + G + + config "BUNDLE_SYSTEM_BINDIR" => system_gem_path('altbin').to_s + bundle :install + should_be_installed "rack 1.0.0" + expect(system_gem_path("altbin/rackup")).to exist + end + end + +end diff --git a/bundler-1.7.2/spec/install/bundler_spec.rb b/bundler-1.7.2/spec/install/bundler_spec.rb new file mode 100644 index 0000000..b85ddf8 --- /dev/null +++ b/bundler-1.7.2/spec/install/bundler_spec.rb @@ -0,0 +1,146 @@ +require 'spec_helper' + +describe "bundle install" do + + describe "with bundler dependencies" do + before(:each) do + build_repo2 do + build_gem "rails", "3.0" do |s| + s.add_dependency "bundler", ">= 0.9.0.pre" + end + build_gem "bundler", "0.9.1" + build_gem "bundler", Bundler::VERSION + end + end + + it "are forced to the current bundler version" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rails", "3.0" + G + + should_be_installed "bundler #{Bundler::VERSION}" + end + + it "are not added if not already present" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + should_not_be_installed "bundler #{Bundler::VERSION}" + end + + it "causes a conflict if explicitly requesting a different version" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rails", "3.0" + gem "bundler", "0.9.2" + G + + nice_error = <<-E.strip.gsub(/^ {8}/, '') + Fetching source index from file:#{gem_repo2}/ + Resolving dependencies... + Bundler could not find compatible versions for gem "bundler": + In Gemfile: + bundler (= 0.9.2) ruby + + Current Bundler version: + bundler (#{Bundler::VERSION}) + E + expect(out).to include(nice_error) + end + + it "works for gems with multiple versions in its dependencies" do + install_gemfile <<-G + source "file://#{gem_repo2}" + + gem "multiple_versioned_deps" + G + + + install_gemfile <<-G + source "file://#{gem_repo2}" + + gem "multiple_versioned_deps" + gem "rack" + G + + should_be_installed "multiple_versioned_deps 1.0.0" + end + + it "includes bundler in the bundle when it's a child dependency" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rails", "3.0" + G + + run "begin; gem 'bundler'; puts 'WIN'; rescue Gem::LoadError; puts 'FAIL'; end" + expect(out).to eq("WIN") + end + + it "allows gem 'bundler' when Bundler is not in the Gemfile or its dependencies" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack" + G + + run "begin; gem 'bundler'; puts 'WIN'; rescue Gem::LoadError => e; puts e.backtrace; end" + expect(out).to eq("WIN") + end + + it "causes a conflict if child dependencies conflict" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "activemerchant" + gem "rails_fail" + G + + nice_error = <<-E.strip.gsub(/^ {8}/, '') + Fetching source index from file:#{gem_repo2}/ + Resolving dependencies... + Bundler could not find compatible versions for gem "activesupport": + In Gemfile: + activemerchant (>= 0) ruby depends on + activesupport (>= 2.0.0) ruby + + rails_fail (>= 0) ruby depends on + activesupport (1.2.3) + E + expect(out).to eq(nice_error) + end + + it "causes a conflict if a child dependency conflicts with the Gemfile" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rails_fail" + gem "activesupport", "2.3.5" + G + + nice_error = <<-E.strip.gsub(/^ {8}/, '') + Fetching source index from file:#{gem_repo2}/ + Resolving dependencies... + Bundler could not find compatible versions for gem "activesupport": + In Gemfile: + rails_fail (>= 0) ruby depends on + activesupport (= 1.2.3) ruby + + activesupport (2.3.5) + E + expect(out).to eq(nice_error) + end + + it "can install dependencies with newer bundler version" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rails", "3.0" + G + + simulate_bundler_version "10.0.0" + #simulate_new_machine + + bundle "check" + expect(out).to eq("The Gemfile's dependencies are satisfied") + end + end + +end diff --git a/bundler-1.7.2/spec/install/deploy_spec.rb b/bundler-1.7.2/spec/install/deploy_spec.rb new file mode 100644 index 0000000..c3ba321 --- /dev/null +++ b/bundler-1.7.2/spec/install/deploy_spec.rb @@ -0,0 +1,237 @@ +require "spec_helper" + +describe "install with --deployment or --frozen" do + before do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + end + + it "fails without a lockfile and says that --deployment requires a lock" do + bundle "install --deployment" + expect(out).to include("The --deployment flag requires a Gemfile.lock") + end + + it "fails without a lockfile and says that --frozen requires a lock" do + bundle "install --frozen" + expect(out).to include("The --frozen flag requires a Gemfile.lock") + end + + it "works after you try to deploy without a lock" do + bundle "install --deployment" + bundle :install, :exitstatus => true + expect(exitstatus).to eq(0) + should_be_installed "rack 1.0" + end + + it "still works if you are not in the app directory and specify --gemfile" do + bundle "install" + Dir.chdir tmp + simulate_new_machine + bundle "install --gemfile #{tmp}/bundled_app/Gemfile --deployment" + Dir.chdir bundled_app + should_be_installed "rack 1.0" + end + + it "works if you exclude a group with a git gem" do + build_git "foo" + gemfile <<-G + group :test do + gem "foo", :git => "#{lib_path('foo-1.0')}" + end + G + bundle :install + bundle "install --deployment --without test", :exitstatus => true + expect(exitstatus).to eq(0) + 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) + end + + it "works when using path gems from the same path and the version is specified" do + build_lib "foo", :path => lib_path("nested/foo") + build_lib "bar", :path => lib_path("nested/bar") + gemfile <<-G + gem "foo", "1.0", :path => "#{lib_path("nested")}" + gem "bar", :path => "#{lib_path("nested")}" + G + + bundle :install + bundle "install --deployment", :exitstatus => true + + expect(exitstatus).to eq(0) + end + + it "works when there are credentials in the source URL" do + install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true) + source "http://user:pass@localgemserver.test/" + + gem "rack-obama", ">= 1.0" + G + + bundle "install --deployment", :exitstatus => true, :artifice => "endpoint_strict_basic_authentication" + + expect(exitstatus).to eq(0) + end + + describe "with an existing lockfile" do + before do + bundle "install" + end + + it "works with the --deployment flag if you didn't change anything" do + bundle "install --deployment", :exitstatus => true + expect(exitstatus).to eq(0) + end + + it "works with the --frozen flag if you didn't change anything" do + bundle "install --frozen", :exitstatus => true + expect(exitstatus).to eq(0) + end + + it "explodes with the --deployment flag if you make a change and don't check in the lockfile" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "rack-obama" + G + + bundle "install --deployment" + expect(out).to include("deployment mode") + expect(out).to include("You have added to the Gemfile") + expect(out).to include("* rack-obama") + expect(out).not_to include("You have deleted from the Gemfile") + expect(out).not_to include("You have changed in the Gemfile") + end + + it "can have --frozen set via an environment variable" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "rack-obama" + G + + ENV['BUNDLE_FROZEN'] = '1' + bundle "install" + expect(out).to include("deployment mode") + expect(out).to include("You have added to the Gemfile") + expect(out).to include("* rack-obama") + expect(out).not_to include("You have deleted from the Gemfile") + expect(out).not_to include("You have changed in the Gemfile") + end + + it "can have --frozen set to false via an environment variable" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "rack-obama" + G + + ENV['BUNDLE_FROZEN'] = "false" + bundle "install" + expect(out).not_to include("deployment mode") + expect(out).not_to include("You have added to the Gemfile") + expect(out).not_to include("* rack-obama") + end + + it "explodes with the --frozen flag if you make a change and don't check in the lockfile" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "rack-obama" + G + + bundle "install --frozen" + expect(out).to include("deployment mode") + expect(out).to include("You have added to the Gemfile") + expect(out).to include("* rack-obama") + expect(out).not_to include("You have deleted from the Gemfile") + expect(out).not_to include("You have changed in the Gemfile") + end + + it "explodes if you remove a gem and don't check in the lockfile" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "activesupport" + G + + bundle "install --deployment" + expect(out).to include("deployment mode") + expect(out).to include("You have added to the Gemfile:\n* activesupport\n\n") + expect(out).to include("You have deleted from the Gemfile:\n* rack") + expect(out).not_to include("You have changed in the Gemfile") + end + + it "explodes if you add a source" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "git://hubz.com" + G + + bundle "install --deployment" + expect(out).to include("deployment mode") + expect(out).to include("You have added to the Gemfile:\n* source: git://hubz.com (at master)") + expect(out).not_to include("You have changed in the Gemfile") + end + + it "explodes if you unpin a source" do + build_git "rack" + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path("rack-1.0")}" + G + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + bundle "install --deployment" + expect(out).to include("deployment mode") + expect(out).to include("You have deleted from the Gemfile:\n* source: #{lib_path("rack-1.0")} (at master)") + expect(out).not_to include("You have added to the Gemfile") + expect(out).not_to include("You have changed in the Gemfile") + end + + it "explodes if you unpin a source, leaving it pinned somewhere else" do + build_lib "foo", :path => lib_path("rack/foo") + build_git "rack", :path => lib_path("rack") + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path("rack")}" + gem "foo", :git => "#{lib_path("rack")}" + G + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "foo", :git => "#{lib_path("rack")}" + G + + bundle "install --deployment" + expect(out).to include("deployment mode") + expect(out).to include("You have changed in the Gemfile:\n* rack from `no specified source` to `#{lib_path("rack")} (at master)`") + expect(out).not_to include("You have added to the Gemfile") + expect(out).not_to include("You have deleted from the Gemfile") + end + + it "remembers that the bundle is frozen at runtime" do + bundle "install --deployment" + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "1.0.0" + gem "rack-obama" + G + + should_be_installed "rack 1.0.0" + end + end +end diff --git a/bundler-1.7.2/spec/install/gemfile/gemspec_spec.rb b/bundler-1.7.2/spec/install/gemfile/gemspec_spec.rb new file mode 100644 index 0000000..7746e45 --- /dev/null +++ b/bundler-1.7.2/spec/install/gemfile/gemspec_spec.rb @@ -0,0 +1,170 @@ +require "spec_helper" + +describe "bundle install from an existing gemspec" do + + before(:each) do + build_gem "bar", :to_system => true + build_gem "bar-dev", :to_system => true + end + + it "should install runtime and development dependencies" do + build_lib("foo", :path => tmp.join("foo")) do |s| + s.write("Gemfile", "source :rubygems\ngemspec") + s.add_dependency "bar", "=1.0.0" + s.add_development_dependency "bar-dev", '=1.0.0' + end + install_gemfile <<-G + source "file://#{gem_repo2}" + gemspec :path => '#{tmp.join("foo")}' + G + + should_be_installed "bar 1.0.0" + should_be_installed "bar-dev 1.0.0", :groups => :development + end + + it "that is hidden should install runtime and development dependencies" do + build_lib("foo", :path => tmp.join("foo")) do |s| + s.write("Gemfile", "source :rubygems\ngemspec") + s.add_dependency "bar", "=1.0.0" + s.add_development_dependency "bar-dev", '=1.0.0' + end + FileUtils.mv tmp.join('foo', 'foo.gemspec'), tmp.join('foo', '.gemspec') + + install_gemfile <<-G + source "file://#{gem_repo2}" + gemspec :path => '#{tmp.join("foo")}' + G + + should_be_installed "bar 1.0.0" + should_be_installed "bar-dev 1.0.0", :groups => :development + end + + it "should handle a list of requirements" do + build_gem "baz", "1.0", :to_system => true + build_gem "baz", "1.1", :to_system => true + + build_lib("foo", :path => tmp.join("foo")) do |s| + s.write("Gemfile", "source :rubygems\ngemspec") + s.add_dependency "baz", ">= 1.0", "< 1.1" + end + install_gemfile <<-G + source "file://#{gem_repo2}" + gemspec :path => '#{tmp.join("foo")}' + G + + should_be_installed "baz 1.0" + end + + it "should raise if there are no gemspecs available" do + build_lib("foo", :path => tmp.join("foo"), :gemspec => false) + + error = install_gemfile(<<-G, :expect_err => true) + source "file://#{gem_repo2}" + gemspec :path => '#{tmp.join("foo")}' + G + expect(error).to match(/There are no gemspecs at #{tmp.join('foo')}/) + end + + it "should raise if there are too many gemspecs available" do + build_lib("foo", :path => tmp.join("foo")) do |s| + s.write("foo2.gemspec", "") + end + + error = install_gemfile(<<-G, :expect_err => true) + source "file://#{gem_repo2}" + gemspec :path => '#{tmp.join("foo")}' + G + expect(error).to match(/There are multiple gemspecs at #{tmp.join('foo')}/) + end + + it "should pick a specific gemspec" do + build_lib("foo", :path => tmp.join("foo")) do |s| + s.write("foo2.gemspec", "") + s.add_dependency "bar", "=1.0.0" + s.add_development_dependency "bar-dev", '=1.0.0' + end + + install_gemfile(<<-G, :expect_err => true) + source "file://#{gem_repo2}" + gemspec :path => '#{tmp.join("foo")}', :name => 'foo' + G + + should_be_installed "bar 1.0.0" + should_be_installed "bar-dev 1.0.0", :groups => :development + end + + it "should use a specific group for development dependencies" do + build_lib("foo", :path => tmp.join("foo")) do |s| + s.write("foo2.gemspec", "") + s.add_dependency "bar", "=1.0.0" + s.add_development_dependency "bar-dev", '=1.0.0' + end + + install_gemfile(<<-G, :expect_err => true) + source "file://#{gem_repo2}" + gemspec :path => '#{tmp.join("foo")}', :name => 'foo', :development_group => :dev + G + + should_be_installed "bar 1.0.0" + should_not_be_installed "bar-dev 1.0.0", :groups => :development + should_be_installed "bar-dev 1.0.0", :groups => :dev + end + + it "should match a lockfile even if the gemspec defines development dependencies" do + build_lib("foo", :path => tmp.join("foo")) do |s| + s.write("Gemfile", "source 'file://#{gem_repo1}'\ngemspec") + s.add_dependency "actionpack", "=2.3.2" + s.add_development_dependency "rake", '=10.0.2' + end + + Dir.chdir(tmp.join("foo")) do + bundle "install" + # This should really be able to rely on $stderr, but, it's not written + # right, so we can't. In fact, this is a bug negation test, and so it'll + # ghost pass in future, and will only catch a regression if the message + # doesn't change. Exit codes should be used correctly (they can be more + # than just 0 and 1). + output = bundle("install --deployment") + expect(output).not_to match(/You have added to the Gemfile/) + expect(output).not_to match(/You have deleted from the Gemfile/) + expect(output).not_to match(/install in deployment mode after changing/) + end + end + + it "should evaluate the gemspec in its directory" do + build_lib("foo", :path => tmp.join("foo")) + File.open(tmp.join("foo/foo.gemspec"), "w") do |s| + s.write "raise 'ahh' unless Dir.pwd == '#{tmp.join("foo")}'" + end + + install_gemfile <<-G, :expect_err => true + gemspec :path => '#{tmp.join("foo")}' + G + expect(@err).not_to match(/ahh/) + end + + context "when child gemspecs conflict with a released gemspec" do + before do + # build the "parent" gem that depends on another gem in the same repo + build_lib "source_conflict", :path => bundled_app do |s| + s.add_dependency "rack_middleware" + end + + # build the "child" gem that is the same version as a released gem, but + # has completely different and conflicting dependency requirements + build_lib "rack_middleware", "1.0", :path => bundled_app("rack_middleware") do |s| + s.add_dependency "rack", "1.0" # anything other than 0.9.1 + end + end + + it "should install the child gemspec's deps" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gemspec + G + + should_be_installed "rack 1.0" + end + end + +end diff --git a/bundler-1.7.2/spec/install/gemfile/git_spec.rb b/bundler-1.7.2/spec/install/gemfile/git_spec.rb new file mode 100644 index 0000000..5d954c4 --- /dev/null +++ b/bundler-1.7.2/spec/install/gemfile/git_spec.rb @@ -0,0 +1,967 @@ +require "spec_helper" + +describe "bundle install with git sources" do + describe "when floating on master" do + before :each do + build_git "foo" do |s| + s.executables = "foobar" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + git "#{lib_path('foo-1.0')}" do + gem 'foo' + end + G + end + + it "fetches gems" do + should_be_installed("foo 1.0") + + run <<-RUBY + require 'foo' + puts "WIN" unless defined?(FOO_PREV_REF) + RUBY + + expect(out).to eq("WIN") + end + + it "caches the git repo" do + expect(Dir["#{default_bundle_path}/cache/bundler/git/foo-1.0-*"].size).to eq(1) + end + + it "caches the evaluated gemspec" do + git = update_git "foo" do |s| + s.executables = ["foobar"] # we added this the first time, so keep it now + s.files = ["bin/foobar"] # updating git nukes the files list + foospec = s.to_ruby.gsub(/s\.files.*/, 's.files = `git ls-files -z`.split("\x0")') + s.write "foo.gemspec", foospec + end + + bundle "update foo" + + sha = git.ref_for("master", 11) + spec_file = default_bundle_path.join("bundler/gems/foo-1.0-#{sha}/foo.gemspec").to_s + ruby_code = Gem::Specification.load(spec_file).to_ruby + file_code = File.read(spec_file) + expect(file_code).to eq(ruby_code) + end + + it "does not update the git source implicitly" do + update_git "foo" + + in_app_root2 do + install_gemfile bundled_app2("Gemfile"), <<-G + git "#{lib_path('foo-1.0')}" do + gem 'foo' + end + G + end + + in_app_root do + run <<-RUBY + require 'foo' + puts "fail" if defined?(FOO_PREV_REF) + RUBY + + expect(out).to be_empty + end + end + + it "sets up git gem executables on the path" do + pending_jruby_shebang_fix + bundle "exec foobar" + expect(out).to eq("1.0") + end + + it "complains if pinned specs don't exist in the git repo" do + build_git "foo" + + install_gemfile <<-G + gem "foo", "1.1", :git => "#{lib_path('foo-1.0')}" + G + + expect(out).to include("Source contains 'foo' at: 1.0") + end + + it "still works after moving the application directory" do + bundle "install --path vendor/bundle" + FileUtils.mv bundled_app, tmp('bundled_app.bck') + + Dir.chdir tmp('bundled_app.bck') + should_be_installed "foo 1.0" + end + + it "can still install after moving the application directory" do + bundle "install --path vendor/bundle" + FileUtils.mv bundled_app, tmp('bundled_app.bck') + + update_git "foo", "1.1", :path => lib_path("foo-1.0") + + Dir.chdir tmp('bundled_app.bck') + gemfile tmp('bundled_app.bck/Gemfile'), <<-G + source "file://#{gem_repo1}" + git "#{lib_path('foo-1.0')}" do + gem 'foo' + end + + gem "rack", "1.0" + G + + bundle "update foo" + + should_be_installed "foo 1.1", "rack 1.0" + end + + end + + describe "with an empty git block" do + before do + build_git "foo" + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + + git "#{lib_path("foo-1.0")}" do + # this page left intentionally blank + end + G + end + + it "does not explode" do + bundle "install" + should_be_installed "rack 1.0" + end + end + + describe "when specifying a revision" do + before(:each) do + build_git "foo" + @revision = revision_for(lib_path("foo-1.0")) + update_git "foo" + end + + it "works" do + install_gemfile <<-G + git "#{lib_path('foo-1.0')}", :ref => "#{@revision}" do + gem "foo" + end + G + + run <<-RUBY + require 'foo' + puts "WIN" unless defined?(FOO_PREV_REF) + RUBY + + expect(out).to eq("WIN") + end + + it "works when the revision is a symbol" do + install_gemfile <<-G + git "#{lib_path('foo-1.0')}", :ref => #{@revision.to_sym.inspect} do + gem "foo" + end + G + expect(err).to eq("") + + run <<-RUBY + require 'foo' + puts "WIN" unless defined?(FOO_PREV_REF) + RUBY + + expect(out).to eq("WIN") + end + end + + describe "when specifying local override" do + it "uses the local repository instead of checking a new one out" do + # We don't generate it because we actually don't need it + # build_git "rack", "0.8" + + build_git "rack", "0.8", :path => lib_path('local-rack') do |s| + s.write "lib/rack.rb", "puts :LOCAL" + end + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :branch => "master" + G + + bundle %|config local.rack #{lib_path('local-rack')}| + bundle :install + expect(out).to match(/at #{lib_path('local-rack')}/) + + run "require 'rack'" + expect(out).to eq("LOCAL") + end + + it "chooses the local repository on runtime" do + build_git "rack", "0.8" + + FileUtils.cp_r("#{lib_path('rack-0.8')}/.", lib_path('local-rack')) + + update_git "rack", "0.8", :path => lib_path('local-rack') do |s| + s.write "lib/rack.rb", "puts :LOCAL" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :branch => "master" + G + + bundle %|config local.rack #{lib_path('local-rack')}| + run "require 'rack'" + expect(out).to eq("LOCAL") + end + + it "updates specs on runtime" do + system_gems "nokogiri-1.4.2" + + build_git "rack", "0.8" + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :branch => "master" + G + + lockfile0 = File.read(bundled_app("Gemfile.lock")) + + FileUtils.cp_r("#{lib_path('rack-0.8')}/.", lib_path('local-rack')) + update_git "rack", "0.8", :path => lib_path('local-rack') do |s| + s.add_dependency "nokogiri", "1.4.2" + end + + bundle %|config local.rack #{lib_path('local-rack')}| + run "require 'rack'" + + lockfile1 = File.read(bundled_app("Gemfile.lock")) + expect(lockfile1).not_to eq(lockfile0) + end + + it "updates ref on install" do + build_git "rack", "0.8" + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :branch => "master" + G + + lockfile0 = File.read(bundled_app("Gemfile.lock")) + + FileUtils.cp_r("#{lib_path('rack-0.8')}/.", lib_path('local-rack')) + update_git "rack", "0.8", :path => lib_path('local-rack') + + bundle %|config local.rack #{lib_path('local-rack')}| + bundle :install + + lockfile1 = File.read(bundled_app("Gemfile.lock")) + expect(lockfile1).not_to eq(lockfile0) + end + + it "explodes if given path does not exist on install" do + build_git "rack", "0.8" + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :branch => "master" + G + + bundle %|config local.rack #{lib_path('local-rack')}| + bundle :install + expect(out).to match(/Cannot use local override for rack-0.8 because #{Regexp.escape(lib_path('local-rack').to_s)} does not exist/) + end + + it "explodes if branch is not given on install" do + build_git "rack", "0.8" + FileUtils.cp_r("#{lib_path('rack-0.8')}/.", lib_path('local-rack')) + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}" + G + + bundle %|config local.rack #{lib_path('local-rack')}| + bundle :install + expect(out).to match(/cannot use local override/i) + end + + it "does not explode if disable_local_branch_check is given" do + build_git "rack", "0.8" + FileUtils.cp_r("#{lib_path('rack-0.8')}/.", lib_path('local-rack')) + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}" + G + + 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!/) + end + + it "explodes on different branches on install" do + build_git "rack", "0.8" + + FileUtils.cp_r("#{lib_path('rack-0.8')}/.", lib_path('local-rack')) + + update_git "rack", "0.8", :path => lib_path('local-rack'), :branch => "another" do |s| + s.write "lib/rack.rb", "puts :LOCAL" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :branch => "master" + G + + bundle %|config local.rack #{lib_path('local-rack')}| + bundle :install + expect(out).to match(/is using branch another but Gemfile specifies master/) + end + + it "explodes on invalid revision on install" do + build_git "rack", "0.8" + + build_git "rack", "0.8", :path => lib_path('local-rack') do |s| + s.write "lib/rack.rb", "puts :LOCAL" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :branch => "master" + G + + bundle %|config local.rack #{lib_path('local-rack')}| + bundle :install + expect(out).to match(/The Gemfile lock is pointing to revision \w+/) + end + end + + describe "specified inline" do + # TODO: Figure out how to write this test so that it is not flaky depending + # on the current network situation. + # it "supports private git URLs" do + # gemfile <<-G + # gem "thingy", :git => "git@notthere.fallingsnow.net:somebody/thingy.git" + # G + # + # bundle :install, :expect_err => true + # + # # p out + # # p err + # puts err unless err.empty? # This spec fails randomly every so often + # err.should include("notthere.fallingsnow.net") + # err.should include("ssh") + # end + + it "installs from git even if a newer gem is available elsewhere" do + build_git "rack", "0.8" + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}" + G + + should_be_installed "rack 0.8" + end + + it "installs dependencies from git even if a newer gem is available elsewhere" do + system_gems "rack-1.0.0" + + build_lib "rack", "1.0", :path => lib_path('nested/bar') do |s| + s.write "lib/rack.rb", "puts 'WIN OVERRIDE'" + end + + build_git "foo", :path => lib_path('nested') do |s| + s.add_dependency "rack", "= 1.0" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "foo", :git => "#{lib_path('nested')}" + G + + run "require 'rack'" + expect(out).to eq('WIN OVERRIDE') + end + + it "correctly unlocks when changing to a git source" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "0.9.1" + G + + build_git "rack", :path => lib_path("rack") + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "1.0.0", :git => "#{lib_path('rack')}" + G + + should_be_installed "rack 1.0.0" + end + + it "correctly unlocks when changing to a git source without versions" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + build_git "rack", "1.2", :path => lib_path("rack") + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack')}" + G + + should_be_installed "rack 1.2" + end + end + + describe "block syntax" do + it "pulls all gems from a git block" do + build_lib "omg", :path => lib_path('hi2u/omg') + build_lib "hi2u", :path => lib_path('hi2u') + + install_gemfile <<-G + path "#{lib_path('hi2u')}" do + gem "omg" + gem "hi2u" + end + G + + should_be_installed "omg 1.0", "hi2u 1.0" + end + end + + it "uses a ref if specified" do + build_git "foo" + @revision = revision_for(lib_path("foo-1.0")) + update_git "foo" + + install_gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}", :ref => "#{@revision}" + G + + run <<-RUBY + require 'foo' + puts "WIN" unless defined?(FOO_PREV_REF) + RUBY + + expect(out).to eq("WIN") + end + + it "correctly handles cases with invalid gemspecs" do + build_git "foo" do |s| + s.summary = nil + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "foo", :git => "#{lib_path('foo-1.0')}" + gem "rails", "2.3.2" + G + + should_be_installed "foo 1.0" + should_be_installed "rails 2.3.2" + end + + it "runs the gemspec in the context of its parent directory" do + build_lib "bar", :path => lib_path("foo/bar"), :gemspec => false do |s| + s.write lib_path("foo/bar/lib/version.rb"), %{BAR_VERSION = '1.0'} + s.write "bar.gemspec", <<-G + $:.unshift Dir.pwd # For 1.9 + require 'lib/version' + Gem::Specification.new do |s| + s.name = 'bar' + s.version = BAR_VERSION + s.summary = 'Bar' + s.files = Dir["lib/**/*.rb"] + end + G + end + + build_git "foo", :path => lib_path("foo") do |s| + s.write "bin/foo", "" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "bar", :git => "#{lib_path("foo")}" + gem "rails", "2.3.2" + G + + should_be_installed "bar 1.0" + should_be_installed "rails 2.3.2" + end + + it "installs from git even if a rubygems gem is present" do + build_gem "foo", "1.0", :path => lib_path('fake_foo'), :to_system => true do |s| + s.write "lib/foo.rb", "raise 'FAIL'" + end + + build_git "foo", "1.0" + + install_gemfile <<-G + gem "foo", "1.0", :git => "#{lib_path('foo-1.0')}" + G + + should_be_installed "foo 1.0" + end + + it "fakes the gem out if there is no gemspec" do + build_git "foo", :gemspec => false + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "foo", "1.0", :git => "#{lib_path('foo-1.0')}" + gem "rails", "2.3.2" + G + + should_be_installed("foo 1.0") + should_be_installed("rails 2.3.2") + end + + it "catches git errors and spits out useful output" do + gemfile <<-G + gem "foo", "1.0", :git => "omgomg" + G + + bundle :install, :expect_err => true + + expect(out).to include("Git error:") + expect(err).to include("fatal") + expect(err).to include("omgomg") + end + + it "works when the gem path has spaces in it" do + build_git "foo", :path => lib_path('foo space-1.0') + + install_gemfile <<-G + gem "foo", :git => "#{lib_path('foo space-1.0')}" + G + + should_be_installed "foo 1.0" + end + + it "handles repos that have been force-pushed" do + build_git "forced", "1.0" + + install_gemfile <<-G + git "#{lib_path('forced-1.0')}" do + gem 'forced' + end + G + should_be_installed "forced 1.0" + + update_git "forced" do |s| + s.write "lib/forced.rb", "FORCED = '1.1'" + end + + bundle "update" + should_be_installed "forced 1.1" + + Dir.chdir(lib_path('forced-1.0')) do + `git reset --hard HEAD^` + end + + bundle "update" + should_be_installed "forced 1.0" + end + + it "ignores submodules if :submodule is not passed" do + build_git "submodule", "1.0" + build_git "has_submodule", "1.0" do |s| + s.add_dependency "submodule" + end + Dir.chdir(lib_path('has_submodule-1.0')) do + `git submodule add #{lib_path('submodule-1.0')} submodule-1.0` + `git commit -m "submodulator"` + end + + install_gemfile <<-G, :expect_err => true + git "#{lib_path('has_submodule-1.0')}" do + gem "has_submodule" + end + G + expect(out).to match(/could not find gem 'submodule/i) + + should_not_be_installed "has_submodule 1.0", :expect_err => true + end + + it "handles repos with submodules" do + build_git "submodule", "1.0" + build_git "has_submodule", "1.0" do |s| + s.add_dependency "submodule" + end + Dir.chdir(lib_path('has_submodule-1.0')) do + `git submodule add #{lib_path('submodule-1.0')} submodule-1.0` + `git commit -m "submodulator"` + end + + install_gemfile <<-G + git "#{lib_path('has_submodule-1.0')}", :submodules => true do + gem "has_submodule" + end + G + + should_be_installed "has_submodule 1.0" + end + + it "handles implicit updates when modifying the source info" do + git = build_git "foo" + + install_gemfile <<-G + git "#{lib_path('foo-1.0')}" do + gem "foo" + end + G + + update_git "foo" + update_git "foo" + + install_gemfile <<-G + git "#{lib_path('foo-1.0')}", :ref => "#{git.ref_for('HEAD^')}" do + gem "foo" + end + G + + run <<-RUBY + require 'foo' + puts "WIN" if FOO_PREV_REF == '#{git.ref_for("HEAD^^")}' + RUBY + + expect(out).to eq("WIN") + end + + it "does not to a remote fetch if the revision is cached locally" do + build_git "foo" + + install_gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + + FileUtils.rm_rf(lib_path('foo-1.0')) + + bundle "install" + expect(out).not_to match(/updating/i) + end + + it "doesn't blow up if bundle install is run twice in a row" do + build_git "foo" + + gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + + bundle "install" + bundle "install", :exitstatus => true + expect(exitstatus).to eq(0) + end + + it "does not duplicate git gem sources" do + build_lib "foo", :path => lib_path('nested/foo') + build_lib "bar", :path => lib_path('nested/bar') + + build_git "foo", :path => lib_path('nested') + build_git "bar", :path => lib_path('nested') + + gemfile <<-G + gem "foo", :git => "#{lib_path('nested')}" + gem "bar", :git => "#{lib_path('nested')}" + G + + bundle "install" + expect(File.read(bundled_app("Gemfile.lock")).scan('GIT').size).to eq(1) + end + + describe "switching sources" do + it "doesn't explode when switching Path to Git sources" do + build_gem "foo", "1.0", :to_system => true do |s| + s.write "lib/foo.rb", "raise 'fail'" + end + build_lib "foo", "1.0", :path => lib_path('bar/foo') + build_git "bar", "1.0", :path => lib_path('bar') do |s| + s.add_dependency 'foo' + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "bar", :path => "#{lib_path('bar')}" + G + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "bar", :git => "#{lib_path('bar')}" + G + + should_be_installed "foo 1.0", "bar 1.0" + end + + it "doesn't explode when switching Gem to Git source" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack-obama" + gem "rack", "1.0.0" + G + + build_git "rack", "1.0" do |s| + s.write "lib/new_file.rb", "puts 'USING GIT'" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack-obama" + gem "rack", "1.0.0", :git => "#{lib_path("rack-1.0")}" + G + + run "require 'new_file'" + expect(out).to eq("USING GIT") + end + end + + describe "bundle install after the remote has been updated" do + it "installs" do + build_git "valim" + + install_gemfile <<-G + gem "valim", :git => "file://#{lib_path("valim-1.0")}" + G + + old_revision = revision_for(lib_path("valim-1.0")) + update_git "valim" + new_revision = revision_for(lib_path("valim-1.0")) + + lockfile = File.read(bundled_app("Gemfile.lock")) + File.open(bundled_app("Gemfile.lock"), "w") do |file| + file.puts lockfile.gsub(/revision: #{old_revision}/, "revision: #{new_revision}") + end + + bundle "install" + + run <<-R + require "valim" + puts VALIM_PREV_REF + R + + expect(out).to eq(old_revision) + end + end + + describe "bundle install --deployment with git sources" do + it "works" do + build_git "valim", :path => lib_path('valim') + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "valim", "= 1.0", :git => "#{lib_path('valim')}" + G + + simulate_new_machine + + bundle "install --deployment", :exitstatus => true + expect(exitstatus).to eq(0) + end + end + + describe "gem install hooks" do + it "runs pre-install hooks" do + build_git "foo" + gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + + File.open(lib_path("install_hooks.rb"), "w") do |h| + h.write <<-H + require 'rubygems' + Gem.pre_install_hooks << lambda do |inst| + STDERR.puts "Ran pre-install hook: \#{inst.spec.full_name}" + end + H + end + + bundle :install, :expect_err => true, + :requires => [lib_path('install_hooks.rb')] + expect(err).to eq("Ran pre-install hook: foo-1.0") + end + + it "runs post-install hooks" do + build_git "foo" + gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + + File.open(lib_path("install_hooks.rb"), "w") do |h| + h.write <<-H + require 'rubygems' + Gem.post_install_hooks << lambda do |inst| + STDERR.puts "Ran post-install hook: \#{inst.spec.full_name}" + end + H + end + + bundle :install, :expect_err => true, + :requires => [lib_path('install_hooks.rb')] + expect(err).to eq("Ran post-install hook: foo-1.0") + end + + it "complains if the install hook fails" do + build_git "foo" + gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + + File.open(lib_path("install_hooks.rb"), "w") do |h| + h.write <<-H + require 'rubygems' + Gem.pre_install_hooks << lambda do |inst| + false + end + H + end + + bundle :install, :expect_err => true, + :requires => [lib_path('install_hooks.rb')] + expect(out).to include("failed for foo-1.0") + end + end + + context "with an extension" do + it "installs the extension" do + build_git "foo" do |s| + s.add_dependency "rake" + s.extensions << "Rakefile" + s.write "Rakefile", <<-RUBY + task :default do + path = File.expand_path("../lib", __FILE__) + FileUtils.mkdir_p(path) + File.open("\#{path}/foo.rb", "w") do |f| + f.puts "FOO = 'YES'" + end + end + RUBY + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + + run <<-R + require 'foo' + puts FOO + R + expect(out).to eq("YES") + end + + it "does not use old extension after ref changes" do + git_reader = build_git "foo", :no_default => true do |s| + s.extensions = ["ext/extconf.rb"] + s.write "ext/extconf.rb", <<-RUBY + require "mkmf" + create_makefile("foo") + RUBY + s.write "ext/foo.c", "void Init_foo() {}" + end + + 2.times do |i| + Dir.chdir(git_reader.path) do + File.open("ext/foo.c", "w") do |file| + file.write <<-C + #include "ruby.h" + VALUE foo() { return INT2FIX(#{i}); } + void Init_foo() { rb_define_global_function("foo", &foo, 0); } + C + end + `git commit -m 'commit for iteration #{i}' ext/foo.c` + end + git_sha = git_reader.ref_for("HEAD") + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "foo", :git => "#{lib_path('foo-1.0')}", :ref => "#{git_sha}" + G + + run <<-R + require 'foo' + puts foo + R + + expect(out).to eq(i.to_s) + end + end + + it "does not prompt to gem install if extension fails" do + build_git "foo" do |s| + s.add_dependency "rake" + s.extensions << "Rakefile" + s.write "Rakefile", <<-RUBY + task :default do + raise + end + RUBY + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + + expect(out).to include("An error occurred while installing foo (1.0)") + expect(out).not_to include("gem install foo") + end + end + + it "ignores git environment variables" do + build_git "xxxxxx" do |s| + s.executables = "xxxxxxbar" + end + + Bundler::SharedHelpers.with_clean_git_env do + ENV['GIT_DIR'] = 'bar' + ENV['GIT_WORK_TREE'] = 'bar' + + install_gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + git "#{lib_path('xxxxxx-1.0')}" do + gem 'xxxxxx' + end + G + + expect(exitstatus).to eq(0) + expect(ENV['GIT_DIR']).to eq('bar') + expect(ENV['GIT_WORK_TREE']).to eq('bar') + end + end + + describe "without git installed" do + it "prints a better error message" do + build_git "foo" + + install_gemfile <<-G + git "#{lib_path('foo-1.0')}" do + gem 'foo' + end + G + + bundle "update", :env => {"PATH" => ""} + expect(out).to include("You need to install git to be able to use gems from git repositories. For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git") + end + + it "installs a packaged git gem successfully" do + build_git "foo" + + install_gemfile <<-G + git "#{lib_path('foo-1.0')}" do + gem 'foo' + end + G + bundle "package --all" + simulate_new_machine + + bundle "install", :env => {"PATH" => ""}, :exitstatus => true + expect(out).to_not include("You need to install git to be able to use gems from git repositories.") + expect(exitstatus).to be_zero + end + end +end diff --git a/bundler-1.7.2/spec/install/gemfile/path_spec.rb b/bundler-1.7.2/spec/install/gemfile/path_spec.rb new file mode 100644 index 0000000..f36f383 --- /dev/null +++ b/bundler-1.7.2/spec/install/gemfile/path_spec.rb @@ -0,0 +1,480 @@ +require "spec_helper" + +describe "bundle install with explicit source paths" do + it "fetches gems" do + build_lib "foo" + + install_gemfile <<-G + path "#{lib_path('foo-1.0')}" + gem 'foo' + G + + should_be_installed("foo 1.0") + end + + it "supports pinned paths" do + build_lib "foo" + + install_gemfile <<-G + gem 'foo', :path => "#{lib_path('foo-1.0')}" + G + + should_be_installed("foo 1.0") + end + + it "supports relative paths" do + build_lib "foo" + + relative_path = lib_path('foo-1.0').relative_path_from(Pathname.new(Dir.pwd)) + + install_gemfile <<-G + gem 'foo', :path => "#{relative_path}" + G + + should_be_installed("foo 1.0") + end + + it "expands paths" do + build_lib "foo" + + relative_path = lib_path('foo-1.0').relative_path_from(Pathname.new('~').expand_path) + + install_gemfile <<-G + gem 'foo', :path => "~/#{relative_path}" + G + + should_be_installed("foo 1.0") + end + + it "expands paths raise error with not existing user's home dir" do + build_lib "foo" + username = 'some_unexisting_user' + relative_path = lib_path('foo-1.0').relative_path_from(Pathname.new("/home/#{username}").expand_path) + + install_gemfile <<-G + gem 'foo', :path => "~#{username}/#{relative_path}" + G + expect(out).to match("There was an error while trying to use the path `~#{username}/#{relative_path}`.") + expect(out).to match("user #{username} doesn't exist") + end + + it "expands paths relative to Bundler.root" do + build_lib "foo", :path => bundled_app("foo-1.0") + + install_gemfile <<-G + gem 'foo', :path => "./foo-1.0" + G + + bundled_app("subdir").mkpath + Dir.chdir(bundled_app("subdir")) do + should_be_installed("foo 1.0") + end + end + + it "expands paths when comparing locked paths to Gemfile paths" do + build_lib "foo", :path => bundled_app("foo-1.0") + + install_gemfile <<-G + gem 'foo', :path => File.expand_path("../foo-1.0", __FILE__) + G + + bundle "install --frozen", :exitstatus => true + expect(exitstatus).to eq(0) + end + + it "installs dependencies from the path even if a newer gem is available elsewhere" do + system_gems "rack-1.0.0" + + build_lib "rack", "1.0", :path => lib_path('nested/bar') do |s| + s.write "lib/rack.rb", "puts 'WIN OVERRIDE'" + end + + build_lib "foo", :path => lib_path('nested') do |s| + s.add_dependency "rack", "= 1.0" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "foo", :path => "#{lib_path('nested')}" + G + + run "require 'rack'" + expect(out).to eq('WIN OVERRIDE') + end + + it "works" do + build_gem "foo", "1.0.0", :to_system => true do |s| + s.write "lib/foo.rb", "puts 'FAIL'" + end + + build_lib "omg", "1.0", :path => lib_path("omg") do |s| + s.add_dependency "foo" + end + + build_lib "foo", "1.0.0", :path => lib_path("omg/foo") + + install_gemfile <<-G + gem "omg", :path => "#{lib_path('omg')}" + G + + should_be_installed "foo 1.0" + end + + it "supports gemspec syntax" do + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.add_dependency "rack", "1.0" + end + + gemfile = <<-G + source "file://#{gem_repo1}" + gemspec + G + + File.open(lib_path("foo/Gemfile"), "w") {|f| f.puts gemfile } + + Dir.chdir(lib_path("foo")) do + bundle "install" + should_be_installed "foo 1.0" + should_be_installed "rack 1.0" + end + end + + it "supports gemspec syntax with an alternative path" do + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.add_dependency "rack", "1.0" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gemspec :path => "#{lib_path("foo")}" + G + + should_be_installed "foo 1.0" + should_be_installed "rack 1.0" + end + + it "doesn't automatically unlock dependencies when using the gemspec syntax" do + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.add_dependency "rack", ">= 1.0" + end + + Dir.chdir lib_path("foo") + + install_gemfile lib_path("foo/Gemfile"), <<-G + source "file://#{gem_repo1}" + gemspec + G + + build_gem "rack", "1.0.1", :to_system => true + + bundle "install" + + should_be_installed "foo 1.0" + should_be_installed "rack 1.0" + end + + it "doesn't automatically unlock dependencies when using the gemspec syntax and the gem has development dependencies" do + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.add_dependency "rack", ">= 1.0" + s.add_development_dependency "activesupport" + end + + Dir.chdir lib_path("foo") + + install_gemfile lib_path("foo/Gemfile"), <<-G + source "file://#{gem_repo1}" + gemspec + G + + build_gem "rack", "1.0.1", :to_system => true + + bundle "install" + + should_be_installed "foo 1.0" + should_be_installed "rack 1.0" + end + + it "raises if there are multiple gemspecs" do + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.write "bar.gemspec" + end + + install_gemfile <<-G, :exitstatus => true + gemspec :path => "#{lib_path("foo")}" + G + + expect(exitstatus).to eq(15) + expect(out).to match(/There are multiple gemspecs/) + end + + it "allows :name to be specified to resolve ambiguity" do + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.write "bar.gemspec" + end + + install_gemfile <<-G, :exitstatus => true + gemspec :path => "#{lib_path("foo")}", :name => "foo" + G + + should_be_installed "foo 1.0" + end + + it "sets up executables" do + pending_jruby_shebang_fix + + build_lib "foo" do |s| + s.executables = "foobar" + end + + install_gemfile <<-G + path "#{lib_path('foo-1.0')}" + gem 'foo' + G + + bundle "exec foobar" + expect(out).to eq("1.0") + end + + it "handles directories in bin/" do + build_lib "foo" + lib_path("foo-1.0").join("foo.gemspec").rmtree + lib_path("foo-1.0").join("bin/performance").mkpath + + install_gemfile <<-G + gem 'foo', '1.0', :path => "#{lib_path('foo-1.0')}" + G + expect(err).to eq("") + end + + it "removes the .gem file after installing" do + build_lib "foo" + + install_gemfile <<-G + gem 'foo', :path => "#{lib_path('foo-1.0')}" + G + + expect(lib_path('foo-1.0').join('foo-1.0.gem')).not_to exist + end + + describe "block syntax" do + it "pulls all gems from a path block" do + build_lib "omg" + build_lib "hi2u" + + install_gemfile <<-G + path "#{lib_path}" do + gem "omg" + gem "hi2u" + end + G + + should_be_installed "omg 1.0", "hi2u 1.0" + end + end + + it "keeps source pinning" do + build_lib "foo", "1.0", :path => lib_path('foo') + build_lib "omg", "1.0", :path => lib_path('omg') + build_lib "foo", "1.0", :path => lib_path('omg/foo') do |s| + s.write "lib/foo.rb", "puts 'FAIL'" + end + + install_gemfile <<-G + gem "foo", :path => "#{lib_path('foo')}" + gem "omg", :path => "#{lib_path('omg')}" + G + + should_be_installed "foo 1.0" + end + + it "works when the path does not have a gemspec" do + build_lib "foo", :gemspec => false + + gemfile <<-G + gem "foo", "1.0", :path => "#{lib_path('foo-1.0')}" + G + + should_be_installed "foo 1.0" + + should_be_installed "foo 1.0" + end + + it "installs executable stubs" do + build_lib "foo" do |s| + s.executables = ['foo'] + end + + install_gemfile <<-G + gem "foo", :path => "#{lib_path('foo-1.0')}" + G + + bundle "exec foo" + expect(out).to eq("1.0") + end + + describe "when the gem version in the path is updated" do + before :each do + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.add_dependency "bar" + end + build_lib "bar", "1.0", :path => lib_path("foo/bar") + + install_gemfile <<-G + gem "foo", :path => "#{lib_path('foo')}" + G + end + + it "unlocks all gems when the top level gem is updated" do + build_lib "foo", "2.0", :path => lib_path("foo") do |s| + s.add_dependency "bar" + end + + bundle "install" + + should_be_installed "foo 2.0", "bar 1.0" + end + + it "unlocks all gems when a child dependency gem is updated" do + build_lib "bar", "2.0", :path => lib_path("foo/bar") + + bundle "install" + + should_be_installed "foo 1.0", "bar 2.0" + end + end + + describe "when dependencies in the path are updated" do + before :each do + build_lib "foo", "1.0", :path => lib_path("foo") + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "foo", :path => "#{lib_path('foo')}" + G + end + + it "gets dependencies that are updated in the path" do + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.add_dependency "rack" + end + + bundle "install" + + should_be_installed "rack 1.0.0" + end + end + + describe "switching sources" do + it "doesn't switch pinned git sources to rubygems when pinning the parent gem to a path source" do + build_gem "foo", "1.0", :to_system => true do |s| + s.write "lib/foo.rb", "raise 'fail'" + end + build_lib "foo", "1.0", :path => lib_path('bar/foo') + build_git "bar", "1.0", :path => lib_path('bar') do |s| + s.add_dependency 'foo' + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "bar", :git => "#{lib_path('bar')}" + G + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "bar", :path => "#{lib_path('bar')}" + G + + should_be_installed "foo 1.0", "bar 1.0" + end + + it "switches the source when the gem existed in rubygems and the path was already being used for another gem" do + build_lib "foo", "1.0", :path => lib_path("foo") + build_gem "bar", "1.0", :to_system => true do |s| + s.write "lib/bar.rb", "raise 'fail'" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "bar" + path "#{lib_path('foo')}" do + gem "foo" + end + G + + build_lib "bar", "1.0", :path => lib_path("foo/bar") + + install_gemfile <<-G + source "file://#{gem_repo1}" + path "#{lib_path('foo')}" do + gem "foo" + gem "bar" + end + G + + should_be_installed "bar 1.0" + end + end + + describe "gem install hooks" do + it "runs pre-install hooks" do + build_git "foo" + gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + + File.open(lib_path("install_hooks.rb"), "w") do |h| + h.write <<-H + require 'rubygems' + Gem.pre_install_hooks << lambda do |inst| + STDERR.puts "Ran pre-install hook: \#{inst.spec.full_name}" + end + H + end + + bundle :install, :expect_err => true, + :requires => [lib_path('install_hooks.rb')] + expect(err).to eq("Ran pre-install hook: foo-1.0") + end + + it "runs post-install hooks" do + build_git "foo" + gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + + File.open(lib_path("install_hooks.rb"), "w") do |h| + h.write <<-H + require 'rubygems' + Gem.post_install_hooks << lambda do |inst| + STDERR.puts "Ran post-install hook: \#{inst.spec.full_name}" + end + H + end + + bundle :install, :expect_err => true, + :requires => [lib_path('install_hooks.rb')] + expect(err).to eq("Ran post-install hook: foo-1.0") + end + + it "complains if the install hook fails" do + build_git "foo" + gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + + File.open(lib_path("install_hooks.rb"), "w") do |h| + h.write <<-H + require 'rubygems' + Gem.pre_install_hooks << lambda do |inst| + false + end + H + end + + bundle :install, :expect_err => true, + :requires => [lib_path('install_hooks.rb')] + expect(out).to include("failed for foo-1.0") + end + end + +end diff --git a/bundler-1.7.2/spec/install/gemfile_spec.rb b/bundler-1.7.2/spec/install/gemfile_spec.rb new file mode 100644 index 0000000..267a7f5 --- /dev/null +++ b/bundler-1.7.2/spec/install/gemfile_spec.rb @@ -0,0 +1,44 @@ +require "spec_helper" + +describe "bundle install" do + + context "with duplicated gems" do + it "will display a warning" do + install_gemfile <<-G + gem 'rails', '~> 4.0.0' + gem 'rails', '~> 4.0.0' + G + expect(out).to include("more than once") + end + end + + context "with --gemfile" do + it "finds the gemfile" do + gemfile bundled_app("NotGemfile"), <<-G + source "file://#{gem_repo1}" + gem 'rack' + G + + bundle :install, :gemfile => bundled_app("NotGemfile") + + ENV['BUNDLE_GEMFILE'] = "NotGemfile" + should_be_installed "rack 1.0.0" + end + end + + context "with deprecated features" do + before :each do + in_app_root + end + + it "reports that lib is an invalid option" do + gemfile <<-G + gem "rack", :lib => "rack" + G + + bundle :install + expect(out).to match(/You passed :lib as an option for gem 'rack', but it is invalid/) + end + end + +end diff --git a/bundler-1.7.2/spec/install/gems/c_ext_spec.rb b/bundler-1.7.2/spec/install/gems/c_ext_spec.rb new file mode 100644 index 0000000..6f9fe22 --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/c_ext_spec.rb @@ -0,0 +1,48 @@ +require "spec_helper" + +describe "installing a gem with C extensions" do + it "installs" do + build_repo2 do + build_gem "c_extension" do |s| + s.extensions = ["ext/extconf.rb"] + s.write "ext/extconf.rb", <<-E + require "mkmf" + name = "c_extension_bundle" + dir_config(name) + raise "OMG" unless with_config("c_extension") == "hello" + create_makefile(name) + E + + s.write "ext/c_extension.c", <<-C + #include "ruby.h" + + VALUE c_extension_true(VALUE self) { + return Qtrue; + } + + void Init_c_extension_bundle() { + VALUE c_Extension = rb_define_class("CExtension", rb_cObject); + rb_define_method(c_Extension, "its_true", c_extension_true, 0); + } + C + + s.write "lib/c_extension.rb", <<-C + require "c_extension_bundle" + C + end + end + + gemfile <<-G + source "file://#{gem_repo2}" + gem "c_extension" + G + + bundle "config build.c_extension --with-c_extension=hello" + bundle "install" + + expect(out).not_to include("extconf.rb failed") + + run "Bundler.require; puts CExtension.new.its_true" + expect(out).to eq("true") + end +end diff --git a/bundler-1.7.2/spec/install/gems/dependency_api_spec.rb b/bundler-1.7.2/spec/install/gems/dependency_api_spec.rb new file mode 100644 index 0000000..b3e5edf --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/dependency_api_spec.rb @@ -0,0 +1,580 @@ +require "spec_helper" + +describe "gemcutter's dependency API" do + let(:source_uri) { "http://localgemserver.test" } + + it "should use the API" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + + bundle :install, :artifice => "endpoint" + expect(out).to include("Fetching gem metadata from #{source_uri}") + should_be_installed "rack 1.0.0" + end + + it "should URI encode gem names" do + gemfile <<-G + source "#{source_uri}" + gem " sinatra" + G + + bundle :install, :artifice => "endpoint" + expect(out).to include("Could not find gem ' sinatra") + end + + it "should handle nested dependencies" do + gemfile <<-G + source "#{source_uri}" + gem "rails" + G + + bundle :install, :artifice => "endpoint" + expect(out).to include("Fetching gem metadata from #{source_uri}/...") + should_be_installed( + "rails 2.3.2", + "actionpack 2.3.2", + "activerecord 2.3.2", + "actionmailer 2.3.2", + "activeresource 2.3.2", + "activesupport 2.3.2") + end + + it "should handle multiple gem dependencies on the same gem" do + gemfile <<-G + source "#{source_uri}" + gem "net-sftp" + G + + bundle :install, :artifice => "endpoint" + should_be_installed "net-sftp 1.1.1" + end + + it "should use the endpoint when using --deployment" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + bundle :install, :artifice => "endpoint" + + bundle "install --deployment", :artifice => "endpoint" + expect(out).to include("Fetching gem metadata from #{source_uri}") + should_be_installed "rack 1.0.0" + end + + it "handles git dependencies that are in rubygems" do + build_git "foo" do |s| + s.executables = "foobar" + s.add_dependency "rails", "2.3.2" + end + + gemfile <<-G + source "#{source_uri}" + git "file:///#{lib_path('foo-1.0')}" do + gem 'foo' + end + G + + bundle :install, :artifice => "endpoint" + + should_be_installed("rails 2.3.2") + end + + it "handles git dependencies that are in rubygems using --deployment" do + build_git "foo" do |s| + s.executables = "foobar" + s.add_dependency "rails", "2.3.2" + end + + gemfile <<-G + source "#{source_uri}" + gem 'foo', :git => "file:///#{lib_path('foo-1.0')}" + G + + bundle :install, :artifice => "endpoint" + + bundle "install --deployment", :artifice => "endpoint" + + should_be_installed("rails 2.3.2") + end + + it "doesn't fail if you only have a git gem with no deps when using --deployment" do + build_git "foo" + gemfile <<-G + source "#{source_uri}" + gem 'foo', :git => "file:///#{lib_path('foo-1.0')}" + G + + bundle "install", :artifice => "endpoint" + bundle "install --deployment", :artifice => "endpoint", :exitstatus => true + + expect(exitstatus).to eq(0) + should_be_installed("foo 1.0") + end + + it "falls back when the API errors out" do + simulate_platform mswin + + gemfile <<-G + source "#{source_uri}" + gem "rcov" + G + + bundle :install, :fakeweb => "windows" + expect(out).to include("Fetching source index from #{source_uri}") + should_be_installed "rcov 1.0.0" + end + + it "falls back when hitting the Gemcutter Dependency Limit" do + gemfile <<-G + source "#{source_uri}" + gem "activesupport" + gem "actionpack" + gem "actionmailer" + gem "activeresource" + gem "thin" + gem "rack" + gem "rails" + G + bundle :install, :artifice => "endpoint_fallback" + expect(out).to include("Fetching source index from #{source_uri}") + + should_be_installed( + "activesupport 2.3.2", + "actionpack 2.3.2", + "actionmailer 2.3.2", + "activeresource 2.3.2", + "activesupport 2.3.2", + "thin 1.0.0", + "rack 1.0.0", + "rails 2.3.2") + end + + it "falls back when Gemcutter API doesn't return proper Marshal format" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + + bundle :install, :verbose => true, :artifice => "endpoint_marshal_fail" + expect(out).to include("could not fetch from the dependency API, trying the full index") + should_be_installed "rack 1.0.0" + end + + it "handles host redirects" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + + bundle :install, :artifice => "endpoint_host_redirect" + should_be_installed "rack 1.0.0" + end + + it "handles host redirects without Net::HTTP::Persistent" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + + FileUtils.mkdir_p lib_path + File.open(lib_path("disable_net_http_persistent.rb"), "w") do |h| + h.write <<-H + module Kernel + alias require_without_disabled_net_http require + def require(*args) + raise LoadError, 'simulated' if args.first == 'openssl' && !caller.grep(/vendored_persistent/).empty? + require_without_disabled_net_http(*args) + end + end + H + end + + bundle :install, :artifice => "endpoint_host_redirect", :requires => [lib_path("disable_net_http_persistent.rb")] + expect(out).to_not match(/Too many redirects/) + should_be_installed "rack 1.0.0" + end + + it "timeouts when Bundler::Fetcher redirects too much" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + + bundle :install, :artifice => "endpoint_redirect" + expect(out).to match(/Too many redirects/) + end + + context "when --full-index is specified" do + it "should use the modern index for install" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + + bundle "install --full-index", :artifice => "endpoint" + expect(out).to include("Fetching source index from #{source_uri}") + should_be_installed "rack 1.0.0" + end + + it "should use the modern index for update" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + + bundle "update --full-index", :artifice => "endpoint" + expect(out).to include("Fetching source index from #{source_uri}") + should_be_installed "rack 1.0.0" + end + end + + it "fetches again when more dependencies are found in subsequent sources" do + build_repo2 do + build_gem "back_deps" do |s| + s.add_dependency "foo" + end + FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")] + end + + gemfile <<-G + source "#{source_uri}" + source "#{source_uri}/extra" + gem "back_deps" + G + + bundle :install, :artifice => "endpoint_extra" + should_be_installed "back_deps 1.0" + end + + it "prints API output properly with back deps" do + build_repo2 do + build_gem "back_deps" do |s| + s.add_dependency "foo" + end + FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")] + end + + gemfile <<-G + source "#{source_uri}" + source "#{source_uri}/extra" + gem "back_deps" + G + + bundle :install, :artifice => "endpoint_extra" + + expect(out).to include("Fetching gem metadata from http://localgemserver.test/..") + expect(out).to include("Fetching source index from http://localgemserver.test/extra") + end + + it "does not fetch every specs if the index of gems is large when doing back deps" do + build_repo2 do + build_gem "back_deps" do |s| + s.add_dependency "foo" + end + build_gem "missing" + # need to hit the limit + 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i| + build_gem "gem#{i}" + end + + FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")] + end + + gemfile <<-G + source "#{source_uri}" + source "#{source_uri}/extra" + gem "back_deps" + G + + bundle :install, :artifice => "endpoint_extra_missing" + should_be_installed "back_deps 1.0" + end + + it "uses the endpoint if all sources support it" do + gemfile <<-G + source "#{source_uri}" + + gem 'foo' + G + + bundle :install, :artifice => "endpoint_api_missing" + should_be_installed "foo 1.0" + end + + it "fetches again when more dependencies are found in subsequent sources using --deployment" do + build_repo2 do + build_gem "back_deps" do |s| + s.add_dependency "foo" + end + FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")] + end + + gemfile <<-G + source "#{source_uri}" + source "#{source_uri}/extra" + gem "back_deps" + G + + bundle :install, :artifice => "endpoint_extra" + + bundle "install --deployment", :artifice => "endpoint_extra" + should_be_installed "back_deps 1.0" + end + + it "does not refetch if the only unmet dependency is bundler" do + gemfile <<-G + source "#{source_uri}" + + gem "bundler_dep" + G + + bundle :install, :artifice => "endpoint" + expect(out).to include("Fetching gem metadata from #{source_uri}") + end + + it "should install when EndpointSpecification has a bin dir owned by root", :sudo => true do + sudo "mkdir -p #{system_gem_path("bin")}" + sudo "chown -R root #{system_gem_path("bin")}" + + gemfile <<-G + source "#{source_uri}" + gem "rails" + G + bundle :install, :artifice => "endpoint" + should_be_installed "rails 2.3.2" + end + + it "installs the binstubs" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + + bundle "install --binstubs", :artifice => "endpoint" + + gembin "rackup" + expect(out).to eq("1.0.0") + end + + it "installs the bins when using --path and uses autoclean" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + + bundle "install --path vendor/bundle", :artifice => "endpoint" + + expect(vendored_gems("bin/rackup")).to exist + end + + it "installs the bins when using --path and uses bundle clean" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + + bundle "install --path vendor/bundle --no-clean", :artifice => "endpoint" + + expect(vendored_gems("bin/rackup")).to exist + end + + it "prints post_install_messages" do + gemfile <<-G + source "#{source_uri}" + gem 'rack-obama' + G + + bundle :install, :artifice => "endpoint" + expect(out).to include("Post-install message from rack:") + end + + it "should display the post install message for a dependency" do + gemfile <<-G + source "#{source_uri}" + gem 'rack_middleware' + G + + bundle :install, :artifice => "endpoint" + expect(out).to include("Post-install message from rack:") + expect(out).to include("Rack's post install message") + end + + context "when using basic authentication" do + let(:user) { "user" } + let(:password) { "pass" } + let(:basic_auth_source_uri) do + uri = URI.parse(source_uri) + uri.user = user + uri.password = password + + uri + end + + it "passes basic authentication details and strips out creds" do + gemfile <<-G + source "#{basic_auth_source_uri}" + gem "rack" + G + + bundle :install, :artifice => "endpoint_basic_authentication" + expect(out).not_to include("#{user}:#{password}") + should_be_installed "rack 1.0.0" + end + + it "strips http basic authentication creds for modern index" do + gemfile <<-G + source "#{basic_auth_source_uri}" + gem "rack" + G + + bundle :install, :artifice => "endopint_marshal_fail_basic_authentication" + expect(out).not_to include("#{user}:#{password}") + should_be_installed "rack 1.0.0" + end + + it "strips http basic auth creds when it can't reach the server" do + gemfile <<-G + source "#{basic_auth_source_uri}" + gem "rack" + G + + bundle :install, :artifice => "endpoint_500" + expect(out).not_to include("#{user}:#{password}") + end + + it "does not pass the user / password to different hosts on redirect" do + gemfile <<-G + source "#{basic_auth_source_uri}" + gem "rack" + G + + bundle :install, :artifice => "endpoint_creds_diff_host" + should_be_installed "rack 1.0.0" + end + + describe "with authentication details in bundle config" do + before do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + end + + it "reads authentication details from bundle config" do + # The trailing slash is necessary here; Fetcher canonicalizes the URI. + bundle "config #{source_uri}/ #{user}:#{password}" + + bundle :install, :artifice => "endpoint_strict_basic_authentication" + 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 :install, :artifice => "endpoint_strict_basic_authentication" + should_be_installed "rack 1.0.0" + end + + 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") + end + + it "fails if authentication has already been provided, but failed" do + bundle "config #{source_uri}/ #{user}:wrong" + + bundle :install, :artifice => "endpoint_strict_basic_authentication" + expect(out).to include("Bad username or password") + end + end + + describe "with no password" do + let(:password) { nil } + + it "passes basic authentication details" do + gemfile <<-G + source "#{basic_auth_source_uri}" + gem "rack" + G + + bundle :install, :artifice => "endpoint_basic_authentication" + should_be_installed "rack 1.0.0" + end + end + end + + context "when ruby is compiled without openssl" do + before do + # Install a monkeypatch that reproduces the effects of openssl being + # missing when the fetcher runs, as happens in real life. The reason + # we can't just overwrite openssl.rb is that Artifice uses it. + bundled_app("broken_ssl").mkpath + bundled_app("broken_ssl/openssl.rb").open("w") do |f| + f.write <<-RUBY + raise LoadError, "cannot load such file -- openssl" + RUBY + end + end + + it "explains what to do to get it" do + gemfile <<-G + source "#{source_uri.gsub(/http/, 'https')}" + gem "rack" + G + + bundle :install, :env => {"RUBYOPT" => "-I#{bundled_app("broken_ssl")}"} + expect(out).to include("OpenSSL") + end + end + + context "when SSL certificate verification fails" do + it "explains what happened" do + # Install a monkeypatch that reproduces the effects of openssl raising + # a certificate validation error when Rubygems tries to connect. + gemfile <<-G + class Net::HTTP + def start + raise OpenSSL::SSL::SSLError, "certificate verify failed" + end + end + + source "#{source_uri.gsub(/http/, 'https')}" + gem "rack" + G + + bundle :install + expect(out).to match(/could not verify the SSL certificate/i) + end + end + + context ".gemrc with sources is present" do + before do + File.open(home('.gemrc'), 'w') do |file| + file.puts({:sources => ["https://rubygems.org"]}.to_yaml) + end + end + + after do + home('.gemrc').rmtree + end + + it "uses other sources declared in the Gemfile" do + gemfile <<-G + source "#{source_uri}" + gem 'rack' + G + + bundle "install", :exitstatus => true, :artifice => "endpoint_marshal_fail" + + expect(exitstatus).to eq(0) + end + end + +end diff --git a/bundler-1.7.2/spec/install/gems/env_spec.rb b/bundler-1.7.2/spec/install/gems/env_spec.rb new file mode 100644 index 0000000..235a1ce --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/env_spec.rb @@ -0,0 +1,107 @@ +require "spec_helper" + +describe "bundle install with ENV conditionals" do + describe "when just setting an ENV key as a string" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + + env "BUNDLER_TEST" do + gem "rack" + end + G + end + + it "excludes the gems when the ENV variable is not set" do + bundle :install + should_not_be_installed "rack" + end + + it "includes the gems when the ENV variable is set" do + ENV['BUNDLER_TEST'] = '1' + bundle :install + should_be_installed "rack 1.0" + end + end + + describe "when just setting an ENV key as a symbol" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + + env :BUNDLER_TEST do + gem "rack" + end + G + end + + it "excludes the gems when the ENV variable is not set" do + bundle :install + should_not_be_installed "rack" + end + + it "includes the gems when the ENV variable is set" do + ENV['BUNDLER_TEST'] = '1' + bundle :install + should_be_installed "rack 1.0" + end + end + + describe "when setting a string to match the env" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + + env "BUNDLER_TEST" => "foo" do + gem "rack" + end + G + end + + it "excludes the gems when the ENV variable is not set" do + bundle :install + should_not_be_installed "rack" + end + + it "excludes the gems when the ENV variable is set but does not match the condition" do + ENV['BUNDLER_TEST'] = '1' + bundle :install + should_not_be_installed "rack" + end + + it "includes the gems when the ENV variable is set and matches the condition" do + ENV['BUNDLER_TEST'] = 'foo' + bundle :install + should_be_installed "rack 1.0" + end + end + + describe "when setting a regex to match the env" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + + env "BUNDLER_TEST" => /foo/ do + gem "rack" + end + G + end + + it "excludes the gems when the ENV variable is not set" do + bundle :install + should_not_be_installed "rack" + end + + it "excludes the gems when the ENV variable is set but does not match the condition" do + ENV['BUNDLER_TEST'] = 'fo' + bundle :install + should_not_be_installed "rack" + end + + it "includes the gems when the ENV variable is set and matches the condition" do + ENV['BUNDLER_TEST'] = 'foobar' + bundle :install + should_be_installed "rack 1.0" + end + end +end diff --git a/bundler-1.7.2/spec/install/gems/flex_spec.rb b/bundler-1.7.2/spec/install/gems/flex_spec.rb new file mode 100644 index 0000000..dbf9278 --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/flex_spec.rb @@ -0,0 +1,314 @@ +require "spec_helper" + +describe "bundle flex_install" do + it "installs the gems as expected" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem 'rack' + G + + should_be_installed "rack 1.0.0" + should_be_locked + end + + it "installs even when the lockfile is invalid" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem 'rack' + G + + should_be_installed "rack 1.0.0" + should_be_locked + + gemfile <<-G + source "file://#{gem_repo1}" + gem 'rack', '1.0' + G + + bundle :install + should_be_installed "rack 1.0.0" + should_be_locked + end + + it "keeps child dependencies at the same version" do + build_repo2 + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack-obama" + G + + should_be_installed "rack 1.0.0", "rack-obama 1.0.0" + + update_repo2 + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack-obama", "1.0" + G + + should_be_installed "rack 1.0.0", "rack-obama 1.0.0" + end + + describe "adding new gems" do + it "installs added gems without updating previously installed gems" do + build_repo2 + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem 'rack' + G + + update_repo2 + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem 'rack' + gem 'activesupport', '2.3.5' + G + + should_be_installed "rack 1.0.0", 'activesupport 2.3.5' + end + + it "keeps child dependencies pinned" do + build_repo2 + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack-obama" + G + + update_repo2 + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack-obama" + gem "thin" + G + + should_be_installed "rack 1.0.0", 'rack-obama 1.0', 'thin 1.0' + end + end + + describe "removing gems" do + it "removes gems without changing the versions of remaining gems" do + build_repo2 + install_gemfile <<-G + source "file://#{gem_repo2}" + gem 'rack' + gem 'activesupport', '2.3.5' + G + + update_repo2 + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem 'rack' + G + + should_be_installed "rack 1.0.0" + should_not_be_installed "activesupport 2.3.5" + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem 'rack' + gem 'activesupport', '2.3.2' + G + + should_be_installed "rack 1.0.0", 'activesupport 2.3.2' + end + + it "removes top level dependencies when removed from the Gemfile while leaving other dependencies intact" do + build_repo2 + install_gemfile <<-G + source "file://#{gem_repo2}" + gem 'rack' + gem 'activesupport', '2.3.5' + G + + update_repo2 + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem 'rack' + G + + should_not_be_installed "activesupport 2.3.5" + end + + it "removes child dependencies" do + build_repo2 + install_gemfile <<-G + source "file://#{gem_repo2}" + gem 'rack-obama' + gem 'activesupport' + G + + should_be_installed "rack 1.0.0", "rack-obama 1.0.0", "activesupport 2.3.5" + + update_repo2 + install_gemfile <<-G + source "file://#{gem_repo2}" + gem 'activesupport' + G + + should_be_installed 'activesupport 2.3.5' + should_not_be_installed "rack-obama", "rack" + end + end + + describe "when Gemfile conflicts with lockfile" do + before(:each) do + build_repo2 + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack_middleware" + G + + should_be_installed "rack_middleware 1.0", "rack 0.9.1" + + build_repo2 + update_repo2 do + build_gem "rack-obama", "2.0" do |s| + s.add_dependency "rack", "=1.2" + end + build_gem "rack_middleware", "2.0" do |s| + s.add_dependency "rack", ">=1.0" + end + end + + gemfile <<-G + source "file://#{gem_repo2}" + gem "rack-obama", "2.0" + gem "rack_middleware" + G + end + + it "does not install gems whose dependencies are not met" do + bundle :install + ruby <<-RUBY, :expect_err => true + require 'bundler/setup' + RUBY + expect(err).to match(/could not find gem 'rack-obama/i) + end + + it "suggests bundle update when the Gemfile requires different versions than the lock" do + nice_error = <<-E.strip.gsub(/^ {8}/, '') + Fetching source index from file:#{gem_repo2}/ + Resolving dependencies... + Bundler could not find compatible versions for gem "rack": + In snapshot (Gemfile.lock): + rack (0.9.1) + + In Gemfile: + rack-obama (= 2.0) ruby depends on + rack (= 1.2) ruby + + Running `bundle update` will rebuild your snapshot from scratch, using only + the gems in your Gemfile, which may resolve the conflict. + E + + bundle :install, :retry => 0 + expect(out).to eq(nice_error) + end + end + + describe "subtler cases" do + before :each do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "rack-obama" + G + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "0.9.1" + gem "rack-obama" + G + end + + it "does something" do + expect { + bundle "install" + }.not_to change { File.read(bundled_app('Gemfile.lock')) } + + expect(out).to include('rack = 0.9.1') + expect(out).to include('locked at 1.0.0') + expect(out).to include('bundle update rack') + end + + it "should work when you update" do + bundle "update rack" + end + end + + describe "when adding a new source" do + it "updates the lockfile" do + build_repo2 + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + install_gemfile <<-G + source "file://#{gem_repo1}" + source "file://#{gem_repo2}" + gem "rack" + G + + lockfile_should_be <<-L + GEM + remote: file:#{gem_repo1}/ + remote: file:#{gem_repo2}/ + specs: + rack (1.0.0) + + PLATFORMS + ruby + + DEPENDENCIES + rack + L + end + end + + # This was written to test github issue #636, but it passed. + # It's insanoly slow (3.36s) so I'm not going to run it + # describe "when a locked child dependency conflicts" do + # before(:each) do + # build_repo2 do + # build_gem "capybara", "0.3.9" do |s| + # s.add_dependency "rack", ">= 1.0.0" + # end + # + # build_gem "rack", "1.1.0" + # build_gem "rails", "3.0.0.rc4" do |s| + # s.add_dependency "rack", "~> 1.1.0" + # end + # + # build_gem "rack", "1.2.1" + # build_gem "rails", "3.0.0" do |s| + # s.add_dependency "rack", "~> 1.2.1" + # end + # end + # end + # + # it "prints the correct error message" do + # # install Rails 3.0.0.rc + # install_gemfile <<-G + # source "file://#{gem_repo2}" + # gem "rails", "3.0.0.rc4" + # gem "capybara", "0.3.9" + # G + # + # # upgrade Rails to 3.0.0 and then install again + # install_gemfile <<-G + # source "file://#{gem_repo2}" + # gem "rails", "3.0.0" + # gem "capybara", "0.3.9" + # G + # + # out.should match(/Gemfile.lock/) + # end + # end + +end diff --git a/bundler-1.7.2/spec/install/gems/groups_spec.rb b/bundler-1.7.2/spec/install/gems/groups_spec.rb new file mode 100644 index 0000000..afce362 --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/groups_spec.rb @@ -0,0 +1,308 @@ +require "spec_helper" + +describe "bundle install with groups" do + + describe "installing with no options" do + before :each do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + group :emo do + gem "activesupport", "2.3.5" + end + gem "thin", :groups => [:emo] + G + end + + it "installs gems in the default group" do + should_be_installed "rack 1.0.0" + end + + it "installs gems in a group block into that group" do + should_be_installed "activesupport 2.3.5" + + load_error_run <<-R, 'activesupport', :default + require 'activesupport' + puts ACTIVESUPPORT + R + + expect(err).to eq("ZOMG LOAD ERROR") + end + + it "installs gems with inline :groups into those groups" do + should_be_installed "thin 1.0" + + load_error_run <<-R, 'thin', :default + require 'thin' + puts THIN + R + + expect(err).to eq("ZOMG LOAD ERROR") + 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') + + out = run("require 'activesupport'; puts ACTIVESUPPORT") + expect(out).to eq('2.3.5') + + out = run("require 'thin'; puts THIN") + expect(out).to eq('1.0') + end + + it "removes old groups when new groups are set up" do + load_error_run <<-RUBY, 'thin', :emo + Bundler.setup(:default) + require 'thin' + puts THIN + RUBY + + expect(err).to eq("ZOMG LOAD ERROR") + end + + it "sets up old groups when they have previously been removed" do + out = run <<-RUBY, :emo + Bundler.setup(:default) + Bundler.setup(:default, :emo) + require 'thin'; puts THIN + RUBY + expect(out).to eq('1.0') + end + end + + describe "installing --without" do + describe "with gems assigned to a single group" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + group :emo do + gem "activesupport", "2.3.5" + end + G + end + + it "installs gems in the default group" do + bundle :install, :without => "emo" + should_be_installed "rack 1.0.0", :groups => [:default] + end + + it "does not install gems from the excluded group" do + bundle :install, :without => "emo" + should_not_be_installed "activesupport 2.3.5", :groups => [:default] + end + + it "does not install gems from the previously excluded group" do + bundle :install, :without => "emo" + should_not_be_installed "activesupport 2.3.5" + bundle :install + should_not_be_installed "activesupport 2.3.5" + end + + it "does not say it installed gems from the excluded group" do + bundle :install, :without => "emo" + expect(out).not_to include("activesupport") + end + + it "allows Bundler.setup for specific groups" do + bundle :install, :without => "emo" + run("require 'rack'; puts RACK", :default) + expect(out).to eq('1.0.0') + end + + it "does not effect the resolve" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "activesupport" + group :emo do + gem "rails", "2.3.2" + end + G + + bundle :install, :without => "emo" + should_be_installed "activesupport 2.3.2", :groups => [:default] + end + + it "still works on a different machine and excludes gems" do + bundle :install, :without => "emo" + + simulate_new_machine + bundle :install, :without => "emo" + + should_be_installed "rack 1.0.0", :groups => [:default] + should_not_be_installed "activesupport 2.3.5", :groups => [:default] + end + + it "still works when BUNDLE_WITHOUT is set" do + ENV["BUNDLE_WITHOUT"] = "emo" + + bundle :install + expect(out).not_to include("activesupport") + + should_be_installed "rack 1.0.0", :groups => [:default] + should_not_be_installed "activesupport 2.3.5", :groups => [:default] + + ENV["BUNDLE_WITHOUT"] = nil + end + + it "clears without when passed an empty list" do + bundle :install, :without => "emo" + + bundle 'install --without ""' + should_be_installed "activesupport 2.3.5" + end + + it "doesn't clear without when nothing is passed" do + bundle :install, :without => "emo" + + bundle :install + should_not_be_installed "activesupport 2.3.5" + end + end + + describe "with gems assigned to multiple groups" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + group :emo, :lolercoaster do + gem "activesupport", "2.3.5" + end + G + end + + it "installs gems in the default group" do + bundle :install, :without => "emo lolercoaster" + should_be_installed "rack 1.0.0" + end + + it "installs the gem if any of its groups are installed" do + bundle "install --without emo" + should_be_installed "rack 1.0.0", "activesupport 2.3.5" + end + + describe "with a gem defined multiple times in different groups" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + + group :emo do + gem "activesupport", "2.3.5" + end + + group :lolercoaster do + gem "activesupport", "2.3.5" + end + G + end + + it "installs the gem w/ option --without emo" do + bundle "install --without emo" + should_be_installed "activesupport 2.3.5" + end + + it "installs the gem w/ option --without lolercoaster" do + bundle "install --without lolercoaster" + should_be_installed "activesupport 2.3.5" + end + + it "does not install the gem w/ option --without emo lolercoaster" do + bundle "install --without emo lolercoaster" + should_not_be_installed "activesupport 2.3.5" + end + + it "does not install the gem w/ option --without 'emo lolercoaster'" do + bundle "install --without 'emo lolercoaster'" + should_not_be_installed "activesupport 2.3.5" + end + end + end + + describe "nesting groups" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + group :emo do + group :lolercoaster do + gem "activesupport", "2.3.5" + end + end + G + end + + it "installs gems in the default group" do + bundle :install, :without => "emo lolercoaster" + should_be_installed "rack 1.0.0" + end + + it "installs the gem if any of its groups are installed" do + bundle "install --without emo" + should_be_installed "rack 1.0.0", "activesupport 2.3.5" + end + + end + end + + describe "when loading only the default group" do + it "should not load all groups" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "activesupport", :groups => :development + G + + ruby <<-R + require "bundler" + Bundler.setup :default + Bundler.require :default + puts RACK + begin + require "activesupport" + rescue LoadError + puts "no activesupport" + end + R + + expect(out).to include("1.0") + expect(out).to include("no activesupport") + end + end + + + describe "when locked and installed with --without" do + before(:each) do + build_repo2 + system_gems "rack-0.9.1" do + install_gemfile <<-G, :without => :rack + source "file://#{gem_repo2}" + gem "rack" + + group :rack do + gem "rack_middleware" + end + G + end + end + + it "uses the correct versions even if --without was used on the original" do + should_be_installed "rack 0.9.1" + should_not_be_installed "rack_middleware 1.0" + simulate_new_machine + + bundle :install + + should_be_installed "rack 0.9.1" + should_be_installed "rack_middleware 1.0" + end + + it "does not hit the remote a second time" do + FileUtils.rm_rf gem_repo2 + bundle "install --without rack" + expect(err).to be_empty + end + end + +end diff --git a/bundler-1.7.2/spec/install/gems/mirror_spec.rb b/bundler-1.7.2/spec/install/gems/mirror_spec.rb new file mode 100644 index 0000000..48b97de --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/mirror_spec.rb @@ -0,0 +1,39 @@ +require "spec_helper" + +describe "bundle install with a mirror configured" do + describe "when the mirror does not match the gem source" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack" + G + bundle "config --local mirror.http://gems.example.org http://gem-mirror.example.org" + end + + it "installs from the normal location" do + bundle :install + expect(out).to include("Fetching source index from file:#{gem_repo1}") + should_be_installed "rack 1.0" + end + end + + describe "when the gem source matches a configured mirror" do + before :each do + gemfile <<-G + # This source is bogus and doesn't have the gem we're looking for + source "file://#{gem_repo2}" + + gem "rack" + G + bundle "config --local mirror.file://#{gem_repo2} file://#{gem_repo1}" + end + + it "installs the gem from the mirror" do + bundle :install + expect(out).to include("Fetching source index from file:#{gem_repo1}") + expect(out).not_to include("Fetching source index from file:#{gem_repo2}") + should_be_installed "rack 1.0" + end + end +end diff --git a/bundler-1.7.2/spec/install/gems/platform_spec.rb b/bundler-1.7.2/spec/install/gems/platform_spec.rb new file mode 100644 index 0000000..71603e1 --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/platform_spec.rb @@ -0,0 +1,195 @@ +require "spec_helper" + +describe "bundle install across platforms" do + it "maintains the same lockfile if all gems are compatible across platforms" do + lockfile <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (0.9.1) + + PLATFORMS + #{not_local} + + DEPENDENCIES + rack + G + + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack" + G + + should_be_installed "rack 0.9.1" + end + + it "pulls in the correct platform specific gem" do + lockfile <<-G + GEM + remote: file:#{gem_repo1} + specs: + platform_specific (1.0) + platform_specific (1.0-java) + platform_specific (1.0-x86-mswin32) + + PLATFORMS + ruby + + DEPENDENCIES + platform_specific + G + + simulate_platform "java" + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "platform_specific" + G + + should_be_installed "platform_specific 1.0 JAVA" + end + + it "works with gems that have different dependencies" do + simulate_platform "java" + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "nokogiri" + G + + should_be_installed "nokogiri 1.4.2 JAVA", "weakling 0.0.3" + + simulate_new_machine + + simulate_platform "ruby" + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "nokogiri" + G + + should_be_installed "nokogiri 1.4.2" + should_not_be_installed "weakling" + end + + it "works the other way with gems that have different dependencies" do + simulate_platform "ruby" + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "nokogiri" + G + + simulate_platform "java" + bundle "install" + + should_be_installed "nokogiri 1.4.2 JAVA", "weakling 0.0.3" + end + + it "fetches gems again after changing the version of Ruby" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack", "1.0.0" + G + + bundle "install --path vendor/bundle" + + new_version = Gem::ConfigMap[:ruby_version] == "1.8" ? "1.9.1" : "1.8" + FileUtils.mv(vendored_gems, bundled_app("vendor/bundle", Gem.ruby_engine, new_version)) + + bundle "install --path vendor/bundle" + expect(vendored_gems("gems/rack-1.0.0")).to exist + end +end + +describe "bundle install with platform conditionals" do + it "installs gems tagged w/ the current platforms" do + install_gemfile <<-G + source "file://#{gem_repo1}" + + platforms :#{local_tag} do + gem "nokogiri" + end + G + + should_be_installed "nokogiri 1.4.2" + end + + it "does not install gems tagged w/ another platforms" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + platforms :#{not_local_tag} do + gem "nokogiri" + end + G + + should_be_installed "rack 1.0" + should_not_be_installed "nokogiri 1.4.2" + end + + it "installs gems tagged w/ the current platforms inline" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "nokogiri", :platforms => :#{local_tag} + G + should_be_installed "nokogiri 1.4.2" + end + + it "does not install gems tagged w/ another platforms inline" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "nokogiri", :platforms => :#{not_local_tag} + G + should_be_installed "rack 1.0" + should_not_be_installed "nokogiri 1.4.2" + end + + it "installs gems tagged w/ the current platform inline" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "nokogiri", :platform => :#{local_tag} + G + should_be_installed "nokogiri 1.4.2" + end + + it "doesn't install gems tagged w/ another platform inline" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "nokogiri", :platform => :#{not_local_tag} + G + should_not_be_installed "nokogiri 1.4.2" + end + + it "does not blow up on sources with all platform-excluded specs" do + build_git "foo" + + install_gemfile <<-G + platform :#{not_local_tag} do + gem "foo", :git => "#{lib_path('foo-1.0')}" + end + G + + bundle :show, :exitstatus => true + expect(exitstatus).to eq(0) + end + +end + +describe "when a gem has no architecture" do + it "still installs correctly" do + simulate_platform mswin + + gemfile <<-G + # Try to install gem with nil arch + source "http://localgemserver.test/" + gem "rcov" + G + + bundle :install, :fakeweb => "windows" + should_be_installed "rcov 1.0.0" + end +end diff --git a/bundler-1.7.2/spec/install/gems/post_install_spec.rb b/bundler-1.7.2/spec/install/gems/post_install_spec.rb new file mode 100644 index 0000000..69841fe --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/post_install_spec.rb @@ -0,0 +1,121 @@ +require 'spec_helper' + +describe "bundle install with gem sources" do + describe "when gems include post install messages" do + it "should display the post-install messages after installing" do + gemfile <<-G + source "file://#{gem_repo1}" + gem 'rack' + gem 'thin' + gem 'rack-obama' + G + + bundle :install + expect(out).to include("Post-install message from rack:") + expect(out).to include("Rack's post install message") + expect(out).to include("Post-install message from thin:") + expect(out).to include("Thin's post install message") + expect(out).to include("Post-install message from rack-obama:") + expect(out).to include("Rack-obama's post install message") + end + end + + describe "when gems do not include post install messages" do + it "should not display any post-install messages" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "activesupport" + G + + bundle :install + expect(out).not_to include("Post-install message") + end + end + + describe "when a dependecy includes a post install message" do + it "should display the post install message" do + gemfile <<-G + source "file://#{gem_repo1}" + gem 'rack_middleware' + G + + bundle :install + expect(out).to include("Post-install message from rack:") + expect(out).to include("Rack's post install message") + end + end +end + +describe "bundle install with git sources" do + describe "when gems include post install messages" do + it "should display the post-install messages after installing" do + build_git "foo" do |s| + s.post_install_message = "Foo's post install message" + end + gemfile <<-G + source "file://#{gem_repo1}" + gem 'foo', :git => '#{lib_path("foo-1.0")}' + G + + bundle :install + expect(out).to include("Post-install message from foo:") + expect(out).to include("Foo's post install message") + end + + it "should display the post-install messages if repo is updated" do + build_git "foo" do |s| + s.post_install_message = "Foo's post install message" + end + gemfile <<-G + source "file://#{gem_repo1}" + gem 'foo', :git => '#{lib_path("foo-1.0")}' + G + bundle :install + + build_git "foo", "1.1" do |s| + s.post_install_message = "Foo's 1.1 post install message" + end + gemfile <<-G + source "file://#{gem_repo1}" + gem 'foo', :git => '#{lib_path("foo-1.1")}' + G + bundle :install + + expect(out).to include("Post-install message from foo:") + expect(out).to include("Foo's 1.1 post install message") + end + + it "should not display the post-install messages if repo is not updated" do + build_git "foo" do |s| + s.post_install_message = "Foo's post install message" + end + gemfile <<-G + source "file://#{gem_repo1}" + gem 'foo', :git => '#{lib_path("foo-1.0")}' + G + + bundle :install + expect(out).to include("Post-install message from foo:") + expect(out).to include("Foo's post install message") + + bundle :install + expect(out).not_to include("Post-install message") + end + end + + describe "when gems do not include post install messages" do + it "should not display any post-install messages" do + build_git "foo" do |s| + s.post_install_message = nil + end + gemfile <<-G + source "file://#{gem_repo1}" + gem 'foo', :git => '#{lib_path("foo-1.0")}' + G + + bundle :install + expect(out).not_to include("Post-install message") + end + end + +end diff --git a/bundler-1.7.2/spec/install/gems/resolving_spec.rb b/bundler-1.7.2/spec/install/gems/resolving_spec.rb new file mode 100644 index 0000000..6e07073 --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/resolving_spec.rb @@ -0,0 +1,124 @@ +require "spec_helper" + +describe "bundle install with gem sources" do + describe "install time dependencies" do + it "installs gems with implicit rake dependencies" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "with_implicit_rake_dep" + gem "another_implicit_rake_dep" + gem "rake" + G + + run <<-R + require 'implicit_rake_dep' + require 'another_implicit_rake_dep' + puts IMPLICIT_RAKE_DEP + puts ANOTHER_IMPLICIT_RAKE_DEP + R + expect(out).to eq("YES\nYES") + end + + it "installs gems with a dependency with no type" do + build_repo2 + + path = "#{gem_repo2}/#{Gem::MARSHAL_SPEC_DIR}/actionpack-2.3.2.gemspec.rz" + spec = Marshal.load(Gem.inflate(File.read(path))) + spec.dependencies.each do |d| + d.instance_variable_set(:@type, :fail) + end + File.open(path, 'w') do |f| + f.write Gem.deflate(Marshal.dump(spec)) + end + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "actionpack", "2.3.2" + G + + should_be_installed "actionpack 2.3.2", "activesupport 2.3.2" + end + + describe "with crazy rubygem plugin stuff" do + it "installs plugins" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "net_b" + G + + should_be_installed "net_b 1.0" + end + + it "installs plugins depended on by other plugins" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "net_a" + G + + should_be_installed "net_a 1.0", "net_b 1.0" + end + + it "installs multiple levels of dependencies" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "net_c" + gem "net_e" + G + + should_be_installed "net_a 1.0", "net_b 1.0", "net_c 1.0", "net_d 1.0", "net_e 1.0" + end + + context "with ENV['DEBUG_RESOLVER'] set" do + it "produces debug output" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "net_c" + gem "net_e" + G + + resolve_output = capture(:stdout) do + bundle :install, :env => {"DEBUG_RESOLVER" => "1"} + end + + expect(resolve_output).to include("==== Iterating ====") + end + end + + context "with ENV['DEBUG_RESOLVER_TREE'] set" do + it "produces debug output" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "net_c" + gem "net_e" + G + + resolve_output = capture(:stdout) do + bundle :install, :env => {"DEBUG_RESOLVER_TREE" => "1"} + end + + expect(resolve_output).to include(" net_b (>= 0) ruby") + end + end + + end + + describe "when some gems require a different version of ruby" do + it "does not try to install those gems" do + pending "waiting for a rubygems index that includes ruby version" + + update_repo gem_repo1 do + build_gem "require_ruby" do |s| + s.required_ruby_version = "> 9000" + end + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem 'require_ruby' + G + + expect(out).to_not include("Gem::InstallError: require_ruby requires Ruby version > 9000") + end + end + end +end diff --git a/bundler-1.7.2/spec/install/gems/simple_case_spec.rb b/bundler-1.7.2/spec/install/gems/simple_case_spec.rb new file mode 100644 index 0000000..7fbd9e0 --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/simple_case_spec.rb @@ -0,0 +1,386 @@ +require "spec_helper" + +describe "bundle install with gem sources" do + describe "the simple case" do + it "prints output and returns if no dependencies are specified" do + gemfile <<-G + source "file://#{gem_repo1}" + G + + bundle :install + expect(out).to match(/no dependencies/) + end + + it "does not make a lockfile if the install fails" do + install_gemfile <<-G, :expect_err => true + raise StandardError, "FAIL" + G + + expect(err).to match(/FAIL \(StandardError\)/) + expect(bundled_app("Gemfile.lock")).not_to exist + end + + it "creates a Gemfile.lock" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + expect(bundled_app('Gemfile.lock')).to exist + end + + it "creates lock files based on the Gemfile name" do + gemfile bundled_app('OmgFile'), <<-G + source "file://#{gem_repo1}" + gem "rack", "1.0" + G + + bundle 'install --gemfile OmgFile' + + expect(bundled_app("OmgFile.lock")).to exist + end + + it "doesn't delete the lockfile if one already exists" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem 'rack' + G + + lockfile = File.read(bundled_app("Gemfile.lock")) + + install_gemfile <<-G, :expect_err => true + raise StandardError, "FAIL" + G + + expect(File.read(bundled_app("Gemfile.lock"))).to eq(lockfile) + end + + it "does not touch the lockfile if nothing changed" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + expect { run '1' }.not_to change { File.mtime(bundled_app('Gemfile.lock')) } + end + + it "fetches gems" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem 'rack' + G + + expect(default_bundle_path("gems/rack-1.0.0")).to exist + should_be_installed("rack 1.0.0") + end + + it "fetches gems when multiple versions are specified" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem 'rack', "> 0.9", "< 1.0" + G + + expect(default_bundle_path("gems/rack-0.9.1")).to exist + should_be_installed("rack 0.9.1") + end + + it "fetches gems when multiple versions are specified take 2" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem 'rack', "< 1.0", "> 0.9" + G + + expect(default_bundle_path("gems/rack-0.9.1")).to exist + should_be_installed("rack 0.9.1") + end + + it "raises an appropriate error when gems are specified using symbols" do + status = install_gemfile(<<-G, :exitstatus => true) + source "file://#{gem_repo1}" + gem :rack + G + expect(status).to eq(4) + end + + it "pulls in dependencies" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + G + + should_be_installed "actionpack 2.3.2", "rails 2.3.2" + end + + it "does the right version" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "0.9.1" + G + + should_be_installed "rack 0.9.1" + end + + it "does not install the development dependency" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "with_development_dependency" + G + + should_be_installed "with_development_dependency 1.0.0" + should_not_be_installed "activesupport 2.3.5" + end + + it "resolves correctly" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "activemerchant" + gem "rails" + G + + should_be_installed "activemerchant 1.0", "activesupport 2.3.2", "actionpack 2.3.2" + end + + it "activates gem correctly according to the resolved gems" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "activesupport", "2.3.5" + G + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "activemerchant" + gem "rails" + G + + should_be_installed "activemerchant 1.0", "activesupport 2.3.2", "actionpack 2.3.2" + end + + it "does not reinstall any gem that is already available locally" do + system_gems "activesupport-2.3.2" + + build_repo2 do + build_gem "activesupport", "2.3.2" do |s| + s.write "lib/activesupport.rb", "ACTIVESUPPORT = 'fail'" + end + end + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "activerecord", "2.3.2" + G + + should_be_installed "activesupport 2.3.2" + end + + it "works when the gemfile specifies gems that only exist in the system" do + build_gem "foo", :to_system => true + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "foo" + G + + should_be_installed "rack 1.0.0", "foo 1.0.0" + end + + it "prioritizes local gems over remote gems" do + build_gem 'rack', '1.0.0', :to_system => true do |s| + s.add_dependency "activesupport", "2.3.5" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + should_be_installed "rack 1.0.0", "activesupport 2.3.5" + end + + describe "with a gem that installs multiple platforms" do + it "installs gems for the local platform as first choice" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "platform_specific" + G + + run "require 'platform_specific' ; puts PLATFORM_SPECIFIC" + expect(out).to eq("1.0.0 #{Gem::Platform.local}") + end + + it "falls back on plain ruby" do + simulate_platform "foo-bar-baz" + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "platform_specific" + G + + run "require 'platform_specific' ; puts PLATFORM_SPECIFIC" + expect(out).to eq("1.0.0 RUBY") + end + + it "installs gems for java" do + simulate_platform "java" + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "platform_specific" + G + + run "require 'platform_specific' ; puts PLATFORM_SPECIFIC" + expect(out).to eq("1.0.0 JAVA") + end + + it "installs gems for windows" do + simulate_platform mswin + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "platform_specific" + G + + run "require 'platform_specific' ; puts PLATFORM_SPECIFIC" + expect(out).to eq("1.0.0 MSWIN") + end + end + + describe "doing bundle install foo" do + before do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + end + + it "works" do + bundle "install --path vendor" + should_be_installed "rack 1.0" + end + + it "allows running bundle install --system without deleting foo" do + bundle "install --path vendor" + bundle "install --system" + FileUtils.rm_rf(bundled_app("vendor")) + should_be_installed "rack 1.0" + end + + it "allows running bundle install --system after deleting foo" do + bundle "install --path vendor" + FileUtils.rm_rf(bundled_app("vendor")) + bundle "install --system" + should_be_installed "rack 1.0" + end + end + + it "finds gems in multiple sources" do + build_repo2 + update_repo2 + + install_gemfile <<-G + source "file://#{gem_repo1}" + source "file://#{gem_repo2}" + + gem "activesupport", "1.2.3" + gem "rack", "1.2" + G + + should_be_installed "rack 1.2", "activesupport 1.2.3" + end + + it "gives a useful error if no sources are set" do + install_gemfile <<-G + gem "rack" + G + + bundle :install, :expect_err => true + expect(out).to match(/Your Gemfile has no gem server sources/i) + end + + it "creates a Gemfile.lock on a blank Gemfile" do + install_gemfile <<-G + G + + expect(File.exist?(bundled_app("Gemfile.lock"))).to eq(true) + end + + it "gracefully handles error when rubygems server is unavailable" do + install_gemfile <<-G + source "file://#{gem_repo1}" + source "http://localhost:9384" + + gem 'foo' + G + + bundle :install + expect(out).to include("Could not fetch specs from http://localhost:9384/") + expect(out).not_to include("file://") + end + + it "doesn't blow up when the local .bundle/config is empty" do + FileUtils.mkdir_p(bundled_app(".bundle")) + FileUtils.touch(bundled_app(".bundle/config")) + + install_gemfile(<<-G, :exitstatus => true) + source "file://#{gem_repo1}" + + gem 'foo' + G + expect(exitstatus).to eq(0) + 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) + source "file://#{gem_repo1}" + + gem 'foo' + G + expect(exitstatus).to eq(0) + end + end + + describe "when Bundler root contains regex chars" do + before do + root_dir = tmp("foo[]bar") + + FileUtils.mkdir_p(root_dir) + in_app_root_custom(root_dir) + end + + it "doesn't blow up" do + build_lib "foo" + gemfile = <<-G + gem 'foo', :path => "#{lib_path('foo-1.0')}" + G + File.open('Gemfile', 'w') do |file| + file.puts gemfile + end + + bundle :install, :exitstatus => true + + expect(exitstatus).to eq(0) + end + end + + describe "when requesting a quiet install via --quiet" do + it "should be quiet if there are no warnings" do + gemfile <<-G + source "file://#{gem_repo1}" + gem 'rack' + G + + bundle :install, :quiet => true + expect(out).to eq("") + end + + it "should still display warnings" do + gemfile <<-G + gem 'rack' + G + + bundle :install, :quiet => true + expect(out).to match(/Your Gemfile has no gem server sources/) + end + end + +end diff --git a/bundler-1.7.2/spec/install/gems/sources_spec.rb b/bundler-1.7.2/spec/install/gems/sources_spec.rb new file mode 100644 index 0000000..d45e25c --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/sources_spec.rb @@ -0,0 +1,247 @@ +require "spec_helper" + +describe "bundle install with gems on multiple sources" do + # repo1 is built automatically before all of the specs run + # it contains rack-obama 1.0.0 and rack 0.9.1 & 1.0.0 amongst other gems + + context "without source affinity" do + before do + # Oh no! Someone evil is trying to hijack rack :( + # need this to be broken to check for correct source ordering + build_repo gem_repo3 do + build_gem "rack", repo3_rack_version do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" + end + end + end + + context "when the same version of the same gem is in multiple sources" do + let(:repo3_rack_version) { "1.0.0" } + + before do + gemfile <<-G + source "file://#{gem_repo3}" + source "file://#{gem_repo1}" + gem "rack-obama" + gem "rack" + G + end + + it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first" do + bundle :install + + 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 + end + + context "when different versions of the same gem are in multiple sources" do + let(:repo3_rack_version) { "1.2" } + + before do + gemfile <<-G + source "file://#{gem_repo3}" + source "file://#{gem_repo1}" + gem "rack-obama" + gem "rack", "1.0.0" # force it to install the working version in repo1 + G + end + + it "warns about ambiguous gems, but installs anyway" do + bundle :install + + 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 + end + end + + context "with source affinity" do + context "with sources given by a block" do + before do + # Oh no! Someone evil is trying to hijack rack :( + # need this to be broken to check for correct source ordering + build_repo gem_repo3 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" + end + end + + gemfile <<-G + source "file://#{gem_repo3}" + source "file://#{gem_repo1}" do + gem "rack" + end + gem "rack-obama" # shoud come from repo3! + G + end + + it "installs the gems without any warning" do + bundle :install + expect(out).not_to include("Warning") + should_be_installed("rack-obama 1.0.0", "rack 1.0.0") + end + end + + context "with sources set by an option" do + before do + # Oh no! Someone evil is trying to hijack rack :( + # need this to be broken to check for correct source ordering + build_repo gem_repo3 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" + end + end + + gemfile <<-G + source "file://#{gem_repo3}" + gem "rack-obama" # should come from repo3! + gem "rack", :source => "file://#{gem_repo1}" + G + end + + it "installs the gems without any warning" do + bundle :install + expect(out).not_to include("Warning") + should_be_installed("rack-obama 1.0.0", "rack 1.0.0") + end + end + + context "with an indirect dependency" do + before do + build_repo gem_repo3 do + build_gem "depends_on_rack", "1.0.1" do |s| + s.add_dependency "rack" + end + end + end + + context "when the indirect dependency is in the pinned source" do + before do + # we need a working rack gem in repo3 + update_repo gem_repo3 do + build_gem "rack", "1.0.0" + end + + gemfile <<-G + source "file://#{gem_repo2}" + source "file://#{gem_repo3}" do + gem "depends_on_rack" + end + G + end + + context "and not in any other sources" do + before do + build_repo(gem_repo2) {} + end + + it "installs from the same source without any warning" do + bundle :install + expect(out).not_to include("Warning") + should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0") + end + end + + context "and in another source" do + before do + # need this to be broken to check for correct source ordering + build_repo gem_repo2 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" + end + end + end + + it "installs from the same source without any warning" do + bundle :install + expect(out).not_to include("Warning") + should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0") + end + end + end + + context "when the indirect dependency is in a different source" do + before do + # In these tests, we need a working rack gem in repo2 and not repo3 + build_repo gem_repo2 do + build_gem "rack", "1.0.0" + end + end + + context "and not in any other sources" do + before do + gemfile <<-G + source "file://#{gem_repo2}" + source "file://#{gem_repo3}" do + gem "depends_on_rack" + end + G + end + + it "installs from the other source without any warning" do + bundle :install + expect(out).not_to include("Warning") + should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0") + end + end + + context "and in yet another source" do + before do + gemfile <<-G + source "file://#{gem_repo1}" + source "file://#{gem_repo2}" + source "file://#{gem_repo3}" do + gem "depends_on_rack" + end + G + end + + it "installs from the other source and warns about ambiguous gems" do + bundle :install + 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") + end + end + end + end + + context "with a gem that is only found in the wrong source" do + before do + build_repo gem_repo3 do + build_gem "not_in_repo1", "1.0.0" + end + + gemfile <<-G + source "file://#{gem_repo3}" + gem "not_in_repo1", :source => "file://#{gem_repo1}" + G + end + + it "does not install the gem" do + bundle :install + expect(out).to include("Could not find gem 'not_in_repo1 (>= 0) ruby'") + end + end + end + + context "when an older version of the same gem also ships with Ruby" do + before do + system_gems "rack-0.9.1" + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" # shoud come from repo1! + G + end + + it "installs the gems without any warning" do + bundle :install + expect(out).not_to include("Warning") + should_be_installed("rack 1.0.0") + end + end +end diff --git a/bundler-1.7.2/spec/install/gems/standalone_spec.rb b/bundler-1.7.2/spec/install/gems/standalone_spec.rb new file mode 100644 index 0000000..c666120 --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/standalone_spec.rb @@ -0,0 +1,260 @@ +require "spec_helper" + +describe "bundle install --standalone" do + describe "with simple gems" do + before do + install_gemfile <<-G, :standalone => true + source "file://#{gem_repo1}" + gem "rails" + G + end + + it "still makes the gems available to normal bundler" do + should_be_installed "actionpack 2.3.2", "rails 2.3.2" + end + + it "generates a bundle/bundler/setup.rb" do + expect(bundled_app("bundle/bundler/setup.rb")).to exist + end + + it "makes the gems available without bundler" do + ruby <<-RUBY, :no_lib => true + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + require "actionpack" + puts ACTIONPACK + RUBY + + expect(out).to eq("2.3.2") + end + + it "works on a different system" do + FileUtils.mv(bundled_app, "#{bundled_app}2") + Dir.chdir("#{bundled_app}2") + + ruby <<-RUBY, :no_lib => true + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + require "actionpack" + puts ACTIONPACK + RUBY + + expect(out).to eq("2.3.2") + end + end + + describe "with a combination of gems and git repos" do + before do + build_git "devise", "1.0" + + install_gemfile <<-G, :standalone => true + source "file://#{gem_repo1}" + gem "rails" + gem "devise", :git => "#{lib_path('devise-1.0')}" + G + end + + it "still makes the gems available to normal bundler" do + should_be_installed "actionpack 2.3.2", "rails 2.3.2", "devise 1.0" + end + + it "generates a bundle/bundler/setup.rb" do + expect(bundled_app("bundle/bundler/setup.rb")).to exist + end + + it "makes the gems available without bundler" do + ruby <<-RUBY, :no_lib => true + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + require "devise" + require "actionpack" + puts DEVISE + puts ACTIONPACK + RUBY + + expect(out).to eq("1.0\n2.3.2") + end + end + + describe "with groups" do + before do + build_git "devise", "1.0" + + install_gemfile <<-G, :standalone => true + source "file://#{gem_repo1}" + gem "rails" + + group :test do + gem "rspec" + gem "rack-test" + end + G + end + + it "makes the gems available without bundler" do + ruby <<-RUBY, :no_lib => true + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + require "actionpack" + require "spec" + require "rack/test" + puts ACTIONPACK + puts SPEC + puts RACK_TEST + RUBY + + expect(out).to eq("2.3.2\n1.2.7\n1.0") + end + + it "allows creating a standalone file with limited groups" do + bundle "install --standalone default" + + load_error_ruby <<-RUBY, 'spec', :no_lib => true + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + require "actionpack" + puts ACTIONPACK + require "spec" + RUBY + + expect(out).to eq("2.3.2") + expect(err).to eq("ZOMG LOAD ERROR") + end + + it "allows --without to limit the groups used in a standalone" do + bundle "install --standalone --without test" + + load_error_ruby <<-RUBY, 'spec', :no_lib => true + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + require "actionpack" + puts ACTIONPACK + require "spec" + RUBY + + expect(out).to eq("2.3.2") + expect(err).to eq("ZOMG LOAD ERROR") + end + + it "allows --path to change the location of the standalone bundle" do + bundle "install --standalone --path path/to/bundle" + + ruby <<-RUBY, :no_lib => true, :expect_err => false + $:.unshift File.expand_path("path/to/bundle") + require "bundler/setup" + + require "actionpack" + puts ACTIONPACK + RUBY + + expect(out).to eq("2.3.2") + end + + it "allows remembered --without to limit the groups used in a standalone" do + bundle "install --without test" + bundle "install --standalone" + + load_error_ruby <<-RUBY, 'spec', :no_lib => true + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + require "actionpack" + puts ACTIONPACK + require "spec" + RUBY + + expect(out).to eq("2.3.2") + expect(err).to eq("ZOMG LOAD ERROR") + end + end + + describe "with gemcutter's dependency API" do + let(:source_uri) { "http://localgemserver.test" } + + describe "simple gems" do + before do + gemfile <<-G + source "#{source_uri}" + gem "rails" + G + end + + it "should run without errors" do + bundle "install --standalone", :artifice => "endpoint", :exitstatus => true + + expect(@exitstatus).to eq(0) + end + + it "still makes the gems available to normal bundler" do + bundle "install --standalone", :artifice => "endpoint" + + should_be_installed "actionpack 2.3.2", "rails 2.3.2" + end + + it "generates a bundle/bundler/setup.rb" do + bundle "install --standalone", :artifice => "endpoint" + + expect(bundled_app("bundle/bundler/setup.rb")).to exist + end + + it "makes the gems available without bundler" do + bundle "install --standalone", :artifice => "endpoint" + + ruby <<-RUBY, :no_lib => true + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + require "actionpack" + puts ACTIONPACK + RUBY + + expect(out).to eq("2.3.2") + end + + it "works on a different system" do + bundle "install --standalone", :artifice => "endpoint" + + FileUtils.mv(bundled_app, "#{bundled_app}2") + Dir.chdir("#{bundled_app}2") + + ruby <<-RUBY, :no_lib => true + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + require "actionpack" + puts ACTIONPACK + RUBY + + expect(out).to eq("2.3.2") + end + end + end + + describe "with --binstubs" do + before do + install_gemfile <<-G, :standalone => true, :binstubs => true + source "file://#{gem_repo1}" + gem "rails" + G + end + + it "creates stubs that use the standalone load path" do + Dir.chdir(bundled_app) do + expect(`bin/rails -v`.chomp).to eql "2.3.2" + end + end + + it "creates stubs that can be executed from anywhere" do + require 'tmpdir' + Dir.chdir(Dir.tmpdir) do + expect(`#{bundled_app}/bin/rails -v`.chomp).to eql "2.3.2" + end + end + end +end diff --git a/bundler-1.7.2/spec/install/gems/sudo_spec.rb b/bundler-1.7.2/spec/install/gems/sudo_spec.rb new file mode 100644 index 0000000..3664321 --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/sudo_spec.rb @@ -0,0 +1,136 @@ +require "spec_helper" + +describe "when using sudo", :sudo => true do + describe "and BUNDLE_PATH is writable" do + context "but BUNDLE_PATH/build_info is not writable" do + before do + subdir = system_gem_path('cache') + subdir.mkpath + sudo "chmod u-w #{subdir}" + end + + it "installs" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + expect(out).to_not match(/an error occurred/i) + expect(system_gem_path("cache/rack-1.0.0.gem")).to exist + should_be_installed "rack 1.0" + end + end + end + + describe "and GEM_HOME is owned by root" do + before :each do + chown_system_gems_to_root + end + + it "installs" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", '1.0' + gem "thin" + G + + expect(system_gem_path("gems/rack-1.0.0")).to exist + expect(system_gem_path("gems/rack-1.0.0").stat.uid).to eq(0) + should_be_installed "rack 1.0" + end + + it "installs rake and a gem dependent on rake in the same session" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rake" + gem "another_implicit_rake_dep" + G + bundle "install" + expect(system_gem_path("gems/another_implicit_rake_dep-1.0")).to exist + end + + + it "installs when BUNDLE_PATH is owned by root" do + bundle_path = tmp("owned_by_root") + FileUtils.mkdir_p bundle_path + sudo "chown -R root #{bundle_path}" + + ENV['BUNDLE_PATH'] = bundle_path.to_s + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", '1.0' + G + + expect(bundle_path.join("gems/rack-1.0.0")).to exist + expect(bundle_path.join("gems/rack-1.0.0").stat.uid).to eq(0) + should_be_installed "rack 1.0" + end + + it "installs when BUNDLE_PATH does not exist" do + root_path = tmp("owned_by_root") + FileUtils.mkdir_p root_path + sudo "chown -R root #{root_path}" + bundle_path = root_path.join("does_not_exist") + + ENV['BUNDLE_PATH'] = bundle_path.to_s + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", '1.0' + G + + expect(bundle_path.join("gems/rack-1.0.0")).to exist + expect(bundle_path.join("gems/rack-1.0.0").stat.uid).to eq(0) + should_be_installed "rack 1.0" + end + + it "installs extensions/ compiled by Rubygems 2.2", :rubygems => "2.2" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "very_simple_binary" + G + + expect(system_gem_path("gems/very_simple_binary-1.0")).to exist + binary_glob = system_gem_path("extensions/*/*/very_simple_binary-1.0") + expect(Dir.glob(binary_glob).first).to be + end + end + + describe "and BUNDLE_PATH is not writable" do + it "installs" do + sudo "chmod ugo-w #{default_bundle_path}" + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", '1.0' + G + + expect(default_bundle_path("gems/rack-1.0.0")).to exist + should_be_installed "rack 1.0" + end + end + + describe "and GEM_HOME is not writable" do + it "installs" do + gem_home = tmp('sudo_gem_home') + sudo "mkdir -p #{gem_home}" + sudo "chmod ugo-w #{gem_home}" + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", '1.0' + G + + bundle :install, :env => {'GEM_HOME' => gem_home.to_s, 'GEM_PATH' => nil} + expect(gem_home.join('bin/rackup')).to exist + should_be_installed "rack 1.0", :env => {'GEM_HOME' => gem_home.to_s, 'GEM_PATH' => nil} + end + end + + describe "and root runs install" do + it "warns against that" do + gemfile %|source "file://#{gem_repo1}"| + bundle :install, :sudo => true + expect(out).to include("Don't run Bundler as root.") + end + end + +end diff --git a/bundler-1.7.2/spec/install/gems/win32_spec.rb b/bundler-1.7.2/spec/install/gems/win32_spec.rb new file mode 100644 index 0000000..6224220 --- /dev/null +++ b/bundler-1.7.2/spec/install/gems/win32_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe "bundle install with win32-generated lockfile" do + it "should read lockfile" do + File.open(bundled_app('Gemfile.lock'), 'wb') do |f| + f << "GEM\r\n" + f << " remote: file:#{gem_repo1}/\r\n" + f << " specs:\r\n" + f << "\r\n" + f << " rack (1.0.0)\r\n" + f << "\r\n" + f << "PLATFORMS\r\n" + f << " ruby\r\n" + f << "\r\n" + f << "DEPENDENCIES\r\n" + f << " rack\r\n" + end + + install_gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + + gem "rack" + G + expect(@exitstatus).to eq(0) + end +end diff --git a/bundler-1.7.2/spec/install/gemspecs_spec.rb b/bundler-1.7.2/spec/install/gemspecs_spec.rb new file mode 100644 index 0000000..201ba95 --- /dev/null +++ b/bundler-1.7.2/spec/install/gemspecs_spec.rb @@ -0,0 +1,50 @@ +require 'spec_helper' + +describe "bundle install" do + + describe "when a gem has a YAML gemspec" do + before :each do + build_repo2 do + build_gem "yaml_spec", :gemspec => :yaml + end + end + + it "still installs correctly" do + gemfile <<-G + source "file://#{gem_repo2}" + gem "yaml_spec" + G + bundle :install + expect(err).to be_empty + end + + it "still installs correctly when using path" do + build_lib 'yaml_spec', :gemspec => :yaml + + install_gemfile <<-G + gem 'yaml_spec', :path => "#{lib_path('yaml_spec-1.0')}" + G + expect(err).to eq("") + end + end + + it "should use gemspecs in the system cache when available" do + gemfile <<-G + source "http://localtestserver.gem" + gem 'rack' + G + + FileUtils.mkdir_p "#{tmp}/gems/system/specifications" + File.open("#{tmp}/gems/system/specifications/rack-1.0.0.gemspec", 'w+') do |f| + spec = Gem::Specification.new do |s| + s.name = 'rack' + s.version = '1.0.0' + s.add_runtime_dependency 'activesupport', '2.3.2' + end + f.write spec.to_ruby + end + bundle :install, :artifice => 'endpoint_marshal_fail' # force gemspec load + should_be_installed "activesupport 2.3.2" + end + +end diff --git a/bundler-1.7.2/spec/install/path_spec.rb b/bundler-1.7.2/spec/install/path_spec.rb new file mode 100644 index 0000000..2ddceb2 --- /dev/null +++ b/bundler-1.7.2/spec/install/path_spec.rb @@ -0,0 +1,150 @@ +require "spec_helper" + +describe "bundle install" do + + describe "with --path" do + before :each do + build_gem "rack", "1.0.0", :to_system => true do |s| + s.write "lib/rack.rb", "puts 'FAIL'" + end + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + end + + it "does not use available system gems with bundle --path vendor/bundle" do + bundle "install --path vendor/bundle" + should_be_installed "rack 1.0.0" + end + + it "handles paths with regex characters in them" do + dir = bundled_app("bun++dle") + dir.mkpath + + Dir.chdir(dir) do + bundle "install --path vendor/bundle" + expect(out).to include("installed into ./vendor/bundle") + end + + dir.rmtree + end + + 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") + end + + it "disallows --path vendor/bundle --system" do + bundle "install --path vendor/bundle --system" + expect(out).to include("Please choose.") + end + + it "remembers to disable system gems after the first time with bundle --path vendor/bundle" do + bundle "install --path vendor/bundle" + FileUtils.rm_rf bundled_app('vendor') + bundle "install" + + expect(vendored_gems('gems/rack-1.0.0')).to be_directory + should_be_installed "rack 1.0.0" + end + end + + describe "when BUNDLE_PATH or the global path config is set" do + before :each do + build_lib "rack", "1.0.0", :to_system => true do |s| + s.write "lib/rack.rb", "raise 'FAIL'" + end + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + end + + def set_bundle_path(type, location) + if type == :env + ENV["BUNDLE_PATH"] = location + elsif type == :global + bundle "config path #{location}", "no-color" => nil + end + end + + [:env, :global].each do |type| + it "installs gems to a path if one is specified" do + set_bundle_path(type, bundled_app("vendor2").to_s) + bundle "install --path vendor/bundle" + + expect(vendored_gems("gems/rack-1.0.0")).to be_directory + expect(bundled_app("vendor2")).not_to be_directory + should_be_installed "rack 1.0.0" + end + + it "installs gems to BUNDLE_PATH with #{type}" do + set_bundle_path(type, bundled_app("vendor").to_s) + + bundle :install + + expect(bundled_app('vendor/gems/rack-1.0.0')).to be_directory + should_be_installed "rack 1.0.0" + end + + it "installs gems to BUNDLE_PATH relative to root when relative" do + set_bundle_path(type, "vendor") + + FileUtils.mkdir_p bundled_app('lol') + Dir.chdir(bundled_app('lol')) do + bundle :install + end + + expect(bundled_app('vendor/gems/rack-1.0.0')).to be_directory + should_be_installed "rack 1.0.0" + end + end + + it "installs gems to BUNDLE_PATH from .bundle/config" do + config "BUNDLE_PATH" => bundled_app("vendor/bundle").to_s + + bundle :install + + expect(vendored_gems('gems/rack-1.0.0')).to be_directory + should_be_installed "rack 1.0.0" + end + + it "sets BUNDLE_PATH as the first argument to bundle install" do + bundle "install --path ./vendor/bundle" + + expect(vendored_gems('gems/rack-1.0.0')).to be_directory + should_be_installed "rack 1.0.0" + end + + it "disables system gems when passing a path to install" do + # This is so that vendored gems can be distributed to others + build_gem "rack", "1.1.0", :to_system => true + bundle "install --path ./vendor/bundle" + + expect(vendored_gems('gems/rack-1.0.0')).to be_directory + should_be_installed "rack 1.0.0" + end + end + + describe "to a dead symlink" do + before do + in_app_root do + `ln -s /tmp/idontexist bundle` + end + end + + it "reports the symlink is dead" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + bundle "install --path bundle" + expect(out).to match(/invalid symlink/) + end + end + +end diff --git a/bundler-1.7.2/spec/install/post_bundle_message_spec.rb b/bundler-1.7.2/spec/install/post_bundle_message_spec.rb new file mode 100644 index 0000000..6bd4e85 --- /dev/null +++ b/bundler-1.7.2/spec/install/post_bundle_message_spec.rb @@ -0,0 +1,142 @@ +require 'spec_helper' + +describe "post bundle message" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "activesupport", "2.3.5", :group => [:emo, :test] + group :test do + gem "rspec" + end + gem "rack-obama", :group => :obama + G + 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!"} + + describe "for fresh bundle install" do + it "without any options" do + bundle :install + expect(out).to include(bundle_show_message) + expect(out).not_to include("Gems in the group") + expect(out).to include(bundle_complete_message) + end + + it "with --without one group" do + bundle "install --without emo" + 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) + end + + it "with --without two groups" do + bundle "install --without emo test" + 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) + end + + it "with --without more groups" do + bundle "install --without emo obama test" + 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) + end + + describe "with --path and" do + it "without any options" do + bundle "install --path vendor" + expect(out).to include(bundle_deployment_message) + expect(out).to_not include("Gems in the group") + expect(out).to include(bundle_complete_message) + end + + it "with --without one group" do + bundle "install --without emo --path vendor" + expect(out).to include(bundle_deployment_message) + expect(out).to include("Gems in the group emo were not installed") + expect(out).to include(bundle_complete_message) + end + + it "with --without two groups" do + bundle "install --without emo test --path vendor" + expect(out).to include(bundle_deployment_message) + expect(out).to include("Gems in the groups emo and test were not installed") + expect(out).to include(bundle_complete_message) + end + + it "with --without more groups" do + bundle "install --without emo obama test --path vendor" + expect(out).to include(bundle_deployment_message) + expect(out).to include("Gems in the groups emo, obama and test were not installed") + expect(out).to include(bundle_complete_message) + end + end + end + + describe "for second bundle install run" do + it "without any options" do + 2.times { bundle :install } + expect(out).to include(bundle_show_message) + expect(out).to_not include("Gems in the groups") + expect(out).to include(bundle_complete_message) + end + + it "with --without one group" do + bundle "install --without emo" + bundle :install + 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) + end + + it "with --without two groups" do + bundle "install --without emo test" + bundle :install + 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) + end + + it "with --without more groups" do + bundle "install --without emo obama test" + bundle :install + 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) + end + end + + describe "for bundle update" do + it "without any options" do + bundle :update + expect(out).not_to include("Gems in the groups") + expect(out).to include(bundle_updated_message) + end + + it "with --without one group" do + bundle :install, :without => :emo + bundle :update + expect(out).to include("Gems in the group emo were not installed") + expect(out).to include(bundle_updated_message) + end + + it "with --without two groups" do + bundle "install --without emo test" + bundle :update + expect(out).to include("Gems in the groups emo and test were not installed") + expect(out).to include(bundle_updated_message) + end + + it "with --without more groups" do + bundle "install --without emo obama test" + bundle :update + expect(out).to include("Gems in the groups emo, obama and test were not installed") + expect(out).to include(bundle_updated_message) + end + end +end diff --git a/bundler-1.7.2/spec/install/prereleases_spec.rb b/bundler-1.7.2/spec/install/prereleases_spec.rb new file mode 100644 index 0000000..f4f79af --- /dev/null +++ b/bundler-1.7.2/spec/install/prereleases_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' + +describe "bundle install" do + + describe "when prerelease gems are available" do + it "finds prereleases" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "not_released" + G + should_be_installed "not_released 1.0.pre" + end + + it "uses regular releases if available" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "has_prerelease" + G + should_be_installed "has_prerelease 1.0" + end + + it "uses prereleases if requested" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "has_prerelease", "1.1.pre" + G + should_be_installed "has_prerelease 1.1.pre" + end + end + + describe "when prerelease gems are not available" do + it "still works" do + build_repo3 + install_gemfile <<-G + source "file://#{gem_repo3}" + gem "rack" + G + + should_be_installed "rack 1.0" + end + end + +end diff --git a/bundler-1.7.2/spec/install/security_policy_spec.rb b/bundler-1.7.2/spec/install/security_policy_spec.rb new file mode 100644 index 0000000..941e14d --- /dev/null +++ b/bundler-1.7.2/spec/install/security_policy_spec.rb @@ -0,0 +1,77 @@ +require "spec_helper" +require "rubygems/security" + +# unfortunately, testing signed gems with a provided CA is extremely difficult +# as 'gem cert' is currently the only way to add CAs to the system. + +describe "policies with unsigned gems" do + before do + build_security_repo + gemfile <<-G + source "file://#{security_repo}" + gem "rack" + gem "signed_gem" + G + end + + it "will work after you try to deploy without a lock" do + bundle "install --deployment" + bundle :install, :exitstatus => true + expect(exitstatus).to eq(0) + should_be_installed "rack 1.0", "signed_gem 1.0" + end + + it "will fail when given invalid security policy" do + bundle "install --trust-policy=InvalidPolicyName" + expect(out).to include("Rubygems doesn't know about trust policy") + end + + it "will fail with High Security setting due to presence of unsigned gem" do + bundle "install --trust-policy=HighSecurity" + expect(out).to include("security policy didn't allow") + end + + # This spec will fail on Rubygems 2 rc1 due to a bug in policy.rb. the bug is fixed in rc3. + it "will fail with Medium Security setting due to presence of unsigned gem", :unless => ENV['RGV'] == "v2.0.0.rc.1" do + bundle "install --trust-policy=MediumSecurity" + expect(out).to include("security policy didn't allow") + end + + it "will succeed with no policy" do + bundle "install", :exitstatus => true + expect(exitstatus).to eq(0) + end + +end + +describe "policies with signed gems and no CA" do + before do + build_security_repo + gemfile <<-G + source "file://#{security_repo}" + gem "signed_gem" + G + end + + it "will fail with High Security setting, gem is self-signed" do + bundle "install --trust-policy=HighSecurity" + expect(out).to include("security policy didn't allow") + end + + it "will fail with Medium Security setting, gem is self-signed" do + bundle "install --trust-policy=MediumSecurity" + expect(out).to include("security policy didn't allow") + 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) + should_be_installed "signed_gem 1.0" + end + + it "will succeed with no policy" do + bundle "install", :exitstatus => true + expect(exitstatus).to eq(0) + should_be_installed "signed_gem 1.0" + end +end diff --git a/bundler-1.7.2/spec/install/upgrade_spec.rb b/bundler-1.7.2/spec/install/upgrade_spec.rb new file mode 100644 index 0000000..603c39b --- /dev/null +++ b/bundler-1.7.2/spec/install/upgrade_spec.rb @@ -0,0 +1,26 @@ +require "spec_helper" + +describe "bundle install for the first time with v1.0" do + before :each do + in_app_root + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + end + + it "removes lockfiles in 0.9 YAML format" do + File.open("Gemfile.lock", "w"){|f| YAML.dump({}, f) } + bundle :install + expect(File.read("Gemfile.lock")).not_to match(/^---/) + end + + it "removes env.rb if it exists" do + bundled_app.join(".bundle").mkdir + bundled_app.join(".bundle/environment.rb").open("w"){|f| f.write("raise 'nooo'") } + bundle :install + expect(bundled_app.join(".bundle/environment.rb")).not_to exist + end + +end diff --git a/bundler-1.7.2/spec/lock/git_spec.rb b/bundler-1.7.2/spec/lock/git_spec.rb new file mode 100644 index 0000000..9d4ecf9 --- /dev/null +++ b/bundler-1.7.2/spec/lock/git_spec.rb @@ -0,0 +1,34 @@ +require "spec_helper" + +describe "bundle lock with git gems" do + before :each do + build_git "foo" + + install_gemfile <<-G + gem 'foo', :git => "#{lib_path('foo-1.0')}" + G + end + + it "doesn't break right after running lock" do + should_be_installed "foo 1.0.0" + end + + it "locks a git source to the current ref" do + update_git "foo" + bundle :install + + run <<-RUBY + require 'foo' + puts "WIN" unless defined?(FOO_PREV_REF) + RUBY + + expect(out).to eq("WIN") + end + + it "provides correct #full_gem_path" do + run <<-RUBY + puts Bundler.rubygems.find_name('foo').first.full_gem_path + RUBY + expect(out).to eq(bundle("show foo")) + end +end diff --git a/bundler-1.7.2/spec/lock/lockfile_spec.rb b/bundler-1.7.2/spec/lock/lockfile_spec.rb new file mode 100644 index 0000000..588d643 --- /dev/null +++ b/bundler-1.7.2/spec/lock/lockfile_spec.rb @@ -0,0 +1,924 @@ +require "spec_helper" + +describe "the lockfile format" do + include Bundler::GemHelpers + + it "generates a simple lockfile for a single source, gem" do + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack" + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + rack + G + end + + it "generates a simple lockfile for a single source, gem with dependencies" do + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack-obama" + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + rack-obama (1.0) + rack + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + rack-obama + G + end + + it "generates a simple lockfile for a single source, gem with a version requirement" do + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack-obama", ">= 1.0" + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + rack-obama (1.0) + rack + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + rack-obama (>= 1.0) + G + end + + it "generates a lockfile wihout credentials for a configured source" do + bundle "config http://localgemserver.test/ user:pass" + + install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true) + source "http://localgemserver.test/" + + gem "rack-obama", ">= 1.0" + G + + lockfile_should_be <<-G + GEM + remote: http://localgemserver.test/ + specs: + rack (1.0.0) + rack-obama (1.0) + rack + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + rack-obama (>= 1.0) + G + end + + it "generates lockfiles with multiple requirements" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "net-sftp" + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + net-sftp (1.1.1) + net-ssh (>= 1.0.0, < 1.99.0) + net-ssh (1.0) + + PLATFORMS + ruby + + DEPENDENCIES + net-sftp + G + + should_be_installed "net-sftp 1.1.1", "net-ssh 1.0.0" + end + + it "generates a simple lockfile for a single pinned source, gem with a version requirement" do + git = build_git "foo" + + install_gemfile <<-G + gem "foo", :git => "#{lib_path("foo-1.0")}" + G + + lockfile_should_be <<-G + GIT + remote: #{lib_path("foo-1.0")} + revision: #{git.ref_for('master')} + specs: + foo (1.0) + + GEM + specs: + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + foo! + G + end + + it "does not asplode when a platform specific dependency is present and the Gemfile has not been resolved on that platform" do + build_lib "omg", :path => lib_path('omg') + + gemfile <<-G + source "file://#{gem_repo1}" + + platforms :#{not_local_tag} do + gem "omg", :path => "#{lib_path('omg')}" + end + + gem "rack" + G + + lockfile <<-L + GIT + remote: git://github.com/nex3/haml.git + revision: 8a2271f + specs: + + GEM + remote: file://#{gem_repo1}/ + specs: + rack (1.0.0) + + PLATFORMS + #{not_local} + + DEPENDENCIES + omg! + rack + L + + bundle "install" + should_be_installed "rack 1.0.0" + end + + it "serializes global git sources" do + git = build_git "foo" + + install_gemfile <<-G + git "#{lib_path('foo-1.0')}" do + gem "foo" + end + G + + lockfile_should_be <<-G + GIT + remote: #{lib_path('foo-1.0')} + revision: #{git.ref_for('master')} + specs: + foo (1.0) + + GEM + specs: + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + foo! + G + end + + it "generates a lockfile with a ref for a single pinned source, git gem with a branch requirement" do + git = build_git "foo" + update_git "foo", :branch => "omg" + + install_gemfile <<-G + gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg" + G + + lockfile_should_be <<-G + GIT + remote: #{lib_path("foo-1.0")} + revision: #{git.ref_for('omg')} + branch: omg + specs: + foo (1.0) + + GEM + specs: + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + foo! + G + end + + it "generates a lockfile with a ref for a single pinned source, git gem with a tag requirement" do + git = build_git "foo" + update_git "foo", :tag => "omg" + + install_gemfile <<-G + gem "foo", :git => "#{lib_path("foo-1.0")}", :tag => "omg" + G + + lockfile_should_be <<-G + GIT + remote: #{lib_path("foo-1.0")} + revision: #{git.ref_for('omg')} + tag: omg + specs: + foo (1.0) + + GEM + specs: + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + foo! + G + end + + it "serializes pinned path sources to the lockfile" do + build_lib "foo" + + install_gemfile <<-G + gem "foo", :path => "#{lib_path("foo-1.0")}" + G + + lockfile_should_be <<-G + PATH + remote: #{lib_path("foo-1.0")} + specs: + foo (1.0) + + GEM + specs: + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + foo! + G + end + + it "sorts serialized sources by type" do + build_lib "foo" + bar = build_git "bar" + + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack" + gem "foo", :path => "#{lib_path("foo-1.0")}" + gem "bar", :git => "#{lib_path("bar-1.0")}" + G + + lockfile_should_be <<-G + GIT + remote: #{lib_path("bar-1.0")} + revision: #{bar.ref_for('master')} + specs: + bar (1.0) + + PATH + remote: #{lib_path("foo-1.0")} + specs: + foo (1.0) + + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + bar! + foo! + rack + G + end + + it "lists gems alphabetically" do + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "thin" + gem "actionpack" + gem "rack-obama" + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + actionpack (2.3.2) + activesupport (= 2.3.2) + activesupport (2.3.2) + rack (1.0.0) + rack-obama (1.0) + rack + thin (1.0) + rack + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + actionpack + rack-obama + thin + G + end + + it "orders dependencies' dependencies in alphabetical order" do + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "rails" + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + actionmailer (2.3.2) + activesupport (= 2.3.2) + actionpack (2.3.2) + activesupport (= 2.3.2) + activerecord (2.3.2) + activesupport (= 2.3.2) + activeresource (2.3.2) + activesupport (= 2.3.2) + activesupport (2.3.2) + rails (2.3.2) + actionmailer (= 2.3.2) + actionpack (= 2.3.2) + activerecord (= 2.3.2) + activeresource (= 2.3.2) + rake (= 10.0.2) + rake (10.0.2) + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + rails + G + end + + it "orders dependencies by version" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem 'double_deps' + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + double_deps (1.0) + net-ssh + net-ssh (>= 1.0.0) + net-ssh (1.0) + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + double_deps + G + end + + it "does not add the :require option to the lockfile" do + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack-obama", ">= 1.0", :require => "rack/obama" + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + rack-obama (1.0) + rack + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + rack-obama (>= 1.0) + G + end + + it "does not add the :group option to the lockfile" do + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack-obama", ">= 1.0", :group => :test + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + rack-obama (1.0) + rack + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + rack-obama (>= 1.0) + G + end + + it "stores relative paths when the path is provided in a relative fashion and in Gemfile dir" do + build_lib "foo", :path => bundled_app('foo') + + install_gemfile <<-G + path "foo" + gem "foo" + G + + lockfile_should_be <<-G + PATH + remote: foo + specs: + foo (1.0) + + GEM + specs: + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + foo + G + end + + it "stores relative paths when the path is provided in a relative fashion and is above Gemfile dir" do + build_lib "foo", :path => bundled_app(File.join('..', 'foo')) + + install_gemfile <<-G + path "../foo" + gem "foo" + G + + lockfile_should_be <<-G + PATH + remote: ../foo + specs: + foo (1.0) + + GEM + specs: + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + foo + G + end + + it "stores relative paths when the path is provided in an absolute fashion but is relative" do + build_lib "foo", :path => bundled_app('foo') + + install_gemfile <<-G + path File.expand_path("../foo", __FILE__) + gem "foo" + G + + lockfile_should_be <<-G + PATH + remote: foo + specs: + foo (1.0) + + GEM + specs: + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + foo + G + end + + it "stores relative paths when the path is provided for gemspec" do + build_lib("foo", :path => tmp.join("foo")) + + install_gemfile <<-G + gemspec :path => "../foo" + G + + lockfile_should_be <<-G + PATH + remote: ../foo + specs: + foo (1.0) + + GEM + specs: + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + foo! + G + end + + it "keeps existing platforms in the lockfile" do + lockfile <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + + PLATFORMS + java + + DEPENDENCIES + rack + G + + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "rack" + G + + platforms = ['java', generic(Gem::Platform.local).to_s].sort + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + + PLATFORMS + #{platforms[0]} + #{platforms[1]} + + DEPENDENCIES + rack + G + end + + it "persists the spec's platform to the lockfile" do + build_gem "platform_specific", "1.0.0", :to_system => true do |s| + s.platform = Gem::Platform.new('universal-java-16') + end + + simulate_platform "universal-java-16" + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "platform_specific" + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + platform_specific (1.0-java) + + PLATFORMS + java + + DEPENDENCIES + platform_specific + G + end + + it "does not add duplicate gems" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "activesupport" + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + activesupport (2.3.5) + rack (1.0.0) + + PLATFORMS + ruby + + DEPENDENCIES + activesupport + rack + G + end + + it "does not add duplicate dependencies" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "rack" + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + + PLATFORMS + ruby + + DEPENDENCIES + rack + G + end + + it "does not add duplicate dependencies with versions" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "1.0" + gem "rack", "1.0" + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + + PLATFORMS + ruby + + DEPENDENCIES + rack (= 1.0) + G + end + + it "does not add duplicate dependencies in different groups" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "1.0", :group => :one + gem "rack", "1.0", :group => :two + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + + PLATFORMS + ruby + + DEPENDENCIES + rack (= 1.0) + G + end + + it "raises if two different versions are used" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "1.0" + gem "rack", "1.1" + G + + expect(bundled_app("Gemfile.lock")).not_to exist + expect(out).to include "rack (= 1.0) and rack (= 1.1)" + end + + + it "raises if two different sources are used" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "rack", :git => "git://hubz.com" + G + + expect(bundled_app("Gemfile.lock")).not_to exist + expect(out).to include "rack (>= 0) should come from an unspecified source and git://hubz.com (at master)" + end + + it "works correctly with multiple version dependencies" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "> 0.9", "< 1.0" + G + + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (0.9.1) + + PLATFORMS + ruby + + DEPENDENCIES + rack (> 0.9, < 1.0) + G + + end + + # Some versions of the Bundler 1.1 RC series introduced corrupted + # lockfiles. There were two major problems: + # + # * multiple copies of the same GIT section appeared in the lockfile + # * when this happened, those sections got multiple copies of gems + # in those sections. + it "fixes corrupted lockfiles" do + build_git "omg", :path => lib_path('omg') + revision = revision_for(lib_path('omg')) + + gemfile <<-G + source "file://#{gem_repo1}" + gem "omg", :git => "#{lib_path('omg')}", :branch => 'master' + G + + bundle "install --path vendor" + should_be_installed "omg 1.0" + + # Create a Gemfile.lock that has duplicate GIT sections + lockfile <<-L + GIT + remote: #{lib_path('omg')} + revision: #{revision} + branch: master + specs: + omg (1.0) + + GIT + remote: #{lib_path('omg')} + revision: #{revision} + branch: master + specs: + omg (1.0) + + GEM + remote: file:#{gem_repo1}/ + specs: + + PLATFORMS + #{local} + + DEPENDENCIES + omg! + L + + FileUtils.rm_rf(bundled_app('vendor')) + bundle "install" + should_be_installed "omg 1.0" + + # Confirm that duplicate specs do not appear + expect(File.read(bundled_app('Gemfile.lock'))).to eq(strip_whitespace(<<-L)) + GIT + remote: #{lib_path('omg')} + revision: #{revision} + branch: master + specs: + omg (1.0) + + GEM + remote: file:#{gem_repo1}/ + specs: + + PLATFORMS + #{local} + + DEPENDENCIES + omg! + L + end + + describe "a line ending" do + def set_lockfile_mtime_to_known_value + time = Time.local(2000, 1, 1, 0, 0, 0) + File.utime(time, time, bundled_app('Gemfile.lock')) + end + before(:each) do + build_repo2 + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "rack" + G + set_lockfile_mtime_to_known_value + end + + it "generates Gemfile.lock with \\n line endings" do + expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n") + should_be_installed "rack 1.0" + end + + context "during updates" do + + it "preserves Gemfile.lock \\n line endings" do + update_repo2 + + expect { bundle "update" }.to change { File.mtime(bundled_app('Gemfile.lock')) } + expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n") + should_be_installed "rack 1.2" + end + + it "preserves Gemfile.lock \\n\\r line endings" do + update_repo2 + win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n") + File.open(bundled_app("Gemfile.lock"), "wb"){|f| f.puts(win_lock) } + set_lockfile_mtime_to_known_value + + expect { bundle "update" }.to change { File.mtime(bundled_app('Gemfile.lock')) } + expect(File.read(bundled_app("Gemfile.lock"))).to match("\r\n") + should_be_installed "rack 1.2" + end + end + + context "when nothing changes" do + + it "preserves Gemfile.lock \\n line endings" do + expect { ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup + RUBY + }.not_to change { File.mtime(bundled_app('Gemfile.lock')) } + end + + it "preserves Gemfile.lock \\n\\r line endings" do + win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n") + File.open(bundled_app("Gemfile.lock"), "wb"){|f| f.puts(win_lock) } + set_lockfile_mtime_to_known_value + + expect { ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup + RUBY + }.not_to change { File.mtime(bundled_app('Gemfile.lock')) } + end + end + end + + it "refuses to install if Gemfile.lock contains conflict markers" do + lockfile <<-L + GEM + remote: file://#{gem_repo1}/ + specs: + <<<<<<< + rack (1.0.0) + ======= + rack (1.0.1) + >>>>>>> + + PLATFORMS + ruby + + DEPENDENCIES + rack + L + + error = install_gemfile(<<-G, :expect_err => true) + source "file://#{gem_repo1}" + gem "rack" + G + + expect(error).to match(/your Gemfile.lock contains merge conflicts/i) + expect(error).to match(/git checkout HEAD -- Gemfile.lock/i) + end +end diff --git a/bundler-1.7.2/spec/other/bundle_ruby_spec.rb b/bundler-1.7.2/spec/other/bundle_ruby_spec.rb new file mode 100644 index 0000000..08d24ee --- /dev/null +++ b/bundler-1.7.2/spec/other/bundle_ruby_spec.rb @@ -0,0 +1,142 @@ +require "spec_helper" + +describe "bundle_ruby" do + context "without patchlevel" do + it "returns the ruby version" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.9.3", :engine => 'ruby', :engine_version => '1.9.3' + + gem "foo" + G + + bundle_ruby + + expect(out).to eq("ruby 1.9.3") + end + + it "engine defaults to MRI" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.9.3" + + gem "foo" + G + + bundle_ruby + + expect(out).to eq("ruby 1.9.3") + end + + it "handles jruby" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.8.7", :engine => 'jruby', :engine_version => '1.6.5' + + gem "foo" + G + + bundle_ruby + + expect(out).to eq("ruby 1.8.7 (jruby 1.6.5)") + end + + it "handles rbx" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.8.7", :engine => 'rbx', :engine_version => '1.2.4' + + gem "foo" + G + + bundle_ruby + + expect(out).to eq("ruby 1.8.7 (rbx 1.2.4)") + end + + it "raises an error if engine is used but engine version is not" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.8.7", :engine => 'rbx' + + gem "foo" + G + + bundle_ruby :exitstatus => true + expect(exitstatus).not_to eq(0) + + bundle_ruby + expect(out).to eq("Please define :engine_version") + end + + it "raises an error if engine_version is used but engine is not" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.8.7", :engine_version => '1.2.4' + + gem "foo" + G + + bundle_ruby :exitstatus => true + expect(exitstatus).not_to eq(0) + + bundle_ruby + expect(out).to eq("Please define :engine") + end + + it "raises an error if engine version doesn't match ruby version for MRI" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.8.7", :engine => 'ruby', :engine_version => '1.2.4' + + gem "foo" + G + + bundle_ruby :exitstatus => true + expect(exitstatus).not_to eq(0) + + bundle_ruby + expect(out).to eq("ruby_version must match the :engine_version for MRI") + end + + it "should print if no ruby version is specified" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "foo" + G + + bundle_ruby + + expect(out).to eq("No ruby version specified") + end + end + + context "when using patchlevel" do + it "returns the ruby version" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.9.3", :patchlevel => '429', :engine => 'ruby', :engine_version => '1.9.3' + + gem "foo" + G + + bundle_ruby + + expect(out).to eq("ruby 1.9.3p429") + end + + it "handles an engine" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.9.3", :patchlevel => '392', :engine => 'jruby', :engine_version => '1.7.4' + + gem "foo" + G + + bundle_ruby + + expect(out).to eq("ruby 1.9.3p392 (jruby 1.7.4)") + end + end +end diff --git a/bundler-1.7.2/spec/other/cli_dispatch_spec.rb b/bundler-1.7.2/spec/other/cli_dispatch_spec.rb new file mode 100644 index 0000000..f03c4ce --- /dev/null +++ b/bundler-1.7.2/spec/other/cli_dispatch_spec.rb @@ -0,0 +1,21 @@ +require "spec_helper" + +describe "bundle command names" do + it "work when given fully" do + bundle "install" + expect(err).to eq("") + expect(out).not_to match(/Ambiguous command/) + end + + it "work when not ambiguous" do + bundle "ins" + expect(err).to eq("") + expect(out).not_to match(/Ambiguous command/) + end + + it "print a friendly error when ambiguous" do + bundle "i" + expect(err).to eq("") + expect(out).to match(/Ambiguous command/) + end +end diff --git a/bundler-1.7.2/spec/other/ext_spec.rb b/bundler-1.7.2/spec/other/ext_spec.rb new file mode 100644 index 0000000..cbee163 --- /dev/null +++ b/bundler-1.7.2/spec/other/ext_spec.rb @@ -0,0 +1,60 @@ +require 'spec_helper' + +describe "Gem::Specification#match_platform" do + it "does not match platforms other than the gem platform" do + darwin = gem "lol", "1.0", "platform_specific-1.0-x86-darwin-10" + expect(darwin.match_platform(pl('java'))).to eq(false) + end +end + +describe "Bundler::GemHelpers#generic" do + include Bundler::GemHelpers + + it "converts non-windows platforms into ruby" do + expect(generic(pl('x86-darwin-10'))).to eq(pl('ruby')) + expect(generic(pl('ruby'))).to eq(pl('ruby')) + end + + it "converts java platform variants into java" do + expect(generic(pl('universal-java-17'))).to eq(pl('java')) + expect(generic(pl('java'))).to eq(pl('java')) + end + + it "converts mswin platform variants into x86-mswin32" do + expect(generic(pl('mswin32'))).to eq(pl('x86-mswin32')) + expect(generic(pl('i386-mswin32'))).to eq(pl('x86-mswin32')) + expect(generic(pl('x86-mswin32'))).to eq(pl('x86-mswin32')) + end + + it "converts 32-bit mingw platform variants into x86-mingw32" do + expect(generic(pl('mingw32'))).to eq(pl('x86-mingw32')) + expect(generic(pl('i386-mingw32'))).to eq(pl('x86-mingw32')) + expect(generic(pl('x86-mingw32'))).to eq(pl('x86-mingw32')) + end + + it "converts 64-bit mingw platform variants into x64-mingw32" do + expect(generic(pl('x64-mingw32'))).to eq(pl('x64-mingw32')) + expect(generic(pl('x86_64-mingw32'))).to eq(pl('x64-mingw32')) + end +end + +describe "Gem::SourceIndex#refresh!" do + rubygems_1_7 = Gem::Version.new(Gem::VERSION) >= Gem::Version.new("1.7.0") + + before do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + end + + it "does not explode when called", :if => rubygems_1_7 do + run "Gem.source_index.refresh!" + run "Gem::SourceIndex.new([]).refresh!" + end + + it "does not explode when called", :unless => rubygems_1_7 do + run "Gem.source_index.refresh!" + run "Gem::SourceIndex.from_gems_in([]).refresh!" + end +end diff --git a/bundler-1.7.2/spec/other/platform_spec.rb b/bundler-1.7.2/spec/other/platform_spec.rb new file mode 100644 index 0000000..619b5c7 --- /dev/null +++ b/bundler-1.7.2/spec/other/platform_spec.rb @@ -0,0 +1,1285 @@ +require "spec_helper" + +describe "bundle platform" do + context "without flags" do + it "returns all the output" do + gemfile <<-G + source "file://#{gem_repo1}" + + #{ruby_version_correct} + + gem "foo" + G + + bundle "platform" + expect(out).to eq(<<-G.chomp) +Your platform is: #{RUBY_PLATFORM} + +Your app has gems that work on these platforms: +* ruby + +Your Gemfile specifies a Ruby version requirement: +* ruby #{RUBY_VERSION} + +Your current platform satisfies the Ruby version requirement. +G + end + + it "returns all the output including the patchlevel" do + gemfile <<-G + source "file://#{gem_repo1}" + + #{ruby_version_correct_patchlevel} + + gem "foo" + G + + bundle "platform" + expect(out).to eq(<<-G.chomp) +Your platform is: #{RUBY_PLATFORM} + +Your app has gems that work on these platforms: +* ruby + +Your Gemfile specifies a Ruby version requirement: +* ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL} + +Your current platform satisfies the Ruby version requirement. +G + end + + it "doesn't print ruby version requirement if it isn't specified" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "foo" + G + + bundle "platform" + expect(out).to eq(<<-G.chomp) +Your platform is: #{RUBY_PLATFORM} + +Your app has gems that work on these platforms: +* ruby + +Your Gemfile does not specify a Ruby version requirement. +G + end + + it "doesn't match the ruby version requirement" do + gemfile <<-G + source "file://#{gem_repo1}" + + #{ruby_version_incorrect} + + gem "foo" + G + + bundle "platform" + expect(out).to eq(<<-G.chomp) +Your platform is: #{RUBY_PLATFORM} + +Your app has gems that work on these platforms: +* ruby + +Your Gemfile specifies a Ruby version requirement: +* ruby #{not_local_ruby_version} + +Your Ruby version is #{RUBY_VERSION}, but your Gemfile specified #{not_local_ruby_version} +G + end + end + + context "--ruby" do + it "returns ruby version when explicit" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.9.3", :engine => 'ruby', :engine_version => '1.9.3' + + gem "foo" + G + + bundle "platform --ruby" + + expect(out).to eq("ruby 1.9.3") + end + + it "defaults to MRI" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.9.3" + + gem "foo" + G + + bundle "platform --ruby" + + expect(out).to eq("ruby 1.9.3") + end + + it "handles jruby" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.8.7", :engine => 'jruby', :engine_version => '1.6.5' + + gem "foo" + G + + bundle "platform --ruby" + + expect(out).to eq("ruby 1.8.7 (jruby 1.6.5)") + end + + it "handles rbx" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.8.7", :engine => 'rbx', :engine_version => '1.2.4' + + gem "foo" + G + + bundle "platform --ruby" + + expect(out).to eq("ruby 1.8.7 (rbx 1.2.4)") + end + + it "raises an error if engine is used but engine version is not" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.8.7", :engine => 'rbx' + + gem "foo" + G + + bundle "platform", :exitstatus => true + + expect(exitstatus).not_to eq(0) + end + + it "raises an error if engine_version is used but engine is not" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.8.7", :engine_version => '1.2.4' + + gem "foo" + G + + bundle "platform", :exitstatus => true + + expect(exitstatus).not_to eq(0) + end + + it "raises an error if engine version doesn't match ruby version for MRI" do + gemfile <<-G + source "file://#{gem_repo1}" + ruby "1.8.7", :engine => 'ruby', :engine_version => '1.2.4' + + gem "foo" + G + + bundle "platform", :exitstatus => true + + expect(exitstatus).not_to eq(0) + end + + it "should print if no ruby version is specified" do + gemfile <<-G + source "file://#{gem_repo1}" + + gem "foo" + G + + bundle "platform --ruby" + puts err + + expect(out).to eq("No ruby version specified") + end + end + + let(:ruby_version_correct) { "ruby \"#{RUBY_VERSION}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{local_engine_version}\"" } + let(:ruby_version_correct_engineless) { "ruby \"#{RUBY_VERSION}\"" } + let(:ruby_version_correct_patchlevel) { "#{ruby_version_correct}, :patchlevel => '#{RUBY_PATCHLEVEL}'" } + let(:ruby_version_incorrect) { "ruby \"#{not_local_ruby_version}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{not_local_ruby_version}\"" } + let(:engine_incorrect) { "ruby \"#{RUBY_VERSION}\", :engine => \"#{not_local_tag}\", :engine_version => \"#{RUBY_VERSION}\"" } + let(:engine_version_incorrect) { "ruby \"#{RUBY_VERSION}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{not_local_engine_version}\"" } + 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] + 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] + 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] + 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] + + 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] + + expect(out).to be_include("The Ruby patchlevel in your Gemfile must be a string") + end + + context "bundle install" do + it "installs fine when the ruby version matches" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + + #{ruby_version_correct} + G + + expect(bundled_app('Gemfile.lock')).to exist + end + + it "installs fine with any engine" do + simulate_ruby_engine "jruby" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + + #{ruby_version_correct_engineless} + G + + expect(bundled_app('Gemfile.lock')).to exist + end + end + + it "installs fine when the patchlevel matches" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + + #{ruby_version_correct_patchlevel} + G + + expect(bundled_app('Gemfile.lock')).to exist + end + + it "doesn't install when the ruby version doesn't match" do + install_gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + gem "rack" + + #{ruby_version_incorrect} + G + + expect(bundled_app('Gemfile.lock')).not_to exist + should_be_ruby_version_incorrect + end + + it "doesn't install when engine doesn't match" do + install_gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + gem "rack" + + #{engine_incorrect} + G + + expect(bundled_app('Gemfile.lock')).not_to exist + should_be_engine_incorrect + end + + it "doesn't install when engine version doesn't match" do + simulate_ruby_engine "jruby" do + install_gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + gem "rack" + + #{engine_version_incorrect} + G + + expect(bundled_app('Gemfile.lock')).not_to exist + should_be_engine_version_incorrect + end + end + + it "doesn't install when patchlevel doesn't match" do + install_gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + gem "rack" + + #{patchlevel_incorrect} + G + + expect(bundled_app('Gemfile.lock')).not_to exist + should_be_patchlevel_incorrect + end + end + + context "bundle check" do + it "checks fine when the ruby version matches" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + + #{ruby_version_correct} + G + + bundle :check, :exitstatus => true + expect(exitstatus).to eq(0) + expect(out).to eq("The Gemfile's dependencies are satisfied") + end + + it "checks fine with any engine" do + simulate_ruby_engine "jruby" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + + #{ruby_version_correct_engineless} + G + + bundle :check, :exitstatus => true + expect(exitstatus).to eq(0) + expect(out).to eq("The Gemfile's dependencies are satisfied") + end + end + + it "fails when ruby version doesn't match" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + + #{ruby_version_incorrect} + G + + bundle :check, :exitstatus => true + should_be_ruby_version_incorrect + end + + it "fails when engine doesn't match" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + + #{engine_incorrect} + G + + bundle :check, :exitstatus => true + should_be_engine_incorrect + end + + it "fails when engine version doesn't match" do + simulate_ruby_engine "ruby" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + + #{engine_version_incorrect} + G + + bundle :check, :exitstatus => true + should_be_engine_version_incorrect + end + end + + it "fails when patchlevel doesn't match" do + install_gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + gem "rack" + G + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + + #{patchlevel_incorrect} + G + + bundle :check, :exitstatus => true + should_be_patchlevel_incorrect + end + end + + context "bundle update" do + before do + build_repo2 + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport" + gem "rack-obama" + G + end + + it "updates successfully when the ruby version matches" do + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport" + gem "rack-obama" + + #{ruby_version_correct} + G + update_repo2 do + build_gem "activesupport", "3.0" + end + + bundle "update" + should_be_installed "rack 1.2", "rack-obama 1.0", "activesupport 3.0" + end + + it "updates fine with any engine" do + simulate_ruby_engine "jruby" do + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport" + gem "rack-obama" + + #{ruby_version_correct_engineless} + G + update_repo2 do + build_gem "activesupport", "3.0" + end + + bundle "update" + should_be_installed "rack 1.2", "rack-obama 1.0", "activesupport 3.0" + end + end + + it "fails when ruby version doesn't match" do + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport" + gem "rack-obama" + + #{ruby_version_incorrect} + G + update_repo2 do + build_gem "activesupport", "3.0" + end + + bundle :update, :exitstatus => true + should_be_ruby_version_incorrect + end + + it "fails when ruby engine doesn't match" do + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport" + gem "rack-obama" + + #{engine_incorrect} + G + update_repo2 do + build_gem "activesupport", "3.0" + end + + bundle :update, :exitstatus => true + should_be_engine_incorrect + end + + it "fails when ruby engine version doesn't match" do + simulate_ruby_engine "jruby" do + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport" + gem "rack-obama" + + #{engine_version_incorrect} + G + update_repo2 do + build_gem "activesupport", "3.0" + end + + bundle :update, :exitstatus => true + should_be_engine_version_incorrect + end + end + + it "fails when patchlevel doesn't match" do + gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + gem "rack" + + #{patchlevel_incorrect} + G + update_repo2 do + build_gem "activesupport", "3.0" + end + + bundle :update, :exitstatus => true + should_be_patchlevel_incorrect + end + end + + context "bundle show" do + before do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + G + end + + it "prints path if ruby version is correct" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + + #{ruby_version_correct} + G + + bundle "show rails" + expect(out).to eq(default_bundle_path('gems', 'rails-2.3.2').to_s) + end + + it "prints path if ruby version is correct for any engine" do + simulate_ruby_engine "jruby" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + + #{ruby_version_correct_engineless} + G + + bundle "show rails" + expect(out).to eq(default_bundle_path('gems', 'rails-2.3.2').to_s) + end + end + + it "fails if ruby version doesn't match" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + + #{ruby_version_incorrect} + G + + bundle "show rails", :exitstatus => true + should_be_ruby_version_incorrect + end + + it "fails if engine doesn't match" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + + #{engine_incorrect} + G + + bundle "show rails", :exitstatus => true + should_be_engine_incorrect + end + + it "fails if engine version doesn't match" do + simulate_ruby_engine "jruby" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + + #{engine_version_incorrect} + G + + bundle "show rails", :exitstatus => true + should_be_engine_version_incorrect + end + end + + it "fails when patchlevel doesn't match" do + gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + gem "rack" + + #{patchlevel_incorrect} + G + update_repo2 do + build_gem "activesupport", "3.0" + end + + bundle "show rails", :exitstatus => true + should_be_patchlevel_incorrect + end + end + + context "bundle cache" do + before do + gemfile <<-G + gem 'rack' + G + + system_gems "rack-1.0.0" + end + + it "copies the .gem file to vendor/cache when ruby version matches" do + gemfile <<-G + gem 'rack' + + #{ruby_version_correct} + G + + bundle :cache + expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist + end + + it "copies the .gem file to vendor/cache when ruby version matches for any engine" do + simulate_ruby_engine "jruby" do + gemfile <<-G + gem 'rack' + + #{ruby_version_correct_engineless} + G + + bundle :cache + expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist + end + end + + it "fails if the ruby version doesn't match" do + gemfile <<-G + gem 'rack' + + #{ruby_version_incorrect} + G + + bundle :cache, :exitstatus => true + should_be_ruby_version_incorrect + end + + it "fails if the engine doesn't match" do + gemfile <<-G + gem 'rack' + + #{engine_incorrect} + G + + bundle :cache, :exitstatus => true + should_be_engine_incorrect + end + + it "fails if the engine version doesn't match" do + simulate_ruby_engine "jruby" do + gemfile <<-G + gem 'rack' + + #{engine_version_incorrect} + G + + bundle :cache, :exitstatus => true + should_be_engine_version_incorrect + end + end + + it "fails when patchlevel doesn't match" do + gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + gem "rack" + + #{patchlevel_incorrect} + G + + bundle :cache, :exitstatus => true + should_be_patchlevel_incorrect + end + end + + context "bundle pack" do + before do + gemfile <<-G + gem 'rack' + G + + system_gems "rack-1.0.0" + end + + it "copies the .gem file to vendor/cache when ruby version matches" do + gemfile <<-G + gem 'rack' + + #{ruby_version_correct} + G + + bundle :pack + expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist + end + + it "copies the .gem file to vendor/cache when ruby version matches any engine" do + simulate_ruby_engine "jruby" do + gemfile <<-G + gem 'rack' + + #{ruby_version_correct_engineless} + G + + bundle :pack + expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist + end + end + + it "fails if the ruby version doesn't match" do + gemfile <<-G + gem 'rack' + + #{ruby_version_incorrect} + G + + bundle :pack, :exitstatus => true + should_be_ruby_version_incorrect + end + + it "fails if the engine doesn't match" do + gemfile <<-G + gem 'rack' + + #{engine_incorrect} + G + + bundle :pack, :exitstatus => true + should_be_engine_incorrect + end + + it "fails if the engine version doesn't match" do + simulate_ruby_engine "jruby" do + gemfile <<-G + gem 'rack' + + #{engine_version_incorrect} + G + + bundle :pack, :exitstatus => true + should_be_engine_version_incorrect + end + end + + it "fails when patchlevel doesn't match" do + gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + gem "rack" + + #{patchlevel_incorrect} + G + + bundle :pack, :exitstatus => true + should_be_patchlevel_incorrect + end + end + + context "bundle exec" do + before do + system_gems "rack-1.0.0", "rack-0.9.1" + end + + it "activates the correct gem when ruby version matches" do + gemfile <<-G + gem "rack", "0.9.1" + + #{ruby_version_correct} + G + + bundle "exec rackup" + expect(out).to eq("0.9.1") + end + + it "activates the correct gem when ruby version matches any engine" do + simulate_ruby_engine "jruby" do + gemfile <<-G + gem "rack", "0.9.1" + + #{ruby_version_correct_engineless} + G + + bundle "exec rackup" + expect(out).to eq("0.9.1") + end + end + + it "fails when the ruby version doesn't match" do + gemfile <<-G + gem "rack", "0.9.1" + + #{ruby_version_incorrect} + G + + bundle "exec rackup", :exitstatus => true + should_be_ruby_version_incorrect + end + + it "fails when the engine doesn't match" do + gemfile <<-G + gem "rack", "0.9.1" + + #{engine_incorrect} + G + + bundle "exec rackup", :exitstatus => true + 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 patchlevel doesn't match" do + gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + gem "rack" + + #{patchlevel_incorrect} + G + + bundle "exec rackup", :exitstatus => true + should_be_patchlevel_incorrect + end + end + + context "bundle console" do + before do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "activesupport", :group => :test + gem "rack_middleware", :group => :development + G + end + + it "starts IRB with the default group loaded when ruby version matches" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "activesupport", :group => :test + gem "rack_middleware", :group => :development + + #{ruby_version_correct} + G + + bundle "console" do |input| + input.puts("puts RACK") + input.puts("exit") + end + expect(out).to include("0.9.1") + end + + it "starts IRB with the default group loaded when ruby version matches any engine" do + simulate_ruby_engine "jruby" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "activesupport", :group => :test + gem "rack_middleware", :group => :development + + #{ruby_version_correct_engineless} + G + + bundle "console" do |input| + input.puts("puts RACK") + input.puts("exit") + end + expect(out).to include("0.9.1") + end + end + + it "fails when ruby version doesn't match" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "activesupport", :group => :test + gem "rack_middleware", :group => :development + + #{ruby_version_incorrect} + G + + bundle "console", :exitstatus => true + should_be_ruby_version_incorrect + end + + it "fails when engine doesn't match" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "activesupport", :group => :test + gem "rack_middleware", :group => :development + + #{engine_incorrect} + G + + bundle "console", :exitstatus => true + should_be_engine_incorrect + end + + it "fails when engine version doesn't match" do + simulate_ruby_engine "jruby" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "activesupport", :group => :test + gem "rack_middleware", :group => :development + + #{engine_version_incorrect} + G + + bundle "console", :exitstatus => true + should_be_engine_version_incorrect + end + end + + it "fails when patchlevel doesn't match" do + gemfile <<-G, :exitstatus => true + source "file://#{gem_repo1}" + gem "rack" + gem "activesupport", :group => :test + gem "rack_middleware", :group => :development + + #{patchlevel_incorrect} + G + + bundle "console", :exitstatus => true + should_be_patchlevel_incorrect + end + end + + context "Bundler.setup" do + before do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "yard" + gem "rack", :group => :test + G + end + + it "makes a Gemfile.lock if setup succeeds" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "yard" + gem "rack" + + #{ruby_version_correct} + G + + File.read(bundled_app("Gemfile.lock")) + + FileUtils.rm(bundled_app("Gemfile.lock")) + + run "1" + expect(bundled_app("Gemfile.lock")).to exist + end + + it "makes a Gemfile.lock if setup succeeds for any engine" do + simulate_ruby_engine "jruby" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "yard" + gem "rack" + + #{ruby_version_correct_engineless} + G + + File.read(bundled_app("Gemfile.lock")) + + FileUtils.rm(bundled_app("Gemfile.lock")) + + run "1" + expect(bundled_app("Gemfile.lock")).to exist + end + end + + it "fails when ruby version doesn't match" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "yard" + gem "rack" + + #{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 + R + + expect(bundled_app("Gemfile.lock")).not_to exist + should_be_ruby_version_incorrect(:exitstatus => false) + end + + it "fails when engine doesn't match" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "yard" + gem "rack" + + #{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 + R + + expect(bundled_app("Gemfile.lock")).not_to exist + should_be_engine_incorrect(:exitstatus => false) + end + + it "fails when engine version doesn't match" do + simulate_ruby_engine "jruby" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "yard" + gem "rack" + + #{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 + R + + expect(bundled_app("Gemfile.lock")).not_to exist + should_be_engine_version_incorrect(:exitstatus => false) + end + end + + it "fails when patchlevel doesn't match" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "yard" + gem "rack" + + #{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 + R + + expect(bundled_app("Gemfile.lock")).not_to exist + should_be_patchlevel_incorrect(:exitstatus => false) + end + end + + context "bundle outdated" do + before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + end + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport", "2.3.5" + gem "foo", :git => "#{lib_path('foo')}" + G + end + + it "returns list of outdated gems when the ruby version matches" do + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end + + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport", "2.3.5" + gem "foo", :git => "#{lib_path('foo')}" + + #{ruby_version_correct} + G + + bundle "outdated" + expect(out).to include("activesupport (3.0 > 2.3.5)") + expect(out).to include("foo (1.0") + end + + it "returns list of outdated gems when the ruby version matches for any engine" do + simulate_ruby_engine "jruby" do + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end + + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport", "2.3.5" + gem "foo", :git => "#{lib_path('foo')}" + + #{ruby_version_correct_engineless} + G + + bundle "outdated" + expect(out).to include("activesupport (3.0 > 2.3.5)") + expect(out).to include("foo (1.0") + end + end + + it "fails when the ruby version doesn't match" do + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end + + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport", "2.3.5" + gem "foo", :git => "#{lib_path('foo')}" + + #{ruby_version_incorrect} + G + + bundle "outdated", :exitstatus => true + should_be_ruby_version_incorrect + end + + it "fails when the engine doesn't match" do + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end + + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport", "2.3.5" + gem "foo", :git => "#{lib_path('foo')}" + + #{engine_incorrect} + G + + bundle "outdated", :exitstatus => true + should_be_engine_incorrect + end + + it "fails when the engine version doesn't match" do + simulate_ruby_engine "jruby" do + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end + + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport", "2.3.5" + gem "foo", :git => "#{lib_path('foo')}" + + #{engine_version_incorrect} + G + + bundle "outdated", :exitstatus => true + should_be_engine_version_incorrect + end + end + + it "fails when the patchlevel doesn't match" do + simulate_ruby_engine "jruby" do + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end + + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport", "2.3.5" + gem "foo", :git => "#{lib_path('foo')}" + + #{patchlevel_incorrect} + G + + bundle "outdated", :exitstatus => true + should_be_patchlevel_incorrect + end + end + + it "fails when the patchlevel is a fixnum" do + simulate_ruby_engine "jruby" do + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end + + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport", "2.3.5" + gem "foo", :git => "#{lib_path('foo')}" + + #{patchlevel_fixnum} + G + + bundle "outdated", :exitstatus => true + should_be_patchlevel_fixnum + end + end + end +end diff --git a/bundler-1.7.2/spec/other/ssl_cert_spec.rb b/bundler-1.7.2/spec/other/ssl_cert_spec.rb new file mode 100644 index 0000000..ac9283a --- /dev/null +++ b/bundler-1.7.2/spec/other/ssl_cert_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'bundler/ssl_certs/certificate_manager' + +describe "SSL Certificates", :if => (ENV['RGV'] == "master") do + it "are up to date with Rubygems" do + rubygems = File.expand_path("../../../tmp/rubygems", __FILE__) + manager = Bundler::SSLCerts::CertificateManager.new(rubygems) + expect(manager).to be_up_to_date + end +end diff --git a/bundler-1.7.2/spec/quality_spec.rb b/bundler-1.7.2/spec/quality_spec.rb new file mode 100644 index 0000000..59a8520 --- /dev/null +++ b/bundler-1.7.2/spec/quality_spec.rb @@ -0,0 +1,88 @@ +require "spec_helper" + +if defined?(Encoding) && Encoding.default_external != "UTF-8" + Encoding.default_external = "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| + failing_lines << number + 1 if line =~ /^ *(describe|it|context) {1}'{1}/ + end + + unless failing_lines.empty? + "#{filename} uses inconsistent single quotes on lines #{failing_lines.join(', ')}" + end + end + + def check_for_tab_characters(filename) + failing_lines = [] + File.readlines(filename).each_with_index do |line,number| + failing_lines << number + 1 if line =~ /\t/ + end + + unless failing_lines.empty? + "#{filename} has tab characters on lines #{failing_lines.join(', ')}" + end + end + + def check_for_extra_spaces(filename) + failing_lines = [] + 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$/ + end + + unless failing_lines.empty? + "#{filename} has spaces on the EOL on lines #{failing_lines.join(', ')}" + end + end + + RSpec::Matchers.define :be_well_formed do + match do |actual| + actual.empty? + end + + failure_message do |actual| + actual.join("\n") + end + end + + it "has no malformed whitespace" do + exempt = /\.gitmodules|\.marshal|fixtures|vendor|ssl_certs|LICENSE/ + error_messages = [] + Dir.chdir(File.expand_path("../..", __FILE__)) do + `git ls-files -z`.split("\x0").each do |filename| + next if filename =~ exempt + error_messages << check_for_tab_characters(filename) + error_messages << check_for_extra_spaces(filename) + end + end + expect(error_messages.compact).to be_well_formed + end + + it "uses double-quotes consistently in specs" do + included = /spec/ + error_messages = [] + Dir.chdir(File.expand_path("../", __FILE__)) do + `git ls-files -z`.split("\x0").each do |filename| + next unless filename =~ included + error_messages << check_for_spec_defs_with_single_quotes(filename) + end + end + expect(error_messages.compact).to be_well_formed + end + + it "can still be built" do + Dir.chdir(root) do + `gem build bundler.gemspec` + expect($?).to eq(0) + + # clean up the .gem generated + system("rm bundler-#{Bundler::VERSION}.gem") + end + end +end diff --git a/bundler-1.7.2/spec/realworld/dependency_api_spec.rb b/bundler-1.7.2/spec/realworld/dependency_api_spec.rb new file mode 100644 index 0000000..5d32947 --- /dev/null +++ b/bundler-1.7.2/spec/realworld/dependency_api_spec.rb @@ -0,0 +1,60 @@ +require "spec_helper" + +describe "gemcutter's dependency API", :realworld => true do + def wait_for_server(port, seconds = 15) + tries = 0 + TCPSocket.new("127.0.0.1", port) + rescue => e + raise(e) if tries > (seconds * 2) + tries += 1 + sleep 0.5 + retry + end + + context "when Gemcutter API takes too long to respond" do + before do + # need to hack, so we can require rack + old_gem_home = ENV['GEM_HOME'] + ENV['GEM_HOME'] = Spec::Path.base_system_gems.to_s + require 'rack' + ENV['GEM_HOME'] = old_gem_home + + port = 21453 + port += 1 while TCPSocket.new("127.0.0.1", port) rescue false + @server_uri = "http://127.0.0.1:#{port}" + + require File.expand_path('../../support/artifice/endpoint_timeout', __FILE__) + require 'thread' + @t = Thread.new { + server = Rack::Server.start(:app => EndpointTimeout, + :Host => '0.0.0.0', + :Port => port, + :server => 'webrick', + :AccessLog => []) + server.start + } + @t.run + + wait_for_server(port) + end + + after do + @t.kill + end + + it "times out and falls back on the modern index" do + gemfile <<-G + source "#{@server_uri}" + gem "rack" + + old_v, $VERBOSE = $VERBOSE, nil + Bundler::Fetcher.api_timeout = 1 + $VERBOSE = old_v + G + + bundle :install + expect(out).to include("Fetching source index from #{@server_uri}/") + should_be_installed "rack 1.0.0" + end + end +end diff --git a/bundler-1.7.2/spec/realworld/edgecases_spec.rb b/bundler-1.7.2/spec/realworld/edgecases_spec.rb new file mode 100644 index 0000000..263ac52 --- /dev/null +++ b/bundler-1.7.2/spec/realworld/edgecases_spec.rb @@ -0,0 +1,177 @@ +require 'spec_helper' + +describe "real world edgecases", :realworld => true do + # there is no rbx-relative-require gem that will install on 1.9 + it "ignores extra gems with bad platforms", :ruby => "1.8" do + install_gemfile <<-G + source :rubygems + gem "linecache", "0.46" + G + expect(err).to eq("") + end + + # https://github.com/bundler/bundler/issues/1202 + it "bundle cache works with rubygems 1.3.7 and pre gems", :ruby => "1.8" do + install_gemfile <<-G + source :rubygems + gem "rack", "1.3.0.beta2" + gem "will_paginate", "3.0.pre2" + G + bundle :cache + expect(out).not_to include("Removing outdated .gem files from vendor/cache") + end + + # https://github.com/bundler/bundler/issues/1486 + # this is a hash collision that only manifests on 1.8.7 + it "finds the correct child versions", :ruby => "1.8" do + install_gemfile <<-G + source :rubygems + + gem 'i18n', '~> 0.4' + gem 'activesupport', '~> 3.0' + gem 'activerecord', '~> 3.0' + gem 'builder', '~> 2.1.2' + G + expect(out).to include("activemodel 3.0.5") + end + + # https://github.com/bundler/bundler/issues/1500 + it "does not fail install because of gem plugins" do + realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2") + gemfile <<-G + source :rubygems + + gem 'rack', '1.0.1' + G + + bundle "install --path vendor/bundle", :expect_err => true + expect(err).not_to include("Could not find rake") + expect(err).to be_empty + end + + it "checks out git repos when the lockfile is corrupted" do + gemfile <<-G + source :rubygems + + gem 'activerecord', :github => 'carlhuda/rails-bundler-test', :branch => 'master' + gem 'activesupport', :github => 'carlhuda/rails-bundler-test', :branch => 'master' + gem 'actionpack', :github => 'carlhuda/rails-bundler-test', :branch => 'master' + G + + lockfile <<-L + GIT + remote: git://github.com/carlhuda/rails-bundler-test.git + revision: 369e28a87419565f1940815219ea9200474589d4 + branch: master + specs: + actionpack (3.2.2) + activemodel (= 3.2.2) + activesupport (= 3.2.2) + builder (~> 3.0.0) + erubis (~> 2.7.0) + journey (~> 1.0.1) + rack (~> 1.4.0) + rack-cache (~> 1.2) + rack-test (~> 0.6.1) + sprockets (~> 2.1.2) + activemodel (3.2.2) + activesupport (= 3.2.2) + builder (~> 3.0.0) + activerecord (3.2.2) + activemodel (= 3.2.2) + activesupport (= 3.2.2) + arel (~> 3.0.2) + tzinfo (~> 0.3.29) + activesupport (3.2.2) + i18n (~> 0.6) + multi_json (~> 1.0) + + GIT + remote: git://github.com/carlhuda/rails-bundler-test.git + revision: 369e28a87419565f1940815219ea9200474589d4 + branch: master + specs: + actionpack (3.2.2) + activemodel (= 3.2.2) + activesupport (= 3.2.2) + builder (~> 3.0.0) + erubis (~> 2.7.0) + journey (~> 1.0.1) + rack (~> 1.4.0) + rack-cache (~> 1.2) + rack-test (~> 0.6.1) + sprockets (~> 2.1.2) + activemodel (3.2.2) + activesupport (= 3.2.2) + builder (~> 3.0.0) + activerecord (3.2.2) + activemodel (= 3.2.2) + activesupport (= 3.2.2) + arel (~> 3.0.2) + tzinfo (~> 0.3.29) + activesupport (3.2.2) + i18n (~> 0.6) + multi_json (~> 1.0) + + GIT + remote: git://github.com/carlhuda/rails-bundler-test.git + revision: 369e28a87419565f1940815219ea9200474589d4 + branch: master + specs: + actionpack (3.2.2) + activemodel (= 3.2.2) + activesupport (= 3.2.2) + builder (~> 3.0.0) + erubis (~> 2.7.0) + journey (~> 1.0.1) + rack (~> 1.4.0) + rack-cache (~> 1.2) + rack-test (~> 0.6.1) + sprockets (~> 2.1.2) + activemodel (3.2.2) + activesupport (= 3.2.2) + builder (~> 3.0.0) + activerecord (3.2.2) + activemodel (= 3.2.2) + activesupport (= 3.2.2) + arel (~> 3.0.2) + tzinfo (~> 0.3.29) + activesupport (3.2.2) + i18n (~> 0.6) + multi_json (~> 1.0) + + GEM + remote: https://rubygems.org/ + specs: + arel (3.0.2) + builder (3.0.0) + erubis (2.7.0) + hike (1.2.1) + i18n (0.6.0) + journey (1.0.3) + multi_json (1.1.0) + rack (1.4.1) + rack-cache (1.2) + rack (>= 0.4) + rack-test (0.6.1) + rack (>= 1.0) + sprockets (2.1.2) + hike (~> 1.2) + rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) + tilt (1.3.3) + tzinfo (0.3.32) + + PLATFORMS + ruby + + DEPENDENCIES + actionpack! + activerecord! + activesupport! + L + + bundle :install, :exitstatus => true + expect(exitstatus).to eq(0) + end +end diff --git a/bundler-1.7.2/spec/realworld/parallel_spec.rb b/bundler-1.7.2/spec/realworld/parallel_spec.rb new file mode 100644 index 0000000..457139b --- /dev/null +++ b/bundler-1.7.2/spec/realworld/parallel_spec.rb @@ -0,0 +1,69 @@ +require 'spec_helper' + +describe "parallel", :realworld => true do + it "installs", :ruby => "1.8" do + gemfile <<-G + source "https://rubygems.org" + gem 'activesupport', '~> 3.2.13' + gem 'faker', '~> 1.1.2' + G + + bundle :install, :jobs => 4, :env => {"DEBUG" => "1"} + expect(out).to match(/[1-3]: /) + + bundle "show activesupport" + expect(out).to match(/activesupport/) + + bundle "show faker" + expect(out).to match(/faker/) + + bundle "config jobs" + expect(out).to match(/: "4"/) + end + + it "installs even with circular dependency", :ruby => "1.9" do + gemfile <<-G + source 'https://rubygems.org' + gem 'activesupport', '~> 3.2.13' + gem 'mongoid_auto_increment', "0.1.1" + G + + bundle :install, :jobs => 4, :env => {"DEBUG" => "1"} + expect(out).to match(/[1-3]: /) + + bundle "show activesupport" + expect(out).to match(/activesupport/) + + bundle "show mongoid_auto_increment" + expect(out).to match(%r{gems/mongoid_auto_increment}) + + bundle "config jobs" + expect(out).to match(/: "4"/) + end + + it "updates" do + install_gemfile <<-G + source "https://rubygems.org" + gem 'activesupport', '3.2.12' + gem 'faker', '~> 1.1.2' + G + + gemfile <<-G + source "https://rubygems.org" + gem 'activesupport', '~> 3.2.12' + gem 'faker', '~> 1.1.2' + G + + bundle :update, :jobs => 4, :env => {"DEBUG" => "1"} + expect(out).to match(/[1-3]: /) + + bundle "show activesupport" + expect(out).to match(/activesupport-3\.2\.1[3-9]/) + + bundle "show faker" + expect(out).to match(/faker/) + + bundle "config jobs" + expect(out).to match(/: "4"/) + end +end diff --git a/bundler-1.7.2/spec/resolver/basic_spec.rb b/bundler-1.7.2/spec/resolver/basic_spec.rb new file mode 100644 index 0000000..e588c9e --- /dev/null +++ b/bundler-1.7.2/spec/resolver/basic_spec.rb @@ -0,0 +1,66 @@ +require "spec_helper" + +describe "Resolving" do + + before :each do + @index = an_awesome_index + end + + it "resolves a single gem" do + dep "rack" + + should_resolve_as %w(rack-1.1) + end + + it "resolves a gem with dependencies" do + dep "actionpack" + + should_resolve_as %w(actionpack-2.3.5 activesupport-2.3.5 rack-1.0) + end + + it "resolves a conflicting index" do + @index = a_conflict_index + dep "my_app" + should_resolve_as %w(activemodel-3.2.11 builder-3.0.4 grape-0.2.6 my_app-1.0.0) + end + + it "resolves a complex conflicting index" do + @index = a_complex_conflict_index + dep "my_app" + should_resolve_as %w(a-1.4.0 b-0.3.5 c-3.2 d-0.9.8 my_app-1.1.0) + end + + it "resolves a index with conflict on child" do + @index = index_with_conflict_on_child + dep "chef_app" + should_resolve_as %w(berkshelf-2.0.7 chef-10.26 chef_app-1.0.0 json-1.7.7) + end + + it "resolves a index with root level conflict on child" do + @index = a_index_with_root_conflict_on_child + dep "i18n", "~> 0.4" + dep "activesupport", "~> 3.0" + dep "activerecord", "~> 3.0" + dep "builder", "~> 2.1.2" + should_resolve_as %w(activesupport-3.0.5 i18n-0.4.2 builder-2.1.2 activerecord-3.0.5 activemodel-3.0.5) + end + + it "raises an exception if a child dependency is not resolved" do + @index = a_unresovable_child_index + dep "chef_app_error" + expect { + resolve + }.to raise_error(Bundler::VersionConflict) + end + + it "should throw error in case of circular dependencies" do + @index = a_circular_index + dep "circular_app" + + got = resolve + expect { + got = got.map { |s| s.full_name }.sort + }.to raise_error(Bundler::CyclicDependencyError, /please remove either gem 'foo' or gem 'bar'/i) + end + +end diff --git a/bundler-1.7.2/spec/resolver/platform_spec.rb b/bundler-1.7.2/spec/resolver/platform_spec.rb new file mode 100644 index 0000000..2a126e4 --- /dev/null +++ b/bundler-1.7.2/spec/resolver/platform_spec.rb @@ -0,0 +1,88 @@ +require "spec_helper" + +describe "Resolving platform craziness" do + describe "with cross-platform gems" do + before :each do + @index = an_awesome_index + end + + it "resolves a simple multi platform gem" do + dep "nokogiri" + platforms "ruby", "java" + + should_resolve_as %w(nokogiri-1.4.2 nokogiri-1.4.2-java weakling-0.0.3) + end + + it "doesn't pull gems that don't exist for the current platform" do + dep "nokogiri" + platforms "ruby" + + should_resolve_as %w(nokogiri-1.4.2) + end + + it "doesn't pull gems when the version is available for all requested platforms" do + dep "nokogiri" + platforms "mswin32" + + should_resolve_as %w(nokogiri-1.4.2.1-x86-mswin32) + end + end + + describe "with mingw32" do + + before :each do + @index = build_index do + platforms "mingw32 mswin32 x64-mingw32" do |platform| + gem "thin", "1.2.7", platform + end + end + end + + it "finds mswin gems" do + # win32 is hardcoded to get CPU x86 in rubygems + platforms "mswin32" + dep "thin" + should_resolve_as %w(thin-1.2.7-x86-mswin32) + end + + it "finds mingw gems" do + # mingw is _not_ hardcoded to add CPU x86 in rubygems + platforms "x86-mingw32" + dep "thin" + should_resolve_as %w(thin-1.2.7-x86-mingw32) + end + + it "finds x64-mingw gems" do + platforms "x64-mingw32" + dep "thin" + should_resolve_as %w(thin-1.2.7-x64-mingw32) + end + end + + describe "with conflicting cases" do + before :each do + @index = build_index do + gem "foo", "1.0.0" do + dep "bar", ">= 0" + end + + gem 'bar', "1.0.0" do + dep "baz", "~> 1.0.0" + end + + gem "bar", "1.0.0", "java" do + dep "baz", " ~> 1.1.0" + end + + gem "baz", %w(1.0.0 1.1.0 1.2.0) + end + end + + it "reports on the conflict" do + platforms "ruby", "java" + dep "foo" + + should_conflict_on "baz" + end + end +end diff --git a/bundler-1.7.2/spec/runtime/executable_spec.rb b/bundler-1.7.2/spec/runtime/executable_spec.rb new file mode 100644 index 0000000..ad43c05 --- /dev/null +++ b/bundler-1.7.2/spec/runtime/executable_spec.rb @@ -0,0 +1,149 @@ +require "spec_helper" + +describe "Running bin/* commands" do + before :each do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + end + + it "runs the bundled command when in the bundle" do + bundle "install --binstubs" + + build_gem "rack", "2.0", :to_system => true do |s| + s.executables = "rackup" + end + + gembin "rackup" + expect(out).to eq("1.0.0") + end + + it "allows the location of the gem stubs to be specified" do + bundle "install --binstubs gbin" + + expect(bundled_app("bin")).not_to exist + expect(bundled_app("gbin/rackup")).to exist + + gembin bundled_app("gbin/rackup") + expect(out).to eq("1.0.0") + end + + it "allows absolute paths as a specification of where to install bin stubs" do + bundle "install --binstubs #{tmp}/bin" + + gembin tmp("bin/rackup") + expect(out).to eq("1.0.0") + end + + it "uses the default ruby install name when shebang is not specified" do + bundle "install --binstubs" + expect(File.open("bin/rackup").gets).to eq("#!/usr/bin/env #{RbConfig::CONFIG['ruby_install_name']}\n") + end + + it "allows the name of the shebang executable to be specified" do + bundle "install --binstubs --shebang ruby-foo" + expect(File.open("bin/rackup").gets).to eq("#!/usr/bin/env ruby-foo\n") + end + + it "runs the bundled command when out of the bundle" do + bundle "install --binstubs" + + build_gem "rack", "2.0", :to_system => true do |s| + s.executables = "rackup" + end + + Dir.chdir(tmp) do + gembin "rackup" + expect(out).to eq("1.0.0") + end + end + + it "works with gems in path" do + build_lib "rack", :path => lib_path("rack") do |s| + s.executables = 'rackup' + end + + gemfile <<-G + gem "rack", :path => "#{lib_path('rack')}" + G + + bundle "install --binstubs" + + build_gem 'rack', '2.0', :to_system => true do |s| + s.executables = 'rackup' + end + + gembin "rackup" + expect(out).to eq('1.0') + end + + it "don't bundle da bundla" do + build_gem "bundler", Bundler::VERSION, :to_system => true do |s| + s.executables = "bundle" + end + + gemfile <<-G + source "file://#{gem_repo1}" + gem "bundler" + G + + bundle "install --binstubs" + + expect(bundled_app("bin/bundle")).not_to exist + end + + it "does not generate bin stubs if the option was not specified" do + bundle "install" + + expect(bundled_app("bin/rackup")).not_to exist + end + + it "allows you to stop installing binstubs" do + bundle "install --binstubs bin/" + bundled_app("bin/rackup").rmtree + bundle "install --binstubs \"\"" + + expect(bundled_app("bin/rackup")).not_to exist + #expect(bundled_app("rackup")).not_to exist + + bundle "config bin" + expect(out).to include("You have not configured a value for `bin`") + end + + it "remembers that the option was specified" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "activesupport" + G + + bundle "install --binstubs" + + gemfile <<-G + source "file://#{gem_repo1}" + gem "activesupport" + gem "rack" + G + + bundle "install" + + expect(bundled_app("bin/rackup")).to exist + end + + it "rewrites bins on --binstubs (to maintain backwards compatibility)" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + bundle "install --binstubs bin/" + + File.open(bundled_app("bin/rackup"), 'wb') do |file| + file.print "OMG" + end + + bundle "install" + + expect(bundled_app("bin/rackup").read).to_not eq("OMG") + end +end diff --git a/bundler-1.7.2/spec/runtime/load_spec.rb b/bundler-1.7.2/spec/runtime/load_spec.rb new file mode 100644 index 0000000..cc2cebf --- /dev/null +++ b/bundler-1.7.2/spec/runtime/load_spec.rb @@ -0,0 +1,107 @@ +require "spec_helper" + +describe "Bundler.load" do + before :each do + system_gems "rack-1.0.0" + # clear memoized method results + # TODO: Don't reset internal ivars + Bundler.instance_eval do + @load = nil + @runtime = nil + @definition = nil + end + end + + describe "with a gemfile" do + before(:each) do + gemfile <<-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 + + it "ignores blank BUNDLE_GEMFILEs" do + expect { + ENV['BUNDLE_GEMFILE'] = "" + Bundler.load + }.not_to raise_error() + end + + end + + describe "without a gemfile" do + it "raises an exception if the default gemfile is not found" do + expect { + Bundler.load + }.to raise_error(Bundler::GemfileNotFound, /could not locate gemfile/i) + end + + it "raises an exception if a specified gemfile is not found" do + expect { + ENV['BUNDLE_GEMFILE'] = "omg.rb" + Bundler.load + }.to raise_error(Bundler::GemfileNotFound, /omg\.rb/) + end + + it "does not find a Gemfile above the testing directory" do + bundler_gemfile = tmp.join("../Gemfile") + unless File.exist?(bundler_gemfile) + FileUtils.touch(bundler_gemfile) + @remove_bundler_gemfile = true + end + begin + expect { Bundler.load }.to raise_error(Bundler::GemfileNotFound) + ensure + bundler_gemfile.rmtree if @remove_bundler_gemfile + end + end + + end + + describe "when called twice" do + it "doesn't try to load the runtime twice" do + system_gems "rack-1.0.0", "activesupport-2.3.5" + gemfile <<-G + gem "rack" + gem "activesupport", :group => :test + G + + ruby <<-RUBY + require "bundler" + Bundler.setup :default + Bundler.require :default + puts RACK + begin + require "activesupport" + rescue LoadError + puts "no activesupport" + end + RUBY + + expect(out.split("\n")).to eq(["1.0.0", "no activesupport"]) + end + end + + describe "not hurting brittle rubygems" do + it "does not inject #source into the generated YAML of the gem specs" do + system_gems "activerecord-2.3.2", "activesupport-2.3.2" + gemfile <<-G + gem "activerecord" + G + + Bundler.load.specs.each do |spec| + expect(spec.to_yaml).not_to match(/^\s+source:/) + expect(spec.to_yaml).not_to match(/^\s+groups:/) + end + end + end + +end diff --git a/bundler-1.7.2/spec/runtime/platform_spec.rb b/bundler-1.7.2/spec/runtime/platform_spec.rb new file mode 100644 index 0000000..cbc12ef --- /dev/null +++ b/bundler-1.7.2/spec/runtime/platform_spec.rb @@ -0,0 +1,90 @@ +require "spec_helper" + +describe "Bundler.setup with multi platform stuff" do + it "raises a friendly error when gems are missing locally" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + lockfile <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0) + + PLATFORMS + #{local_tag} + + DEPENDENCIES + rack + G + + ruby <<-R + begin + require 'bundler' + Bundler.setup + rescue Bundler::GemNotFound => e + puts "WIN" + end + R + + expect(out).to eq("WIN") + end + + it "will resolve correctly on the current platform when the lockfile was targetted for a different one" do + lockfile <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + nokogiri (1.4.2-java) + weakling (= 0.0.3) + weakling (0.0.3) + + PLATFORMS + java + + DEPENDENCIES + nokogiri + G + + system_gems "nokogiri-1.4.2" + + simulate_platform "x86-darwin-10" + gemfile <<-G + source "file://#{gem_repo1}" + gem "nokogiri" + G + + should_be_installed "nokogiri 1.4.2" + end + + it "will add the resolve for the current platform" do + lockfile <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + nokogiri (1.4.2-java) + weakling (= 0.0.3) + weakling (0.0.3) + + PLATFORMS + java + + DEPENDENCIES + nokogiri + G + + simulate_platform "x86-darwin-100" + + system_gems "nokogiri-1.4.2", "platform_specific-1.0-x86-darwin-100" + + gemfile <<-G + source "file://#{gem_repo1}" + gem "nokogiri" + gem "platform_specific" + G + + should_be_installed "nokogiri 1.4.2", "platform_specific 1.0 x86-darwin-100" + end +end diff --git a/bundler-1.7.2/spec/runtime/require_spec.rb b/bundler-1.7.2/spec/runtime/require_spec.rb new file mode 100644 index 0000000..e1c9389 --- /dev/null +++ b/bundler-1.7.2/spec/runtime/require_spec.rb @@ -0,0 +1,332 @@ +require "spec_helper" + +describe "Bundler.require" do + before :each do + build_lib "one", "1.0.0" do |s| + s.write "lib/baz.rb", "puts 'baz'" + s.write "lib/qux.rb", "puts 'qux'" + end + + build_lib "two", "1.0.0" do |s| + s.write "lib/two.rb", "puts 'two'" + s.add_dependency "three", "= 1.0.0" + end + + build_lib "three", "1.0.0" do |s| + s.write "lib/three.rb", "puts 'three'" + s.add_dependency "seven", "= 1.0.0" + end + + build_lib "four", "1.0.0" do |s| + s.write "lib/four.rb", "puts 'four'" + end + + build_lib "five", "1.0.0", :no_default => true do |s| + s.write "lib/mofive.rb", "puts 'five'" + end + + build_lib "six", "1.0.0" do |s| + s.write "lib/six.rb", "puts 'six'" + end + + build_lib "seven", "1.0.0" do |s| + s.write "lib/seven.rb", "puts 'seven'" + end + + build_lib "eight", "1.0.0" do |s| + s.write "lib/eight.rb", "puts 'eight'" + end + + gemfile <<-G + path "#{lib_path}" + gem "one", :group => :bar, :require => %w(baz qux) + gem "two" + gem "three", :group => :not + gem "four", :require => false + gem "five" + gem "six", :group => "string" + gem "seven", :group => :not + gem "eight", :require => true, :group => :require_true + G + end + + it "requires the gems" do + # default group + run "Bundler.require" + expect(out).to eq("two") + + # specific group + run "Bundler.require(:bar)" + expect(out).to eq("baz\nqux") + + # default and specific group + run "Bundler.require(:default, :bar)" + expect(out).to eq("baz\nqux\ntwo") + + # specific group given as a string + run "Bundler.require('bar')" + expect(out).to eq("baz\nqux") + + # specific group declared as a string + run "Bundler.require(:string)" + expect(out).to eq("six") + + # required in resolver order instead of gemfile order + run("Bundler.require(:not)") + expect(out.split("\n").sort).to eq(['seven', 'three']) + + # test require: true + run "Bundler.require(:require_true)" + expect(out).to eq("eight") + end + + it "allows requiring gems with non standard names explicitly" do + run "Bundler.require ; require 'mofive'" + expect(out).to eq("two\nfive") + end + + it "raises an exception if a require is specified but the file does not exist" do + gemfile <<-G + path "#{lib_path}" + gem "two", :require => 'fail' + G + + load_error_run <<-R, 'fail' + Bundler.require + R + + expect(err).to eq("ZOMG LOAD ERROR") + end + + describe "with namespaced gems" do + before :each do + build_lib "jquery-rails", "1.0.0" do |s| + s.write "lib/jquery/rails.rb", "puts 'jquery/rails'" + end + lib_path('jquery-rails-1.0.0/lib/jquery-rails.rb').rmtree + end + + it "requires gem names that are namespaced" do + gemfile <<-G + path '#{lib_path}' + gem 'jquery-rails' + G + + run "Bundler.require" + expect(out).to eq("jquery/rails") + end + + it "silently passes if the require fails" do + build_lib "bcrypt-ruby", "1.0.0", :no_default => true do |s| + s.write "lib/brcrypt.rb", "BCrypt = '1.0.0'" + end + gemfile <<-G + path "#{lib_path}" + gem "bcrypt-ruby" + G + + cmd = <<-RUBY + require 'bundler' + Bundler.require + RUBY + ruby(cmd, :expect_err => true) + + expect(err).to be_empty + end + + it "does not mangle explictly given requires" do + gemfile <<-G + path "#{lib_path}" + gem 'jquery-rails', :require => 'jquery-rails' + G + + load_error_run <<-R, 'jquery-rails' + Bundler.require + R + expect(err).to eq("ZOMG LOAD ERROR") + end + + it "handles the case where regex fails" do + build_lib "load-fuuu", "1.0.0" do |s| + s.write "lib/load-fuuu.rb", "raise LoadError.new(\"Could not open library 'libfuuu-1.0': libfuuu-1.0: cannot open shared object file: No such file or directory.\")" + end + + gemfile <<-G + path "#{lib_path}" + gem "load-fuuu" + G + + cmd = <<-RUBY + begin + Bundler.require + rescue LoadError => e + $stderr.puts "ZOMG LOAD ERROR" if e.message.include?("Could not open library 'libfuuu-1.0'") + end + RUBY + run(cmd, :expect_err => true) + + expect(err).to eq("ZOMG LOAD ERROR") + end + + 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\")" + end + + gemfile <<-G + path "#{lib_path}" + gem "load-fuuu" + 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 + end + + describe "using bundle exec" do + it "requires the locked gems" do + bundle "exec ruby -e 'Bundler.require'" + expect(out).to eq("two") + + bundle "exec ruby -e 'Bundler.require(:bar)'" + expect(out).to eq("baz\nqux") + + bundle "exec ruby -e 'Bundler.require(:default, :bar)'" + expect(out).to eq("baz\nqux\ntwo") + end + end + + describe "order" do + before(:each) do + build_lib "one", "1.0.0" do |s| + s.write "lib/one.rb", <<-ONE + if defined?(Two) + Two.two + else + puts "two_not_loaded" + end + puts 'one' + ONE + end + + build_lib "two", "1.0.0" do |s| + s.write "lib/two.rb", <<-TWO + module Two + def self.two + puts 'module_two' + end + end + puts 'two' + TWO + end + end + + it "works when the gems are in the Gemfile in the correct order" do + gemfile <<-G + path "#{lib_path}" + gem "two" + gem "one" + G + + run "Bundler.require" + expect(out).to eq("two\nmodule_two\none") + end + + describe "a gem with different requires for different envs" do + before(:each) do + build_gem "multi_gem", :to_system => true do |s| + s.write "lib/one.rb", "puts 'ONE'" + s.write "lib/two.rb", "puts 'TWO'" + end + + install_gemfile <<-G + gem "multi_gem", :require => "one", :group => :one + gem "multi_gem", :require => "two", :group => :two + G + end + + it "requires both with Bundler.require(both)" do + run "Bundler.require(:one, :two)" + expect(out).to eq("ONE\nTWO") + end + + it "requires one with Bundler.require(:one)" do + run "Bundler.require(:one)" + expect(out).to eq("ONE") + end + + it "requires :two with Bundler.require(:two)" do + run "Bundler.require(:two)" + expect(out).to eq("TWO") + end + end + + it "fails when the gems are in the Gemfile in the wrong order" do + gemfile <<-G + path "#{lib_path}" + gem "one" + gem "two" + G + + run "Bundler.require" + expect(out).to eq("two_not_loaded\none\ntwo") + end + + describe "with busted gems" do + it "should be busted" do + build_gem "busted_require", :to_system => true do |s| + s.write "lib/busted_require.rb", "require 'no_such_file_omg'" + end + + install_gemfile <<-G + gem "busted_require" + G + + load_error_run <<-R, 'no_such_file_omg' + Bundler.require + R + expect(err).to eq('ZOMG LOAD ERROR') + end + end + end +end + +describe "Bundler.require with platform specific dependencies" do + it "does not require the gems that are pinned to other platforms" do + install_gemfile <<-G + source "file://#{gem_repo1}" + + platforms :#{not_local_tag} do + gem "fail", :require => "omgomg" + end + + gem "rack", "1.0.0" + G + + run "Bundler.require", :expect_err => true + expect(err).to be_empty + end + + it "requires gems pinned to multiple platforms, including the current one" do + install_gemfile <<-G + source "file://#{gem_repo1}" + + platforms :#{not_local_tag}, :#{local_tag} do + gem "rack", :require => "rack" + end + G + + run "Bundler.require; puts RACK", :expect_err => true + + expect(out).to eq("1.0.0") + expect(err).to be_empty + end +end diff --git a/bundler-1.7.2/spec/runtime/setup_spec.rb b/bundler-1.7.2/spec/runtime/setup_spec.rb new file mode 100644 index 0000000..02ce0de --- /dev/null +++ b/bundler-1.7.2/spec/runtime/setup_spec.rb @@ -0,0 +1,853 @@ +require "spec_helper" + +describe "Bundler.setup" do + describe "with no arguments" do + it "makes all groups available" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :group => :test + G + + ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup + + require 'rack' + puts RACK + RUBY + expect(err).to eq("") + expect(out).to eq("1.0.0") + end + end + + describe "when called with groups" do + before(:each) do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "yard" + gem "rack", :group => :test + G + end + + it "doesn't make all groups available" do + ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup(:default) + + begin + require 'rack' + rescue LoadError + puts "WIN" + end + RUBY + expect(err).to eq("") + expect(out).to eq("WIN") + end + + it "accepts string for group name" do + ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup(:default, 'test') + + require 'rack' + puts RACK + RUBY + expect(err).to eq("") + expect(out).to eq("1.0.0") + end + + it "leaves all groups available if they were already" do + ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup + Bundler.setup(:default) + + require 'rack' + puts RACK + RUBY + expect(err).to eq("") + expect(out).to eq("1.0.0") + end + + it "leaves :default available if setup is called twice" do + ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup(:default) + Bundler.setup(:default, :test) + + begin + require 'yard' + puts "WIN" + rescue LoadError + puts "FAIL" + end + RUBY + expect(err).to eq("") + expect(out).to match("WIN") + end + end + + it "raises if the Gemfile was not yet installed" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + ruby <<-R + require 'rubygems' + require 'bundler' + + begin + Bundler.setup + puts "FAIL" + rescue Bundler::GemNotFound + puts "WIN" + end + R + + expect(out).to eq("WIN") + end + + it "doesn't create a Gemfile.lock if the setup fails" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + ruby <<-R, :expect_err => true + require 'rubygems' + require 'bundler' + + Bundler.setup + R + + expect(bundled_app("Gemfile.lock")).not_to exist + end + + it "doesn't change the Gemfile.lock if the setup fails" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + lockfile = File.read(bundled_app("Gemfile.lock")) + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "nosuchgem", "10.0" + G + + ruby <<-R, :expect_err => true + require 'rubygems' + require 'bundler' + + Bundler.setup + R + + expect(File.read(bundled_app("Gemfile.lock"))).to eq(lockfile) + end + + it "makes a Gemfile.lock if setup succeeds" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + File.read(bundled_app("Gemfile.lock")) + + FileUtils.rm(bundled_app("Gemfile.lock")) + + run "1" + expect(bundled_app("Gemfile.lock")).to exist + end + + it "uses BUNDLE_GEMFILE to locate the gemfile if present" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + gemfile bundled_app('4realz'), <<-G + source "file://#{gem_repo1}" + gem "activesupport", "2.3.5" + G + + ENV['BUNDLE_GEMFILE'] = bundled_app('4realz').to_s + bundle :install + + should_be_installed "activesupport 2.3.5" + end + + it "prioritizes gems in BUNDLE_PATH over gems in GEM_HOME" do + ENV['BUNDLE_PATH'] = bundled_app('.bundle').to_s + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "1.0.0" + G + + build_gem "rack", "1.0", :to_system => true do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" + end + + should_be_installed "rack 1.0.0" + end + + describe "integrate with rubygems" do + describe "by replacing #gem" do + before :each do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "0.9.1" + G + end + + it "replaces #gem but raises when the gem is missing" do + run <<-R + begin + gem "activesupport" + puts "FAIL" + rescue LoadError + puts "WIN" + end + R + + expect(out).to eq("WIN") + end + + it "version_requirement is now deprecated in rubygems 1.4.0+ when gem is missing" do + run <<-R, :expect_err => true + begin + gem "activesupport" + puts "FAIL" + rescue LoadError + puts "WIN" + end + R + + expect(err).to be_empty + end + + it "replaces #gem but raises when the version is wrong" do + run <<-R + begin + gem "rack", "1.0.0" + puts "FAIL" + rescue LoadError + puts "WIN" + end + R + + expect(out).to eq("WIN") + end + + it "version_requirement is now deprecated in rubygems 1.4.0+ when the version is wrong" do + run <<-R, :expect_err => true + begin + gem "rack", "1.0.0" + puts "FAIL" + rescue LoadError + puts "WIN" + end + R + + expect(err).to be_empty + end + end + + describe "by hiding system gems" do + before :each do + system_gems "activesupport-2.3.5" + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "yard" + G + end + + it "removes system gems from Gem.source_index" do + run "require 'yard'" + expect(out).to eq("bundler-#{Bundler::VERSION}\nyard-1.0") + end + + context "when the ruby stdlib is a substring of Gem.path" do + it "does not reject the stdlib from $LOAD_PATH" do + substring = "/" + $LOAD_PATH.find{|p| p =~ /vendor_ruby/ }.split("/")[2] + run "puts 'worked!'", :env => {"GEM_PATH" => substring} + expect(out).to eq("worked!") + end + end + end + end + + describe "with paths" do + it "activates the gems in the path source" do + system_gems "rack-1.0.0" + + build_lib "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "puts 'WIN'" + end + + gemfile <<-G + path "#{lib_path('rack-1.0.0')}" + source "file://#{gem_repo1}" + gem "rack" + G + + run "require 'rack'" + expect(out).to eq("WIN") + end + end + + describe "with git" do + before do + build_git "rack", "1.0.0" + + gemfile <<-G + gem "rack", :git => "#{lib_path('rack-1.0.0')}" + G + end + + it "provides a useful exception when the git repo is not checked out yet" do + run "1", :expect_err => true + expect(err).to match(/the git source #{lib_path('rack-1.0.0')} is not yet checked out. Please run `bundle install`/i) + end + + it "does not hit the git binary if the lockfile is available and up to date" do + bundle "install" + + break_git! + + ruby <<-R + require 'rubygems' + require 'bundler' + + begin + Bundler.setup + puts "WIN" + rescue Exception => e + puts "FAIL" + end + R + + expect(out).to eq("WIN") + end + + it "provides a good exception if the lockfile is unavailable" do + bundle "install" + + FileUtils.rm(bundled_app("Gemfile.lock")) + + break_git! + + ruby <<-R + require "rubygems" + require "bundler" + + begin + Bundler.setup + puts "FAIL" + rescue Bundler::GitError => e + puts e.message + end + R + + run "puts 'FAIL'", :expect_err => true + + expect(err).not_to include "This is not the git you are looking for" + end + + it "works even when the cache directory has been deleted" do + bundle "install --path vendor/bundle" + FileUtils.rm_rf vendored_gems('cache') + should_be_installed "rack 1.0.0" + end + + it "does not randomly change the path when specifying --path and the bundle directory becomes read only" do + bundle "install --path vendor/bundle" + + with_read_only("**/*") do + should_be_installed "rack 1.0.0" + end + end + + it "finds git gem when default bundle path becomes read only" do + bundle "install" + + with_read_only("#{Bundler.bundle_path}/**/*") do + should_be_installed "rack 1.0.0" + end + end + end + + describe "when specifying local override" do + it "explodes if given path does not exist on runtime" do + build_git "rack", "0.8" + + FileUtils.cp_r("#{lib_path('rack-0.8')}/.", lib_path('local-rack')) + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :branch => "master" + G + + bundle %|config local.rack #{lib_path('local-rack')}| + bundle :install + expect(out).to match(/at #{lib_path('local-rack')}/) + + FileUtils.rm_rf(lib_path('local-rack')) + run "require 'rack'", :expect_err => true + expect(err).to match(/Cannot use local override for rack-0.8 because #{Regexp.escape(lib_path('local-rack').to_s)} does not exist/) + end + + it "explodes if branch is not given on runtime" do + build_git "rack", "0.8" + + FileUtils.cp_r("#{lib_path('rack-0.8')}/.", lib_path('local-rack')) + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :branch => "master" + G + + bundle %|config local.rack #{lib_path('local-rack')}| + bundle :install + expect(out).to match(/at #{lib_path('local-rack')}/) + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}" + G + + run "require 'rack'", :expect_err => true + expect(err).to match(/because :branch is not specified in Gemfile/) + end + + it "explodes on different branches on runtime" do + build_git "rack", "0.8" + + FileUtils.cp_r("#{lib_path('rack-0.8')}/.", lib_path('local-rack')) + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :branch => "master" + G + + bundle %|config local.rack #{lib_path('local-rack')}| + bundle :install + expect(out).to match(/at #{lib_path('local-rack')}/) + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :branch => "changed" + G + + run "require 'rack'", :expect_err => true + expect(err).to match(/is using branch master but Gemfile specifies changed/) + end + + it "explodes on refs with different branches on runtime" do + build_git "rack", "0.8" + + FileUtils.cp_r("#{lib_path('rack-0.8')}/.", lib_path('local-rack')) + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :ref => "master", :branch => "master" + G + + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :ref => "master", :branch => "nonexistant" + G + + bundle %|config local.rack #{lib_path('local-rack')}| + run "require 'rack'", :expect_err => true + expect(err).to match(/is using branch master but Gemfile specifies nonexistant/) + end + end + + describe "when excluding groups" do + it "doesn't change the resolve if --without is used" do + install_gemfile <<-G, :without => :rails + source "file://#{gem_repo1}" + gem "activesupport" + + group :rails do + gem "rails", "2.3.2" + end + G + + install_gems "activesupport-2.3.5" + + should_be_installed "activesupport 2.3.2", :groups => :default + end + + it "remembers --without and does not bail on bare Bundler.setup" do + install_gemfile <<-G, :without => :rails + source "file://#{gem_repo1}" + gem "activesupport" + + group :rails do + gem "rails", "2.3.2" + end + G + + install_gems "activesupport-2.3.5" + + should_be_installed "activesupport 2.3.2" + end + + it "remembers --without and does not include groups passed to Bundler.setup" do + install_gemfile <<-G, :without => :rails + source "file://#{gem_repo1}" + gem "activesupport" + + group :rack do + gem "rack" + end + + group :rails do + gem "rails", "2.3.2" + end + G + + should_not_be_installed "activesupport 2.3.2", :groups => :rack + should_be_installed "rack 1.0.0", :groups => :rack + end + end + + # Unfortunately, gem_prelude does not record the information about + # activated gems, so this test cannot work on 1.9 :( + if RUBY_VERSION < "1.9" + describe "preactivated gems" do + it "raises an exception if a pre activated gem conflicts with the bundle" do + system_gems "thin-1.0", "rack-1.0.0" + build_gem "thin", "1.1", :to_system => true do |s| + s.add_dependency "rack" + end + + gemfile <<-G + gem "thin", "1.0" + G + + ruby <<-R + require 'rubygems' + gem "thin" + require 'bundler' + begin + Bundler.setup + puts "FAIL" + rescue Gem::LoadError => e + puts e.message + end + R + + expect(out).to eq("You have already activated thin 1.1, but your Gemfile requires thin 1.0. Prepending `bundle exec` to your command may solve this.") + end + + it "version_requirement is now deprecated in rubygems 1.4.0+" do + system_gems "thin-1.0", "rack-1.0.0" + build_gem "thin", "1.1", :to_system => true do |s| + s.add_dependency "rack" + end + + gemfile <<-G + gem "thin", "1.0" + G + + ruby <<-R, :expect_err => true + require 'rubygems' + gem "thin" + require 'bundler' + begin + Bundler.setup + puts "FAIL" + rescue Gem::LoadError => e + puts e.message + end + R + + expect(err).to be_empty + end + end + end + + # Rubygems returns loaded_from as a string + it "has loaded_from as a string on all specs" do + build_git "foo" + build_git "no-gemspec", :gemspec => false + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + gem "foo", :git => "#{lib_path('foo-1.0')}" + gem "no-gemspec", "1.0", :git => "#{lib_path('no-gemspec-1.0')}" + G + + run <<-R + Gem.loaded_specs.each do |n, s| + puts "FAIL" unless s.loaded_from.is_a?(String) + end + R + + expect(out).to be_empty + end + + it "ignores empty gem paths" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + ENV["GEM_HOME"] = "" + bundle %{exec ruby -e "require 'set'"} + + expect(err).to be_empty + end + + it "should prepend gemspec require paths to $LOAD_PATH in order" do + update_repo2 do + build_gem("requirepaths") do |s| + s.write("lib/rq.rb", "puts 'yay'") + s.write("src/rq.rb", "puts 'nooo'") + s.require_paths = ["lib", "src"] + end + end + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "requirepaths", :require => nil + G + + run "require 'rq'" + expect(out).to eq("yay") + end + + it "stubs out Gem.refresh so it does not reveal system gems" do + system_gems "rack-1.0.0" + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "activesupport" + G + + run <<-R + puts Bundler.rubygems.find_name("rack").inspect + Gem.refresh + puts Bundler.rubygems.find_name("rack").inspect + R + + expect(out).to eq("[]\n[]") + end + + describe "when a vendored gem specification uses the :path option" do + it "should resolve paths relative to the Gemfile" do + path = bundled_app(File.join('vendor', 'foo')) + build_lib "foo", :path => path + + # If the .gemspec exists, then Bundler handles the path differently. + # See Source::Path.load_spec_files for details. + FileUtils.rm(File.join(path, 'foo.gemspec')) + + install_gemfile <<-G + gem 'foo', '1.2.3', :path => 'vendor/foo' + G + + Dir.chdir(bundled_app.parent) do + run <<-R, :env => {"BUNDLE_GEMFILE" => bundled_app('Gemfile')} + require 'foo' + R + end + expect(err).to eq("") + end + + it "should make sure the Bundler.root is really included in the path relative to the Gemfile" do + relative_path = File.join('vendor', Dir.pwd[1..-1], 'foo') + absolute_path = bundled_app(relative_path) + FileUtils.mkdir_p(absolute_path) + build_lib "foo", :path => absolute_path + + # If the .gemspec exists, then Bundler handles the path differently. + # See Source::Path.load_spec_files for details. + FileUtils.rm(File.join(absolute_path, 'foo.gemspec')) + + gemfile <<-G + gem 'foo', '1.2.3', :path => '#{relative_path}' + G + + bundle :install + + Dir.chdir(bundled_app.parent) do + run <<-R, :env => {"BUNDLE_GEMFILE" => bundled_app('Gemfile')} + require 'foo' + R + end + + expect(err).to eq("") + end + end + + describe "with git gems that don't have gemspecs" do + before :each do + build_git "no-gemspec", :gemspec => false + + install_gemfile <<-G + gem "no-gemspec", "1.0", :git => "#{lib_path('no-gemspec-1.0')}" + G + end + + it "loads the library via a virtual spec" do + run <<-R + require 'no-gemspec' + puts NOGEMSPEC + R + + expect(out).to eq("1.0") + end + end + + describe "with bundled and system gems" do + before :each do + system_gems "rack-1.0.0" + + install_gemfile <<-G + source "file://#{gem_repo1}" + + gem "activesupport", "2.3.5" + G + end + + it "does not pull in system gems" do + run <<-R + require 'rubygems' + + begin; + require 'rack' + rescue LoadError + puts 'WIN' + end + R + + expect(out).to eq("WIN") + end + + it "provides a gem method" do + run <<-R + gem 'activesupport' + require 'activesupport' + puts ACTIVESUPPORT + R + + expect(out).to eq("2.3.5") + end + + it "raises an exception if gem is used to invoke a system gem not in the bundle" do + run <<-R + begin + gem 'rack' + rescue LoadError => e + puts e.message + end + R + + expect(out).to eq("rack is not part of the bundle. Add it to Gemfile.") + end + + it "sets GEM_HOME appropriately" do + run "puts ENV['GEM_HOME']" + expect(out).to eq(default_bundle_path.to_s) + end + end + + describe "with system gems in the bundle" do + before :each do + system_gems "rack-1.0.0" + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "1.0.0" + gem "activesupport", "2.3.5" + G + end + + it "sets GEM_PATH appropriately" do + run "puts Gem.path" + paths = out.split("\n") + expect(paths).to include(system_gem_path.to_s) + expect(paths).to include(default_bundle_path.to_s) + end + end + + describe "with a gemspec that requires other files" do + before :each do + build_git "bar", :gemspec => false do |s| + s.write "lib/bar/version.rb", %{BAR_VERSION = '1.0'} + s.write "bar.gemspec", <<-G + lib = File.expand_path('../lib/', __FILE__) + $:.unshift lib unless $:.include?(lib) + require 'bar/version' + + Gem::Specification.new do |s| + s.name = 'bar' + s.version = BAR_VERSION + s.summary = 'Bar' + s.files = Dir["lib/**/*.rb"] + end + G + end + + gemfile <<-G + gem "bar", :git => "#{lib_path('bar-1.0')}" + G + end + + it "evals each gemspec in the context of its parent directory" do + bundle :install + run "require 'bar'; puts BAR" + expect(out).to eq("1.0") + end + + it "error intelligently if the gemspec has a LoadError" do + update_git "bar", :gemspec => false do |s| + s.write "bar.gemspec", "require 'foobarbaz'" + end + bundle :install + expect(out).to include("was a LoadError while loading bar.gemspec") + expect(out).to include("foobarbaz") + expect(out).to include("bar.gemspec:1") + expect(out).to include("try to require a relative path") if RUBY_VERSION >= "1.9" + end + + it "evals each gemspec with a binding from the top level" do + bundle "install" + + ruby <<-RUBY + require 'bundler' + def Bundler.require(path) + raise "LOSE" + end + Bundler.load + RUBY + + expect(err).to eq("") + expect(out).to eq("") + end + end + + describe "when Bundler is bundled" do + it "doesn't blow up" do + install_gemfile <<-G + gem "bundler", :path => "#{File.expand_path("..", lib)}" + G + + bundle %|exec ruby -e "require 'bundler'; Bundler.setup"| + expect(err).to be_empty + end + end + +end diff --git a/bundler-1.7.2/spec/runtime/with_clean_env_spec.rb b/bundler-1.7.2/spec/runtime/with_clean_env_spec.rb new file mode 100644 index 0000000..193a6e5 --- /dev/null +++ b/bundler-1.7.2/spec/runtime/with_clean_env_spec.rb @@ -0,0 +1,91 @@ +require "spec_helper" + +describe "Bundler.with_env helpers" do + + shared_examples_for "Bundler.with_*_env" do + it "should reset and restore the environment" do + gem_path = ENV['GEM_PATH'] + + Bundler.with_clean_env do + expect(`echo $GEM_PATH`.strip).not_to eq(gem_path) + end + + expect(ENV['GEM_PATH']).to eq(gem_path) + end + end + + around do |example| + env = Bundler::ORIGINAL_ENV.dup + Bundler::ORIGINAL_ENV['BUNDLE_PATH'] = "./Gemfile" + example.run + Bundler::ORIGINAL_ENV.replace env + end + + describe "Bundler.with_clean_env" do + + it_should_behave_like "Bundler.with_*_env" + + it "should keep the original GEM_PATH even in sub processes" do + gemfile "" + bundle "install --path vendor/bundle" + + code = "Bundler.with_clean_env do;" + + " print ENV['GEM_PATH'] != '';" + + "end" + + result = bundle "exec ruby -e #{code.inspect}" + expect(result).to eq("true") + end + + it "should not pass any bundler environment variables" do + Bundler.with_clean_env do + expect(`echo $BUNDLE_PATH`.strip).not_to eq('./Gemfile') + end + end + + it "should not pass RUBYOPT changes" do + lib_path = File.expand_path('../../../lib', __FILE__) + Bundler::ORIGINAL_ENV['RUBYOPT'] = " -I#{lib_path} -rbundler/setup" + + Bundler.with_clean_env do + expect(`echo $RUBYOPT`.strip).not_to include '-rbundler/setup' + expect(`echo $RUBYOPT`.strip).not_to include "-I#{lib_path}" + end + + expect(Bundler::ORIGINAL_ENV['RUBYOPT']).to eq(" -I#{lib_path} -rbundler/setup") + end + + it "should not change ORIGINAL_ENV" do + expect(Bundler::ORIGINAL_ENV['BUNDLE_PATH']).to eq('./Gemfile') + end + + end + + describe "Bundler.with_original_env" do + + it_should_behave_like "Bundler.with_*_env" + + it "should pass bundler environment variables set before Bundler was run" do + Bundler.with_original_env do + expect(`echo $BUNDLE_PATH`.strip).to eq('./Gemfile') + end + end + end + + describe "Bundler.clean_system" do + it "runs system inside with_clean_env" do + Bundler.clean_system(%{echo 'if [ "$BUNDLE_PATH" = "" ]; then exit 42; else exit 1; fi' | /bin/sh}) + expect($?.exitstatus).to eq(42) + end + end + + describe "Bundler.clean_exec" do + it "runs exec inside with_clean_env" do + pid = Kernel.fork do + Bundler.clean_exec(%{echo 'if [ "$BUNDLE_PATH" = "" ]; then exit 42; else exit 1; fi' | /bin/sh}) + end + Process.wait(pid) + expect($?.exitstatus).to eq(42) + end + end +end diff --git a/bundler-1.7.2/spec/spec_helper.rb b/bundler-1.7.2/spec/spec_helper.rb new file mode 100644 index 0000000..54e79bd --- /dev/null +++ b/bundler-1.7.2/spec/spec_helper.rb @@ -0,0 +1,121 @@ +$:.unshift File.expand_path('..', __FILE__) +$:.unshift File.expand_path('../../lib', __FILE__) +# stdlib first +require 'uri' +require 'digest/sha1' +require 'fileutils' +require 'bundler/psyched_yaml' +require 'rubygems' +require 'rspec' +require 'bundler' + +# Require the correct version of popen for the current platform +if RbConfig::CONFIG['host_os'] =~ /mingw|mswin/ + begin + require 'win32/open3' + rescue LoadError + abort "Run `gem install win32-open3` to be able to run specs" + end +else + require 'open3' +end + +Dir["#{File.expand_path('../support', __FILE__)}/*.rb"].each do |file| + require file unless file =~ /fakeweb\/.*\.rb/ +end + +$debug = false +$show_err = true + +Spec::Rubygems.setup +FileUtils.rm_rf(Spec::Path.gem_repo1) +ENV['RUBYOPT'] = "#{ENV['RUBYOPT']} -r#{Spec::Path.root}/spec/support/hax.rb" +ENV['BUNDLE_SPEC_RUN'] = "true" + +# Don't wrap output in tests +ENV['THOR_COLUMNS'] = '10000' + +RSpec.configure do |config| + config.include Spec::Builders + config.include Spec::Helpers + config.include Spec::Indexes + config.include Spec::Matchers + config.include Spec::Path + config.include Spec::Rubygems + config.include Spec::Platforms + config.include Spec::Sudo + config.include Spec::Permissions + + if ENV['BUNDLER_SUDO_TESTS'] && Spec::Sudo.present? + config.filter_run :sudo => true + else + config.filter_run_excluding :sudo => true + end + + if ENV['BUNDLER_REALWORLD_TESTS'] + config.filter_run :realworld => true + else + 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 :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'] + original_gem_home = ENV['GEM_HOME'] + + def pending_jruby_shebang_fix + pending "JRuby executables do not have a proper shebang" if RUBY_PLATFORM == "java" + end + + config.expect_with :rspec do |c| + c.syntax = :expect + end + + config.before :all do + build_repo1 + end + + config.before :each do + reset! + system_gems [] + in_app_root + end + + config.after :each do |example| + puts @out if example.exception + + 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['BUNDLER_SPEC_PLATFORM'] = nil + ENV['BUNDLER_SPEC_VERSION'] = nil + ENV['BUNDLE_APP_CONFIG'] = nil + end +end diff --git a/bundler-1.7.2/spec/support/artifice/endopint_marshal_fail_basic_authentication.rb b/bundler-1.7.2/spec/support/artifice/endopint_marshal_fail_basic_authentication.rb new file mode 100644 index 0000000..205b258 --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endopint_marshal_fail_basic_authentication.rb @@ -0,0 +1,13 @@ +require File.expand_path("../endpoint_marshal_fail", __FILE__) + +Artifice.deactivate + +class EndpointMarshalFailBasicAuthentication < EndpointMarshalFail + before do + unless env["HTTP_AUTHORIZATION"] + halt 401, "Authentication info not supplied" + end + end +end + +Artifice.activate_with(EndpointMarshalFailBasicAuthentication) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint.rb b/bundler-1.7.2/spec/support/artifice/endpoint.rb new file mode 100644 index 0000000..68b41b7 --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint.rb @@ -0,0 +1,71 @@ +require File.expand_path("../../path.rb", __FILE__) +require File.expand_path("../../../../lib/bundler/deprecate", __FILE__) +include Spec::Path + +# Set up pretend http gem server with FakeWeb +$LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/artifice*/lib")].first}" +$LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/rack-*/lib")].first}" +$LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/rack-*/lib")].last}" +$LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/tilt*/lib")].first}" +$LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/sinatra*/lib")].first}" +require 'artifice' +require 'sinatra/base' + +class Endpoint < Sinatra::Base + + helpers do + def dependencies_for(gem_names, marshal = gem_repo1("specs.4.8")) + return [] if gem_names.nil? || gem_names.empty? + + require 'rubygems' + require 'bundler' + Bundler::Deprecate.skip_during do + Marshal.load(File.open(marshal).read).map do |name, version, platform| + spec = load_spec(name, version, platform) + if gem_names.include?(spec.name) + { + :name => spec.name, + :number => spec.version.version, + :platform => spec.platform.to_s, + :dependencies => spec.dependencies.select {|dep| dep.type == :runtime }.map do |dep| + [dep.name, dep.requirement.requirements.map {|a| a.join(" ") }.join(", ")] + end + } + end + end.compact + end + end + + def load_spec(name, version, platform) + full_name = "#{name}-#{version}" + full_name += "-#{platform}" if platform != "ruby" + Marshal.load(Gem.inflate(File.open(gem_repo1("quick/Marshal.4.8/#{full_name}.gemspec.rz")).read)) + end + end + + get "/quick/Marshal.4.8/:id" do + redirect "/fetch/actual/gem/#{params[:id]}" + end + + get "/fetch/actual/gem/:id" do + File.read("#{gem_repo1}/quick/Marshal.4.8/#{params[:id]}") + end + + get "/gems/:id" do + File.read("#{gem_repo1}/gems/#{params[:id]}") + end + + get "/api/v1/dependencies" do + Marshal.dump(dependencies_for(params[:gems])) + end + + get "/specs.4.8.gz" do + File.read("#{gem_repo1}/specs.4.8.gz") + end + + get "/prerelease_specs.4.8.gz" do + File.read("#{gem_repo1}/prerelease_specs.4.8.gz") + end +end + +Artifice.activate_with(Endpoint) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint_500.rb b/bundler-1.7.2/spec/support/artifice/endpoint_500.rb new file mode 100644 index 0000000..84997db --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint_500.rb @@ -0,0 +1,37 @@ +require File.expand_path("../../path.rb", __FILE__) +include Spec::Path + +$LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/artifice*/lib")].first}" +$LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/rack-*/lib")].first}" +$LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/rack-*/lib")].last}" +$LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/tilt*/lib")].first}" +$LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/sinatra*/lib")].first}" + +require 'artifice' +require 'sinatra/base' + +Artifice.deactivate + +class Endpoint500 < Sinatra::Base + get "/quick/Marshal.4.8/:id" do + halt 500 + end + + get "/fetch/actual/gem/:id" do + halt 500 + end + + get "/gems/:id" do + halt 500 + end + + get "/api/v1/dependencies" do + halt 500 + end + + get "/specs.4.8.gz" do + halt 500 + end +end + +Artifice.activate_with(Endpoint500) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint_api_missing.rb b/bundler-1.7.2/spec/support/artifice/endpoint_api_missing.rb new file mode 100644 index 0000000..bc89db3 --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint_api_missing.rb @@ -0,0 +1,16 @@ +require File.expand_path("../endpoint", __FILE__) + +Artifice.deactivate + +class EndpointApiMissing < Endpoint + get "/fetch/actual/gem/:id" do + $stderr.puts params[:id] + if params[:id] == 'rack-1.0.gemspec.rz' + halt 404 + else + File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") + end + end +end + +Artifice.activate_with(EndpointApiMissing) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint_basic_authentication.rb b/bundler-1.7.2/spec/support/artifice/endpoint_basic_authentication.rb new file mode 100644 index 0000000..0cfba89 --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint_basic_authentication.rb @@ -0,0 +1,13 @@ +require File.expand_path("../endpoint", __FILE__) + +Artifice.deactivate + +class EndpointBasicAuthentication < Endpoint + before do + unless env["HTTP_AUTHORIZATION"] + halt 401, "Authentication info not supplied" + end + end +end + +Artifice.activate_with(EndpointBasicAuthentication) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint_creds_diff_host.rb b/bundler-1.7.2/spec/support/artifice/endpoint_creds_diff_host.rb new file mode 100644 index 0000000..21cce22 --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint_creds_diff_host.rb @@ -0,0 +1,38 @@ +require File.expand_path("../endpoint", __FILE__) + +Artifice.deactivate + +class EndpointCredsDiffHost < Endpoint + helpers do + def auth + @auth ||= Rack::Auth::Basic::Request.new(request.env) + end + + def authorized? + auth.provided? && auth.basic? && auth.credentials && auth.credentials == ['user', 'pass'] + end + + def protected! + unless authorized? + response['WWW-Authenticate'] = %(Basic realm="Testing HTTP Auth") + throw(:halt, [401, "Not authorized\n"]) + end + end + end + + before do + protected! unless request.path_info.include?("/no/creds/") + end + + get "/gems/:id" do + redirect "http://diffhost.com/no/creds/#{params[:id]}" + end + + get "/no/creds/:id" do + if request.host.include?("diffhost") && !auth.provided? + File.read("#{gem_repo1}/gems/#{params[:id]}") + end + end +end + +Artifice.activate_with(EndpointCredsDiffHost) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint_extra.rb b/bundler-1.7.2/spec/support/artifice/endpoint_extra.rb new file mode 100644 index 0000000..c50428f --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint_extra.rb @@ -0,0 +1,31 @@ +require File.expand_path("../endpoint", __FILE__) + +Artifice.deactivate + +class EndpointExtra < Endpoint + get "/extra/api/v1/dependencies" do + halt 404 + end + + get "/extra/specs.4.8.gz" do + File.read("#{gem_repo2}/specs.4.8.gz") + end + + get "/extra/prerelease_specs.4.8.gz" do + File.read("#{gem_repo2}/prerelease_specs.4.8.gz") + end + + get "/extra/quick/Marshal.4.8/:id" do + redirect "/extra/fetch/actual/gem/#{params[:id]}" + end + + get "/extra/fetch/actual/gem/:id" do + File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") + end + + get "/extra/gems/:id" do + File.read("#{gem_repo2}/gems/#{params[:id]}") + end +end + +Artifice.activate_with(EndpointExtra) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint_extra_missing.rb b/bundler-1.7.2/spec/support/artifice/endpoint_extra_missing.rb new file mode 100644 index 0000000..29322ad --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint_extra_missing.rb @@ -0,0 +1,15 @@ +require File.expand_path("../endpoint_extra", __FILE__) + +Artifice.deactivate + +class EndpointExtraMissing < EndpointExtra + get "/extra/fetch/actual/gem/:id" do + if params[:id] == 'missing-1.0.gemspec.rz' + halt 404 + else + File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") + end + end +end + +Artifice.activate_with(EndpointExtraMissing) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint_fallback.rb b/bundler-1.7.2/spec/support/artifice/endpoint_fallback.rb new file mode 100644 index 0000000..db02a88 --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint_fallback.rb @@ -0,0 +1,17 @@ +require File.expand_path("../endpoint", __FILE__) + +Artifice.deactivate + +class EndpointFallback < Endpoint + DEPENDENCY_LIMIT = 60 + + get "/api/v1/dependencies" do + if params[:gems] && params[:gems].size <= DEPENDENCY_LIMIT + Marshal.dump(dependencies_for(params[:gems])) + else + halt 413, "Too many gems to resolve, please request less than #{DEPENDENCY_LIMIT} gems" + end + end +end + +Artifice.activate_with(EndpointFallback) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint_host_redirect.rb b/bundler-1.7.2/spec/support/artifice/endpoint_host_redirect.rb new file mode 100644 index 0000000..e44d63e --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint_host_redirect.rb @@ -0,0 +1,15 @@ +require File.expand_path("../endpoint", __FILE__) + +Artifice.deactivate + +class EndpointHostRedirect < Endpoint + get "/fetch/actual/gem/:id", :host_name => 'localgemserver.test' do + redirect "http://bundler.localgemserver.test#{request.path_info}" + end + + get "/api/v1/dependencies" do + status 404 + end +end + +Artifice.activate_with(EndpointHostRedirect) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint_marshal_fail.rb b/bundler-1.7.2/spec/support/artifice/endpoint_marshal_fail.rb new file mode 100644 index 0000000..a0dc182 --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint_marshal_fail.rb @@ -0,0 +1,11 @@ +require File.expand_path("../endpoint_fallback", __FILE__) + +Artifice.deactivate + +class EndpointMarshalFail < EndpointFallback + get "/api/v1/dependencies" do + "f0283y01hasf" + end +end + +Artifice.activate_with(EndpointMarshalFail) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint_redirect.rb b/bundler-1.7.2/spec/support/artifice/endpoint_redirect.rb new file mode 100644 index 0000000..2b48fa5 --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint_redirect.rb @@ -0,0 +1,15 @@ +require File.expand_path("../endpoint", __FILE__) + +Artifice.deactivate + +class EndpointRedirect < Endpoint + get "/fetch/actual/gem/:id" do + redirect "/fetch/actual/gem/#{params[:id]}" + end + + get "/api/v1/dependencies" do + status 404 + end +end + +Artifice.activate_with(EndpointRedirect) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint_strict_basic_authentication.rb b/bundler-1.7.2/spec/support/artifice/endpoint_strict_basic_authentication.rb new file mode 100644 index 0000000..e7329ab --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint_strict_basic_authentication.rb @@ -0,0 +1,18 @@ +require File.expand_path("../endpoint", __FILE__) + +Artifice.deactivate + +class EndpointStrictBasicAuthentication < Endpoint + before do + unless env["HTTP_AUTHORIZATION"] + halt 401, "Authentication info not supplied" + end + + # Only accepts password == "password" + unless env["HTTP_AUTHORIZATION"] == "Basic dXNlcjpwYXNz" + halt 403, "Authentication failed" + end + end +end + +Artifice.activate_with(EndpointStrictBasicAuthentication) diff --git a/bundler-1.7.2/spec/support/artifice/endpoint_timeout.rb b/bundler-1.7.2/spec/support/artifice/endpoint_timeout.rb new file mode 100644 index 0000000..da68220 --- /dev/null +++ b/bundler-1.7.2/spec/support/artifice/endpoint_timeout.rb @@ -0,0 +1,13 @@ +require File.expand_path("../endpoint_fallback", __FILE__) + +Artifice.deactivate + +class EndpointTimeout < EndpointFallback + SLEEP_TIMEOUT = 15 + + get "/api/v1/dependencies" do + sleep(SLEEP_TIMEOUT) + end +end + +Artifice.activate_with(EndpointTimeout) diff --git a/bundler-1.7.2/spec/support/builders.rb b/bundler-1.7.2/spec/support/builders.rb new file mode 100644 index 0000000..a49cda8 --- /dev/null +++ b/bundler-1.7.2/spec/support/builders.rb @@ -0,0 +1,681 @@ +require 'bundler/shared_helpers' + +module Spec + module Builders + def self.constantize(name) + name.gsub('-', '').upcase + end + + def v(version) + Gem::Version.new(version) + end + + def pl(platform) + Gem::Platform.new(platform) + end + + def build_repo1 + build_repo gem_repo1 do + build_gem "rack", %w(0.9.1 1.0.0) do |s| + s.executables = "rackup" + s.post_install_message = "Rack's post install message" + end + + build_gem "thin" do |s| + s.add_dependency "rack" + s.post_install_message = "Thin's post install message" + end + + build_gem "rack-obama" do |s| + s.add_dependency "rack" + s.post_install_message = "Rack-obama's post install message" + end + + build_gem "rack_middleware", "1.0" do |s| + s.add_dependency "rack", "0.9.1" + end + + build_gem "rails", "2.3.2" do |s| + s.executables = "rails" + s.add_dependency "rake", "10.0.2" + s.add_dependency "actionpack", "2.3.2" + s.add_dependency "activerecord", "2.3.2" + s.add_dependency "actionmailer", "2.3.2" + s.add_dependency "activeresource", "2.3.2" + end + build_gem "actionpack", "2.3.2" do |s| + s.add_dependency "activesupport", "2.3.2" + end + build_gem "activerecord", ["2.3.1", "2.3.2"] do |s| + s.add_dependency "activesupport", "2.3.2" + end + build_gem "actionmailer", "2.3.2" do |s| + s.add_dependency "activesupport", "2.3.2" + end + build_gem "activeresource", "2.3.2" do |s| + s.add_dependency "activesupport", "2.3.2" + end + build_gem "activesupport", %w(1.2.3 2.3.2 2.3.5) + + build_gem "activemerchant" do |s| + s.add_dependency "activesupport", ">= 2.0.0" + end + + build_gem "rails_fail" do |s| + s.add_dependency "activesupport", "= 1.2.3" + end + + build_gem "missing_dep" do |s| + s.add_dependency "not_here" + end + + build_gem "rspec", "1.2.7", :no_default => true do |s| + s.write "lib/spec.rb", "SPEC = '1.2.7'" + end + + build_gem "rack-test", :no_default => true do |s| + s.write "lib/rack/test.rb", "RACK_TEST = '1.0'" + end + + build_gem "platform_specific" do |s| + s.platform = Gem::Platform.local + s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Gem::Platform.local}'" + end + + build_gem "platform_specific" do |s| + s.platform = "java" + s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 JAVA'" + end + + build_gem "platform_specific" do |s| + s.platform = "ruby" + s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'" + end + + build_gem "platform_specific" do |s| + s.platform = "x86-mswin32" + s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 MSWIN'" + end + + build_gem "platform_specific" do |s| + s.platform = "x86-darwin-100" + s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 x86-darwin-100'" + end + + build_gem "only_java" do |s| + s.platform = "java" + end + + build_gem "nokogiri", "1.4.2" + build_gem "nokogiri", "1.4.2" do |s| + s.platform = "java" + s.write "lib/nokogiri.rb", "NOKOGIRI = '1.4.2 JAVA'" + s.add_dependency "weakling", ">= 0.0.3" + end + + build_gem "weakling", "0.0.3" + + build_gem "multiple_versioned_deps" do |s| + s.add_dependency "weakling", ">= 0.0.1", "< 0.1" + end + + build_gem "not_released", "1.0.pre" + + build_gem "has_prerelease", "1.0" + build_gem "has_prerelease", "1.1.pre" + + build_gem "with_development_dependency" do |s| + s.add_development_dependency "activesupport", "= 2.3.5" + end + + build_gem "with_license" do |s| + s.license = "MIT" + end + + build_gem "with_implicit_rake_dep" do |s| + s.extensions << "Rakefile" + s.write "Rakefile", <<-RUBY + task :default do + path = File.expand_path("../lib", __FILE__) + FileUtils.mkdir_p(path) + File.open("\#{path}/implicit_rake_dep.rb", "w") do |f| + f.puts "IMPLICIT_RAKE_DEP = 'YES'" + end + end + RUBY + end + + build_gem "another_implicit_rake_dep" do |s| + s.extensions << "Rakefile" + s.write "Rakefile", <<-RUBY + task :default do + path = File.expand_path("../lib", __FILE__) + FileUtils.mkdir_p(path) + File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f| + f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'" + end + end + RUBY + end + + build_gem "very_simple_binary" do |s| + s.add_c_extension + end + + build_gem "bundler", "0.9" do |s| + s.executables = "bundle" + s.write "bin/bundle", "puts 'FAIL'" + end + + # The bundler 0.8 gem has a rubygems plugin that always loads :( + build_gem "bundler", "0.8.1" do |s| + s.write "lib/bundler/omg.rb", "" + s.write "lib/rubygems_plugin.rb", "require 'bundler/omg' ; puts 'FAIL'" + end + + build_gem "bundler_dep" do |s| + s.add_dependency "bundler" + end + + # The yard gem iterates over Gem.source_index looking for plugins + build_gem "yard" do |s| + s.write "lib/yard.rb", <<-Y + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("1.8.10") + specs = Gem::Specification + else + specs = Gem.source_index.find_name('') + end + specs.each do |gem| + puts gem.full_name + end + Y + end + + # The rcov gem is platform mswin32, but has no arch + build_gem "rcov" do |s| + s.platform = Gem::Platform.new([nil, "mswin32", nil]) + s.write "lib/rcov.rb", "RCOV = '1.0.0'" + end + + build_gem "net-ssh" + build_gem "net-sftp", "1.1.1" do |s| + s.add_dependency "net-ssh", ">= 1.0.0", "< 1.99.0" + end + + # Test comlicated gem dependencies for install + build_gem "net_a" do |s| + s.add_dependency "net_b" + s.add_dependency "net_build_extensions" + end + + build_gem "net_b" + + build_gem "net_build_extensions" do |s| + s.add_dependency "rake" + s.extensions << "Rakefile" + s.write "Rakefile", <<-RUBY + task :default do + path = File.expand_path("../lib", __FILE__) + FileUtils.mkdir_p(path) + File.open("\#{path}/net_build_extensions.rb", "w") do |f| + f.puts "NET_BUILD_EXTENSIONS = 'YES'" + end + end + RUBY + end + + build_gem "net_c" do |s| + s.add_dependency "net_a" + s.add_dependency "net_d" + end + + build_gem "net_d" + + build_gem "net_e" do |s| + s.add_dependency "net_d" + end + + # Capistrano did this (at least until version 2.5.10) + # Rubygems 2.2 doesn't allow the specifying of a dependency twice + # See https://github.com/rubygems/rubygems/commit/03dbac93a3396a80db258d9bc63500333c25bd2f + build_gem "double_deps", "1.0", :skip_validation => true do |s| + s.add_dependency "net-ssh", ">= 1.0.0" + s.add_dependency "net-ssh" + end + + build_gem "foo" + end + end + + def build_repo2(&blk) + FileUtils.rm_rf gem_repo2 + FileUtils.cp_r gem_repo1, gem_repo2 + update_repo2(&blk) if block_given? + end + + def build_repo3 + build_repo gem_repo3 do + build_gem "rack" + end + FileUtils.rm_rf Dir[gem_repo3("prerelease*")] + end + + def update_repo2 + update_repo gem_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + yield if block_given? + end + end + + def build_security_repo + build_repo security_repo do + build_gem "rack" + + build_gem "signed_gem" do |s| + cert = 'signing-cert.pem' + pkey = 'signing-pkey.pem' + s.write cert, TEST_CERT + s.write pkey, TEST_PKEY + s.signing_key = pkey + s.cert_chain = [cert] + end + end + + end + + def build_repo(path, &blk) + return if File.directory?(path) + rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first + if rake_path + FileUtils.mkdir_p("#{path}/gems") + FileUtils.cp rake_path, "#{path}/gems/" + else + abort "You need to `rm -rf #{tmp}`" + end + update_repo(path, &blk) + end + + def update_repo(path) + @_build_path = "#{path}/gems" + yield + @_build_path = nil + with_gem_path_as Path.base_system_gems do + Dir.chdir(path) { gem_command :generate_index } + end + end + + def build_index(&block) + index = Bundler::Index.new + IndexBuilder.run(index, &block) if block_given? + index + end + + def build_spec(name, version, platform = nil, &block) + Array(version).map do |v| + Gem::Specification.new do |s| + s.name = name + s.version = Gem::Version.new(v) + s.platform = platform + DepBuilder.run(s, &block) if block_given? + end + end + end + + def build_dep(name, requirements = Gem::Requirement.default, type = :runtime) + Bundler::Dependency.new(name, :version => requirements) + end + + def build_lib(name, *args, &blk) + build_with(LibBuilder, name, args, &blk) + end + + def build_gem(name, *args, &blk) + build_with(GemBuilder, name, args, &blk) + end + + def build_git(name, *args, &block) + opts = args.last.is_a?(Hash) ? args.last : {} + builder = opts[:bare] ? GitBareBuilder : GitBuilder + spec = build_with(builder, name, args, &block) + GitReader.new(opts[:path] || lib_path(spec.full_name)) + end + + def update_git(name, *args, &block) + spec = build_with(GitUpdater, name, args, &block) + GitReader.new lib_path(spec.full_name) + end + + private + + def build_with(builder, name, args, &blk) + @_build_path ||= nil + options = args.last.is_a?(Hash) ? args.pop : {} + versions = args.last || "1.0" + spec = nil + + options[:path] ||= @_build_path + + Array(versions).each do |version| + spec = builder.new(self, name, version) + if !spec.authors or spec.authors.empty? + spec.authors = ["no one"] + end + yield spec if block_given? + spec._build(options) + end + + spec + end + + class IndexBuilder + include Builders + + def self.run(index, &block) + new(index).run(&block) + end + + def initialize(index) + @index = index + end + + def run(&block) + instance_eval(&block) + end + + def gem(*args, &block) + build_spec(*args, &block).each do |s| + @index << s + end + end + + def platforms(platforms) + platforms.split(/\s+/).each do |platform| + platform.gsub!(/^(mswin32)$/, 'x86-\1') + yield Gem::Platform.new(platform) + end + end + + def versions(versions) + versions.split(/\s+/).each { |version| yield v(version) } + end + end + + class DepBuilder + include Builders + + def self.run(spec, &block) + new(spec).run(&block) + end + + def initialize(spec) + @spec = spec + end + + def run(&block) + instance_eval(&block) + end + + def runtime(name, requirements) + @spec.add_runtime_dependency(name, requirements) + end + + alias dep runtime + end + + class LibBuilder + def initialize(context, name, version) + @context = context + @name = name + @spec = Gem::Specification.new do |s| + s.name = name + s.version = version + s.summary = "This is just a fake gem for testing" + end + @files = {} + end + + def method_missing(*args, &blk) + @spec.send(*args, &blk) + end + + def write(file, source = "") + @files[file] = source + end + + def executables=(val) + Array(val).each do |file| + write "#{@spec.bindir}/#{file}", "require '#{@name}' ; puts #{@name.upcase}" + end + @spec.executables = Array(val) + end + + def add_c_extension + require_paths << 'ext' + extensions << "ext/extconf.rb" + write "ext/extconf.rb", <<-RUBY + require "mkmf" + + # exit 1 unless with_config("simple") + + extension_name = "very_simple_binary_c" + dir_config extension_name + create_makefile extension_name + RUBY + write "ext/very_simple_binary.c", <<-C + #include "ruby.h" + + void Init_very_simple_binary_c() { + rb_define_module("VerySimpleBinaryInC"); + } + C + end + + def _build(options) + path = options[:path] || _default_path + + if options[:rubygems_version] + @spec.rubygems_version = options[:rubygems_version] + def @spec.mark_version; end + def @spec.validate; end + end + + case options[:gemspec] + when false + # do nothing + when :yaml + @files["#{name}.gemspec"] = @spec.to_yaml + else + @files["#{name}.gemspec"] = @spec.to_ruby + end + + unless options[:no_default] + @files = _default_files.merge(@files) + end + + @spec.authors = ["no one"] + + @files.each do |file, source| + file = Pathname.new(path).join(file) + FileUtils.mkdir_p(file.dirname) + File.open(file, 'w') { |f| f.puts source } + end + @spec.files = @files.keys + path + end + + def _default_files + @_default_files ||= { "lib/#{name}.rb" => "#{Builders.constantize(name)} = '#{version}'" } + end + + def _default_path + @context.tmp('libs', @spec.full_name) + end + end + + class GitBuilder < LibBuilder + def _build(options) + path = options[:path] || _default_path + super(options.merge(:path => path)) + Dir.chdir(path) do + `git init` + `git add *` + `git config user.email "lol@wut.com"` + `git config user.name "lolwut"` + `git commit -m 'OMG INITIAL COMMIT'` + end + end + end + + class GitBareBuilder < LibBuilder + def _build(options) + path = options[:path] || _default_path + super(options.merge(:path => path)) + Dir.chdir(path) do + `git init --bare` + end + end + end + + class GitUpdater < LibBuilder + def silently(str) + `#{str} 2>#{Bundler::NULL}` + end + + def _build(options) + libpath = options[:path] || _default_path + + Dir.chdir(libpath) do + silently "git checkout master" + + if branch = options[:branch] + raise "You can't specify `master` as the branch" if branch == "master" + + if `git branch | grep #{branch}`.empty? + silently("git branch #{branch}") + end + + silently("git checkout #{branch}") + elsif tag = options[:tag] + `git tag #{tag}` + elsif options[:remote] + silently("git remote add origin file://#{options[:remote]}") + elsif options[:push] + silently("git push origin #{options[:push]}") + end + + current_ref = `git rev-parse HEAD`.strip + _default_files.keys.each do |path| + _default_files[path] << "\n#{Builders.constantize(name)}_PREV_REF = '#{current_ref}'" + end + super(options.merge(:path => libpath, :gemspec => false)) + `git add *` + `git commit -m "BUMP"` + end + end + end + + class GitReader + attr_reader :path + + def initialize(path) + @path = path + end + + def ref_for(ref, len = nil) + ref = git "rev-parse #{ref}" + ref = ref[0..len] if len + ref + end + + private + + def git(cmd) + Bundler::SharedHelpers.with_clean_git_env do + Dir.chdir(@path) { `git #{cmd}`.strip } + end + end + + end + + class GemBuilder < LibBuilder + + def _build(opts) + lib_path = super(opts.merge(:path => @context.tmp(".tmp/#{@spec.full_name}"), :no_default => opts[:no_default])) + Dir.chdir(lib_path) do + destination = opts[:path] || _default_path + FileUtils.mkdir_p(destination) + + if !@spec.authors or @spec.authors.empty? + @spec.authors = ["that guy"] + end + + Bundler.rubygems.build(@spec, opts[:skip_validation]) + if opts[:to_system] + `gem install --ignore-dependencies #{@spec.full_name}.gem` + else + FileUtils.mv("#{@spec.full_name}.gem", opts[:path] || _default_path) + end + end + end + + def _default_path + @context.gem_repo1('gems') + end + end + + TEST_CERT=<= 0["ruby-openid" ~> 2.0.0[" mongrel" >= 0["memcache-client" >= 0[" fcgi" >= 0[" camping" >= 0["test-spec" >= 0: platform" ruby: name" rack: number" +1.0.0 \ No newline at end of file diff --git a/bundler-1.7.2/spec/support/fakeweb/windows.rb b/bundler-1.7.2/spec/support/fakeweb/windows.rb new file mode 100644 index 0000000..0a5dfcb --- /dev/null +++ b/bundler-1.7.2/spec/support/fakeweb/windows.rb @@ -0,0 +1,23 @@ +require File.expand_path("../../path.rb", __FILE__) +include Spec::Path + +files = [ 'specs.4.8.gz', + 'prerelease_specs.4.8.gz', + 'quick/Marshal.4.8/rcov-1.0-mswin32.gemspec.rz', + 'gems/rcov-1.0-mswin32.gem' ] + +# Set up pretend http gem server with FakeWeb +$LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/fakeweb*/lib")].first}" +require 'fakeweb' + +FakeWeb.allow_net_connect = false + +files.each do |file| + FakeWeb.register_uri(:get, "http://localgemserver.test/#{file}", + :body => File.read("#{gem_repo1}/#{file}")) +end +FakeWeb.register_uri(:get, "http://localgemserver.test/gems/rcov-1.0-x86-mswin32.gem", + :status => ["404", "Not Found"]) + +FakeWeb.register_uri(:get, "http://localgemserver.test/api/v1/dependencies", + :status => ["404", "Not Found"]) diff --git a/bundler-1.7.2/spec/support/hax.rb b/bundler-1.7.2/spec/support/hax.rb new file mode 100644 index 0000000..a473768 --- /dev/null +++ b/bundler-1.7.2/spec/support/hax.rb @@ -0,0 +1,22 @@ +require 'rubygems' + +class Gem::Platform + @local = new(ENV['BUNDLER_SPEC_PLATFORM']) if ENV['BUNDLER_SPEC_PLATFORM'] +end + +if ENV['BUNDLER_SPEC_VERSION'] + module Bundler + VERSION = ENV['BUNDLER_SPEC_VERSION'].dup + end +end + +class Object + if ENV['BUNDLER_SPEC_RUBY_ENGINE'] + remove_const :RUBY_ENGINE if defined?(RUBY_ENGINE) + RUBY_ENGINE = ENV['BUNDLER_SPEC_RUBY_ENGINE'] + + if RUBY_ENGINE == "jruby" + JRUBY_VERSION = ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] + end + end +end diff --git a/bundler-1.7.2/spec/support/helpers.rb b/bundler-1.7.2/spec/support/helpers.rb new file mode 100644 index 0000000..db1a785 --- /dev/null +++ b/bundler-1.7.2/spec/support/helpers.rb @@ -0,0 +1,359 @@ +module Spec + module Helpers + def reset! + @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 + `sudo rm -rf #{dir}` + end + end + FileUtils.mkdir_p(tmp) + FileUtils.mkdir_p(home) + end + + attr_reader :out, :err, :exitstatus + + def in_app_root(&blk) + Dir.chdir(bundled_app, &blk) + end + + def in_app_root2(&blk) + Dir.chdir(bundled_app2, &blk) + end + + def in_app_root_custom(root, &blk) + Dir.chdir(root, &blk) + end + + def run(cmd, *args) + opts = args.last.is_a?(Hash) ? args.pop : {} + expect_err = opts.delete(:expect_err) + env = opts.delete(:env) + groups = args.map {|a| a.inspect }.join(", ") + setup = "require 'rubygems' ; require 'bundler' ; Bundler.setup(#{groups})\n" + @out = ruby(setup + cmd, :expect_err => expect_err, :env => env) + end + + def load_error_run(ruby, name, *args) + cmd = <<-RUBY + begin + #{ruby} + rescue LoadError => e + $stderr.puts "ZOMG LOAD ERROR" if e.message.include?("-- #{name}") + end + RUBY + opts = args.last.is_a?(Hash) ? args.pop : {} + opts.merge!(:expect_err => true) + args += [opts] + run(cmd, *args) + end + + def lib + File.expand_path('../../../lib', __FILE__) + end + + 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]) + + bundle_bin = File.expand_path('../../../bin/bundle', __FILE__) + + requires = options.delete(:requires) || [] + requires << File.expand_path('../fakeweb/'+options.delete(:fakeweb)+'.rb', __FILE__) if options.key?(:fakeweb) + 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| + 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 + end + + def bundle_ruby(options = {}) + expect_err = options.delete(:expect_err) + exitstatus = options.delete(:exitstatus) + options["no-color"] = true unless options.key?("no-color") + + bundle_bin = File.expand_path('../../../bin/bundle_ruby', __FILE__) + + requires = options.delete(:requires) || [] + requires << File.expand_path('../fakeweb/'+options.delete(:fakeweb)+'.rb', __FILE__) if options.key?(:fakeweb) + 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 + 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 + end + + def ruby(ruby, options = {}) + expect_err = options.delete(:expect_err) + 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) + end + + def load_error_ruby(ruby, name, opts = {}) + cmd = <<-R + begin + #{ruby} + rescue LoadError => e + $stderr.puts "ZOMG LOAD ERROR"# if e.message.include?("-- #{name}") + end + R + ruby(cmd, opts.merge(:expect_err => true)) + end + + def gembin(cmd) + lib = File.expand_path("../../../lib", __FILE__) + old, ENV['RUBYOPT'] = ENV['RUBYOPT'], "#{ENV['RUBYOPT']} -I#{lib}" + cmd = bundled_app("bin/#{cmd}") unless cmd.to_s.include?("/") + sys_exec(cmd.to_s) + ensure + ENV['RUBYOPT'] = old + end + + def sys_exec(cmd, expect_err = false) + Open3.popen3(cmd.to_s) do |stdin, stdout, stderr| + @in_p, @out_p, @err_p = stdin, stdout, stderr + + yield @in_p if block_given? + @in_p.close + + @out = @out_p.read_available_bytes.strip + @err = @err_p.read_available_bytes.strip + 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)) + File.open(path, 'w') do |f| + f.puts config.to_yaml + end + config + end + + def gemfile(*args) + path = bundled_app("Gemfile") + path = args.shift if args.first.is_a?(Pathname) + str = args.shift || "" + path.dirname.mkpath + File.open(path.to_s, 'w') do |f| + f.puts strip_whitespace(str) + end + end + + def lockfile(*args) + path = bundled_app("Gemfile.lock") + path = args.shift if args.first.is_a?(Pathname) + str = args.shift || "" + File.open(path.to_s, 'w') do |f| + f.puts strip_whitespace(str) + end + end + + def strip_whitespace(str) + # Trim the leading spaces + spaces = str[/\A\s+/, 0] || "" + str.gsub(/^#{spaces}/, '') + end + + def install_gemfile(*args) + gemfile(*args) + opts = args.last.is_a?(Hash) ? args.last : {} + opts[:retry] ||= 0 + bundle :install, opts + end + + def install_gems(*gems) + gems.each do |g| + path = "#{gem_repo1}/gems/#{g}.gem" + + raise "OMG `#{path}` does not exist!" unless File.exist?(path) + + gem_command :install, "--no-rdoc --no-ri --ignore-dependencies #{path}" + end + end + + alias install_gem install_gems + + def with_gem_path_as(path) + gem_home, gem_path = ENV['GEM_HOME'], ENV['GEM_PATH'] + ENV['GEM_HOME'], ENV['GEM_PATH'] = path.to_s, path.to_s + yield + ensure + ENV['GEM_HOME'], ENV['GEM_PATH'] = gem_home, gem_path + end + + def break_git! + FileUtils.mkdir_p(tmp("broken_path")) + File.open(tmp("broken_path/git"), "w", 0755) do |f| + f.puts "#!/usr/bin/env ruby\nSTDERR.puts 'This is not the git you are looking for'\nexit 1" + end + + ENV["PATH"] = "#{tmp("broken_path")}:#{ENV["PATH"]}" + end + + def fake_man! + FileUtils.mkdir_p(tmp("fake_man")) + File.open(tmp("fake_man/man"), "w", 0755) do |f| + f.puts "#!/usr/bin/env ruby\nputs ARGV.inspect\n" + end + + ENV["PATH"] = "#{tmp("fake_man")}:#{ENV["PATH"]}" + end + + def kill_path! + ENV["PATH"] = "" + end + + def system_gems(*gems) + gems = gems.flatten + + FileUtils.rm_rf(system_gem_path) + FileUtils.mkdir_p(system_gem_path) + + Gem.clear_paths + + gem_home, gem_path, path = ENV['GEM_HOME'], ENV['GEM_PATH'], ENV['PATH'] + ENV['GEM_HOME'], ENV['GEM_PATH'] = system_gem_path.to_s, system_gem_path.to_s + + install_gems(*gems) + if block_given? + begin + yield + ensure + ENV['GEM_HOME'], ENV['GEM_PATH'] = gem_home, gem_path + ENV['PATH'] = path + end + end + end + + def realworld_system_gems(*gems) + gems = gems.flatten + + FileUtils.rm_rf(system_gem_path) + FileUtils.mkdir_p(system_gem_path) + + Gem.clear_paths + + gem_home, gem_path, path = ENV['GEM_HOME'], ENV['GEM_PATH'], ENV['PATH'] + ENV['GEM_HOME'], ENV['GEM_PATH'] = system_gem_path.to_s, system_gem_path.to_s + + gems.each do |gem| + gem_command :install, "--no-rdoc --no-ri #{gem}" + end + if block_given? + begin + yield + ensure + ENV['GEM_HOME'], ENV['GEM_PATH'] = gem_home, gem_path + ENV['PATH'] = path + end + end + end + + def cache_gems(*gems) + gems = gems.flatten + + FileUtils.rm_rf("#{bundled_app}/vendor/cache") + FileUtils.mkdir_p("#{bundled_app}/vendor/cache") + + gems.each do |g| + path = "#{gem_repo1}/gems/#{g}.gem" + raise "OMG `#{path}` does not exist!" unless File.exist?(path) + FileUtils.cp(path, "#{bundled_app}/vendor/cache") + end + end + + def simulate_new_machine + system_gems [] + FileUtils.rm_rf default_bundle_path + FileUtils.rm_rf bundled_app('.bundle') + end + + def simulate_platform(platform) + old, ENV['BUNDLER_SPEC_PLATFORM'] = ENV['BUNDLER_SPEC_PLATFORM'], platform.to_s + yield if block_given? + ensure + ENV['BUNDLER_SPEC_PLATFORM'] = old if block_given? + end + + def simulate_ruby_engine(engine, version = "1.6.0") + return if engine == local_ruby_engine + + old, ENV['BUNDLER_SPEC_RUBY_ENGINE'] = ENV['BUNDLER_SPEC_RUBY_ENGINE'], engine + old_version, ENV['BUNDLER_SPEC_RUBY_ENGINE_VERSION'] = ENV['BUNDLER_SPEC_RUBY_ENGINE_VERSION'], version + yield if block_given? + ensure + ENV['BUNDLER_SPEC_RUBY_ENGINE'] = old if block_given? + ENV['BUNDLER_SPEC_RUBY_ENGINE_VERSION'] = old_version if block_given? + end + + def simulate_bundler_version(version) + old, ENV['BUNDLER_SPEC_VERSION'] = ENV['BUNDLER_SPEC_VERSION'], version.to_s + yield if block_given? + ensure + ENV['BUNDLER_SPEC_VERSION'] = old if block_given? + end + + def revision_for(path) + Dir.chdir(path) { `git rev-parse HEAD`.strip } + end + + def capture_output + fake_stdout = StringIO.new + actual_stdout = $stdout + $stdout = fake_stdout + yield + fake_stdout.rewind + fake_stdout.read + ensure + $stdout = actual_stdout + end + + def with_read_only(pattern) + chmod = lambda do |dirmode, filemode| + lambda do |f| + mode = File.directory?(f) ? dirmode : filemode + File.chmod(mode, f) + end + end + + Dir[pattern].each(&chmod[0555, 0444]) + yield + ensure + Dir[pattern].each(&chmod[0755, 0644]) + end + end +end diff --git a/bundler-1.7.2/spec/support/indexes.rb b/bundler-1.7.2/spec/support/indexes.rb new file mode 100644 index 0000000..5aba3e2 --- /dev/null +++ b/bundler-1.7.2/spec/support/indexes.rb @@ -0,0 +1,280 @@ +module Spec + module Indexes + def dep(name, reqs = nil) + @deps ||= [] + @deps << Bundler::Dependency.new(name, reqs) + end + + def platform(*args) + @platforms ||= [] + @platforms.concat args.map { |p| Gem::Platform.new(p) } + end + + alias platforms platform + + def resolve + @platforms ||= ['ruby'] + deps = [] + @deps.each do |d| + @platforms.each do |p| + deps << Bundler::DepProxy.new(d, p) + end + end + Bundler::Resolver.resolve(deps, @index) + end + + def should_resolve_as(specs) + got = resolve + got = got.map { |s| s.full_name }.sort + expect(got).to eq(specs.sort) + end + + def should_conflict_on(names) + begin + got = resolve + flunk "The resolve succeeded with: #{got.map { |s| s.full_name }.sort.inspect}" + rescue Bundler::VersionConflict => e + expect(Array(names).sort).to eq(e.conflicts.sort) + end + end + + def gem(*args, &blk) + build_spec(*args, &blk).first + end + + def an_awesome_index + build_index do + gem "rack", %w(0.8 0.9 0.9.1 0.9.2 1.0 1.1) + gem "rack-mount", %w(0.4 0.5 0.5.1 0.5.2 0.6) + + # --- Rails + versions "1.2.3 2.2.3 2.3.5 3.0.0.beta 3.0.0.beta1" do |version| + gem "activesupport", version + gem "actionpack", version do + dep "activesupport", version + if version >= v('3.0.0.beta') + dep "rack", '~> 1.1' + dep "rack-mount", ">= 0.5" + elsif version > v('2.3') then dep "rack", '~> 1.0.0' + elsif version > v('2.0.0') then dep "rack", '~> 0.9.0' + end + end + gem "activerecord", version do + dep "activesupport", version + dep "arel", ">= 0.2" if version >= v('3.0.0.beta') + end + gem "actionmailer", version do + dep "activesupport", version + dep "actionmailer", version + end + if version < v('3.0.0.beta') + gem "railties", version do + dep "activerecord", version + dep "actionpack", version + dep "actionmailer", version + dep "activesupport", version + end + else + gem "railties", version + gem "rails", version do + dep "activerecord", version + dep "actionpack", version + dep "actionmailer", version + dep "activesupport", version + dep "railties", version + end + end + end + + versions '1.0 1.2 1.2.1 1.2.2 1.3 1.3.0.1 1.3.5 1.4.0 1.4.2 1.4.2.1' do |version| + platforms "ruby java mswin32 mingw32 x64-mingw32" do |platform| + next if version == v('1.4.2.1') && platform != pl('x86-mswin32') + next if version == v('1.4.2') && platform == pl('x86-mswin32') + gem "nokogiri", version, platform do + dep "weakling", ">= 0.0.3" if platform =~ pl('java') + end + end + end + + versions '0.0.1 0.0.2 0.0.3' do |version| + gem "weakling", version + end + + # --- Rails related + versions '1.2.3 2.2.3 2.3.5' do |version| + gem "activemerchant", version do + dep "activesupport", ">= #{version}" + end + end + end + end + + # Builder 3.1.4 will activate first, but if all + # goes well, it should resolve to 3.0.4 + def a_conflict_index + build_index do + gem "builder", %w(3.0.4 3.1.4) + gem("grape", '0.2.6') do + dep "builder", ">= 0" + end + + versions '3.2.8 3.2.9 3.2.10 3.2.11' do |version| + gem("activemodel", version) do + dep "builder", "~> 3.0.0" + end + end + + gem("my_app", '1.0.0') do + dep "activemodel", ">= 0" + dep "grape", ">= 0" + end + end + end + + def a_complex_conflict_index + build_index do + gem("a", %w(1.0.2 1.1.4 1.2.0 1.4.0)) do + dep "d", ">= 0" + end + + gem("d", %w(1.3.0 1.4.1)) do + dep "x", ">= 0" + end + + gem "d", "0.9.8" + + gem("b", '0.3.4') do + dep "a", ">= 1.5.0" + end + + gem("b", '0.3.5') do + dep "a", ">= 1.2" + end + + gem("b", '0.3.3') do + dep "a", "> 1.0" + end + + versions '3.2 3.3' do |version| + gem("c", version) do + dep "a", "~> 1.0" + end + end + + gem("my_app", '1.3.0') do + dep "c", ">= 4.0" + dep "b", ">= 0" + end + + gem("my_app", '1.2.0') do + dep "c", "~> 3.3.0" + dep "b", "0.3.4" + end + + gem("my_app", '1.1.0') do + dep "c", "~> 3.2.0" + dep "b", "0.3.5" + end + end + end + + def index_with_conflict_on_child + build_index do + gem "json", %w(1.6.5 1.7.7 1.8.0) + + gem("chef", '10.26') do + dep "json", [">= 1.4.4", "<= 1.7.7"] + end + + gem("berkshelf", "2.0.7") do + dep "json", ">= 1.7.7" + end + + gem("chef_app", '1.0.0') do + dep "berkshelf", "~> 2.0" + dep "chef", "~> 10.26" + end + end + end + + def a_unresovable_child_index + build_index do + gem "json", %w(1.8.0) + + gem("chef", '10.26') do + dep "json", [">= 1.4.4", "<= 1.7.7"] + end + + gem("berkshelf", "2.0.7") do + dep "json", ">= 1.7.7" + end + + gem("chef_app_error", '1.0.0') do + dep "berkshelf", "~> 2.0" + dep "chef", "~> 10.26" + end + end + end + + def a_index_with_root_conflict_on_child + build_index do + gem "builder", %w(2.1.2 3.0.1 3.1.3) + gem "i18n", %w(0.4.1 0.4.2) + + gem "activesupport", %w(3.0.0 3.0.1 3.0.5 3.1.7) + + gem("activemodel", '3.0.5') do + dep "activesupport", "= 3.0.5" + dep "builder", "~> 2.1.2" + dep 'i18n', '~> 0.4' + end + + gem("activemodel", '3.0.0') do + dep "activesupport", "= 3.0.0" + dep "builder", "~> 2.1.2" + dep 'i18n', '~> 0.4.1' + end + + gem("activemodel", '3.1.3') do + dep "activesupport", "= 3.1.3" + dep "builder", "~> 2.1.2" + dep 'i18n', '~> 0.5' + end + + gem("activerecord", '3.0.0') do + dep "activesupport", "= 3.0.0" + dep "activemodel", "= 3.0.0" + end + + gem("activerecord", '3.0.5') do + dep "activesupport", "= 3.0.5" + dep "activemodel", "= 3.0.5" + end + + gem("activerecord", '3.0.9') do + dep "activesupport", "= 3.1.5" + dep "activemodel", "= 3.1.5" + end + end + end + + def a_circular_index + build_index do + gem "rack", "1.0.1" + gem("foo", '0.2.6') do + dep "bar", ">= 0" + end + + gem("bar", "1.0.0") do + dep "foo", ">= 0" + end + + gem("circular_app", '1.0.0') do + dep "foo", ">= 0" + dep "bar", ">= 0" + end + end + end + + end +end diff --git a/bundler-1.7.2/spec/support/matchers.rb b/bundler-1.7.2/spec/support/matchers.rb new file mode 100644 index 0000000..e42c67b --- /dev/null +++ b/bundler-1.7.2/spec/support/matchers.rb @@ -0,0 +1,77 @@ +module Spec + module Matchers + RSpec::Matchers.define :have_dep do |*args| + dep = Bundler::Dependency.new(*args) + + match do |actual| + actual.length == 1 && actual.all? { |d| d == dep } + end + end + + RSpec::Matchers.define :have_gem do |*args| + match do |actual| + actual.length == args.length && actual.all? { |a| args.include?(a.full_name) } + end + end + + RSpec::Matchers.define :have_rubyopts do |*args| + args = args.flatten + args = args.first.split(/\s+/) if args.size == 1 + + #failure_message_for_should "Expected RUBYOPT to have options #{args.join(" ")}. It was #{ENV["RUBYOPT"]}" + + match do |actual| + actual = actual.split(/\s+/) if actual.is_a?(String) + args.all? {|arg| actual.include?(arg) } && actual.uniq.size == actual.size + end + end + + def should_be_installed(*names) + opts = names.last.is_a?(Hash) ? names.pop : {} + groups = Array(opts[:groups]) + groups << opts + names.each do |name| + name, version, platform = name.split(/\s+/) + version_const = name == 'bundler' ? 'Bundler::VERSION' : Spec::Builders.constantize(name) + run "require '#{name}.rb'; puts #{version_const}", *groups + actual_version, actual_platform = out.split(/\s+/) + expect(Gem::Version.new(actual_version)).to eq(Gem::Version.new(version)) + expect(actual_platform).to eq(platform) + end + end + + alias should_be_available should_be_installed + + def should_not_be_installed(*names) + opts = names.last.is_a?(Hash) ? names.pop : {} + groups = Array(opts[:groups]) || [] + names.each do |name| + name, version = name.split(/\s+/) + run <<-R, *(groups + [opts]) + begin + require '#{name}' + puts #{Spec::Builders.constantize(name)} + rescue LoadError, NameError + puts "WIN" + end + R + if version.nil? || out == "WIN" + expect(out).to eq("WIN") + else + expect(Gem::Version.new(out)).not_to eq(Gem::Version.new(version)) + end + end + end + + def should_be_locked + expect(bundled_app("Gemfile.lock")).to exist + end + + def lockfile_should_be(expected) + should_be_locked + spaces = expected[/\A\s+/, 0] || "" + expected.gsub!(/^#{spaces}/, '') + expect(bundled_app("Gemfile.lock").read).to eq(expected) + end + end +end diff --git a/bundler-1.7.2/spec/support/path.rb b/bundler-1.7.2/spec/support/path.rb new file mode 100644 index 0000000..74dbd89 --- /dev/null +++ b/bundler-1.7.2/spec/support/path.rb @@ -0,0 +1,81 @@ +require 'pathname' + +module Spec + module Path + def root + @root ||= Pathname.new(File.expand_path("../../..", __FILE__)) + end + + def tmp(*path) + root.join("tmp", *path) + end + + def home(*path) + tmp.join("home", *path) + end + + def default_bundle_path(*path) + system_gem_path(*path) + end + + def bundled_app(*path) + root = tmp.join("bundled_app") + FileUtils.mkdir_p(root) + root.join(*path) + end + + alias bundled_app1 bundled_app + + def bundled_app2(*path) + root = tmp.join("bundled_app2") + FileUtils.mkdir_p(root) + root.join(*path) + end + + def vendored_gems(path = nil) + bundled_app(*["vendor/bundle", Gem.ruby_engine, Gem::ConfigMap[:ruby_version], path].compact) + end + + def cached_gem(path) + bundled_app("vendor/cache/#{path}.gem") + end + + def base_system_gems + tmp.join("gems/base") + end + + def gem_repo1(*args) + tmp("gems/remote1", *args) + end + + def gem_repo_missing(*args) + tmp("gems/missing", *args) + end + + def gem_repo2(*args) + tmp("gems/remote2", *args) + end + + def gem_repo3(*args) + tmp("gems/remote3", *args) + end + + def security_repo(*args) + tmp("gems/security_repo", *args) + end + + def system_gem_path(*path) + tmp("gems/system", *path) + end + + def lib_path(*args) + tmp("libs", *args) + end + + def bundler_path + Pathname.new(File.expand_path('../../../lib', __FILE__)) + end + + extend self + end +end diff --git a/bundler-1.7.2/spec/support/permissions.rb b/bundler-1.7.2/spec/support/permissions.rb new file mode 100644 index 0000000..efdb4a5 --- /dev/null +++ b/bundler-1.7.2/spec/support/permissions.rb @@ -0,0 +1,10 @@ +module Spec + module Permissions + def with_umask(new_umask) + old_umask = File.umask(new_umask) + yield if block_given? + ensure + File.umask(old_umask) + end + end +end diff --git a/bundler-1.7.2/spec/support/platforms.rb b/bundler-1.7.2/spec/support/platforms.rb new file mode 100644 index 0000000..b574d63 --- /dev/null +++ b/bundler-1.7.2/spec/support/platforms.rb @@ -0,0 +1,94 @@ +module Spec + module Platforms + include Bundler::GemHelpers + + def rb + Gem::Platform::RUBY + end + + def mac + Gem::Platform.new('x86-darwin-10') + end + + def java + Gem::Platform.new([nil, "java", nil]) + end + + def linux + Gem::Platform.new(['x86', 'linux', nil]) + end + + def mswin + Gem::Platform.new(['x86', 'mswin32', nil]) + end + + def mingw + Gem::Platform.new(['x86', 'mingw32', nil]) + end + + def x64_mingw + Gem::Platform.new(['x64', 'mingw32', nil]) + end + + def all_platforms + [rb, java, linux, mswin, mingw, x64_mingw] + end + + def local + generic(Gem::Platform.local) + end + + def not_local + all_platforms.find { |p| p != generic(Gem::Platform.local) } + end + + def local_tag + if RUBY_PLATFORM == "java" + :jruby + else + :ruby + end + end + + def not_local_tag + [:ruby, :jruby].find { |tag| tag != local_tag } + end + + def local_ruby_engine + ENV["BUNDLER_SPEC_RUBY_ENGINE"] || (defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby") + end + + def local_engine_version + return ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] if ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] + + case local_ruby_engine + when "ruby" + RUBY_VERSION + when "rbx" + Rubinius::VERSION + when "jruby" + JRUBY_VERSION + else + raise BundlerError, "That RUBY_ENGINE is not recognized" + nil + end + end + + def not_local_engine_version + case not_local_tag + when :ruby + not_local_ruby_version + when :jruby + "1.6.1" + end + end + + def not_local_ruby_version + "1.12" + end + + def not_local_patchlevel + 9999 + end + end +end diff --git a/bundler-1.7.2/spec/support/ruby_ext.rb b/bundler-1.7.2/spec/support/ruby_ext.rb new file mode 100644 index 0000000..f1590a7 --- /dev/null +++ b/bundler-1.7.2/spec/support/ruby_ext.rb @@ -0,0 +1,20 @@ +class IO + def read_available_bytes(chunk_size = 16384, select_timeout = 0.02) + buffer = [] + + return "" if closed? || eof? + # IO.select cannot be used here due to the fact that it + # just does not work on windows + while true + begin + IO.select([self], nil, nil, select_timeout) + break if eof? # stop raising :-( + buffer << self.readpartial(chunk_size) + rescue(EOFError) + break + end + end + + return buffer.join + end +end diff --git a/bundler-1.7.2/spec/support/rubygems_ext.rb b/bundler-1.7.2/spec/support/rubygems_ext.rb new file mode 100644 index 0000000..6d71d32 --- /dev/null +++ b/bundler-1.7.2/spec/support/rubygems_ext.rb @@ -0,0 +1,39 @@ +require 'rubygems/user_interaction' +require 'support/path' + +module Spec + module Rubygems + def self.setup + Gem.clear_paths + + ENV['BUNDLE_PATH'] = nil + ENV['GEM_HOME'] = ENV['GEM_PATH'] = Path.base_system_gems.to_s + ENV['PATH'] = ["#{Path.root}/bin", "#{Path.system_gem_path}/bin", ENV['PATH']].join(File::PATH_SEPARATOR) + + unless File.exist?("#{Path.base_system_gems}") + FileUtils.mkdir_p(Path.base_system_gems) + puts "fetching fakeweb, artifice, sinatra, rake, rack, and builder for the tests to use..." + `gem install fakeweb artifice --no-rdoc --no-ri` + `gem install sinatra --version 1.2.7 --no-rdoc --no-ri` + # Rake version has to be consistent for tests to pass + `gem install rake --version 10.0.2 --no-rdoc --no-ri` + # 3.0.0 breaks 1.9.2 specs + `gem install builder --version 2.1.2 --no-rdoc --no-ri` + `gem install rack --no-rdoc --no-ri` + end + + ENV['HOME'] = Path.home.to_s + + Gem::DefaultUserInteraction.ui = Gem::SilentUI.new + end + + def gem_command(command, args = "", options = {}) + if command == :exec && !options[:no_quote] + args = args.gsub(/(?=")/, "\\") + args = %["#{args}"] + end + lib = File.join(File.dirname(__FILE__), '..', '..', 'lib') + %x{#{Gem.ruby} -I#{lib} -rubygems -S gem --backtrace #{command} #{args}}.strip + end + end +end diff --git a/bundler-1.7.2/spec/support/streams.rb b/bundler-1.7.2/spec/support/streams.rb new file mode 100644 index 0000000..610e999 --- /dev/null +++ b/bundler-1.7.2/spec/support/streams.rb @@ -0,0 +1,13 @@ +require 'stringio' + +def capture(*streams) + streams.map! { |stream| stream.to_s } + begin + result = StringIO.new + streams.each { |stream| eval "$#{stream} = result" } + yield + ensure + streams.each { |stream| eval("$#{stream} = #{stream.upcase}") } + end + result.string +end diff --git a/bundler-1.7.2/spec/support/sudo.rb b/bundler-1.7.2/spec/support/sudo.rb new file mode 100644 index 0000000..2192b09 --- /dev/null +++ b/bundler-1.7.2/spec/support/sudo.rb @@ -0,0 +1,16 @@ +module Spec + module Sudo + def self.present? + @which_sudo ||= Bundler.which("sudo") + end + + def sudo(cmd) + raise "sudo not present" unless Sudo.present? + sys_exec("sudo #{cmd}") + end + + def chown_system_gems_to_root + sudo "chown -R root #{system_gem_path}" + end + end +end diff --git a/bundler-1.7.2/spec/update/gems_spec.rb b/bundler-1.7.2/spec/update/gems_spec.rb new file mode 100644 index 0000000..856e922 --- /dev/null +++ b/bundler-1.7.2/spec/update/gems_spec.rb @@ -0,0 +1,201 @@ +require "spec_helper" + +describe "bundle update" do + before :each do + build_repo2 + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport" + gem "rack-obama" + G + end + + describe "with no arguments" do + it "updates the entire bundle" do + update_repo2 do + build_gem "activesupport", "3.0" + end + + bundle "update" + should_be_installed "rack 1.2", "rack-obama 1.0", "activesupport 3.0" + end + + it "doesn't delete the Gemfile.lock file if something goes wrong" do + gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport" + gem "rack-obama" + exit! + G + bundle "update" + expect(bundled_app("Gemfile.lock")).to exist + end + end + + describe "--quiet argument" do + it "shows UI messages without --quiet argument" do + bundle "update" + expect(out).to include("Fetching source") + end + + it "does not show UI messages with --quiet argument" do + bundle "update --quiet" + expect(out).not_to include("Fetching source") + end + end + + describe "with a top level dependency" do + it "unlocks all child dependencies that are unrelated to other locked dependencies" do + update_repo2 do + build_gem "activesupport", "3.0" + end + + bundle "update rack-obama" + should_be_installed "rack 1.2", "rack-obama 1.0", "activesupport 2.3.5" + end + end + + describe "with an unknown dependency" do + it "should inform the user" do + 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 + expect(out).to include "Did you mean activesupport?" + end + end + + describe "with a child dependency" do + it "should update the child dependency" do + update_repo2 + bundle "update rack" + should_be_installed "rack 1.2" + end + end + + describe "with --local option" do + it "doesn't hit repo2" do + FileUtils.rm_rf(gem_repo2) + + bundle "update --local" + expect(out).not_to match(/Fetching source index/) + end + end + + describe "with --group option" do + it "should update only specifed group gems" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport", :group => :development + gem "rack" + G + update_repo2 do + build_gem "activesupport", "3.0" + end + bundle "update --group development" + should_be_installed "activesupport 3.0" + should_not_be_installed "rack 1.2" + end + end +end + +describe "bundle update in more complicated situations" do + before :each do + build_repo2 + end + + it "will eagerly unlock dependencies of a specified gem" do + install_gemfile <<-G + source "file://#{gem_repo2}" + + gem "thin" + gem "rack-obama" + G + + update_repo2 do + build_gem "thin" , '2.0' do |s| + s.add_dependency "rack" + end + end + + bundle "update thin" + should_be_installed "thin 2.0", "rack 1.2", "rack-obama 1.0" + end +end + +describe "bundle update without a Gemfile.lock" do + it "should not explode" do + build_repo2 + + gemfile <<-G + source "file://#{gem_repo2}" + + gem "rack", "1.0" + G + + bundle "update" + + should_be_installed "rack 1.0.0" + end +end + +describe "bundle update when a gem depends on a newer version of bundler" do + before(:each) do + build_repo2 do + build_gem "rails", "3.0.1" do |s| + s.add_dependency "bundler", Bundler::VERSION.succ + end + end + + gemfile <<-G + source "file://#{gem_repo2}" + gem "rails", "3.0.1" + G + end + + it "should not explode" do + bundle "update" + expect(err).to be_empty + end + + it "should explain that bundler conflicted" do + bundle "update" + expect(out).not_to match(/in snapshot/i) + expect(out).to match(/current Bundler version/i) + expect(out).to match(/perhaps you need to update bundler/i) + end +end + +describe "bundle update" do + it "shows the previous version of the gem when updated from rubygems source" do + build_repo2 + + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport" + G + + bundle "update" + expect(out).to include("Using activesupport 2.3.5") + + update_repo2 do + build_gem "activesupport", "3.0" + end + + bundle "update" + expect(out).to include("Installing activesupport 3.0 (was 2.3.5)") + end + + it "shows error message when Gemfile.lock is not preset and gem is specified" do + install_gemfile <<-G + source "file://#{gem_repo2}" + gem "activesupport" + G + + bundle "update nonexisting", :exitstatus => true + 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) + end +end diff --git a/bundler-1.7.2/spec/update/git_spec.rb b/bundler-1.7.2/spec/update/git_spec.rb new file mode 100644 index 0000000..2452636 --- /dev/null +++ b/bundler-1.7.2/spec/update/git_spec.rb @@ -0,0 +1,283 @@ +require "spec_helper" + +describe "bundle update" do + describe "git sources" do + it "floats on a branch when :branch is used" do + build_git "foo", "1.0" + update_git "foo", :branch => "omg" + + install_gemfile <<-G + git "#{lib_path('foo-1.0')}", :branch => "omg" do + gem 'foo' + end + G + + update_git "foo", :branch => "omg" do |s| + s.write "lib/foo.rb", "FOO = '1.1'" + end + + bundle "update" + + should_be_installed "foo 1.1" + end + + it "updates correctly when you have like craziness" do + build_lib "activesupport", "3.0", :path => lib_path("rails/activesupport") + build_git "rails", "3.0", :path => lib_path("rails") do |s| + s.add_dependency "activesupport", "= 3.0" + end + + install_gemfile <<-G + gem "rails", :git => "#{lib_path('rails')}" + G + + bundle "update rails" + expect(out).to include("Using activesupport 3.0 from #{lib_path('rails')} (at master)") + should_be_installed "rails 3.0", "activesupport 3.0" + end + + it "floats on a branch when :branch is used and the source is specified in the update" do + build_git "foo", "1.0", :path => lib_path("foo") + update_git "foo", :branch => "omg", :path => lib_path("foo") + + install_gemfile <<-G + git "#{lib_path('foo')}", :branch => "omg" do + gem 'foo' + end + G + + update_git "foo", :branch => "omg", :path => lib_path("foo") do |s| + s.write "lib/foo.rb", "FOO = '1.1'" + end + + bundle "update --source foo" + + should_be_installed "foo 1.1" + end + + it "floats on master when updating all gems that are pinned to the source even if you have child dependencies" do + build_git "foo", :path => lib_path('foo') + build_gem "bar", :to_system => true do |s| + s.add_dependency "foo" + end + + install_gemfile <<-G + gem "foo", :git => "#{lib_path('foo')}" + gem "bar" + G + + update_git "foo", :path => lib_path('foo') do |s| + s.write "lib/foo.rb", "FOO = '1.1'" + end + + bundle "update foo" + + should_be_installed "foo 1.1" + end + + it "notices when you change the repo url in the Gemfile" do + build_git "foo", :path => lib_path("foo_one") + build_git "foo", :path => lib_path("foo_two") + + install_gemfile <<-G + gem "foo", "1.0", :git => "#{lib_path('foo_one')}" + G + + FileUtils.rm_rf lib_path("foo_one") + + install_gemfile <<-G + gem "foo", "1.0", :git => "#{lib_path('foo_two')}" + G + + expect(err).to be_empty + expect(out).to include("Fetching #{lib_path}/foo_two") + expect(out).to include("Your bundle is complete!") + end + + + it "fetches tags from the remote" do + build_git "foo" + @remote = build_git("bar", :bare => true) + update_git "foo", :remote => @remote.path + update_git "foo", :push => "master" + + install_gemfile <<-G + gem 'foo', :git => "#{@remote.path}" + G + + # Create a new tag on the remote that needs fetching + update_git "foo", :tag => "fubar" + update_git "foo", :push => "fubar" + + gemfile <<-G + gem 'foo', :git => "#{@remote.path}", :tag => "fubar" + G + + bundle "update", :exitstatus => true + expect(exitstatus).to eq(0) + end + + describe "with submodules" do + before :each do + build_gem "submodule", :to_system => true do |s| + s.write "lib/submodule.rb", "puts 'GEM'" + end + + build_git "submodule", "1.0" do |s| + s.write "lib/submodule.rb", "puts 'GIT'" + end + + build_git "has_submodule", "1.0" do |s| + s.add_dependency "submodule" + end + + Dir.chdir(lib_path('has_submodule-1.0')) do + `git submodule add #{lib_path('submodule-1.0')} submodule-1.0` + `git commit -m "submodulator"` + end + end + + it "it unlocks the source when submodules are added to a git source" do + install_gemfile <<-G + git "#{lib_path('has_submodule-1.0')}" do + gem "has_submodule" + end + G + + run "require 'submodule'" + expect(out).to eq('GEM') + + install_gemfile <<-G + git "#{lib_path('has_submodule-1.0')}", :submodules => true do + gem "has_submodule" + end + G + + run "require 'submodule'" + expect(out).to eq('GIT') + end + + it "it unlocks the source when submodules are removed from git source" do + pending "This would require actually removing the submodule from the clone" + install_gemfile <<-G + git "#{lib_path('has_submodule-1.0')}", :submodules => true do + gem "has_submodule" + end + G + + run "require 'submodule'" + expect(out).to eq('GIT') + + install_gemfile <<-G + git "#{lib_path('has_submodule-1.0')}" do + gem "has_submodule" + end + G + + run "require 'submodule'" + expect(out).to eq('GEM') + end + end + + it "errors with a message when the .git repo is gone" do + build_git "foo", "1.0" + + install_gemfile <<-G + gem "foo", :git => "#{lib_path('foo-1.0')}" + G + + lib_path("foo-1.0").join(".git").rmtree + + bundle :update, :expect_err => true + expect(out).to include(lib_path("foo-1.0").to_s) + end + + it "should not explode on invalid revision on update of gem by name" do + build_git "rack", "0.8" + + build_git "rack", "0.8", :path => lib_path('local-rack') do |s| + s.write "lib/rack.rb", "puts :LOCAL" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :git => "#{lib_path('rack-0.8')}", :branch => "master" + G + + bundle %|config local.rack #{lib_path('local-rack')}| + bundle "update rack" + expect(out).to include("Your bundle is updated!") + end + + it "shows the previous version of the gem" do + build_git "rails", "3.0", :path => lib_path("rails") + + install_gemfile <<-G + gem "rails", :git => "#{lib_path('rails')}" + G + + lockfile <<-G + GIT + remote: #{lib_path("rails")} + specs: + rails (2.3.2) + + PLATFORMS + #{generic(Gem::Platform.local)} + + DEPENDENCIES + rails! + G + + bundle "update" + expect(out).to include("Using rails 3.0 (was 2.3.2) from #{lib_path('rails')} (at master)") + end + end + + describe "with --source flag" do + before :each do + build_repo2 + @git = build_git "foo", :path => lib_path("foo") do |s| + s.executables = "foobar" + end + + install_gemfile <<-G + source "file://#{gem_repo2}" + git "#{lib_path('foo')}" do + gem 'foo' + end + gem 'rack' + G + end + + it "updates the source" do + update_git "foo", :path => @git.path + + bundle "update --source foo" + + in_app_root do + run <<-RUBY + require 'foo' + puts "WIN" if defined?(FOO_PREV_REF) + RUBY + + expect(out).to eq("WIN") + end + end + + it "unlocks gems that were originally pulled in by the source" do + update_git "foo", "2.0", :path => @git.path + + bundle "update --source foo" + should_be_installed "foo 2.0" + end + + it "leaves all other gems frozen" do + update_repo2 + update_git "foo", :path => @git.path + + bundle "update --source foo" + should_be_installed "rack 1.0" + end + end +end diff --git a/bundler-1.7.2/spec/update/path_spec.rb b/bundler-1.7.2/spec/update/path_spec.rb new file mode 100644 index 0000000..fdc4615 --- /dev/null +++ b/bundler-1.7.2/spec/update/path_spec.rb @@ -0,0 +1,18 @@ +require "spec_helper" + +describe "path sources" do + describe "bundle update --source" do + it "shows the previous version of the gem when updated from path source" do + build_lib "activesupport", "2.3.5", :path => lib_path("rails/activesupport") + + install_gemfile <<-G + gem "activesupport", :path => "#{lib_path('rails/activesupport')}" + G + + build_lib "activesupport", "3.0", :path => lib_path("rails/activesupport") + + bundle "update --source activesupport" + expect(out).to include("Using activesupport 3.0 (was 2.3.5) from source at #{lib_path('rails/activesupport')}") + end + end +end