Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPM: allow pod specs to declare Swift Package Manager dependencies with spm_dependency #743

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/cocoapods-core/specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require 'cocoapods-core/specification/root_attribute_accessors'
require 'cocoapods-core/specification/set'
require 'cocoapods-core/specification/json'
require 'cocoapods-core/specification/spm_requirement'

module Pod
# The Specification provides a DSL to describe a Pod. A pod is defined as a
Expand Down
9 changes: 9 additions & 0 deletions lib/cocoapods-core/specification/consumer.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'cocoapods-core/specification/root_attribute_accessors'
require 'cocoapods-core/specification/spm_requirement'

module Pod
class Specification
Expand Down Expand Up @@ -234,6 +235,14 @@ def dependencies
end
end

#-----------------------------------------------------------------------#
def spm_dependencies
value = value_for_attribute(:spm_dependencies)
value.map do |spm_dependency|
{:url => spm_dependency[:url], :requirement => Pod::Specification::SpmRequirement.new(spm_dependency[:requirement]), :products => spm_dependency[:products]}
end
end

# Raw values need to be prepared as soon as they are read so they can be
# safely merged to support multi platform attributes and inheritance
#-----------------------------------------------------------------------#
Expand Down
28 changes: 28 additions & 0 deletions lib/cocoapods-core/specification/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,34 @@ def dependency=(args)

#------------------#

attribute :spm_dependencies,
:container => Array,
:inherited => true

# Dependency on Swift Manager Packages.
#
# ---
#
# Dependencies should specify versions requirements.
#
# @example
# spec.spm_dependency(
# :url => 'https://github.com/apple/swift-atomics.git',
# :requirement' => {:kind => 'upToNextMajorVersion', :minimumVersion => '1.1.0'},
# :products' => ['Atomics']
# )

def spm_dependency(url: , requirement:, products:)
attributes_hash['spm_dependencies'] ||= []
attributes_hash['spm_dependencies'] << {
:url => url,
:requirement => requirement,
:products => products,
}
end

#------------------#

# @!method info_plist=(info_plist)
#
# Key-Value pairs to add to the generated `Info.plist`.
Expand Down
22 changes: 22 additions & 0 deletions lib/cocoapods-core/specification/linter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,28 @@ def _validate_scheme(s)
end
end


# Performs validations related to the `spm_dependencies` attribute.
#
def _validate_spm_dependencies(s)
unless s.empty?
s.each do |spm_dependency|
if spm_dependency[:url].nil?
results.add_error('spm_dependencies', 'SPM dependencies should specify a url.')
end
if spm_dependency[:requirement].nil?
results.add_error('spm_dependencies', 'SPM dependencies should specify a requirement.')
end
if requirement_errors = SpmRequirement.validate(spm_dependency[:requirement])
results.add_error('spm_dependencies', requirement_errors)
end
if spm_dependency[:products].nil?
results.add_error('spm_dependencies', 'SPM dependencies should specify products.')
end
end
end
end

# Performs validations related to github sources.
#
def perform_github_source_checks(s)
Expand Down
51 changes: 51 additions & 0 deletions lib/cocoapods-core/specification/spm_requirement.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module Pod
class Specification
# This class validates and represents swift package manager dependecy requirements
class SpmRequirement
REQUIRED_KEYS = {
:upToNextMajorVersion => [:minimumVersion],
:upToNextMinorVersion => [:minimumVersion],
:exactVersion => [:version],
:versionRange => %i[minimumVersion maximumVersion],
}.freeze

def initialize(requirement_hash)
@requirement = requirement_hash
validate
end

def kind
@requirement[:kind]
end

def ==(other)
@requirement == other.instance_variable_get(:@requirement)
end

def validate
raise 'Kind should be string' unless kind.is_a?(String)
raise "Unknown requirement kind #{kind}" if REQUIRED_KEYS[kind.to_sym].nil?

REQUIRED_KEYS[kind.to_sym].each do |key|
raise "Missing key #{key} for requirement #{@requirement}" unless @requirement[key]
end
end

def to_h
@requirement.map { |k,v| [k.to_s, v.to_s] }.to_h
end

def self.validate(requirement_hash)
if (requirement_hash.is_a? SpmRequirement)
requirement_hash.validate
nil
else
new(requirement_hash)
nil
end
rescue => e
e.message
end
end
end
end
24 changes: 24 additions & 0 deletions spec/specification/consumer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,30 @@ module Pod

#-------------------------------------------------------------------------#

describe 'SPM Dependencies' do
before do
@spec = Spec.new do |s|
s.name = 'Pod'
s.spm_dependency(
:url => "https://github.com/apple/example-package-fisheryates.git",
:requirement => { :kind => "upToNextMajorVersion", :minimumVersion => "1.0.0" },
:products => ["FisherYates"],
)
end
@consumer = Specification::Consumer.new(@spec, :ios)
end

it 'returns the spm_dependencies with SpmRequirement' do
@consumer.spm_dependencies.should == [{
:url => "https://github.com/apple/example-package-fisheryates.git",
:requirement => Specification::SpmRequirement.new({ :kind => "upToNextMajorVersion", :minimumVersion => "1.0.0" }),
:products => ["FisherYates"],
}]
end
end

#-------------------------------------------------------------------------#

describe 'Private helpers' do
before do
@spec = Spec.new do |s|
Expand Down
11 changes: 11 additions & 0 deletions spec/specification/dsl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,17 @@ module Pod

#------------------#

describe 'spm_dependency' do
it 'allows to specify a single spm_dependency' do
@spec.spm_dependency(:url => "foo", :requirement => {:kind => "upToNextMajorVersion", :minimumVersion => "1.0.0"}, :products => ["Foo"])
@spec.attributes_hash['spm_dependencies'].should == [
{ :url => 'foo', :requirement => {:kind => "upToNextMajorVersion", :minimumVersion => "1.0.0"}, :products => ["Foo"] },
]
end
end

#------------------#

it 'allows to specify whether the specification requires ARC' do
@spec.requires_arc = false
@spec.attributes_hash['requires_arc'].should == false
Expand Down
18 changes: 18 additions & 0 deletions spec/specification/json_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,24 @@ module Pod
result.swift_versions.map(&:to_s).should == %w(3.2 4.0 4.1)
result.swift_version.to_s.should == '4.1'
end

describe 'Swift Package Manger dependencies' do
it 'writes spm dependency' do
@spec.spm_dependency(
:url => 'http://github.com/foo/foo',
:requirement => {:kind => 'upToNextMajorVersion', :minimumVersion => '1.0.0'},
:products => ['Foo'],
)
hash = @spec.to_hash
hash['spm_dependencies'].should == [
{
:url => 'http://github.com/foo/foo',
:requirement => {:kind => 'upToNextMajorVersion', :minimumVersion => '1.0.0'},
:products => ['Foo'],
},
]
end
end
end
end
end
Expand Down
7 changes: 7 additions & 0 deletions spec/specification/linter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,13 @@ def result_should_include(*values)
@spec.compiler_flags = '-some_flag', '-another -Wno_flags'
result_should_include('warnings', 'disabled', 'compiler_flags')
end

#------------------#

it 'check if spm dependency requirement upToNextMinorVersion has a minimumVersion key' do
@spec.spm_dependency(:url => 'https://github.com/foo/foo', :requirement => { :kind => 'upToNextMinorVersion' }, :products => ['Foo'])
result_should_include('missing key minimumVersion')
end
end

#--------------------------------------#
Expand Down