Class: Rubygems::Await::Awaiter

Inherits:
Object
  • Object
show all
Defined in:
lib/rubygems/await.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(gems, source, deadline, name_indent = 10) ⇒ Awaiter

Returns a new instance of Awaiter.



28
29
30
31
32
33
34
# File 'lib/rubygems/await.rb', line 28

def initialize(gems, source, deadline, name_indent = 10)
  @gems = gems
  @source = source
  @source_uri = URI.parse(source)
  @deadline = deadline
  @name_indent = name_indent
end

Instance Attribute Details

#deadlineObject (readonly)

Returns the value of attribute deadline.



26
27
28
# File 'lib/rubygems/await.rb', line 26

def deadline
  @deadline
end

#gemsObject (readonly)

Returns the value of attribute gems.



26
27
28
# File 'lib/rubygems/await.rb', line 26

def gems
  @gems
end

#name_indentObject (readonly)

Returns the value of attribute name_indent.



26
27
28
# File 'lib/rubygems/await.rb', line 26

def name_indent
  @name_indent
end

#sourceObject (readonly)

Returns the value of attribute source.



26
27
28
# File 'lib/rubygems/await.rb', line 26

def source
  @source
end

#source_uriObject (readonly)

Returns the value of attribute source_uri.



26
27
28
# File 'lib/rubygems/await.rb', line 26

def source_uri
  @source_uri
end

Class Method Details

.awaiter_nameObject

Raises:

  • (NotImplementedError)


165
166
167
# File 'lib/rubygems/await.rb', line 165

def self.awaiter_name
  raise NotImplementedError
end

.callObject



36
37
38
39
40
41
42
43
44
# File 'lib/rubygems/await.rb', line 36

def self.call(...)
  Thread.new do
    awaiter = new(...)
    Thread.current.name = "#{awaiter_name} awaiter"
    Thread.current.report_on_exception = false

    awaiter.call
  end
end

.subclassesObject



16
17
18
# File 'lib/rubygems/await.rb', line 16

def self.subclasses
  @subclasses ||= []
end

Instance Method Details

#callObject



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/rubygems/await.rb', line 50

def call
  missing = collection
  iteration = 0
  loop do
    break if missing.empty? || expired?(iteration)

    sleep iteration if iteration.positive?
    start = Time.now

    log { "#{Bundler.ui.add_color("missing", :yellow)}: #{format_element(missing)}" }
    process_collection(missing)
  rescue StandardError => e
    log_error(e) { e.full_message(highlight: false) }
  ensure
    iteration += 1
    log(level: "debug") { "##{iteration} #{Time.now.-(start).round(2)}s" } if start
  end

  if missing.empty?
    log { Bundler.ui.add_color("all found!", :green, :bold) }
  else
    log(level: "error") { "#{Bundler.ui.add_color("missing", :red, :bold)} #{format_element(missing)}" }
  end

  missing
end

#collectionObject



46
47
48
# File 'lib/rubygems/await.rb', line 46

def collection
  Set.new(@gems)
end

#compact_index_clientObject



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/rubygems/await.rb', line 124

def compact_index_client
  remote = Bundler::Source::Rubygems::Remote.new URI.parse(source)
  fetcher = Bundler::Fetcher.new(remote)
  client =
    if Bundler::VERSION < "2.5.0"
      Bundler::Fetcher::CompactIndex.new(fetcher.send(:downloader), remote, fetcher.uri)
    else
      Bundler::Fetcher::CompactIndex.new(fetcher.send(:downloader), remote, fetcher.uri,
                                         fetcher.gem_remote_fetcher)
    end.send(:compact_index_client)
  # ensure that updating info always hits the network
  if client.instance_variable_defined?(:@parser)
    client.instance_variable_get(:@parser).instance_variable_set(:@info_checksums, Hash.new { "" })
  else
    client.instance_variable_set(:@info_checksums_by_name, Hash.new { "" })
  end
  client
end

#downloaderObject



118
119
120
121
122
# File 'lib/rubygems/await.rb', line 118

def downloader
  remote = Bundler::Source::Rubygems::Remote.new URI.parse(source)
  fetcher = Bundler::Fetcher.new(remote)
  fetcher.send(:downloader)
end

#expired?(padding = 0) ⇒ Boolean

Returns:

  • (Boolean)


196
197
198
# File 'lib/rubygems/await.rb', line 196

def expired?(padding = 0)
  Time.now + padding > deadline
end

#format_element(element) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/rubygems/await.rb', line 103

def format_element(element)
  case element
  when Gem::NameTuple
    Bundler.ui.add_color element.full_name, :bold
  when Set, Array
    element.map(&method(:format_element)).join(", ")
  when Hash
    element.map { |k, v| "#{k} (#{format_element(v)})" }.join(", ")
  when String
    Bundler.ui.add_color element, :bold
  else
    element.inspect
  end
end

#gem_remote_fetcherObject



143
144
145
146
147
148
149
150
151
152
153
# File 'lib/rubygems/await.rb', line 143

def gem_remote_fetcher
  if Bundler.rubygems.respond_to?(:gem_remote_fetcher)
    Bundler.rubygems.gem_remote_fetcher
  else
    remote = Bundler::Source::Rubygems::Remote.new URI.parse(source)
    fetcher = Bundler::Fetcher.new(remote)
    raise "unsupported bundler version" unless fetcher.respond_to?(:gem_remote_fetcher)

    fetcher.gem_remote_fetcher
  end
end

#index_fetcherObject



155
156
157
158
159
160
161
162
163
# File 'lib/rubygems/await.rb', line 155

def index_fetcher
  remote = Bundler::Source::Rubygems::Remote.new URI.parse(source)
  fetcher = Bundler::Fetcher.new(remote)
  if Bundler::VERSION < "2.5.0"
    Bundler::Fetcher::Index.new(fetcher.send(:downloader), remote, fetcher.uri)
  else
    Bundler::Fetcher::Index.new(fetcher.send(:downloader), remote, fetcher.uri, fetcher.gem_remote_fetcher)
  end
end

#inherited(klass) ⇒ Object



20
21
22
23
# File 'lib/rubygems/await.rb', line 20

def inherited(klass)
  super(klass)
  subclasses << klass
end

#log(level: "info", tags: nil) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/rubygems/await.rb', line 169

def log(level: "info", tags: nil)
  return unless Bundler.ui.level(level)

  s = Time.now.to_s << " "
  case level
  when "info"
    s << Bundler.ui.add_color("I", :white)
  when "warn"
    s << Bundler.ui.add_color("W", :yellow)
  when "error"
    s << Bundler.ui.add_color("E", :red)
  when "debug"
    s << "D"
  else
    raise ArgumentError, "unhandled level #{level.inspect}"
  end
  s << " ["
  s << Bundler.ui.add_color(self.class.awaiter_name.rjust(name_indent, " "), :bold, :white)
  s << "] "
  tags&.each do |tag|
    s << Bundler.ui.add_color("[#{tag}]", :white)
    s << " "
  end
  s << yield
  Bundler.ui.info s
end

#log_error(error, &block) ⇒ Object



97
98
99
100
101
# File 'lib/rubygems/await.rb', line 97

def log_error(error, &block)
  block ||= proc { error.message.to_s }
  log(level: "warn", tags: [Bundler.ui.add_color(error.class.name, :red)], &block)
  false
end

#log_found(element) ⇒ Object



91
92
93
94
95
# File 'lib/rubygems/await.rb', line 91

def log_found(element)
  log(level: "info") { "#{Bundler.ui.add_color("found", :green)} #{format_element(element)}" }

  true
end

#process_collection(missing) ⇒ Object



77
78
79
80
81
82
83
84
85
# File 'lib/rubygems/await.rb', line 77

def process_collection(missing)
  to_delete = []

  missing.each do |m|
    to_delete << m if process_element(m) && log_found(m)
  end
ensure
  missing.subtract(to_delete)
end

#process_element(element) ⇒ Object

Raises:

  • (NotImplementedError)


87
88
89
# File 'lib/rubygems/await.rb', line 87

def process_element(element)
  raise NotImplementedError
end

#safe_load_marshal(contents) ⇒ Object



200
201
202
203
204
205
206
# File 'lib/rubygems/await.rb', line 200

def safe_load_marshal(contents)
  if Bundler.respond_to?(:safe_load_marshal)
    Bundler.safe_load_marshal(contents)
  else
    Marshal.load(contents) # rubocop:disable Security/MarshalLoad
  end
end