Class: Bundler::Fetcher

Inherits:
Object
  • Object
show all
Defined in:
lib/bundler/fetcher.rb,
lib/bundler/fetcher/base.rb,
lib/bundler/fetcher/index.rb,
lib/bundler/fetcher/dependency.rb,
lib/bundler/fetcher/downloader.rb

Overview

Handles all the fetching with the rubygems server

Defined Under Namespace

Classes: AuthenticationRequiredError, BadAuthenticationError, Base, CertificateFailureError, Dependency, Downloader, FallbackError, Index, NetworkDownError, SSLError

Constant Summary collapse

AUTH_ERRORS =

Exceptions classes that should bypass retry attempts. If your password didn’t work the first time, it’s not going to the third time.

[AuthenticationRequiredError, BadAuthenticationError]

Class Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(remote) ⇒ Fetcher

Returns a new instance of Fetcher.



65
66
67
68
69
70
# File 'lib/bundler/fetcher.rb', line 65

def initialize(remote)
  @remote = remote

  Socket.do_not_reverse_lookup = true
  connection # create persistent connection
end

Class Attribute Details

.api_timeoutObject

Returns the value of attribute api_timeout.



58
59
60
# File 'lib/bundler/fetcher.rb', line 58

def api_timeout
  @api_timeout
end

.disable_endpointObject

Returns the value of attribute disable_endpoint.



58
59
60
# File 'lib/bundler/fetcher.rb', line 58

def disable_endpoint
  @disable_endpoint
end

.max_retriesObject

Returns the value of attribute max_retries.



58
59
60
# File 'lib/bundler/fetcher.rb', line 58

def max_retries
  @max_retries
end

.redirect_limitObject

Returns the value of attribute redirect_limit.



58
59
60
# File 'lib/bundler/fetcher.rb', line 58

def redirect_limit
  @redirect_limit
end

Instance Method Details

#fetch_spec(spec) ⇒ Object

fetch a gem specification



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/bundler/fetcher.rb', line 77

def fetch_spec(spec)
  spec = spec - [nil, 'ruby', '']
  spec_file_name = "#{spec.join '-'}.gemspec"

  uri = URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")
  if uri.scheme == 'file'
    Bundler.load_marshal Gem.inflate(Gem.read_binary(uri.path))
  elsif cached_spec_path = gemspec_cached_path(spec_file_name)
    Bundler.load_gemspec(cached_spec_path)
  else
    Bundler.load_marshal Gem.inflate(downloader.fetch uri)
  end
rescue MarshalError
  raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \
    "Your network or your gem server is probably having issues right now."
end

#fetchersObject



171
172
173
# File 'lib/bundler/fetcher.rb', line 171

def fetchers
  @fetchers ||= FETCHERS.map { |f| f.new(downloader, remote_uri, fetch_uri, uri) }
end

#inspectObject



175
176
177
# File 'lib/bundler/fetcher.rb', line 175

def inspect
  "#<#{self.class}:0x#{object_id} uri=#{uri}>"
end

#specs(gem_names, source) ⇒ Object

return the specs in the bundler format as an index



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/bundler/fetcher.rb', line 95

def specs(gem_names, source)
  old = Bundler.rubygems.sources
  index = Bundler::Index.new

  specs = {}
  fetchers.dup.each do |f|
    unless f.api_fetcher? && !gem_names
      break if specs = f.specs(gem_names)
    end
    fetchers.delete(f)
  end
  @use_api = false if fetchers.none?(&:api_fetcher?)

  specs[remote_uri].each do |name, version, platform, dependencies|
    next if name == 'bundler'
    spec = nil
    if dependencies
      spec = EndpointSpecification.new(name, version, platform, dependencies)
    else
      spec = RemoteSpecification.new(name, version, platform, self)
    end
    spec.source = source
    spec.remote = @remote
    index << spec
  end

  index
rescue CertificateFailureError
  Bundler.ui.info "" if gem_names && use_api # newline after dots
  raise
ensure
  Bundler.rubygems.sources = old
end

#uriObject



72
73
74
# File 'lib/bundler/fetcher.rb', line 72

def uri
  @remote.anonymized_uri
end

#use_apiObject



129
130
131
132
133
134
135
136
137
138
# File 'lib/bundler/fetcher.rb', line 129

def use_api
  return @use_api if defined?(@use_api)

  if remote_uri.scheme == "file" || Bundler::Fetcher.disable_endpoint
    @use_api = false
  else
    fetchers.reject! { |f| f.api_fetcher? && !f.api_available? }
    @use_api = fetchers.any?(&:api_fetcher?)
  end
end

#user_agentObject



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/bundler/fetcher.rb', line 140

def user_agent
  @user_agent ||= begin
    ruby = Bundler.ruby_version

    agent = "bundler/#{Bundler::VERSION}"
    agent << " rubygems/#{Gem::VERSION}"
    agent << " ruby/#{ruby.version}"
    agent << " (#{ruby.host})"
    agent << " command/#{ARGV.first}"

    if ruby.engine != "ruby"
      # engine_version raises on unknown engines
      engine_version = ruby.engine_version rescue "???"
      agent << " #{ruby.engine}/#{engine_version}"
    end

    agent << " options/#{Bundler.settings.all.join(",")}"

    agent << " ci/#{cis.join(",")}" if cis.any?

    # add a random ID so we can consolidate runs server-side
    agent << " " << SecureRandom.hex(8)

    # add any user agent strings set in the config
    extra_ua = Bundler.settings[:user_agent]
    agent << " " << extra_ua if extra_ua

    agent
  end
end