dependabot-npm_and_yarn 0.95.55 → 0.95.56

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: 4829f6fc333c2f2401b4255dc07ebace059b0990d12f15c228305390c5095892
4
- data.tar.gz: 31c7a882ff85d7c1943db60df2c1cccc819a226b73ef31d327cc78293c8f3d4b
3
+ metadata.gz: 042c1ec8fff67eae6767a168fcbe893e6adabb6a603d6fca44d7d6490fa21a32
4
+ data.tar.gz: 1a1620d75df5db1ae7e8cd30d85fc7f31e551d6e1f34b78a78bc8a620be83685
5
5
  SHA512:
6
- metadata.gz: 4150f2b342457a3b6bccc74e812daa3e0280d894bc23abaab8971d9c3c050bb2869b2787f7f488a9ac4a1ead33b1fb15f9d8b2ebbfb5b93b9d0f9cc3b1958456
7
- data.tar.gz: d71d971c535e1d3f26a90d38c3f74bceab6167cb9a0eec0e628ca95e081185f9133d76fe9a81f1b968a37f6587770b3481958e9b03e0bd32ed161aa652713994
6
+ metadata.gz: bb56fe83c7b46954449c2824847d5b0dfc4b54d898f988ce76b4fe002551b3f8b584c1a0f7d65e335dde6468429d8acd3810c29eaba3172af72c36b1bfea2262
7
+ data.tar.gz: c271b8d7ea1e3e98bd68ac3b5895b2a520baf95bb7efc09a96e8258784c67dc500e871213f17eac6fea8f1b80e4231433d52a2a461da92d27148bf9be13912bd
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "dependabot/utils"
4
+ require "dependabot/npm_and_yarn/file_parser/lockfile_parser"
4
5
 
5
6
  # Used in the version resolver and file updater to only run yarn/npm helpers on
6
7
  # dependency files that require updates. This is useful for large monorepos with
@@ -14,23 +15,21 @@ module Dependabot
14
15
  end
15
16
 
16
17
  def files_requiring_update
17
- dependency_files.select do |file|
18
- if manifest?(file)
19
- package_manifests.include?(file)
20
- elsif lockfile?(file)
21
- package_manifests.any? do |package_file|
22
- File.dirname(package_file.name) == File.dirname(file.name)
18
+ @files_requiring_update ||=
19
+ begin
20
+ dependency_files.select do |file|
21
+ package_files_requiring_update.include?(file) ||
22
+ package_required_lockfile?(file) ||
23
+ yarn_workspaces_lockfile?(file)
23
24
  end
24
- else
25
- # Include all non-manifest/lockfiles
26
- # e.g. .npmrc, lerna.json
27
- true
28
25
  end
29
- end
30
26
  end
31
27
 
32
28
  def package_files_requiring_update
33
- files_requiring_update.select { |file| manifest?(file) }
29
+ @package_files_requiring_update ||=
30
+ dependency_files.select do |file|
31
+ dependency_manifest_requirements.include?(file.name)
32
+ end
34
33
  end
35
34
 
36
35
  private
@@ -44,18 +43,43 @@ module Dependabot
44
43
  end
45
44
  end
46
45
 
47
- def package_manifests
48
- @package_manifests ||=
49
- dependency_files.select do |file|
50
- next unless manifest?(file)
46
+ def package_required_lockfile?(lockfile)
47
+ return false unless lockfile?(lockfile)
48
+
49
+ package_files_requiring_update.any? do |package_file|
50
+ File.dirname(package_file.name) == File.dirname(lockfile.name)
51
+ end
52
+ end
51
53
 
52
- root_manifest?(file) ||
53
- dependency_manifest_requirements.include?(file.name)
54
+ def yarn_workspaces_lockfile?(lockfile)
55
+ return false unless lockfile.name == "yarn.lock"
56
+ return false unless parsed_root_package_json["workspaces"]
57
+
58
+ updated_dependencies_in_lockfile?(lockfile)
59
+ end
60
+
61
+ def parsed_root_package_json
62
+ @parsed_root_package_json ||=
63
+ begin
64
+ package = dependency_files.find { |f| f.name == "package.json" }
65
+ JSON.parse(package.content)
54
66
  end
55
67
  end
56
68
 
57
- def root_manifest?(file)
58
- file.name == "package.json"
69
+ def updated_dependencies_in_lockfile?(lockfile)
70
+ lockfile_dependencies(lockfile).any? do |sub_dep|
71
+ updated_dependencies.any? do |updated_dep|
72
+ sub_dep.name == updated_dep.name
73
+ end
74
+ end
75
+ end
76
+
77
+ def lockfile_dependencies(lockfile)
78
+ @lockfile_dependencies ||= {}
79
+ @lockfile_dependencies[lockfile.name] ||=
80
+ NpmAndYarn::FileParser::LockfileParser.new(
81
+ dependency_files: [lockfile]
82
+ ).parse
59
83
  end
60
84
 
61
85
  def manifest?(file)
@@ -7,13 +7,14 @@ require "dependabot/file_parsers"
7
7
  require "dependabot/file_parsers/base"
8
8
  require "dependabot/shared_helpers"
9
9
  require "dependabot/npm_and_yarn/native_helpers"
10
+ require "dependabot/npm_and_yarn/version"
10
11
  require "dependabot/errors"
11
12
 
12
- # rubocop:disable Metrics/ClassLength
13
13
  module Dependabot
14
14
  module NpmAndYarn
15
15
  class FileParser < Dependabot::FileParsers::Base
16
16
  require "dependabot/file_parsers/base/dependency_set"
17
+ require_relative "file_parser/lockfile_parser"
17
18
 
18
19
  DEPENDENCY_TYPES =
19
20
  %w(dependencies devDependencies optionalDependencies).freeze
@@ -36,9 +37,7 @@ module Dependabot
36
37
  def parse
37
38
  dependency_set = DependencySet.new
38
39
  dependency_set += manifest_dependencies
39
- dependency_set += yarn_lock_dependencies if yarn_locks.any?
40
- dependency_set += package_lock_dependencies if package_locks.any?
41
- dependency_set += shrinkwrap_dependencies if shrinkwraps.any?
40
+ dependency_set += lockfile_dependencies
42
41
  dependencies = dependency_set.dependencies
43
42
 
44
43
  # TODO: Currently, Dependabot can't handle dependencies that have both
@@ -79,84 +78,22 @@ module Dependabot
79
78
  dependency_set
80
79
  end
81
80
 
82
- def yarn_lock_dependencies
83
- dependency_set = DependencySet.new
84
-
85
- yarn_locks.each do |yarn_lock|
86
- parse_yarn_lock(yarn_lock).each do |req, details|
87
- next unless details["version"] && details["version"] != ""
88
-
89
- # Note: The DependencySet will de-dupe our dependencies, so they
90
- # end up unique by name. That's not a perfect representation of
91
- # the nested nature of JS resolution, but it makes everything work
92
- # comparably to other flat-resolution strategies
93
- dependency_set << Dependency.new(
94
- name: req.split(/(?<=\w)\@/).first,
95
- version: details["version"],
96
- package_manager: "npm_and_yarn",
97
- requirements: []
98
- )
99
- end
100
- end
101
-
102
- dependency_set
103
- end
104
-
105
- def package_lock_dependencies
106
- dependency_set = DependencySet.new
107
-
108
- # Note: The DependencySet will de-dupe our dependencies, so they
109
- # end up unique by name. That's not a perfect representation of
110
- # the nested nature of JS resolution, but it makes everything work
111
- # comparably to other flat-resolution strategies
112
- package_locks.each do |package_lock|
113
- parsed_lockfile = parse_package_lock(package_lock)
114
- deps = recursively_fetch_npm_lock_dependencies(parsed_lockfile)
115
- dependency_set += deps
116
- end
117
-
118
- dependency_set
119
- end
120
-
121
- def shrinkwrap_dependencies
122
- dependency_set = DependencySet.new
123
-
124
- # Note: The DependencySet will de-dupe our dependencies, so they
125
- # end up unique by name. That's not a perfect representation of
126
- # the nested nature of JS resolution, but it makes everything work
127
- # comparably to other flat-resolution strategies
128
- shrinkwraps.each do |shrinkwrap|
129
- parsed_lockfile = parse_shrinkwrap(shrinkwrap)
130
- deps = recursively_fetch_npm_lock_dependencies(parsed_lockfile)
131
- dependency_set += deps
132
- end
133
-
134
- dependency_set
81
+ def lockfile_parser
82
+ @lockfile_parser ||= LockfileParser.new(
83
+ dependency_files: dependency_files
84
+ )
135
85
  end
136
86
 
137
- def recursively_fetch_npm_lock_dependencies(object_with_dependencies)
138
- dependency_set = DependencySet.new
139
-
140
- object_with_dependencies.
141
- fetch("dependencies", {}).each do |name, details|
142
- next unless details["version"] && details["version"] != ""
143
-
144
- dependency_set << Dependency.new(
145
- name: name,
146
- version: details["version"],
147
- package_manager: "npm_and_yarn",
148
- requirements: []
149
- )
150
-
151
- dependency_set += recursively_fetch_npm_lock_dependencies(details)
152
- end
153
-
154
- dependency_set
87
+ def lockfile_dependencies
88
+ DependencySet.new(lockfile_parser.parse)
155
89
  end
156
90
 
157
91
  def build_dependency(file:, type:, name:, requirement:)
158
- return if lockfile_details(name, requirement) &&
159
- !version_for(name, requirement)
92
+ lockfile_details = lockfile_parser.lockfile_details(
93
+ dependency_name: name,
94
+ requirement: requirement
95
+ )
96
+ return if lockfile_details && !version_for(name, requirement)
160
97
  return if ignore_requirement?(requirement)
161
98
  return if workspace_package_names.include?(name)
162
99
 
@@ -226,10 +163,12 @@ module Dependabot
226
163
  def git_revision_for(name, requirement)
227
164
  return unless git_url?(requirement)
228
165
 
229
- lock_version = lockfile_details(name, requirement)&.
230
- fetch("version", nil)
231
- lock_res = lockfile_details(name, requirement)&.
232
- fetch("resolved", nil)
166
+ lockfile_details = lockfile_parser.lockfile_details(
167
+ dependency_name: name,
168
+ requirement: requirement
169
+ )
170
+ lock_version = lockfile_details&.fetch("version", nil)
171
+ lock_res = lockfile_details&.fetch("resolved", nil)
233
172
 
234
173
  return lock_version.split("#").last if lock_version&.include?("#")
235
174
  return lock_res.split("#").last if lock_res&.include?("#")
@@ -242,8 +181,10 @@ module Dependabot
242
181
  end
243
182
 
244
183
  def semver_version_for(name, requirement)
245
- lock_version = lockfile_details(name, requirement)&.
246
- fetch("version", nil)
184
+ lock_version = lockfile_parser.lockfile_details(
185
+ dependency_name: name,
186
+ requirement: requirement
187
+ )&.fetch("version", nil)
247
188
 
248
189
  return unless lock_version
249
190
  return if lock_version.include?("://")
@@ -257,8 +198,10 @@ module Dependabot
257
198
  def source_for(name, requirement)
258
199
  return git_source_for(requirement) if git_url?(requirement)
259
200
 
260
- resolved_url = lockfile_details(name, requirement)&.
261
- fetch("resolved", nil)
201
+ resolved_url = lockfile_parser.lockfile_details(
202
+ dependency_name: name,
203
+ requirement: requirement
204
+ )&.fetch("resolved", nil)
262
205
 
263
206
  return unless resolved_url
264
207
  return unless resolved_url.start_with?("http")
@@ -314,107 +257,24 @@ module Dependabot
314
257
  false
315
258
  end
316
259
 
317
- def lockfile_details(name, requirement)
318
- [*package_locks, *shrinkwraps].each do |package_lock|
319
- parsed_package_lock_json = parse_package_lock(package_lock)
320
- next unless parsed_package_lock_json.dig("dependencies", name)
321
-
322
- return parsed_package_lock_json.dig("dependencies", name)
323
- end
324
-
325
- req = requirement
326
- yarn_locks.each do |yarn_lock|
327
- parsed_yarn_lock = parse_yarn_lock(yarn_lock)
328
-
329
- details_candidates =
330
- parsed_yarn_lock.
331
- select { |k, _| k.split(/(?<=\w)\@/).first == name }
332
-
333
- # If there's only one entry for this dependency, use it, even if
334
- # the requirement in the lockfile doesn't match
335
- details = details_candidates.first.last if details_candidates.one?
336
-
337
- details ||=
338
- details_candidates.
339
- find { |k, _| k.split(/(?<=\w)\@/)[1..-1].join("@") == req }&.
340
- last
341
-
342
- return details if details
343
- end
344
-
345
- nil
346
- end
347
-
348
- def parse_package_lock(package_lock)
349
- JSON.parse(package_lock.content)
350
- rescue JSON::ParserError
351
- raise Dependabot::DependencyFileNotParseable, package_lock.path
352
- end
353
-
354
- def parse_shrinkwrap(shrinkwrap)
355
- JSON.parse(shrinkwrap.content)
356
- rescue JSON::ParserError
357
- raise Dependabot::DependencyFileNotParseable, shrinkwrap.path
358
- end
359
-
360
- def parse_yarn_lock(yarn_lock)
361
- @parsed_yarn_lock ||= {}
362
- @parsed_yarn_lock[yarn_lock.name] ||=
363
- SharedHelpers.in_a_temporary_directory do
364
- File.write("yarn.lock", yarn_lock.content)
365
-
366
- SharedHelpers.run_helper_subprocess(
367
- command: "node #{yarn_helper_path}",
368
- function: "parseLockfile",
369
- args: [Dir.pwd]
370
- )
371
- rescue SharedHelpers::HelperSubprocessFailed
372
- raise Dependabot::DependencyFileNotParseable, yarn_lock.path
373
- end
374
- end
375
-
376
- def yarn_helper_path
377
- NativeHelpers.yarn_helper_path
378
- end
379
-
380
260
  def package_files
381
- sub_packages =
382
- dependency_files.
383
- select { |f| f.name.end_with?("package.json") }.
384
- reject { |f| f.name == "package.json" }.
385
- reject(&:support_file?)
386
-
387
- [
388
- dependency_files.find { |f| f.name == "package.json" },
389
- *sub_packages
390
- ].compact
391
- end
392
-
393
- def lockfile?
394
- package_locks.any? || yarn_locks.any?
395
- end
396
-
397
- def package_locks
398
- @package_locks ||=
399
- dependency_files.
400
- select { |f| f.name.end_with?("package-lock.json") }
401
- end
402
-
403
- def yarn_locks
404
- @yarn_locks ||=
405
- dependency_files.
406
- select { |f| f.name.end_with?("yarn.lock") }
407
- end
408
-
409
- def shrinkwraps
410
- @shrinkwraps ||=
411
- dependency_files.
412
- select { |f| f.name.end_with?("npm-shrinkwrap.json") }
261
+ @package_files ||=
262
+ begin
263
+ sub_packages =
264
+ dependency_files.
265
+ select { |f| f.name.end_with?("package.json") }.
266
+ reject { |f| f.name == "package.json" }.
267
+ reject(&:support_file?)
268
+
269
+ [
270
+ dependency_files.find { |f| f.name == "package.json" },
271
+ *sub_packages
272
+ ].compact
273
+ end
413
274
  end
414
275
  end
415
276
  end
416
277
  end
417
- # rubocop:enable Metrics/ClassLength
418
278
 
419
279
  Dependabot::FileParsers.
420
280
  register("npm_and_yarn", Dependabot::NpmAndYarn::FileParser)
@@ -0,0 +1,190 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/dependency_file"
4
+ require "dependabot/npm_and_yarn/file_parser"
5
+
6
+ module Dependabot
7
+ module NpmAndYarn
8
+ class FileParser
9
+ class LockfileParser
10
+ def initialize(dependency_files:)
11
+ @dependency_files = dependency_files
12
+ end
13
+
14
+ def parse
15
+ dependency_set = Dependabot::NpmAndYarn::FileParser::DependencySet.new
16
+ dependency_set += yarn_lock_dependencies if yarn_locks.any?
17
+ dependency_set += package_lock_dependencies if package_locks.any?
18
+ dependency_set += shrinkwrap_dependencies if shrinkwraps.any?
19
+ dependency_set.dependencies
20
+ end
21
+
22
+ def lockfile_details(dependency_name:, requirement:)
23
+ [*package_locks, *shrinkwraps].each do |package_lock|
24
+ parsed_package_lock_json = parse_package_lock(package_lock)
25
+ next unless parsed_package_lock_json.dig("dependencies",
26
+ dependency_name)
27
+
28
+ return parsed_package_lock_json.dig("dependencies", dependency_name)
29
+ end
30
+
31
+ yarn_locks.each do |yarn_lock|
32
+ parsed_yarn_lock = parse_yarn_lock(yarn_lock)
33
+
34
+ details_candidates =
35
+ parsed_yarn_lock.
36
+ select { |k, _| k.split(/(?<=\w)\@/).first == dependency_name }
37
+
38
+ # If there's only one entry for this dependency, use it, even if
39
+ # the requirement in the lockfile doesn't match
40
+ details = details_candidates.first.last if details_candidates.one?
41
+
42
+ details ||=
43
+ details_candidates.
44
+ find do |k, _|
45
+ k.split(/(?<=\w)\@/)[1..-1].join("@") == requirement
46
+ end&.
47
+ last
48
+
49
+ return details if details
50
+ end
51
+
52
+ nil
53
+ end
54
+
55
+ private
56
+
57
+ attr_reader :dependency_files
58
+
59
+ def yarn_lock_dependencies
60
+ dependency_set = Dependabot::NpmAndYarn::FileParser::DependencySet.new
61
+
62
+ yarn_locks.each do |yarn_lock|
63
+ parse_yarn_lock(yarn_lock).each do |req, details|
64
+ next unless details["version"] && details["version"] != ""
65
+
66
+ # Note: The DependencySet will de-dupe our dependencies, so they
67
+ # end up unique by name. That's not a perfect representation of
68
+ # the nested nature of JS resolution, but it makes everything work
69
+ # comparably to other flat-resolution strategies
70
+ dependency_set << Dependency.new(
71
+ name: req.split(/(?<=\w)\@/).first,
72
+ version: details["version"],
73
+ package_manager: "npm_and_yarn",
74
+ requirements: []
75
+ )
76
+ end
77
+ end
78
+
79
+ dependency_set
80
+ end
81
+
82
+ def package_lock_dependencies
83
+ dependency_set = Dependabot::NpmAndYarn::FileParser::DependencySet.new
84
+
85
+ # Note: The DependencySet will de-dupe our dependencies, so they
86
+ # end up unique by name. That's not a perfect representation of
87
+ # the nested nature of JS resolution, but it makes everything work
88
+ # comparably to other flat-resolution strategies
89
+ package_locks.each do |package_lock|
90
+ parsed_lockfile = parse_package_lock(package_lock)
91
+ deps = recursively_fetch_npm_lock_dependencies(parsed_lockfile)
92
+ dependency_set += deps
93
+ end
94
+
95
+ dependency_set
96
+ end
97
+
98
+ def shrinkwrap_dependencies
99
+ dependency_set = Dependabot::NpmAndYarn::FileParser::DependencySet.new
100
+
101
+ # Note: The DependencySet will de-dupe our dependencies, so they
102
+ # end up unique by name. That's not a perfect representation of
103
+ # the nested nature of JS resolution, but it makes everything work
104
+ # comparably to other flat-resolution strategies
105
+ shrinkwraps.each do |shrinkwrap|
106
+ parsed_lockfile = parse_shrinkwrap(shrinkwrap)
107
+ deps = recursively_fetch_npm_lock_dependencies(parsed_lockfile)
108
+ dependency_set += deps
109
+ end
110
+
111
+ dependency_set
112
+ end
113
+
114
+ def recursively_fetch_npm_lock_dependencies(object_with_dependencies)
115
+ dependency_set = Dependabot::NpmAndYarn::FileParser::DependencySet.new
116
+
117
+ object_with_dependencies.
118
+ fetch("dependencies", {}).each do |name, details|
119
+ next unless details["version"] && details["version"] != ""
120
+
121
+ dependency_set << Dependency.new(
122
+ name: name,
123
+ version: details["version"],
124
+ package_manager: "npm_and_yarn",
125
+ requirements: []
126
+ )
127
+
128
+ dependency_set += recursively_fetch_npm_lock_dependencies(details)
129
+ end
130
+
131
+ dependency_set
132
+ end
133
+
134
+ def parse_package_lock(package_lock)
135
+ @parse_package_lock ||= {}
136
+ @parse_package_lock[package_lock.name] ||=
137
+ JSON.parse(package_lock.content)
138
+ rescue JSON::ParserError
139
+ raise Dependabot::DependencyFileNotParseable, package_lock.path
140
+ end
141
+
142
+ def parse_shrinkwrap(shrinkwrap)
143
+ @parse_shrinkwrap ||= {}
144
+ @parse_shrinkwrap[shrinkwrap.name] ||=
145
+ JSON.parse(shrinkwrap.content)
146
+ rescue JSON::ParserError
147
+ raise Dependabot::DependencyFileNotParseable, shrinkwrap.path
148
+ end
149
+
150
+ def parse_yarn_lock(yarn_lock)
151
+ @parsed_yarn_lock ||= {}
152
+ @parsed_yarn_lock[yarn_lock.name] ||=
153
+ SharedHelpers.in_a_temporary_directory do
154
+ File.write("yarn.lock", yarn_lock.content)
155
+
156
+ SharedHelpers.run_helper_subprocess(
157
+ command: "node #{yarn_helper_path}",
158
+ function: "parseLockfile",
159
+ args: [Dir.pwd]
160
+ )
161
+ rescue SharedHelpers::HelperSubprocessFailed
162
+ raise Dependabot::DependencyFileNotParseable, yarn_lock.path
163
+ end
164
+ end
165
+
166
+ def yarn_helper_path
167
+ NativeHelpers.yarn_helper_path
168
+ end
169
+
170
+ def package_locks
171
+ @package_locks ||=
172
+ dependency_files.
173
+ select { |f| f.name.end_with?("package-lock.json") }
174
+ end
175
+
176
+ def yarn_locks
177
+ @yarn_locks ||=
178
+ dependency_files.
179
+ select { |f| f.name.end_with?("yarn.lock") }
180
+ end
181
+
182
+ def shrinkwraps
183
+ @shrinkwraps ||=
184
+ dependency_files.
185
+ select { |f| f.name.end_with?("npm-shrinkwrap.json") }
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "dependabot/utils"
4
- require "dependabot/dependency_file"
5
- require "dependabot/npm_and_yarn/file_parser"
6
4
  require "dependabot/npm_and_yarn/version"
5
+ require "dependabot/npm_and_yarn/file_parser/lockfile_parser"
7
6
 
8
7
  # Used in the sub dependency version resolver and file updater to only run
9
8
  # yarn/npm helpers on dependency files that require updates. This is useful for
@@ -18,41 +17,35 @@ module Dependabot
18
17
  end
19
18
 
20
19
  def files_requiring_update
21
- lockfiles.select do |lockfile|
22
- sub_dependencies(lockfile).any? do |sub_dep|
23
- updated_dependencies.any? do |updated_dep|
24
- next false unless sub_dep.name == updated_dep.name
20
+ @files_requiring_update ||=
21
+ begin
22
+ lockfiles.select do |lockfile|
23
+ lockfile_dependencies(lockfile).any? do |sub_dep|
24
+ updated_dependencies.any? do |updated_dep|
25
+ next false unless sub_dep.name == updated_dep.name
25
26
 
26
- version_class.new(updated_dep.version) >
27
- version_class.new(sub_dep.version)
27
+ version_class.new(updated_dep.version) >
28
+ version_class.new(sub_dep.version)
29
+ end
30
+ end
28
31
  end
29
32
  end
30
- end
31
33
  end
32
34
 
33
35
  private
34
36
 
35
37
  attr_reader :dependency_files, :updated_dependencies
36
38
 
37
- def sub_dependencies(lockfile)
38
- # Add dummy_package_manifest to keep existing validation login in base
39
- # file parser
40
- NpmAndYarn::FileParser.new(
41
- dependency_files: [dummy_package_manifest, lockfile],
42
- source: nil,
43
- credentials: [] # Credentials are only needed for top level deps
44
- ).parse
39
+ def lockfile_dependencies(lockfile)
40
+ @lockfile_dependencies ||= {}
41
+ @lockfile_dependencies[lockfile.name] ||=
42
+ NpmAndYarn::FileParser::LockfileParser.new(
43
+ dependency_files: [lockfile]
44
+ ).parse
45
45
  end
46
46
 
47
47
  def lockfiles
48
- @lockfiles ||= dependency_files.select { |file| lockfile?(file) }
49
- end
50
-
51
- def dummy_package_manifest
52
- @dummy_package_manifest ||= Dependabot::DependencyFile.new(
53
- content: "{}",
54
- name: "package.json"
55
- )
48
+ dependency_files.select { |file| lockfile?(file) }
56
49
  end
57
50
 
58
51
  def lockfile?(file)
@@ -96,7 +96,6 @@ module Dependabot
96
96
 
97
97
  updates << { dependency: dep, version: updated_version }
98
98
  end
99
-
100
99
  updates
101
100
  end
102
101
 
@@ -238,12 +237,21 @@ module Dependabot
238
237
  return [] if relevant_unmet_peer_dependencies.empty?
239
238
 
240
239
  # Prune out any pre-existing warnings
241
- relevant_unmet_peer_dependencies.reject do |issue|
240
+ issues = relevant_unmet_peer_dependencies.reject do |issue|
242
241
  old_unmet_peer_dependencies.any? do |old_issue|
243
242
  old_issue.slice(:requirement_name, :requiring_dep_name) ==
244
243
  issue.slice(:requirement_name, :requiring_dep_name)
245
244
  end
246
245
  end
246
+
247
+ # If we find duplicate errors it probably means we have double run the
248
+ # checker on the same files and want to hear about it
249
+ if issues.length != issues.uniq.length
250
+ duplicate = issues.find { |i| issues.count(i) > 1 }
251
+ raise "Duplicate peer dep error: #{duplicate[:requiring_dep_name]}"
252
+ end
253
+
254
+ issues
247
255
  end
248
256
 
249
257
  def satisfying_versions
@@ -394,7 +402,7 @@ module Dependabot
394
402
  def write_lock_files
395
403
  yarn_locks.each do |f|
396
404
  FileUtils.mkdir_p(Pathname.new(f.name).dirname)
397
- File.write(f.name, prepared_yarn_lockfile_content(f.content))
405
+ File.write(f.name, f.content)
398
406
  end
399
407
 
400
408
  package_locks.each do |f|
@@ -408,10 +416,6 @@ module Dependabot
408
416
  end
409
417
  end
410
418
 
411
- def prepared_yarn_lockfile_content(content)
412
- content.gsub(/^#{Regexp.quote(dependency.name)}\@.*?\n\n/m, "")
413
- end
414
-
415
419
  def prepared_package_json_content(file)
416
420
  NpmAndYarn::FileUpdater::PackageJsonPreparer.new(
417
421
  package_json_content: file.content
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-npm_and_yarn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.95.55
4
+ version: 0.95.56
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.95.55
19
+ version: 0.95.56
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.95.55
26
+ version: 0.95.56
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: byebug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -184,6 +184,7 @@ files:
184
184
  - lib/dependabot/npm_and_yarn/file_fetcher.rb
185
185
  - lib/dependabot/npm_and_yarn/file_fetcher/path_dependency_builder.rb
186
186
  - lib/dependabot/npm_and_yarn/file_parser.rb
187
+ - lib/dependabot/npm_and_yarn/file_parser/lockfile_parser.rb
187
188
  - lib/dependabot/npm_and_yarn/file_updater.rb
188
189
  - lib/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater.rb
189
190
  - lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb