dependabot-sbt 0.377.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/sbt/file_fetcher.rb +121 -0
- data/lib/dependabot/sbt/file_parser/property_value_finder.rb +179 -0
- data/lib/dependabot/sbt/file_parser/repositories_finder.rb +141 -0
- data/lib/dependabot/sbt/file_parser.rb +468 -0
- data/lib/dependabot/sbt/file_updater/property_value_updater.rb +28 -0
- data/lib/dependabot/sbt/file_updater.rb +240 -0
- data/lib/dependabot/sbt/language.rb +24 -0
- data/lib/dependabot/sbt/metadata_finder.rb +24 -0
- data/lib/dependabot/sbt/native_helpers.rb +28 -0
- data/lib/dependabot/sbt/package/package_details_fetcher.rb +175 -0
- data/lib/dependabot/sbt/package_manager.rb +39 -0
- data/lib/dependabot/sbt/requirement.rb +64 -0
- data/lib/dependabot/sbt/update_checker/requirements_updater.rb +98 -0
- data/lib/dependabot/sbt/update_checker/version_finder.rb +76 -0
- data/lib/dependabot/sbt/update_checker.rb +177 -0
- data/lib/dependabot/sbt/version.rb +21 -0
- data/lib/dependabot/sbt.rb +19 -0
- metadata +298 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 9eafbe53d441a9d8b07914410bf4dc22012c56e3dc2cf3b57908c6024da99c27
|
|
4
|
+
data.tar.gz: a308cafa02b00033ad80af59a511fa44b30748052fc230aa9a74ec93e86b3d85
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 543b3691a28a571bf6cdfdf53af5e4fcf517190f51481944a8e62ecfab0218a30511ed16f7363851ca138e6ef047ba8bf17f41217ac51f6390e9ebfba94b5698
|
|
7
|
+
data.tar.gz: c2e1ee2eaf7055654ff518174718ee4f3a1afadea6724a69e0adff2d77453cfddf19452abdfcfef4ad858e478867bef303d9cbcac5c231ae8d7e759c826ea019
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
|
|
6
|
+
require "dependabot/file_fetchers"
|
|
7
|
+
require "dependabot/file_fetchers/base"
|
|
8
|
+
require "dependabot/file_filtering"
|
|
9
|
+
|
|
10
|
+
module Dependabot
|
|
11
|
+
module Sbt
|
|
12
|
+
class FileFetcher < Dependabot::FileFetchers::Base
|
|
13
|
+
extend T::Sig
|
|
14
|
+
extend T::Helpers
|
|
15
|
+
|
|
16
|
+
BUILD_SBT_FILENAME = "build.sbt"
|
|
17
|
+
PLUGINS_SBT_FILENAME = "project/plugins.sbt"
|
|
18
|
+
BUILD_PROPERTIES_FILENAME = "project/build.properties"
|
|
19
|
+
# Directories that are part of the SBT build structure, not subprojects
|
|
20
|
+
NON_SUBPROJECT_DIRS = T.let(%w(project target .git .github).freeze, T::Array[String])
|
|
21
|
+
|
|
22
|
+
sig { override.params(filenames: T::Array[String]).returns(T::Boolean) }
|
|
23
|
+
def self.required_files_in?(filenames)
|
|
24
|
+
filenames.any? { |name| name.end_with?(BUILD_SBT_FILENAME) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
sig { override.returns(String) }
|
|
28
|
+
def self.required_files_message
|
|
29
|
+
"Repo must contain a build.sbt file."
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
sig { override.returns(T::Array[DependencyFile]) }
|
|
33
|
+
def fetch_files
|
|
34
|
+
unless allow_beta_ecosystems?
|
|
35
|
+
raise Dependabot::DependencyFileNotFound.new(
|
|
36
|
+
nil,
|
|
37
|
+
"Sbt support is currently in beta. Enable the beta ecosystems experiment to use it " \
|
|
38
|
+
"(for example, run bin/dry-run.rb --enable-beta-ecosystems)."
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
fetched_files = T.let([], T::Array[DependencyFile])
|
|
43
|
+
|
|
44
|
+
fetched_files << build_sbt
|
|
45
|
+
fetched_files << T.must(plugins_sbt) if plugins_sbt
|
|
46
|
+
fetched_files << T.must(build_properties) if build_properties
|
|
47
|
+
fetched_files += subproject_build_files
|
|
48
|
+
fetched_files += project_scala_files
|
|
49
|
+
|
|
50
|
+
fetched_files.reject do |file|
|
|
51
|
+
Dependabot::FileFiltering.should_exclude_path?(file.name, "file from final collection", @exclude_paths)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
sig { override.returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
|
56
|
+
def ecosystem_versions
|
|
57
|
+
return nil unless build_properties
|
|
58
|
+
|
|
59
|
+
sbt_version = parse_sbt_version(T.must(build_properties).content)
|
|
60
|
+
return nil unless sbt_version
|
|
61
|
+
|
|
62
|
+
{
|
|
63
|
+
package_managers: {
|
|
64
|
+
"sbt" => sbt_version
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
sig { returns(DependencyFile) }
|
|
72
|
+
def build_sbt
|
|
73
|
+
@build_sbt ||= T.let(fetch_file_from_host(BUILD_SBT_FILENAME), T.nilable(DependencyFile))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
sig { returns(T.nilable(DependencyFile)) }
|
|
77
|
+
def plugins_sbt
|
|
78
|
+
@plugins_sbt ||= T.let(fetch_file_if_present(PLUGINS_SBT_FILENAME), T.nilable(DependencyFile))
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
sig { returns(T.nilable(DependencyFile)) }
|
|
82
|
+
def build_properties
|
|
83
|
+
@build_properties ||= T.let(fetch_file_if_present(BUILD_PROPERTIES_FILENAME), T.nilable(DependencyFile))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
87
|
+
def subproject_build_files
|
|
88
|
+
repo_contents(raise_errors: false)
|
|
89
|
+
.select { |item| item.type == "dir" }
|
|
90
|
+
.reject { |dir| NON_SUBPROJECT_DIRS.include?(dir.name) }
|
|
91
|
+
.reject { |dir| Dependabot::FileFiltering.should_exclude_path?(dir.name, "subproject directory", @exclude_paths) }
|
|
92
|
+
.filter_map { |dir| fetch_file_if_present(File.join(dir.name, BUILD_SBT_FILENAME)) }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
96
|
+
def project_scala_files
|
|
97
|
+
project_dir_contents = repo_contents(dir: "project", raise_errors: false)
|
|
98
|
+
project_dir_contents
|
|
99
|
+
.select { |item| item.type == "file" && item.name.end_with?(".scala") }
|
|
100
|
+
.filter_map { |item| fetch_file_if_present(File.join("project", item.name)) }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
sig { params(content: T.nilable(String)).returns(T.nilable(String)) }
|
|
104
|
+
def parse_sbt_version(content)
|
|
105
|
+
return nil unless content
|
|
106
|
+
|
|
107
|
+
content.each_line do |line|
|
|
108
|
+
line = line.strip
|
|
109
|
+
next if line.empty? || line.start_with?("#", "!")
|
|
110
|
+
|
|
111
|
+
match = line.match(/\Asbt\.version\s*=\s*(.+)\z/)
|
|
112
|
+
return match[1]&.strip if match
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
nil
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
Dependabot::FileFetchers.register("sbt", Dependabot::Sbt::FileFetcher)
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
|
|
6
|
+
require "dependabot/sbt/file_parser"
|
|
7
|
+
|
|
8
|
+
module Dependabot
|
|
9
|
+
module Sbt
|
|
10
|
+
class FileParser < Dependabot::FileParsers::Base
|
|
11
|
+
class PropertyValueFinder
|
|
12
|
+
extend T::Sig
|
|
13
|
+
|
|
14
|
+
# Matches: val someVersion = "1.2.3"
|
|
15
|
+
# Also: val someVersion: String = "1.2.3"
|
|
16
|
+
# Also: lazy val someVersion = "1.2.3"
|
|
17
|
+
VAL_DECLARATION_REGEX = T.let(
|
|
18
|
+
/(?:^|\s)(?:lazy\s+)?val\s+(?<name>\w+)(?:\s*:\s*String)?\s*=\s*"(?<value>[^"]+)"/,
|
|
19
|
+
Regexp
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
sig { params(dependency_files: T::Array[Dependabot::DependencyFile]).void }
|
|
23
|
+
def initialize(dependency_files:)
|
|
24
|
+
@dependency_files = T.let(dependency_files, T::Array[Dependabot::DependencyFile])
|
|
25
|
+
@properties = T.let({}, T::Hash[String, T::Hash[String, T::Hash[Symbol, String]]])
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
sig do
|
|
29
|
+
params(property_name: String, callsite_buildfile: Dependabot::DependencyFile)
|
|
30
|
+
.returns(T.nilable(T::Hash[Symbol, String]))
|
|
31
|
+
end
|
|
32
|
+
def property_details(property_name:, callsite_buildfile:)
|
|
33
|
+
# Handle dotted references like "V.scalafixVersion" by looking up the member name
|
|
34
|
+
if property_name.include?(".")
|
|
35
|
+
return dotted_property_details(property_name: property_name, callsite_buildfile: callsite_buildfile)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Look in the callsite file first, then fall back to the root build.sbt,
|
|
39
|
+
# then check project/*.scala build definition files
|
|
40
|
+
all_files = [callsite_buildfile, top_level_buildfile].compact
|
|
41
|
+
all_files += project_scala_files
|
|
42
|
+
all_files.uniq!
|
|
43
|
+
all_files.each do |file|
|
|
44
|
+
details = properties(file).fetch(property_name, nil)
|
|
45
|
+
return details if details
|
|
46
|
+
end
|
|
47
|
+
nil
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
sig { params(property_name: String, callsite_buildfile: Dependabot::DependencyFile).returns(T.nilable(String)) }
|
|
51
|
+
def property_value(property_name:, callsite_buildfile:)
|
|
52
|
+
property_details(
|
|
53
|
+
property_name: property_name,
|
|
54
|
+
callsite_buildfile: callsite_buildfile
|
|
55
|
+
)&.fetch(:value)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
61
|
+
attr_reader :dependency_files
|
|
62
|
+
|
|
63
|
+
# Resolves dotted property references like "Versions.catsVersion" or "V.scala212".
|
|
64
|
+
# Searches for `val <member> = "..."` inside `object <ObjectName> { ... }` blocks
|
|
65
|
+
# across all dependency files.
|
|
66
|
+
sig do
|
|
67
|
+
params(property_name: String, callsite_buildfile: Dependabot::DependencyFile)
|
|
68
|
+
.returns(T.nilable(T::Hash[Symbol, String]))
|
|
69
|
+
end
|
|
70
|
+
def dotted_property_details(property_name:, callsite_buildfile:)
|
|
71
|
+
parts = property_name.split(".")
|
|
72
|
+
return nil unless parts.length == 2
|
|
73
|
+
|
|
74
|
+
object_name = T.must(parts.first)
|
|
75
|
+
member_name = T.must(parts.last)
|
|
76
|
+
|
|
77
|
+
# Resolve val aliases (e.g. "val V = BuildInfo" means V.x should look in object BuildInfo)
|
|
78
|
+
resolved_names = resolve_object_aliases(object_name, callsite_buildfile)
|
|
79
|
+
|
|
80
|
+
all_files = [callsite_buildfile, top_level_buildfile].compact
|
|
81
|
+
all_files += project_scala_files
|
|
82
|
+
all_files.uniq!
|
|
83
|
+
|
|
84
|
+
resolved_names.each do |resolved_name|
|
|
85
|
+
all_files.each do |file|
|
|
86
|
+
content = prepared_content(file)
|
|
87
|
+
object_regex = /object\s+#{Regexp.quote(resolved_name)}\b[^{]*\{(?<body>[^}]*)\}/m
|
|
88
|
+
content.scan(object_regex) do
|
|
89
|
+
body = T.must(Regexp.last_match).named_captures.fetch("body")
|
|
90
|
+
member_regex = /(?:^|\s)(?:lazy\s+)?val\s+#{Regexp.quote(member_name)}/
|
|
91
|
+
member_value_regex = /#{member_regex}(?:\s*:\s*String)?\s*=\s*"(?<value>[^"]+)"/
|
|
92
|
+
member_match = body&.match(member_value_regex)
|
|
93
|
+
next unless member_match
|
|
94
|
+
|
|
95
|
+
declaration_string = member_match.to_s.strip
|
|
96
|
+
return {
|
|
97
|
+
value: T.must(member_match[:value]),
|
|
98
|
+
declaration_string: declaration_string,
|
|
99
|
+
file: file.name
|
|
100
|
+
}
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
nil
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Resolves val aliases like "val V = BuildInfo" → returns ["V", "BuildInfo"]
|
|
109
|
+
# so that dotted references like V.member can look in object BuildInfo.
|
|
110
|
+
sig { params(name: String, callsite_buildfile: Dependabot::DependencyFile).returns(T::Array[String]) }
|
|
111
|
+
def resolve_object_aliases(name, callsite_buildfile)
|
|
112
|
+
names = [name]
|
|
113
|
+
|
|
114
|
+
all_files = [callsite_buildfile, top_level_buildfile].compact
|
|
115
|
+
all_files += project_scala_files
|
|
116
|
+
all_files.uniq!
|
|
117
|
+
|
|
118
|
+
all_files.each do |file|
|
|
119
|
+
prepared_content(file).scan(/(?:^|\s)(?:lazy\s+)?val\s+#{Regexp.quote(name)}\s*=\s*(?<target>[A-Z]\w*)/) do
|
|
120
|
+
target = T.must(Regexp.last_match).named_captures.fetch("target")
|
|
121
|
+
names << T.must(target) unless names.include?(target)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
names
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
sig { params(buildfile: Dependabot::DependencyFile).returns(T::Hash[String, T::Hash[Symbol, String]]) }
|
|
129
|
+
def properties(buildfile)
|
|
130
|
+
@properties[buildfile.name] ||= fetch_val_declarations(buildfile)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
sig { params(buildfile: Dependabot::DependencyFile).returns(T::Hash[String, T::Hash[Symbol, String]]) }
|
|
134
|
+
def fetch_val_declarations(buildfile)
|
|
135
|
+
props = T.let({}, T::Hash[String, T::Hash[Symbol, String]])
|
|
136
|
+
|
|
137
|
+
prepared_content(buildfile).scan(VAL_DECLARATION_REGEX) do
|
|
138
|
+
captures = T.must(Regexp.last_match).named_captures
|
|
139
|
+
name = T.must(captures.fetch("name"))
|
|
140
|
+
value = T.must(captures.fetch("value"))
|
|
141
|
+
|
|
142
|
+
unless props.key?(name)
|
|
143
|
+
props[name] = {
|
|
144
|
+
value: value,
|
|
145
|
+
declaration_string: Regexp.last_match.to_s.strip,
|
|
146
|
+
file: buildfile.name
|
|
147
|
+
}
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
props
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
sig { params(buildfile: Dependabot::DependencyFile).returns(String) }
|
|
155
|
+
def prepared_content(buildfile)
|
|
156
|
+
T.must(buildfile.content)
|
|
157
|
+
.gsub(%r{(?<=^|\s)//.*$}, "\n")
|
|
158
|
+
.gsub(%r{(?<=^|\s)/\*.*?\*/}m, "")
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
|
162
|
+
def top_level_buildfile
|
|
163
|
+
@top_level_buildfile ||= T.let(
|
|
164
|
+
dependency_files.find { |f| f.name == "build.sbt" },
|
|
165
|
+
T.nilable(Dependabot::DependencyFile)
|
|
166
|
+
)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
170
|
+
def project_scala_files
|
|
171
|
+
@project_scala_files ||= T.let(
|
|
172
|
+
dependency_files.select { |f| f.name.end_with?(".scala") && f.name.start_with?("project/") },
|
|
173
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
|
174
|
+
)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
|
|
6
|
+
require "dependabot/sbt/file_parser"
|
|
7
|
+
|
|
8
|
+
module Dependabot
|
|
9
|
+
module Sbt
|
|
10
|
+
class FileParser < Dependabot::FileParsers::Base
|
|
11
|
+
class RepositoriesFinder
|
|
12
|
+
extend T::Sig
|
|
13
|
+
|
|
14
|
+
CENTRAL_REPO_URL = "https://repo.maven.apache.org/maven2"
|
|
15
|
+
|
|
16
|
+
# Matches: resolvers += "Name" at "https://url"
|
|
17
|
+
RESOLVER_AT_REGEX = T.let(
|
|
18
|
+
/resolvers\s*\+?=\s*(?:Seq\s*\()?\s*"[^"]*"\s+at\s+"(?<url>[^"]+)"/,
|
|
19
|
+
Regexp
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Matches: resolvers ++= Seq("Name" at "url", ...)
|
|
23
|
+
RESOLVER_SEQ_AT_REGEX = T.let(
|
|
24
|
+
/"[^"]*"\s+at\s+"(?<url>[^"]+)"/,
|
|
25
|
+
Regexp
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# Matches: Resolver.url("name", url("https://url"))
|
|
29
|
+
RESOLVER_URL_REGEX = T.let(
|
|
30
|
+
/Resolver\.url\(\s*"[^"]*"\s*,\s*url\(\s*"(?<url>[^"]+)"\s*\)/,
|
|
31
|
+
Regexp
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Matches: MavenRepository("name", "https://url")
|
|
35
|
+
MAVEN_REPOSITORY_REGEX = T.let(
|
|
36
|
+
/MavenRepository\(\s*"[^"]*"\s*,\s*"(?<url>[^"]+)"\s*\)/,
|
|
37
|
+
Regexp
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
sig do
|
|
41
|
+
params(
|
|
42
|
+
dependency_files: T::Array[Dependabot::DependencyFile],
|
|
43
|
+
credentials: T::Array[Dependabot::Credential]
|
|
44
|
+
).void
|
|
45
|
+
end
|
|
46
|
+
def initialize(dependency_files:, credentials: [])
|
|
47
|
+
@dependency_files = T.let(dependency_files, T::Array[Dependabot::DependencyFile])
|
|
48
|
+
@credentials = T.let(credentials, T::Array[Dependabot::Credential])
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
sig { returns(T::Array[String]) }
|
|
52
|
+
def repository_urls
|
|
53
|
+
urls = T.let([], T::Array[String])
|
|
54
|
+
|
|
55
|
+
sbt_files.each do |file|
|
|
56
|
+
urls += repository_urls_from(file)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# SBT always includes Maven Central as a default resolver.
|
|
60
|
+
# Custom resolvers supplement but don't replace it.
|
|
61
|
+
urls << central_repo_url unless urls.include?(central_repo_url)
|
|
62
|
+
|
|
63
|
+
urls.uniq
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
69
|
+
attr_reader :dependency_files
|
|
70
|
+
|
|
71
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
|
72
|
+
attr_reader :credentials
|
|
73
|
+
|
|
74
|
+
sig { params(buildfile: Dependabot::DependencyFile).returns(T::Array[String]) }
|
|
75
|
+
def repository_urls_from(buildfile)
|
|
76
|
+
content = comment_free_content(buildfile)
|
|
77
|
+
|
|
78
|
+
urls = [RESOLVER_AT_REGEX, RESOLVER_SEQ_AT_REGEX, RESOLVER_URL_REGEX, MAVEN_REPOSITORY_REGEX]
|
|
79
|
+
.flat_map { |regex| scan_urls(content, regex) }
|
|
80
|
+
|
|
81
|
+
urls
|
|
82
|
+
.map { |url| url.strip.gsub(%r{/$}, "") }
|
|
83
|
+
.select { |url| valid_url?(url) }
|
|
84
|
+
.uniq
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
sig { params(content: String, regex: Regexp).returns(T::Array[String]) }
|
|
88
|
+
def scan_urls(content, regex)
|
|
89
|
+
urls = T.let([], T::Array[String])
|
|
90
|
+
content.scan(regex) do
|
|
91
|
+
urls << T.must(T.must(Regexp.last_match).named_captures.fetch("url"))
|
|
92
|
+
end
|
|
93
|
+
urls
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
sig { returns(String) }
|
|
97
|
+
def central_repo_url
|
|
98
|
+
base_credential = credentials.find do |cred|
|
|
99
|
+
cred["type"] == "maven_repository" && replaces_base?(cred) && cred["url"]
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
base_credential ? T.must(base_credential["url"]).gsub(%r{/+$}, "") : CENTRAL_REPO_URL
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
sig { params(credential: Dependabot::Credential).returns(T::Boolean) }
|
|
106
|
+
def replaces_base?(credential)
|
|
107
|
+
if credential.respond_to?(:replaces_base?)
|
|
108
|
+
credential.replaces_base?
|
|
109
|
+
else
|
|
110
|
+
credential["replaces-base"] == true
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
sig { params(url: String).returns(T::Boolean) }
|
|
115
|
+
def valid_url?(url)
|
|
116
|
+
return false unless url.start_with?("http")
|
|
117
|
+
|
|
118
|
+
URI.parse(url)
|
|
119
|
+
true
|
|
120
|
+
rescue URI::InvalidURIError
|
|
121
|
+
false
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
sig { params(buildfile: Dependabot::DependencyFile).returns(String) }
|
|
125
|
+
def comment_free_content(buildfile)
|
|
126
|
+
T.must(buildfile.content)
|
|
127
|
+
.gsub(%r{(?<=^|\s)//.*$}, "\n")
|
|
128
|
+
.gsub(%r{(?<=^|\s)/\*.*?\*/}m, "")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
132
|
+
def sbt_files
|
|
133
|
+
@sbt_files ||= T.let(
|
|
134
|
+
dependency_files.select { |f| f.name.end_with?(".sbt") },
|
|
135
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
|
136
|
+
)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|