Class: Dependabot::Dependency

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/dependabot/dependency.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, requirements:, package_manager:, version: nil, previous_version: nil, previous_requirements: nil, directory: nil, subdependency_metadata: [], removed: false, metadata: {}) ⇒ Dependency

Returns a new instance of Dependency.



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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/dependabot/dependency.rb', line 144

def initialize(
  name:,
  requirements:,
  package_manager:,
  version: nil,
  previous_version: nil,
  previous_requirements: nil,
  directory: nil,
  subdependency_metadata: [],
  removed: false,
  metadata: {}
)
  @name = name
  @version = T.let(
    case version
    when Dependabot::Version then version.to_s
    when String then version
    end,
    T.nilable(String)
  )
  @version = nil if @version == ""
  @requirements = T.let(requirements.map { |req| symbolize_keys(req) }, T::Array[T::Hash[Symbol, T.untyped]])
  @previous_version = previous_version
  @previous_version = nil if @previous_version == ""
  @previous_requirements = T.let(
    previous_requirements&.map { |req| symbolize_keys(req) },
    T.nilable(T::Array[T::Hash[Symbol, T.untyped]])
  )
  @package_manager = package_manager
  @directory = directory
  unless top_level? ||  == []
    @subdependency_metadata = T.let(
      &.map { |h| symbolize_keys(h) },
      T.nilable(T::Array[T::Hash[Symbol, T.untyped]])
    )
  end
  @removed = removed
  @metadata = T.let(symbolize_keys( || {}), T::Hash[Symbol, T.untyped])
  check_values
end

Instance Attribute Details

#attribution_directoryObject

Returns the value of attribute attribution_directory.



122
123
124
# File 'lib/dependabot/dependency.rb', line 122

def attribution_directory
  @attribution_directory
end

#attribution_selection_reasonObject

Returns the value of attribute attribution_selection_reason.



119
120
121
# File 'lib/dependabot/dependency.rb', line 119

def attribution_selection_reason
  @attribution_selection_reason
end

#attribution_source_groupObject

Returns the value of attribute attribution_source_group.



116
117
118
# File 'lib/dependabot/dependency.rb', line 116

def attribution_source_group
  @attribution_source_group
end

#attribution_timestampObject

Returns the value of attribute attribution_timestamp.



125
126
127
# File 'lib/dependabot/dependency.rb', line 125

def attribution_timestamp
  @attribution_timestamp
end

#directoryObject

Returns the value of attribute directory.



106
107
108
# File 'lib/dependabot/dependency.rb', line 106

def directory
  @directory
end

#metadataObject (readonly)

Returns the value of attribute metadata.



112
113
114
# File 'lib/dependabot/dependency.rb', line 112

def 
  @metadata
end

#nameObject (readonly)

Returns the value of attribute name.



88
89
90
# File 'lib/dependabot/dependency.rb', line 88

def name
  @name
end

#package_managerObject (readonly)

Returns the value of attribute package_manager.



97
98
99
# File 'lib/dependabot/dependency.rb', line 97

def package_manager
  @package_manager
end

#previous_requirementsObject (readonly)

Returns the value of attribute previous_requirements.



103
104
105
# File 'lib/dependabot/dependency.rb', line 103

def previous_requirements
  @previous_requirements
end

#previous_versionObject (readonly)

Returns the value of attribute previous_version.



100
101
102
# File 'lib/dependabot/dependency.rb', line 100

def previous_version
  @previous_version
end

#requirementsObject (readonly)

Returns the value of attribute requirements.



94
95
96
# File 'lib/dependabot/dependency.rb', line 94

def requirements
  @requirements
end

#subdependency_metadataObject (readonly)

Returns the value of attribute subdependency_metadata.



109
110
111
# File 'lib/dependabot/dependency.rb', line 109

def 
  @subdependency_metadata
end

#versionObject (readonly)

Returns the value of attribute version.



91
92
93
# File 'lib/dependabot/dependency.rb', line 91

def version
  @version
end

Class Method Details

.display_name_builder_for_package_manager(package_manager) ⇒ Object



44
45
46
# File 'lib/dependabot/dependency.rb', line 44

def self.display_name_builder_for_package_manager(package_manager)
  @display_name_builders[package_manager]
end

.humanized_previous_version_builder_for_package_manager(package_manager) ⇒ Object



73
74
75
# File 'lib/dependabot/dependency.rb', line 73

def self.humanized_previous_version_builder_for_package_manager(package_manager)
  @humanized_previous_version_builders[package_manager]
end

.name_normaliser_for_package_manager(package_manager) ⇒ Object



54
55
56
# File 'lib/dependabot/dependency.rb', line 54

def self.name_normaliser_for_package_manager(package_manager)
  @name_normalisers[package_manager] || ->(name) { name }
end

.production_check_for_package_manager(package_manager) ⇒ Object



25
26
27
28
29
30
# File 'lib/dependabot/dependency.rb', line 25

def self.production_check_for_package_manager(package_manager)
  production_check = @production_checks[package_manager]
  return production_check if production_check

  raise "Unsupported package_manager #{package_manager}"
end

.register_display_name_builder(package_manager, name_builder) ⇒ Object



49
50
51
# File 'lib/dependabot/dependency.rb', line 49

def self.register_display_name_builder(package_manager, name_builder)
  @display_name_builders[package_manager] = name_builder
end

.register_humanized_previous_version_builder(package_manager, builder) ⇒ Object



83
84
85
# File 'lib/dependabot/dependency.rb', line 83

def self.register_humanized_previous_version_builder(package_manager, builder)
  @humanized_previous_version_builders[package_manager] = builder
end

.register_name_normaliser(package_manager, name_builder) ⇒ Object



64
65
66
# File 'lib/dependabot/dependency.rb', line 64

def self.register_name_normaliser(package_manager, name_builder)
  @name_normalisers[package_manager] = name_builder
end

.register_production_check(package_manager, production_check) ⇒ Object



39
40
41
# File 'lib/dependabot/dependency.rb', line 39

def self.register_production_check(package_manager, production_check)
  @production_checks[package_manager] = production_check
end

Instance Method Details

#==(other) ⇒ Object



324
325
326
327
328
329
330
331
# File 'lib/dependabot/dependency.rb', line 324

def ==(other)
  case other
  when Dependency
    to_h == other.to_h
  else
    false
  end
end

#all_sourcesObject



386
387
388
389
390
391
392
393
394
# File 'lib/dependabot/dependency.rb', line 386

def all_sources
  if top_level?
    requirements.map { |requirement| requirement.fetch(:source) }
  elsif 
    T.must().filter_map { |data| data[:source] }
  else
    []
  end
end

#all_versionsObject



308
309
310
311
312
313
# File 'lib/dependabot/dependency.rb', line 308

def all_versions
  all_versions = [:all_versions]
  return [version].compact unless all_versions

  all_versions.filter_map(&:version)
end

#appears_in_lockfile?Boolean

Returns:

  • (Boolean)


220
221
222
# File 'lib/dependabot/dependency.rb', line 220

def appears_in_lockfile?
  !!(previous_version || (version && previous_requirements.nil?))
end

#display_nameObject



241
242
243
244
245
246
247
# File 'lib/dependabot/dependency.rb', line 241

def display_name
  display_name_builder =
    self.class.display_name_builder_for_package_manager(package_manager)
  return name unless display_name_builder

  display_name_builder.call(name)
end

#docker_digest_from_reqs(requirements) ⇒ Object



276
277
278
279
280
# File 'lib/dependabot/dependency.rb', line 276

def docker_digest_from_reqs(requirements)
  requirements
    .filter_map { |r| r.dig(:source, "digest") || r.dig(:source, :digest) }
    .first
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


339
340
341
# File 'lib/dependabot/dependency.rb', line 339

def eql?(other)
  self == other
end

#hashObject



334
335
336
# File 'lib/dependabot/dependency.rb', line 334

def hash
  to_h.hash
end

#humanized_previous_versionObject



250
251
252
253
254
255
# File 'lib/dependabot/dependency.rb', line 250

def humanized_previous_version
  custom_version = custom_humanized_previous_version
  return custom_version if custom_version

  default_humanized_previous_version
end

#humanized_versionObject



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/dependabot/dependency.rb', line 258

def humanized_version
  return "removed" if removed?
  return nil if version.nil?

  if T.must(version).match?(/^[0-9a-f]{40}/)
    return new_ref if ref_changed? && new_ref

    "`#{T.must(version)[0..6]}`"
  elsif version == previous_version &&
        package_manager == "docker"
    digest = docker_digest_from_reqs(requirements)
    "`#{T.must(T.must(digest).split(':').last)[0..6]}`"
  else
    version
  end
end

#informational_only?Boolean

Returns:

  • (Boolean)


319
320
321
# File 'lib/dependabot/dependency.rb', line 319

def informational_only?
  [:information_only]
end

#new_refObject



293
294
295
296
297
298
# File 'lib/dependabot/dependency.rb', line 293

def new_ref
  new_refs = requirements.filter_map do |r|
    r.dig(:source, "ref") || r.dig(:source, :ref)
  end.uniq
  new_refs.first if new_refs.one?
end

#numeric_versionObject



198
199
200
201
202
# File 'lib/dependabot/dependency.rb', line 198

def numeric_version
  return unless version && version_class.correct?(version)

  @numeric_version ||= T.let(version_class.new(T.must(version)), T.nilable(Dependabot::Version))
end

#previous_refObject



283
284
285
286
287
288
289
290
# File 'lib/dependabot/dependency.rb', line 283

def previous_ref
  return nil if previous_requirements.nil?

  previous_refs = T.must(previous_requirements).filter_map do |r|
    r.dig(:source, "ref") || r.dig(:source, :ref)
  end.uniq
  previous_refs.first if previous_refs.one?
end

#production?Boolean

Returns:

  • (Boolean)


225
226
227
228
229
230
231
232
233
# File 'lib/dependabot/dependency.rb', line 225

def production?
  return subdependency_production_check unless top_level?

  groups = requirements.flat_map { |r| r.fetch(:groups).map(&:to_s) }

  self.class
      .production_check_for_package_manager(package_manager)
      .call(groups)
end

#ref_changed?Boolean

Returns:

  • (Boolean)


301
302
303
# File 'lib/dependabot/dependency.rb', line 301

def ref_changed?
  previous_ref != new_ref
end

#removed?Boolean

Returns:

  • (Boolean)


193
194
195
# File 'lib/dependabot/dependency.rb', line 193

def removed?
  @removed
end

#requirement_classObject



349
350
351
# File 'lib/dependabot/dependency.rb', line 349

def requirement_class
  Utils.requirement_class_for_package_manager(package_manager)
end

#requirements_changed?Boolean

Returns:

  • (Boolean)


397
398
399
# File 'lib/dependabot/dependency.rb', line 397

def requirements_changed?
  (requirements - T.must(previous_requirements)).any?
end

#source_details(allowed_types: nil) ⇒ Object



364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/dependabot/dependency.rb', line 364

def source_details(allowed_types: nil)
  sources = all_sources.uniq.compact
  sources.select! { |source| allowed_types.include?(source[:type].to_s) } if allowed_types

  git = allowed_types == ["git"]

  if (git && sources.map { |s| s[:url] }.uniq.count > 1) || (!git && sources.count > 1)
    raise "Multiple sources! #{sources.join(', ')}"
  end

  sources.first
end

#source_typeObject



378
379
380
381
382
383
# File 'lib/dependabot/dependency.rb', line 378

def source_type
  details = source_details
  return "default" if details.nil?

  details[:type] || details.fetch("type")
end

#specific_requirementsObject



344
345
346
# File 'lib/dependabot/dependency.rb', line 344

def specific_requirements
  requirements.select { |r| requirement_class.new(r[:requirement]).specific? }
end

#subdependency_production_checkObject



236
237
238
# File 'lib/dependabot/dependency.rb', line 236

def subdependency_production_check
  !&.all? { |h| h[:production] == false }
end

#to_hObject



205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/dependabot/dependency.rb', line 205

def to_h
  {
    "name" => name,
    "version" => version,
    "requirements" => requirements,
    "previous_version" => previous_version,
    "previous_requirements" => previous_requirements,
    "directory" => directory,
    "package_manager" => package_manager,
    "subdependency_metadata" => ,
    "removed" => removed? || nil
  }.compact
end

#top_level?Boolean

Returns:

  • (Boolean)


188
189
190
# File 'lib/dependabot/dependency.rb', line 188

def top_level?
  requirements.any?
end

#version_classObject



354
355
356
# File 'lib/dependabot/dependency.rb', line 354

def version_class
  Utils.version_class_for_package_manager(package_manager)
end