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: 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