dependabot-bundler 0.263.0 → 0.264.0
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dcc0bc531e33ee50374a4f53b0e72e3522ad9b2b9c0b5470b047f6a72933446f
|
|
4
|
+
data.tar.gz: 91ec4898f9462acc61fa9204e1ae198f454cd9d2a325026d53d451d4d903cbf5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 80c13a67225b597da16fa1925a71eb2a0dd8b423205c68261ec52b93b17bf600b0c3b7a1a958b18fb01ba82dc83d66ecc850545a597aeb0b62d9d7653af468ac
|
|
7
|
+
data.tar.gz: 5a636844b3dbc57420f47ac32b6922634c92a139de00e204c5df7ecb48c3d577a233c4e1a33c09e42ef5a46e45ff9c45e3aeecb74c2983429548c6d64466ffb2
|
|
@@ -9,13 +9,13 @@ RSpec.describe BundlerDefinitionRubyVersionPatch do
|
|
|
9
9
|
include_context "when stubbing rubygems compact index"
|
|
10
10
|
|
|
11
11
|
let(:project_name) { "ruby_version_implied" }
|
|
12
|
+
let(:ui) { Bundler.ui }
|
|
12
13
|
|
|
13
14
|
before do
|
|
14
|
-
@ui = Bundler.ui
|
|
15
15
|
Bundler.ui = Bundler::UI::Silent.new
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
after { Bundler.ui =
|
|
18
|
+
after { Bundler.ui = ui }
|
|
19
19
|
|
|
20
20
|
it "updates to the most recent version" do
|
|
21
21
|
in_tmp_folder do
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "pathname"
|
|
5
|
+
require "parser/current"
|
|
6
|
+
require "dependabot/bundler/file_fetcher"
|
|
7
|
+
require "dependabot/errors"
|
|
8
|
+
require "sorbet-runtime"
|
|
9
|
+
|
|
10
|
+
module Dependabot
|
|
11
|
+
module Bundler
|
|
12
|
+
class FileFetcher
|
|
13
|
+
# Finds the paths of any files included using `require_relative` and `eval` in the
|
|
14
|
+
# passed file.
|
|
15
|
+
class IncludedPathFinder
|
|
16
|
+
extend T::Sig
|
|
17
|
+
|
|
18
|
+
sig { params(file: Dependabot::DependencyFile).void }
|
|
19
|
+
def initialize(file:)
|
|
20
|
+
@file = file
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
sig { returns(T::Array[String]) }
|
|
24
|
+
def find_included_paths
|
|
25
|
+
ast = Parser::CurrentRuby.parse(file.content)
|
|
26
|
+
find_require_relative_paths(ast) + find_eval_paths(ast)
|
|
27
|
+
rescue Parser::SyntaxError
|
|
28
|
+
raise Dependabot::DependencyFileNotParseable, file.path
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
sig { returns(Dependabot::DependencyFile) }
|
|
34
|
+
attr_reader :file
|
|
35
|
+
|
|
36
|
+
sig { params(node: T.untyped).returns(T::Array[String]) }
|
|
37
|
+
def find_require_relative_paths(node)
|
|
38
|
+
return [] unless node.is_a?(Parser::AST::Node)
|
|
39
|
+
|
|
40
|
+
if declares_require_relative?(node)
|
|
41
|
+
return [] unless node.children[2].type == :str
|
|
42
|
+
|
|
43
|
+
path = node.children[2].loc.expression.source.gsub(/['"]/, "")
|
|
44
|
+
path = File.join(current_dir, path) unless current_dir.nil?
|
|
45
|
+
path += ".rb" unless path.end_with?(".rb")
|
|
46
|
+
return [Pathname.new(path).cleanpath.to_path]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
node.children.flat_map do |child_node|
|
|
50
|
+
find_require_relative_paths(child_node)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
sig { params(node: T.untyped).returns(T::Array[String]) }
|
|
55
|
+
def find_eval_paths(node)
|
|
56
|
+
return [] unless node.is_a?(Parser::AST::Node)
|
|
57
|
+
|
|
58
|
+
if declares_eval?(node)
|
|
59
|
+
eval_arg = node.children[2]
|
|
60
|
+
if eval_arg.is_a?(Parser::AST::Node)
|
|
61
|
+
file_read_node = find_file_read_node(eval_arg)
|
|
62
|
+
path = extract_path_from_file_read(file_read_node) if file_read_node
|
|
63
|
+
return [path] if path
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
node.children.flat_map do |child_node|
|
|
68
|
+
find_eval_paths(child_node)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
sig { params(node: Parser::AST::Node).returns(T.nilable(Parser::AST::Node)) }
|
|
73
|
+
def find_file_read_node(node)
|
|
74
|
+
return nil unless node.is_a?(Parser::AST::Node)
|
|
75
|
+
|
|
76
|
+
# Check if the node represents a method call (:send)
|
|
77
|
+
# and if the method name is :read
|
|
78
|
+
method_name = node.children[1]
|
|
79
|
+
receiver_node = node.children[0]
|
|
80
|
+
|
|
81
|
+
if node.type == :send && method_name == :read && receiver_node.is_a?(Parser::AST::Node)
|
|
82
|
+
# Check if the receiver of the :read method call is :File
|
|
83
|
+
receiver_const = receiver_node.children[1]
|
|
84
|
+
return node if receiver_const == :File
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Recursively search for a file read node in the children
|
|
88
|
+
node.children.each do |child|
|
|
89
|
+
next unless child.is_a?(Parser::AST::Node)
|
|
90
|
+
|
|
91
|
+
result = find_file_read_node(child)
|
|
92
|
+
return result if result
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
nil
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
sig { params(node: Parser::AST::Node).returns(T.nilable(String)) }
|
|
99
|
+
def extract_path_from_file_read(node)
|
|
100
|
+
return nil unless node.is_a?(Parser::AST::Node)
|
|
101
|
+
|
|
102
|
+
expand_path_node = node.children[2]
|
|
103
|
+
if expand_path_node.type == :send && expand_path_node.children[1] == :expand_path
|
|
104
|
+
path_node = expand_path_node.children[2]
|
|
105
|
+
return path_node.loc.expression.source.gsub(/['"]/, "") if path_node.type == :str
|
|
106
|
+
end
|
|
107
|
+
nil
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
sig { returns(T.nilable(String)) }
|
|
111
|
+
def current_dir
|
|
112
|
+
@current_dir ||= T.let(file.name.rpartition("/").first, T.nilable(String))
|
|
113
|
+
@current_dir = nil if @current_dir == ""
|
|
114
|
+
@current_dir
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
sig { params(node: Parser::AST::Node).returns(T::Boolean) }
|
|
118
|
+
def declares_require_relative?(node)
|
|
119
|
+
return false unless node.is_a?(Parser::AST::Node)
|
|
120
|
+
|
|
121
|
+
node.children[1] == :require_relative
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
sig { params(node: Parser::AST::Node).returns(T::Boolean) }
|
|
125
|
+
def declares_eval?(node)
|
|
126
|
+
return false unless node.is_a?(Parser::AST::Node)
|
|
127
|
+
|
|
128
|
+
node.children[1] == :eval
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "sorbet-runtime"
|
|
@@ -17,18 +17,21 @@ module Dependabot
|
|
|
17
17
|
require "dependabot/bundler/file_fetcher/gemspec_finder"
|
|
18
18
|
require "dependabot/bundler/file_fetcher/path_gemspec_finder"
|
|
19
19
|
require "dependabot/bundler/file_fetcher/child_gemfile_finder"
|
|
20
|
-
require "dependabot/bundler/file_fetcher/
|
|
20
|
+
require "dependabot/bundler/file_fetcher/included_path_finder"
|
|
21
21
|
|
|
22
|
+
sig { override.params(filenames: T::Array[String]).returns(T::Boolean) }
|
|
22
23
|
def self.required_files_in?(filenames)
|
|
23
24
|
return true if filenames.any? { |name| name.match?(%r{^[^/]*\.gemspec$}) }
|
|
24
25
|
|
|
25
26
|
filenames.include?("Gemfile") || filenames.include?("gems.rb")
|
|
26
27
|
end
|
|
27
28
|
|
|
29
|
+
sig { override.returns(String) }
|
|
28
30
|
def self.required_files_message
|
|
29
31
|
"Repo must contain either a Gemfile, a gemspec, or a gems.rb."
|
|
30
32
|
end
|
|
31
33
|
|
|
34
|
+
sig { override.returns(T.nilable(T::Hash[Symbol, T.nilable(String)])) }
|
|
32
35
|
def ecosystem_versions
|
|
33
36
|
{
|
|
34
37
|
package_managers: {
|
|
@@ -39,41 +42,47 @@ module Dependabot
|
|
|
39
42
|
|
|
40
43
|
sig { override.returns(T::Array[DependencyFile]) }
|
|
41
44
|
def fetch_files
|
|
42
|
-
fetched_files = []
|
|
43
|
-
fetched_files << gemfile if gemfile
|
|
44
|
-
fetched_files << lockfile if gemfile && lockfile
|
|
45
|
+
fetched_files = T.let([], T::Array[DependencyFile])
|
|
46
|
+
fetched_files << T.must(gemfile) if gemfile
|
|
47
|
+
fetched_files << T.must(lockfile) if gemfile && lockfile
|
|
45
48
|
fetched_files += child_gemfiles
|
|
46
49
|
fetched_files += gemspecs
|
|
47
|
-
fetched_files << ruby_version_file if ruby_version_file
|
|
48
|
-
fetched_files << tool_versions_file if tool_versions_file
|
|
50
|
+
fetched_files << T.must(ruby_version_file) if ruby_version_file
|
|
51
|
+
fetched_files << T.must(tool_versions_file) if tool_versions_file
|
|
49
52
|
fetched_files += path_gemspecs
|
|
50
|
-
fetched_files +=
|
|
53
|
+
fetched_files += find_included_files(fetched_files)
|
|
51
54
|
|
|
52
55
|
uniq_files(fetched_files)
|
|
53
56
|
end
|
|
54
57
|
|
|
55
58
|
private
|
|
56
59
|
|
|
60
|
+
sig { params(fetched_files: T::Array[DependencyFile]).returns(T::Array[DependencyFile]) }
|
|
57
61
|
def uniq_files(fetched_files)
|
|
58
62
|
uniq_files = fetched_files.reject(&:support_file?).uniq
|
|
59
63
|
uniq_files += fetched_files
|
|
60
64
|
.reject { |f| uniq_files.map(&:name).include?(f.name) }
|
|
61
65
|
end
|
|
62
66
|
|
|
67
|
+
sig { returns(T.nilable(DependencyFile)) }
|
|
63
68
|
def gemfile
|
|
64
69
|
return @gemfile if defined?(@gemfile)
|
|
65
70
|
|
|
66
|
-
@gemfile = fetch_file_if_present("gems.rb") || fetch_file_if_present("Gemfile")
|
|
71
|
+
@gemfile = T.let(fetch_file_if_present("gems.rb") || fetch_file_if_present("Gemfile"),
|
|
72
|
+
T.nilable(Dependabot::DependencyFile))
|
|
67
73
|
end
|
|
68
74
|
|
|
75
|
+
sig { returns(T.nilable(DependencyFile)) }
|
|
69
76
|
def lockfile
|
|
70
77
|
return @lockfile if defined?(@lockfile)
|
|
71
78
|
|
|
72
|
-
@lockfile = fetch_file_if_present("gems.locked") || fetch_file_if_present("Gemfile.lock")
|
|
79
|
+
@lockfile = T.let(fetch_file_if_present("gems.locked") || fetch_file_if_present("Gemfile.lock"),
|
|
80
|
+
T.nilable(Dependabot::DependencyFile))
|
|
73
81
|
end
|
|
74
82
|
|
|
83
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
75
84
|
def gemspecs
|
|
76
|
-
return @gemspecs if defined?(@gemspecs)
|
|
85
|
+
return T.must(@gemspecs) if defined?(@gemspecs)
|
|
77
86
|
|
|
78
87
|
gemspecs_paths =
|
|
79
88
|
gemspec_directories
|
|
@@ -83,11 +92,17 @@ module Dependabot
|
|
|
83
92
|
.map { |f| File.join(d, f.name) }
|
|
84
93
|
end
|
|
85
94
|
|
|
86
|
-
@gemspecs
|
|
95
|
+
@gemspecs ||= T.let(
|
|
96
|
+
gemspecs_paths.map do |n|
|
|
97
|
+
fetch_file_from_host(n)
|
|
98
|
+
end,
|
|
99
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
|
100
|
+
)
|
|
87
101
|
rescue Octokit::NotFound
|
|
88
102
|
[]
|
|
89
103
|
end
|
|
90
104
|
|
|
105
|
+
sig { returns(T::Array[String]) }
|
|
91
106
|
def gemspec_directories
|
|
92
107
|
gemfiles = ([gemfile] + child_gemfiles).compact
|
|
93
108
|
directories =
|
|
@@ -98,18 +113,21 @@ module Dependabot
|
|
|
98
113
|
directories.empty? ? ["."] : directories
|
|
99
114
|
end
|
|
100
115
|
|
|
116
|
+
sig { returns(T.nilable(DependencyFile)) }
|
|
101
117
|
def ruby_version_file
|
|
102
118
|
return unless gemfile
|
|
103
119
|
|
|
104
|
-
@ruby_version_file ||= fetch_support_file(".ruby-version")
|
|
120
|
+
@ruby_version_file ||= T.let(fetch_support_file(".ruby-version"), T.nilable(Dependabot::DependencyFile))
|
|
105
121
|
end
|
|
106
122
|
|
|
123
|
+
sig { returns(T.nilable(DependencyFile)) }
|
|
107
124
|
def tool_versions_file
|
|
108
125
|
return unless gemfile
|
|
109
126
|
|
|
110
|
-
@tool_versions_file ||= fetch_support_file(".tool-versions")
|
|
127
|
+
@tool_versions_file ||= T.let(fetch_support_file(".tool-versions"), T.nilable(Dependabot::DependencyFile))
|
|
111
128
|
end
|
|
112
129
|
|
|
130
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
113
131
|
def path_gemspecs
|
|
114
132
|
gemspec_files = T.let([], T::Array[Dependabot::DependencyFile])
|
|
115
133
|
unfetchable_gems = []
|
|
@@ -141,21 +159,25 @@ module Dependabot
|
|
|
141
159
|
gemspec_files
|
|
142
160
|
end
|
|
143
161
|
|
|
162
|
+
sig { returns(T::Array[Pathname]) }
|
|
144
163
|
def path_gemspec_paths
|
|
145
164
|
fetch_path_gemspec_paths.map { |path| Pathname.new(path) }
|
|
146
165
|
end
|
|
147
166
|
|
|
148
|
-
|
|
167
|
+
sig { params(files: T::Array[DependencyFile]).returns(T::Array[DependencyFile]) }
|
|
168
|
+
def find_included_files(files)
|
|
149
169
|
ruby_files =
|
|
150
170
|
files.select { |f| f.name.end_with?(".rb", "Gemfile", ".gemspec") }
|
|
151
171
|
|
|
152
172
|
paths = ruby_files.flat_map do |file|
|
|
153
|
-
|
|
173
|
+
IncludedPathFinder.new(file: file).find_included_paths
|
|
154
174
|
end
|
|
155
175
|
|
|
156
|
-
@
|
|
176
|
+
@find_included_files ||= T.let(
|
|
157
177
|
paths.map { |path| fetch_file_from_host(path) }
|
|
158
|
-
.tap { |req_files| req_files.each { |f| f.support_file = true } }
|
|
178
|
+
.tap { |req_files| req_files.each { |f| f.support_file = true } },
|
|
179
|
+
T.nilable(T::Array[DependencyFile])
|
|
180
|
+
)
|
|
159
181
|
end
|
|
160
182
|
|
|
161
183
|
sig { params(dir_path: T.any(String, Pathname)).returns(T::Array[DependencyFile]) }
|
|
@@ -166,9 +188,10 @@ module Dependabot
|
|
|
166
188
|
.map { |fp| fetch_file_from_host(fp, fetch_submodules: true) }
|
|
167
189
|
end
|
|
168
190
|
|
|
191
|
+
sig { returns(T::Array[String]) }
|
|
169
192
|
def fetch_path_gemspec_paths
|
|
170
193
|
if lockfile
|
|
171
|
-
parsed_lockfile = CachedLockfileParser.parse(sanitized_lockfile_content)
|
|
194
|
+
parsed_lockfile = CachedLockfileParser.parse(T.must(sanitized_lockfile_content))
|
|
172
195
|
parsed_lockfile.specs
|
|
173
196
|
.select { |s| s.source.instance_of?(::Bundler::Source::Path) }
|
|
174
197
|
.map { |s| s.source.path }.uniq
|
|
@@ -179,26 +202,35 @@ module Dependabot
|
|
|
179
202
|
end.uniq
|
|
180
203
|
end
|
|
181
204
|
rescue ::Bundler::LockfileError
|
|
182
|
-
raise Dependabot::DependencyFileNotParseable, lockfile.path
|
|
205
|
+
raise Dependabot::DependencyFileNotParseable, T.must(lockfile).path
|
|
183
206
|
rescue ::Bundler::Plugin::UnknownSourceError
|
|
184
207
|
# Quietly ignore plugin errors - we'll raise a better error during
|
|
185
208
|
# parsing
|
|
186
209
|
[]
|
|
187
210
|
end
|
|
188
211
|
|
|
212
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
189
213
|
def child_gemfiles
|
|
190
214
|
return [] unless gemfile
|
|
191
215
|
|
|
192
|
-
@child_gemfiles ||=
|
|
193
|
-
fetch_child_gemfiles(file: gemfile, previously_fetched_files: [])
|
|
216
|
+
@child_gemfiles ||= T.let(
|
|
217
|
+
fetch_child_gemfiles(file: T.must(gemfile), previously_fetched_files: []),
|
|
218
|
+
T.nilable(T::Array[DependencyFile])
|
|
219
|
+
)
|
|
194
220
|
end
|
|
195
221
|
|
|
196
222
|
# TODO: Stop sanitizing the lockfile once we have bundler 2 installed
|
|
223
|
+
|
|
224
|
+
sig { returns T.nilable(String) }
|
|
197
225
|
def sanitized_lockfile_content
|
|
198
226
|
regex = FileUpdater::LockfileUpdater::LOCKFILE_ENDING
|
|
199
|
-
lockfile
|
|
227
|
+
lockfile&.content&.gsub(regex, "")
|
|
200
228
|
end
|
|
201
229
|
|
|
230
|
+
sig do
|
|
231
|
+
params(file: DependencyFile,
|
|
232
|
+
previously_fetched_files: T::Array[DependencyFile]).returns(T::Array[DependencyFile])
|
|
233
|
+
end
|
|
202
234
|
def fetch_child_gemfiles(file:, previously_fetched_files:)
|
|
203
235
|
paths = ChildGemfileFinder.new(gemfile: file).child_gemfile_paths
|
|
204
236
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-bundler
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.264.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-
|
|
11
|
+
date: 2024-07-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: dependabot-common
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - '='
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.
|
|
19
|
+
version: 0.264.0
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - '='
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.
|
|
26
|
+
version: 0.264.0
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: parallel
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -310,8 +310,8 @@ files:
|
|
|
310
310
|
- lib/dependabot/bundler/file_fetcher.rb
|
|
311
311
|
- lib/dependabot/bundler/file_fetcher/child_gemfile_finder.rb
|
|
312
312
|
- lib/dependabot/bundler/file_fetcher/gemspec_finder.rb
|
|
313
|
+
- lib/dependabot/bundler/file_fetcher/included_path_finder.rb
|
|
313
314
|
- lib/dependabot/bundler/file_fetcher/path_gemspec_finder.rb
|
|
314
|
-
- lib/dependabot/bundler/file_fetcher/require_relative_finder.rb
|
|
315
315
|
- lib/dependabot/bundler/file_parser.rb
|
|
316
316
|
- lib/dependabot/bundler/file_parser/file_preparer.rb
|
|
317
317
|
- lib/dependabot/bundler/file_parser/gemfile_declaration_finder.rb
|
|
@@ -345,7 +345,7 @@ licenses:
|
|
|
345
345
|
- MIT
|
|
346
346
|
metadata:
|
|
347
347
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
348
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
348
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.264.0
|
|
349
349
|
post_install_message:
|
|
350
350
|
rdoc_options: []
|
|
351
351
|
require_paths:
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
# typed: strict
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require "pathname"
|
|
5
|
-
require "parser/current"
|
|
6
|
-
require "dependabot/bundler/file_fetcher"
|
|
7
|
-
require "dependabot/errors"
|
|
8
|
-
require "sorbet-runtime"
|
|
9
|
-
|
|
10
|
-
module Dependabot
|
|
11
|
-
module Bundler
|
|
12
|
-
class FileFetcher
|
|
13
|
-
# Finds the paths of any files included using `require_relative` in the
|
|
14
|
-
# passed file.
|
|
15
|
-
class RequireRelativeFinder
|
|
16
|
-
extend T::Sig
|
|
17
|
-
|
|
18
|
-
sig { params(file: Dependabot::DependencyFile).void }
|
|
19
|
-
def initialize(file:)
|
|
20
|
-
@file = file
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
sig { returns(T::Array[String]) }
|
|
24
|
-
def require_relative_paths
|
|
25
|
-
ast = Parser::CurrentRuby.parse(file.content)
|
|
26
|
-
find_require_relative_paths(ast)
|
|
27
|
-
rescue Parser::SyntaxError
|
|
28
|
-
raise Dependabot::DependencyFileNotParseable, file.path
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
private
|
|
32
|
-
|
|
33
|
-
sig { returns(Dependabot::DependencyFile) }
|
|
34
|
-
attr_reader :file
|
|
35
|
-
|
|
36
|
-
sig { params(node: T.untyped).returns(T::Array[T.untyped]) }
|
|
37
|
-
def find_require_relative_paths(node)
|
|
38
|
-
return [] unless node.is_a?(Parser::AST::Node)
|
|
39
|
-
|
|
40
|
-
if declares_require_relative?(node)
|
|
41
|
-
return [] unless node.children[2].type == :str
|
|
42
|
-
|
|
43
|
-
path = node.children[2].loc.expression.source.gsub(/['"]/, "")
|
|
44
|
-
path = File.join(current_dir, path) unless current_dir.nil?
|
|
45
|
-
path += ".rb" unless path.end_with?(".rb")
|
|
46
|
-
return [Pathname.new(path).cleanpath.to_path]
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
node.children.flat_map do |child_node|
|
|
50
|
-
find_require_relative_paths(child_node)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
sig { returns(T.nilable(String)) }
|
|
55
|
-
def current_dir
|
|
56
|
-
@current_dir ||= T.let(file.name.rpartition("/").first, T.nilable(String))
|
|
57
|
-
@current_dir = nil if @current_dir == ""
|
|
58
|
-
@current_dir
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
sig { params(node: Parser::AST::Node).returns(T::Boolean) }
|
|
62
|
-
def declares_require_relative?(node)
|
|
63
|
-
return false unless node.is_a?(Parser::AST::Node)
|
|
64
|
-
|
|
65
|
-
node.children[1] == :require_relative
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|