dependabot-cargo 0.81.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 +7 -0
- data/lib/dependabot/cargo.rb +11 -0
- data/lib/dependabot/cargo/file_fetcher.rb +241 -0
- data/lib/dependabot/cargo/file_parser.rb +214 -0
- data/lib/dependabot/cargo/file_updater.rb +83 -0
- data/lib/dependabot/cargo/file_updater/lockfile_updater.rb +247 -0
- data/lib/dependabot/cargo/file_updater/manifest_updater.rb +158 -0
- data/lib/dependabot/cargo/metadata_finder.rb +62 -0
- data/lib/dependabot/cargo/requirement.rb +108 -0
- data/lib/dependabot/cargo/update_checker.rb +283 -0
- data/lib/dependabot/cargo/update_checker/file_preparer.rb +200 -0
- data/lib/dependabot/cargo/update_checker/requirements_updater.rb +173 -0
- data/lib/dependabot/cargo/update_checker/version_resolver.rb +239 -0
- data/lib/dependabot/cargo/version.rb +34 -0
- metadata +183 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 9a15f5a5286fc161d2f722711b599016486490abb64c446631eeed673a9a7742
|
|
4
|
+
data.tar.gz: d01689805661704379ea8b2ccd1795dd674fcf7c5c6a8c0de8680d64dfd08a31
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e3bcff1df9f77bc8b94230cff603352c84dab68e7c4f2648c952e32b02ad2a186a2052e4cd5d862c7e59cb19c247e1772b720e3ccf69c81dbfd94943406151b0
|
|
7
|
+
data.tar.gz: cf7de24ba36776e1b0377caf4a73f99eeb172f432c32c2f9ae18dad0c04b08ea8b3652aee5319f4a2a70f12bc630ea7419ac40b75349c2217260a6bac0d46244
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# These all need to be required so the various classes can be registered in a
|
|
4
|
+
# lookup table of package manager names to concrete classes.
|
|
5
|
+
require "dependabot/cargo/file_fetcher"
|
|
6
|
+
require "dependabot/cargo/file_parser"
|
|
7
|
+
require "dependabot/cargo/update_checker"
|
|
8
|
+
require "dependabot/cargo/file_updater"
|
|
9
|
+
require "dependabot/cargo/metadata_finder"
|
|
10
|
+
require "dependabot/cargo/requirement"
|
|
11
|
+
require "dependabot/cargo/version"
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "pathname"
|
|
4
|
+
require "toml-rb"
|
|
5
|
+
|
|
6
|
+
require "dependabot/file_fetchers"
|
|
7
|
+
require "dependabot/file_fetchers/base"
|
|
8
|
+
require "dependabot/cargo/file_parser"
|
|
9
|
+
|
|
10
|
+
# Docs on Cargo workspaces:
|
|
11
|
+
# https://doc.rust-lang.org/cargo/reference/manifest.html#the-workspace-section
|
|
12
|
+
module Dependabot
|
|
13
|
+
module Cargo
|
|
14
|
+
class FileFetcher < Dependabot::FileFetchers::Base
|
|
15
|
+
def self.required_files_in?(filenames)
|
|
16
|
+
filenames.include?("Cargo.toml")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.required_files_message
|
|
20
|
+
"Repo must contain a Cargo.toml."
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def fetch_files
|
|
26
|
+
fetched_files = []
|
|
27
|
+
fetched_files << cargo_toml
|
|
28
|
+
fetched_files << cargo_lock if cargo_lock
|
|
29
|
+
fetched_files << rust_toolchain if rust_toolchain
|
|
30
|
+
fetched_files += workspace_files
|
|
31
|
+
fetched_files += path_dependency_files
|
|
32
|
+
fetched_files
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def workspace_files
|
|
36
|
+
@workspace_files ||=
|
|
37
|
+
fetch_workspace_files(
|
|
38
|
+
file: cargo_toml,
|
|
39
|
+
previously_fetched_files: []
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def path_dependency_files
|
|
44
|
+
@path_dependency_files ||=
|
|
45
|
+
begin
|
|
46
|
+
fetched_path_dependency_files = []
|
|
47
|
+
[cargo_toml, *workspace_files].each do |file|
|
|
48
|
+
fetched_path_dependency_files +=
|
|
49
|
+
fetch_path_dependency_files(
|
|
50
|
+
file: file,
|
|
51
|
+
previously_fetched_files: [cargo_toml, *workspace_files] +
|
|
52
|
+
fetched_path_dependency_files
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
fetched_path_dependency_files
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def fetch_workspace_files(file:, previously_fetched_files:)
|
|
61
|
+
current_dir = file.name.split("/")[0..-2].join("/")
|
|
62
|
+
current_dir = nil if current_dir == ""
|
|
63
|
+
|
|
64
|
+
workspace_dependency_paths_from_file(file).flat_map do |path|
|
|
65
|
+
path = File.join(current_dir, path) unless current_dir.nil?
|
|
66
|
+
path = Pathname.new(path).cleanpath.to_path
|
|
67
|
+
|
|
68
|
+
next if previously_fetched_files.map(&:name).include?(path)
|
|
69
|
+
next if file.name == path
|
|
70
|
+
|
|
71
|
+
fetched_file = fetch_file_from_host(path)
|
|
72
|
+
previously_fetched_files << fetched_file
|
|
73
|
+
grandchild_requirement_files =
|
|
74
|
+
fetch_workspace_files(
|
|
75
|
+
file: fetched_file,
|
|
76
|
+
previously_fetched_files: previously_fetched_files
|
|
77
|
+
)
|
|
78
|
+
[fetched_file, *grandchild_requirement_files]
|
|
79
|
+
end.compact
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def fetch_path_dependency_files(
|
|
83
|
+
file:,
|
|
84
|
+
previously_fetched_files:
|
|
85
|
+
)
|
|
86
|
+
current_dir = file.name.split("/")[0..-2].join("/")
|
|
87
|
+
current_dir = nil if current_dir == ""
|
|
88
|
+
|
|
89
|
+
path_dependency_paths_from_file(file).flat_map do |path|
|
|
90
|
+
path = File.join(current_dir, path) unless current_dir.nil?
|
|
91
|
+
path = Pathname.new(path).cleanpath.to_path
|
|
92
|
+
|
|
93
|
+
next if previously_fetched_files.map(&:name).include?(path)
|
|
94
|
+
next if file.name == path
|
|
95
|
+
|
|
96
|
+
fetched_file = fetch_file_from_host(path, type: "path_dependency").
|
|
97
|
+
tap { |f| f.support_file = true }
|
|
98
|
+
previously_fetched_files << fetched_file
|
|
99
|
+
grandchild_requirement_files =
|
|
100
|
+
fetch_path_dependency_files(
|
|
101
|
+
file: fetched_file,
|
|
102
|
+
previously_fetched_files: previously_fetched_files
|
|
103
|
+
)
|
|
104
|
+
[fetched_file, *grandchild_requirement_files]
|
|
105
|
+
rescue Dependabot::DependencyFileNotFound
|
|
106
|
+
raise if required_path?(file, path)
|
|
107
|
+
end.compact
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def path_dependency_paths_from_file(file)
|
|
111
|
+
paths = []
|
|
112
|
+
|
|
113
|
+
# Paths specified in dependency declaration
|
|
114
|
+
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
115
|
+
parsed_file(file).fetch(type, {}).each do |_, details|
|
|
116
|
+
next unless details.is_a?(Hash)
|
|
117
|
+
next unless details["path"]
|
|
118
|
+
|
|
119
|
+
paths << File.join(details["path"], "Cargo.toml")
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Paths specified for target-specific dependencies
|
|
124
|
+
parsed_file(file).fetch("target", {}).each do |_, t_details|
|
|
125
|
+
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
126
|
+
t_details.fetch(type, {}).each do |_, details|
|
|
127
|
+
next unless details.is_a?(Hash)
|
|
128
|
+
next unless details["path"]
|
|
129
|
+
|
|
130
|
+
paths << File.join(details["path"], "Cargo.toml")
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Paths specified as replacements
|
|
136
|
+
parsed_file(file).fetch("replace", {}).each do |_, details|
|
|
137
|
+
next unless details.is_a?(Hash)
|
|
138
|
+
next unless details["path"]
|
|
139
|
+
|
|
140
|
+
paths << File.join(details["path"], "Cargo.toml")
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
paths
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def workspace_dependency_paths_from_file(file)
|
|
147
|
+
workspace_paths = parsed_file(file).dig("workspace", "members")
|
|
148
|
+
return [] unless workspace_paths&.any?
|
|
149
|
+
|
|
150
|
+
# Expand any workspace paths that specify a `*`
|
|
151
|
+
workspace_paths = workspace_paths.flat_map do |path|
|
|
152
|
+
path.end_with?("*") ? expand_workspaces(path) : [path]
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Excluded paths, to be subtracted for the workspaces array
|
|
156
|
+
excluded_paths = parsed_file(file).dig("workspace", "excluded_paths")
|
|
157
|
+
|
|
158
|
+
(workspace_paths - (excluded_paths || [])).map do |path|
|
|
159
|
+
File.join(path, "Cargo.toml")
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Check whether a path is required or not. It will not be required if
|
|
164
|
+
# an alternative source (i.e., a git source) is also specified
|
|
165
|
+
# rubocop:disable Metrics/AbcSize
|
|
166
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
167
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
|
168
|
+
def required_path?(file, path)
|
|
169
|
+
# Paths specified in dependency declaration
|
|
170
|
+
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
171
|
+
parsed_file(file).fetch(type, {}).each do |_, details|
|
|
172
|
+
next unless details.is_a?(Hash)
|
|
173
|
+
next unless details["path"]
|
|
174
|
+
next unless path == File.join(details["path"], "Cargo.toml")
|
|
175
|
+
|
|
176
|
+
return true if details["git"].nil?
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Paths specified for target-specific dependencies
|
|
181
|
+
parsed_file(file).fetch("target", {}).each do |_, t_details|
|
|
182
|
+
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
183
|
+
t_details.fetch(type, {}).each do |_, details|
|
|
184
|
+
next unless details.is_a?(Hash)
|
|
185
|
+
next unless details["path"]
|
|
186
|
+
next unless path == File.join(details["path"], "Cargo.toml")
|
|
187
|
+
|
|
188
|
+
return true if details["git"].nil?
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Paths specified as replacements
|
|
194
|
+
parsed_file(file).fetch("replace", {}).each do |_, details|
|
|
195
|
+
next unless details.is_a?(Hash)
|
|
196
|
+
next unless details["path"]
|
|
197
|
+
next unless path == File.join(details["path"], "Cargo.toml")
|
|
198
|
+
|
|
199
|
+
return true if details["git"].nil?
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
false
|
|
203
|
+
end
|
|
204
|
+
# rubocop:enable Metrics/AbcSize
|
|
205
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
206
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
|
207
|
+
|
|
208
|
+
def expand_workspaces(path)
|
|
209
|
+
path = Pathname.new(path).cleanpath.to_path
|
|
210
|
+
dir = directory.gsub(%r{(^/|/$)}, "")
|
|
211
|
+
unglobbed_path = path.split("*").first.gsub(%r{(?<=/)[^/]*$}, "")
|
|
212
|
+
|
|
213
|
+
repo_contents(dir: unglobbed_path, raise_errors: false).
|
|
214
|
+
select { |file| file.type == "dir" }.
|
|
215
|
+
map { |f| f.path.gsub(%r{^/?#{Regexp.escape(dir)}/?}, "") }.
|
|
216
|
+
select { |filename| File.fnmatch?(path, filename) }
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def parsed_file(file)
|
|
220
|
+
TomlRB.parse(file.content)
|
|
221
|
+
rescue TomlRB::ParseError
|
|
222
|
+
raise Dependabot::DependencyFileNotParseable, file.path
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def cargo_toml
|
|
226
|
+
@cargo_toml ||= fetch_file_from_host("Cargo.toml")
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def cargo_lock
|
|
230
|
+
@cargo_lock ||= fetch_file_if_present("Cargo.lock")
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def rust_toolchain
|
|
234
|
+
@rust_toolchain ||= fetch_file_if_present("rust-toolchain")&.
|
|
235
|
+
tap { |f| f.support_file = true }
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
Dependabot::FileFetchers.register("cargo", Dependabot::Cargo::FileFetcher)
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "toml-rb"
|
|
4
|
+
|
|
5
|
+
require "dependabot/dependency"
|
|
6
|
+
require "dependabot/file_parsers"
|
|
7
|
+
require "dependabot/file_parsers/base"
|
|
8
|
+
require "dependabot/cargo/requirement"
|
|
9
|
+
require "dependabot/cargo/version"
|
|
10
|
+
require "dependabot/errors"
|
|
11
|
+
|
|
12
|
+
# Relevant Cargo docs can be found at:
|
|
13
|
+
# - https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
14
|
+
# - https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
|
|
15
|
+
module Dependabot
|
|
16
|
+
module Cargo
|
|
17
|
+
class FileParser < Dependabot::FileParsers::Base
|
|
18
|
+
require "dependabot/file_parsers/base/dependency_set"
|
|
19
|
+
|
|
20
|
+
DEPENDENCY_TYPES =
|
|
21
|
+
%w(dependencies dev-dependencies build-dependencies).freeze
|
|
22
|
+
|
|
23
|
+
def parse
|
|
24
|
+
check_rust_workspace_root
|
|
25
|
+
|
|
26
|
+
dependency_set = DependencySet.new
|
|
27
|
+
dependency_set += manifest_dependencies
|
|
28
|
+
dependency_set += lockfile_dependencies if lockfile
|
|
29
|
+
|
|
30
|
+
dependencies = dependency_set.dependencies
|
|
31
|
+
|
|
32
|
+
# TODO: Handle patched dependencies
|
|
33
|
+
dependencies.reject! { |d| patched_dependencies.include?(d.name) }
|
|
34
|
+
|
|
35
|
+
# TODO: Currently, Dependabot can't handle dependencies that have
|
|
36
|
+
# multiple source types. Fix that!
|
|
37
|
+
dependencies.reject do |dep|
|
|
38
|
+
dep.requirements.map { |r| r.dig(:source, :type) }.uniq.count > 1
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def check_rust_workspace_root
|
|
45
|
+
cargo_toml = dependency_files.find { |f| f.name == "Cargo.toml" }
|
|
46
|
+
workspace_root = parsed_file(cargo_toml).dig("package", "workspace")
|
|
47
|
+
return unless workspace_root
|
|
48
|
+
|
|
49
|
+
msg = "This project is part of a Rust workspace but is not the "\
|
|
50
|
+
"workspace root."\
|
|
51
|
+
|
|
52
|
+
if cargo_toml.directory != "/"
|
|
53
|
+
msg += "Please update your settings so Dependabot points at the "\
|
|
54
|
+
"workspace root instead of #{cargo_toml.directory}."
|
|
55
|
+
end
|
|
56
|
+
raise Dependabot::DependencyFileNotEvaluatable, msg
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def manifest_dependencies
|
|
60
|
+
dependency_set = DependencySet.new
|
|
61
|
+
|
|
62
|
+
DEPENDENCY_TYPES.each do |type|
|
|
63
|
+
manifest_files.each do |file|
|
|
64
|
+
parsed_file(file).fetch(type, {}).each do |name, requirement|
|
|
65
|
+
next if lockfile && !version_from_lockfile(name, requirement)
|
|
66
|
+
|
|
67
|
+
dependency_set << Dependency.new(
|
|
68
|
+
name: name,
|
|
69
|
+
version: version_from_lockfile(name, requirement),
|
|
70
|
+
package_manager: "cargo",
|
|
71
|
+
requirements: [{
|
|
72
|
+
requirement: requirement_from_declaration(requirement),
|
|
73
|
+
file: file.name,
|
|
74
|
+
groups: [type],
|
|
75
|
+
source: source_from_declaration(requirement)
|
|
76
|
+
}]
|
|
77
|
+
)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
dependency_set
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def lockfile_dependencies
|
|
86
|
+
dependency_set = DependencySet.new
|
|
87
|
+
return dependency_set unless lockfile
|
|
88
|
+
|
|
89
|
+
parsed_file(lockfile).fetch("package", []).each do |package_details|
|
|
90
|
+
next unless package_details["source"]
|
|
91
|
+
|
|
92
|
+
# TODO: This isn't quite right, as it will only give us one
|
|
93
|
+
# version of each dependency (when in fact there are many)
|
|
94
|
+
dependency_set << Dependency.new(
|
|
95
|
+
name: package_details["name"],
|
|
96
|
+
version: version_from_lockfile_details(package_details),
|
|
97
|
+
package_manager: "cargo",
|
|
98
|
+
requirements: []
|
|
99
|
+
)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
dependency_set
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def patched_dependencies
|
|
106
|
+
root_manifest = manifest_files.find { |f| f.name == "Cargo.toml" }
|
|
107
|
+
return [] unless parsed_file(root_manifest)["patch"]
|
|
108
|
+
|
|
109
|
+
parsed_file(root_manifest)["patch"].values.flat_map(&:keys)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def requirement_from_declaration(declaration)
|
|
113
|
+
if declaration.is_a?(String)
|
|
114
|
+
return declaration == "" ? nil : declaration
|
|
115
|
+
end
|
|
116
|
+
unless declaration.is_a?(Hash)
|
|
117
|
+
raise "Unexpected dependency declaration: #{declaration}"
|
|
118
|
+
end
|
|
119
|
+
return declaration["version"] if declaration["version"]
|
|
120
|
+
|
|
121
|
+
nil
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def source_from_declaration(declaration)
|
|
125
|
+
return if declaration.is_a?(String)
|
|
126
|
+
unless declaration.is_a?(Hash)
|
|
127
|
+
raise "Unexpected dependency declaration: #{declaration}"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
return git_source_details(declaration) if declaration["git"]
|
|
131
|
+
return { type: "path" } if declaration["path"]
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def version_from_lockfile(name, declaration)
|
|
135
|
+
return unless lockfile
|
|
136
|
+
|
|
137
|
+
candidate_packages =
|
|
138
|
+
parsed_file(lockfile).fetch("package", []).
|
|
139
|
+
select { |p| p["name"] == name }
|
|
140
|
+
|
|
141
|
+
if (req = requirement_from_declaration(declaration))
|
|
142
|
+
req = Cargo::Requirement.new(req)
|
|
143
|
+
|
|
144
|
+
candidate_packages =
|
|
145
|
+
candidate_packages.
|
|
146
|
+
select { |p| req.satisfied_by?(version_class.new(p["version"])) }
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
candidate_packages =
|
|
150
|
+
candidate_packages.
|
|
151
|
+
select do |p|
|
|
152
|
+
git_req?(declaration) ^ !p["source"]&.start_with?("git+")
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
package =
|
|
156
|
+
candidate_packages.
|
|
157
|
+
max_by { |p| version_class.new(p["version"]) }
|
|
158
|
+
|
|
159
|
+
return unless package
|
|
160
|
+
|
|
161
|
+
version_from_lockfile_details(package)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def git_req?(declaration)
|
|
165
|
+
source_from_declaration(declaration)&.fetch(:type, nil) == "git"
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def git_source_details(declaration)
|
|
169
|
+
{
|
|
170
|
+
type: "git",
|
|
171
|
+
url: declaration["git"],
|
|
172
|
+
branch: declaration["branch"],
|
|
173
|
+
ref: declaration["tag"] || declaration["rev"]
|
|
174
|
+
}
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def version_from_lockfile_details(package_details)
|
|
178
|
+
unless package_details["source"]&.start_with?("git+")
|
|
179
|
+
return package_details["version"]
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
package_details["source"].split("#").last
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def check_required_files
|
|
186
|
+
raise "No Cargo.toml!" unless get_original_file("Cargo.toml")
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def parsed_file(file)
|
|
190
|
+
@parsed_file ||= {}
|
|
191
|
+
@parsed_file[file.name] ||= TomlRB.parse(file.content)
|
|
192
|
+
rescue TomlRB::ParseError
|
|
193
|
+
raise Dependabot::DependencyFileNotParseable, file.path
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def manifest_files
|
|
197
|
+
@manifest_files ||=
|
|
198
|
+
dependency_files.
|
|
199
|
+
select { |f| f.name.end_with?("Cargo.toml") }.
|
|
200
|
+
reject { |f| f.type == "path_dependency" }
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def lockfile
|
|
204
|
+
@lockfile ||= get_original_file("Cargo.lock")
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def version_class
|
|
208
|
+
Cargo::Version
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
Dependabot::FileParsers.register("cargo", Dependabot::Cargo::FileParser)
|