dependabot-core 0.83.2 → 0.84.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,90 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/file_parsers/java/gradle"
4
-
5
- module Dependabot
6
- module FileParsers
7
- module Java
8
- class Gradle
9
- class PropertyValueFinder
10
- PROPERTY_DECLARATION_REGEX =
11
- /(?:^|\s+|ext.)(?<name>[^\s=]+)\s*=\s*['"](?<value>[^\s]+)['"]/.
12
- freeze
13
-
14
- def initialize(dependency_files:)
15
- @dependency_files = dependency_files
16
- end
17
-
18
- def property_details(property_name:, callsite_buildfile:)
19
- # If the root project was specified, just look in the top-level
20
- # buildfile
21
- if property_name.start_with?("rootProject.")
22
- property_name = property_name.sub("rootProject.", "")
23
- return properties(top_level_buildfile).fetch(property_name, nil)
24
- end
25
-
26
- # If this project was specified strip the specifier
27
- if property_name.start_with?("project.")
28
- property_name = property_name.sub("project.", "")
29
- end
30
-
31
- # If a `properties` prefix was specified strip that out, too
32
- if property_name.start_with?("properties.")
33
- property_name = property_name.sub("properties.", "")
34
- end
35
-
36
- # Look for a property in the callsite buildfile. If that fails, look
37
- # for the property in the top-level buildfile
38
- if properties(callsite_buildfile).fetch(property_name, nil)
39
- return properties(callsite_buildfile).fetch(property_name)
40
- end
41
-
42
- properties(top_level_buildfile).fetch(property_name, nil)
43
- end
44
-
45
- def property_value(property_name:, callsite_buildfile:)
46
- property_details(
47
- property_name: property_name,
48
- callsite_buildfile: callsite_buildfile
49
- )&.fetch(:value)
50
- end
51
-
52
- private
53
-
54
- attr_reader :dependency_files
55
-
56
- def properties(buildfile)
57
- @properties ||= {}
58
- return @properties[buildfile.name] if @properties[buildfile.name]
59
-
60
- @properties[buildfile.name] = {}
61
- prepared_content(buildfile).scan(PROPERTY_DECLARATION_REGEX) do
62
- declaration_string = Regexp.last_match.to_s.strip
63
- captures = Regexp.last_match.named_captures
64
- name = captures.fetch("name").sub(/^ext\./, "")
65
- @properties[buildfile.name][name] = {
66
- value: captures.fetch("value"),
67
- declaration_string: declaration_string,
68
- file: buildfile.name
69
- }
70
- end
71
-
72
- @properties[buildfile.name]
73
- end
74
-
75
- def prepared_content(buildfile)
76
- # Remove any comments
77
- buildfile.content.
78
- gsub(%r{(?<=^|\s)//.*$}, "\n").
79
- gsub(%r{(?<=^|\s)/\*.*?\*/}m, "")
80
- end
81
-
82
- def top_level_buildfile
83
- @top_level_buildfile ||=
84
- dependency_files.find { |f| f.name == "build.gradle" }
85
- end
86
- end
87
- end
88
- end
89
- end
90
- end
@@ -1,145 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/file_parsers/java/gradle"
4
-
5
- module Dependabot
6
- module FileParsers
7
- module Java
8
- class Gradle
9
- class RepositoriesFinder
10
- # The Central Repo doesn't have special status for Gradle, but until
11
- # we're confident we're selecting repos correctly it's wise to include
12
- # it as a default.
13
- CENTRAL_REPO_URL = "https://repo.maven.apache.org/maven2"
14
-
15
- REPOSITORIES_BLOCK_START = /(?:^|\s)repositories\s*\{/.freeze
16
- MAVEN_REPO_REGEX =
17
- /maven\s*\{[^\}]*\surl[\s\(]\s*['"](?<url>[^'"]+)['"]/.freeze
18
-
19
- def initialize(dependency_files:, target_dependency_file:)
20
- @dependency_files = dependency_files
21
- @target_dependency_file = target_dependency_file
22
- raise "No target file!" unless target_dependency_file
23
- end
24
-
25
- def repository_urls
26
- repository_urls = []
27
- repository_urls += inherited_repository_urls
28
- repository_urls += own_buildfile_repository_urls
29
- repository_urls = repository_urls.uniq
30
-
31
- return repository_urls unless repository_urls.empty?
32
-
33
- [CENTRAL_REPO_URL]
34
- end
35
-
36
- private
37
-
38
- attr_reader :dependency_files, :target_dependency_file
39
-
40
- def inherited_repository_urls
41
- return [] unless top_level_buildfile
42
-
43
- buildfile_content = comment_free_content(top_level_buildfile)
44
- subproject_blocks = []
45
-
46
- buildfile_content.scan(/(?:^|\s)allprojects\s*\{/) do
47
- mtch = Regexp.last_match
48
- subproject_blocks <<
49
- mtch.post_match[0..closing_bracket_index(mtch.post_match)]
50
- end
51
-
52
- if top_level_buildfile != target_dependency_file
53
- buildfile_content.scan(/(?:^|\s)subprojects\s*\{/) do
54
- mtch = Regexp.last_match
55
- subproject_blocks <<
56
- mtch.post_match[0..closing_bracket_index(mtch.post_match)]
57
- end
58
- end
59
-
60
- repository_urls_from(subproject_blocks.join("\n"))
61
- end
62
-
63
- def own_buildfile_repository_urls
64
- buildfile_content = comment_free_content(target_dependency_file)
65
-
66
- buildfile_content.dup.scan(/(?:^|\s)subprojects\s*\{/) do
67
- mtch = Regexp.last_match
68
- buildfile_content.gsub!(
69
- mtch.post_match[0..closing_bracket_index(mtch.post_match)],
70
- ""
71
- )
72
- end
73
-
74
- repository_urls_from(buildfile_content)
75
- end
76
-
77
- def repository_urls_from(buildfile_content)
78
- repository_urls = []
79
-
80
- repository_blocks = []
81
- buildfile_content.scan(REPOSITORIES_BLOCK_START) do
82
- mtch = Regexp.last_match
83
- repository_blocks <<
84
- mtch.post_match[0..closing_bracket_index(mtch.post_match)]
85
- end
86
-
87
- repository_blocks.each do |block|
88
- if block.include?(" google(")
89
- repository_urls << "https://maven.google.com/"
90
- end
91
-
92
- if block.include?(" mavenCentral(")
93
- repository_urls << "https://repo.maven.apache.org/maven2/"
94
- end
95
-
96
- if block.include?(" jcenter(")
97
- repository_urls << "https://jcenter.bintray.com/"
98
- end
99
-
100
- block.scan(MAVEN_REPO_REGEX) do
101
- repository_urls << Regexp.last_match.named_captures.fetch("url")
102
- end
103
- end
104
-
105
- repository_urls.
106
- map { |url| url.strip.gsub(%r{/$}, "") }.
107
- select { |url| valid_url?(url) }.
108
- uniq
109
- end
110
-
111
- def closing_bracket_index(string)
112
- closes_required = 1
113
-
114
- string.chars.each_with_index do |char, index|
115
- closes_required += 1 if char == "{"
116
- closes_required -= 1 if char == "}"
117
- return index if closes_required.zero?
118
- end
119
- end
120
-
121
- def valid_url?(url)
122
- # Reject non-http URLs because they're probably parsing mistakes
123
- return false unless url.start_with?("http")
124
-
125
- URI.parse(url)
126
- true
127
- rescue URI::InvalidURIError
128
- false
129
- end
130
-
131
- def comment_free_content(buildfile)
132
- buildfile.content.
133
- gsub(%r{(?<=^|\s)//.*$}, "\n").
134
- gsub(%r{(?<=^|\s)/\*.*?\*/}m, "")
135
- end
136
-
137
- def top_level_buildfile
138
- @top_level_buildfile ||=
139
- dependency_files.find { |f| f.name == "build.gradle" }
140
- end
141
- end
142
- end
143
- end
144
- end
145
- end
@@ -1,176 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/file_updaters/base"
4
- require "dependabot/file_parsers/java/gradle"
5
-
6
- module Dependabot
7
- module FileUpdaters
8
- module Java
9
- class Gradle < Dependabot::FileUpdaters::Base
10
- require_relative "gradle/dependency_set_updater"
11
- require_relative "gradle/property_value_updater"
12
-
13
- def self.updated_files_regex
14
- [/^build\.gradle$/, %r{/build\.gradle$}]
15
- end
16
-
17
- def updated_dependency_files
18
- updated_files = buildfiles.dup
19
-
20
- # Loop through each of the changed requirements, applying changes to
21
- # all buildfiles for that change. Note that the logic is different
22
- # here to other languages because Java has property inheritance across
23
- # files (although we're not supporting it for gradle yet).
24
- dependencies.each do |dependency|
25
- updated_files = update_buildfiles_for_dependency(
26
- buildfiles: updated_files,
27
- dependency: dependency
28
- )
29
- end
30
-
31
- updated_files = updated_files.reject { |f| buildfiles.include?(f) }
32
-
33
- raise "No files changed!" if updated_files.none?
34
-
35
- updated_files
36
- end
37
-
38
- private
39
-
40
- def check_required_files
41
- raise "No build.gradle!" unless get_original_file("build.gradle")
42
- end
43
-
44
- def update_buildfiles_for_dependency(buildfiles:, dependency:)
45
- files = buildfiles.dup
46
-
47
- # The UpdateChecker ensures the order of requirements is preserved
48
- # when updating, so we can zip them together in new/old pairs.
49
- reqs = dependency.requirements.zip(dependency.previous_requirements).
50
- reject { |new_req, old_req| new_req == old_req }
51
-
52
- # Loop through each changed requirement and update the buildfiles
53
- reqs.each do |new_req, old_req|
54
- raise "Bad req match" unless new_req[:file] == old_req[:file]
55
- next if new_req[:requirement] == old_req[:requirement]
56
-
57
- buildfile = files.find { |f| f.name == new_req.fetch(:file) }
58
-
59
- if new_req.dig(:metadata, :property_name)
60
- files = update_files_for_property_change(files, old_req, new_req)
61
- elsif new_req.dig(:metadata, :dependency_set)
62
- files = update_files_for_dep_set_change(files, old_req, new_req)
63
- else
64
- files[files.index(buildfile)] =
65
- update_version_in_buildfile(
66
- dependency,
67
- buildfile,
68
- old_req,
69
- new_req
70
- )
71
- end
72
- end
73
-
74
- files
75
- end
76
-
77
- def update_files_for_property_change(buildfiles, old_req, new_req)
78
- files = buildfiles.dup
79
- property_name = new_req.fetch(:metadata).fetch(:property_name)
80
- buildfile = files.find { |f| f.name == new_req.fetch(:file) }
81
-
82
- PropertyValueUpdater.new(dependency_files: files).
83
- update_files_for_property_change(
84
- property_name: property_name,
85
- callsite_buildfile: buildfile,
86
- previous_value: old_req.fetch(:requirement),
87
- updated_value: new_req.fetch(:requirement)
88
- )
89
- end
90
-
91
- def update_files_for_dep_set_change(buildfiles, old_req, new_req)
92
- files = buildfiles.dup
93
- dependency_set = new_req.fetch(:metadata).fetch(:dependency_set)
94
- buildfile = files.find { |f| f.name == new_req.fetch(:file) }
95
-
96
- DependencySetUpdater.new(dependency_files: files).
97
- update_files_for_dep_set_change(
98
- dependency_set: dependency_set,
99
- buildfile: buildfile,
100
- previous_requirement: old_req.fetch(:requirement),
101
- updated_requirement: new_req.fetch(:requirement)
102
- )
103
- end
104
-
105
- def update_version_in_buildfile(dependency, buildfile, previous_req,
106
- requirement)
107
- updated_content =
108
- buildfile.content.gsub(
109
- original_buildfile_declaration(dependency, previous_req),
110
- updated_buildfile_declaration(
111
- dependency,
112
- previous_req,
113
- requirement
114
- )
115
- )
116
-
117
- if updated_content == buildfile.content
118
- raise "Expected content to change!"
119
- end
120
-
121
- updated_file(file: buildfile, content: updated_content)
122
- end
123
-
124
- def original_buildfile_declaration(dependency, requirement)
125
- # This implementation is limited to declarations that appear on a
126
- # single line.
127
- buildfile = buildfiles.find { |f| f.name == requirement.fetch(:file) }
128
- buildfile.content.lines.find do |line|
129
- line = evaluate_properties(line, buildfile)
130
- next false unless line.include?(dependency.name.split(":").first)
131
- next false unless line.include?(dependency.name.split(":").last)
132
-
133
- line.include?(requirement.fetch(:requirement))
134
- end
135
- end
136
-
137
- def evaluate_properties(string, buildfile)
138
- result = string.dup
139
-
140
- string.scan(FileParsers::Java::Gradle::PROPERTY_REGEX) do
141
- prop_name = Regexp.last_match.named_captures.fetch("property_name")
142
- property_value = property_value_finder.property_value(
143
- property_name: prop_name,
144
- callsite_buildfile: buildfile
145
- )
146
- next unless property_value
147
-
148
- result.sub!(Regexp.last_match.to_s, property_value)
149
- end
150
-
151
- result
152
- end
153
-
154
- def property_value_finder
155
- @property_value_finder ||=
156
- FileParsers::Java::Gradle::PropertyValueFinder.
157
- new(dependency_files: dependency_files)
158
- end
159
-
160
- def updated_buildfile_declaration(dependency, previous_req, requirement)
161
- original_req_string = previous_req.fetch(:requirement)
162
-
163
- original_buildfile_declaration(dependency, previous_req).gsub(
164
- original_req_string,
165
- requirement.fetch(:requirement)
166
- )
167
- end
168
-
169
- def buildfiles
170
- @buildfiles ||=
171
- dependency_files.select { |f| f.name.end_with?("build.gradle") }
172
- end
173
- end
174
- end
175
- end
176
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/file_parsers/java/gradle"
4
- require "dependabot/file_updaters/java/gradle"
5
-
6
- module Dependabot
7
- module FileUpdaters
8
- module Java
9
- class Gradle
10
- class DependencySetUpdater
11
- def initialize(dependency_files:)
12
- @dependency_files = dependency_files
13
- end
14
-
15
- def update_files_for_dep_set_change(dependency_set:,
16
- buildfile:,
17
- previous_requirement:,
18
- updated_requirement:)
19
- declaration_string =
20
- original_declaration_string(dependency_set, buildfile)
21
-
22
- return dependency_files unless declaration_string
23
-
24
- updated_content = buildfile.content.sub(
25
- declaration_string,
26
- declaration_string.sub(
27
- previous_requirement,
28
- updated_requirement
29
- )
30
- )
31
-
32
- updated_files = dependency_files.dup
33
- updated_files[updated_files.index(buildfile)] =
34
- update_file(file: buildfile, content: updated_content)
35
-
36
- updated_files
37
- end
38
-
39
- private
40
-
41
- attr_reader :dependency_files
42
-
43
- def original_declaration_string(dependency_set, buildfile)
44
- regex = FileParsers::Java::Gradle::DEPENDENCY_SET_DECLARATION_REGEX
45
- dependency_sets = []
46
- buildfile.content.scan(regex) do
47
- dependency_sets << Regexp.last_match.to_s
48
- end
49
-
50
- dependency_sets.find do |mtch|
51
- next unless mtch.include?(dependency_set[:group])
52
-
53
- mtch.include?(dependency_set[:version])
54
- end
55
- end
56
-
57
- def update_file(file:, content:)
58
- updated_file = file.dup
59
- updated_file.content = content
60
- updated_file
61
- end
62
- end
63
- end
64
- end
65
- end
66
- end