豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 50d1d25

Browse files
committed
Inject the file_parser and use its attributes, Add a prepare! hook
1 parent b02739b commit 50d1d25

File tree

6 files changed

+41
-51
lines changed

6 files changed

+41
-51
lines changed

bundler/spec/dependabot/bundler/dependency_grapher_spec.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
context "with a bundler project" do
1111
subject(:grapher) do
1212
Dependabot::DependencyGraphers.for_package_manager("bundler").new(
13-
dependency_files:,
14-
dependencies:
13+
file_parser: parser
1514
)
1615
end
1716

@@ -36,6 +35,8 @@
3635

3736
let(:dependencies) { parser.parse }
3837

38+
before { grapher.prepare! }
39+
3940
# NOTE: This documents existing behaviour where Gemfile PURLs do not include a resolved version
4041
#
4142
# Package URLs deal in resolved versions, so for a Gemfile only project we only have a range

common/lib/dependabot/dependency_graphers/base.rb

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,16 @@ class Base
1313

1414
abstract!
1515

16-
# TODO(brrygrdn): Inject the Dependency parser instead of pre-parsed `dependencies`
17-
#
18-
# Semantically it makes sense for the grapher to wrap the parser as a higher order function, but we already know
19-
# that some package managers will require extra native commands before, after or during the parse - in extreme
20-
# cases it may make sense to use an alternative parser that is more optimal.
21-
#
22-
# By injecting the parser, this allows the ecosystem to encapsulate the package manager specifics without the
23-
# executor needing to manage parser modes / feature flags.
16+
sig { returns(T::Boolean) }
17+
attr_reader :prepared
18+
2419
sig do
25-
params(
26-
dependency_files: T::Array[Dependabot::DependencyFile],
27-
dependencies: T::Array[Dependabot::Dependency]
28-
).void
20+
params(file_parser: Dependabot::FileParsers::Base).void
2921
end
30-
def initialize(dependency_files:, dependencies:)
31-
@dependency_files = dependency_files
32-
@dependencies = dependencies
22+
def initialize(file_parser:)
23+
@file_parser = file_parser
24+
@dependencies = T.let([], T::Array[Dependabot::Dependency])
25+
@prepared = T.let(false, T::Boolean)
3326
end
3427

3528
# Each grapher must implement a heuristic to determine which dependency file should be used as the owner
@@ -40,8 +33,21 @@ def initialize(dependency_files:, dependencies:)
4033
sig { abstract.returns(Dependabot::DependencyFile) }
4134
def relevant_dependency_file; end
4235

36+
# A grapher may override this method if it needs to perform extra steps around the normal file parser for
37+
# the ecosystem.
38+
sig { void }
39+
def prepare!
40+
@dependencies = @file_parser.parse
41+
@prepared = true
42+
end
43+
4344
sig { returns(T::Hash[String, T.untyped]) }
4445
def resolved_dependencies
46+
unless prepared
47+
raise Dependabot::DependabotError,
48+
"prepare! must be called before accessing resolved_dependencies"
49+
end
50+
4551
@dependencies.each_with_object({}) do |dep, resolved|
4652
resolved[dep.name] = {
4753
package_url: build_purl(dep),
@@ -55,6 +61,14 @@ def resolved_dependencies
5561

5662
private
5763

64+
sig { returns(Dependabot::FileParsers::Base) }
65+
attr_reader :file_parser
66+
67+
sig { returns(T::Array[Dependabot::DependencyFile]) }
68+
def dependency_files
69+
file_parser.dependency_files
70+
end
71+
5872
# Each grapher is expected to implement a method to look up the parents of a given dependency.
5973
#
6074
# The strategy that should be used is highly dependent on the ecosystem, in some cases the parser

common/lib/dependabot/dependency_graphers/generic.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def relevant_dependency_file
2525

2626
sig { returns(T::Array[Dependabot::DependencyFile]) }
2727
def filtered_dependency_files
28-
@dependency_files.reject { |f| f.support_file? || f.vendored_file? }
28+
dependency_files.reject { |f| f.support_file? || f.vendored_file? }
2929
end
3030

3131
# Our generic strategy is to check if the parser has attached a `depends_on` key to the Dependency's

go_modules/lib/dependabot/go_modules/dependency_grapher.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ module GoModules
1111
class DependencyGrapher < Dependabot::DependencyGraphers::Base
1212
sig { override.returns(Dependabot::DependencyFile) }
1313
def relevant_dependency_file
14+
# This cannot realistically happen as the parser will throw a runtime error on init without a go_mod file,
15+
# but this will avoid surprises if anything changes.
1416
raise DependabotError, "No go.mod present in dependency files." unless go_mod
1517

1618
T.must(go_mod)
@@ -32,7 +34,7 @@ def go_mod
3234
return @go_mod if defined?(@go_mod)
3335

3436
@go_mod = T.let(
35-
@dependency_files.find { |f| f.name = "go.mod" },
37+
dependency_files.find { |f| f.name = "go.mod" },
3638
T.nilable(Dependabot::DependencyFile)
3739
)
3840
end

go_modules/spec/dependabot/go_modules/dependency_grapher_spec.rb

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
RSpec.describe Dependabot::GoModules::DependencyGrapher do
88
subject(:grapher) do
99
Dependabot::DependencyGraphers.for_package_manager("go_modules").new(
10-
dependency_files:,
11-
dependencies:
10+
file_parser: parser
1211
)
1312
end
1413

@@ -34,38 +33,15 @@
3433
let(:dependencies) { parser.parse }
3534
let(:dependency_files) { [go_mod] }
3635

36+
before { grapher.prepare! }
37+
3738
after do
3839
# Reset the environment variable after each test to avoid side effects
3940
ENV.delete("GOENV")
4041
ENV.delete("GOPROXY")
4142
ENV.delete("GOPRIVATE")
4243
end
4344

44-
context "when the go.mod is unexpectedly missing from dependency_files" do
45-
# This scenario is very unlikely, it would most likely result from
46-
# programmer error where the set of files passed in is malformed.
47-
subject(:grapher) do
48-
Dependabot::DependencyGraphers.for_package_manager("go_modules").new(
49-
dependency_files: [],
50-
dependencies:
51-
)
52-
end
53-
54-
let(:go_mod) do
55-
Dependabot::DependencyFile.new(
56-
name: "go.mod",
57-
content: fixture("go_mods", "go.mod"),
58-
directory: "/"
59-
)
60-
end
61-
62-
describe "#relevant_dependency_file" do
63-
it "throws an exception" do
64-
expect { grapher.relevant_dependency_file }.to raise_error(Dependabot::DependabotError, /No go.mod present/)
65-
end
66-
end
67-
end
68-
6945
context "with a simple project" do
7046
let(:go_mod) do
7147
Dependabot::DependencyFile.new(

updater/lib/dependabot/update_graph_processor.rb

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ def dependency_files_for(directory)
9696
).returns(GithubApi::DependencySubmission)
9797
end
9898
def create_submission(source, files)
99-
# TODO(brrygrdn): Refactor the grapher to wrap the parser call
10099
parser = Dependabot::FileParsers.for_package_manager(job.package_manager).new(
101100
dependency_files: files,
102101
repo_contents_path: job.repo_contents_path,
@@ -106,10 +105,8 @@ def create_submission(source, files)
106105
options: job.experiments
107106
)
108107

109-
grapher = Dependabot::DependencyGraphers.for_package_manager(job.package_manager).new(
110-
dependency_files: files,
111-
dependencies: parser.parse
112-
)
108+
grapher = Dependabot::DependencyGraphers.for_package_manager(job.package_manager).new(file_parser: parser)
109+
grapher.prepare!
113110

114111
GithubApi::DependencySubmission.new(
115112
job_id: job.id.to_s,

0 commit comments

Comments
 (0)