dependabot-bundler 0.263.0 → 0.264.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 50457240c048f6430b4894d8f032b2eab8bbda90c88566bbbee21e6d4d29fcbe
4
- data.tar.gz: c907811fc0c0ea30a9b9bb62f59c53182515b1cc94bf6e94d65899d588afa1cc
3
+ metadata.gz: dcc0bc531e33ee50374a4f53b0e72e3522ad9b2b9c0b5470b047f6a72933446f
4
+ data.tar.gz: 91ec4898f9462acc61fa9204e1ae198f454cd9d2a325026d53d451d4d903cbf5
5
5
  SHA512:
6
- metadata.gz: f230c5e09b5cd4c5a6d92012a6a7590d6edeb22f0663a1f2bdc26911202360c4edbcb02304f2f128b4ce9e44ec763d19d2fac00bde79a0a5dc507addc768b8ff
7
- data.tar.gz: eca4288984f2fe056f60c3147a20347f599e49294b8c9e66aae53069577ea8300c89a0085fbfc59528dbf53be28ee32289435f2f75f27038065c931f73cf576a
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 = @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: true
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/require_relative_finder"
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 += require_relative_files(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 = gemspecs_paths.map { |n| fetch_file_from_host(n) }
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
- def require_relative_files(files)
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
- RequireRelativeFinder.new(file: file).require_relative_paths
173
+ IncludedPathFinder.new(file: file).find_included_paths
154
174
  end
155
175
 
156
- @require_relative_files ||=
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.content.gsub(regex, "")
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.263.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-06-27 00:00:00.000000000 Z
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.263.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.263.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.263.0
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