├── .rspec ├── lib └── bundler │ ├── ssl_certs │ ├── .document │ ├── index.rubygems.org │ │ └── GlobalSignRootCA.pem │ ├── rubygems.global.ssl.fastly.net │ │ └── DigiCertHighAssuranceEVRootCA.pem │ ├── rubygems.org │ │ └── AddTrustExternalCARoot.pem │ └── certificate_manager.rb │ ├── templates │ ├── newgem │ │ ├── rspec.tt │ │ ├── exe │ │ │ └── newgem.tt │ │ ├── ext │ │ │ └── newgem │ │ │ │ ├── extconf.rb.tt │ │ │ │ ├── newgem.h.tt │ │ │ │ └── newgem.c.tt │ │ ├── Gemfile.tt │ │ ├── spec │ │ │ ├── spec_helper.rb.tt │ │ │ └── newgem_spec.rb.tt │ │ ├── .travis.yml.tt │ │ ├── test │ │ │ ├── test_helper.rb.tt │ │ │ └── newgem_test.rb.tt │ │ ├── bin │ │ │ ├── setup.tt │ │ │ └── console.tt │ │ ├── gitignore.tt │ │ ├── lib │ │ │ ├── newgem │ │ │ │ └── version.rb.tt │ │ │ └── newgem.rb.tt │ │ ├── Rakefile.tt │ │ ├── LICENSE.txt.tt │ │ ├── newgem.gemspec.tt │ │ └── README.md.tt │ ├── Gemfile │ ├── Executable.standalone │ └── Executable │ ├── vendor │ ├── thor │ │ └── lib │ │ │ └── thor │ │ │ ├── version.rb │ │ │ ├── parser.rb │ │ │ ├── core_ext │ │ │ ├── io_binary_read.rb │ │ │ └── hash_with_indifferent_access.rb │ │ │ ├── line_editor.rb │ │ │ ├── line_editor │ │ │ ├── basic.rb │ │ │ └── readline.rb │ │ │ ├── error.rb │ │ │ ├── actions │ │ │ └── create_link.rb │ │ │ └── parser │ │ │ └── argument.rb │ ├── postit │ │ └── lib │ │ │ ├── postit │ │ │ ├── version.rb │ │ │ ├── setup.rb │ │ │ ├── parser.rb │ │ │ ├── installer.rb │ │ │ └── environment.rb │ │ │ └── postit.rb │ ├── compact_index_client │ │ └── lib │ │ │ └── compact_index_client │ │ │ └── version.rb │ ├── molinillo │ │ └── lib │ │ │ ├── molinillo │ │ │ ├── gem_metadata.rb │ │ │ ├── dependency_graph │ │ │ │ ├── tag.rb │ │ │ │ ├── action.rb │ │ │ │ ├── set_payload.rb │ │ │ │ ├── detach_vertex_named.rb │ │ │ │ ├── add_vertex.rb │ │ │ │ └── add_edge_no_circular.rb │ │ │ ├── resolver.rb │ │ │ ├── delegates │ │ │ │ └── resolution_state.rb │ │ │ ├── state.rb │ │ │ └── modules │ │ │ │ └── ui.rb │ │ │ └── molinillo.rb │ └── net │ │ └── http │ │ └── faster.rb │ ├── vendored_molinillo.rb │ ├── vendored_thor.rb │ ├── gem_tasks.rb │ ├── ui.rb │ ├── constants.rb │ ├── source │ ├── gemspec.rb │ └── rubygems │ │ └── remote.rb │ ├── rubygems_gem_installer.rb │ ├── match_platform.rb │ ├── ui │ ├── rg_proxy.rb │ └── silent.rb │ ├── vlad.rb │ ├── version.rb │ ├── vendored_persistent.rb │ ├── stub_specification.rb │ ├── plugin │ ├── installer │ │ ├── rubygems.rb │ │ └── git.rb │ ├── source_list.rb │ └── dsl.rb │ ├── cli │ ├── clean.rb │ ├── open.rb │ ├── viz.rb │ ├── console.rb │ ├── init.rb │ ├── plugin.rb │ ├── cache.rb │ ├── lock.rb │ ├── binstubs.rb │ ├── check.rb │ ├── platform.rb │ ├── package.rb │ ├── inject.rb │ └── common.rb │ ├── deprecate.rb │ ├── capistrano.rb │ ├── psyched_yaml.rb │ ├── ruby_dsl.rb │ ├── setup.rb │ ├── environment.rb │ ├── dep_proxy.rb │ ├── fetcher │ ├── base.rb │ └── index.rb │ ├── environment_preserver.rb │ ├── source.rb │ ├── gem_helpers.rb │ ├── uri_credentials_filter.rb │ ├── gem_remote_fetcher.rb │ ├── retry.rb │ ├── installer │ └── standalone.rb │ ├── similarity_detector.rb │ ├── postit_trampoline.rb │ ├── current_ruby.rb │ └── worker.rb ├── exe ├── bundler ├── bundle └── bundle_ruby ├── spec ├── support │ ├── fakeweb │ │ ├── rack-1.0.0.marshal │ │ └── windows.rb │ ├── permissions.rb │ ├── artifice │ │ ├── compact_index_forbidden.rb │ │ ├── endpoint_api_forbidden.rb │ │ ├── endpoint_marshal_fail.rb │ │ ├── endpoint_timeout.rb │ │ ├── endpoint_basic_authentication.rb │ │ ├── endpoint_redirect.rb │ │ ├── compact_index_basic_authentication.rb │ │ ├── endpoint_mirror_source.rb │ │ ├── endopint_marshal_fail_basic_authentication.rb │ │ ├── endpoint_extra_missing.rb │ │ ├── endpoint_host_redirect.rb │ │ ├── endpoint_api_missing.rb │ │ ├── compact_index_checksum_mismatch.rb │ │ ├── compact_index_redirects.rb │ │ ├── compact_index_extra_missing.rb │ │ ├── compact_index_api_missing.rb │ │ ├── compact_index_host_redirect.rb │ │ ├── endpoint_fallback.rb │ │ ├── endpoint_strict_basic_authentication.rb │ │ ├── compact_index_strict_basic_authentication.rb │ │ ├── endpoint_500.rb │ │ ├── endpoint_extra.rb │ │ ├── endpoint_extra_api.rb │ │ ├── compact_index_extra.rb │ │ ├── endpoint_creds_diff_host.rb │ │ ├── compact_index_creds_diff_host.rb │ │ ├── compact_index_concurrent_download.rb │ │ └── compact_index_extra_api.rb │ ├── streams.rb │ ├── sudo.rb │ ├── less_than_proc.rb │ ├── code_climate.rb │ ├── hax.rb │ ├── sometimes.rb │ ├── platforms.rb │ └── path.rb ├── bundler │ ├── psyched_yaml_spec.rb │ ├── index_spec.rb │ ├── fetcher │ │ └── compact_index_spec.rb │ ├── plugin │ │ ├── source_list_spec.rb │ │ ├── dsl_spec.rb │ │ └── api_spec.rb │ ├── source │ │ ├── rubygems_spec.rb │ │ └── git │ │ │ └── git_proxy_spec.rb │ ├── spec_set_spec.rb │ ├── retry_spec.rb │ ├── cli_spec.rb │ ├── endpoint_specification_spec.rb │ └── env_spec.rb ├── other │ ├── ssl_cert_spec.rb │ └── cli_dispatch_spec.rb ├── update │ └── path_spec.rb ├── install │ ├── gems │ │ ├── win32_spec.rb │ │ ├── mirror_spec.rb │ │ └── native_extensions_spec.rb │ ├── upgrade_spec.rb │ ├── force_spec.rb │ ├── gemfile │ │ ├── install_if.rb │ │ └── eval_gemfile_spec.rb │ ├── prereleases_spec.rb │ ├── yanked_spec.rb │ ├── git_spec.rb │ ├── binstubs_spec.rb │ └── gemfile_spec.rb ├── commands │ ├── licenses_spec.rb │ ├── init_spec.rb │ └── viz_spec.rb ├── lock │ └── git_spec.rb ├── cache │ ├── cache_path_spec.rb │ └── platform_spec.rb ├── runtime │ ├── gem_tasks_spec.rb │ └── platform_spec.rb └── realworld │ ├── dependency_api_spec.rb │ ├── gemfile_source_header_spec.rb │ └── parallel_spec.rb ├── man ├── index.txt ├── bundle-platform.ronn └── bundle-lock.ronn ├── .codeclimate.yml ├── bin ├── rspec ├── rubocop ├── rake └── with_rubygems ├── .gitignore ├── LICENSE.md └── bundler.gemspec /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | --warnings 4 | -------------------------------------------------------------------------------- /lib/bundler/ssl_certs/.document: -------------------------------------------------------------------------------- 1 | # Ignore all files in this directory 2 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/rspec.tt: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /lib/bundler/vendor/thor/lib/thor/version.rb: -------------------------------------------------------------------------------- 1 | class Bundler::Thor 2 | VERSION = "0.19.1" 3 | end 4 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/exe/newgem.tt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "<%= config[:namespaced_path] %>" 4 | -------------------------------------------------------------------------------- /exe/bundler: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | load File.expand_path("../bundle", __FILE__) 5 | -------------------------------------------------------------------------------- /lib/bundler/vendor/postit/lib/postit/version.rb: -------------------------------------------------------------------------------- 1 | module BundlerVendoredPostIt::PostIt 2 | VERSION = '0.2.0'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt: -------------------------------------------------------------------------------- 1 | require "mkmf" 2 | 3 | create_makefile(<%= config[:makefile_path].inspect %>) 4 | -------------------------------------------------------------------------------- /lib/bundler/templates/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # A sample Gemfile 3 | source "https://rubygems.org" 4 | 5 | # gem "rails" 6 | -------------------------------------------------------------------------------- /lib/bundler/vendored_molinillo.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler; end 3 | require "bundler/vendor/molinillo/lib/molinillo" 4 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/Gemfile.tt: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in <%=config[:name]%>.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/spec/spec_helper.rb.tt: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__) 2 | require "<%= config[:namespaced_path] %>" 3 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/.travis.yml.tt: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: ruby 3 | rvm: 4 | - <%= RUBY_VERSION %> 5 | before_install: gem install bundler -v <%= Bundler::VERSION %> 6 | -------------------------------------------------------------------------------- /lib/bundler/vendored_thor.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler; end 3 | require "bundler/vendor/thor/lib/thor" 4 | require "bundler/vendor/thor/lib/thor/actions" 5 | -------------------------------------------------------------------------------- /lib/bundler/gem_tasks.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "rake/clean" 3 | CLOBBER.include "pkg" 4 | 5 | require "bundler/gem_helper" 6 | Bundler::GemHelper.install_tasks 7 | -------------------------------------------------------------------------------- /lib/bundler/vendor/compact_index_client/lib/compact_index_client/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Bundler::CompactIndexClient 3 | VERSION = "0.1.0".freeze 4 | end 5 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/test/test_helper.rb.tt: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) 2 | require '<%= config[:namespaced_path] %>' 3 | 4 | require 'minitest/autorun' 5 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/bin/setup.tt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler::Molinillo 3 | # The version of Bundler::Molinillo. 4 | VERSION = '0.5.0'.freeze 5 | end 6 | -------------------------------------------------------------------------------- /spec/support/fakeweb/rack-1.0.0.marshal: -------------------------------------------------------------------------------- 1 | [{ :dependencies[ [" thin" >= 0["ruby-openid" ~> 2.0.0[" mongrel" >= 0["memcache-client" >= 0[" fcgi" >= 0[" camping" >= 0["test-spec" >= 0: platform" ruby: name" rack: number" 2 | 1.0.0 -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/ext/newgem/newgem.h.tt: -------------------------------------------------------------------------------- 1 | #ifndef <%=config[:underscored_name].upcase%>_H 2 | #define <%=config[:underscored_name].upcase%>_H 1 3 | 4 | #include "ruby.h" 5 | 6 | #endif /* <%=config[:underscored_name].upcase%>_H */ 7 | -------------------------------------------------------------------------------- /lib/bundler/ui.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | module UI 4 | autoload :RGProxy, "bundler/ui/rg_proxy" 5 | autoload :Shell, "bundler/ui/shell" 6 | autoload :Silent, "bundler/ui/silent" 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/bundler/constants.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | WINDOWS = RbConfig::CONFIG["host_os"] =~ /(msdos|mswin|djgpp|mingw)/ 4 | FREEBSD = RbConfig::CONFIG["host_os"] =~ /bsd/ 5 | NULL = WINDOWS ? "NUL" : "/dev/null" 6 | end 7 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/gitignore.tt: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | <%- if config[:ext] -%> 11 | *.bundle 12 | *.so 13 | *.o 14 | *.a 15 | mkmf.log 16 | <%- end -%> 17 | -------------------------------------------------------------------------------- /lib/bundler/vendor/thor/lib/thor/parser.rb: -------------------------------------------------------------------------------- 1 | require "bundler/vendor/thor/lib/thor/parser/argument" 2 | require "bundler/vendor/thor/lib/thor/parser/arguments" 3 | require "bundler/vendor/thor/lib/thor/parser/option" 4 | require "bundler/vendor/thor/lib/thor/parser/options" 5 | -------------------------------------------------------------------------------- /spec/support/permissions.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Spec 3 | module Permissions 4 | def with_umask(new_umask) 5 | old_umask = File.umask(new_umask) 6 | yield if block_given? 7 | ensure 8 | File.umask(old_umask) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/bundler/source/gemspec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class Source 4 | class Gemspec < Path 5 | attr_reader :gemspec 6 | 7 | def initialize(options) 8 | super 9 | @gemspec = options["gemspec"] 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /man/index.txt: -------------------------------------------------------------------------------- 1 | Gemfile(5) gemfile.5 2 | bundle-install bundle-install.1 3 | bundle-update bundle-update.1 4 | bundle-package bundle-package.1 5 | bundle-exec bundle-exec.1 6 | bundle-config bundle-config.1 7 | bundle-platform bundle-platform.1 8 | bundle-gem bundle-gem.1 9 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/lib/newgem/version.rb.tt: -------------------------------------------------------------------------------- 1 | <%- config[:constant_array].each_with_index do |c,i| -%> 2 | <%= ' '*i %>module <%= c %> 3 | <%- end -%> 4 | <%= ' '*config[:constant_array].size %>VERSION = "0.1.0" 5 | <%- (config[:constant_array].size-1).downto(0) do |i| -%> 6 | <%= ' '*i %>end 7 | <%- end -%> 8 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/ext/newgem/newgem.c.tt: -------------------------------------------------------------------------------- 1 | #include "<%=config[:underscored_name]%>.h" 2 | 3 | VALUE rb_m<%=config[:constant_array].join%>; 4 | 5 | void 6 | Init_<%=config[:underscored_name]%>(void) 7 | { 8 | rb_m<%=config[:constant_array].join%> = rb_define_module(<%=config[:constant_name].inspect%>); 9 | } 10 | -------------------------------------------------------------------------------- /spec/bundler/psyched_yaml_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | require "bundler/psyched_yaml" 4 | 5 | describe "Bundler::YamlLibrarySyntaxError" do 6 | it "is raised on YAML parse errors" do 7 | expect { YAML.parse "{foo" }.to raise_error(Bundler::YamlLibrarySyntaxError) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/bundler/rubygems_gem_installer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "rubygems/installer" 3 | 4 | module Bundler 5 | class RubyGemsGemInstaller < Gem::Installer 6 | def check_executable_overwrite(filename) 7 | # Bundler needs to install gems regardless of binstub overwriting 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/spec/newgem_spec.rb.tt: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe <%= config[:constant_name] %> do 4 | it "has a version number" do 5 | expect(<%= config[:constant_name] %>::VERSION).not_to be nil 6 | end 7 | 8 | it "does something useful" do 9 | expect(false).to eq(true) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/test/newgem_test.rb.tt: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class <%= config[:constant_name] %>Test < Minitest::Test 4 | def test_that_it_has_a_version_number 5 | refute_nil ::<%= config[:constant_name] %>::VERSION 6 | end 7 | 8 | def test_it_does_something_useful 9 | assert false 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/support/artifice/compact_index_forbidden.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../compact_index", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class CompactIndexForbidden < CompactIndexAPI 7 | get "/versions" do 8 | halt 403 9 | end 10 | end 11 | 12 | Artifice.activate_with(CompactIndexForbidden) 13 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_api_forbidden.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointApiForbidden < Endpoint 7 | get "/api/v1/dependencies" do 8 | halt 403 9 | end 10 | end 11 | 12 | Artifice.activate_with(EndpointApiForbidden) 13 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_marshal_fail.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint_fallback", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointMarshalFail < EndpointFallback 7 | get "/api/v1/dependencies" do 8 | "f0283y01hasf" 9 | end 10 | end 11 | 12 | Artifice.activate_with(EndpointMarshalFail) 13 | -------------------------------------------------------------------------------- /lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb: -------------------------------------------------------------------------------- 1 | class IO #:nodoc: 2 | class << self 3 | def binread(file, *args) 4 | fail ArgumentError, "wrong number of arguments (#{1 + args.size} for 1..3)" unless args.size < 3 5 | File.open(file, "rb") do |f| 6 | f.read(*args) 7 | end 8 | end unless method_defined? :binread 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /spec/support/streams.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "stringio" 3 | 4 | def capture(*streams) 5 | streams.map!(&:to_s) 6 | begin 7 | result = StringIO.new 8 | streams.each {|stream| eval "$#{stream} = result" } 9 | yield 10 | ensure 11 | streams.each {|stream| eval("$#{stream} = #{stream.upcase}") } 12 | end 13 | result.string 14 | end 15 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_timeout.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint_fallback", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointTimeout < EndpointFallback 7 | SLEEP_TIMEOUT = 15 8 | 9 | get "/api/v1/dependencies" do 10 | sleep(SLEEP_TIMEOUT) 11 | end 12 | end 13 | 14 | Artifice.activate_with(EndpointTimeout) 15 | -------------------------------------------------------------------------------- /lib/bundler/match_platform.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "bundler/gem_helpers" 3 | 4 | module Bundler 5 | module MatchPlatform 6 | include GemHelpers 7 | 8 | def match_platform(p) 9 | Gem::Platform::RUBY == platform || 10 | platform.nil? || p == platform || 11 | generic(Gem::Platform.new(platform)) === p 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/bundler/ui/rg_proxy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "bundler/ui" 3 | require "rubygems/user_interaction" 4 | 5 | module Bundler 6 | module UI 7 | class RGProxy < ::Gem::SilentUI 8 | def initialize(ui) 9 | @ui = ui 10 | super() 11 | end 12 | 13 | def say(message) 14 | @ui && @ui.debug(message) 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/bundler/vlad.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Vlad task for Bundler. 3 | # 4 | # Add "require 'bundler/vlad'" in your Vlad deploy.rb, and 5 | # include the vlad:bundle:install task in your vlad:deploy task. 6 | require "bundler/deployment" 7 | 8 | include Rake::DSL if defined? Rake::DSL 9 | 10 | namespace :vlad do 11 | Bundler::Deployment.define_task(Rake::RemoteTask, :remote_task, :roles => :app) 12 | end 13 | -------------------------------------------------------------------------------- /lib/bundler/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby 1.9.3 and old RubyGems don't play nice with frozen version strings 4 | # rubocop:disable MutableConstant 5 | 6 | module Bundler 7 | # We're doing this because we might write tests that deal 8 | # with other versions of bundler and we are unsure how to 9 | # handle this better. 10 | VERSION = "1.13.0.rc.1" unless defined?(::Bundler::VERSION) 11 | end 12 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_basic_authentication.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointBasicAuthentication < Endpoint 7 | before do 8 | unless env["HTTP_AUTHORIZATION"] 9 | halt 401, "Authentication info not supplied" 10 | end 11 | end 12 | end 13 | 14 | Artifice.activate_with(EndpointBasicAuthentication) 15 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_redirect.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointRedirect < Endpoint 7 | get "/fetch/actual/gem/:id" do 8 | redirect "/fetch/actual/gem/#{params[:id]}" 9 | end 10 | 11 | get "/api/v1/dependencies" do 12 | status 404 13 | end 14 | end 15 | 16 | Artifice.activate_with(EndpointRedirect) 17 | -------------------------------------------------------------------------------- /spec/support/sudo.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Spec 3 | module Sudo 4 | def self.present? 5 | @which_sudo ||= Bundler.which("sudo") 6 | end 7 | 8 | def sudo(cmd) 9 | raise "sudo not present" unless Sudo.present? 10 | sys_exec("sudo #{cmd}") 11 | end 12 | 13 | def chown_system_gems_to_root 14 | sudo "chown -R root #{system_gem_path}" 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/bundler/vendor/postit/lib/postit/setup.rb: -------------------------------------------------------------------------------- 1 | require 'bundler/vendor/postit/lib/postit/environment' 2 | require 'bundler/vendor/postit/lib/postit/installer' 3 | 4 | environment = BundlerVendoredPostIt::PostIt::Environment.new(ARGV) 5 | version = environment.bundler_version 6 | 7 | installer = BundlerVendoredPostIt::PostIt::Installer.new(version) 8 | installer.install! 9 | 10 | gem 'bundler', version 11 | 12 | require 'bundler/version' 13 | -------------------------------------------------------------------------------- /spec/support/artifice/compact_index_basic_authentication.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../compact_index", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class CompactIndexBasicAuthentication < CompactIndexAPI 7 | before do 8 | unless env["HTTP_AUTHORIZATION"] 9 | halt 401, "Authentication info not supplied" 10 | end 11 | end 12 | end 13 | 14 | Artifice.activate_with(CompactIndexBasicAuthentication) 15 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/bin/console.tt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "<%= config[:namespaced_path] %>" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start 15 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_mirror_source.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint", __FILE__) 3 | 4 | class EndpointMirrorSource < Endpoint 5 | get "/gems/:id" do 6 | if request.env["HTTP_X_GEMFILE_SOURCE"] == "https://server.example.org/" 7 | File.read("#{gem_repo1}/gems/#{params[:id]}") 8 | else 9 | halt 500 10 | end 11 | end 12 | end 13 | 14 | Artifice.activate_with(EndpointMirrorSource) 15 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engines: 3 | duplication: 4 | enabled: true 5 | config: 6 | languages: 7 | - ruby 8 | fixme: 9 | enabled: true 10 | rubocop: 11 | enabled: false 12 | ratings: 13 | paths: 14 | - "**.rb" 15 | - "bin/*" 16 | - "exe/*" 17 | exclude_paths: 18 | - bundler.gemspec 19 | - "*.md" 20 | - lib/bundler/ssl_certs/*.pem 21 | - lib/bundler/vendor/**/* 22 | - lib/bundler/templates/**/*.tt 23 | - man/* 24 | - spec/**/* 25 | -------------------------------------------------------------------------------- /lib/bundler/vendored_persistent.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # We forcibly require OpenSSL, because net/http/persistent will only autoload 3 | # it. On some Rubies, autoload fails but explicit require succeeds. 4 | begin 5 | require "openssl" 6 | rescue LoadError 7 | # some Ruby builds don't have OpenSSL 8 | end 9 | 10 | vendor = File.expand_path("../vendor", __FILE__) 11 | $:.unshift(vendor) unless $:.include?(vendor) 12 | require "net/http/persistent" 13 | -------------------------------------------------------------------------------- /bin/rspec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | load File.expand_path("../with_rubygems", __FILE__) if ENV["RGV"] 5 | 6 | require "rubygems" 7 | 8 | bundler_spec = Gem::Specification.load(File.expand_path("../../bundler.gemspec", __FILE__)) 9 | bundler_spec.dependencies.each do |dep| 10 | gem dep.name, dep.requirement.to_s 11 | end 12 | 13 | Gem.finish_resolve if Gem.respond_to?(:finish_resolve) 14 | 15 | load Gem.bin_path("rspec-core", "rspec") 16 | -------------------------------------------------------------------------------- /spec/support/artifice/endopint_marshal_fail_basic_authentication.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint_marshal_fail", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointMarshalFailBasicAuthentication < EndpointMarshalFail 7 | before do 8 | unless env["HTTP_AUTHORIZATION"] 9 | halt 401, "Authentication info not supplied" 10 | end 11 | end 12 | end 13 | 14 | Artifice.activate_with(EndpointMarshalFailBasicAuthentication) 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Please do not submit patches for including directives to ignore IDE/editor 2 | # generated files. Use a global gitignore as described in 3 | # https://help.github.com/articles/ignoring-files and find useful gitignore 4 | # samples at https://github.com/github/gitignore 5 | 6 | # files created by running the specs 7 | /tmp/ 8 | 9 | # gems built by `rake build` 10 | /pkg/ 11 | 12 | # output from ronn 13 | /lib/bundler/man/ 14 | 15 | # rspec failure tracking 16 | .rspec_status 17 | -------------------------------------------------------------------------------- /lib/bundler/templates/Executable.standalone: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env <%= Bundler.settings[:shebang] || RbConfig::CONFIG['ruby_install_name'] %> 2 | # 3 | # This file was generated by Bundler. 4 | # 5 | # The application '<%= executable %>' is installed as part of a gem, and 6 | # this file is here to facilitate running it. 7 | # 8 | 9 | $:.unshift File.expand_path '../<%= standalone_path %>', __FILE__ 10 | 11 | require 'bundler/setup' 12 | load File.expand_path '../<%= executable_path %>', __FILE__ 13 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/lib/newgem.rb.tt: -------------------------------------------------------------------------------- 1 | require "<%=config[:namespaced_path]%>/version" 2 | <%- if config[:ext] -%> 3 | require "<%=config[:namespaced_path]%>/<%=config[:underscored_name]%>" 4 | <%- end -%> 5 | 6 | <%- config[:constant_array].each_with_index do |c,i| -%> 7 | <%= ' '*i %>module <%= c %> 8 | <%- end -%> 9 | <%= ' '*config[:constant_array].size %># Your code goes here... 10 | <%- (config[:constant_array].size-1).downto(0) do |i| -%> 11 | <%= ' '*i %>end 12 | <%- end -%> 13 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_extra_missing.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint_extra", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointExtraMissing < EndpointExtra 7 | get "/extra/fetch/actual/gem/:id" do 8 | if params[:id] == "missing-1.0.gemspec.rz" 9 | halt 404 10 | else 11 | File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") 12 | end 13 | end 14 | end 15 | 16 | Artifice.activate_with(EndpointExtraMissing) 17 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_host_redirect.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointHostRedirect < Endpoint 7 | get "/fetch/actual/gem/:id", :host_name => "localgemserver.test" do 8 | redirect "http://bundler.localgemserver.test#{request.path_info}" 9 | end 10 | 11 | get "/api/v1/dependencies" do 12 | status 404 13 | end 14 | end 15 | 16 | Artifice.activate_with(EndpointHostRedirect) 17 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_api_missing.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointApiMissing < Endpoint 7 | get "/fetch/actual/gem/:id" do 8 | $stderr.puts params[:id] 9 | if params[:id] == "rack-1.0.gemspec.rz" 10 | halt 404 11 | else 12 | File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") 13 | end 14 | end 15 | end 16 | 17 | Artifice.activate_with(EndpointApiMissing) 18 | -------------------------------------------------------------------------------- /bin/rubocop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | load File.expand_path("../with_rubygems", __FILE__) if ENV["RGV"] 5 | 6 | require "rubygems" 7 | 8 | bundler_spec = Gem::Specification.load(File.expand_path("../../bundler.gemspec", __FILE__)) 9 | bundler_spec.dependencies.each do |dep| 10 | gem dep.name, dep.requirement.to_s 11 | end 12 | 13 | gem "rubocop", "= 0.39.0" 14 | 15 | Gem.finish_resolve if Gem.respond_to?(:finish_resolve) 16 | 17 | load Gem.bin_path("rubocop", "rubocop") 18 | -------------------------------------------------------------------------------- /spec/support/artifice/compact_index_checksum_mismatch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../compact_index", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class CompactIndexChecksumMismatch < CompactIndexAPI 7 | get "/versions" do 8 | headers "ETag" => quote("123") 9 | headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60" 10 | content_type "text/plain" 11 | body "" 12 | end 13 | end 14 | 15 | Artifice.activate_with(CompactIndexChecksumMismatch) 16 | -------------------------------------------------------------------------------- /spec/support/artifice/compact_index_redirects.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../compact_index", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class CompactIndexRedirect < CompactIndexAPI 7 | get "/fetch/actual/gem/:id" do 8 | redirect "/fetch/actual/gem/#{params[:id]}" 9 | end 10 | 11 | get "/versions" do 12 | status 404 13 | end 14 | 15 | get "/api/v1/dependencies" do 16 | status 404 17 | end 18 | end 19 | 20 | Artifice.activate_with(CompactIndexRedirect) 21 | -------------------------------------------------------------------------------- /lib/bundler/vendor/molinillo/lib/molinillo.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'bundler/vendor/molinillo/lib/molinillo/gem_metadata' 3 | require 'bundler/vendor/molinillo/lib/molinillo/errors' 4 | require 'bundler/vendor/molinillo/lib/molinillo/resolver' 5 | require 'bundler/vendor/molinillo/lib/molinillo/modules/ui' 6 | require 'bundler/vendor/molinillo/lib/molinillo/modules/specification_provider' 7 | 8 | # Bundler::Molinillo is a generic dependency resolution algorithm. 9 | module Bundler::Molinillo 10 | end 11 | -------------------------------------------------------------------------------- /spec/support/artifice/compact_index_extra_missing.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../compact_index_extra", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class CompactIndexExtraMissing < CompactIndexExtra 7 | get "/extra/fetch/actual/gem/:id" do 8 | if params[:id] == "missing-1.0.gemspec.rz" 9 | halt 404 10 | else 11 | File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") 12 | end 13 | end 14 | end 15 | 16 | Artifice.activate_with(CompactIndexExtraMissing) 17 | -------------------------------------------------------------------------------- /lib/bundler/vendor/postit/lib/postit.rb: -------------------------------------------------------------------------------- 1 | require 'bundler/vendor/postit/lib/postit/environment' 2 | require 'bundler/vendor/postit/lib/postit/installer' 3 | require 'bundler/vendor/postit/lib/postit/parser' 4 | require 'bundler/vendor/postit/lib/postit/version' 5 | require 'rubygems' 6 | 7 | module BundlerVendoredPostIt::PostIt 8 | def self.setup 9 | load File.expand_path('../postit/setup.rb', __FILE__) 10 | end 11 | 12 | def self.bundler_version 13 | defined?(Bundler::VERSION) && Bundler::VERSION 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/other/ssl_cert_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | require "bundler/ssl_certs/certificate_manager" 4 | 5 | describe "SSL Certificates", :rubygems_master do 6 | hosts = %w( 7 | rubygems.org 8 | index.rubygems.org 9 | rubygems.global.ssl.fastly.net 10 | staging.rubygems.org 11 | ) 12 | 13 | hosts.each do |host| 14 | it "can securely connect to #{host}", :realworld do 15 | Bundler::SSLCerts::CertificateManager.new.connect_to(host) 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /spec/support/artifice/compact_index_api_missing.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../compact_index", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class CompactIndexApiMissing < CompactIndexAPI 7 | get "/fetch/actual/gem/:id" do 8 | $stderr.puts params[:id] 9 | if params[:id] == "rack-1.0.gemspec.rz" 10 | halt 404 11 | else 12 | File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") 13 | end 14 | end 15 | end 16 | 17 | Artifice.activate_with(CompactIndexApiMissing) 18 | -------------------------------------------------------------------------------- /spec/support/less_than_proc.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class LessThanProc < Proc 3 | attr_accessor :present 4 | 5 | def self.with(present) 6 | provided = Gem::Version.new(present.dup) 7 | new do |required| 8 | if required =~ /[=><~]/ 9 | !Gem::Requirement.new(required).satisfied_by?(provided) 10 | else 11 | provided < Gem::Version.new(required) 12 | end 13 | end.tap {|l| l.present = present } 14 | end 15 | 16 | def inspect 17 | "\"=< #{present}\"" 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/bundler/vendor/postit/lib/postit/parser.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | 3 | module BundlerVendoredPostIt::PostIt 4 | class Parser 5 | def initialize(file) 6 | @file = file 7 | end 8 | 9 | BUNDLED_WITH = 10 | /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ 11 | 12 | def parse 13 | return unless lockfile = File.file?(@file) && File.read(@file) 14 | if lockfile =~ BUNDLED_WITH 15 | Regexp.last_match(1) 16 | else 17 | '< 1.10' 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/bundler/vendor/thor/lib/thor/line_editor.rb: -------------------------------------------------------------------------------- 1 | require "bundler/vendor/thor/lib/thor/line_editor/basic" 2 | require "bundler/vendor/thor/lib/thor/line_editor/readline" 3 | 4 | class Bundler::Thor 5 | module LineEditor 6 | def self.readline(prompt, options = {}) 7 | best_available.new(prompt, options).readline 8 | end 9 | 10 | def self.best_available 11 | [ 12 | Bundler::Thor::LineEditor::Readline, 13 | Bundler::Thor::LineEditor::Basic 14 | ].detect(&:available?) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/bundler/stub_specification.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "bundler/remote_specification" 3 | 4 | module Bundler 5 | class StubSpecification < RemoteSpecification 6 | def self.from_stub(stub) 7 | spec = new(stub.name, stub.version, stub.platform, nil) 8 | spec.stub = stub 9 | spec 10 | end 11 | 12 | attr_accessor :stub 13 | 14 | def to_yaml 15 | _remote_specification.to_yaml 16 | end 17 | 18 | private 19 | 20 | def _remote_specification 21 | stub.to_spec 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | load File.expand_path("../with_rubygems", __FILE__) if ENV["RGV"] 5 | 6 | require "rubygems" 7 | 8 | bundler_spec = Gem::Specification.load(File.expand_path("../../bundler.gemspec", __FILE__)) 9 | bundler_spec.dependencies.each do |dep| 10 | begin 11 | gem dep.name, dep.requirement.to_s 12 | rescue Gem::LoadError => e 13 | $stderr.puts "#{e.message} (#{e.class})" 14 | end 15 | end 16 | 17 | Gem.finish_resolve if Gem.respond_to?(:finish_resolve) 18 | 19 | load Gem.bin_path("rake", "rake") 20 | -------------------------------------------------------------------------------- /spec/support/artifice/compact_index_host_redirect.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../compact_index", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class CompactIndexHostRedirect < CompactIndexAPI 7 | get "/fetch/actual/gem/:id", :host_name => "localgemserver.test" do 8 | redirect "http://bundler.localgemserver.test#{request.path_info}" 9 | end 10 | 11 | get "/versions" do 12 | status 404 13 | end 14 | 15 | get "/api/v1/dependencies" do 16 | status 404 17 | end 18 | end 19 | 20 | Artifice.activate_with(CompactIndexHostRedirect) 21 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_fallback.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointFallback < Endpoint 7 | DEPENDENCY_LIMIT = 60 8 | 9 | get "/api/v1/dependencies" do 10 | if params[:gems] && params[:gems].size <= DEPENDENCY_LIMIT 11 | Marshal.dump(dependencies_for(params[:gems])) 12 | else 13 | halt 413, "Too many gems to resolve, please request less than #{DEPENDENCY_LIMIT} gems" 14 | end 15 | end 16 | end 17 | 18 | Artifice.activate_with(EndpointFallback) 19 | -------------------------------------------------------------------------------- /lib/bundler/templates/Executable: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env <%= Bundler.settings[:shebang] || RbConfig::CONFIG['ruby_install_name'] %> 2 | # frozen_string_literal: true 3 | # 4 | # This file was generated by Bundler. 5 | # 6 | # The application '<%= executable %>' is installed as part of a gem, and 7 | # this file is here to facilitate running it. 8 | # 9 | 10 | require "pathname" 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../<%= relative_gemfile_path %>", 12 | Pathname.new(__FILE__).realpath) 13 | 14 | require "rubygems" 15 | require "bundler/setup" 16 | 17 | load Gem.bin_path("<%= spec.name %>", "<%= executable %>") 18 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_strict_basic_authentication.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointStrictBasicAuthentication < Endpoint 7 | before do 8 | unless env["HTTP_AUTHORIZATION"] 9 | halt 401, "Authentication info not supplied" 10 | end 11 | 12 | # Only accepts password == "password" 13 | unless env["HTTP_AUTHORIZATION"] == "Basic dXNlcjpwYXNz" 14 | halt 403, "Authentication failed" 15 | end 16 | end 17 | end 18 | 19 | Artifice.activate_with(EndpointStrictBasicAuthentication) 20 | -------------------------------------------------------------------------------- /spec/other/cli_dispatch_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle command names" do 5 | it "work when given fully" do 6 | bundle "install" 7 | expect(err).to eq("") 8 | expect(out).not_to match(/Ambiguous command/) 9 | end 10 | 11 | it "work when not ambiguous" do 12 | bundle "ins" 13 | expect(err).to eq("") 14 | expect(out).not_to match(/Ambiguous command/) 15 | end 16 | 17 | it "print a friendly error when ambiguous" do 18 | bundle "in" 19 | expect(err).to eq("") 20 | expect(out).to match(/Ambiguous command/) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/support/artifice/compact_index_strict_basic_authentication.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../compact_index", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class CompactIndexStrictBasicAuthentication < CompactIndexAPI 7 | before do 8 | unless env["HTTP_AUTHORIZATION"] 9 | halt 401, "Authentication info not supplied" 10 | end 11 | 12 | # Only accepts password == "password" 13 | unless env["HTTP_AUTHORIZATION"] == "Basic dXNlcjpwYXNz" 14 | halt 403, "Authentication failed" 15 | end 16 | end 17 | end 18 | 19 | Artifice.activate_with(CompactIndexStrictBasicAuthentication) 20 | -------------------------------------------------------------------------------- /lib/bundler/plugin/installer/rubygems.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bundler 4 | module Plugin 5 | class Installer 6 | class Rubygems < Bundler::Source::Rubygems 7 | def version_message(spec) 8 | "#{spec.name} #{spec.version}" 9 | end 10 | 11 | private 12 | 13 | def requires_sudo? 14 | false # Will change on implementation of project level plugins 15 | end 16 | 17 | def rubygems_dir 18 | Plugin.root 19 | end 20 | 21 | def cache_path 22 | Plugin.cache 23 | end 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/support/code_climate.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Spec 3 | module CodeClimate 4 | def self.setup 5 | require "codeclimate-test-reporter" 6 | ::CodeClimate::TestReporter.start 7 | configure_exclusions 8 | rescue LoadError 9 | # it's fine if CodeClimate isn't set up 10 | nil 11 | end 12 | 13 | def self.configure_exclusions 14 | SimpleCov.start do 15 | add_filter "/bin/" 16 | add_filter "/lib/bundler/man/" 17 | add_filter "/lib/bundler/vendor/" 18 | add_filter "/man/" 19 | add_filter "/pkg/" 20 | add_filter "/spec/" 21 | add_filter "/tmp/" 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/bundler/cli/clean.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class CLI::Clean 4 | attr_reader :options 5 | 6 | def initialize(options) 7 | @options = options 8 | end 9 | 10 | def run 11 | require_path_or_force 12 | Bundler.load.clean(options[:"dry-run"]) 13 | end 14 | 15 | protected 16 | 17 | def require_path_or_force 18 | if !Bundler.settings[:path] && !options[:force] 19 | Bundler.ui.error "Cleaning all the gems on your system is dangerous! " \ 20 | "If you're sure you want to remove every system gem not in this " \ 21 | "bundle, run `bundle clean --force`." 22 | exit 1 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/bundler/deprecate.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | if defined? ::Deprecate 4 | Deprecate = ::Deprecate 5 | elsif defined? Gem::Deprecate 6 | Deprecate = Gem::Deprecate 7 | else 8 | class Deprecate; end 9 | end 10 | 11 | unless Deprecate.respond_to?(:skip_during) 12 | def Deprecate.skip_during 13 | original = skip 14 | self.skip = true 15 | yield 16 | ensure 17 | self.skip = original 18 | end 19 | end 20 | 21 | unless Deprecate.respond_to?(:skip) 22 | def Deprecate.skip 23 | @skip 24 | end 25 | end 26 | 27 | unless Deprecate.respond_to?(:skip=) 28 | def Deprecate.skip=(skip) 29 | @skip = skip 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb: -------------------------------------------------------------------------------- 1 | class Bundler::Thor 2 | module LineEditor 3 | class Basic 4 | attr_reader :prompt, :options 5 | 6 | def self.available? 7 | true 8 | end 9 | 10 | def initialize(prompt, options) 11 | @prompt = prompt 12 | @options = options 13 | end 14 | 15 | def readline 16 | $stdout.print(prompt) 17 | get_input 18 | end 19 | 20 | private 21 | 22 | def get_input 23 | if echo? 24 | $stdin.gets 25 | else 26 | $stdin.noecho(&:gets) 27 | end 28 | end 29 | 30 | def echo? 31 | options.fetch(:echo, true) 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /spec/update/path_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "path sources" do 5 | describe "bundle update --source" do 6 | it "shows the previous version of the gem when updated from path source" do 7 | build_lib "activesupport", "2.3.5", :path => lib_path("rails/activesupport") 8 | 9 | install_gemfile <<-G 10 | gem "activesupport", :path => "#{lib_path("rails/activesupport")}" 11 | G 12 | 13 | build_lib "activesupport", "3.0", :path => lib_path("rails/activesupport") 14 | 15 | bundle "update --source activesupport" 16 | expect(out).to include("Using activesupport 3.0 (was 2.3.5) from source at `#{lib_path("rails/activesupport")}`") 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/install/gems/win32_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle install with win32-generated lockfile" do 5 | it "should read lockfile" do 6 | File.open(bundled_app("Gemfile.lock"), "wb") do |f| 7 | f << "GEM\r\n" 8 | f << " remote: file:#{gem_repo1}/\r\n" 9 | f << " specs:\r\n" 10 | f << "\r\n" 11 | f << " rack (1.0.0)\r\n" 12 | f << "\r\n" 13 | f << "PLATFORMS\r\n" 14 | f << " ruby\r\n" 15 | f << "\r\n" 16 | f << "DEPENDENCIES\r\n" 17 | f << " rack\r\n" 18 | end 19 | 20 | install_gemfile <<-G 21 | source "file://#{gem_repo1}" 22 | 23 | gem "rack" 24 | G 25 | expect(exitstatus).to eq(0) if exitstatus 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_500.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../../path.rb", __FILE__) 3 | include Spec::Path 4 | 5 | $LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/artifice*/lib")].first}" 6 | $LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/rack-*/lib")].first}" 7 | $LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/rack-*/lib")].last}" 8 | $LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/tilt*/lib")].first}" 9 | $LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/sinatra*/lib")].first}" 10 | 11 | require "artifice" 12 | require "sinatra/base" 13 | 14 | Artifice.deactivate 15 | 16 | class Endpoint500 < Sinatra::Base 17 | before do 18 | halt 500 19 | end 20 | end 21 | 22 | Artifice.activate_with(Endpoint500) 23 | -------------------------------------------------------------------------------- /lib/bundler/capistrano.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Capistrano task for Bundler. 3 | # 4 | # Add "require 'bundler/capistrano'" in your Capistrano deploy.rb, and 5 | # Bundler will be activated after each new deployment. 6 | require "bundler/deployment" 7 | require "capistrano/version" 8 | 9 | if defined?(Capistrano::Version) && Gem::Version.new(Capistrano::Version).release >= Gem::Version.new("3.0") 10 | raise "For Capistrano 3.x integration, please use http://github.com/capistrano/bundler" 11 | end 12 | 13 | Capistrano::Configuration.instance(:must_exist).load do 14 | before "deploy:finalize_update", "bundle:install" 15 | Bundler::Deployment.define_task(self, :task, :except => { :no_release => true }) 16 | set :rake, lambda { "#{fetch(:bundle_cmd, "bundle")} exec rake" } 17 | end 18 | -------------------------------------------------------------------------------- /lib/bundler/vendor/net/http/faster.rb: -------------------------------------------------------------------------------- 1 | require 'net/protocol' 2 | 3 | ## 4 | # Aaron Patterson's monkeypatch (accepted into 1.9.1) to fix Net::HTTP's speed 5 | # problems. 6 | # 7 | # http://gist.github.com/251244 8 | 9 | class Net::BufferedIO #:nodoc: 10 | alias :old_rbuf_fill :rbuf_fill 11 | 12 | def rbuf_fill 13 | if @io.respond_to? :read_nonblock then 14 | begin 15 | @rbuf << @io.read_nonblock(65536) 16 | rescue Errno::EWOULDBLOCK, Errno::EAGAIN => e 17 | retry if IO.select [@io], nil, nil, @read_timeout 18 | raise Timeout::Error, e.message 19 | end 20 | else # SSL sockets do not have read_nonblock 21 | timeout @read_timeout do 22 | @rbuf << @io.sysread(65536) 23 | end 24 | end 25 | end 26 | end if RUBY_VERSION < '1.9' 27 | -------------------------------------------------------------------------------- /spec/install/upgrade_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle install for the first time with v1.0" do 5 | before :each do 6 | in_app_root 7 | 8 | gemfile <<-G 9 | source "file://#{gem_repo1}" 10 | gem "rack" 11 | G 12 | end 13 | 14 | it "removes lockfiles in 0.9 YAML format" do 15 | File.open("Gemfile.lock", "w") {|f| YAML.dump({}, f) } 16 | bundle :install 17 | expect(File.read("Gemfile.lock")).not_to match(/^---/) 18 | end 19 | 20 | it "removes env.rb if it exists" do 21 | bundled_app.join(".bundle").mkdir 22 | bundled_app.join(".bundle/environment.rb").open("w") {|f| f.write("raise 'nooo'") } 23 | bundle :install 24 | expect(bundled_app.join(".bundle/environment.rb")).not_to exist 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/bundler/psyched_yaml.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Psych could be a gem, so try to ask for it 3 | begin 4 | gem "psych" 5 | rescue LoadError 6 | end if defined?(gem) 7 | 8 | # Psych could be in the stdlib 9 | # but it's too late if Syck is already loaded 10 | begin 11 | require "psych" unless defined?(Syck) 12 | rescue LoadError 13 | # Apparently Psych wasn't available. Oh well. 14 | end 15 | 16 | # At least load the YAML stdlib, whatever that may be 17 | require "yaml" unless defined?(YAML.dump) 18 | 19 | module Bundler 20 | # On encountering invalid YAML, 21 | # Psych raises Psych::SyntaxError 22 | if defined?(::Psych::SyntaxError) 23 | YamlLibrarySyntaxError = ::Psych::SyntaxError 24 | else # Syck raises ArgumentError 25 | YamlLibrarySyntaxError = ::ArgumentError 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/Rakefile.tt: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | <% if config[:test] == 'minitest' -%> 3 | require "rake/testtask" 4 | 5 | Rake::TestTask.new(:test) do |t| 6 | t.libs << "test" 7 | t.libs << "lib" 8 | t.test_files = FileList['test/**/*_test.rb'] 9 | end 10 | 11 | <% elsif config[:test] == 'rspec' -%> 12 | require "rspec/core/rake_task" 13 | 14 | RSpec::Core::RakeTask.new(:spec) 15 | 16 | <% end -%> 17 | <% if config[:ext] -%> 18 | require "rake/extensiontask" 19 | 20 | task :build => :compile 21 | 22 | Rake::ExtensionTask.new("<%=config[:underscored_name]%>") do |ext| 23 | ext.lib_dir = "lib/<%=config[:namespaced_path]%>" 24 | end 25 | 26 | task :default => [:clobber, :compile, :<%= config[:test_task] %>] 27 | <% else -%> 28 | task :default => :<%= config[:test_task] %> 29 | <% end -%> 30 | -------------------------------------------------------------------------------- /lib/bundler/ruby_dsl.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | module RubyDsl 4 | def ruby(*ruby_version) 5 | options = ruby_version.last.is_a?(Hash) ? ruby_version.pop : {} 6 | ruby_version.flatten! 7 | raise GemfileError, "Please define :engine_version" if options[:engine] && options[:engine_version].nil? 8 | raise GemfileError, "Please define :engine" if options[:engine_version] && options[:engine].nil? 9 | 10 | if options[:engine] == "ruby" && options[:engine_version] && 11 | ruby_version != Array(options[:engine_version]) 12 | raise GemfileEvalError, "ruby_version must match the :engine_version for MRI" 13 | end 14 | @ruby_version = RubyVersion.new(ruby_version, options[:patchlevel], options[:engine], options[:engine_version]) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/commands/licenses_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle licenses" do 5 | before :each do 6 | install_gemfile <<-G 7 | source "file://#{gem_repo1}" 8 | gem "rails" 9 | gem "with_license" 10 | G 11 | end 12 | 13 | it "prints license information for all gems in the bundle" do 14 | bundle "licenses" 15 | 16 | expect(out).to include("bundler: Unknown") 17 | expect(out).to include("with_license: MIT") 18 | end 19 | 20 | it "performs an automatic bundle install" do 21 | gemfile <<-G 22 | source "file://#{gem_repo1}" 23 | gem "rails" 24 | gem "with_license" 25 | gem "foo" 26 | G 27 | 28 | bundle "config auto_install 1" 29 | bundle :licenses 30 | expect(out).to include("Installing foo 1.0") 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/bundler/cli/open.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "bundler/cli/common" 3 | require "shellwords" 4 | 5 | module Bundler 6 | class CLI::Open 7 | attr_reader :options, :name 8 | def initialize(options, name) 9 | @options = options 10 | @name = name 11 | end 12 | 13 | def run 14 | editor = [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? } 15 | return Bundler.ui.info("To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR") unless editor 16 | path = Bundler::CLI::Common.select_spec(name, :regex_match).full_gem_path 17 | Dir.chdir(path) do 18 | command = Shellwords.split(editor) + [path] 19 | Bundler.with_clean_env do 20 | system(*command) 21 | end || Bundler.ui.info("Could not run '#{command.join(" ")}'") 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/lock/git_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle lock with git gems" do 5 | before :each do 6 | build_git "foo" 7 | 8 | install_gemfile <<-G 9 | gem 'foo', :git => "#{lib_path("foo-1.0")}" 10 | G 11 | end 12 | 13 | it "doesn't break right after running lock" do 14 | should_be_installed "foo 1.0.0" 15 | end 16 | 17 | it "locks a git source to the current ref" do 18 | update_git "foo" 19 | bundle :install 20 | 21 | run <<-RUBY 22 | require 'foo' 23 | puts "WIN" unless defined?(FOO_PREV_REF) 24 | RUBY 25 | 26 | expect(out).to eq("WIN") 27 | end 28 | 29 | it "provides correct #full_gem_path" do 30 | run <<-RUBY 31 | puts Bundler.rubygems.find_name('foo').first.full_gem_path 32 | RUBY 33 | expect(out).to eq(bundle("show foo")) 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_extra.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointExtra < Endpoint 7 | get "/extra/api/v1/dependencies" do 8 | halt 404 9 | end 10 | 11 | get "/extra/specs.4.8.gz" do 12 | File.read("#{gem_repo2}/specs.4.8.gz") 13 | end 14 | 15 | get "/extra/prerelease_specs.4.8.gz" do 16 | File.read("#{gem_repo2}/prerelease_specs.4.8.gz") 17 | end 18 | 19 | get "/extra/quick/Marshal.4.8/:id" do 20 | redirect "/extra/fetch/actual/gem/#{params[:id]}" 21 | end 22 | 23 | get "/extra/fetch/actual/gem/:id" do 24 | File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") 25 | end 26 | 27 | get "/extra/gems/:id" do 28 | File.read("#{gem_repo2}/gems/#{params[:id]}") 29 | end 30 | end 31 | 32 | Artifice.activate_with(EndpointExtra) 33 | -------------------------------------------------------------------------------- /spec/bundler/index_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe Bundler::Index do 5 | let(:specs) { [] } 6 | subject { described_class.build {|i| i.use(specs) } } 7 | 8 | context "specs with a nil platform" do 9 | let(:spec) do 10 | Gem::Specification.new do |s| 11 | s.name = "json" 12 | s.version = "1.8.3" 13 | allow(s).to receive(:platform).and_return(nil) 14 | end 15 | end 16 | let(:specs) { [spec] } 17 | 18 | describe "#search_by_spec" do 19 | it "finds the spec when a nil platform is specified" do 20 | expect(subject.search(spec)).to eq([spec]) 21 | end 22 | 23 | it "finds the spec when a ruby platform is specified" do 24 | query = spec.dup.tap {|s| s.platform = "ruby" } 25 | expect(subject.search(query)).to eq([spec]) 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/bundler/setup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "bundler/postit_trampoline" unless ENV["BUNDLE_DISABLE_POSTIT"] 3 | require "bundler/shared_helpers" 4 | 5 | if Bundler::SharedHelpers.in_bundle? 6 | require "bundler" 7 | 8 | if STDOUT.tty? || ENV["BUNDLER_FORCE_TTY"] 9 | begin 10 | Bundler.setup 11 | rescue Bundler::BundlerError => e 12 | puts "\e[31m#{e.message}\e[0m" 13 | puts e.backtrace.join("\n") if ENV["DEBUG"] 14 | if e.is_a?(Bundler::GemNotFound) 15 | puts "\e[33mRun `bundle install` to install missing gems.\e[0m" 16 | end 17 | exit e.status_code 18 | end 19 | else 20 | Bundler.setup 21 | end 22 | 23 | # Add bundler to the load path after disabling system gems 24 | bundler_lib = File.expand_path("../..", __FILE__) 25 | $LOAD_PATH.unshift(bundler_lib) unless $LOAD_PATH.include?(bundler_lib) 26 | 27 | Bundler.ui = nil 28 | end 29 | -------------------------------------------------------------------------------- /lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/action' 3 | module Bundler::Molinillo 4 | class DependencyGraph 5 | # @!visibility private 6 | # @see DependencyGraph#tag 7 | class Tag < Action 8 | # @!group Action 9 | 10 | # (see Action.name) 11 | def self.name 12 | :tag 13 | end 14 | 15 | # (see Action#up) 16 | def up(_graph) 17 | end 18 | 19 | # (see Action#down) 20 | def down(_graph) 21 | end 22 | 23 | # @!group Tag 24 | 25 | # @return [Object] An opaque tag 26 | attr_reader :tag 27 | 28 | # Initialize an action to tag a state of a dependency graph 29 | # @param [Object] tag an opaque tag 30 | def initialize(tag) 31 | @tag = tag 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /spec/bundler/fetcher/compact_index_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe Bundler::Fetcher::CompactIndex do 5 | let(:downloader) { double(:downloader) } 6 | let(:remote) { double(:remote, :cache_slug => "lsjdf") } 7 | let(:display_uri) { URI("http://sampleuri.com") } 8 | let(:compact_index) { described_class.new(downloader, remote, display_uri) } 9 | 10 | describe "#specs_for_names" do 11 | it "has only one thread open at the end of the run" do 12 | compact_index.specs_for_names(["lskdjf"]) 13 | 14 | thread_count = Thread.list.select {|thread| thread.status == "run" }.count 15 | expect(thread_count).to eq 1 16 | end 17 | 18 | it "calls worker#stop during the run" do 19 | expect_any_instance_of(Bundler::Worker).to receive(:stop).at_least(:once) 20 | 21 | compact_index.specs_for_names(["lskdjf"]) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/bundler/vendor/postit/lib/postit/installer.rb: -------------------------------------------------------------------------------- 1 | module BundlerVendoredPostIt::PostIt 2 | class Installer 3 | def initialize(bundler_version) 4 | @bundler_version = bundler_version 5 | end 6 | 7 | def installed? 8 | if Gem::Specification.respond_to?(:find_by_name) 9 | !Gem::Specification.find_by_name('bundler', @bundler_version).nil? 10 | else 11 | requirement = Gem::Requirement.new(@bundler_version) 12 | Gem.source_index.gems.values.any? do |s| 13 | s.name == 'bundler' && requirement.satisfied_by?(s.version) 14 | end 15 | end 16 | rescue LoadError 17 | false 18 | end 19 | 20 | def install! 21 | return if installed? 22 | require 'rubygems/dependency_installer' 23 | installer = Gem::DependencyInstaller.new 24 | installer.install('bundler', @bundler_version) 25 | installer.installed_gems 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/bundler/plugin/source_list_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe Bundler::Plugin::SourceList do 5 | SourceList = Bundler::Plugin::SourceList 6 | 7 | before do 8 | allow(Bundler).to receive(:root) { Pathname.new "/" } 9 | end 10 | 11 | subject(:source_list) { SourceList.new } 12 | 13 | describe "adding sources uses classes for plugin" do 14 | it "uses Plugin::Installer::Rubygems for rubygems sources" do 15 | source = source_list. 16 | add_rubygems_source("remotes" => ["https://existing-rubygems.org"]) 17 | expect(source).to be_instance_of(Bundler::Plugin::Installer::Rubygems) 18 | end 19 | 20 | it "uses Plugin::Installer::Git for git sources" do 21 | source = source_list. 22 | add_git_source("uri" => "git://existing-git.org/path.git") 23 | expect(source).to be_instance_of(Bundler::Plugin::Installer::Git) 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_extra_api.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointExtraApi < Endpoint 7 | get "/extra/api/v1/dependencies" do 8 | deps = dependencies_for(params[:gems], gem_repo4) 9 | Marshal.dump(deps) 10 | end 11 | 12 | get "/extra/specs.4.8.gz" do 13 | File.read("#{gem_repo4}/specs.4.8.gz") 14 | end 15 | 16 | get "/extra/prerelease_specs.4.8.gz" do 17 | File.read("#{gem_repo4}/prerelease_specs.4.8.gz") 18 | end 19 | 20 | get "/extra/quick/Marshal.4.8/:id" do 21 | redirect "/extra/fetch/actual/gem/#{params[:id]}" 22 | end 23 | 24 | get "/extra/fetch/actual/gem/:id" do 25 | File.read("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}") 26 | end 27 | 28 | get "/extra/gems/:id" do 29 | File.read("#{gem_repo4}/gems/#{params[:id]}") 30 | end 31 | end 32 | 33 | Artifice.activate_with(EndpointExtraApi) 34 | -------------------------------------------------------------------------------- /lib/bundler/plugin/source_list.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bundler 4 | # SourceList object to be used while parsing the Gemfile, setting the 5 | # approptiate options to be used with Source classes for plugin installation 6 | module Plugin 7 | class SourceList < Bundler::SourceList 8 | def initialize 9 | @path_sources = [] 10 | @git_sources = [] 11 | @rubygems_aggregate = Plugin::Installer::Rubygems.new 12 | @rubygems_sources = [] 13 | end 14 | 15 | def add_git_source(options = {}) 16 | add_source_to_list Plugin::Installer::Git.new(options), git_sources 17 | end 18 | 19 | def add_rubygems_source(options = {}) 20 | add_source_to_list Plugin::Installer::Rubygems.new(options), @rubygems_sources 21 | end 22 | 23 | def all_sources 24 | path_sources + git_sources + rubygems_sources 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/support/artifice/compact_index_extra.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../compact_index", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class CompactIndexExtra < CompactIndexAPI 7 | get "/extra/versions" do 8 | halt 404 9 | end 10 | 11 | get "/extra/api/v1/dependencies" do 12 | halt 404 13 | end 14 | 15 | get "/extra/specs.4.8.gz" do 16 | File.read("#{gem_repo2}/specs.4.8.gz") 17 | end 18 | 19 | get "/extra/prerelease_specs.4.8.gz" do 20 | File.read("#{gem_repo2}/prerelease_specs.4.8.gz") 21 | end 22 | 23 | get "/extra/quick/Marshal.4.8/:id" do 24 | redirect "/extra/fetch/actual/gem/#{params[:id]}" 25 | end 26 | 27 | get "/extra/fetch/actual/gem/:id" do 28 | File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") 29 | end 30 | 31 | get "/extra/gems/:id" do 32 | File.read("#{gem_repo2}/gems/#{params[:id]}") 33 | end 34 | end 35 | 36 | Artifice.activate_with(CompactIndexExtra) 37 | -------------------------------------------------------------------------------- /lib/bundler/environment.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class Environment 4 | attr_reader :root 5 | 6 | def initialize(root, definition) 7 | @root = root 8 | @definition = definition 9 | 10 | env_file = Bundler.app_config_path.join("environment.rb") 11 | env_file.rmtree if env_file.exist? 12 | end 13 | 14 | def inspect 15 | @definition.to_lock.inspect 16 | end 17 | 18 | def requested_specs 19 | @definition.requested_specs 20 | end 21 | 22 | def specs 23 | @definition.specs 24 | end 25 | 26 | def dependencies 27 | @definition.dependencies 28 | end 29 | 30 | def current_dependencies 31 | @definition.current_dependencies 32 | end 33 | 34 | def lock(opts = {}) 35 | @definition.lock(Bundler.default_lockfile, opts[:preserve_unknown_sections]) 36 | end 37 | 38 | def update(*gems) 39 | # Nothing 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/bundler/dep_proxy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class DepProxy 4 | attr_reader :__platform, :dep 5 | 6 | def initialize(dep, platform) 7 | @dep = dep 8 | @__platform = platform 9 | end 10 | 11 | def hash 12 | @hash ||= dep.hash 13 | end 14 | 15 | def ==(other) 16 | dep == other.dep && __platform == other.__platform 17 | end 18 | 19 | alias_method :eql?, :== 20 | 21 | def type 22 | @dep.type 23 | end 24 | 25 | def name 26 | @dep.name 27 | end 28 | 29 | def requirement 30 | @dep.requirement 31 | end 32 | 33 | def to_s 34 | s = name.dup 35 | s << " (#{requirement})" unless requirement == Gem::Requirement.default 36 | s << " #{__platform}" unless __platform == Gem::Platform::RUBY 37 | s 38 | end 39 | 40 | private 41 | 42 | def method_missing(*args, &blk) 43 | @dep.send(*args, &blk) 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/bundler/ui/silent.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | module UI 4 | class Silent 5 | def add_color(string, color) 6 | string 7 | end 8 | 9 | def info(message, newline = nil) 10 | end 11 | 12 | def confirm(message, newline = nil) 13 | end 14 | 15 | def warn(message, newline = nil) 16 | end 17 | 18 | def error(message, newline = nil) 19 | end 20 | 21 | def debug(message, newline = nil) 22 | end 23 | 24 | def debug? 25 | false 26 | end 27 | 28 | def quiet? 29 | false 30 | end 31 | 32 | def ask(message) 33 | end 34 | 35 | def level=(name) 36 | end 37 | 38 | def level(name = nil) 39 | end 40 | 41 | def trace(message, newline = nil) 42 | end 43 | 44 | def major_deprecation(message) 45 | end 46 | 47 | def silence 48 | yield 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/bundler/fetcher/base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class Fetcher 4 | class Base 5 | attr_reader :downloader 6 | attr_reader :display_uri 7 | attr_reader :remote 8 | 9 | def initialize(downloader, remote, display_uri) 10 | raise "Abstract class" if self.class == Base 11 | @downloader = downloader 12 | @remote = remote 13 | @display_uri = display_uri 14 | end 15 | 16 | def remote_uri 17 | @remote.uri 18 | end 19 | 20 | def fetch_uri 21 | @fetch_uri ||= begin 22 | if remote_uri.host == "rubygems.org" 23 | uri = remote_uri.dup 24 | uri.host = "index.rubygems.org" 25 | uri 26 | else 27 | remote_uri 28 | end 29 | end 30 | end 31 | 32 | def available? 33 | true 34 | end 35 | 36 | def api_fetcher? 37 | false 38 | end 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /spec/cache/cache_path_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle package" do 5 | before do 6 | gemfile <<-G 7 | source "file://#{gem_repo1}" 8 | gem "rack" 9 | G 10 | end 11 | 12 | context "with --cache-path" do 13 | it "caches gems at given path" do 14 | bundle :package, "cache-path" => "vendor/cache-foo" 15 | expect(bundled_app("vendor/cache-foo/rack-1.0.0.gem")).to exist 16 | end 17 | end 18 | 19 | context "with config cache_path" do 20 | it "caches gems at given path" do 21 | bundle "config cache_path vendor/cache-foo" 22 | bundle :package 23 | expect(bundled_app("vendor/cache-foo/rack-1.0.0.gem")).to exist 24 | end 25 | end 26 | 27 | context "when given an absolute path" do 28 | it "exits with non-zero status" do 29 | bundle :package, "cache-path" => "/tmp/cache-foo" 30 | expect(out).to match(/must be relative/) 31 | expect(exitstatus).to eq(15) if exitstatus 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/bundler/source/rubygems_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe Bundler::Source::Rubygems do 5 | before do 6 | allow(Bundler).to receive(:root) { Pathname.new("root") } 7 | end 8 | 9 | describe "caches" do 10 | it "includes Bundler.app_cache" do 11 | expect(subject.caches).to include(Bundler.app_cache) 12 | end 13 | 14 | it "includes GEM_PATH entries" do 15 | Gem.path.each do |path| 16 | expect(subject.caches).to include(File.expand_path("#{path}/cache")) 17 | end 18 | end 19 | 20 | it "is an array of strings or pathnames" do 21 | subject.caches.each do |cache| 22 | expect([String, Pathname]).to include(cache.class) 23 | end 24 | end 25 | end 26 | 27 | describe "#add_remote" do 28 | context "when the source is an HTTP(s) URI with no host" do 29 | it "raises error" do 30 | expect { subject.add_remote("https:rubygems.org") }.to raise_error(ArgumentError) 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/bundler/plugin/installer/git.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bundler 4 | module Plugin 5 | class Installer 6 | class Git < Bundler::Source::Git 7 | def cache_path 8 | @cache_path ||= begin 9 | git_scope = "#{base_name}-#{uri_hash}" 10 | 11 | Plugin.cache.join("bundler", "git", git_scope) 12 | end 13 | end 14 | 15 | def install_path 16 | @install_path ||= begin 17 | git_scope = "#{base_name}-#{shortref_for_path(revision)}" 18 | 19 | Plugin.root.join("bundler", "gems", git_scope) 20 | end 21 | end 22 | 23 | def version_message(spec) 24 | "#{spec.name} #{spec.version}" 25 | end 26 | 27 | def root 28 | Plugin.root 29 | end 30 | 31 | def generate_bin(spec, disable_extensions = false) 32 | # Need to find a way without code duplication 33 | # For now, we can ignore this 34 | end 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/bundler/environment_preserver.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class EnvironmentPreserver 4 | # @param env [ENV] 5 | # @param keys [Array] 6 | def initialize(env, keys) 7 | @original = env.to_hash 8 | @keys = keys 9 | @prefix = "BUNDLE_ORIG_" 10 | end 11 | 12 | # @return [Hash] 13 | def backup 14 | env = @original.clone 15 | @keys.each do |key| 16 | value = env[key] 17 | original_value = env[@prefix + key] 18 | if !value.nil? && !value.empty? && original_value.nil? 19 | env[@prefix + key] = value 20 | end 21 | end 22 | env 23 | end 24 | 25 | # @return [Hash] 26 | def restore 27 | env = @original.clone 28 | @keys.each do |key| 29 | value_original = env[@prefix + key] 30 | unless value_original.nil? || value_original.empty? 31 | env[key] = value_original 32 | env.delete(@prefix + key) 33 | end 34 | end 35 | env 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /spec/support/fakeweb/windows.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../../path.rb", __FILE__) 3 | include Spec::Path 4 | 5 | files = ["specs.4.8.gz", 6 | "prerelease_specs.4.8.gz", 7 | "quick/Marshal.4.8/rcov-1.0-mswin32.gemspec.rz", 8 | "gems/rcov-1.0-mswin32.gem"] 9 | 10 | # Set up pretend http gem server with FakeWeb 11 | $LOAD_PATH.unshift "#{Dir[base_system_gems.join("gems/fakeweb*/lib")].first}" 12 | require "fakeweb" 13 | 14 | FakeWeb.allow_net_connect = false 15 | 16 | files.each do |file| 17 | FakeWeb.register_uri(:get, "http://localgemserver.test/#{file}", 18 | :body => File.read("#{gem_repo1}/#{file}")) 19 | end 20 | FakeWeb.register_uri(:get, "http://localgemserver.test/gems/rcov-1.0-x86-mswin32.gem", 21 | :status => ["404", "Not Found"]) 22 | 23 | FakeWeb.register_uri(:get, "http://localgemserver.test/api/v1/dependencies", 24 | :status => ["404", "Not Found"]) 25 | 26 | FakeWeb.register_uri(:get, "http://localgemserver.test/versions", 27 | :status => ["500", "Internal Server Error"]) 28 | -------------------------------------------------------------------------------- /lib/bundler/cli/viz.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class CLI::Viz 4 | attr_reader :options, :gem_name 5 | def initialize(options) 6 | @options = options 7 | end 8 | 9 | def run 10 | require "graphviz" 11 | 12 | options[:without] = options[:without].join(":").tr(" ", ":").split(":") 13 | output_file = File.expand_path(options[:file]) 14 | 15 | graph = Graph.new(Bundler.load, output_file, options[:version], options[:requirements], options[:format], options[:without]) 16 | graph.viz 17 | rescue LoadError => e 18 | Bundler.ui.error e.inspect 19 | Bundler.ui.warn "Make sure you have the graphviz ruby gem. You can install it with:" 20 | Bundler.ui.warn "`gem install ruby-graphviz`" 21 | rescue StandardError => e 22 | raise unless e.message =~ /GraphViz not installed or dot not in PATH/ 23 | Bundler.ui.error e.message 24 | Bundler.ui.warn "Please install GraphViz. On a Mac with homebrew, you can run `brew install graphviz`." 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/bundler/spec_set_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe Bundler::SpecSet do 5 | let(:specs) do 6 | [ 7 | build_spec("a", "1.0"), 8 | build_spec("b", "1.0"), 9 | build_spec("c", "1.1") do |s| 10 | s.dep "a", "< 2.0" 11 | s.dep "e", "> 0" 12 | end, 13 | build_spec("d", "2.0") do |s| 14 | s.dep "a", "1.0" 15 | s.dep "c", "~> 1.0" 16 | end, 17 | build_spec("e", "1.0.0.pre.1"), 18 | ].flatten 19 | end 20 | subject { described_class.new(specs) } 21 | 22 | context "enumerable methods" do 23 | it "has a length" do 24 | expect(subject.length).to eq(5) 25 | end 26 | 27 | it "has a size" do 28 | expect(subject.size).to eq(5) 29 | end 30 | end 31 | 32 | describe "#to_a" do 33 | it "returns the specs in order" do 34 | expect(subject.to_a.map(&:full_name)).to eq %w( 35 | a-1.0 36 | b-1.0 37 | e-1.0.0.pre.1 38 | c-1.1 39 | d-2.0 40 | ) 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/bundler/cli/console.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class CLI::Console 4 | attr_reader :options, :group 5 | def initialize(options, group) 6 | @options = options 7 | @group = group 8 | end 9 | 10 | def run 11 | group ? Bundler.require(:default, *(group.split.map!(&:to_sym))) : Bundler.require 12 | ARGV.clear 13 | 14 | console = get_console(Bundler.settings[:console] || "irb") 15 | console.start 16 | end 17 | 18 | def get_console(name) 19 | require name 20 | get_constant(name) 21 | rescue LoadError 22 | Bundler.ui.error "Couldn't load console #{name}, falling back to irb" 23 | require "irb" 24 | get_constant("irb") 25 | end 26 | 27 | def get_constant(name) 28 | const_name = { 29 | "pry" => :Pry, 30 | "ripl" => :Ripl, 31 | "irb" => :IRB, 32 | }[name] 33 | Object.const_get(const_name) 34 | rescue NameError 35 | Bundler.ui.error "Could not find constant #{const_name}" 36 | exit 1 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/bundler/source.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class Source 4 | autoload :Gemspec, "bundler/source/gemspec" 5 | autoload :Git, "bundler/source/git" 6 | autoload :Path, "bundler/source/path" 7 | autoload :Rubygems, "bundler/source/rubygems" 8 | 9 | attr_accessor :dependency_names 10 | 11 | def unmet_deps 12 | specs.unmet_dependency_names 13 | end 14 | 15 | def version_message(spec) 16 | message = "#{spec.name} #{spec.version}" 17 | 18 | if Bundler.locked_gems 19 | locked_spec = Bundler.locked_gems.specs.find {|s| s.name == spec.name } 20 | locked_spec_version = locked_spec.version if locked_spec 21 | if locked_spec_version && spec.version != locked_spec_version 22 | message += " (#{Bundler.ui.add_color("was #{locked_spec_version}", :green)})" 23 | end 24 | end 25 | 26 | message 27 | end 28 | 29 | def can_lock?(spec) 30 | spec.source == self 31 | end 32 | 33 | def include?(other) 34 | other == self 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /spec/support/artifice/endpoint_creds_diff_host.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../endpoint", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class EndpointCredsDiffHost < Endpoint 7 | helpers do 8 | def auth 9 | @auth ||= Rack::Auth::Basic::Request.new(request.env) 10 | end 11 | 12 | def authorized? 13 | auth.provided? && auth.basic? && auth.credentials && auth.credentials == %w(user pass) 14 | end 15 | 16 | def protected! 17 | return if authorized? 18 | response["WWW-Authenticate"] = %(Basic realm="Testing HTTP Auth") 19 | throw(:halt, [401, "Not authorized\n"]) 20 | end 21 | end 22 | 23 | before do 24 | protected! unless request.path_info.include?("/no/creds/") 25 | end 26 | 27 | get "/gems/:id" do 28 | redirect "http://diffhost.com/no/creds/#{params[:id]}" 29 | end 30 | 31 | get "/no/creds/:id" do 32 | if request.host.include?("diffhost") && !auth.provided? 33 | File.read("#{gem_repo1}/gems/#{params[:id]}") 34 | end 35 | end 36 | end 37 | 38 | Artifice.activate_with(EndpointCredsDiffHost) 39 | -------------------------------------------------------------------------------- /lib/bundler/cli/init.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class CLI::Init 4 | attr_reader :options 5 | def initialize(options) 6 | @options = options 7 | end 8 | 9 | def run 10 | if File.exist?("Gemfile") 11 | Bundler.ui.error "Gemfile already exists at #{SharedHelpers.pwd}/Gemfile" 12 | exit 1 13 | end 14 | 15 | if options[:gemspec] 16 | gemspec = File.expand_path(options[:gemspec]) 17 | unless File.exist?(gemspec) 18 | Bundler.ui.error "Gem specification #{gemspec} doesn't exist" 19 | exit 1 20 | end 21 | spec = Gem::Specification.load(gemspec) 22 | puts "Writing new Gemfile to #{SharedHelpers.pwd}/Gemfile" 23 | File.open("Gemfile", "wb") do |file| 24 | file << "# Generated from #{gemspec}\n" 25 | file << spec.to_gemfile 26 | end 27 | else 28 | puts "Writing new Gemfile to #{SharedHelpers.pwd}/Gemfile" 29 | FileUtils.cp(File.expand_path("../../templates/Gemfile", __FILE__), "Gemfile") 30 | end 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler::Molinillo 3 | class DependencyGraph 4 | # An action that modifies a {DependencyGraph} that is reversible. 5 | # @abstract 6 | class Action 7 | # rubocop:disable Lint/UnusedMethodArgument 8 | 9 | # @return [Symbol] The name of the action. 10 | def self.name 11 | raise 'Abstract' 12 | end 13 | 14 | # Performs the action on the given graph. 15 | # @param [DependencyGraph] graph the graph to perform the action on. 16 | # @return [Void] 17 | def up(graph) 18 | raise 'Abstract' 19 | end 20 | 21 | # Reverses the action on the given graph. 22 | # @param [DependencyGraph] graph the graph to reverse the action on. 23 | # @return [Void] 24 | def down(graph) 25 | raise 'Abstract' 26 | end 27 | 28 | # @return [Action,Nil] The previous action 29 | attr_accessor :previous 30 | 31 | # @return [Action,Nil] The next action 32 | attr_accessor :next 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /spec/support/artifice/compact_index_creds_diff_host.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../compact_index", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class CompactIndexCredsDiffHost < CompactIndexAPI 7 | helpers do 8 | def auth 9 | @auth ||= Rack::Auth::Basic::Request.new(request.env) 10 | end 11 | 12 | def authorized? 13 | auth.provided? && auth.basic? && auth.credentials && auth.credentials == %w(user pass) 14 | end 15 | 16 | def protected! 17 | return if authorized? 18 | response["WWW-Authenticate"] = %(Basic realm="Testing HTTP Auth") 19 | throw(:halt, [401, "Not authorized\n"]) 20 | end 21 | end 22 | 23 | before do 24 | protected! unless request.path_info.include?("/no/creds/") 25 | end 26 | 27 | get "/gems/:id" do 28 | redirect "http://diffhost.com/no/creds/#{params[:id]}" 29 | end 30 | 31 | get "/no/creds/:id" do 32 | if request.host.include?("diffhost") && !auth.provided? 33 | File.read("#{gem_repo1}/gems/#{params[:id]}") 34 | end 35 | end 36 | end 37 | 38 | Artifice.activate_with(CompactIndexCredsDiffHost) 39 | -------------------------------------------------------------------------------- /spec/install/force_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle install" do 5 | describe "with --force" do 6 | before :each do 7 | gemfile <<-G 8 | source "file://#{gem_repo1}" 9 | gem "rack" 10 | G 11 | end 12 | 13 | it "re-installs installed gems" do 14 | rack_lib = default_bundle_path("gems/rack-1.0.0/lib/rack.rb") 15 | 16 | bundle "install" 17 | rack_lib.open("w") {|f| f.write("blah blah blah") } 18 | bundle "install --force" 19 | 20 | expect(exitstatus).to eq(0) if exitstatus 21 | expect(out).to include "Using bundler" 22 | expect(out).to include "Installing rack 1.0.0" 23 | expect(rack_lib.open(&:read)).to eq("RACK = '1.0.0'\n") 24 | should_be_installed "rack 1.0.0" 25 | end 26 | 27 | it "works on first bundle install" do 28 | bundle "install --force" 29 | 30 | expect(exitstatus).to eq(0) if exitstatus 31 | expect(out).to include "Using bundler" 32 | expect(out).to include "Installing rack 1.0.0" 33 | should_be_installed "rack 1.0.0" 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/bundler/cli/plugin.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "bundler/vendored_thor" 3 | module Bundler 4 | class CLI::Plugin < Thor 5 | desc "install PLUGINS", "Install the plugin from the source" 6 | long_desc <<-D 7 | Install plugins either from the rubygems source provided (with --source option) or from a git source provided with (--git option). If no sources are provided, it uses Gem.sources 8 | D 9 | method_option "source", :type => :string, :default => nil, :banner => 10 | "URL of the RubyGems source to fetch the plugin from" 11 | method_option "version", :type => :string, :default => nil, :banner => 12 | "The version of the plugin to fetch" 13 | method_option "git", :type => :string, :default => nil, :banner => 14 | "URL of the git repo to fetch from" 15 | method_option "branch", :type => :string, :default => nil, :banner => 16 | "The git branch to checkout" 17 | method_option "ref", :type => :string, :default => nil, :banner => 18 | "The git revision to check out" 19 | def install(*plugins) 20 | Bundler::Plugin.install(plugins, options) 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /spec/install/gemfile/install_if.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle install with install_if conditionals" do 5 | it "follows the install_if DSL" do 6 | install_gemfile <<-G 7 | source "file://#{gem_repo1}" 8 | install_if(lambda { true }) do 9 | gem "activesupport", "2.3.5" 10 | end 11 | gem "thin", :install_if => false 12 | install_if(lambda { false }) do 13 | gem "foo" 14 | end 15 | gem "rack" 16 | G 17 | 18 | should_be_installed("rack 1.0", "activesupport 2.3.5") 19 | should_not_be_installed("thin") 20 | should_not_be_installed("foo") 21 | 22 | lockfile_should_be <<-L 23 | GEM 24 | remote: file:#{gem_repo1}/ 25 | specs: 26 | activesupport (2.3.5) 27 | foo (1.0) 28 | rack (1.0.0) 29 | thin (1.0) 30 | rack 31 | 32 | PLATFORMS 33 | ruby 34 | 35 | DEPENDENCIES 36 | activesupport (= 2.3.5) 37 | foo 38 | rack 39 | thin 40 | 41 | BUNDLED WITH 42 | #{Bundler::VERSION} 43 | L 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /bin/with_rubygems: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require "pathname" 5 | 6 | def run(*cmd) 7 | return if system(*cmd) 8 | raise "Running `#{cmd.join(" ")}` failed" 9 | end 10 | 11 | version = ENV.delete("RGV") 12 | rubygems_path = Pathname.new(__FILE__).join("../../tmp/rubygems").expand_path 13 | unless rubygems_path.directory? 14 | rubygems_path.parent.mkpath unless rubygems_path.directory? 15 | run("git", "clone", "https://github.com/rubygems/rubygems.git", rubygems_path.to_s) 16 | end 17 | Dir.chdir(rubygems_path) do 18 | version = "v#{version}" if version =~ /\A\d/ 19 | run("git", "checkout", version, "--quiet") 20 | end if version 21 | 22 | rubygems_lib = rubygems_path + "lib" 23 | ENV["RUBYOPT"] = %(-I#{rubygems_lib} #{ENV["RUBYOPT"]}) 24 | 25 | if $0 != __FILE__ 26 | ARGV.unshift($0) 27 | elsif cmd = ARGV.first 28 | possible_dirs = [ 29 | Pathname.new(__FILE__) + "..", 30 | Pathname.new(__FILE__) + "../../exe", 31 | rubygems_path + "bin", 32 | ] 33 | cmd = possible_dirs.map do |dir| 34 | dir.join(cmd).expand_path 35 | end.find(&:file?) 36 | ARGV[0] = cmd.to_s if cmd 37 | end 38 | 39 | exec(*ARGV) 40 | -------------------------------------------------------------------------------- /lib/bundler/vendor/thor/lib/thor/error.rb: -------------------------------------------------------------------------------- 1 | class Bundler::Thor 2 | # Bundler::Thor::Error is raised when it's caused by wrong usage of thor classes. Those 3 | # errors have their backtrace suppressed and are nicely shown to the user. 4 | # 5 | # Errors that are caused by the developer, like declaring a method which 6 | # overwrites a thor keyword, it SHOULD NOT raise a Bundler::Thor::Error. This way, we 7 | # ensure that developer errors are shown with full backtrace. 8 | class Error < StandardError 9 | end 10 | 11 | # Raised when a command was not found. 12 | class UndefinedCommandError < Error 13 | end 14 | UndefinedTaskError = UndefinedCommandError # rubocop:disable ConstantName 15 | 16 | class AmbiguousCommandError < Error 17 | end 18 | AmbiguousTaskError = AmbiguousCommandError # rubocop:disable ConstantName 19 | 20 | # Raised when a command was found, but not invoked properly. 21 | class InvocationError < Error 22 | end 23 | 24 | class UnknownArgumentError < Error 25 | end 26 | 27 | class RequiredArgumentMissingError < InvocationError 28 | end 29 | 30 | class MalformattedArgumentError < InvocationError 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /spec/install/prereleases_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle install" do 5 | describe "when prerelease gems are available" do 6 | it "finds prereleases" do 7 | install_gemfile <<-G 8 | source "file://#{gem_repo1}" 9 | gem "not_released" 10 | G 11 | should_be_installed "not_released 1.0.pre" 12 | end 13 | 14 | it "uses regular releases if available" do 15 | install_gemfile <<-G 16 | source "file://#{gem_repo1}" 17 | gem "has_prerelease" 18 | G 19 | should_be_installed "has_prerelease 1.0" 20 | end 21 | 22 | it "uses prereleases if requested" do 23 | install_gemfile <<-G 24 | source "file://#{gem_repo1}" 25 | gem "has_prerelease", "1.1.pre" 26 | G 27 | should_be_installed "has_prerelease 1.1.pre" 28 | end 29 | end 30 | 31 | describe "when prerelease gems are not available" do 32 | it "still works" do 33 | build_repo3 34 | install_gemfile <<-G 35 | source "file://#{gem_repo3}" 36 | gem "rack" 37 | G 38 | 39 | should_be_installed "rack 1.0" 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Portions copyright (c) 2010 Andre Arko 2 | Portions copyright (c) 2009 Engine Yard 3 | 4 | MIT License 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /spec/install/yanked_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | context "when installing a bundle that includes yanked gems" do 5 | before(:each) do 6 | build_repo4 do 7 | build_gem "foo", "9.0.0" 8 | end 9 | end 10 | 11 | it "throws an error when the original gem version is yanked" do 12 | lockfile <<-L 13 | GEM 14 | remote: file://#{gem_repo4} 15 | specs: 16 | foo (10.0.0) 17 | 18 | PLATFORMS 19 | ruby 20 | 21 | DEPENDENCIES 22 | foo (= 10.0.0) 23 | 24 | L 25 | 26 | install_gemfile <<-G 27 | source "file://#{gem_repo4}" 28 | gem "foo", "10.0.0" 29 | G 30 | 31 | expect(out).to include("Your bundle is locked to foo (10.0.0)") 32 | end 33 | 34 | it "throws the original error when only the Gemfile specifies a gem version that doesn't exist" do 35 | install_gemfile <<-G 36 | source "file://#{gem_repo4}" 37 | gem "foo", "10.0.0" 38 | G 39 | 40 | expect(out).not_to include("Your bundle is locked to foo (10.0.0)") 41 | expect(out).to include("Could not find gem 'foo (= 10.0.0)' in any of the gem sources") 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/LICENSE.txt.tt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) <%=Time.now.year%> <%=config[:author]%> 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /spec/commands/init_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle init" do 5 | it "generates a Gemfile" do 6 | bundle :init 7 | expect(bundled_app("Gemfile")).to exist 8 | end 9 | 10 | it "does not change existing Gemfiles" do 11 | gemfile <<-G 12 | gem "rails" 13 | G 14 | 15 | expect do 16 | bundle :init 17 | end.not_to change { File.read(bundled_app("Gemfile")) } 18 | end 19 | 20 | it "should generate from an existing gemspec" do 21 | spec_file = tmp.join("test.gemspec") 22 | File.open(spec_file, "w") do |file| 23 | file << <<-S 24 | Gem::Specification.new do |s| 25 | s.name = 'test' 26 | s.add_dependency 'rack', '= 1.0.1' 27 | s.add_development_dependency 'rspec', '1.2' 28 | end 29 | S 30 | end 31 | 32 | bundle :init, :gemspec => spec_file 33 | 34 | gemfile = bundled_app("Gemfile").read 35 | expect(gemfile).to match(%r{source 'https://rubygems.org'}) 36 | expect(gemfile.scan(/gem "rack", "= 1.0.1"/).size).to eq(1) 37 | expect(gemfile.scan(/gem "rspec", "= 1.2"/).size).to eq(1) 38 | expect(gemfile.scan(/group :development/).size).to eq(1) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/bundler/cli/cache.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class CLI::Cache 4 | attr_reader :options 5 | def initialize(options) 6 | @options = options 7 | end 8 | 9 | def run 10 | Bundler.definition.validate_ruby! 11 | Bundler.definition.resolve_with_cache! 12 | setup_cache_all 13 | Bundler.settings[:cache_all_platforms] = options["all-platforms"] if options.key?("all-platforms") 14 | Bundler.load.cache 15 | Bundler.settings[:no_prune] = true if options["no-prune"] 16 | Bundler.load.lock 17 | rescue GemNotFound => e 18 | Bundler.ui.error(e.message) 19 | Bundler.ui.warn "Run `bundle install` to install missing gems." 20 | exit 1 21 | end 22 | 23 | private 24 | 25 | def setup_cache_all 26 | Bundler.settings[:cache_all] = options[:all] if options.key?("all") 27 | 28 | if Bundler.definition.has_local_dependencies? && !Bundler.settings[:cache_all] 29 | Bundler.ui.warn "Your Gemfile contains path and git dependencies. If you want " \ 30 | "to package them as well, please pass the --all flag. This will be the default " \ 31 | "on Bundler 2.0." 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/bundler/gem_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | module GemHelpers 4 | GENERIC_CACHE = {} # rubocop:disable MutableConstant 5 | GENERICS = [ 6 | [Gem::Platform.new("java"), Gem::Platform.new("java")], 7 | [Gem::Platform.new("mswin32"), Gem::Platform.new("mswin32")], 8 | [Gem::Platform.new("mswin64"), Gem::Platform.new("mswin64")], 9 | [Gem::Platform.new("universal-mingw32"), Gem::Platform.new("universal-mingw32")], 10 | [Gem::Platform.new("x64-mingw32"), Gem::Platform.new("x64-mingw32")], 11 | [Gem::Platform.new("x86_64-mingw32"), Gem::Platform.new("x64-mingw32")], 12 | [Gem::Platform.new("mingw32"), Gem::Platform.new("x86-mingw32")] 13 | ].freeze 14 | 15 | def generic(p) 16 | return p if p == Gem::Platform::RUBY 17 | 18 | GENERIC_CACHE[p] ||= begin 19 | _, found = GENERICS.find do |match, _generic| 20 | p.os == match.os && (!match.cpu || p.cpu == match.cpu) 21 | end 22 | found || Gem::Platform::RUBY 23 | end 24 | end 25 | module_function :generic 26 | 27 | def generic_local_platform 28 | generic(Gem::Platform.local) 29 | end 30 | module_function :generic_local_platform 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /spec/support/hax.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "rubygems" 3 | 4 | class Gem::Platform 5 | @local = new(ENV["BUNDLER_SPEC_PLATFORM"]) if ENV["BUNDLER_SPEC_PLATFORM"] 6 | end 7 | 8 | if ENV["BUNDLER_SPEC_VERSION"] 9 | module Bundler 10 | VERSION = ENV["BUNDLER_SPEC_VERSION"].dup 11 | end 12 | end 13 | 14 | if ENV["BUNDLER_SPEC_WINDOWS"] == "true" 15 | require "bundler/constants" 16 | 17 | module Bundler 18 | remove_const :WINDOWS if defined?(WINDOWS) 19 | WINDOWS = true 20 | end 21 | end 22 | 23 | class Object 24 | if ENV["BUNDLER_SPEC_RUBY_ENGINE"] 25 | if defined?(RUBY_ENGINE) && RUBY_ENGINE != "jruby" && ENV["BUNDLER_SPEC_RUBY_ENGINE"] == "jruby" 26 | begin 27 | # this has to be done up front because psych will try to load a .jar 28 | # if it thinks its on jruby 29 | require "psych" 30 | rescue LoadError 31 | nil 32 | end 33 | end 34 | 35 | remove_const :RUBY_ENGINE if defined?(RUBY_ENGINE) 36 | RUBY_ENGINE = ENV["BUNDLER_SPEC_RUBY_ENGINE"] 37 | 38 | if RUBY_ENGINE == "jruby" 39 | remove_const :JRUBY_VERSION if defined?(JRUBY_VERSION) 40 | JRUBY_VERSION = ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/bundler/vendor/postit/lib/postit/environment.rb: -------------------------------------------------------------------------------- 1 | require 'bundler/vendor/postit/lib/postit/parser' 2 | 3 | module BundlerVendoredPostIt::PostIt 4 | class Environment 5 | def initialize(argv) 6 | @argv = argv 7 | end 8 | 9 | def env_var_version 10 | ENV['BUNDLER_VERSION'] 11 | end 12 | 13 | def cli_arg_version 14 | return unless str = @argv.first 15 | str = str.dup.force_encoding('BINARY') if str.respond_to?(:force_encoding) 16 | if Gem::Version.correct?(str) 17 | @argv.shift 18 | str 19 | end 20 | end 21 | 22 | def gemfile 23 | ENV['BUNDLE_GEMFILE'] || 'Gemfile' 24 | end 25 | 26 | def lockfile 27 | File.expand_path case File.basename(gemfile) 28 | when 'gems.rb' then gemfile.sub(/\.rb$/, gemfile) 29 | else "#{gemfile}.lock" 30 | end 31 | end 32 | 33 | def lockfile_version 34 | BundlerVendoredPostIt::PostIt::Parser.new(lockfile).parse 35 | end 36 | 37 | def bundler_version 38 | @bundler_version ||= begin 39 | env_var_version || cli_arg_version || 40 | lockfile_version || "#{Gem::Requirement.default}.a" 41 | end 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /spec/runtime/gem_tasks_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "require 'bundler/gem_tasks'" do 5 | before :each do 6 | bundled_app("foo.gemspec").open("w") do |f| 7 | f.write <<-GEMSPEC 8 | Gem::Specification.new do |s| 9 | s.name = "foo" 10 | end 11 | GEMSPEC 12 | end 13 | bundled_app("Rakefile").open("w") do |f| 14 | f.write <<-RAKEFILE 15 | $:.unshift("#{bundler_path}") 16 | require "bundler/gem_tasks" 17 | RAKEFILE 18 | end 19 | end 20 | 21 | it "includes the relevant tasks" do 22 | with_gem_path_as(Spec::Path.base_system_gems.to_s) do 23 | sys_exec "ruby -S rake -T" 24 | end 25 | 26 | expect(err).to eq("") 27 | expected_tasks = [ 28 | "rake build", 29 | "rake clean", 30 | "rake clobber", 31 | "rake install", 32 | "rake release[remote]", 33 | ] 34 | tasks = out.lines.to_a.map {|s| s.split("#").first.strip } 35 | expect(tasks & expected_tasks).to eq(expected_tasks) 36 | expect(exitstatus).to eq(0) if exitstatus 37 | end 38 | 39 | it "adds 'pkg' to rake/clean's CLOBBER" do 40 | require "bundler/gem_tasks" 41 | expect(CLOBBER).to include("pkg") 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /exe/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # Exit cleanly from an early interrupt 5 | Signal.trap("INT") { exit 1 } 6 | 7 | unless ENV["BUNDLE_DISABLE_POSTIT"] 8 | update = "update".start_with?(ARGV.first || " ") && ARGV.find {|a| a.start_with?("--bundler") } 9 | update &&= update =~ /--bundler(?:=(.+))?/ && $1 || "> 0.a" 10 | ENV["BUNDLER_VERSION"] = update if update 11 | require "bundler/postit_trampoline" 12 | end 13 | 14 | require "bundler" 15 | # Check if an older version of bundler is installed 16 | $LOAD_PATH.each do |path| 17 | next unless path =~ %r{/bundler-0\.(\d+)} && $1.to_i < 9 18 | err = String.new 19 | err << "Looks like you have a version of bundler that's older than 0.9.\n" 20 | err << "Please remove your old versions.\n" 21 | err << "An easy way to do this is by running `gem cleanup bundler`." 22 | abort(err) 23 | end 24 | 25 | require "bundler/friendly_errors" 26 | Bundler.with_friendly_errors do 27 | require "bundler/cli" 28 | 29 | # Allow any command to use --help flag to show help for that command 30 | help_flags = %w(--help -h) 31 | help_flag_used = ARGV.any? {|a| help_flags.include? a } 32 | args = help_flag_used ? Bundler::CLI.reformatted_help_args(ARGV) : ARGV 33 | 34 | Bundler::CLI.start(args, :debug => true) 35 | end 36 | -------------------------------------------------------------------------------- /spec/support/artifice/compact_index_concurrent_download.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../compact_index", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class CompactIndexConcurrentDownload < CompactIndexAPI 7 | get "/versions" do 8 | versions = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index", 9 | "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions") 10 | 11 | # Verify the original (empty) content hasn't been deleted, e.g. on a retry 12 | File.read(versions) == "" || raise("Original file should be present and empty") 13 | 14 | # Verify this is only requested once for a partial download 15 | env["HTTP_RANGE"] || raise("Missing Range header for expected partial download") 16 | 17 | # Overwrite the file in parallel, which should be then overwritten 18 | # after a successful download to prevent corruption 19 | File.open(versions, "w") {|f| f.puts "another process" } 20 | 21 | etag_response do 22 | file = tmp("versions.list") 23 | file.delete if file.file? 24 | file = CompactIndex::VersionsFile.new(file.to_s) 25 | file.update_with(gems) 26 | CompactIndex.versions(file, nil, {}) 27 | end 28 | end 29 | end 30 | 31 | Artifice.activate_with(CompactIndexConcurrentDownload) 32 | -------------------------------------------------------------------------------- /spec/bundler/plugin/dsl_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe Bundler::Plugin::DSL do 5 | DSL = Bundler::Plugin::DSL 6 | 7 | subject(:dsl) { Bundler::Plugin::DSL.new } 8 | 9 | before do 10 | allow(Bundler).to receive(:root) { Pathname.new "/" } 11 | end 12 | 13 | describe "it ignores only the methods defined in Bundler::Dsl" do 14 | it "doesn't raises error for Dsl methods" do 15 | expect { dsl.install_if }.not_to raise_error 16 | end 17 | 18 | it "raises error for other methods" do 19 | expect { dsl.no_method }.to raise_error(DSL::PluginGemfileError) 20 | end 21 | end 22 | 23 | describe "source block" do 24 | it "adds #source with :type to list and also inferred_plugins list" do 25 | expect(dsl).to receive(:plugin).with("bundler-source-news").once 26 | 27 | dsl.source("some_random_url", :type => "news") {} 28 | 29 | expect(dsl.inferred_plugins).to eq(["bundler-source-news"]) 30 | end 31 | 32 | it "registers a source type plugin only once for multiple declataions" do 33 | expect(dsl).to receive(:plugin).with("bundler-source-news").and_call_original.once 34 | 35 | dsl.source("some_random_url", :type => "news") {} 36 | dsl.source("another_random_url", :type => "news") {} 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /man/bundle-platform.ronn: -------------------------------------------------------------------------------- 1 | bundle-platform(1) -- Displays platform compatibility information 2 | ================================================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `bundle platform` [--ruby] 7 | 8 | ## DESCRIPTION 9 | 10 | `platform` will display information from your Gemfile, Gemfile.lock, and Ruby 11 | VM about your platform. 12 | 13 | For instance, using this Gemfile(5): 14 | 15 | source "https://rubygems.org" 16 | 17 | ruby "1.9.3" 18 | 19 | gem "rack" 20 | 21 | If you run `bundle platform` on Ruby 1.9.3, it will display the following output: 22 | 23 | Your platform is: x86_64-linux 24 | 25 | Your app has gems that work on these platforms: 26 | * ruby 27 | 28 | Your Gemfile specifies a Ruby version requirement: 29 | * ruby 1.9.3 30 | 31 | Your current platform satisfies the Ruby version requirement. 32 | 33 | `platform` will list all the platforms in your `Gemfile.lock` as well as the 34 | `ruby` directive if applicable from your Gemfile(5). It will also let you know 35 | if the `ruby` directive requirement has been met. If `ruby` directive doesn't 36 | match the running Ruby VM, it will tell you what part does not. 37 | 38 | ## OPTIONS 39 | 40 | * `--ruby`: 41 | It will display the ruby directive information, so you don't have to 42 | parse it from the Gemfile(5). 43 | -------------------------------------------------------------------------------- /lib/bundler/cli/lock.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class CLI::Lock 4 | attr_reader :options 5 | 6 | def initialize(options) 7 | @options = options 8 | end 9 | 10 | def run 11 | unless Bundler.default_gemfile 12 | Bundler.ui.error "Unable to find a Gemfile to lock" 13 | exit 1 14 | end 15 | 16 | print = options[:print] 17 | ui = Bundler.ui 18 | Bundler.ui = UI::Silent.new if print 19 | 20 | gems = options[:update] 21 | Bundler::Fetcher.disable_endpoint = options["full-index"] 22 | 23 | if gems && !gems.empty? 24 | definition = Bundler.definition(:gems => gems) 25 | else 26 | definition = Bundler.definition(true) 27 | end 28 | 29 | options["add-platform"].each do |platform| 30 | platform = Gem::Platform.new(platform) 31 | definition.add_platform(platform) 32 | end 33 | 34 | definition.resolve_remotely! unless options[:local] 35 | 36 | if print 37 | puts definition.to_lock 38 | else 39 | file = options[:lockfile] 40 | file = file ? File.expand_path(file) : Bundler.default_lockfile 41 | puts "Writing lockfile to #{file}" 42 | definition.lock(file) 43 | end 44 | 45 | Bundler.ui = ui 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /spec/install/git_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle install" do 5 | context "git sources" do 6 | it "displays the revision hash of the gem repository" do 7 | build_git "foo", "1.0", :path => lib_path("foo") 8 | 9 | install_gemfile <<-G 10 | gem "foo", :git => "#{lib_path("foo")}" 11 | G 12 | 13 | bundle :install 14 | expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at master@#{revision_for(lib_path("foo"))[0..6]})") 15 | should_be_installed "foo 1.0" 16 | end 17 | 18 | it "should check out git repos that are missing but not being installed" do 19 | build_git "foo" 20 | 21 | gemfile <<-G 22 | gem "foo", :git => "file://#{lib_path("foo-1.0")}", :group => :development 23 | G 24 | 25 | lockfile <<-L 26 | GIT 27 | remote: file://#{lib_path("foo-1.0")} 28 | specs: 29 | foo (1.0) 30 | 31 | PLATFORMS 32 | ruby 33 | 34 | DEPENDENCIES 35 | foo! 36 | L 37 | 38 | bundle "install --path=vendor/bundle --without development" 39 | 40 | expect(out).to include("Bundle complete!") 41 | expect(vendored_gems("bundler/gems/foo-1.0-#{revision_for(lib_path("foo-1.0"))[0..11]}")).to be_directory 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /spec/install/gems/mirror_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle install with a mirror configured" do 5 | describe "when the mirror does not match the gem source" do 6 | before :each do 7 | gemfile <<-G 8 | source "file://#{gem_repo1}" 9 | 10 | gem "rack" 11 | G 12 | bundle "config --local mirror.http://gems.example.org http://gem-mirror.example.org" 13 | end 14 | 15 | it "installs from the normal location" do 16 | bundle :install 17 | expect(out).to include("Fetching source index from file:#{gem_repo1}") 18 | should_be_installed "rack 1.0" 19 | end 20 | end 21 | 22 | describe "when the gem source matches a configured mirror" do 23 | before :each do 24 | gemfile <<-G 25 | # This source is bogus and doesn't have the gem we're looking for 26 | source "file://#{gem_repo2}" 27 | 28 | gem "rack" 29 | G 30 | bundle "config --local mirror.file://#{gem_repo2} file://#{gem_repo1}" 31 | end 32 | 33 | it "installs the gem from the mirror" do 34 | bundle :install 35 | expect(out).to include("Fetching source index from file:#{gem_repo1}") 36 | expect(out).not_to include("Fetching source index from file:#{gem_repo2}") 37 | should_be_installed "rack 1.0" 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG 3 | A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv 4 | b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw 5 | MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i 6 | YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT 7 | aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ 8 | jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp 9 | xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp 10 | 1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG 11 | snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ 12 | U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 13 | 9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E 14 | BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B 15 | AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz 16 | yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE 17 | 38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP 18 | AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad 19 | DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME 20 | HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/action' 3 | module Bundler::Molinillo 4 | class DependencyGraph 5 | # @!visibility private 6 | # @see DependencyGraph#set_payload 7 | class SetPayload < Action # :nodoc: 8 | # @!group Action 9 | 10 | # (see Action.name) 11 | def self.name 12 | :set_payload 13 | end 14 | 15 | # (see Action#up) 16 | def up(graph) 17 | vertex = graph.vertex_named(name) 18 | @old_payload = vertex.payload 19 | vertex.payload = payload 20 | end 21 | 22 | # (see Action#down) 23 | def down(graph) 24 | graph.vertex_named(name).payload = @old_payload 25 | end 26 | 27 | # @!group SetPayload 28 | 29 | # @return [String] the name of the vertex 30 | attr_reader :name 31 | 32 | # @return [Object] the payload for the vertex 33 | attr_reader :payload 34 | 35 | # Initialize an action to add set the payload for a vertex in a dependency 36 | # graph 37 | # @param [String] name the name of the vertex 38 | # @param [Object] payload the payload for the vertex 39 | def initialize(name, payload) 40 | @name = name 41 | @payload = payload 42 | end 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/bundler/uri_credentials_filter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | module URICredentialsFilter 4 | module_function 5 | 6 | def credential_filtered_uri(uri_to_anonymize) 7 | return uri_to_anonymize if uri_to_anonymize.nil? 8 | uri = uri_to_anonymize.dup 9 | uri = URI(uri.to_s) unless uri.is_a?(URI) 10 | if uri.userinfo 11 | # oauth authentication 12 | if uri.password == "x-oauth-basic" || uri.password == "x" 13 | # URI as string does not display with password if no user is set 14 | oauth_designation = uri.password 15 | uri.user = oauth_designation 16 | end 17 | uri.password = nil 18 | end 19 | return uri if uri_to_anonymize.is_a?(URI) 20 | return uri.to_s if uri_to_anonymize.is_a?(String) 21 | rescue URI::InvalidURIError # uri is not canonical uri scheme 22 | uri 23 | end 24 | 25 | def credential_filtered_string(str_to_filter, uri) 26 | return str_to_filter if uri.nil? || str_to_filter.nil? 27 | str_with_no_credentials = str_to_filter.dup 28 | anonymous_uri_str = credential_filtered_uri(uri).to_s 29 | uri_str = uri.to_s 30 | if anonymous_uri_str != uri_str 31 | str_with_no_credentials = str_with_no_credentials.gsub(uri_str, anonymous_uri_str) 32 | end 33 | str_with_no_credentials 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/bundler/cli/binstubs.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "bundler/cli/common" 3 | 4 | module Bundler 5 | class CLI::Binstubs 6 | attr_reader :options, :gems 7 | def initialize(options, gems) 8 | @options = options 9 | @gems = gems 10 | end 11 | 12 | def run 13 | Bundler.definition.validate_ruby! 14 | Bundler.settings[:bin] = options["path"] if options["path"] 15 | Bundler.settings[:bin] = nil if options["path"] && options["path"].empty? 16 | installer = Installer.new(Bundler.root, Bundler.definition) 17 | 18 | if gems.empty? 19 | Bundler.ui.error "`bundle binstubs` needs at least one gem to run." 20 | exit 1 21 | end 22 | 23 | gems.each do |gem_name| 24 | spec = installer.specs.find {|s| s.name == gem_name } 25 | unless spec 26 | raise GemNotFound, Bundler::CLI::Common.gem_not_found_message( 27 | gem_name, Bundler.definition.specs) 28 | end 29 | 30 | if spec.name == "bundler" 31 | Bundler.ui.warn "Sorry, Bundler can only be run via Rubygems." 32 | elsif options[:standalone] 33 | installer.generate_standalone_bundler_executable_stubs(spec) 34 | else 35 | installer.generate_bundler_executable_stubs(spec, :force => options[:force], :binstubs_cmd => true) 36 | end 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/install/gemfile/eval_gemfile_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle install with gemfile that uses eval_gemfile" do 5 | before do 6 | build_lib("gunks", :path => bundled_app.join("gems/gunks")) do |s| 7 | s.name = "gunks" 8 | s.version = "0.0.1" 9 | end 10 | end 11 | 12 | context "eval-ed Gemfile points to an internal gemspec" do 13 | before do 14 | create_file "Gemfile-other", <<-G 15 | gemspec :path => 'gems/gunks' 16 | G 17 | end 18 | 19 | it "installs the gemspec specified gem" do 20 | install_gemfile <<-G 21 | eval_gemfile 'Gemfile-other' 22 | G 23 | expect(out).to include("Resolving dependencies") 24 | expect(out).to include("Using gunks 0.0.1 from source at `gems/gunks`") 25 | expect(out).to include("Bundle complete") 26 | end 27 | end 28 | 29 | context "Gemfile uses gemspec paths after eval-ing a Gemfile" do 30 | before { create_file "other/Gemfile-other" } 31 | 32 | it "installs the gemspec specified gem" do 33 | install_gemfile <<-G 34 | eval_gemfile 'other/Gemfile-other' 35 | gemspec :path => 'gems/gunks' 36 | G 37 | expect(out).to include("Resolving dependencies") 38 | expect(out).to include("Using gunks 0.0.1 from source at `gems/gunks`") 39 | expect(out).to include("Bundle complete") 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/bundler/retry_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe Bundler::Retry do 5 | it "return successful result if no errors" do 6 | attempts = 0 7 | result = Bundler::Retry.new(nil, nil, 3).attempt do 8 | attempts += 1 9 | :success 10 | end 11 | expect(result).to eq(:success) 12 | expect(attempts).to eq(1) 13 | end 14 | 15 | it "returns the first valid result" do 16 | jobs = [proc { raise "foo" }, proc { :bar }, proc { raise "foo" }] 17 | attempts = 0 18 | result = Bundler::Retry.new(nil, nil, 3).attempt do 19 | attempts += 1 20 | jobs.shift.call 21 | end 22 | expect(result).to eq(:bar) 23 | expect(attempts).to eq(2) 24 | end 25 | 26 | it "raises the last error" do 27 | errors = [StandardError, StandardError, StandardError, Bundler::GemfileNotFound] 28 | attempts = 0 29 | expect do 30 | Bundler::Retry.new(nil, nil, 3).attempt do 31 | attempts += 1 32 | raise errors.shift 33 | end 34 | end.to raise_error(Bundler::GemfileNotFound) 35 | expect(attempts).to eq(4) 36 | end 37 | 38 | it "raises exceptions" do 39 | error = Bundler::GemfileNotFound 40 | attempts = 0 41 | expect do 42 | Bundler::Retry.new(nil, error).attempt do 43 | attempts += 1 44 | raise error 45 | end 46 | end.to raise_error(error) 47 | expect(attempts).to eq(1) 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /spec/bundler/source/git/git_proxy_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe Bundler::Source::Git::GitProxy do 5 | let(:uri) { "https://github.com/bundler/bundler.git" } 6 | subject { described_class.new(Pathname("path"), uri, "HEAD") } 7 | 8 | context "with configured credentials" do 9 | it "adds username and password to URI" do 10 | Bundler.settings[uri] = "u:p" 11 | expect(subject).to receive(:git_retry).with(match("https://u:p@github.com/bundler/bundler.git")) 12 | subject.checkout 13 | end 14 | 15 | it "adds username and password to URI for host" do 16 | Bundler.settings["github.com"] = "u:p" 17 | expect(subject).to receive(:git_retry).with(match("https://u:p@github.com/bundler/bundler.git")) 18 | subject.checkout 19 | end 20 | 21 | it "does not add username and password to mismatched URI" do 22 | Bundler.settings["https://u:p@github.com/bundler/bundler-mismatch.git"] = "u:p" 23 | expect(subject).to receive(:git_retry).with(match(uri)) 24 | subject.checkout 25 | end 26 | 27 | it "keeps original userinfo" do 28 | Bundler.settings["github.com"] = "u:p" 29 | original = "https://orig:info@github.com/bundler/bundler.git" 30 | subject = described_class.new(Pathname("path"), original, "HEAD") 31 | expect(subject).to receive(:git_retry).with(match(original)) 32 | subject.checkout 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /spec/realworld/dependency_api_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "gemcutter's dependency API", :realworld => true do 5 | context "when Gemcutter API takes too long to respond" do 6 | before do 7 | require_rack 8 | 9 | port = find_unused_port 10 | @server_uri = "http://127.0.0.1:#{port}" 11 | 12 | require File.expand_path("../../support/artifice/endpoint_timeout", __FILE__) 13 | require "thread" 14 | @t = Thread.new do 15 | server = Rack::Server.start(:app => EndpointTimeout, 16 | :Host => "0.0.0.0", 17 | :Port => port, 18 | :server => "webrick", 19 | :AccessLog => []) 20 | server.start 21 | end 22 | @t.run 23 | 24 | wait_for_server("127.0.0.1", port) 25 | end 26 | 27 | after do 28 | @t.kill 29 | @t.join 30 | end 31 | 32 | it "times out and falls back on the modern index" do 33 | gemfile <<-G 34 | source "#{@server_uri}" 35 | gem "rack" 36 | 37 | old_v, $VERBOSE = $VERBOSE, nil 38 | Bundler::Fetcher.api_timeout = 1 39 | $VERBOSE = old_v 40 | G 41 | 42 | bundle :install 43 | expect(out).to include("Fetching source index from #{@server_uri}/") 44 | should_be_installed "rack 1.0.0" 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /spec/cache/platform_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle cache with multiple platforms" do 5 | before :each do 6 | gemfile <<-G 7 | source "file://#{gem_repo1}" 8 | 9 | platforms :mri, :rbx do 10 | gem "rack", "1.0.0" 11 | end 12 | 13 | platforms :jruby do 14 | gem "activesupport", "2.3.5" 15 | end 16 | G 17 | 18 | lockfile <<-G 19 | GEM 20 | remote: file:#{gem_repo1}/ 21 | specs: 22 | rack (1.0.0) 23 | activesupport (2.3.5) 24 | 25 | PLATFORMS 26 | ruby 27 | java 28 | 29 | DEPENDENCIES 30 | rack (1.0.0) 31 | activesupport (2.3.5) 32 | G 33 | 34 | cache_gems "rack-1.0.0", "activesupport-2.3.5" 35 | end 36 | 37 | it "ensures that a successful bundle install does not delete gems for other platforms" do 38 | bundle "install" 39 | 40 | expect(exitstatus).to eq 0 if exitstatus 41 | 42 | expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist 43 | expect(bundled_app("vendor/cache/activesupport-2.3.5.gem")).to exist 44 | end 45 | 46 | it "ensures that a successful bundle update does not delete gems for other platforms" do 47 | bundle "update" 48 | 49 | expect(exitstatus).to eq 0 if exitstatus 50 | 51 | expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist 52 | expect(bundled_app("vendor/cache/activesupport-2.3.5.gem")).to exist 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /spec/support/artifice/compact_index_extra_api.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require File.expand_path("../compact_index", __FILE__) 3 | 4 | Artifice.deactivate 5 | 6 | class CompactIndexExtraApi < CompactIndexAPI 7 | get "/extra/names" do 8 | etag_response do 9 | CompactIndex.names(gems(gem_repo4).map(&:name)) 10 | end 11 | end 12 | 13 | get "/extra/versions" do 14 | etag_response do 15 | file = tmp("versions.list") 16 | file.delete if file.file? 17 | file = CompactIndex::VersionsFile.new(file.to_s) 18 | file.update_with(gems(gem_repo4)) 19 | CompactIndex.versions(file, nil, {}) 20 | end 21 | end 22 | 23 | get "/extra/info/:name" do 24 | etag_response do 25 | gem = gems(gem_repo4).find {|g| g.name == params[:name] } 26 | CompactIndex.info(gem ? gem.versions : []) 27 | end 28 | end 29 | 30 | get "/extra/specs.4.8.gz" do 31 | File.read("#{gem_repo4}/specs.4.8.gz") 32 | end 33 | 34 | get "/extra/prerelease_specs.4.8.gz" do 35 | File.read("#{gem_repo4}/prerelease_specs.4.8.gz") 36 | end 37 | 38 | get "/extra/quick/Marshal.4.8/:id" do 39 | redirect "/extra/fetch/actual/gem/#{params[:id]}" 40 | end 41 | 42 | get "/extra/fetch/actual/gem/:id" do 43 | File.read("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}") 44 | end 45 | 46 | get "/extra/gems/:id" do 47 | File.read("#{gem_repo4}/gems/#{params[:id]}") 48 | end 49 | end 50 | 51 | Artifice.activate_with(CompactIndexExtraApi) 52 | -------------------------------------------------------------------------------- /spec/realworld/gemfile_source_header_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | require "thread" 4 | 5 | describe "fetching dependencies with a mirrored source", :realworld => true, :rubygems => ">= 2.0" do 6 | let(:mirror) { "https://server.example.org" } 7 | let(:original) { "http://127.0.0.1:#{@port}" } 8 | 9 | before do 10 | setup_server 11 | bundle "config --local mirror.#{mirror} #{original}" 12 | end 13 | 14 | after do 15 | @t.kill 16 | @t.join 17 | end 18 | 19 | it "sets the 'X-Gemfile-Source' header and bundles successfully" do 20 | gemfile <<-G 21 | source "#{mirror}" 22 | gem 'weakling' 23 | G 24 | 25 | bundle :install 26 | 27 | expect(out).to include("Installing weakling") 28 | expect(out).to include("Bundle complete") 29 | should_be_installed "weakling 0.0.3" 30 | end 31 | 32 | private 33 | 34 | def setup_server 35 | require_rack 36 | @port = find_unused_port 37 | @server_uri = "http://127.0.0.1:#{@port}" 38 | 39 | require File.expand_path("../../support/artifice/endpoint_mirror_source", __FILE__) 40 | 41 | @t = Thread.new do 42 | Rack::Server.start(:app => EndpointMirrorSource, 43 | :Host => "0.0.0.0", 44 | :Port => @port, 45 | :server => "webrick", 46 | :AccessLog => []) 47 | end.run 48 | 49 | wait_for_server("127.0.0.1", @port) 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs 3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 4 | d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j 5 | ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL 6 | MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 7 | LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug 8 | RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm 9 | +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW 10 | PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM 11 | xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB 12 | Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 13 | hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg 14 | EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF 15 | MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA 16 | FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec 17 | nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z 18 | eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF 19 | hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 20 | Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe 21 | vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep 22 | +OkuE6N36B9K 23 | -----END CERTIFICATE----- 24 | -------------------------------------------------------------------------------- /lib/bundler/cli/check.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class CLI::Check 4 | attr_reader :options 5 | 6 | def initialize(options) 7 | @options = options 8 | end 9 | 10 | def run 11 | if options[:path] 12 | Bundler.settings[:path] = File.expand_path(options[:path]) 13 | Bundler.settings[:disable_shared_gems] = true 14 | end 15 | 16 | begin 17 | definition = Bundler.definition 18 | definition.validate_ruby! 19 | not_installed = definition.missing_specs 20 | rescue GemNotFound, VersionConflict 21 | Bundler.ui.error "Bundler can't satisfy your Gemfile's dependencies." 22 | Bundler.ui.warn "Install missing gems with `bundle install`." 23 | exit 1 24 | end 25 | 26 | if not_installed.any? 27 | Bundler.ui.error "The following gems are missing" 28 | not_installed.each {|s| Bundler.ui.error " * #{s.name} (#{s.version})" } 29 | Bundler.ui.warn "Install missing gems with `bundle install`" 30 | exit 1 31 | elsif !Bundler.default_lockfile.exist? && Bundler.settings[:frozen] 32 | Bundler.ui.error "This bundle has been frozen, but there is no #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} present" 33 | exit 1 34 | else 35 | Bundler.load.lock(:preserve_unknown_sections => true) unless options[:"dry-run"] 36 | Bundler.ui.info "The Gemfile's dependencies are satisfied" 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /bundler.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | # frozen_string_literal: true 3 | lib = File.expand_path("../lib/", __FILE__) 4 | $:.unshift lib unless $:.include?(lib) 5 | require "bundler/version" 6 | 7 | Gem::Specification.new do |s| 8 | s.name = "bundler" 9 | s.version = Bundler::VERSION 10 | s.licenses = ["MIT"] 11 | s.authors = ["André Arko", "Samuel Giddins"] 12 | s.email = ["team@bundler.io"] 13 | s.homepage = "http://bundler.io" 14 | s.summary = "The best way to manage your application's dependencies" 15 | s.description = "Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably" 16 | 17 | s.required_ruby_version = ">= 1.8.7" 18 | s.required_rubygems_version = ">= 1.3.6" 19 | 20 | s.add_development_dependency "automatiek", "~> 0.1.0" 21 | s.add_development_dependency "mustache", "0.99.6" 22 | s.add_development_dependency "rake", "~> 10.0" 23 | s.add_development_dependency "rdiscount", "~> 2.1.8" 24 | s.add_development_dependency "ronn", "~> 0.7.3" 25 | s.add_development_dependency "rspec", "~> 3.0" 26 | 27 | s.files = `git ls-files -z`.split("\x0").reject {|f| f.match(%r{^(test|spec|features)/}) } 28 | # we don't check in man pages, but we need to ship them because 29 | # we use them to generate the long-form help for each command. 30 | s.files += Dir.glob("lib/bundler/man/**/*") 31 | 32 | s.bindir = "exe" 33 | s.executables = %w(bundle bundler) 34 | s.require_paths = ["lib"] 35 | end 36 | -------------------------------------------------------------------------------- /spec/install/gems/native_extensions_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "installing a gem with native extensions" do 5 | it "installs" do 6 | build_repo2 do 7 | build_gem "c_extension" do |s| 8 | s.extensions = ["ext/extconf.rb"] 9 | s.write "ext/extconf.rb", <<-E 10 | require "mkmf" 11 | name = "c_extension_bundle" 12 | dir_config(name) 13 | raise "OMG" unless with_config("c_extension") == "hello" 14 | create_makefile(name) 15 | E 16 | 17 | s.write "ext/c_extension.c", <<-C 18 | #include "ruby.h" 19 | 20 | VALUE c_extension_true(VALUE self) { 21 | return Qtrue; 22 | } 23 | 24 | void Init_c_extension_bundle() { 25 | VALUE c_Extension = rb_define_class("CExtension", rb_cObject); 26 | rb_define_method(c_Extension, "its_true", c_extension_true, 0); 27 | } 28 | C 29 | 30 | s.write "lib/c_extension.rb", <<-C 31 | require "c_extension_bundle" 32 | C 33 | end 34 | end 35 | 36 | gemfile <<-G 37 | source "file://#{gem_repo2}" 38 | gem "c_extension" 39 | G 40 | 41 | bundle "config build.c_extension --with-c_extension=hello" 42 | bundle "install" 43 | 44 | expect(out).not_to include("extconf.rb failed") 45 | expect(out).to include("Installing c_extension 1.0 with native extensions") 46 | 47 | run "Bundler.require; puts CExtension.new.its_true" 48 | expect(out).to eq("true") 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/bundler/cli/platform.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class CLI::Platform 4 | attr_reader :options 5 | def initialize(options) 6 | @options = options 7 | end 8 | 9 | def run 10 | platforms, ruby_version = Bundler.ui.silence do 11 | locked_ruby_version = Bundler.locked_gems && Bundler.locked_gems.ruby_version 12 | gemfile_ruby_version = Bundler.definition.ruby_version && Bundler.definition.ruby_version.single_version_string 13 | [Bundler.definition.platforms.map {|p| "* #{p}" }, 14 | locked_ruby_version || gemfile_ruby_version] 15 | end 16 | output = [] 17 | 18 | if options[:ruby] 19 | if ruby_version 20 | output << ruby_version 21 | else 22 | output << "No ruby version specified" 23 | end 24 | else 25 | output << "Your platform is: #{RUBY_PLATFORM}" 26 | output << "Your app has gems that work on these platforms:\n#{platforms.join("\n")}" 27 | 28 | if ruby_version 29 | output << "Your Gemfile specifies a Ruby version requirement:\n* #{ruby_version}" 30 | 31 | begin 32 | Bundler.definition.validate_ruby! 33 | output << "Your current platform satisfies the Ruby version requirement." 34 | rescue RubyVersionMismatch => e 35 | output << e.message 36 | end 37 | else 38 | output << "Your Gemfile does not specify a Ruby version requirement." 39 | end 40 | end 41 | 42 | Bundler.ui.info output.join("\n\n") 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/bundler/cli/package.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class CLI::Package 4 | attr_reader :options 5 | 6 | def initialize(options) 7 | @options = options 8 | end 9 | 10 | def run 11 | Bundler.ui.level = "error" if options[:quiet] 12 | Bundler.settings[:path] = File.expand_path(options[:path]) if options[:path] 13 | Bundler.settings[:cache_all_platforms] = options["all-platforms"] if options.key?("all-platforms") 14 | Bundler.settings[:cache_path] = options["cache-path"] if options.key?("cache-path") 15 | 16 | setup_cache_all 17 | install 18 | 19 | # TODO: move cache contents here now that all bundles are locked 20 | custom_path = Pathname.new(options[:path]) if options[:path] 21 | Bundler.load.cache(custom_path) 22 | end 23 | 24 | private 25 | 26 | def install 27 | require "bundler/cli/install" 28 | options = self.options.dup 29 | if Bundler.settings[:cache_all_platforms] 30 | options["local"] = false 31 | options["update"] = true 32 | end 33 | Bundler::CLI::Install.new(options).run 34 | end 35 | 36 | def setup_cache_all 37 | Bundler.settings[:cache_all] = options[:all] if options.key?("all") 38 | 39 | if Bundler.definition.has_local_dependencies? && !Bundler.settings[:cache_all] 40 | Bundler.ui.warn "Your Gemfile contains path and git dependencies. If you want " \ 41 | "to package them as well, please pass the --all flag. This will be the default " \ 42 | "on Bundler 2.0." 43 | end 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /spec/install/binstubs_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle install" do 5 | describe "when system_bindir is set" do 6 | # On OS X, Gem.bindir defaults to /usr/bin, so system_bindir is useful if 7 | # you want to avoid sudo installs for system gems with OS X's default ruby 8 | it "overrides Gem.bindir" do 9 | expect(Pathname.new("/usr/bin")).not_to be_writable unless Process.euid == 0 10 | gemfile <<-G 11 | require 'rubygems' 12 | def Gem.bindir; "/usr/bin"; end 13 | source "file://#{gem_repo1}" 14 | gem "rack" 15 | G 16 | 17 | config "BUNDLE_SYSTEM_BINDIR" => system_gem_path("altbin").to_s 18 | bundle :install 19 | should_be_installed "rack 1.0.0" 20 | expect(system_gem_path("altbin/rackup")).to exist 21 | end 22 | end 23 | 24 | describe "when multiple gems contain the same exe" do 25 | before do 26 | update_repo gem_repo1 do 27 | build_gem "fake", "14" do |s| 28 | s.executables = "rackup" 29 | end 30 | end 31 | 32 | install_gemfile <<-G, :binstubs => true 33 | source "file://#{gem_repo1}" 34 | gem "fake" 35 | gem "rack" 36 | G 37 | end 38 | 39 | it "prints a deprecation notice" do 40 | bundle "config major_deprecations true" 41 | gembin("rackup") 42 | expect(out).to include("Bundler is using a binstub that was created for a different gem.") 43 | end 44 | 45 | it "loads the correct spec's executable" do 46 | gembin("rackup") 47 | expect(out).to eq("1.0.0") 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/bundler/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU 3 | MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs 4 | IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 5 | MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux 6 | FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h 7 | bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v 8 | dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt 9 | H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 10 | uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX 11 | mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX 12 | a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN 13 | E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 14 | WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD 15 | VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 16 | Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU 17 | cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx 18 | IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN 19 | AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH 20 | YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 21 | 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC 22 | Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX 23 | c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a 24 | mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= 25 | -----END CERTIFICATE----- 26 | -------------------------------------------------------------------------------- /lib/bundler/gem_remote_fetcher.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "rubygems/remote_fetcher" 3 | 4 | module Bundler 5 | # Adds support for setting custom HTTP headers when fetching gems from the 6 | # server. 7 | # 8 | # TODO: Get rid of this when and if gemstash only supports RubyGems versions 9 | # that contain https://github.com/rubygems/rubygems/commit/3db265cc20b2f813. 10 | class GemRemoteFetcher < Gem::RemoteFetcher 11 | attr_accessor :headers 12 | 13 | # Extracted from RubyGems 2.4. 14 | def fetch_http(uri, last_modified = nil, head = false, depth = 0) 15 | fetch_type = head ? Net::HTTP::Head : Net::HTTP::Get 16 | # beginning of change 17 | response = request uri, fetch_type, last_modified do |req| 18 | headers.each {|k, v| req.add_field(k, v) } if headers 19 | end 20 | # end of change 21 | 22 | case response 23 | when Net::HTTPOK, Net::HTTPNotModified then 24 | response.uri = uri if response.respond_to? :uri 25 | head ? response : response.body 26 | when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther, 27 | Net::HTTPTemporaryRedirect then 28 | raise FetchError.new("too many redirects", uri) if depth > 10 29 | 30 | location = URI.parse response["Location"] 31 | 32 | if https?(uri) && !https?(location) 33 | raise FetchError.new("redirecting to non-https resource: #{location}", uri) 34 | end 35 | 36 | fetch_http(location, last_modified, head, depth + 1) 37 | else 38 | raise FetchError.new("bad response #{response.message} #{response.code}", uri) 39 | end 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /exe/bundle_ruby: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | Signal.trap("INT") { exit 1 } 5 | 6 | require "bundler/errors" 7 | require "bundler/ruby_version" 8 | require "bundler/ruby_dsl" 9 | require "bundler/shared_helpers" 10 | 11 | module Bundler 12 | class Dsl 13 | include RubyDsl 14 | 15 | attr_accessor :ruby_version 16 | 17 | def initialize 18 | @ruby_version = nil 19 | end 20 | 21 | def eval_gemfile(gemfile, contents = nil) 22 | contents ||= File.open(gemfile, "rb", &:read) 23 | instance_eval(contents, gemfile.to_s, 1) 24 | rescue SyntaxError => e 25 | bt = e.message.split("\n")[1..-1] 26 | raise GemfileError, ["Gemfile syntax error:", *bt].join("\n") 27 | rescue ScriptError, RegexpError, NameError, ArgumentError => e 28 | e.backtrace[0] = "#{e.backtrace[0]}: #{e.message} (#{e.class})" 29 | STDERR.puts e.backtrace.join("\n ") 30 | raise GemfileError, "There was an error in your Gemfile," \ 31 | " and Bundler cannot continue." 32 | end 33 | 34 | def source(source, options = {}) 35 | end 36 | 37 | def gem(name, *args) 38 | end 39 | 40 | def group(*args) 41 | end 42 | end 43 | end 44 | 45 | Bundler::SharedHelpers.major_deprecation("the bundle_ruby executable has been removed in favor of `bundle platform --ruby`") 46 | 47 | dsl = Bundler::Dsl.new 48 | begin 49 | dsl.eval_gemfile(Bundler::SharedHelpers.default_gemfile) 50 | ruby_version = dsl.ruby_version 51 | if ruby_version 52 | puts ruby_version 53 | else 54 | puts "No ruby version specified" 55 | end 56 | rescue Bundler::GemfileError => e 57 | puts e.message 58 | exit(-1) 59 | end 60 | -------------------------------------------------------------------------------- /lib/bundler/retry.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | # General purpose class for retrying code that may fail 4 | class Retry 5 | attr_accessor :name, :total_runs, :current_run 6 | 7 | class << self 8 | def default_attempts 9 | default_retries + 1 10 | end 11 | alias_method :attempts, :default_attempts 12 | 13 | def default_retries 14 | Bundler.settings[:retry] 15 | end 16 | end 17 | 18 | def initialize(name, exceptions = nil, retries = self.class.default_retries) 19 | @name = name 20 | @retries = retries 21 | @exceptions = Array(exceptions) || [] 22 | @total_runs = @retries + 1 # will run once, then upto attempts.times 23 | end 24 | 25 | def attempt(&block) 26 | @current_run = 0 27 | @failed = false 28 | @error = nil 29 | run(&block) while keep_trying? 30 | @result 31 | end 32 | alias_method :attempts, :attempt 33 | 34 | private 35 | 36 | def run(&block) 37 | @failed = false 38 | @current_run += 1 39 | @result = block.call 40 | rescue => e 41 | fail_attempt(e) 42 | end 43 | 44 | def fail_attempt(e) 45 | @failed = true 46 | raise e if last_attempt? || @exceptions.any? {|k| e.is_a?(k) } 47 | return true unless name 48 | Bundler.ui.warn "Retrying#{" #{name}" if name} due to error (#{current_run.next}/#{total_runs}): #{e.class} #{e.message}" 49 | end 50 | 51 | def keep_trying? 52 | return true if current_run.zero? 53 | return false if last_attempt? 54 | return true if @failed 55 | end 56 | 57 | def last_attempt? 58 | current_run >= total_runs 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/action' 3 | module Bundler::Molinillo 4 | class DependencyGraph 5 | # @!visibility private 6 | # @see DependencyGraph#detach_vertex_named 7 | class DetachVertexNamed < Action 8 | # @!group Action 9 | 10 | # (see Action#name) 11 | def self.name 12 | :add_vertex 13 | end 14 | 15 | # (see Action#up) 16 | def up(graph) 17 | return unless @vertex = graph.vertices.delete(name) 18 | @vertex.outgoing_edges.each do |e| 19 | v = e.destination 20 | v.incoming_edges.delete(e) 21 | graph.detach_vertex_named(v.name) unless v.root? || v.predecessors.any? 22 | end 23 | @vertex.incoming_edges.each do |e| 24 | v = e.origin 25 | v.outgoing_edges.delete(e) 26 | end 27 | end 28 | 29 | # (see Action#down) 30 | def down(graph) 31 | return unless @vertex 32 | graph.vertices[@vertex.name] = @vertex 33 | @vertex.outgoing_edges.each do |e| 34 | e.destination.incoming_edges << e 35 | end 36 | @vertex.incoming_edges.each do |e| 37 | e.origin.outgoing_edges << e 38 | end 39 | end 40 | 41 | # @!group DetachVertexNamed 42 | 43 | # @return [String] the name of the vertex to detach 44 | attr_reader :name 45 | 46 | # Initialize an action to detach a vertex from a dependency graph 47 | # @param [String] name the name of the vertex to detach 48 | def initialize(name) 49 | @name = name 50 | end 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /man/bundle-lock.ronn: -------------------------------------------------------------------------------- 1 | bundle-lock(1) -- Creates / Updates a lockfile without installing 2 | ================================================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `bundle lock` [--update] 7 | [--local] 8 | [--print] 9 | [--lockfile=PATH] 10 | 11 | ## DESCRIPTION 12 | 13 | Lock the gems specified in Gemfile. 14 | 15 | ## OPTIONS 16 | 17 | * `--update=<*gems>`: 18 | Ignores the existing lockfile. Resolve then updates lockfile. Taking a list 19 | of gems or updating all gems if no list is given. 20 | 21 | * `--local`: 22 | Do not attempt to connect to `rubygems.org`. Instead, Bundler will use the 23 | gems already present in Rubygems' cache or in `vendor/cache`. Note that if a 24 | appropriate platform-specific gem exists on `rubygems.org` it will not be 25 | found. 26 | 27 | * `--print`: 28 | Prints the lockfile to STDOUT instead of writing to the file system. 29 | 30 | * `--lockfile=`: 31 | The path where the lockfile should be written to. 32 | 33 | ## UPDATING ALL GEMS 34 | 35 | If you run `bundle lock` with `--update` option without list of gems, bundler will 36 | ignore any previously installed gems and resolve all dependencies again based 37 | on the latest versions of all gems available in the sources. 38 | 39 | ## UPDATING A LIST OF GEMS 40 | 41 | Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of 42 | the gems that you specified locked to the versions in the `Gemfile.lock`. 43 | 44 | For instance, you only want to update `nokogiri`, run `bundle lock --update nokogiri`. 45 | 46 | Bundler will update `nokogiri` and any of its dependencies, but leave the rest of the 47 | gems that you specified locked to the versions in the `Gemfile.lock`. 48 | -------------------------------------------------------------------------------- /lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph' 3 | 4 | module Bundler::Molinillo 5 | # This class encapsulates a dependency resolver. 6 | # The resolver is responsible for determining which set of dependencies to 7 | # activate, with feedback from the {#specification_provider} 8 | # 9 | # 10 | class Resolver 11 | require 'bundler/vendor/molinillo/lib/molinillo/resolution' 12 | 13 | # @return [SpecificationProvider] the specification provider used 14 | # in the resolution process 15 | attr_reader :specification_provider 16 | 17 | # @return [UI] the UI module used to communicate back to the user 18 | # during the resolution process 19 | attr_reader :resolver_ui 20 | 21 | # Initializes a new resolver. 22 | # @param [SpecificationProvider] specification_provider 23 | # see {#specification_provider} 24 | # @param [UI] resolver_ui 25 | # see {#resolver_ui} 26 | def initialize(specification_provider, resolver_ui) 27 | @specification_provider = specification_provider 28 | @resolver_ui = resolver_ui 29 | end 30 | 31 | # Resolves the requested dependencies into a {DependencyGraph}, 32 | # locking to the base dependency graph (if specified) 33 | # @param [Array] requested an array of 'requested' dependencies that the 34 | # {#specification_provider} can understand 35 | # @param [DependencyGraph,nil] base the base dependency graph to which 36 | # dependencies should be 'locked' 37 | def resolve(requested, base = DependencyGraph.new) 38 | Resolution.new(specification_provider, 39 | resolver_ui, 40 | requested, 41 | base). 42 | resolve 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/bundler/source/rubygems/remote.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class Source 4 | class Rubygems 5 | class Remote 6 | attr_reader :uri, :anonymized_uri, :original_uri 7 | 8 | def initialize(uri) 9 | orig_uri = uri 10 | uri = Bundler.settings.mirror_for(uri) 11 | @original_uri = orig_uri if orig_uri != uri 12 | fallback_auth = Bundler.settings.credentials_for(uri) 13 | 14 | @uri = apply_auth(uri, fallback_auth).freeze 15 | @anonymized_uri = remove_auth(@uri).freeze 16 | end 17 | 18 | # @return [String] A slug suitable for use as a cache key for this 19 | # remote. 20 | # 21 | def cache_slug 22 | @cache_slug ||= begin 23 | cache_uri = original_uri || uri 24 | 25 | uri_parts = [cache_uri.host, cache_uri.user, cache_uri.port, cache_uri.path] 26 | uri_digest = Digest::MD5.hexdigest(uri_parts.compact.join(".")) 27 | 28 | uri_parts[-1] = uri_digest 29 | uri_parts.compact.join(".") 30 | end 31 | end 32 | 33 | private 34 | 35 | def apply_auth(uri, auth) 36 | if auth && uri.userinfo.nil? 37 | uri = uri.dup 38 | uri.userinfo = auth 39 | end 40 | 41 | uri 42 | rescue URI::InvalidComponentError 43 | error_message = "Please CGI escape your usernames and passwords before " \ 44 | "setting them for authentication." 45 | raise HTTPError.new(error_message) 46 | end 47 | 48 | def remove_auth(uri) 49 | if uri.userinfo 50 | uri = uri.dup 51 | uri.user = uri.password = nil 52 | end 53 | 54 | uri 55 | end 56 | end 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler::Molinillo 3 | # @!visibility private 4 | module Delegates 5 | # Delegates all {Bundler::Molinillo::ResolutionState} methods to a `#state` property. 6 | module ResolutionState 7 | # (see Bundler::Molinillo::ResolutionState#name) 8 | def name 9 | current_state = state || Bundler::Molinillo::ResolutionState.empty 10 | current_state.name 11 | end 12 | 13 | # (see Bundler::Molinillo::ResolutionState#requirements) 14 | def requirements 15 | current_state = state || Bundler::Molinillo::ResolutionState.empty 16 | current_state.requirements 17 | end 18 | 19 | # (see Bundler::Molinillo::ResolutionState#activated) 20 | def activated 21 | current_state = state || Bundler::Molinillo::ResolutionState.empty 22 | current_state.activated 23 | end 24 | 25 | # (see Bundler::Molinillo::ResolutionState#requirement) 26 | def requirement 27 | current_state = state || Bundler::Molinillo::ResolutionState.empty 28 | current_state.requirement 29 | end 30 | 31 | # (see Bundler::Molinillo::ResolutionState#possibilities) 32 | def possibilities 33 | current_state = state || Bundler::Molinillo::ResolutionState.empty 34 | current_state.possibilities 35 | end 36 | 37 | # (see Bundler::Molinillo::ResolutionState#depth) 38 | def depth 39 | current_state = state || Bundler::Molinillo::ResolutionState.empty 40 | current_state.depth 41 | end 42 | 43 | # (see Bundler::Molinillo::ResolutionState#conflicts) 44 | def conflicts 45 | current_state = state || Bundler::Molinillo::ResolutionState.empty 46 | current_state.conflicts 47 | end 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/bundler/ssl_certs/certificate_manager.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "fileutils" 3 | require "net/https" 4 | require "openssl" 5 | 6 | module Bundler 7 | module SSLCerts 8 | class CertificateManager 9 | attr_reader :bundler_cert_path, :bundler_certs, :rubygems_certs 10 | 11 | def self.update_from!(rubygems_path) 12 | new(rubygems_path).update! 13 | end 14 | 15 | def initialize(rubygems_path = nil) 16 | if rubygems_path 17 | rubygems_cert_path = File.join(rubygems_path, "lib/rubygems/ssl_certs") 18 | @rubygems_certs = certificates_in(rubygems_cert_path) 19 | end 20 | 21 | @bundler_cert_path = File.expand_path("..", __FILE__) 22 | @bundler_certs = certificates_in(bundler_cert_path) 23 | end 24 | 25 | def up_to_date? 26 | rubygems_certs.all? do |rc| 27 | bundler_certs.find do |bc| 28 | File.basename(bc) == File.basename(rc) && FileUtils.compare_file(bc, rc) 29 | end 30 | end 31 | end 32 | 33 | def update! 34 | return if up_to_date? 35 | 36 | FileUtils.rm bundler_certs 37 | FileUtils.cp rubygems_certs, bundler_cert_path 38 | end 39 | 40 | def connect_to(host) 41 | http = Net::HTTP.new(host, 443) 42 | http.use_ssl = true 43 | http.verify_mode = OpenSSL::SSL::VERIFY_PEER 44 | http.cert_store = store 45 | http.head("/") 46 | end 47 | 48 | private 49 | 50 | def certificates_in(path) 51 | Dir[File.join(path, "**/*.pem")].sort 52 | end 53 | 54 | def store 55 | @store ||= begin 56 | store = OpenSSL::X509::Store.new 57 | bundler_certs.each do |cert| 58 | store.add_file cert 59 | end 60 | store 61 | end 62 | end 63 | end 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /lib/bundler/vendor/molinillo/lib/molinillo/state.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler::Molinillo 3 | # A state that a {Resolution} can be in 4 | # @attr [String] name the name of the current requirement 5 | # @attr [Array] requirements currently unsatisfied requirements 6 | # @attr [DependencyGraph] activated the graph of activated dependencies 7 | # @attr [Object] requirement the current requirement 8 | # @attr [Object] possibilities the possibilities to satisfy the current requirement 9 | # @attr [Integer] depth the depth of the resolution 10 | # @attr [Set] conflicts unresolved conflicts 11 | ResolutionState = Struct.new( 12 | :name, 13 | :requirements, 14 | :activated, 15 | :requirement, 16 | :possibilities, 17 | :depth, 18 | :conflicts 19 | ) 20 | 21 | class ResolutionState 22 | # Returns an empty resolution state 23 | # @return [ResolutionState] an empty state 24 | def self.empty 25 | new(nil, [], DependencyGraph.new, nil, nil, 0, Set.new) 26 | end 27 | end 28 | 29 | # A state that encapsulates a set of {#requirements} with an {Array} of 30 | # possibilities 31 | class DependencyState < ResolutionState 32 | # Removes a possibility from `self` 33 | # @return [PossibilityState] a state with a single possibility, 34 | # the possibility that was removed from `self` 35 | def pop_possibility_state 36 | PossibilityState.new( 37 | name, 38 | requirements.dup, 39 | activated, 40 | requirement, 41 | [possibilities.pop], 42 | depth + 1, 43 | conflicts.dup 44 | ).tap do |state| 45 | state.activated.tag(state) 46 | end 47 | end 48 | end 49 | 50 | # A state that encapsulates a single possibility to fulfill the given 51 | # {#requirement} 52 | class PossibilityState < ResolutionState 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /spec/commands/viz_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle viz", :ruby => "1.9.3", :if => Bundler.which("dot") do 5 | let(:graphviz_lib) do 6 | graphviz_glob = base_system_gems.join("gems/ruby-graphviz*/lib") 7 | Dir[graphviz_glob].first 8 | end 9 | 10 | it "graphs gems from the Gemfile" do 11 | install_gemfile <<-G 12 | source "file://#{gem_repo1}" 13 | gem "rack" 14 | gem "rack-obama" 15 | G 16 | 17 | bundle "viz", :env => { "RUBYOPT" => "-I #{graphviz_lib}" } 18 | expect(out).to include("gem_graph.png") 19 | end 20 | 21 | it "graphs gems that are prereleases" do 22 | update_repo(gem_repo1) do 23 | build_gem "rack", "1.3.pre" 24 | end 25 | 26 | install_gemfile <<-G 27 | source "file://#{gem_repo1}" 28 | gem "rack", "= 1.3.pre" 29 | gem "rack-obama" 30 | G 31 | 32 | bundle "viz", :env => { "RUBYOPT" => "-I #{graphviz_lib}" } 33 | expect(out).to include("gem_graph.png") 34 | end 35 | 36 | context "--without option" do 37 | it "one group" do 38 | install_gemfile <<-G 39 | source "file://#{gem_repo1}" 40 | gem "activesupport" 41 | 42 | group :rails do 43 | gem "rails" 44 | end 45 | G 46 | 47 | bundle "viz --without=rails", :env => { "RUBYOPT" => "-I #{graphviz_lib}" } 48 | expect(out).to include("gem_graph.png") 49 | end 50 | 51 | it "two groups" do 52 | install_gemfile <<-G 53 | source "file://#{gem_repo1}" 54 | gem "activesupport" 55 | 56 | group :rack do 57 | gem "rack" 58 | end 59 | 60 | group :rails do 61 | gem "rails" 62 | end 63 | G 64 | 65 | bundle "viz --without=rails:rack", :env => { "RUBYOPT" => "-I #{graphviz_lib}" } 66 | expect(out).to include("gem_graph.png") 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /spec/install/gemfile_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "bundle install" do 5 | context "with duplicated gems" do 6 | it "will display a warning" do 7 | install_gemfile <<-G 8 | gem 'rails', '~> 4.0.0' 9 | gem 'rails', '~> 4.0.0' 10 | G 11 | expect(out).to include("more than once") 12 | end 13 | end 14 | 15 | context "with --gemfile" do 16 | it "finds the gemfile" do 17 | gemfile bundled_app("NotGemfile"), <<-G 18 | source "file://#{gem_repo1}" 19 | gem 'rack' 20 | G 21 | 22 | bundle :install, :gemfile => bundled_app("NotGemfile") 23 | 24 | ENV["BUNDLE_GEMFILE"] = "NotGemfile" 25 | should_be_installed "rack 1.0.0" 26 | end 27 | end 28 | 29 | context "with gemfile set via config" do 30 | before do 31 | gemfile bundled_app("NotGemfile"), <<-G 32 | source "file://#{gem_repo1}" 33 | gem 'rack' 34 | G 35 | 36 | bundle "config --local gemfile #{bundled_app("NotGemfile")}" 37 | end 38 | it "uses the gemfile to install" do 39 | bundle "install" 40 | bundle "show" 41 | 42 | expect(out).to include("rack (1.0.0)") 43 | end 44 | it "uses the gemfile while in a subdirectory" do 45 | bundled_app("subdir").mkpath 46 | Dir.chdir(bundled_app("subdir")) do 47 | bundle "install" 48 | bundle "show" 49 | 50 | expect(out).to include("rack (1.0.0)") 51 | end 52 | end 53 | end 54 | 55 | context "with deprecated features" do 56 | before :each do 57 | in_app_root 58 | end 59 | 60 | it "reports that lib is an invalid option" do 61 | gemfile <<-G 62 | gem "rack", :lib => "rack" 63 | G 64 | 65 | bundle :install 66 | expect(out).to match(/You passed :lib as an option for gem 'rack', but it is invalid/) 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /lib/bundler/cli/inject.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class CLI::Inject 4 | attr_reader :options, :name, :version, :group, :source, :gems 5 | def initialize(options, name, version, gems) 6 | @options = options 7 | @name = name 8 | @version = version || last_version_number 9 | @group = options[:group] 10 | @source = options[:source] 11 | @gems = gems 12 | end 13 | 14 | def run 15 | # The required arguments allow Thor to give useful feedback when the arguments 16 | # are incorrect. This adds those first two arguments onto the list as a whole. 17 | gems.unshift(source).unshift(group).unshift(version).unshift(name) 18 | 19 | # Build an array of Dependency objects out of the arguments 20 | deps = [] 21 | gems.each_slice(4) do |gem_name, gem_version, gem_group, gem_source| 22 | ops = Gem::Requirement::OPS.map {|key, _val| key } 23 | has_op = ops.any? {|op| gem_version.start_with? op } 24 | gem_version = "~> #{gem_version}" unless has_op 25 | deps << Bundler::Dependency.new(gem_name, gem_version, "group" => gem_group, "source" => gem_source) 26 | end 27 | 28 | added = Injector.inject(deps, options) 29 | 30 | if added.any? 31 | Bundler.ui.confirm "Added to Gemfile:" 32 | Bundler.ui.confirm added.map {|g| " #{g}" }.join("\n") 33 | else 34 | Bundler.ui.confirm "All injected gems were already present in the Gemfile" 35 | end 36 | end 37 | 38 | private 39 | 40 | def last_version_number 41 | definition = Bundler.definition(true) 42 | definition.resolve_remotely! 43 | specs = definition.index[name].sort_by(&:version) 44 | unless options[:pre] 45 | specs.delete_if {|b| b.respond_to?(:version) && b.version.prerelease? } 46 | end 47 | spec = specs.last 48 | spec.version.to_s 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/bundler/plugin/dsl.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bundler 4 | module Plugin 5 | # Dsl to parse the Gemfile looking for plugins to install 6 | class DSL < Bundler::Dsl 7 | class PluginGemfileError < PluginError; end 8 | alias_method :_gem, :gem # To use for plugin installation as gem 9 | 10 | # So that we don't have to override all there methods to dummy ones 11 | # explicitly. 12 | # They will be handled by method_missing 13 | [:gemspec, :gem, :path, :install_if, :platforms, :env].each {|m| undef_method m } 14 | 15 | # This lists the plugins that was added automatically and not specified by 16 | # the user. 17 | # 18 | # When we encounter :type attribute with a source block, we add a plugin 19 | # by name bundler-source- to list of plugins to be installed. 20 | # 21 | # These plugins are optional and are not installed when there is conflict 22 | # with any other plugin. 23 | attr_reader :inferred_plugins 24 | 25 | def initialize 26 | super 27 | @sources = Plugin::SourceList.new 28 | @inferred_plugins = [] # The source plugins inferred from :type 29 | end 30 | 31 | def plugin(name, *args) 32 | _gem(name, *args) 33 | end 34 | 35 | def method_missing(name, *args) 36 | raise PluginGemfileError, "Undefined local variable or method `#{name}' for Gemfile" unless Bundler::Dsl.method_defined? name 37 | end 38 | 39 | def source(source, *args, &blk) 40 | options = args.last.is_a?(Hash) ? args.pop.dup : {} 41 | options = normalize_hash(options) 42 | return super unless options.key?("type") 43 | 44 | plugin_name = "bundler-source-#{options["type"]}" 45 | 46 | return if @dependencies.any? {|d| d.name == plugin_name } 47 | 48 | plugin(plugin_name) 49 | @inferred_plugins << plugin_name 50 | end 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/action' 3 | module Bundler::Molinillo 4 | class DependencyGraph 5 | # @!visibility private 6 | # (see DependencyGraph#add_vertex) 7 | class AddVertex < Action # :nodoc: 8 | # @!group Action 9 | 10 | # (see Action.name) 11 | def self.name 12 | :add_vertex 13 | end 14 | 15 | # (see Action#up) 16 | def up(graph) 17 | if existing = graph.vertices[name] 18 | @existing_payload = existing.payload 19 | @existing_root = existing.root 20 | end 21 | vertex = existing || Vertex.new(name, payload) 22 | graph.vertices[vertex.name] = vertex 23 | vertex.payload ||= payload 24 | vertex.root ||= root 25 | vertex 26 | end 27 | 28 | # (see Action#down) 29 | def down(graph) 30 | if defined?(@existing_payload) 31 | vertex = graph.vertices[name] 32 | vertex.payload = @existing_payload 33 | vertex.root = @existing_root 34 | else 35 | graph.vertices.delete(name) 36 | end 37 | end 38 | 39 | # @!group AddVertex 40 | 41 | # @return [String] the name of the vertex 42 | attr_reader :name 43 | 44 | # @return [Object] the payload for the vertex 45 | attr_reader :payload 46 | 47 | # @return [Boolean] whether the vertex is root or not 48 | attr_reader :root 49 | 50 | # Initialize an action to add a vertex to a dependency graph 51 | # @param [String] name the name of the vertex 52 | # @param [Object] payload the payload for the vertex 53 | # @param [Boolean] root whether the vertex is root or not 54 | def initialize(name, payload, root) 55 | @name = name 56 | @payload = payload 57 | @root = root 58 | end 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/bundler/installer/standalone.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class Standalone 4 | def initialize(groups, definition) 5 | @specs = groups.empty? ? definition.requested_specs : definition.specs_for(groups.map(&:to_sym)) 6 | end 7 | 8 | def generate 9 | SharedHelpers.filesystem_access(bundler_path) do |p| 10 | FileUtils.mkdir_p(p) 11 | end 12 | File.open File.join(bundler_path, "setup.rb"), "w" do |file| 13 | file.puts "require 'rbconfig'" 14 | file.puts "# ruby 1.8.7 doesn't define RUBY_ENGINE" 15 | file.puts "ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'" 16 | file.puts "ruby_version = RbConfig::CONFIG[\"ruby_version\"]" 17 | file.puts "path = File.expand_path('..', __FILE__)" 18 | paths.each do |path| 19 | file.puts %($:.unshift "\#{path}/#{path}") 20 | end 21 | end 22 | end 23 | 24 | private 25 | 26 | def paths 27 | @specs.map do |spec| 28 | next if spec.name == "bundler" 29 | Array(spec.require_paths).map do |path| 30 | gem_path(path, spec).sub(version_dir, '#{ruby_engine}/#{ruby_version}') 31 | # This is a static string intentionally. It's interpolated at a later time. 32 | end 33 | end.flatten 34 | end 35 | 36 | def version_dir 37 | "#{Bundler::RubyVersion.system.engine}/#{RbConfig::CONFIG["ruby_version"]}" 38 | end 39 | 40 | def bundler_path 41 | Bundler.root.join(Bundler.settings[:path], "bundler") 42 | end 43 | 44 | def gem_path(path, spec) 45 | full_path = Pathname.new(path).absolute? ? path : File.join(spec.full_gem_path, path) 46 | Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)).to_s 47 | rescue TypeError 48 | error_message = "#{spec.name} #{spec.version} has an invalid gemspec" 49 | raise Gem::InvalidSpecificationException.new(error_message) 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/bundler/fetcher/index.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "bundler/fetcher/base" 3 | require "rubygems/remote_fetcher" 4 | 5 | module Bundler 6 | class Fetcher 7 | class Index < Base 8 | def specs(_gem_names) 9 | Bundler.rubygems.fetch_all_remote_specs(remote) 10 | rescue Gem::RemoteFetcher::FetchError, OpenSSL::SSL::SSLError, Net::HTTPFatalError => e 11 | case e.message 12 | when /certificate verify failed/ 13 | raise CertificateFailureError.new(display_uri) 14 | when /401/ 15 | raise AuthenticationRequiredError, remote_uri 16 | when /403/ 17 | raise BadAuthenticationError, remote_uri if remote_uri.userinfo 18 | raise AuthenticationRequiredError, remote_uri 19 | else 20 | Bundler.ui.trace e 21 | raise HTTPError, "Could not fetch specs from #{display_uri}" 22 | end 23 | end 24 | 25 | def fetch_spec(spec) 26 | spec -= [nil, "ruby", ""] 27 | spec_file_name = "#{spec.join "-"}.gemspec" 28 | 29 | uri = URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz") 30 | if uri.scheme == "file" 31 | Bundler.load_marshal Gem.inflate(Gem.read_binary(uri.path)) 32 | elsif cached_spec_path = gemspec_cached_path(spec_file_name) 33 | Bundler.load_gemspec(cached_spec_path) 34 | else 35 | Bundler.load_marshal Gem.inflate(downloader.fetch(uri).body) 36 | end 37 | rescue MarshalError 38 | raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \ 39 | "Your network or your gem server is probably having issues right now." 40 | end 41 | 42 | private 43 | 44 | # cached gem specification path, if one exists 45 | def gemspec_cached_path(spec_file_name) 46 | paths = Bundler.rubygems.spec_cache_dirs.map {|dir| File.join(dir, spec_file_name) } 47 | paths.find {|path| File.file? path } 48 | end 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler::Molinillo 3 | # Conveys information about the resolution process to a user. 4 | module UI 5 | # The {IO} object that should be used to print output. `STDOUT`, by default. 6 | # 7 | # @return [IO] 8 | def output 9 | STDOUT 10 | end 11 | 12 | # Called roughly every {#progress_rate}, this method should convey progress 13 | # to the user. 14 | # 15 | # @return [void] 16 | def indicate_progress 17 | output.print '.' unless debug? 18 | end 19 | 20 | # How often progress should be conveyed to the user via 21 | # {#indicate_progress}, in seconds. A third of a second, by default. 22 | # 23 | # @return [Float] 24 | def progress_rate 25 | 0.33 26 | end 27 | 28 | # Called before resolution begins. 29 | # 30 | # @return [void] 31 | def before_resolution 32 | output.print 'Resolving dependencies...' 33 | end 34 | 35 | # Called after resolution ends (either successfully or with an error). 36 | # By default, prints a newline. 37 | # 38 | # @return [void] 39 | def after_resolution 40 | output.puts 41 | end 42 | 43 | # Conveys debug information to the user. 44 | # 45 | # @param [Integer] depth the current depth of the resolution process. 46 | # @return [void] 47 | def debug(depth = 0) 48 | if debug? 49 | debug_info = yield 50 | debug_info = debug_info.inspect unless debug_info.is_a?(String) 51 | output.puts debug_info.split("\n").map { |s| ' ' * depth + s } 52 | end 53 | end 54 | 55 | # Whether or not debug messages should be printed. 56 | # By default, whether or not the `MOLINILLO_DEBUG` environment variable is 57 | # set. 58 | # 59 | # @return [Boolean] 60 | def debug? 61 | return @debug_mode if defined?(@debug_mode) 62 | @debug_mode = ENV['MOLINILLO_DEBUG'] 63 | end 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /spec/bundler/cli_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | require "bundler/cli" 4 | 5 | describe "bundle executable" do 6 | it "returns non-zero exit status when passed unrecognized options" do 7 | bundle "--invalid_argument" 8 | expect(exitstatus).to_not be_zero if exitstatus 9 | end 10 | 11 | it "returns non-zero exit status when passed unrecognized task" do 12 | bundle "unrecognized-task" 13 | expect(exitstatus).to_not be_zero if exitstatus 14 | end 15 | 16 | it "looks for a binary and executes it if it's named bundler-" do 17 | File.open(tmp("bundler-testtasks"), "w", 0755) do |f| 18 | f.puts "#!/usr/bin/env ruby\nputs 'Hello, world'\n" 19 | end 20 | 21 | with_path_added(tmp) do 22 | bundle "testtasks" 23 | end 24 | 25 | expect(exitstatus).to be_zero if exitstatus 26 | expect(out).to eq("Hello, world") 27 | end 28 | 29 | context "when ENV['BUNDLE_GEMFILE'] is set to an empty string" do 30 | it "ignores it" do 31 | gemfile bundled_app("Gemfile"), <<-G 32 | source "file://#{gem_repo1}" 33 | gem 'rack' 34 | G 35 | 36 | bundle :install, :env => { "BUNDLE_GEMFILE" => "" } 37 | 38 | should_be_installed "rack 1.0.0" 39 | end 40 | end 41 | 42 | context "when ENV['RUBYGEMS_GEMDEPS'] is set" do 43 | it "displays a warning" do 44 | gemfile bundled_app("Gemfile"), <<-G 45 | source "file://#{gem_repo1}" 46 | gem 'rack' 47 | G 48 | 49 | bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "foo" } 50 | expect(out).to include("RUBYGEMS_GEMDEPS") 51 | expect(out).to include("conflict with Bundler") 52 | 53 | bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "" } 54 | expect(out).not_to include("RUBYGEMS_GEMDEPS") 55 | end 56 | end 57 | end 58 | 59 | describe "bundler executable" do 60 | it "shows the bundler version just as the `bundle` executable does" do 61 | bundler "--version" 62 | expect(out).to eq("Bundler version #{Bundler::VERSION}") 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/newgem.gemspec.tt: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require '<%=config[:namespaced_path]%>/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = <%=config[:name].inspect%> 8 | spec.version = <%=config[:constant_name]%>::VERSION 9 | spec.authors = [<%=config[:author].inspect%>] 10 | spec.email = [<%=config[:email].inspect%>] 11 | 12 | spec.summary = %q{TODO: Write a short summary, because Rubygems requires one.} 13 | spec.description = %q{TODO: Write a longer description or delete this line.} 14 | spec.homepage = "TODO: Put your gem's website or public repo URL here." 15 | <%- if config[:mit] -%> 16 | spec.license = "MIT" 17 | <%- end -%> 18 | 19 | # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' 20 | # to allow pushing to a single host or delete this section to allow pushing to any host. 21 | if spec.respond_to?(:metadata) 22 | spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'" 23 | else 24 | raise "RubyGems 2.0 or newer is required to protect against " \ 25 | "public gem pushes." 26 | end 27 | 28 | spec.files = `git ls-files -z`.split("\x0").reject do |f| 29 | f.match(%r{^(test|spec|features)/}) 30 | end 31 | spec.bindir = "exe" 32 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 33 | spec.require_paths = ["lib"] 34 | <%- if config[:ext] -%> 35 | spec.extensions = ["ext/<%=config[:underscored_name]%>/extconf.rb"] 36 | <%- end -%> 37 | 38 | spec.add_development_dependency "bundler", "~> <%= config[:bundler_version] %>" 39 | spec.add_development_dependency "rake", "~> 10.0" 40 | <%- if config[:ext] -%> 41 | spec.add_development_dependency "rake-compiler" 42 | <%- end -%> 43 | <%- if config[:test] -%> 44 | spec.add_development_dependency "<%=config[:test]%>", "~> <%=config[:test_framework_version]%>" 45 | <%- end -%> 46 | end 47 | -------------------------------------------------------------------------------- /lib/bundler/templates/newgem/README.md.tt: -------------------------------------------------------------------------------- 1 | # <%=config[:constant_name]%> 2 | 3 | Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/<%=config[:namespaced_path]%>`. To experiment with that code, run `bin/console` for an interactive prompt. 4 | 5 | TODO: Delete this and the text above, and describe your gem 6 | 7 | ## Installation 8 | 9 | Add this line to your application's Gemfile: 10 | 11 | ```ruby 12 | gem '<%=config[:name]%>' 13 | ``` 14 | 15 | And then execute: 16 | 17 | $ bundle 18 | 19 | Or install it yourself as: 20 | 21 | $ gem install <%=config[:name]%> 22 | 23 | ## Usage 24 | 25 | TODO: Write usage instructions here 26 | 27 | ## Development 28 | 29 | After checking out the repo, run `bin/setup` to install dependencies.<% if config[:test] %> Then, run `rake <%= config[:test].sub('mini', '').sub('rspec', 'spec') %>` to run the tests.<% end %> You can also run `bin/console` for an interactive prompt that will allow you to experiment.<% if config[:bin] %> Run `bundle exec <%= config[:name] %>` to use the gem in this directory, ignoring other installed copies of this gem.<% end %> 30 | 31 | To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). 32 | 33 | ## Contributing 34 | 35 | Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/<%= config[:name] %>.<% if config[:coc] %> This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.<% end %> 36 | <% if config[:mit] %> 37 | 38 | ## License 39 | 40 | The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). 41 | <% end %> 42 | -------------------------------------------------------------------------------- /lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/action' 3 | module Bundler::Molinillo 4 | class DependencyGraph 5 | # @!visibility private 6 | # (see DependencyGraph#add_edge_no_circular) 7 | class AddEdgeNoCircular < Action 8 | # @!group Action 9 | 10 | # (see Action.name) 11 | def self.name 12 | :add_vertex 13 | end 14 | 15 | # (see Action#up) 16 | def up(graph) 17 | edge = make_edge(graph) 18 | edge.origin.outgoing_edges << edge 19 | edge.destination.incoming_edges << edge 20 | edge 21 | end 22 | 23 | # (see Action#down) 24 | def down(graph) 25 | edge = make_edge(graph) 26 | edge.origin.outgoing_edges.delete(edge) 27 | edge.destination.incoming_edges.delete(edge) 28 | end 29 | 30 | # @!group AddEdgeNoCircular 31 | 32 | # @return [String] the name of the origin of the edge 33 | attr_reader :origin 34 | 35 | # @return [String] the name of the destination of the edge 36 | attr_reader :destination 37 | 38 | # @return [Object] the requirement that the edge represents 39 | attr_reader :requirement 40 | 41 | # @param [DependencyGraph] graph the graph to find vertices from 42 | # @return [Edge] The edge this action adds 43 | def make_edge(graph) 44 | Edge.new(graph.vertex_named(origin), graph.vertex_named(destination), requirement) 45 | end 46 | 47 | # Initialize an action to add an edge to a dependency graph 48 | # @param [String] origin the name of the origin of the edge 49 | # @param [String] destination the name of the destination of the edge 50 | # @param [Object] requirement the requirement that the edge represents 51 | def initialize(origin, destination, requirement) 52 | @origin = origin 53 | @destination = destination 54 | @requirement = requirement 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /spec/bundler/endpoint_specification_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe Bundler::EndpointSpecification do 5 | let(:name) { "foo" } 6 | let(:version) { "1.0.0" } 7 | let(:platform) { Gem::Platform::RUBY } 8 | let(:dependencies) { [] } 9 | let(:metadata) { nil } 10 | 11 | subject { described_class.new(name, version, platform, dependencies, metadata) } 12 | 13 | describe "#build_dependency" do 14 | let(:name) { "foo" } 15 | let(:requirement1) { "~> 1.1" } 16 | let(:requirement2) { ">= 1.1.7" } 17 | 18 | it "should return a Gem::Dependency" do 19 | expect(subject.send(:build_dependency, name, [requirement1, requirement2])). 20 | to eq(Gem::Dependency.new(name, requirement1, requirement2)) 21 | end 22 | 23 | context "when an ArgumentError occurs" do 24 | before do 25 | allow(Gem::Dependency).to receive(:new).with(name, [requirement1, requirement2]) { 26 | raise ArgumentError.new("Some error occurred") 27 | } 28 | end 29 | 30 | it "should raise the original error" do 31 | expect { subject.send(:build_dependency, name, [requirement1, requirement2]) }.to raise_error( 32 | ArgumentError, "Some error occurred") 33 | end 34 | end 35 | 36 | context "when there is an ill formed requirement" do 37 | before do 38 | allow(Gem::Dependency).to receive(:new).with(name, [requirement1, requirement2]) { 39 | raise ArgumentError.new("Ill-formed requirement [\"# true 25 | config.add_setting :sometimes_retry_count, :default => 5 26 | 27 | config.around(:each, :sometimes => true) do |example| 28 | retries = example.metadata[:retries] || RSpec.configuration.sometimes_retry_count 29 | run_with_retries(example, retries) 30 | end 31 | 32 | config.after(:suite) do 33 | message = proc do |color, text| 34 | colored = RSpec::Core::Formatters::ConsoleCodes.wrap(text, color) 35 | notification = RSpec::Core::Notifications::MessageNotification.new(colored) 36 | RSpec.configuration.formatters.first.message(notification) 37 | end 38 | 39 | retried_examples = RSpec.world.example_groups.map do |g| 40 | g.descendants.map do |d| 41 | d.filtered_examples.select do |e| 42 | e.metadata[:sometimes] && e.metadata.fetch(:retried, 1) > 1 43 | end 44 | end 45 | end.flatten 46 | 47 | message.call(retried_examples.empty? ? :green : :yellow, "\n\nRetried examples: #{retried_examples.count}") 48 | 49 | retried_examples.each do |e| 50 | message.call(:cyan, " #{e.full_description}") 51 | path = RSpec::Core::Metadata.relative_path(e.location) 52 | message.call(:cyan, " [#{e.metadata[:retried]}/#{e.metadata[:retries]}] " + path) 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/bundler/cli/common.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | module CLI::Common 4 | def self.without_groups_message 5 | groups = Bundler.settings.without 6 | group_list = [groups[0...-1].join(", "), groups[-1..-1]]. 7 | reject {|s| s.to_s.empty? }.join(" and ") 8 | group_str = (groups.size == 1) ? "group" : "groups" 9 | "Gems in the #{group_str} #{group_list} were not installed." 10 | end 11 | 12 | def self.select_spec(name, regex_match = nil) 13 | specs = [] 14 | regexp = Regexp.new(name) if regex_match 15 | 16 | Bundler.definition.specs.each do |spec| 17 | return spec if spec.name == name 18 | specs << spec if regexp && spec.name =~ regexp 19 | end 20 | 21 | case specs.count 22 | when 0 23 | raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies) 24 | when 1 25 | specs.first 26 | else 27 | ask_for_spec_from(specs) 28 | end 29 | rescue RegexpError 30 | raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies) 31 | end 32 | 33 | def self.ask_for_spec_from(specs) 34 | if !$stdout.tty? && ENV["BUNDLE_SPEC_RUN"].nil? 35 | raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies) 36 | end 37 | 38 | specs.each_with_index do |spec, index| 39 | Bundler.ui.info "#{index.succ} : #{spec.name}", true 40 | end 41 | Bundler.ui.info "0 : - exit -", true 42 | 43 | num = Bundler.ui.ask("> ").to_i 44 | num > 0 ? specs[num - 1] : nil 45 | end 46 | 47 | def self.gem_not_found_message(missing_gem_name, alternatives) 48 | require "bundler/similarity_detector" 49 | message = "Could not find gem '#{missing_gem_name}'." 50 | alternate_names = alternatives.map {|a| a.respond_to?(:name) ? a.name : a } 51 | suggestions = SimilarityDetector.new(alternate_names).similar_word_list(missing_gem_name) 52 | message += "\nDid you mean #{suggestions}?" if suggestions 53 | message 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /lib/bundler/vendor/thor/lib/thor/actions/create_link.rb: -------------------------------------------------------------------------------- 1 | require "bundler/vendor/thor/lib/thor/actions/create_file" 2 | 3 | class Bundler::Thor 4 | module Actions 5 | # Create a new file relative to the destination root from the given source. 6 | # 7 | # ==== Parameters 8 | # destination:: the relative path to the destination root. 9 | # source:: the relative path to the source root. 10 | # config:: give :verbose => false to not log the status. 11 | # :: give :symbolic => false for hard link. 12 | # 13 | # ==== Examples 14 | # 15 | # create_link "config/apache.conf", "/etc/apache.conf" 16 | # 17 | def create_link(destination, *args, &block) 18 | config = args.last.is_a?(Hash) ? args.pop : {} 19 | source = args.first 20 | action CreateLink.new(self, destination, source, config) 21 | end 22 | alias_method :add_link, :create_link 23 | 24 | # CreateLink is a subset of CreateFile, which instead of taking a block of 25 | # data, just takes a source string from the user. 26 | # 27 | class CreateLink < CreateFile #:nodoc: 28 | attr_reader :data 29 | 30 | # Checks if the content of the file at the destination is identical to the rendered result. 31 | # 32 | # ==== Returns 33 | # Boolean:: true if it is identical, false otherwise. 34 | # 35 | def identical? 36 | exists? && File.identical?(render, destination) 37 | end 38 | 39 | def invoke! 40 | invoke_with_conflict_check do 41 | FileUtils.mkdir_p(File.dirname(destination)) 42 | # Create a symlink by default 43 | config[:symbolic] = true if config[:symbolic].nil? 44 | File.unlink(destination) if exists? 45 | if config[:symbolic] 46 | File.symlink(render, destination) 47 | else 48 | File.link(render, destination) 49 | end 50 | end 51 | given_destination 52 | end 53 | 54 | def exists? 55 | super || File.symlink?(destination) 56 | end 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/bundler/similarity_detector.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | class SimilarityDetector 4 | SimilarityScore = Struct.new(:string, :distance) 5 | 6 | # initialize with an array of words to be matched against 7 | def initialize(corpus) 8 | @corpus = corpus 9 | end 10 | 11 | # return an array of words similar to 'word' from the corpus 12 | def similar_words(word, limit = 3) 13 | words_by_similarity = @corpus.map {|w| SimilarityScore.new(w, levenshtein_distance(word, w)) } 14 | words_by_similarity.select {|s| s.distance <= limit }.sort_by(&:distance).map(&:string) 15 | end 16 | 17 | # return the result of 'similar_words', concatenated into a list 18 | # (eg "a, b, or c") 19 | def similar_word_list(word, limit = 3) 20 | words = similar_words(word, limit) 21 | if words.length == 1 22 | words[0] 23 | elsif words.length > 1 24 | [words[0..-2].join(", "), words[-1]].join(" or ") 25 | end 26 | end 27 | 28 | protected 29 | 30 | # http://www.informit.com/articles/article.aspx?p=683059&seqNum=36 31 | def levenshtein_distance(this, that, ins = 2, del = 2, sub = 1) 32 | # ins, del, sub are weighted costs 33 | return nil if this.nil? 34 | return nil if that.nil? 35 | dm = [] # distance matrix 36 | 37 | # Initialize first row values 38 | dm[0] = (0..this.length).collect {|i| i * ins } 39 | fill = [0] * (this.length - 1) 40 | 41 | # Initialize first column values 42 | (1..that.length).each do |i| 43 | dm[i] = [i * del, fill.flatten] 44 | end 45 | 46 | # populate matrix 47 | (1..that.length).each do |i| 48 | (1..this.length).each do |j| 49 | # critical comparison 50 | dm[i][j] = [ 51 | dm[i - 1][j - 1] + (this[j - 1] == that[i - 1] ? 0 : sub), 52 | dm[i][j - 1] + ins, 53 | dm[i - 1][j] + del 54 | ].min 55 | end 56 | end 57 | 58 | # The last value in matrix is the Levenshtein distance between the strings 59 | dm[that.length][this.length] 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /spec/support/platforms.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Spec 3 | module Platforms 4 | include Bundler::GemHelpers 5 | 6 | def rb 7 | Gem::Platform::RUBY 8 | end 9 | 10 | def mac 11 | Gem::Platform.new("x86-darwin-10") 12 | end 13 | 14 | def java 15 | Gem::Platform.new([nil, "java", nil]) 16 | end 17 | 18 | def linux 19 | Gem::Platform.new(["x86", "linux", nil]) 20 | end 21 | 22 | def mswin 23 | Gem::Platform.new(["x86", "mswin32", nil]) 24 | end 25 | 26 | def mingw 27 | Gem::Platform.new(["x86", "mingw32", nil]) 28 | end 29 | 30 | def x64_mingw 31 | Gem::Platform.new(["x64", "mingw32", nil]) 32 | end 33 | 34 | def all_platforms 35 | [rb, java, linux, mswin, mingw, x64_mingw] 36 | end 37 | 38 | def local 39 | generic_local_platform 40 | end 41 | 42 | def not_local 43 | all_platforms.find {|p| p != generic_local_platform } 44 | end 45 | 46 | def local_tag 47 | if RUBY_PLATFORM == "java" 48 | :jruby 49 | else 50 | :ruby 51 | end 52 | end 53 | 54 | def not_local_tag 55 | [:ruby, :jruby].find {|tag| tag != local_tag } 56 | end 57 | 58 | def local_ruby_engine 59 | ENV["BUNDLER_SPEC_RUBY_ENGINE"] || (defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby") 60 | end 61 | 62 | def local_engine_version 63 | return ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] if ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] 64 | 65 | case local_ruby_engine 66 | when "ruby" 67 | RUBY_VERSION 68 | when "rbx" 69 | Rubinius::VERSION 70 | when "jruby" 71 | JRUBY_VERSION 72 | else 73 | raise BundlerError, "That RUBY_ENGINE is not recognized" 74 | end 75 | end 76 | 77 | def not_local_engine_version 78 | case not_local_tag 79 | when :ruby 80 | not_local_ruby_version 81 | when :jruby 82 | "1.6.1" 83 | end 84 | end 85 | 86 | def not_local_ruby_version 87 | "1.12" 88 | end 89 | 90 | def not_local_patchlevel 91 | 9999 92 | end 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /lib/bundler/vendor/thor/lib/thor/parser/argument.rb: -------------------------------------------------------------------------------- 1 | class Bundler::Thor 2 | class Argument #:nodoc: 3 | VALID_TYPES = [:numeric, :hash, :array, :string] 4 | 5 | attr_reader :name, :description, :enum, :required, :type, :default, :banner 6 | alias_method :human_name, :name 7 | 8 | def initialize(name, options = {}) 9 | class_name = self.class.name.split("::").last 10 | 11 | type = options[:type] 12 | 13 | fail ArgumentError, "#{class_name} name can't be nil." if name.nil? 14 | fail ArgumentError, "Type :#{type} is not valid for #{class_name.downcase}s." if type && !valid_type?(type) 15 | 16 | @name = name.to_s 17 | @description = options[:desc] 18 | @required = options.key?(:required) ? options[:required] : true 19 | @type = (type || :string).to_sym 20 | @default = options[:default] 21 | @banner = options[:banner] || default_banner 22 | @enum = options[:enum] 23 | 24 | validate! # Trigger specific validations 25 | end 26 | 27 | def usage 28 | required? ? banner : "[#{banner}]" 29 | end 30 | 31 | def required? 32 | required 33 | end 34 | 35 | def show_default? 36 | case default 37 | when Array, String, Hash 38 | !default.empty? 39 | else 40 | default 41 | end 42 | end 43 | 44 | protected 45 | 46 | def validate! 47 | if required? && !default.nil? 48 | fail ArgumentError, "An argument cannot be required and have default value." 49 | elsif @enum && !@enum.is_a?(Array) 50 | fail ArgumentError, "An argument cannot have an enum other than an array." 51 | end 52 | end 53 | 54 | def valid_type?(type) 55 | self.class::VALID_TYPES.include?(type.to_sym) 56 | end 57 | 58 | def default_banner 59 | case type 60 | when :boolean 61 | nil 62 | when :string, :default 63 | human_name.upcase 64 | when :numeric 65 | "N" 66 | when :hash 67 | "key:value" 68 | when :array 69 | "one two three" 70 | end 71 | end 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /spec/support/path.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "pathname" 3 | 4 | module Spec 5 | module Path 6 | def root 7 | @root ||= Pathname.new(File.expand_path("../../..", __FILE__)) 8 | end 9 | 10 | def tmp(*path) 11 | root.join("tmp", *path) 12 | end 13 | 14 | def home(*path) 15 | tmp.join("home", *path) 16 | end 17 | 18 | def default_bundle_path(*path) 19 | system_gem_path(*path) 20 | end 21 | 22 | def bundled_app(*path) 23 | root = tmp.join("bundled_app") 24 | FileUtils.mkdir_p(root) 25 | root.join(*path) 26 | end 27 | 28 | alias_method :bundled_app1, :bundled_app 29 | 30 | def bundled_app2(*path) 31 | root = tmp.join("bundled_app2") 32 | FileUtils.mkdir_p(root) 33 | root.join(*path) 34 | end 35 | 36 | def vendored_gems(path = nil) 37 | bundled_app(*["vendor/bundle", Gem.ruby_engine, Gem::ConfigMap[:ruby_version], path].compact) 38 | end 39 | 40 | def cached_gem(path) 41 | bundled_app("vendor/cache/#{path}.gem") 42 | end 43 | 44 | def base_system_gems 45 | tmp.join("gems/base") 46 | end 47 | 48 | def gem_repo1(*args) 49 | tmp("gems/remote1", *args) 50 | end 51 | 52 | def gem_repo_missing(*args) 53 | tmp("gems/missing", *args) 54 | end 55 | 56 | def gem_repo2(*args) 57 | tmp("gems/remote2", *args) 58 | end 59 | 60 | def gem_repo3(*args) 61 | tmp("gems/remote3", *args) 62 | end 63 | 64 | def gem_repo4(*args) 65 | tmp("gems/remote4", *args) 66 | end 67 | 68 | def security_repo(*args) 69 | tmp("gems/security_repo", *args) 70 | end 71 | 72 | def system_gem_path(*path) 73 | tmp("gems/system", *path) 74 | end 75 | 76 | def lib_path(*args) 77 | tmp("libs", *args) 78 | end 79 | 80 | def bundler_path 81 | Pathname.new(File.expand_path("../../../lib", __FILE__)) 82 | end 83 | 84 | def plugin_root(*args) 85 | home ".bundle", "plugin", *args 86 | end 87 | 88 | def plugin_gems(*args) 89 | plugin_root "gems", *args 90 | end 91 | 92 | extend self 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /spec/runtime/platform_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "Bundler.setup with multi platform stuff" do 5 | it "raises a friendly error when gems are missing locally" do 6 | gemfile <<-G 7 | source "file://#{gem_repo1}" 8 | gem "rack" 9 | G 10 | 11 | lockfile <<-G 12 | GEM 13 | remote: file:#{gem_repo1}/ 14 | specs: 15 | rack (1.0) 16 | 17 | PLATFORMS 18 | #{local_tag} 19 | 20 | DEPENDENCIES 21 | rack 22 | G 23 | 24 | ruby <<-R 25 | begin 26 | require 'bundler' 27 | Bundler.setup 28 | rescue Bundler::GemNotFound => e 29 | puts "WIN" 30 | end 31 | R 32 | 33 | expect(out).to eq("WIN") 34 | end 35 | 36 | it "will resolve correctly on the current platform when the lockfile was targetted for a different one" do 37 | lockfile <<-G 38 | GEM 39 | remote: file:#{gem_repo1}/ 40 | specs: 41 | nokogiri (1.4.2-java) 42 | weakling (= 0.0.3) 43 | weakling (0.0.3) 44 | 45 | PLATFORMS 46 | java 47 | 48 | DEPENDENCIES 49 | nokogiri 50 | G 51 | 52 | system_gems "nokogiri-1.4.2" 53 | 54 | simulate_platform "x86-darwin-10" 55 | gemfile <<-G 56 | source "file://#{gem_repo1}" 57 | gem "nokogiri" 58 | G 59 | 60 | should_be_installed "nokogiri 1.4.2" 61 | end 62 | 63 | it "will add the resolve for the current platform" do 64 | lockfile <<-G 65 | GEM 66 | remote: file:#{gem_repo1}/ 67 | specs: 68 | nokogiri (1.4.2-java) 69 | weakling (= 0.0.3) 70 | weakling (0.0.3) 71 | 72 | PLATFORMS 73 | java 74 | 75 | DEPENDENCIES 76 | nokogiri 77 | G 78 | 79 | simulate_platform "x86-darwin-100" 80 | 81 | system_gems "nokogiri-1.4.2", "platform_specific-1.0-x86-darwin-100" 82 | 83 | gemfile <<-G 84 | source "file://#{gem_repo1}" 85 | gem "nokogiri" 86 | gem "platform_specific" 87 | G 88 | 89 | should_be_installed "nokogiri 1.4.2", "platform_specific 1.0 x86-darwin-100" 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb: -------------------------------------------------------------------------------- 1 | class Bundler::Thor 2 | module CoreExt #:nodoc: 3 | # A hash with indifferent access and magic predicates. 4 | # 5 | # hash = Bundler::Thor::CoreExt::HashWithIndifferentAccess.new 'foo' => 'bar', 'baz' => 'bee', 'force' => true 6 | # 7 | # hash[:foo] #=> 'bar' 8 | # hash['foo'] #=> 'bar' 9 | # hash.foo? #=> true 10 | # 11 | class HashWithIndifferentAccess < ::Hash #:nodoc: 12 | def initialize(hash = {}) 13 | super() 14 | hash.each do |key, value| 15 | self[convert_key(key)] = value 16 | end 17 | end 18 | 19 | def [](key) 20 | super(convert_key(key)) 21 | end 22 | 23 | def []=(key, value) 24 | super(convert_key(key), value) 25 | end 26 | 27 | def delete(key) 28 | super(convert_key(key)) 29 | end 30 | 31 | def values_at(*indices) 32 | indices.map { |key| self[convert_key(key)] } 33 | end 34 | 35 | def merge(other) 36 | dup.merge!(other) 37 | end 38 | 39 | def merge!(other) 40 | other.each do |key, value| 41 | self[convert_key(key)] = value 42 | end 43 | self 44 | end 45 | 46 | # Convert to a Hash with String keys. 47 | def to_hash 48 | Hash.new(default).merge!(self) 49 | end 50 | 51 | protected 52 | 53 | def convert_key(key) 54 | key.is_a?(Symbol) ? key.to_s : key 55 | end 56 | 57 | # Magic predicates. For instance: 58 | # 59 | # options.force? # => !!options['force'] 60 | # options.shebang # => "/usr/lib/local/ruby" 61 | # options.test_framework?(:rspec) # => options[:test_framework] == :rspec 62 | # 63 | def method_missing(method, *args, &block) 64 | method = method.to_s 65 | if method =~ /^(\w+)\?$/ 66 | if args.empty? 67 | !!self[$1] 68 | else 69 | self[$1] == args.first 70 | end 71 | else 72 | self[method] 73 | end 74 | end 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /spec/bundler/env_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | require "bundler/settings" 4 | 5 | describe Bundler::Env do 6 | let(:env) { described_class.new } 7 | 8 | describe "#report" do 9 | it "prints the environment" do 10 | out = env.report 11 | 12 | expect(out).to include("Environment") 13 | expect(out).to include(Bundler::VERSION) 14 | expect(out).to include(Gem::VERSION) 15 | expect(out).to include(env.send(:ruby_version)) 16 | expect(out).to include(env.send(:git_version)) 17 | end 18 | 19 | context "when there is a Gemfile and a lockfile and print_gemfile is true" do 20 | before do 21 | gemfile "gem 'rack', '1.0.0'" 22 | 23 | lockfile <<-L 24 | GEM 25 | remote: file:#{gem_repo1}/ 26 | specs: 27 | rack (1.0.0) 28 | 29 | DEPENDENCIES 30 | rack 31 | 32 | BUNDLED WITH 33 | 1.10.0 34 | L 35 | end 36 | 37 | let(:output) { env.report(:print_gemfile => true) } 38 | 39 | it "prints the Gemfile" do 40 | expect(output).to include("Gemfile") 41 | expect(output).to include("'rack', '1.0.0'") 42 | end 43 | 44 | it "prints the lockfile" do 45 | expect(output).to include("Gemfile.lock") 46 | expect(output).to include("rack (1.0.0)") 47 | end 48 | end 49 | 50 | context "when Gemfile contains a gemspec and print_gemspecs is true" do 51 | let(:gemspec) do 52 | <<-GEMSPEC.gsub(/^\s+/, "") 53 | Gem::Specification.new do |gem| 54 | gem.name = "foo" 55 | gem.author = "Fumofu" 56 | end 57 | GEMSPEC 58 | end 59 | 60 | before do 61 | gemfile("gemspec") 62 | 63 | File.open(bundled_app.join("foo.gemspec"), "wb") do |f| 64 | f.write(gemspec) 65 | end 66 | end 67 | 68 | it "prints the gemspec" do 69 | output = env.report(:print_gemspecs => true).gsub(/^\s+/, "") 70 | 71 | expect(output).to include("foo.gemspec") 72 | expect(output).to include(gemspec) 73 | end 74 | end 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /lib/bundler/postit_trampoline.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module BundlerVendoredPostIt; end 4 | require "bundler/vendor/postit/lib/postit" 5 | require "rubygems" 6 | 7 | environment = BundlerVendoredPostIt::PostIt::Environment.new([]) 8 | version = Gem::Requirement.new(environment.bundler_version) 9 | 10 | installed_version = 11 | if defined?(Bundler::VERSION) 12 | Bundler::VERSION 13 | else 14 | File.read(File.expand_path("../version.rb", __FILE__)) =~ /VERSION = "(.+)"/ 15 | $1 16 | end 17 | installed_version &&= Gem::Version.new(installed_version) 18 | 19 | if !version.satisfied_by?(installed_version) 20 | begin 21 | installer = BundlerVendoredPostIt::PostIt::Installer.new(version) 22 | installer.install! 23 | rescue => e 24 | abort <<-EOS.strip 25 | Installing the inferred bundler version (#{version}) failed. 26 | If you'd like to update to the current bundler version (#{installed_version}) in this project, run `bundle update --bundler`. 27 | The error was: #{e} 28 | EOS 29 | end 30 | 31 | if deleted_spec = Gem.loaded_specs.delete("bundler") 32 | deleted_spec.full_require_paths.each {|path| $:.delete(path) } 33 | else 34 | $:.delete(File.expand_path("../..", __FILE__)) 35 | end 36 | gem "bundler", version 37 | else 38 | begin 39 | gem "bundler", version 40 | rescue LoadError 41 | $:.unshift(File.expand_path("../..", __FILE__)) 42 | end 43 | end 44 | 45 | running_version = begin 46 | require "bundler/version" 47 | Bundler::VERSION 48 | rescue LoadError, NameError 49 | nil 50 | end 51 | 52 | if Gem::Requirement.new(">= 1.13.pre".dup).satisfied_by?(Gem::Version.new(running_version)) 53 | ENV["BUNDLE_POSTIT_TRAMPOLINING_VERSION"] = installed_version.to_s 54 | elsif ARGV.empty? || ARGV.any? {|a| %w(install i).include? a } 55 | puts <<-WARN.strip 56 | You're running Bundler #{installed_version} but this project uses #{running_version}. To update, run `bundle update --bundler`. 57 | WARN 58 | end 59 | 60 | if !Gem::Version.correct?(running_version.to_s) || !version.satisfied_by?(Gem::Version.create(running_version)) 61 | abort "The running bundler (#{running_version}) does not match the required `#{version}`" 62 | end 63 | -------------------------------------------------------------------------------- /lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require "readline" 3 | rescue LoadError 4 | end 5 | 6 | class Bundler::Thor 7 | module LineEditor 8 | class Readline < Basic 9 | def self.available? 10 | Object.const_defined?(:Readline) 11 | end 12 | 13 | def readline 14 | if echo? 15 | ::Readline.completion_append_character = nil 16 | # Ruby 1.8.7 does not allow Readline.completion_proc= to receive nil. 17 | if complete = completion_proc 18 | ::Readline.completion_proc = complete 19 | end 20 | ::Readline.readline(prompt, add_to_history?) 21 | else 22 | super 23 | end 24 | end 25 | 26 | private 27 | 28 | def add_to_history? 29 | options.fetch(:add_to_history, true) 30 | end 31 | 32 | def completion_proc 33 | if use_path_completion? 34 | proc { |text| PathCompletion.new(text).matches } 35 | elsif completion_options.any? 36 | proc do |text| 37 | completion_options.select { |option| option.start_with?(text) } 38 | end 39 | end 40 | end 41 | 42 | def completion_options 43 | options.fetch(:limited_to, []) 44 | end 45 | 46 | def use_path_completion? 47 | options.fetch(:path, false) 48 | end 49 | 50 | class PathCompletion 51 | attr_reader :text 52 | private :text 53 | 54 | def initialize(text) 55 | @text = text 56 | end 57 | 58 | def matches 59 | relative_matches 60 | end 61 | 62 | private 63 | 64 | def relative_matches 65 | absolute_matches.map { |path| path.sub(base_path, "") } 66 | end 67 | 68 | def absolute_matches 69 | Dir[glob_pattern].map do |path| 70 | if File.directory?(path) 71 | "#{path}/" 72 | else 73 | path 74 | end 75 | end 76 | end 77 | 78 | def glob_pattern 79 | "#{base_path}#{text}*" 80 | end 81 | 82 | def base_path 83 | "#{Dir.pwd}/" 84 | end 85 | end 86 | end 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /spec/realworld/parallel_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe "parallel", :realworld => true, :sometimes => true do 5 | it "installs" do 6 | gemfile <<-G 7 | source "https://rubygems.org" 8 | gem 'activesupport', '~> 3.2.13' 9 | gem 'faker', '~> 1.1.2' 10 | gem 'i18n', '~> 0.6.0' # Because 0.7+ requires Ruby 1.9.3+ 11 | G 12 | 13 | bundle :install, :jobs => 4, :env => { "DEBUG" => "1" } 14 | 15 | if Bundler.rubygems.provides?(">= 2.1.0") 16 | expect(out).to match(/[1-3]: /) 17 | else 18 | expect(out).to include("is not threadsafe") 19 | end 20 | 21 | bundle "show activesupport" 22 | expect(out).to match(/activesupport/) 23 | 24 | bundle "show faker" 25 | expect(out).to match(/faker/) 26 | 27 | bundle "config jobs" 28 | expect(out).to match(/: "4"/) 29 | end 30 | 31 | it "updates" do 32 | install_gemfile <<-G 33 | source "https://rubygems.org" 34 | gem 'activesupport', '3.2.12' 35 | gem 'faker', '~> 1.1.2' 36 | G 37 | 38 | gemfile <<-G 39 | source "https://rubygems.org" 40 | gem 'activesupport', '~> 3.2.12' 41 | gem 'faker', '~> 1.1.2' 42 | gem 'i18n', '~> 0.6.0' # Because 0.7+ requires Ruby 1.9.3+ 43 | G 44 | 45 | bundle :update, :jobs => 4, :env => { "DEBUG" => "1" } 46 | 47 | if Bundler.rubygems.provides?(">= 2.1.0") 48 | expect(out).to match(/[1-3]: /) 49 | else 50 | expect(out).to include("is not threadsafe") 51 | end 52 | 53 | bundle "show activesupport" 54 | expect(out).to match(/activesupport-3\.2\.\d+/) 55 | 56 | bundle "show faker" 57 | expect(out).to match(/faker/) 58 | 59 | bundle "config jobs" 60 | expect(out).to match(/: "4"/) 61 | end 62 | 63 | it "works with --standalone" do 64 | gemfile <<-G, :standalone => true 65 | source "https://rubygems.org" 66 | gem "diff-lcs" 67 | G 68 | 69 | bundle :install, :standalone => true, :jobs => 4 70 | 71 | ruby <<-RUBY, :no_lib => true 72 | $:.unshift File.expand_path("bundle") 73 | require "bundler/setup" 74 | 75 | require "diff/lcs" 76 | puts Diff::LCS 77 | RUBY 78 | 79 | expect(out).to eq("Diff::LCS") 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /lib/bundler/current_ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Bundler 3 | # Returns current version of Ruby 4 | # 5 | # @return [CurrentRuby] Current version of Ruby 6 | def self.current_ruby 7 | @current_ruby ||= CurrentRuby.new 8 | end 9 | 10 | class CurrentRuby 11 | KNOWN_MINOR_VERSIONS = %w( 12 | 1.8 13 | 1.9 14 | 2.0 15 | 2.1 16 | 2.2 17 | 2.3 18 | 2.4 19 | ).freeze 20 | 21 | KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze 22 | 23 | KNOWN_PLATFORMS = %w( 24 | jruby 25 | maglev 26 | mingw 27 | mri 28 | mswin 29 | mswin64 30 | rbx 31 | ruby 32 | x64_mingw 33 | ).freeze 34 | 35 | def ruby? 36 | !mswin? && (!defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby" || RUBY_ENGINE == "rbx" || RUBY_ENGINE == "maglev") 37 | end 38 | 39 | def mri? 40 | !mswin? && (!defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby") 41 | end 42 | 43 | def rbx? 44 | ruby? && defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx" 45 | end 46 | 47 | def jruby? 48 | defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" 49 | end 50 | 51 | def maglev? 52 | defined?(RUBY_ENGINE) && RUBY_ENGINE == "maglev" 53 | end 54 | 55 | def mswin? 56 | Bundler::WINDOWS 57 | end 58 | 59 | def mswin64? 60 | Bundler::WINDOWS && Gem::Platform.local.os == "mswin64" && Gem::Platform.local.cpu == "x64" 61 | end 62 | 63 | def mingw? 64 | Bundler::WINDOWS && Gem::Platform.local.os == "mingw32" && Gem::Platform.local.cpu != "x64" 65 | end 66 | 67 | def x64_mingw? 68 | Bundler::WINDOWS && Gem::Platform.local.os == "mingw32" && Gem::Platform.local.cpu == "x64" 69 | end 70 | 71 | (KNOWN_MINOR_VERSIONS + KNOWN_MAJOR_VERSIONS).each do |version| 72 | trimmed_version = version.tr(".", "") 73 | define_method(:"on_#{trimmed_version}?") do 74 | RUBY_VERSION.start_with?("#{version}.") 75 | end 76 | 77 | KNOWN_PLATFORMS.each do |platform| 78 | define_method(:"#{platform}_#{trimmed_version}?") do 79 | send(:"#{platform}?") && send(:"on_#{trimmed_version}?") 80 | end 81 | end 82 | end 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /lib/bundler/worker.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "thread" 3 | 4 | module Bundler 5 | class Worker 6 | POISON = Object.new 7 | 8 | class WrappedException < StandardError 9 | attr_reader :exception 10 | def initialize(exn) 11 | @exception = exn 12 | end 13 | end 14 | 15 | # @return [String] the name of the worker 16 | attr_reader :name 17 | 18 | # Creates a worker pool of specified size 19 | # 20 | # @param size [Integer] Size of pool 21 | # @param name [String] name the name of the worker 22 | # @param func [Proc] job to run in inside the worker pool 23 | def initialize(size, name, func) 24 | @name = name 25 | @request_queue = Queue.new 26 | @response_queue = Queue.new 27 | @func = func 28 | @threads = Array.new(size) do |i| 29 | Thread.start { process_queue(i) }.tap do |thread| 30 | thread.name = "#{name} Worker ##{i}" if thread.respond_to?(:name=) 31 | end 32 | end 33 | trap("INT") { abort_threads } 34 | end 35 | 36 | # Enqueue a request to be executed in the worker pool 37 | # 38 | # @param obj [String] mostly it is name of spec that should be downloaded 39 | def enq(obj) 40 | @request_queue.enq obj 41 | end 42 | 43 | # Retrieves results of job function being executed in worker pool 44 | def deq 45 | result = @response_queue.deq 46 | raise result.exception if result.is_a?(WrappedException) 47 | result 48 | end 49 | 50 | def stop 51 | stop_threads 52 | end 53 | 54 | private 55 | 56 | def process_queue(i) 57 | loop do 58 | obj = @request_queue.deq 59 | break if obj.equal? POISON 60 | @response_queue.enq apply_func(obj, i) 61 | end 62 | end 63 | 64 | def apply_func(obj, i) 65 | @func.call(obj, i) 66 | rescue Exception => e 67 | WrappedException.new(e) 68 | end 69 | 70 | # Stop the worker threads by sending a poison object down the request queue 71 | # so as worker threads after retrieving it, shut themselves down 72 | def stop_threads 73 | @threads.each { @request_queue.enq POISON } 74 | @threads.each(&:join) 75 | end 76 | 77 | def abort_threads 78 | @threads.each(&:exit) 79 | exit 1 80 | end 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /spec/bundler/plugin/api_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require "spec_helper" 3 | 4 | describe Bundler::Plugin::API do 5 | context "plugin declarations" do 6 | before do 7 | stub_const "UserPluginClass", Class.new(Bundler::Plugin::API) 8 | end 9 | 10 | describe "#command" do 11 | it "declares a command plugin with same class as handler" do 12 | expect(Bundler::Plugin). 13 | to receive(:add_command).with("meh", UserPluginClass).once 14 | 15 | UserPluginClass.command "meh" 16 | end 17 | 18 | it "accepts another class as argument that handles the command" do 19 | stub_const "NewClass", Class.new 20 | expect(Bundler::Plugin).to receive(:add_command).with("meh", NewClass).once 21 | 22 | UserPluginClass.command "meh", NewClass 23 | end 24 | end 25 | 26 | describe "#source" do 27 | it "declares a source plugin with same class as handler" do 28 | expect(Bundler::Plugin). 29 | to receive(:add_source).with("a_source", UserPluginClass).once 30 | 31 | UserPluginClass.source "a_source" 32 | end 33 | 34 | it "accepts another class as argument that handles the command" do 35 | stub_const "NewClass", Class.new 36 | expect(Bundler::Plugin).to receive(:add_source).with("a_source", NewClass).once 37 | 38 | UserPluginClass.source "a_source", NewClass 39 | end 40 | end 41 | end 42 | 43 | context "bundler interfaces provided" do 44 | before do 45 | stub_const "UserPluginClass", Class.new(Bundler::Plugin::API) 46 | end 47 | 48 | subject(:api) { UserPluginClass.new } 49 | 50 | # A test of delegation 51 | it "provides the Bundler's functions" do 52 | expect(Bundler).to receive(:an_unkown_function).once 53 | 54 | api.an_unkown_function 55 | end 56 | 57 | it "includes Bundler::SharedHelpers' functions" do 58 | expect(Bundler::SharedHelpers).to receive(:an_unkown_helper).once 59 | 60 | api.an_unkown_helper 61 | end 62 | 63 | context "#tmp" do 64 | it "provides a tmp dir" do 65 | expect(api.tmp("mytmp")).to be_directory 66 | end 67 | 68 | it "accepts multiple names for suffix" do 69 | expect(api.tmp("myplugin", "download")).to be_directory 70 | end 71 | end 72 | end 73 | end 74 | --------------------------------------------------------------------------------