dependabot-swift 0.222.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4aef4a94ae75bf75d90152d46b40c74149b9b6724392bcd7aed6ab75843dc359
4
+ data.tar.gz: b1423ec2d83751d7f0fca41a5e24b0d7c952015ca355042ab5a585f02b321895
5
+ SHA512:
6
+ metadata.gz: 2451f0816f18243f61732cd2cb751953ba5b7cb8e55727901c33a81ae9f574282ee58f098df107b7b550e1dfa98b37475b50e1e0e323ae0b3dc9c7a5ec04002c
7
+ data.tar.gz: 7a8dc186c3490327e53c721c01a2424c34a18350bc00d92367866e667980e851379ac2a9f3efb74d892f8bcdb238260fc67843054805c69d62de3228c75f0b0b
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/file_fetchers"
4
+ require "dependabot/file_fetchers/base"
5
+
6
+ module Dependabot
7
+ module Swift
8
+ class FileFetcher < Dependabot::FileFetchers::Base
9
+ def self.required_files_in?(filenames)
10
+ filenames.include?("Package.swift")
11
+ end
12
+
13
+ def self.required_files_message
14
+ "Repo must contain a Package.swift configuration file."
15
+ end
16
+
17
+ private
18
+
19
+ def fetch_files
20
+ check_required_files_present
21
+
22
+ fetched_files = []
23
+ fetched_files << package_manifest
24
+ fetched_files << package_resolved if package_resolved
25
+ fetched_files
26
+ end
27
+
28
+ def package_manifest
29
+ @package_manifest ||= fetch_file_from_host("Package.swift")
30
+ end
31
+
32
+ def package_resolved
33
+ return @package_resolved if defined?(@package_resolved)
34
+
35
+ @package_resolved = fetch_file_if_present("Package.resolved")
36
+ end
37
+
38
+ def check_required_files_present
39
+ return if package_manifest
40
+
41
+ path = Pathname.new(File.join(directory, "Package.swift")).
42
+ cleanpath.to_path
43
+ raise Dependabot::DependencyFileNotFound, path
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ Dependabot::FileFetchers.
50
+ register("swift", Dependabot::Swift::FileFetcher)
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/file_parsers/base"
4
+ require "dependabot/shared_helpers"
5
+ require "dependabot/dependency"
6
+ require "json"
7
+
8
+ module Dependabot
9
+ module Swift
10
+ class FileParser < Dependabot::FileParsers::Base
11
+ class DependencyParser
12
+ def initialize(dependency_files:, repo_contents_path:, credentials:)
13
+ @dependency_files = dependency_files
14
+ @repo_contents_path = repo_contents_path
15
+ @credentials = credentials
16
+ end
17
+
18
+ def parse
19
+ SharedHelpers.in_a_temporary_repo_directory(dependency_files.first.directory, repo_contents_path) do
20
+ write_temporary_dependency_files
21
+
22
+ SharedHelpers.with_git_configured(credentials: credentials) do
23
+ subdependencies(formatted_deps)
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def write_temporary_dependency_files
31
+ dependency_files.each do |file|
32
+ File.write(file.name, file.content)
33
+ end
34
+ end
35
+
36
+ def formatted_deps
37
+ deps = SharedHelpers.run_shell_command(
38
+ "swift package show-dependencies --format json",
39
+ stderr_to_stdout: false
40
+ )
41
+
42
+ JSON.parse(deps)
43
+ end
44
+
45
+ def subdependencies(data, level: 0)
46
+ data["dependencies"].flat_map { |root| all_dependencies(root, level: level) }
47
+ end
48
+
49
+ def all_dependencies(data, level: 0)
50
+ name = data["identity"]
51
+ url = data["url"]
52
+ version = data["version"]
53
+
54
+ source = { type: "git", url: url, ref: version, branch: nil }
55
+ args = { name: name, version: version, package_manager: "swift", requirements: [] }
56
+
57
+ if level.zero?
58
+ args[:requirements] << { requirement: nil, groups: ["dependencies"], file: nil, source: source }
59
+ else
60
+ args[:subdependency_metadata] = [{ source: source }]
61
+ end
62
+
63
+ dep = Dependency.new(**args) if data["version"] != "unspecified"
64
+
65
+ [dep, *subdependencies(data, level: level + 1)].compact
66
+ end
67
+
68
+ attr_reader :dependency_files, :repo_contents_path, :credentials
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/file_parsers/base"
4
+ require "dependabot/swift/native_requirement"
5
+
6
+ module Dependabot
7
+ module Swift
8
+ class FileParser < Dependabot::FileParsers::Base
9
+ class ManifestParser
10
+ DEPENDENCY = /(?<declaration>\.package\(\s*(?:name: "[^"]+",\s*)?url: "(?<url>[^"]+)",\s*(?<requirement>.*)\))/
11
+
12
+ def initialize(manifest, source:)
13
+ @manifest = manifest
14
+ @source = source
15
+ end
16
+
17
+ def requirements
18
+ found = manifest.content.scan(DEPENDENCY).find do |_declaration, url, requirement|
19
+ # TODO: Support pinning to specific revisions
20
+ next if requirement.start_with?("branch:", ".branch(", "revision:", ".revision(")
21
+
22
+ url == source[:url]
23
+ end
24
+
25
+ return [] unless found
26
+
27
+ declaration = found.first
28
+ requirement = NativeRequirement.new(found.last)
29
+
30
+ [
31
+ {
32
+ requirement: requirement.to_s,
33
+ groups: ["dependencies"],
34
+ file: manifest.name,
35
+ source: source,
36
+ metadata: { declaration_string: declaration, requirement_string: requirement.declaration }
37
+ }
38
+ ]
39
+ end
40
+
41
+ private
42
+
43
+ attr_reader :manifest, :source
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/dependency"
4
+ require "dependabot/file_parsers"
5
+ require "dependabot/file_parsers/base"
6
+ require "dependabot/swift/file_parser/dependency_parser"
7
+ require "dependabot/swift/file_parser/manifest_parser"
8
+
9
+ module Dependabot
10
+ module Swift
11
+ class FileParser < Dependabot::FileParsers::Base
12
+ require "dependabot/file_parsers/base/dependency_set"
13
+
14
+ def parse
15
+ dependency_set = DependencySet.new
16
+
17
+ dependency_parser.parse.map do |dep|
18
+ if dep.top_level?
19
+ source = dep.requirements.first[:source]
20
+
21
+ requirements = ManifestParser.new(package_manifest_file, source: source).requirements
22
+
23
+ dependency_set << Dependency.new(
24
+ name: dep.name,
25
+ version: dep.version,
26
+ package_manager: dep.package_manager,
27
+ requirements: requirements
28
+ )
29
+ else
30
+ dependency_set << dep
31
+ end
32
+ end
33
+
34
+ dependency_set.dependencies
35
+ end
36
+
37
+ private
38
+
39
+ def dependency_parser
40
+ DependencyParser.new(
41
+ dependency_files: dependency_files,
42
+ repo_contents_path: repo_contents_path,
43
+ credentials: credentials
44
+ )
45
+ end
46
+
47
+ def check_required_files
48
+ raise "No Package.swift!" unless package_manifest_file
49
+ end
50
+
51
+ def package_manifest_file
52
+ # TODO: Select version-specific manifest
53
+ @package_manifest_file ||= get_original_file("Package.swift")
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ Dependabot::FileParsers.
60
+ register("swift", Dependabot::Swift::FileParser)
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/file_updaters/base"
4
+ require "dependabot/shared_helpers"
5
+
6
+ module Dependabot
7
+ module Swift
8
+ class FileUpdater < Dependabot::FileUpdaters::Base
9
+ class LockfileUpdater
10
+ def initialize(dependencies:, manifest:, repo_contents_path:, credentials:)
11
+ @dependencies = dependencies
12
+ @manifest = manifest
13
+ @repo_contents_path = repo_contents_path
14
+ @credentials = credentials
15
+ end
16
+
17
+ def updated_lockfile_content
18
+ SharedHelpers.in_a_temporary_repo_directory(manifest.directory, repo_contents_path) do
19
+ File.write(manifest.name, manifest.content)
20
+
21
+ SharedHelpers.with_git_configured(credentials: credentials) do
22
+ SharedHelpers.run_shell_command(
23
+ "swift package update #{dependencies.map(&:name).join(' ')}",
24
+ fingerprint: "swift package update <dependency_name>"
25
+ )
26
+
27
+ File.read("Package.resolved")
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :dependencies, :manifest, :repo_contents_path, :credentials
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/file_updaters/base"
4
+ require "dependabot/swift/file_updater/requirement_replacer"
5
+
6
+ module Dependabot
7
+ module Swift
8
+ class FileUpdater < FileUpdaters::Base
9
+ class ManifestUpdater
10
+ def initialize(content, old_requirements:, new_requirements:)
11
+ @content = content
12
+ @old_requirements = old_requirements
13
+ @new_requirements = new_requirements
14
+ end
15
+
16
+ def updated_manifest_content
17
+ updated_content = content
18
+
19
+ old_requirements.zip(new_requirements).each do |old, new|
20
+ updated_content = RequirementReplacer.new(
21
+ content: updated_content,
22
+ declaration: old[:metadata][:declaration_string],
23
+ old_requirement: old[:metadata][:requirement_string],
24
+ new_requirement: new[:metadata][:requirement_string]
25
+ ).updated_content
26
+ end
27
+
28
+ updated_content
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :content, :old_requirements, :new_requirements
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/file_updaters/base"
4
+
5
+ module Dependabot
6
+ module Swift
7
+ class FileUpdater < Dependabot::FileUpdaters::Base
8
+ class RequirementReplacer
9
+ def initialize(content:, declaration:, old_requirement:, new_requirement:)
10
+ @content = content
11
+ @declaration = declaration
12
+ @old_requirement = old_requirement
13
+ @new_requirement = new_requirement
14
+ end
15
+
16
+ def updated_content
17
+ content.gsub(declaration) do |match|
18
+ match.to_s.sub(old_requirement, new_requirement)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :content, :declaration, :old_requirement, :new_requirement
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/file_updaters"
4
+ require "dependabot/file_updaters/base"
5
+ require "dependabot/swift/file_updater/lockfile_updater"
6
+ require "dependabot/swift/file_updater/manifest_updater"
7
+
8
+ module Dependabot
9
+ module Swift
10
+ class FileUpdater < Dependabot::FileUpdaters::Base
11
+ def self.updated_files_regex
12
+ [
13
+ /Package(@swift-\d(\.\d){0,2})?\.swift/,
14
+ /^Package\.resolved$/
15
+ ]
16
+ end
17
+
18
+ def updated_dependency_files
19
+ updated_files = []
20
+
21
+ SharedHelpers.in_a_temporary_repo_directory(manifest.directory, repo_contents_path) do
22
+ updated_manifest = nil
23
+
24
+ if file_changed?(manifest)
25
+ updated_manifest = updated_file(file: manifest, content: updated_manifest_content)
26
+ updated_files << updated_manifest
27
+ end
28
+
29
+ updated_files << updated_file(file: lockfile, content: updated_lockfile_content(updated_manifest)) if lockfile
30
+ end
31
+
32
+ updated_files
33
+ end
34
+
35
+ private
36
+
37
+ def dependency
38
+ # For now we will be updating a single dependency.
39
+ # TODO: Revisit when/if implementing full unlocks
40
+ dependencies.first
41
+ end
42
+
43
+ def check_required_files
44
+ raise "A Package.swift file must be provided!" unless manifest
45
+ end
46
+
47
+ def updated_manifest_content
48
+ ManifestUpdater.new(
49
+ manifest.content,
50
+ old_requirements: dependency.previous_requirements,
51
+ new_requirements: dependency.requirements
52
+ ).updated_manifest_content
53
+ end
54
+
55
+ def updated_lockfile_content(updated_manifest)
56
+ LockfileUpdater.new(
57
+ dependencies: dependencies,
58
+ manifest: updated_manifest || manifest,
59
+ repo_contents_path: repo_contents_path,
60
+ credentials: credentials
61
+ ).updated_lockfile_content
62
+ end
63
+
64
+ def manifest
65
+ @manifest ||= get_original_file("Package.swift")
66
+ end
67
+
68
+ def lockfile
69
+ return @lockfile if defined?(@lockfile)
70
+
71
+ @lockfile = get_original_file("Package.resolved")
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ Dependabot::FileUpdaters.
78
+ register("swift", Dependabot::Swift::FileUpdater)
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/metadata_finders"
4
+ require "dependabot/metadata_finders/base"
5
+
6
+ module Dependabot
7
+ module Swift
8
+ class MetadataFinder < Dependabot::MetadataFinders::Base
9
+ private
10
+
11
+ def look_up_source
12
+ case new_source_type
13
+ when "git" then find_source_from_git_url
14
+ when "registry" then find_source_from_registry
15
+ else raise "Unexpected source type: #{new_source_type}"
16
+ end
17
+ end
18
+
19
+ def new_source_type
20
+ dependency.source_type
21
+ end
22
+
23
+ def find_source_from_git_url
24
+ info = dependency.source_details
25
+
26
+ url = info[:url] || info.fetch("url")
27
+ Source.from_url(url)
28
+ end
29
+
30
+ def find_source_from_registry
31
+ raise NotImplementedError
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ Dependabot::MetadataFinders.
38
+ register("swift", Dependabot::Swift::MetadataFinder)
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/utils"
4
+ require "dependabot/swift/requirement"
5
+
6
+ module Dependabot
7
+ module Swift
8
+ class NativeRequirement
9
+ attr_reader :declaration
10
+
11
+ def self.map_requirements(requirements)
12
+ requirements.map do |requirement|
13
+ declaration = new(requirement[:metadata][:requirement_string])
14
+
15
+ new_declaration = yield(declaration)
16
+ new_requirement = new(new_declaration)
17
+
18
+ requirement.merge(
19
+ requirement: new_requirement.to_s,
20
+ metadata: { requirement_string: new_declaration }
21
+ )
22
+ end
23
+ end
24
+
25
+ def initialize(declaration)
26
+ @declaration = declaration
27
+
28
+ min, max = parse_declaration(declaration)
29
+
30
+ constraint = if min == max
31
+ ["= #{min}"]
32
+ elsif closed_range?
33
+ [">= #{min}", "<= #{max}"]
34
+ else
35
+ [">= #{min}", "< #{max}"]
36
+ end
37
+
38
+ @min = min
39
+ @max = max
40
+ @requirement = Requirement.new(constraint)
41
+ end
42
+
43
+ def to_s
44
+ requirement.to_s
45
+ end
46
+
47
+ def update_if_needed(version)
48
+ return declaration if requirement.satisfied_by?(version)
49
+
50
+ update(version)
51
+ end
52
+
53
+ def update(version)
54
+ if single_version_declaration?
55
+ declaration.sub(min, version.to_s)
56
+ elsif closed_range?
57
+ declaration.sub(max, version.to_s)
58
+ elsif range?
59
+ declaration.sub(max, bump_major(version.to_s))
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def parse_declaration(declaration)
66
+ if up_to_next_major?
67
+ min = declaration.gsub(/\Afrom\s*:\s*"(\S+)"\s*\z/, '\1')
68
+ max = bump_major(min)
69
+ elsif up_to_next_major_deprecated?
70
+ min = declaration.gsub(/\A\.upToNextMajor\s*\(\s*from\s*:\s*"(\S+)"\s*\)\z/, '\1')
71
+ max = bump_major(min)
72
+ elsif up_to_next_minor_deprecated?
73
+ min = declaration.gsub(/\A\.upToNextMinor\s*\(\s*from\s*:\s*"(\S+)"\s*\)\z/, '\1')
74
+ max = bump_minor(min)
75
+ elsif closed_range?
76
+ min, max = parse_range("...")
77
+ elsif range?
78
+ min, max = parse_range("..<")
79
+ elsif exact_version?
80
+ min = declaration.gsub(/\Aexact\s*:\s*"(\S+)"\s*\z/, '\1')
81
+ max = min
82
+ elsif exact_version_deprecated?
83
+ min = declaration.gsub(/\A\.exact\s*\(\s*"(\S+)"\s*\)\z/, '\1')
84
+ max = min
85
+ else
86
+ raise "Unsupported constraint: #{declaration}"
87
+ end
88
+
89
+ [min, max]
90
+ end
91
+
92
+ def parse_range(separator)
93
+ declaration.split(separator).map { |str| unquote(str) }
94
+ end
95
+
96
+ def single_version_declaration?
97
+ up_to_next_major? || up_to_next_major_deprecated? || up_to_next_minor? ||
98
+ exact_version? || exact_version_deprecated?
99
+ end
100
+
101
+ def bump_major(str)
102
+ transform_version(str) do |s, i|
103
+ i.zero? ? s.to_i + 1 : 0
104
+ end
105
+ end
106
+
107
+ def bump_minor(str)
108
+ transform_version(str) do |s, i|
109
+ if i.zero?
110
+ s
111
+ else
112
+ (i == 1 ? s.to_i + 1 : 0)
113
+ end
114
+ end
115
+ end
116
+
117
+ def transform_version(str, &block)
118
+ str.split(".").map.with_index(&block).join(".")
119
+ end
120
+
121
+ def up_to_next_major?
122
+ declaration.start_with?("from")
123
+ end
124
+
125
+ def up_to_next_major_deprecated?
126
+ declaration.start_with?(".upToNextMajor")
127
+ end
128
+
129
+ def up_to_next_minor_deprecated?
130
+ declaration.start_with?(".upToNextMinor")
131
+ end
132
+
133
+ def exact_version?
134
+ declaration.start_with?("exact")
135
+ end
136
+
137
+ def exact_version_deprecated?
138
+ declaration.start_with?(".exact")
139
+ end
140
+
141
+ def closed_range?
142
+ declaration.include?("...")
143
+ end
144
+
145
+ def range?
146
+ declaration.include?("..<")
147
+ end
148
+
149
+ attr_reader :min, :max, :requirement
150
+
151
+ def unquote(declaration)
152
+ declaration[1..-2]
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ Dependabot::Utils.
159
+ register_requirement_class("swift", Dependabot::Swift::Requirement)
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/utils"
4
+
5
+ module Dependabot
6
+ module Swift
7
+ class Requirement < Gem::Requirement
8
+ # For consistency with other languages, we define a requirements array.
9
+ # Swift doesn't have an `OR` separator for requirements, so it
10
+ # always contains a single element.
11
+ def self.requirements_array(requirement_string)
12
+ [new(requirement_string)]
13
+ end
14
+
15
+ # Patches Gem::Requirement to make it accept requirement strings like
16
+ # "~> 4.2.5, >= 4.2.5.1" without first needing to split them.
17
+ def initialize(*requirements)
18
+ requirements = requirements.flatten.flat_map do |req_string|
19
+ req_string.split(",").map(&:strip)
20
+ end
21
+
22
+ super(requirements)
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ Dependabot::Utils.
29
+ register_requirement_class("swift", Dependabot::Swift::Requirement)
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/update_checkers/base"
4
+ require "dependabot/swift/native_requirement"
5
+ require "dependabot/swift/version"
6
+
7
+ module Dependabot
8
+ module Swift
9
+ class UpdateChecker < Dependabot::UpdateCheckers::Base
10
+ class RequirementsUpdater
11
+ def initialize(requirements:, target_version:)
12
+ @requirements = requirements
13
+
14
+ return unless target_version && Version.correct?(target_version)
15
+
16
+ @target_version = Version.new(target_version)
17
+ end
18
+
19
+ def updated_requirements
20
+ NativeRequirement.map_requirements(requirements) do |requirement|
21
+ requirement.update_if_needed(target_version)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :requirements, :target_version
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/update_checkers/base"
4
+ require "dependabot/swift/file_parser/dependency_parser"
5
+ require "dependabot/swift/file_updater/lockfile_updater"
6
+
7
+ module Dependabot
8
+ module Swift
9
+ class UpdateChecker < Dependabot::UpdateCheckers::Base
10
+ class VersionResolver
11
+ def initialize(dependency:, manifest:, repo_contents_path:, credentials:)
12
+ @dependency = dependency
13
+ @manifest = manifest
14
+ @credentials = credentials
15
+ @repo_contents_path = repo_contents_path
16
+ end
17
+
18
+ def latest_resolvable_version
19
+ @latest_resolvable_version ||= fetch_latest_resolvable_version
20
+ end
21
+
22
+ private
23
+
24
+ def fetch_latest_resolvable_version
25
+ updated_lockfile_content = FileUpdater::LockfileUpdater.new(
26
+ dependencies: [dependency],
27
+ manifest: manifest,
28
+ repo_contents_path: repo_contents_path,
29
+ credentials: credentials
30
+ ).updated_lockfile_content
31
+
32
+ lockfile = DependencyFile.new(
33
+ name: "Package.resolved",
34
+ content: updated_lockfile_content
35
+ )
36
+
37
+ dependency_parser(manifest, lockfile).parse.find do |parsed_dep|
38
+ parsed_dep.name == dependency.name
39
+ end.version
40
+ end
41
+
42
+ def dependency_parser(manifest, lockfile)
43
+ FileParser::DependencyParser.new(
44
+ dependency_files: [manifest, lockfile],
45
+ repo_contents_path: repo_contents_path,
46
+ credentials: credentials
47
+ )
48
+ end
49
+
50
+ attr_reader :dependency, :manifest, :repo_contents_path, :credentials
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/update_checkers"
4
+ require "dependabot/update_checkers/base"
5
+ require "dependabot/git_commit_checker"
6
+ require "dependabot/swift/native_requirement"
7
+ require "dependabot/swift/file_updater/manifest_updater"
8
+
9
+ module Dependabot
10
+ module Swift
11
+ class UpdateChecker < Dependabot::UpdateCheckers::Base
12
+ require_relative "update_checker/requirements_updater"
13
+ require_relative "update_checker/version_resolver"
14
+
15
+ def latest_version
16
+ @latest_version ||= fetch_latest_version
17
+ end
18
+
19
+ def latest_resolvable_version
20
+ @latest_resolvable_version ||= fetch_latest_resolvable_version
21
+ end
22
+
23
+ def latest_resolvable_version_with_no_unlock
24
+ raise NotImplementedError
25
+ end
26
+
27
+ def updated_requirements
28
+ RequirementsUpdater.new(
29
+ requirements: old_requirements,
30
+ target_version: preferred_resolvable_version
31
+ ).updated_requirements
32
+ end
33
+
34
+ private
35
+
36
+ def old_requirements
37
+ dependency.requirements
38
+ end
39
+
40
+ def fetch_latest_version
41
+ return unless git_commit_checker.pinned_ref_looks_like_version? && latest_version_tag
42
+
43
+ latest_version_tag.fetch(:version)
44
+ end
45
+
46
+ def fetch_latest_resolvable_version
47
+ Version.new(version_resolver.latest_resolvable_version)
48
+ end
49
+
50
+ def version_resolver
51
+ VersionResolver.new(
52
+ dependency: dependency,
53
+ manifest: prepared_manifest,
54
+ repo_contents_path: repo_contents_path,
55
+ credentials: credentials
56
+ )
57
+ end
58
+
59
+ def unlocked_requirements
60
+ NativeRequirement.map_requirements(old_requirements) do |_old_requirement|
61
+ "\"#{dependency.version}\"...\"#{latest_version}\""
62
+ end
63
+ end
64
+
65
+ def prepared_manifest
66
+ DependencyFile.new(
67
+ name: manifest.name,
68
+ content: FileUpdater::ManifestUpdater.new(
69
+ manifest.content,
70
+ old_requirements: old_requirements,
71
+ new_requirements: unlocked_requirements
72
+ ).updated_manifest_content
73
+ )
74
+ end
75
+
76
+ def manifest
77
+ dependency_files.find { |file| file.name == "Package.swift" }
78
+ end
79
+
80
+ def latest_version_resolvable_with_full_unlock?
81
+ # Full unlock checks aren't implemented for Swift (yet)
82
+ false
83
+ end
84
+
85
+ def updated_dependencies_after_full_unlock
86
+ raise NotImplementedError
87
+ end
88
+
89
+ def git_commit_checker
90
+ @git_commit_checker ||= Dependabot::GitCommitChecker.new(
91
+ dependency: dependency,
92
+ credentials: credentials,
93
+ ignored_versions: ignored_versions,
94
+ raise_on_ignored: raise_on_ignored,
95
+ consider_version_branches_pinned: true
96
+ )
97
+ end
98
+
99
+ def latest_version_tag
100
+ git_commit_checker.local_tag_for_latest_version
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ Dependabot::UpdateCheckers.
107
+ register("swift", Dependabot::Swift::UpdateChecker)
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dependabot
4
+ module Swift
5
+ class Version < Dependabot::Version
6
+ end
7
+ end
8
+ end
9
+
10
+ Dependabot::Utils.
11
+ register_version_class("swift", Dependabot::Swift::Version)
@@ -0,0 +1,22 @@
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/swift/file_fetcher"
6
+ require "dependabot/swift/file_parser"
7
+ require "dependabot/swift/update_checker"
8
+ require "dependabot/swift/file_updater"
9
+ require "dependabot/swift/metadata_finder"
10
+ require "dependabot/swift/requirement"
11
+ require "dependabot/swift/version"
12
+
13
+ require "dependabot/pull_request_creator/labeler"
14
+ Dependabot::PullRequestCreator::Labeler.
15
+ register_label_details("swift", name: "swift_package_manager", colour: "F05138")
16
+
17
+ require "dependabot/dependency"
18
+ Dependabot::Dependency.
19
+ register_production_check("swift", ->(_) { true })
20
+
21
+ require "dependabot/utils"
22
+ Dependabot::Utils.register_always_clone("swift")
metadata ADDED
@@ -0,0 +1,230 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dependabot-swift
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.222.0
5
+ platform: ruby
6
+ authors:
7
+ - Dependabot
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-07-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dependabot-common
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.222.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.222.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: debug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.8.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: gpgme
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: parallel_tests
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 4.2.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 4.2.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '13'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '13'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.12'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.12'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-its
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.3'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.3'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 1.50.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 1.50.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-performance
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 1.17.1
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 1.17.1
139
+ - !ruby/object:Gem::Dependency
140
+ name: stackprof
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 0.2.16
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 0.2.16
153
+ - !ruby/object:Gem::Dependency
154
+ name: vcr
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '6.1'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '6.1'
167
+ - !ruby/object:Gem::Dependency
168
+ name: webmock
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '3.18'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '3.18'
181
+ description: Dependabot-Swift provides support for bumping Swift packages via Dependabot.
182
+ If you want support for multiple package managers, you probably want the meta-gem
183
+ dependabot-omnibus.
184
+ email: opensource@github.com
185
+ executables: []
186
+ extensions: []
187
+ extra_rdoc_files: []
188
+ files:
189
+ - lib/dependabot/swift.rb
190
+ - lib/dependabot/swift/file_fetcher.rb
191
+ - lib/dependabot/swift/file_parser.rb
192
+ - lib/dependabot/swift/file_parser/dependency_parser.rb
193
+ - lib/dependabot/swift/file_parser/manifest_parser.rb
194
+ - lib/dependabot/swift/file_updater.rb
195
+ - lib/dependabot/swift/file_updater/lockfile_updater.rb
196
+ - lib/dependabot/swift/file_updater/manifest_updater.rb
197
+ - lib/dependabot/swift/file_updater/requirement_replacer.rb
198
+ - lib/dependabot/swift/metadata_finder.rb
199
+ - lib/dependabot/swift/native_requirement.rb
200
+ - lib/dependabot/swift/requirement.rb
201
+ - lib/dependabot/swift/update_checker.rb
202
+ - lib/dependabot/swift/update_checker/requirements_updater.rb
203
+ - lib/dependabot/swift/update_checker/version_resolver.rb
204
+ - lib/dependabot/swift/version.rb
205
+ homepage: https://github.com/dependabot/dependabot-core
206
+ licenses:
207
+ - Nonstandard
208
+ metadata:
209
+ bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
210
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.222.0
211
+ post_install_message:
212
+ rdoc_options: []
213
+ require_paths:
214
+ - lib
215
+ required_ruby_version: !ruby/object:Gem::Requirement
216
+ requirements:
217
+ - - ">="
218
+ - !ruby/object:Gem::Version
219
+ version: 3.1.0
220
+ required_rubygems_version: !ruby/object:Gem::Requirement
221
+ requirements:
222
+ - - ">="
223
+ - !ruby/object:Gem::Version
224
+ version: 3.1.0
225
+ requirements: []
226
+ rubygems_version: 3.3.26
227
+ signing_key:
228
+ specification_version: 4
229
+ summary: Provides Dependabot support for Swift
230
+ test_files: []