dependabot-core 0.89.5 → 0.90.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.
@@ -1,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/shared_helpers"
4
- require "dependabot/file_updaters/base"
5
-
6
- module Dependabot
7
- module FileUpdaters
8
- module Go
9
- class Dep < Dependabot::FileUpdaters::Base
10
- require_relative "dep/manifest_updater"
11
- require_relative "dep/lockfile_updater"
12
-
13
- def self.updated_files_regex
14
- [
15
- /^Gopkg\.toml$/,
16
- /^Gopkg\.lock$/,
17
- /^go\.mod$/,
18
- /^go\.sum$/
19
- ]
20
- end
21
-
22
- def updated_dependency_files
23
- updated_files = []
24
-
25
- if manifest && file_changed?(manifest)
26
- updated_files <<
27
- updated_file(
28
- file: manifest,
29
- content: updated_manifest_content
30
- )
31
- end
32
-
33
- if lockfile
34
- updated_files <<
35
- updated_file(file: lockfile, content: updated_lockfile_content)
36
- end
37
-
38
- raise "No files changed!" if updated_files.none?
39
-
40
- updated_files
41
- end
42
-
43
- private
44
-
45
- def check_required_files
46
- return if get_original_file("Gopkg.toml")
47
- return if get_original_file("go.mod")
48
-
49
- raise "No Gopkg.toml or go.mod!"
50
- end
51
-
52
- def manifest
53
- @manifest ||= get_original_file("Gopkg.toml")
54
- end
55
-
56
- def lockfile
57
- @lockfile ||= get_original_file("Gopkg.lock")
58
- end
59
-
60
- def updated_manifest_content
61
- ManifestUpdater.new(
62
- dependencies: dependencies,
63
- manifest: manifest
64
- ).updated_manifest_content
65
- end
66
-
67
- def updated_lockfile_content
68
- LockfileUpdater.new(
69
- dependencies: dependencies,
70
- dependency_files: dependency_files,
71
- credentials: credentials
72
- ).updated_lockfile_content
73
- end
74
- end
75
- end
76
- end
77
- end
@@ -1,222 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "toml-rb"
4
- require "open3"
5
- require "dependabot/shared_helpers"
6
- require "dependabot/dependency_file"
7
- require "dependabot/file_updaters/go/dep"
8
- require "dependabot/file_parsers/go/dep"
9
-
10
- module Dependabot
11
- module FileUpdaters
12
- module Go
13
- class Dep
14
- class LockfileUpdater
15
- def initialize(dependencies:, dependency_files:, credentials:)
16
- @dependencies = dependencies
17
- @dependency_files = dependency_files
18
- @credentials = credentials
19
- end
20
-
21
- def updated_lockfile_content
22
- deps = dependencies.select { |d| appears_in_lockfile(d) }
23
- return lockfile.content if deps.none?
24
-
25
- base_directory = File.join("src", "project",
26
- dependency_files.first.directory)
27
- base_parts = base_directory.split("/").length
28
- updated_content =
29
- SharedHelpers.in_a_temporary_directory(base_directory) do |dir|
30
- write_temporary_dependency_files
31
-
32
- SharedHelpers.with_git_configured(credentials: credentials) do
33
- # Shell out to dep, which handles everything for us.
34
- # Note: We are currently doing a full install here (we're not
35
- # passing no-vendor) because dep needs to generate the digests
36
- # for each project.
37
- command = "dep ensure -update #{deps.map(&:name).join(' ')}"
38
- dir_parts = dir.realpath.to_s.split("/")
39
- gopath = File.join(dir_parts[0..-(base_parts + 1)])
40
- run_shell_command(command, "GOPATH" => gopath)
41
- end
42
-
43
- File.read("Gopkg.lock")
44
- end
45
-
46
- updated_content
47
- end
48
-
49
- private
50
-
51
- attr_reader :dependencies, :dependency_files, :credentials
52
-
53
- def run_shell_command(command, env = {})
54
- start = Time.now
55
- stdout, process = Open3.capture2e(env, command)
56
- time_taken = start - Time.now
57
-
58
- # Raise an error with the output from the shell session if dep
59
- # returns a non-zero status
60
- return if process.success?
61
-
62
- raise SharedHelpers::HelperSubprocessFailed.new(
63
- message: stdout,
64
- error_context: {
65
- command: command,
66
- time_taken: time_taken,
67
- process_exit_value: process.to_s
68
- }
69
- )
70
- end
71
-
72
- def write_temporary_dependency_files
73
- File.write(lockfile.name, lockfile.content)
74
-
75
- # Overwrite the manifest with our custom prepared one
76
- File.write(prepared_manifest.name, prepared_manifest.content)
77
-
78
- File.write("hello.go", dummy_app_content)
79
- end
80
-
81
- def prepared_manifest
82
- DependencyFile.new(
83
- name: manifest.name,
84
- content: prepared_manifest_content
85
- )
86
- end
87
-
88
- def prepared_manifest_content
89
- parsed_manifest = TomlRB.parse(manifest.content)
90
-
91
- parsed_manifest["override"] =
92
- add_fsnotify_override(parsed_manifest["override"])
93
-
94
- dependencies.each do |dep|
95
- req = dep.requirements.find { |r| r[:file] == manifest.name }
96
- next unless appears_in_lockfile(dep)
97
-
98
- if req
99
- update_constraint!(parsed_manifest, dep)
100
- else
101
- create_constraint!(parsed_manifest, dep)
102
- end
103
- end
104
-
105
- TomlRB.dump(parsed_manifest)
106
- end
107
-
108
- # Used to lock the version when updating a top-level dependency
109
- def update_constraint!(parsed_manifest, dep)
110
- details =
111
- parsed_manifest.
112
- values_at(*FileParsers::Go::Dep::REQUIREMENT_TYPES).
113
- flatten.compact.find { |d| d["name"] == dep.name }
114
-
115
- req = dep.requirements.find { |r| r[:file] == manifest.name }
116
-
117
- if req.fetch(:source).fetch(:type) == "git" && !details["branch"]
118
- # Note: we don't try to update to a specific revision if the
119
- # branch was previously specified because the change in
120
- # specification type would be persisted in the lockfile
121
- details["revision"] = dep.version if details["revision"]
122
- details["version"] = dep.version if details["version"]
123
- elsif req.fetch(:source).fetch(:type) == "default"
124
- details.delete("branch")
125
- details.delete("revision")
126
- details["version"] = "=#{dep.version}"
127
- end
128
- end
129
-
130
- # Used to lock the version when updating a subdependency
131
- def create_constraint!(parsed_manifest, dep)
132
- details = { "name" => dep.name }
133
-
134
- # Fetch the details from the lockfile to check whether this
135
- # sub-dependency needs a git revision or a version.
136
- original_details =
137
- parsed_file(lockfile).fetch("projects").
138
- find { |p| p["name"] == dep.name }
139
-
140
- if original_details["source"]
141
- details["source"] = original_details["source"]
142
- end
143
-
144
- if original_details["version"]
145
- details["version"] = dep.version
146
- else
147
- details["revision"] = dep.version
148
- end
149
-
150
- parsed_manifest["constraint"] ||= []
151
- parsed_manifest["constraint"] << details
152
- end
153
-
154
- # Work around a dep bug that results in a panic
155
- def add_fsnotify_override(overrides)
156
- overrides ||= []
157
- dep_name = "gopkg.in/fsnotify.v1"
158
-
159
- override = overrides.find { |s| s["name"] == dep_name }
160
- if override.nil?
161
- override = { "name" => dep_name }
162
- overrides << override
163
- end
164
-
165
- unless override["source"]
166
- override["source"] = "gopkg.in/fsnotify/fsnotify.v1"
167
- end
168
-
169
- overrides
170
- end
171
-
172
- def dummy_app_content
173
- base = "package main\n\n"\
174
- "import \"fmt\"\n\n"
175
-
176
- packages_to_import.each { |nm| base += "import \"#{nm}\"\n\n" }
177
-
178
- base + "func main() {\n fmt.Printf(\"hello, world\\n\")\n}"
179
- end
180
-
181
- def packages_to_import
182
- parsed_lockfile = TomlRB.parse(lockfile.content)
183
-
184
- # If the lockfile was created using dep v0.5.0+ then it will tell us
185
- # exactly which packages to import
186
- if parsed_lockfile.dig("solve-meta", "input-imports")
187
- return parsed_lockfile.dig("solve-meta", "input-imports")
188
- end
189
-
190
- # Otherwise we have no way of knowing, so import everything in the
191
- # lockfile that isn't marked as internal
192
- parsed_lockfile.fetch("projects").flat_map do |dep|
193
- dep["packages"].map do |package|
194
- next if package.start_with?("internal")
195
-
196
- package == "." ? dep["name"] : File.join(dep["name"], package)
197
- end.compact
198
- end
199
- end
200
-
201
- def appears_in_lockfile(dep)
202
- !parsed_file(lockfile)["projects"]&.
203
- find { |p| p["name"] == dep.name }.nil?
204
- end
205
-
206
- def parsed_file(file)
207
- @parsed_file ||= {}
208
- @parsed_file[file.name] ||= TomlRB.parse(file.content)
209
- end
210
-
211
- def manifest
212
- @manifest ||= dependency_files.find { |f| f.name == "Gopkg.toml" }
213
- end
214
-
215
- def lockfile
216
- @lockfile ||= dependency_files.find { |f| f.name == "Gopkg.lock" }
217
- end
218
- end
219
- end
220
- end
221
- end
222
- end
@@ -1,155 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/file_updaters/go/dep"
4
-
5
- module Dependabot
6
- module FileUpdaters
7
- module Go
8
- class Dep
9
- class ManifestUpdater
10
- def initialize(dependencies:, manifest:)
11
- @dependencies = dependencies
12
- @manifest = manifest
13
- end
14
-
15
- def updated_manifest_content
16
- dependencies.
17
- select { |dep| requirement_changed?(manifest, dep) }.
18
- reduce(manifest.content.dup) do |content, dep|
19
- updated_content = content
20
-
21
- updated_content = update_requirements(
22
- content: updated_content,
23
- filename: manifest.name,
24
- dependency: dep
25
- )
26
- updated_content = update_git_pin(
27
- content: updated_content,
28
- filename: manifest.name,
29
- dependency: dep
30
- )
31
-
32
- if content == updated_content
33
- raise "Expected content to change!"
34
- end
35
-
36
- updated_content
37
- end
38
- end
39
-
40
- private
41
-
42
- attr_reader :dependencies, :manifest
43
-
44
- def requirement_changed?(file, dependency)
45
- changed_requirements =
46
- dependency.requirements - dependency.previous_requirements
47
-
48
- changed_requirements.any? { |f| f[:file] == file.name }
49
- end
50
-
51
- def update_requirements(content:, filename:, dependency:)
52
- updated_content = content.dup
53
-
54
- # The UpdateChecker ensures the order of requirements is preserved
55
- # when updating, so we can zip them together in new/old pairs.
56
- reqs = dependency.requirements.
57
- zip(dependency.previous_requirements).
58
- reject { |new_req, old_req| new_req == old_req }
59
-
60
- # Loop through each changed requirement
61
- reqs.each do |new_req, old_req|
62
- raise "Bad req match" unless new_req[:file] == old_req[:file]
63
- next if new_req[:requirement] == old_req[:requirement]
64
- next unless new_req[:file] == filename
65
-
66
- updated_content = update_manifest_req(
67
- content: updated_content,
68
- dep: dependency,
69
- old_req: old_req.fetch(:requirement),
70
- new_req: new_req.fetch(:requirement)
71
- )
72
- end
73
-
74
- updated_content
75
- end
76
-
77
- def update_git_pin(content:, filename:, dependency:)
78
- updated_pin =
79
- dependency.requirements.
80
- find { |r| r[:file] == filename }&.
81
- dig(:source, :ref)
82
-
83
- old_pin =
84
- dependency.previous_requirements.
85
- find { |r| r[:file] == filename }&.
86
- dig(:source, :ref)
87
-
88
- return content unless old_pin
89
-
90
- update_manifest_pin(
91
- content: content,
92
- dep: dependency,
93
- old_pin: old_pin,
94
- new_pin: updated_pin
95
- )
96
- end
97
-
98
- # rubocop:disable Metrics/CyclomaticComplexity
99
- # rubocop:disable Metrics/PerceivedComplexity
100
- def update_manifest_req(content:, dep:, old_req:, new_req:)
101
- declaration = content.scan(declaration_regex(dep)).
102
- find { |m| old_req.nil? || m.include?(old_req) }
103
-
104
- return content unless declaration
105
-
106
- if old_req && new_req
107
- content.gsub(declaration) do |line|
108
- line.gsub(old_req, new_req)
109
- end
110
- elsif old_req && new_req.nil?
111
- content.gsub(declaration) do |line|
112
- line.gsub(/\R+.*version\s*=.*/, "")
113
- end
114
- elsif old_req.nil? && new_req
115
- content.gsub(declaration) do |line|
116
- indent = line.match(/(?<indent>\s*)name/).
117
- named_captures.fetch("indent")
118
- version_declaration = indent + "version = \"#{new_req}\""
119
- line.gsub(/name\s*=.*/) { |nm_ln| nm_ln + version_declaration }
120
- end
121
- end
122
- end
123
- # rubocop:enable Metrics/CyclomaticComplexity
124
- # rubocop:enable Metrics/PerceivedComplexity
125
-
126
- def update_manifest_pin(content:, dep:, old_pin:, new_pin:)
127
- declaration = content.scan(declaration_regex(dep)).
128
- find { |m| m.include?(old_pin) }
129
-
130
- return content unless declaration
131
-
132
- if old_pin && new_pin
133
- content.gsub(declaration) do |line|
134
- line.gsub(old_pin, new_pin)
135
- end
136
- elsif old_pin && new_pin.nil?
137
- content.gsub(declaration) do |line|
138
- line.gsub(/\R+.*(revision|branch)\s*=.*/, "")
139
- end
140
- end
141
- end
142
-
143
- def declaration_regex(dep)
144
- /
145
- (?<=\]\])
146
- (?:(?!^\[).)*
147
- name\s*=\s*["']#{Regexp.escape(dep.name)}["']
148
- (?:(?!^\[).)*
149
- /mx
150
- end
151
- end
152
- end
153
- end
154
- end
155
- end