dependabot-bundler 0.95.5 → 0.95.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- metadata +4 -38
- data/helpers/Makefile +0 -9
- data/helpers/build +0 -26
- data/lib/dependabot/bundler.rb +0 -27
- data/lib/dependabot/bundler/file_fetcher.rb +0 -216
- data/lib/dependabot/bundler/file_fetcher/child_gemfile_finder.rb +0 -68
- data/lib/dependabot/bundler/file_fetcher/gemspec_finder.rb +0 -96
- data/lib/dependabot/bundler/file_fetcher/path_gemspec_finder.rb +0 -112
- data/lib/dependabot/bundler/file_fetcher/require_relative_finder.rb +0 -65
- data/lib/dependabot/bundler/file_parser.rb +0 -297
- data/lib/dependabot/bundler/file_parser/file_preparer.rb +0 -84
- data/lib/dependabot/bundler/file_parser/gemfile_checker.rb +0 -46
- data/lib/dependabot/bundler/file_updater.rb +0 -125
- data/lib/dependabot/bundler/file_updater/gemfile_updater.rb +0 -114
- data/lib/dependabot/bundler/file_updater/gemspec_dependency_name_finder.rb +0 -50
- data/lib/dependabot/bundler/file_updater/gemspec_sanitizer.rb +0 -298
- data/lib/dependabot/bundler/file_updater/gemspec_updater.rb +0 -62
- data/lib/dependabot/bundler/file_updater/git_pin_replacer.rb +0 -78
- data/lib/dependabot/bundler/file_updater/git_source_remover.rb +0 -100
- data/lib/dependabot/bundler/file_updater/lockfile_updater.rb +0 -387
- data/lib/dependabot/bundler/file_updater/requirement_replacer.rb +0 -221
- data/lib/dependabot/bundler/metadata_finder.rb +0 -204
- data/lib/dependabot/bundler/requirement.rb +0 -29
- data/lib/dependabot/bundler/update_checker.rb +0 -334
- data/lib/dependabot/bundler/update_checker/file_preparer.rb +0 -279
- data/lib/dependabot/bundler/update_checker/force_updater.rb +0 -259
- data/lib/dependabot/bundler/update_checker/latest_version_finder.rb +0 -165
- data/lib/dependabot/bundler/update_checker/requirements_updater.rb +0 -281
- data/lib/dependabot/bundler/update_checker/ruby_requirement_setter.rb +0 -113
- data/lib/dependabot/bundler/update_checker/shared_bundler_helpers.rb +0 -244
- data/lib/dependabot/bundler/update_checker/version_resolver.rb +0 -272
- data/lib/dependabot/bundler/version.rb +0 -13
- data/lib/dependabot/monkey_patches/bundler/definition_bundler_version_patch.rb +0 -15
- data/lib/dependabot/monkey_patches/bundler/definition_ruby_version_patch.rb +0 -14
- data/lib/dependabot/monkey_patches/bundler/git_source_patch.rb +0 -27
@@ -1,221 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "parser/current"
|
4
|
-
require "dependabot/bundler/file_updater"
|
5
|
-
|
6
|
-
module Dependabot
|
7
|
-
module Bundler
|
8
|
-
class FileUpdater
|
9
|
-
class RequirementReplacer
|
10
|
-
attr_reader :dependency, :file_type, :updated_requirement,
|
11
|
-
:previous_requirement
|
12
|
-
|
13
|
-
def initialize(dependency:, file_type:, updated_requirement:,
|
14
|
-
previous_requirement: nil, insert_if_bare: false)
|
15
|
-
@dependency = dependency
|
16
|
-
@file_type = file_type
|
17
|
-
@updated_requirement = updated_requirement
|
18
|
-
@previous_requirement = previous_requirement
|
19
|
-
@insert_if_bare = insert_if_bare
|
20
|
-
end
|
21
|
-
|
22
|
-
def rewrite(content)
|
23
|
-
buffer = Parser::Source::Buffer.new("(gemfile_content)")
|
24
|
-
buffer.source = content
|
25
|
-
ast = Parser::CurrentRuby.new.parse(buffer)
|
26
|
-
|
27
|
-
updated_content = Rewriter.new(
|
28
|
-
dependency: dependency,
|
29
|
-
file_type: file_type,
|
30
|
-
updated_requirement: updated_requirement,
|
31
|
-
insert_if_bare: insert_if_bare?
|
32
|
-
).rewrite(buffer, ast)
|
33
|
-
|
34
|
-
update_comment_spacing_if_required(content, updated_content)
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def insert_if_bare?
|
40
|
-
@insert_if_bare
|
41
|
-
end
|
42
|
-
|
43
|
-
def update_comment_spacing_if_required(content, updated_content)
|
44
|
-
return updated_content unless previous_requirement
|
45
|
-
|
46
|
-
return updated_content if updated_content == content
|
47
|
-
return updated_content if length_change.zero?
|
48
|
-
|
49
|
-
updated_lines = updated_content.lines
|
50
|
-
updated_line_index =
|
51
|
-
updated_lines.length.
|
52
|
-
times.find { |i| content.lines[i] != updated_content.lines[i] }
|
53
|
-
updated_line = updated_lines[updated_line_index]
|
54
|
-
|
55
|
-
updated_line =
|
56
|
-
if length_change.positive?
|
57
|
-
updated_line.sub(/(?<=\s)\s{#{length_change}}#/, "#")
|
58
|
-
elsif length_change.negative?
|
59
|
-
updated_line.sub(/(?<=\s{2})#/, " " * length_change.abs + "#")
|
60
|
-
end
|
61
|
-
|
62
|
-
updated_lines[updated_line_index] = updated_line
|
63
|
-
updated_lines.join
|
64
|
-
end
|
65
|
-
|
66
|
-
def length_change
|
67
|
-
unless previous_requirement.start_with?("=")
|
68
|
-
return updated_requirement.length - previous_requirement.length
|
69
|
-
end
|
70
|
-
|
71
|
-
updated_requirement.length -
|
72
|
-
previous_requirement.gsub(/^=/, "").strip.length
|
73
|
-
end
|
74
|
-
|
75
|
-
class Rewriter < Parser::TreeRewriter
|
76
|
-
# TODO: Ideally we wouldn't have to ignore all of these, but
|
77
|
-
# implementing each one will be tricky.
|
78
|
-
SKIPPED_TYPES = %i(send lvar dstr begin if splat const).freeze
|
79
|
-
|
80
|
-
def initialize(dependency:, file_type:, updated_requirement:,
|
81
|
-
insert_if_bare:)
|
82
|
-
@dependency = dependency
|
83
|
-
@file_type = file_type
|
84
|
-
@updated_requirement = updated_requirement
|
85
|
-
@insert_if_bare = insert_if_bare
|
86
|
-
|
87
|
-
return if %i(gemfile gemspec).include?(file_type)
|
88
|
-
|
89
|
-
raise "File type must be :gemfile or :gemspec. Got #{file_type}."
|
90
|
-
end
|
91
|
-
|
92
|
-
def on_send(node)
|
93
|
-
return unless declares_targeted_gem?(node)
|
94
|
-
|
95
|
-
req_nodes = node.children[3..-1]
|
96
|
-
req_nodes = req_nodes.reject { |child| child.type == :hash }
|
97
|
-
|
98
|
-
return if req_nodes.none? && !insert_if_bare?
|
99
|
-
return if req_nodes.any? { |n| SKIPPED_TYPES.include?(n.type) }
|
100
|
-
|
101
|
-
quote_characters = extract_quote_characters_from(req_nodes)
|
102
|
-
space_after_specifier = space_after_specifier?(req_nodes)
|
103
|
-
use_equality_operator = use_equality_operator?(req_nodes)
|
104
|
-
|
105
|
-
new_req = new_requirement_string(
|
106
|
-
quote_characters: quote_characters,
|
107
|
-
space_after_specifier: space_after_specifier,
|
108
|
-
use_equality_operator: use_equality_operator
|
109
|
-
)
|
110
|
-
if req_nodes.any?
|
111
|
-
replace(range_for(req_nodes), new_req)
|
112
|
-
else
|
113
|
-
insert_after(range_for(node.children[2..2]), ", #{new_req}")
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
private
|
118
|
-
|
119
|
-
attr_reader :dependency, :file_type, :updated_requirement
|
120
|
-
|
121
|
-
def insert_if_bare?
|
122
|
-
@insert_if_bare
|
123
|
-
end
|
124
|
-
|
125
|
-
def declaration_methods
|
126
|
-
return %i(gem) if file_type == :gemfile
|
127
|
-
|
128
|
-
%i(add_dependency add_runtime_dependency
|
129
|
-
add_development_dependency)
|
130
|
-
end
|
131
|
-
|
132
|
-
def declares_targeted_gem?(node)
|
133
|
-
return false unless declaration_methods.include?(node.children[1])
|
134
|
-
|
135
|
-
node.children[2].children.first == dependency.name
|
136
|
-
end
|
137
|
-
|
138
|
-
def extract_quote_characters_from(requirement_nodes)
|
139
|
-
return ['"', '"'] if requirement_nodes.none?
|
140
|
-
|
141
|
-
case requirement_nodes.first.type
|
142
|
-
when :str, :dstr
|
143
|
-
[
|
144
|
-
requirement_nodes.first.loc.begin.source,
|
145
|
-
requirement_nodes.first.loc.end.source
|
146
|
-
]
|
147
|
-
else
|
148
|
-
[
|
149
|
-
requirement_nodes.first.children.first.loc.begin.source,
|
150
|
-
requirement_nodes.first.children.first.loc.end.source
|
151
|
-
]
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def space_after_specifier?(requirement_nodes)
|
156
|
-
return true if requirement_nodes.none?
|
157
|
-
|
158
|
-
req_string =
|
159
|
-
case requirement_nodes.first.type
|
160
|
-
when :str, :dstr
|
161
|
-
requirement_nodes.first.loc.expression.source
|
162
|
-
else
|
163
|
-
requirement_nodes.first.children.first.loc.expression.source
|
164
|
-
end
|
165
|
-
|
166
|
-
ops = Gem::Requirement::OPS.keys
|
167
|
-
return true if ops.none? { |op| req_string.include?(op) }
|
168
|
-
|
169
|
-
req_string.include?(" ")
|
170
|
-
end
|
171
|
-
|
172
|
-
def use_equality_operator?(requirement_nodes)
|
173
|
-
return true if requirement_nodes.none?
|
174
|
-
|
175
|
-
req_string =
|
176
|
-
case requirement_nodes.first.type
|
177
|
-
when :str, :dstr
|
178
|
-
requirement_nodes.first.loc.expression.source
|
179
|
-
else
|
180
|
-
requirement_nodes.first.children.first.loc.expression.source
|
181
|
-
end
|
182
|
-
|
183
|
-
req_string.match?(/(?<![<>])=/)
|
184
|
-
end
|
185
|
-
|
186
|
-
def new_requirement_string(quote_characters:,
|
187
|
-
space_after_specifier:,
|
188
|
-
use_equality_operator:)
|
189
|
-
open_quote, close_quote = quote_characters
|
190
|
-
new_requirement_string =
|
191
|
-
updated_requirement.split(",").
|
192
|
-
map do |r|
|
193
|
-
req_string = serialized_req(r, use_equality_operator)
|
194
|
-
%(#{open_quote}#{req_string}#{close_quote})
|
195
|
-
end.join(", ")
|
196
|
-
|
197
|
-
new_requirement_string.delete!(" ") unless space_after_specifier
|
198
|
-
new_requirement_string
|
199
|
-
end
|
200
|
-
|
201
|
-
def serialized_req(req, use_equality_operator)
|
202
|
-
tmp_req = req
|
203
|
-
|
204
|
-
# Gem::Requirement serializes exact matches as a string starting
|
205
|
-
# with `=`. We may need to remove that equality operator if it
|
206
|
-
# wasn't used originally.
|
207
|
-
unless use_equality_operator
|
208
|
-
tmp_req = tmp_req.gsub(/(?<![<>])=/, "")
|
209
|
-
end
|
210
|
-
|
211
|
-
tmp_req.strip
|
212
|
-
end
|
213
|
-
|
214
|
-
def range_for(nodes)
|
215
|
-
nodes.first.loc.begin.begin.join(nodes.last.loc.expression)
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
@@ -1,204 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "excon"
|
4
|
-
require "dependabot/metadata_finders"
|
5
|
-
require "dependabot/metadata_finders/base"
|
6
|
-
|
7
|
-
module Dependabot
|
8
|
-
module Bundler
|
9
|
-
class MetadataFinder < Dependabot::MetadataFinders::Base
|
10
|
-
SOURCE_KEYS = %w(
|
11
|
-
source_code_uri
|
12
|
-
homepage_uri
|
13
|
-
wiki_uri
|
14
|
-
bug_tracker_uri
|
15
|
-
documentation_uri
|
16
|
-
changelog_uri
|
17
|
-
mailing_list_uri
|
18
|
-
download_uri
|
19
|
-
).freeze
|
20
|
-
|
21
|
-
def homepage_url
|
22
|
-
return super unless %w(default rubygems).include?(new_source_type)
|
23
|
-
return super unless rubygems_api_response["homepage_uri"]
|
24
|
-
|
25
|
-
rubygems_api_response["homepage_uri"]
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def look_up_source
|
31
|
-
case new_source_type
|
32
|
-
when "git" then find_source_from_git_url
|
33
|
-
when "default", "rubygems" then find_source_from_rubygems
|
34
|
-
else raise "Unexpected source type: #{new_source_type}"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def new_source_type
|
39
|
-
sources =
|
40
|
-
dependency.requirements.map { |r| r.fetch(:source) }.uniq.compact
|
41
|
-
|
42
|
-
return "default" if sources.empty?
|
43
|
-
raise "Multiple sources! #{sources.join(', ')}" if sources.count > 1
|
44
|
-
|
45
|
-
sources.first[:type] || sources.first.fetch("type")
|
46
|
-
end
|
47
|
-
|
48
|
-
def find_source_from_rubygems
|
49
|
-
api_source = find_source_from_rubygems_api_response
|
50
|
-
return api_source if api_source || new_source_type == "default"
|
51
|
-
|
52
|
-
find_source_from_gemspec_download
|
53
|
-
end
|
54
|
-
|
55
|
-
def find_source_from_rubygems_api_response
|
56
|
-
source_url = rubygems_api_response.
|
57
|
-
values_at(*SOURCE_KEYS).
|
58
|
-
compact.
|
59
|
-
find { |url| Source.from_url(url) }
|
60
|
-
|
61
|
-
Source.from_url(source_url)
|
62
|
-
end
|
63
|
-
|
64
|
-
def find_source_from_git_url
|
65
|
-
info = dependency.requirements.map { |r| r[:source] }.compact.first
|
66
|
-
|
67
|
-
url = info[:url] || info.fetch("url")
|
68
|
-
Source.from_url(url)
|
69
|
-
end
|
70
|
-
|
71
|
-
def find_source_from_gemspec_download
|
72
|
-
github_urls = []
|
73
|
-
return unless rubygems_marshalled_gemspec_response
|
74
|
-
|
75
|
-
rubygems_marshalled_gemspec_response.scan(Source::SOURCE_REGEX) do
|
76
|
-
github_urls << Regexp.last_match.to_s
|
77
|
-
end
|
78
|
-
|
79
|
-
source_url = github_urls.find do |url|
|
80
|
-
repo = Source.from_url(url).repo
|
81
|
-
repo.downcase.end_with?(dependency.name)
|
82
|
-
end
|
83
|
-
return unless source_url
|
84
|
-
|
85
|
-
Source.from_url(source_url)
|
86
|
-
end
|
87
|
-
|
88
|
-
# Note: This response MUST NOT be unmarshalled
|
89
|
-
# (as calling Marshal.load is unsafe)
|
90
|
-
def rubygems_marshalled_gemspec_response
|
91
|
-
if defined?(@rubygems_marshalled_gemspec_response)
|
92
|
-
return @rubygems_marshalled_gemspec_response
|
93
|
-
end
|
94
|
-
|
95
|
-
gemspec_uri =
|
96
|
-
"#{registry_url}quick/Marshal.4.8/"\
|
97
|
-
"#{dependency.name}-#{dependency.version}.gemspec.rz"
|
98
|
-
|
99
|
-
response =
|
100
|
-
Excon.get(
|
101
|
-
gemspec_uri,
|
102
|
-
headers: registry_auth_headers,
|
103
|
-
idempotent: true,
|
104
|
-
**SharedHelpers.excon_defaults
|
105
|
-
)
|
106
|
-
|
107
|
-
if response.status >= 400
|
108
|
-
return @rubygems_marshalled_gemspec_response = nil
|
109
|
-
end
|
110
|
-
|
111
|
-
@rubygems_marshalled_gemspec_response =
|
112
|
-
Zlib::Inflate.inflate(response.body)
|
113
|
-
rescue Zlib::DataError
|
114
|
-
@rubygems_marshalled_gemspec_response = nil
|
115
|
-
end
|
116
|
-
|
117
|
-
def rubygems_api_response
|
118
|
-
return @rubygems_api_response if defined?(@rubygems_api_response)
|
119
|
-
|
120
|
-
response =
|
121
|
-
Excon.get(
|
122
|
-
"#{registry_url}api/v1/gems/#{dependency.name}.json",
|
123
|
-
headers: registry_auth_headers,
|
124
|
-
idempotent: true,
|
125
|
-
**SharedHelpers.excon_defaults
|
126
|
-
)
|
127
|
-
return @rubygems_api_response = {} if response.status >= 400
|
128
|
-
|
129
|
-
response_body = response.body
|
130
|
-
response_body = augment_private_response_if_appropriate(response_body)
|
131
|
-
|
132
|
-
@rubygems_api_response = JSON.parse(response_body)
|
133
|
-
append_slash_to_source_code_uri(@rubygems_api_response)
|
134
|
-
rescue JSON::ParserError, Excon::Error::Timeout
|
135
|
-
@rubygems_api_response = {}
|
136
|
-
end
|
137
|
-
|
138
|
-
def append_slash_to_source_code_uri(listing)
|
139
|
-
# We have to do this so that `Source.from_url(...)` doesn't prune the
|
140
|
-
# last line off of the directory.
|
141
|
-
return listing unless listing&.fetch("source_code_uri", nil)
|
142
|
-
return listing if listing.fetch("source_code_uri").end_with?("/")
|
143
|
-
|
144
|
-
listing["source_code_uri"] = listing["source_code_uri"] + "/"
|
145
|
-
listing
|
146
|
-
end
|
147
|
-
|
148
|
-
def augment_private_response_if_appropriate(response_body)
|
149
|
-
return response_body if new_source_type == "default"
|
150
|
-
|
151
|
-
parsed_body = JSON.parse(response_body)
|
152
|
-
return response_body if (SOURCE_KEYS - parsed_body.keys).none?
|
153
|
-
|
154
|
-
digest = parsed_body.values_at("version", "authors", "info").hash
|
155
|
-
|
156
|
-
source_url = parsed_body.
|
157
|
-
values_at(*SOURCE_KEYS).
|
158
|
-
compact.
|
159
|
-
find { |url| Source.from_url(url) }
|
160
|
-
return response_body if source_url
|
161
|
-
|
162
|
-
rubygems_response =
|
163
|
-
Excon.get(
|
164
|
-
"https://rubygems.org/api/v1/gems/#{dependency.name}.json",
|
165
|
-
idempotent: true,
|
166
|
-
**SharedHelpers.excon_defaults
|
167
|
-
)
|
168
|
-
parsed_rubygems_body = JSON.parse(rubygems_response.body)
|
169
|
-
rubygems_digest =
|
170
|
-
parsed_rubygems_body.values_at("version", "authors", "info").hash
|
171
|
-
|
172
|
-
digest == rubygems_digest ? rubygems_response.body : response_body
|
173
|
-
rescue JSON::ParserError, Excon::Error::Socket, Excon::Error::Timeout
|
174
|
-
response_body
|
175
|
-
end
|
176
|
-
|
177
|
-
def registry_url
|
178
|
-
return "https://rubygems.org/" if new_source_type == "default"
|
179
|
-
|
180
|
-
info = dependency.requirements.map { |r| r[:source] }.compact.first
|
181
|
-
info[:url] || info.fetch("url")
|
182
|
-
end
|
183
|
-
|
184
|
-
def registry_auth_headers
|
185
|
-
return {} unless new_source_type == "rubygems"
|
186
|
-
|
187
|
-
token =
|
188
|
-
credentials.
|
189
|
-
select { |cred| cred["type"] == "rubygems_server" }.
|
190
|
-
find { |cred| registry_url.include?(cred["host"]) }&.
|
191
|
-
fetch("token")
|
192
|
-
|
193
|
-
return {} unless token
|
194
|
-
|
195
|
-
token += ":" unless token.include?(":")
|
196
|
-
encoded_token = Base64.encode64(token).delete("\n")
|
197
|
-
{ "Authorization" => "Basic #{encoded_token}" }
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
Dependabot::MetadataFinders.
|
204
|
-
register("bundler", Dependabot::Bundler::MetadataFinder)
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "dependabot/utils"
|
4
|
-
|
5
|
-
module Dependabot
|
6
|
-
module Bundler
|
7
|
-
class Requirement < Gem::Requirement
|
8
|
-
# For consistency with other langauges, we define a requirements array.
|
9
|
-
# Ruby doesn't have an `OR` separator for requirements, so it always
|
10
|
-
# contains a single element.
|
11
|
-
def self.requirements_array(requirement_string)
|
12
|
-
[new(requirement_string)]
|
13
|
-
end
|
14
|
-
|
15
|
-
# Patches Gem::Requirement to make it accept requirement strings like
|
16
|
-
# "~> 4.2.5, >= 4.2.5.1" without first needing to split them.
|
17
|
-
def initialize(*requirements)
|
18
|
-
requirements = requirements.flatten.flat_map do |req_string|
|
19
|
-
req_string.split(",")
|
20
|
-
end
|
21
|
-
|
22
|
-
super(requirements)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
Dependabot::Utils.
|
29
|
-
register_requirement_class("bundler", Dependabot::Bundler::Requirement)
|