dependabot-bundler 0.95.5 → 0.95.6
Sign up to get free protection for your applications and to get access to all the features.
- 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,112 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "pathname"
|
4
|
-
require "parser/current"
|
5
|
-
require "dependabot/bundler/file_fetcher"
|
6
|
-
require "dependabot/errors"
|
7
|
-
|
8
|
-
module Dependabot
|
9
|
-
module Bundler
|
10
|
-
class FileFetcher
|
11
|
-
# Finds the paths of any gemspecs declared using `path: ` in the
|
12
|
-
# passed Gemfile.
|
13
|
-
class PathGemspecFinder
|
14
|
-
def initialize(gemfile:)
|
15
|
-
@gemfile = gemfile
|
16
|
-
end
|
17
|
-
|
18
|
-
def path_gemspec_paths
|
19
|
-
ast = Parser::CurrentRuby.parse(gemfile.content)
|
20
|
-
find_path_gemspec_paths(ast)
|
21
|
-
rescue Parser::SyntaxError
|
22
|
-
raise Dependabot::DependencyFileNotParseable, gemfile.path
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
attr_reader :gemfile
|
28
|
-
|
29
|
-
# rubocop:disable Security/Eval
|
30
|
-
def find_path_gemspec_paths(node)
|
31
|
-
return [] unless node.is_a?(Parser::AST::Node)
|
32
|
-
|
33
|
-
if declares_path_dependency?(node)
|
34
|
-
path_node = path_node_for_gem_declaration(node)
|
35
|
-
|
36
|
-
begin
|
37
|
-
# We use eval here, but we know what we're doing. The
|
38
|
-
# FileFetchers helper method should only ever be run in an
|
39
|
-
# isolated environment
|
40
|
-
path = eval(path_node.loc.expression.source)
|
41
|
-
rescue StandardError
|
42
|
-
return []
|
43
|
-
end
|
44
|
-
return [clean_path(path)]
|
45
|
-
end
|
46
|
-
|
47
|
-
relevant_child_nodes(node).flat_map do |child_node|
|
48
|
-
find_path_gemspec_paths(child_node)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
# rubocop:enable Security/Eval
|
52
|
-
|
53
|
-
def current_dir
|
54
|
-
@current_dir ||= gemfile.name.rpartition("/").first
|
55
|
-
@current_dir = nil if @current_dir == ""
|
56
|
-
@current_dir
|
57
|
-
end
|
58
|
-
|
59
|
-
def declares_path_dependency?(node)
|
60
|
-
return false unless node.is_a?(Parser::AST::Node)
|
61
|
-
return false unless node.children[1] == :gem
|
62
|
-
|
63
|
-
!path_node_for_gem_declaration(node).nil?
|
64
|
-
end
|
65
|
-
|
66
|
-
def clean_path(path)
|
67
|
-
if Pathname.new(path).absolute?
|
68
|
-
base_path = Pathname.new(File.expand_path(Dir.pwd))
|
69
|
-
path = Pathname.new(path).relative_path_from(base_path).to_s
|
70
|
-
end
|
71
|
-
path = File.join(current_dir, path) unless current_dir.nil?
|
72
|
-
Pathname.new(path).cleanpath
|
73
|
-
end
|
74
|
-
|
75
|
-
# rubocop:disable Security/Eval
|
76
|
-
def relevant_child_nodes(node)
|
77
|
-
return [] unless node.is_a?(Parser::AST::Node)
|
78
|
-
return node.children unless node.type == :if
|
79
|
-
|
80
|
-
begin
|
81
|
-
if eval(node.children.first.loc.expression.source)
|
82
|
-
[node.children[1]]
|
83
|
-
else
|
84
|
-
[node.children[2]]
|
85
|
-
end
|
86
|
-
rescue StandardError
|
87
|
-
return node.children
|
88
|
-
end
|
89
|
-
end
|
90
|
-
# rubocop:enable Security/Eval
|
91
|
-
|
92
|
-
def path_node_for_gem_declaration(node)
|
93
|
-
return unless node.children.last.type == :hash
|
94
|
-
|
95
|
-
kwargs_node = node.children.last
|
96
|
-
|
97
|
-
path_hash_pair =
|
98
|
-
kwargs_node.children.
|
99
|
-
find { |hash_pair| key_from_hash_pair(hash_pair) == :path }
|
100
|
-
|
101
|
-
return unless path_hash_pair
|
102
|
-
|
103
|
-
path_hash_pair.children.last
|
104
|
-
end
|
105
|
-
|
106
|
-
def key_from_hash_pair(node)
|
107
|
-
node.children.first.children.first.to_sym
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "pathname"
|
4
|
-
require "parser/current"
|
5
|
-
require "dependabot/bundler/file_fetcher"
|
6
|
-
require "dependabot/errors"
|
7
|
-
|
8
|
-
module Dependabot
|
9
|
-
module Bundler
|
10
|
-
class FileFetcher
|
11
|
-
# Finds the paths of any files included using `require_relative` in the
|
12
|
-
# passed file.
|
13
|
-
class RequireRelativeFinder
|
14
|
-
def initialize(file:)
|
15
|
-
@file = file
|
16
|
-
end
|
17
|
-
|
18
|
-
def require_relative_paths
|
19
|
-
ast = Parser::CurrentRuby.parse(file.content)
|
20
|
-
find_require_relative_paths(ast)
|
21
|
-
rescue Parser::SyntaxError
|
22
|
-
raise Dependabot::DependencyFileNotParseable, file.path
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
attr_reader :file
|
28
|
-
|
29
|
-
# rubocop:disable Security/Eval
|
30
|
-
def find_require_relative_paths(node)
|
31
|
-
return [] unless node.is_a?(Parser::AST::Node)
|
32
|
-
|
33
|
-
if declares_require_relative?(node)
|
34
|
-
# We use eval here, but we know what we're doing. The FileFetchers
|
35
|
-
# helper method should only ever be run in an isolated environment
|
36
|
-
source = node.children[2].loc.expression.source
|
37
|
-
begin
|
38
|
-
path = eval(source)
|
39
|
-
rescue StandardError
|
40
|
-
return []
|
41
|
-
end
|
42
|
-
|
43
|
-
path = File.join(current_dir, path) unless current_dir.nil?
|
44
|
-
return [Pathname.new(path + ".rb").cleanpath.to_path]
|
45
|
-
end
|
46
|
-
|
47
|
-
node.children.flat_map do |child_node|
|
48
|
-
find_require_relative_paths(child_node)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
# rubocop:enable Security/Eval
|
52
|
-
|
53
|
-
def current_dir
|
54
|
-
@current_dir ||= file.name.split("/")[0..-2].last
|
55
|
-
end
|
56
|
-
|
57
|
-
def declares_require_relative?(node)
|
58
|
-
return false unless node.is_a?(Parser::AST::Node)
|
59
|
-
|
60
|
-
node.children[1] == :require_relative
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,297 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "dependabot/dependency"
|
4
|
-
require "dependabot/file_parsers"
|
5
|
-
require "dependabot/file_parsers/base"
|
6
|
-
require "dependabot/bundler/file_updater/lockfile_updater"
|
7
|
-
require "dependabot/bundler/version"
|
8
|
-
require "dependabot/shared_helpers"
|
9
|
-
require "dependabot/errors"
|
10
|
-
|
11
|
-
module Dependabot
|
12
|
-
module Bundler
|
13
|
-
class FileParser < Dependabot::FileParsers::Base
|
14
|
-
require "dependabot/file_parsers/base/dependency_set"
|
15
|
-
require "dependabot/bundler/file_parser/file_preparer"
|
16
|
-
require "dependabot/bundler/file_parser/gemfile_checker"
|
17
|
-
|
18
|
-
def parse
|
19
|
-
dependency_set = DependencySet.new
|
20
|
-
dependency_set += gemfile_dependencies
|
21
|
-
dependency_set += gemspec_dependencies
|
22
|
-
dependency_set += lockfile_dependencies
|
23
|
-
dependency_set.dependencies
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
# Can't be a constant because some of these don't exist in bundler
|
29
|
-
# 1.15, which Heroku uses, which causes an exception on boot.
|
30
|
-
def sources
|
31
|
-
[
|
32
|
-
NilClass,
|
33
|
-
::Bundler::Source::Rubygems,
|
34
|
-
::Bundler::Source::Git,
|
35
|
-
::Bundler::Source::Path,
|
36
|
-
::Bundler::Source::Gemspec,
|
37
|
-
::Bundler::Source::Metadata
|
38
|
-
]
|
39
|
-
end
|
40
|
-
|
41
|
-
def gemfile_dependencies
|
42
|
-
dependencies = DependencySet.new
|
43
|
-
|
44
|
-
return dependencies unless gemfile
|
45
|
-
|
46
|
-
[gemfile, *evaled_gemfiles].each do |file|
|
47
|
-
parsed_gemfile.each do |dep|
|
48
|
-
next unless dependency_in_gemfile?(gemfile: file, dependency: dep)
|
49
|
-
|
50
|
-
dependencies <<
|
51
|
-
Dependency.new(
|
52
|
-
name: dep.name,
|
53
|
-
version: dependency_version(dep.name)&.to_s,
|
54
|
-
requirements: [{
|
55
|
-
requirement: dep.requirement.to_s,
|
56
|
-
groups: dep.groups,
|
57
|
-
source: source_for(dep),
|
58
|
-
file: file.name
|
59
|
-
}],
|
60
|
-
package_manager: "bundler"
|
61
|
-
)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
dependencies
|
66
|
-
end
|
67
|
-
|
68
|
-
def gemspec_dependencies
|
69
|
-
dependencies = DependencySet.new
|
70
|
-
|
71
|
-
gemspecs.each do |gemspec|
|
72
|
-
parsed_gemspec(gemspec).dependencies.each do |dependency|
|
73
|
-
dependencies <<
|
74
|
-
Dependency.new(
|
75
|
-
name: dependency.name,
|
76
|
-
version: dependency_version(dependency.name)&.to_s,
|
77
|
-
requirements: [{
|
78
|
-
requirement: dependency.requirement.to_s,
|
79
|
-
groups: dependency.runtime? ? ["runtime"] : ["development"],
|
80
|
-
source: nil,
|
81
|
-
file: gemspec.name
|
82
|
-
}],
|
83
|
-
package_manager: "bundler"
|
84
|
-
)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
dependencies
|
89
|
-
end
|
90
|
-
|
91
|
-
def lockfile_dependencies
|
92
|
-
dependencies = DependencySet.new
|
93
|
-
|
94
|
-
return dependencies unless lockfile
|
95
|
-
|
96
|
-
# Create a DependencySet where each element has no requirement. Any
|
97
|
-
# requirements will be added when combining the DependencySet with
|
98
|
-
# other DependencySets.
|
99
|
-
parsed_lockfile.specs.each do |dependency|
|
100
|
-
next if dependency.source.is_a?(::Bundler::Source::Path)
|
101
|
-
|
102
|
-
dependencies <<
|
103
|
-
Dependency.new(
|
104
|
-
name: dependency.name,
|
105
|
-
version: dependency_version(dependency.name)&.to_s,
|
106
|
-
requirements: [],
|
107
|
-
package_manager: "bundler"
|
108
|
-
)
|
109
|
-
end
|
110
|
-
|
111
|
-
dependencies
|
112
|
-
end
|
113
|
-
|
114
|
-
def parsed_gemfile
|
115
|
-
base_directory = dependency_files.first.directory
|
116
|
-
@parsed_gemfile ||=
|
117
|
-
SharedHelpers.in_a_temporary_directory(base_directory) do
|
118
|
-
write_temporary_dependency_files
|
119
|
-
|
120
|
-
SharedHelpers.in_a_forked_process do
|
121
|
-
::Bundler.instance_variable_set(:@root, Pathname.new(Dir.pwd))
|
122
|
-
|
123
|
-
::Bundler::Definition.build(gemfile.name, nil, {}).
|
124
|
-
dependencies.
|
125
|
-
select(&:current_platform?).
|
126
|
-
# We can't dump gemspec sources, and we wouldn't bump them
|
127
|
-
# anyway, so we filter them out.
|
128
|
-
reject { |dep| dep.source.is_a?(::Bundler::Source::Gemspec) }
|
129
|
-
end
|
130
|
-
end
|
131
|
-
rescue SharedHelpers::ChildProcessFailed => error
|
132
|
-
msg = error.error_class + " with message: " +
|
133
|
-
error.error_message.force_encoding("UTF-8").encode
|
134
|
-
raise Dependabot::DependencyFileNotEvaluatable, msg
|
135
|
-
end
|
136
|
-
|
137
|
-
def parsed_gemspec(file)
|
138
|
-
@parsed_gemspecs ||= {}
|
139
|
-
@parsed_gemspecs[file.name] ||=
|
140
|
-
SharedHelpers.in_a_temporary_directory do
|
141
|
-
[file, *imported_ruby_files].each do |f|
|
142
|
-
path = f.name
|
143
|
-
FileUtils.mkdir_p(Pathname.new(path).dirname)
|
144
|
-
File.write(path, f.content)
|
145
|
-
end
|
146
|
-
|
147
|
-
SharedHelpers.in_a_forked_process do
|
148
|
-
::Bundler.instance_variable_set(:@root, Pathname.new(Dir.pwd))
|
149
|
-
::Bundler.load_gemspec_uncached(file.name)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
rescue SharedHelpers::ChildProcessFailed => error
|
153
|
-
msg = error.error_class + " with message: " + error.error_message
|
154
|
-
raise Dependabot::DependencyFileNotEvaluatable, msg
|
155
|
-
end
|
156
|
-
|
157
|
-
def prepared_dependency_files
|
158
|
-
@prepared_dependency_files ||=
|
159
|
-
FilePreparer.new(dependency_files: dependency_files).
|
160
|
-
prepared_dependency_files
|
161
|
-
end
|
162
|
-
|
163
|
-
def write_temporary_dependency_files
|
164
|
-
prepared_dependency_files.each do |file|
|
165
|
-
path = file.name
|
166
|
-
FileUtils.mkdir_p(Pathname.new(path).dirname)
|
167
|
-
File.write(path, file.content)
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
def check_required_files
|
172
|
-
file_names = dependency_files.map(&:name)
|
173
|
-
|
174
|
-
return if file_names.any? do |name|
|
175
|
-
name.end_with?(".gemspec") && !name.include?("/")
|
176
|
-
end
|
177
|
-
|
178
|
-
return if gemfile
|
179
|
-
|
180
|
-
raise "A gemspec or Gemfile must be provided!"
|
181
|
-
end
|
182
|
-
|
183
|
-
def source_for(dependency)
|
184
|
-
source = dependency.source
|
185
|
-
if lockfile && default_rubygems?(source)
|
186
|
-
# If there's a lockfile and the Gemfile doesn't have anything
|
187
|
-
# interesting to say about the source, check that.
|
188
|
-
source = source_from_lockfile(dependency.name)
|
189
|
-
end
|
190
|
-
raise "Bad source: #{source}" unless sources.include?(source.class)
|
191
|
-
|
192
|
-
return nil if default_rubygems?(source)
|
193
|
-
|
194
|
-
details = { type: source.class.name.split("::").last.downcase }
|
195
|
-
if source.is_a?(::Bundler::Source::Git)
|
196
|
-
details.merge!(git_source_details(source))
|
197
|
-
end
|
198
|
-
if source.is_a?(::Bundler::Source::Rubygems)
|
199
|
-
details[:url] = source.remotes.first.to_s
|
200
|
-
end
|
201
|
-
details
|
202
|
-
end
|
203
|
-
|
204
|
-
def git_source_details(source)
|
205
|
-
{
|
206
|
-
url: source.uri,
|
207
|
-
branch: source.branch || "master",
|
208
|
-
ref: source.ref
|
209
|
-
}
|
210
|
-
end
|
211
|
-
|
212
|
-
def default_rubygems?(source)
|
213
|
-
return true if source.nil?
|
214
|
-
return false unless source.is_a?(::Bundler::Source::Rubygems)
|
215
|
-
|
216
|
-
source.remotes.any? { |r| r.to_s.include?("rubygems.org") }
|
217
|
-
end
|
218
|
-
|
219
|
-
def dependency_version(dependency_name)
|
220
|
-
return unless lockfile
|
221
|
-
|
222
|
-
spec = parsed_lockfile.specs.find { |s| s.name == dependency_name }
|
223
|
-
|
224
|
-
# Not all files in the Gemfile will appear in the Gemfile.lock. For
|
225
|
-
# instance, if a gem specifies `platform: [:windows]`, and the
|
226
|
-
# Gemfile.lock is generated on a Linux machine, the gem will be not
|
227
|
-
# appear in the lockfile.
|
228
|
-
return unless spec
|
229
|
-
|
230
|
-
# If the source is Git we're better off knowing the SHA-1 than the
|
231
|
-
# version.
|
232
|
-
if spec.source.instance_of?(::Bundler::Source::Git)
|
233
|
-
return spec.source.revision
|
234
|
-
end
|
235
|
-
|
236
|
-
spec.version
|
237
|
-
end
|
238
|
-
|
239
|
-
def source_from_lockfile(dependency_name)
|
240
|
-
parsed_lockfile.specs.find { |s| s.name == dependency_name }&.source
|
241
|
-
end
|
242
|
-
|
243
|
-
def dependency_in_gemfile?(gemfile:, dependency:)
|
244
|
-
GemfileChecker.new(
|
245
|
-
dependency: dependency,
|
246
|
-
gemfile: gemfile
|
247
|
-
).includes_dependency?
|
248
|
-
end
|
249
|
-
|
250
|
-
def gemfile
|
251
|
-
@gemfile ||= get_original_file("Gemfile") ||
|
252
|
-
get_original_file("gems.rb")
|
253
|
-
end
|
254
|
-
|
255
|
-
def evaled_gemfiles
|
256
|
-
dependency_files.
|
257
|
-
reject { |f| f.name.end_with?(".gemspec") }.
|
258
|
-
reject { |f| f.name.end_with?(".lock") }.
|
259
|
-
reject { |f| f.name.end_with?(".ruby-version") }.
|
260
|
-
reject { |f| f.name == "Gemfile" }.
|
261
|
-
reject { |f| f.name == "gems.rb" }.
|
262
|
-
reject { |f| f.name == "gems.locked" }
|
263
|
-
end
|
264
|
-
|
265
|
-
def lockfile
|
266
|
-
@lockfile ||= get_original_file("Gemfile.lock") ||
|
267
|
-
get_original_file("gems.locked")
|
268
|
-
end
|
269
|
-
|
270
|
-
def parsed_lockfile
|
271
|
-
@parsed_lockfile ||=
|
272
|
-
::Bundler::LockfileParser.new(sanitized_lockfile_content)
|
273
|
-
end
|
274
|
-
|
275
|
-
def sanitized_lockfile_content
|
276
|
-
regex = FileUpdater::LockfileUpdater::LOCKFILE_ENDING
|
277
|
-
lockfile.content.gsub(regex, "")
|
278
|
-
end
|
279
|
-
|
280
|
-
def gemspecs
|
281
|
-
# Path gemspecs are excluded (they're supporting files)
|
282
|
-
@gemspecs ||= prepared_dependency_files.
|
283
|
-
select { |file| file.name.end_with?(".gemspec") }.
|
284
|
-
reject(&:support_file?)
|
285
|
-
end
|
286
|
-
|
287
|
-
def imported_ruby_files
|
288
|
-
dependency_files.
|
289
|
-
select { |f| f.name.end_with?(".rb") }.
|
290
|
-
reject { |f| f.name == "gems.rb" }
|
291
|
-
end
|
292
|
-
end
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
Dependabot::FileParsers.
|
297
|
-
register("bundler", Dependabot::Bundler::FileParser)
|