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.



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/dependabot/dependency.rb', line 121

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? ||  == []
     = T.let(
      &.map { |h| symbolize_keys(h) },
      T.nilable(T::Array[T::Hash[Symbol, T.untyped]])
    )
  end
  @removed = removed
   = T.let(symbolize_keys( || {}), T::Hash[Symbol, T.untyped])
  check_values
end

Instance Attribute Details

#attribution_directoryObject

Returns the value of attribute attribution_directory.



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

def attribution_directory
  @attribution_directory
end

#attribution_selection_reasonObject

Returns the value of attribute attribution_selection_reason.



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

def attribution_selection_reason
  @attribution_selection_reason
end

#attribution_source_groupObject

Returns the value of attribute attribution_source_group.



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

def attribution_source_group
  @attribution_source_group
end

#attribution_timestampObject

Returns the value of attribute attribution_timestamp.



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

def attribution_timestamp
  @attribution_timestamp
end

#directoryObject

Returns the value of attribute directory.



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

def directory
  @directory
end

#metadataObject (readonly)

Returns the value of attribute metadata.



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

def 
  
end

#nameObject (readonly)

Returns the value of attribute name.



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

def name
  @name
end

#package_managerObject (readonly)

Returns the value of attribute package_manager.



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

def package_manager
  @package_manager
end

#previous_requirementsObject (readonly)

Returns the value of attribute previous_requirements.



80
81
82
# File 'lib/dependabot/dependency.rb', line 80

def previous_requirements
  @previous_requirements
end

#previous_versionObject (readonly)

Returns the value of attribute previous_version.



77
78
79
# File 'lib/dependabot/dependency.rb', line 77

def previous_version
  @previous_version
end

#requirementsObject (readonly)

Returns the value of attribute requirements.



71
72
73
# File 'lib/dependabot/dependency.rb', line 71

def requirements
  @requirements
end

#subdependency_metadataObject (readonly)

Returns the value of attribute subdependency_metadata.



86
87
88
# File 'lib/dependabot/dependency.rb', line 86

def 
  
end

#versionObject (readonly)

Returns the value of attribute version.



68
69
70
# File 'lib/dependabot/dependency.rb', line 68

def version
  @version
end

Class Method Details

.display_name_builder_for_package_manager(package_manager) ⇒ Object



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

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

.name_normaliser_for_package_manager(package_manager) ⇒ Object



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

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

.production_check_for_package_manager(package_manager) ⇒ Object



21
22
23
24
25
26
# File 'lib/dependabot/dependency.rb', line 21

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



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

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

.register_name_normaliser(package_manager, name_builder) ⇒ Object



60
61
62
# File 'lib/dependabot/dependency.rb', line 60

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

.register_production_check(package_manager, production_check) ⇒ Object



35
36
37
# File 'lib/dependabot/dependency.rb', line 35

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

Instance Method Details

#==(other) ⇒ Object



315
316
317
318
319
320
321
322
# File 'lib/dependabot/dependency.rb', line 315

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

#all_sourcesObject



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

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



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

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)


197
198
199
# File 'lib/dependabot/dependency.rb', line 197

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

#display_nameObject



218
219
220
221
222
223
224
# File 'lib/dependabot/dependency.rb', line 218

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



267
268
269
270
271
# File 'lib/dependabot/dependency.rb', line 267

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)


330
331
332
# File 'lib/dependabot/dependency.rb', line 330

def eql?(other)
  self == other
end

#hashObject



325
326
327
# File 'lib/dependabot/dependency.rb', line 325

def hash
  to_h.hash
end

#humanized_previous_versionObject



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/dependabot/dependency.rb', line 227

def humanized_previous_version
  # If we don't have a previous version, we *may* still be able to figure
  # one out if a ref was provided and has been changed (in which case the
  # previous ref was essentially the version).
  if previous_version.nil?
    return ref_changed? ? previous_ref : nil
  end

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

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

#humanized_versionObject



249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/dependabot/dependency.rb', line 249

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)


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

def informational_only?
  [:information_only]
end

#new_refObject



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

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



175
176
177
178
179
# File 'lib/dependabot/dependency.rb', line 175

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



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

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)


202
203
204
205
206
207
208
209
210
# File 'lib/dependabot/dependency.rb', line 202

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)


292
293
294
# File 'lib/dependabot/dependency.rb', line 292

def ref_changed?
  previous_ref != new_ref
end

#removed?Boolean

Returns:

  • (Boolean)


170
171
172
# File 'lib/dependabot/dependency.rb', line 170

def removed?
  @removed
end

#requirement_classObject



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

def requirement_class
  Utils.requirement_class_for_package_manager(package_manager)
end

#requirements_changed?Boolean

Returns:

  • (Boolean)


388
389
390
# File 'lib/dependabot/dependency.rb', line 388

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

#source_details(allowed_types: nil) ⇒ Object



355
356
357
358
359
360
361
362
363
364
365
366
# File 'lib/dependabot/dependency.rb', line 355

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



369
370
371
372
373
374
# File 'lib/dependabot/dependency.rb', line 369

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

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

#specific_requirementsObject



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

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

#subdependency_production_checkObject



213
214
215
# File 'lib/dependabot/dependency.rb', line 213

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

#to_hObject



182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/dependabot/dependency.rb', line 182

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)


165
166
167
# File 'lib/dependabot/dependency.rb', line 165

def top_level?
  requirements.any?
end

#version_classObject



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

def version_class
  Utils.version_class_for_package_manager(package_manager)
end