dependabot-core 0.89.5 → 0.90.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/metadata_finders/base"
4
- require "dependabot/utils/go/path_converter"
5
-
6
- module Dependabot
7
- module MetadataFinders
8
- module Go
9
- class Dep < Dependabot::MetadataFinders::Base
10
- private
11
-
12
- def look_up_source
13
- return look_up_git_dependency_source if git_dependency?
14
-
15
- path_str = (specified_source_string || dependency.name)
16
- url = Dependabot::Utils::Go::PathConverter.
17
- git_url_for_path_without_go_helper(path_str)
18
- Source.from_url(url) if url
19
- end
20
-
21
- def git_dependency?
22
- return false unless declared_source_details
23
-
24
- dependency_type =
25
- declared_source_details.fetch(:type, nil) ||
26
- declared_source_details.fetch("type")
27
-
28
- dependency_type == "git"
29
- end
30
-
31
- def look_up_git_dependency_source
32
- specified_url =
33
- declared_source_details.fetch(:url, nil) ||
34
- declared_source_details.fetch("url")
35
-
36
- Source.from_url(specified_url)
37
- end
38
-
39
- def specified_source_string
40
- declared_source_details&.fetch(:source, nil) ||
41
- declared_source_details&.fetch("source", nil)
42
- end
43
-
44
- def declared_source_details
45
- sources = dependency.requirements.
46
- map { |r| r.fetch(:source) }.
47
- uniq.compact
48
-
49
- raise "Multiple sources! #{sources.join(', ')}" if sources.count > 1
50
-
51
- sources.first
52
- end
53
- end
54
- end
55
- end
56
- end
@@ -1,311 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "toml-rb"
4
- require "dependabot/update_checkers/base"
5
-
6
- module Dependabot
7
- module UpdateCheckers
8
- module Go
9
- class Dep < Dependabot::UpdateCheckers::Base
10
- require_relative "dep/file_preparer"
11
- require_relative "dep/latest_version_finder"
12
- require_relative "dep/requirements_updater"
13
- require_relative "dep/version_resolver"
14
-
15
- def latest_version
16
- @latest_version ||=
17
- LatestVersionFinder.new(
18
- dependency: dependency,
19
- dependency_files: dependency_files,
20
- credentials: credentials,
21
- ignored_versions: ignored_versions
22
- ).latest_version
23
- end
24
-
25
- def latest_resolvable_version
26
- @latest_resolvable_version ||=
27
- if modules_dependency?
28
- latest_version
29
- elsif git_dependency?
30
- latest_resolvable_version_for_git_dependency
31
- else
32
- latest_resolvable_released_version(unlock_requirement: true)
33
- end
34
- end
35
-
36
- def latest_resolvable_version_with_no_unlock
37
- @latest_resolvable_version_with_no_unlock ||=
38
- if git_dependency?
39
- latest_resolvable_commit_with_unchanged_git_source
40
- else
41
- latest_resolvable_released_version(unlock_requirement: false)
42
- end
43
- end
44
-
45
- def updated_requirements
46
- @updated_requirements ||=
47
- RequirementsUpdater.new(
48
- requirements: dependency.requirements,
49
- updated_source: updated_source,
50
- update_strategy: requirements_update_strategy,
51
- latest_version: latest_version&.to_s,
52
- latest_resolvable_version: latest_resolvable_version&.to_s
53
- ).updated_requirements
54
- end
55
-
56
- def requirements_update_strategy
57
- # If passed in as an option (in the base class) honour that option
58
- if @requirements_update_strategy
59
- return @requirements_update_strategy.to_sym
60
- end
61
-
62
- # Otherwise, widen ranges for libraries and bump versions for apps
63
- library? ? :widen_ranges : :bump_versions
64
- end
65
-
66
- private
67
-
68
- def latest_version_resolvable_with_full_unlock?
69
- # Full unlock checks aren't implemented for Go (yet)
70
- false
71
- end
72
-
73
- def updated_dependencies_after_full_unlock
74
- raise NotImplementedError
75
- end
76
-
77
- # Override the base class's check for whether this is a git dependency,
78
- # since not all dep git dependencies have a SHA version (sometimes their
79
- # version is the tag)
80
- def existing_version_is_sha?
81
- git_dependency?
82
- end
83
-
84
- def library?
85
- dependency_files.none? { |f| f.type == "package_main" }
86
- end
87
-
88
- # rubocop:disable Metrics/CyclomaticComplexity
89
- # rubocop:disable Metrics/PerceivedComplexity
90
- def latest_resolvable_version_for_git_dependency
91
- return latest_version if modules_dependency?
92
-
93
- latest_release =
94
- begin
95
- latest_resolvable_released_version(unlock_requirement: true)
96
- rescue SharedHelpers::HelperSubprocessFailed => error
97
- raise unless error.message.include?("Solving failure")
98
- end
99
-
100
- # If there's a resolvable release that includes the current pinned
101
- # ref or that the current branch is behind, we switch to that release.
102
- return latest_release if git_branch_or_ref_in_release?(latest_release)
103
-
104
- # Otherwise, if the gem isn't pinned, the latest version is just the
105
- # latest commit for the specified branch.
106
- unless git_commit_checker.pinned?
107
- return latest_resolvable_commit_with_unchanged_git_source
108
- end
109
-
110
- # If the dependency is pinned to a tag that looks like a version then
111
- # we want to update that tag.
112
- if git_commit_checker.pinned_ref_looks_like_version? &&
113
- latest_git_tag_is_resolvable?
114
- new_tag = git_commit_checker.local_tag_for_latest_version
115
- return version_from_tag(new_tag)
116
- end
117
-
118
- # If the dependency is pinned to a tag that doesn't look like a
119
- # version then there's nothing we can do.
120
- nil
121
- end
122
- # rubocop:enable Metrics/CyclomaticComplexity
123
- # rubocop:enable Metrics/PerceivedComplexity
124
-
125
- def version_from_tag(tag)
126
- # To compare with the current version we either use the commit SHA
127
- # (if that's what the parser picked up) of the tag name.
128
- if dependency.version&.match?(/^[0-9a-f]{40}$/)
129
- return tag&.fetch(:commit_sha)
130
- end
131
-
132
- tag&.fetch(:tag)
133
- end
134
-
135
- def latest_resolvable_commit_with_unchanged_git_source
136
- if @commit_lookup_attempted
137
- return @latest_resolvable_commit_with_unchanged_git_source
138
- end
139
-
140
- @commit_lookup_attempted = true
141
- @latest_resolvable_commit_with_unchanged_git_source ||=
142
- begin
143
- prepared_files = FilePreparer.new(
144
- dependency_files: dependency_files,
145
- dependency: dependency,
146
- unlock_requirement: false,
147
- remove_git_source: false,
148
- latest_allowable_version: latest_version
149
- ).prepared_dependency_files
150
-
151
- VersionResolver.new(
152
- dependency: dependency,
153
- dependency_files: prepared_files,
154
- credentials: credentials
155
- ).latest_resolvable_version
156
- end
157
- rescue SharedHelpers::HelperSubprocessFailed => error
158
- # This should rescue resolvability errors in future
159
- raise unless error.message.include?("Solving failure")
160
- end
161
-
162
- def latest_resolvable_released_version(unlock_requirement:)
163
- @latest_resolvable_released_version ||= {}
164
- @latest_resolvable_released_version[unlock_requirement] ||=
165
- begin
166
- prepared_files = FilePreparer.new(
167
- dependency_files: dependency_files,
168
- dependency: dependency,
169
- unlock_requirement: unlock_requirement,
170
- remove_git_source: git_dependency?,
171
- latest_allowable_version: latest_version
172
- ).prepared_dependency_files
173
-
174
- VersionResolver.new(
175
- dependency: dependency,
176
- dependency_files: prepared_files,
177
- credentials: credentials
178
- ).latest_resolvable_version
179
- end
180
- end
181
-
182
- def latest_git_tag_is_resolvable?
183
- return @git_tag_resolvable if @latest_git_tag_is_resolvable_checked
184
-
185
- @latest_git_tag_is_resolvable_checked = true
186
-
187
- return false if git_commit_checker.local_tag_for_latest_version.nil?
188
-
189
- replacement_tag = git_commit_checker.local_tag_for_latest_version
190
-
191
- prepared_files = FilePreparer.new(
192
- dependency: dependency,
193
- dependency_files: dependency_files,
194
- unlock_requirement: false,
195
- remove_git_source: false,
196
- replacement_git_pin: replacement_tag.fetch(:tag)
197
- ).prepared_dependency_files
198
-
199
- VersionResolver.new(
200
- dependency: dependency,
201
- dependency_files: prepared_files,
202
- credentials: credentials
203
- ).latest_resolvable_version
204
-
205
- @git_tag_resolvable = true
206
- rescue SharedHelpers::HelperSubprocessFailed => error
207
- # This should rescue resolvability errors in future
208
- raise unless error.message.include?("Solving failure")
209
-
210
- @git_tag_resolvable = false
211
- end
212
-
213
- def updated_source
214
- # Never need to update source, unless a git_dependency
215
- return dependency_source_details unless git_dependency?
216
-
217
- # Source becomes `nil` if switching to default rubygems
218
- return default_source if should_switch_source_from_ref_to_release?
219
-
220
- # Update the git tag if updating a pinned version
221
- if git_commit_checker.pinned_ref_looks_like_version? &&
222
- latest_git_tag_is_resolvable?
223
- new_tag = git_commit_checker.local_tag_for_latest_version
224
- return dependency_source_details.merge(ref: new_tag.fetch(:tag))
225
- end
226
-
227
- # Otherwise return the original source
228
- dependency_source_details
229
- end
230
-
231
- def dependency_source_details
232
- sources =
233
- dependency.requirements.map { |r| r.fetch(:source) }.uniq.compact
234
-
235
- raise "Multiple sources! #{sources.join(', ')}" if sources.count > 1
236
-
237
- sources.first
238
- end
239
-
240
- def should_switch_source_from_ref_to_release?
241
- return false unless git_dependency?
242
- return false if latest_resolvable_version_for_git_dependency.nil?
243
-
244
- Gem::Version.correct?(latest_resolvable_version_for_git_dependency)
245
- end
246
-
247
- def modules_dependency?
248
- # If dep is being used then we use that to determine the latest
249
- # version we can update to (since it will have resolvability
250
- # requirements, whereas Go modules won't)
251
- !dependency_in_gopkg_lock?
252
- end
253
-
254
- def dependency_in_gopkg_lock?
255
- lockfile = dependency_files.find { |f| f.name == "Gopkg.lock" }
256
- return false unless lockfile
257
-
258
- parsed_file(lockfile).fetch("projects", []).any? do |details|
259
- details.fetch("name") == dependency.name
260
- end
261
- end
262
-
263
- def git_dependency?
264
- git_commit_checker.git_dependency?
265
- end
266
-
267
- def default_source
268
- if modules_dependency?
269
- return { type: "default", source: dependency.name }
270
- end
271
-
272
- original_declaration =
273
- parsed_file(manifest).
274
- values_at(*FileParsers::Go::Dep::REQUIREMENT_TYPES).
275
- flatten.compact.
276
- find { |d| d["name"] == dependency.name }
277
-
278
- {
279
- type: "default",
280
- source:
281
- original_declaration&.fetch("source", nil) || dependency.name
282
- }
283
- end
284
-
285
- def git_branch_or_ref_in_release?(release)
286
- return false unless release
287
-
288
- git_commit_checker.branch_or_ref_in_release?(release)
289
- end
290
-
291
- def parsed_file(file)
292
- @parsed_file ||= {}
293
- @parsed_file[file.name] ||= TomlRB.parse(file.content)
294
- end
295
-
296
- def manifest
297
- @manifest ||= dependency_files.find { |f| f.name == "Gopkg.toml" }
298
- end
299
-
300
- def git_commit_checker
301
- @git_commit_checker ||=
302
- GitCommitChecker.new(
303
- dependency: dependency,
304
- credentials: credentials,
305
- ignored_versions: ignored_versions
306
- )
307
- end
308
- end
309
- end
310
- end
311
- end
@@ -1,221 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "toml-rb"
4
- require "dependabot/dependency_file"
5
- require "dependabot/file_parsers/go/dep"
6
- require "dependabot/update_checkers/go/dep"
7
-
8
- module Dependabot
9
- module UpdateCheckers
10
- module Go
11
- class Dep
12
- # This class takes a set of dependency files and prepares them for use
13
- # in UpdateCheckers::Go::Dep.
14
- class FilePreparer
15
- def initialize(dependency_files:, dependency:,
16
- remove_git_source: false,
17
- unlock_requirement: true,
18
- replacement_git_pin: nil,
19
- latest_allowable_version: nil)
20
- @dependency_files = dependency_files
21
- @dependency = dependency
22
- @unlock_requirement = unlock_requirement
23
- @remove_git_source = remove_git_source
24
- @replacement_git_pin = replacement_git_pin
25
- @latest_allowable_version = latest_allowable_version
26
- end
27
-
28
- def prepared_dependency_files
29
- files = []
30
-
31
- files << manifest_for_update_check
32
- files << lockfile if lockfile
33
-
34
- files
35
- end
36
-
37
- private
38
-
39
- attr_reader :dependency_files, :dependency, :replacement_git_pin,
40
- :latest_allowable_version
41
-
42
- def unlock_requirement?
43
- @unlock_requirement
44
- end
45
-
46
- def remove_git_source?
47
- @remove_git_source
48
- end
49
-
50
- def replace_git_pin?
51
- !replacement_git_pin.nil?
52
- end
53
-
54
- def manifest_for_update_check
55
- DependencyFile.new(
56
- name: manifest.name,
57
- content: manifest_content_for_update_check(manifest),
58
- directory: manifest.directory
59
- )
60
- end
61
-
62
- def manifest_content_for_update_check(file)
63
- content = file.content
64
-
65
- content = remove_git_source(content) if remove_git_source?
66
- content = replace_git_pin(content) if replace_git_pin?
67
- content = replace_version_constraint(content, file.name)
68
- content = add_fsnotify_override(content)
69
-
70
- content
71
- end
72
-
73
- def remove_git_source(content)
74
- parsed_manifest = TomlRB.parse(content)
75
-
76
- FileParsers::Go::Dep::REQUIREMENT_TYPES.each do |type|
77
- (parsed_manifest[type] || []).each do |details|
78
- next unless details["name"] == dependency.name
79
-
80
- details.delete("revision")
81
- details.delete("branch")
82
- end
83
- end
84
-
85
- TomlRB.dump(parsed_manifest)
86
- end
87
-
88
- def replace_git_pin(content)
89
- parsed_manifest = TomlRB.parse(content)
90
-
91
- FileParsers::Go::Dep::REQUIREMENT_TYPES.each do |type|
92
- (parsed_manifest[type] || []).each do |details|
93
- next unless details["name"] == dependency.name
94
-
95
- raise "Invalid details! #{details}" if details["branch"]
96
-
97
- if details["version"]
98
- details["version"] = replacement_git_pin
99
- else
100
- details["revision"] = replacement_git_pin
101
- end
102
- end
103
- end
104
-
105
- TomlRB.dump(parsed_manifest)
106
- end
107
-
108
- # Note: We don't need to care about formatting in this method, since
109
- # we're only using the manifest to find the latest resolvable version
110
- def replace_version_constraint(content, filename)
111
- parsed_manifest = TomlRB.parse(content)
112
-
113
- FileParsers::Go::Dep::REQUIREMENT_TYPES.each do |type|
114
- (parsed_manifest[type] || []).each do |details|
115
- next unless details["name"] == dependency.name
116
- next if details["revision"] || details["branch"]
117
- next if replacement_git_pin
118
-
119
- updated_req = temporary_requirement_for_resolution(filename)
120
-
121
- details["version"] = updated_req
122
- end
123
- end
124
-
125
- TomlRB.dump(parsed_manifest)
126
- end
127
-
128
- # A dep bug means we have to specify a source for gopkg.in/fsnotify.v1
129
- # or we get `panic: version queue is empty` errors
130
- def add_fsnotify_override(content)
131
- parsed_manifest = TomlRB.parse(content)
132
-
133
- overrides = parsed_manifest.fetch("override", [])
134
- dep_name = "gopkg.in/fsnotify.v1"
135
-
136
- override = overrides.find { |s| s["name"] == dep_name }
137
- if override.nil?
138
- override = { "name" => dep_name }
139
- overrides << override
140
- end
141
-
142
- unless override["source"]
143
- override["source"] = "gopkg.in/fsnotify/fsnotify.v1"
144
- end
145
-
146
- parsed_manifest["override"] = overrides
147
- TomlRB.dump(parsed_manifest)
148
- end
149
-
150
- def temporary_requirement_for_resolution(filename)
151
- original_req = dependency.requirements.
152
- find { |r| r.fetch(:file) == filename }&.
153
- fetch(:requirement)
154
-
155
- lower_bound_req =
156
- if original_req && !unlock_requirement?
157
- original_req
158
- else
159
- ">= #{lower_bound_version}"
160
- end
161
-
162
- unless latest_allowable_version &&
163
- version_class.correct?(latest_allowable_version) &&
164
- version_class.new(latest_allowable_version) >=
165
- version_class.new(lower_bound_version)
166
- return lower_bound_req
167
- end
168
-
169
- lower_bound_req + ", <= #{latest_allowable_version}"
170
- end
171
-
172
- def lower_bound_version
173
- @lower_bound_version ||=
174
- if version_from_lockfile
175
- version_from_lockfile
176
- else
177
- version_from_requirement =
178
- dependency.requirements.map { |r| r.fetch(:requirement) }.
179
- compact.
180
- flat_map { |req_str| requirement_class.new(req_str) }.
181
- flat_map(&:requirements).
182
- reject { |req_array| req_array.first.start_with?("<") }.
183
- map(&:last).
184
- max&.to_s
185
-
186
- version_from_requirement || 0
187
- end
188
- end
189
-
190
- def version_from_lockfile
191
- return unless lockfile
192
-
193
- TomlRB.parse(lockfile.content).
194
- fetch("projects", []).
195
- find { |p| p["name"] == dependency.name }&.
196
- fetch("version", nil)&.
197
- sub(/^v?/, "")
198
- end
199
-
200
- def version_class
201
- Utils.version_class_for_package_manager(dependency.package_manager)
202
- end
203
-
204
- def requirement_class
205
- Utils.requirement_class_for_package_manager(
206
- dependency.package_manager
207
- )
208
- end
209
-
210
- def manifest
211
- @manifest ||= dependency_files.find { |f| f.name == "Gopkg.toml" }
212
- end
213
-
214
- def lockfile
215
- @lockfile ||= dependency_files.find { |f| f.name == "Gopkg.lock" }
216
- end
217
- end
218
- end
219
- end
220
- end
221
- end