Skip to content

Commit

Permalink
Merge pull request #697 from dnkoutso/odr_category
Browse files Browse the repository at this point in the history
Extend `on_demand_resources` DSL to allow the ability to specify a category.
  • Loading branch information
dnkoutso committed Aug 10, 2021
2 parents 609a964 + dddf36e commit b3b2436
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 17 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

##### Enhancements

* None.
* Extend `on_demand_resources` DSL to allow the ability to specify a category.
[Dimitris Koutsogiorgas](https://github.com/dnkoutso)
[#697](https://github.com/CocoaPods/Core/pull/697)

##### Bug Fixes

Expand Down
6 changes: 6 additions & 0 deletions lib/cocoapods-core/specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,12 @@ def script_phases
end
end

# @return [Hash] The on demand resources value.
#
def on_demand_resources
attributes_hash['on_demand_resources'] || {}
end

# @return [Hash] The scheme value.
#
def scheme
Expand Down
12 changes: 10 additions & 2 deletions lib/cocoapods-core/specification/consumer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -471,13 +471,21 @@ def _prepare_scheme(value)
# @param [String, Array, Hash] value.
# The value of the attribute as specified by the user.
#
# @return [Hash] the on demand resources1.
# @return [Hash] the on demand resources.
#
def _prepare_on_demand_resources(value)
result = {}
if value
value.each do |key, patterns|
result[key] = [*patterns].compact
case patterns
when String, Array
result[key] = { :paths => [*patterns].compact, :category => :download_on_demand }
when Hash
patterns = Specification.convert_keys_to_symbol(patterns, :recursive => false)
result[key] = { :paths => [*patterns[:paths]].compact, :category => patterns.fetch(:category, :download_on_demand).to_sym }
else
raise StandardError, "Unknown on demand resource value type `#{patterns}`."
end
end
end
result
Expand Down
29 changes: 22 additions & 7 deletions lib/cocoapods-core/specification/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1361,26 +1361,41 @@ def dependency=(args)

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

# The keys accepted by the category attribute for each on demand resource entry.
#
ON_DEMAND_RESOURCES_CATEGORY_KEYS = [:download_on_demand, :prefetched, :initial_install].freeze

# @!method on_demand_resources=(on_demand_resources)
#
# A hash of on_demand_resources that should be copied into the target bundle. Resources specified here
# will automatically become part of the resources build phase of the target.
# A hash of on demand resources that should be copied into the target bundle. Resources specified here
# will automatically become part of the resources build phase of the target this pod is integrated into.
#
# If no category is specified then `:download_on_demand` is used as the default.
#
# @note
#
# Tags specified by pods are always managed by CocoaPods. If a tag is renamed or deleted then CocoaPods will
# delete the tag within the targets the pod was integrated into.
#
# @example
#
# s.on_demand_resources = {
# 'Tag1' => 'file1.png'
# 'Tag1' => 'file1.png'
# }
#
# s.on_demand_resources = {
# 'Tag1' => ['file1.png', 'file2.png']
# 'Tag1' => ['file1.png', 'file2.png']
# }
#
# @param [Hash{String=>String}, Hash{String=>Array<String>}] on_demand_resources
# The on_demand_resources shipped with the Pod.
# s.on_demand_resources = {
# 'Tag1' => { :paths => ['file1.png', 'file2.png'], :category => :download_on_demand }
# }
#
# @param [Hash{String=>String}, Hash{String=>Array<String>}, Hash{String=>Hash}] on_demand_resources
# The on demand resources shipped with the Pod.
#
attribute :on_demand_resources,
:types => [String, Array],
:types => [String, Array, Hash],
:container => Hash,
:file_patterns => true,
:singularize => true
Expand Down
11 changes: 11 additions & 0 deletions lib/cocoapods-core/specification/linter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,17 @@ def _validate_script_phases(s)
end
end

# Performs validations related to the `on_demand_resources` attribute.
#
def _validate_on_demand_resources(h)
h.values.each do |value|
unless Specification::ON_DEMAND_RESOURCES_CATEGORY_KEYS.include?(value[:category])
results.add_error('on_demand_resources', "Invalid on demand resources category value `#{value[:category]}`. " \
"Available options are `#{Specification::ON_DEMAND_RESOURCES_CATEGORY_KEYS.join(', ')}`.")
end
end
end

# Performs validation related to the `scheme` attribute.
#
def _validate_scheme(s)
Expand Down
1 change: 1 addition & 0 deletions lib/cocoapods-core/specification/linter/analyzer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ def validate_file_patterns

if patterns.respond_to?(:each)
patterns.each do |pattern|
pattern = pattern[:paths].join if attrb.name == :on_demand_resources
if pattern.respond_to?(:start_with?) && pattern.start_with?('/')
results.add_error('File Patterns', 'File patterns must be ' \
"relative and cannot start with a slash (#{attrb.name}).")
Expand Down
26 changes: 19 additions & 7 deletions spec/specification/consumer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -463,25 +463,37 @@ module Pod

it 'returns the on demand resources specified as a string wrapped in an array' do
@spec.on_demand_resources = { 'Maps' => 'MapView/Map/Resources/*.png' }
@consumer.on_demand_resources.should == { 'Maps' => ['MapView/Map/Resources/*.png'] }
@consumer.on_demand_resources.should == { 'Maps' => { :paths => ['MapView/Map/Resources/*.png'], :category => :download_on_demand } }
end

it 'returns the on demand resources specified as an array wrapped in an array' do
@spec.on_demand_resources = { 'Levels' => %w[Levels/Level1/Resources/*.png Levels/Level2/Resources/*.png] }
@consumer.on_demand_resources.should == { 'Levels' => %w[Levels/Level1/Resources/*.png Levels/Level2/Resources/*.png] }
@consumer.on_demand_resources.should == {
'Levels' => { :paths => %w[Levels/Level1/Resources/*.png Levels/Level2/Resources/*.png], :category => :download_on_demand },
}
end

it 'handles multi-platform on demand resources' do
@spec.ios.on_demand_resources = { 'Maps' => 'MapView/Map/Resources/*.png' }
@consumer.on_demand_resources.should == { 'Maps' => ['MapView/Map/Resources/*.png'] }
@consumer.on_demand_resources.should == { 'Maps' => { :paths => ['MapView/Map/Resources/*.png'], :category => :download_on_demand } }
end

it 'handles on demand resources with categories' do
@spec.on_demand_resources = { 'Maps' => { :paths => 'MapView/Map/Resources/*.png', :category => :initial_install } }
@consumer.on_demand_resources.should == { 'Maps' => { :paths => ['MapView/Map/Resources/*.png'], :category => :initial_install } }
end

it 'handles on demand resources with keys and values as strings' do
@spec.on_demand_resources = { 'Maps' => { 'paths' => 'MapView/Map/Resources/*.png', 'category' => 'initial_install' } }
@consumer.on_demand_resources.should == { 'Maps' => { :paths => ['MapView/Map/Resources/*.png'], :category => :initial_install } }
end

it 'merges multi platform on demand resources if needed' do
it 'merges multi platform on demand resources if needed' do
@spec.on_demand_resources = { 'Maps' => 'MapView/Map/Resources/*.png' }
@spec.ios.on_demand_resources = { 'Maps-iOS' => 'MapView/Map/iOS/Resources/*.png' }
@spec.ios.on_demand_resources = { 'Maps-iOS' => ['MapView/Map/iOS/Resources/*.png'] }
@consumer.on_demand_resources.should == {
'Maps' => ['MapView/Map/Resources/*.png'],
'Maps-iOS' => ['MapView/Map/iOS/Resources/*.png'],
'Maps' => { :paths => ['MapView/Map/Resources/*.png'], :category => :download_on_demand },
'Maps-iOS' => { :paths => ['MapView/Map/iOS/Resources/*.png'], :category => :download_on_demand },
}
end

Expand Down
30 changes: 30 additions & 0 deletions spec/specification/json_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,25 @@ module Pod
]
end

it 'can load on demand resources from a hash' do
hash = {
'name' => 'BananaLib',
'version' => '1.0',
'on_demand_resources' => {
'Tag1' => { :paths => 'Tag1Resources/*', :category => :download_on_demand },
'Tag2' => ['Tag2Resources/*'],
'Tag3' => 'Tag3Resources/bear.png*',
},
}
result = Specification.from_hash(hash)
result.on_demand_resources.count.should.equal 3
result.on_demand_resources.should == {
'Tag1' => { :paths => 'Tag1Resources/*', :category => :download_on_demand },
'Tag2' => ['Tag2Resources/*'],
'Tag3' => 'Tag3Resources/bear.png*',
}
end

it 'can load default subspecs from hash' do
hash = {
'name' => 'BananaLib',
Expand Down Expand Up @@ -445,6 +464,17 @@ module Pod
]
end

it 'can load on demand resources from json' do
json = '{"on_demand_resources":{"tag1":{"paths":"Tag1Resources/*","category":"download_on_demand"},"tag2":"Tag2Resources/*","tag3":["Tag3Resources/*"]}}'
result = Specification.from_json(json)
result.on_demand_resources.count.should.equal 3
result.on_demand_resources.should == {
'tag1' => { 'paths' => 'Tag1Resources/*', 'category' => 'download_on_demand' },
'tag2' => 'Tag2Resources/*',
'tag3' => ['Tag3Resources/*'],
}
end

it 'loads script phase execution position from json' do
json = '{"script_phases": [{"name": "Hello World", "script": "echo \"Hello World\"", "execution_position": "before_compile"}]}'
result = Specification.from_json(json)
Expand Down
12 changes: 12 additions & 0 deletions spec/specification/linter/analyzer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,18 @@ module Pod
results.first.attribute_name.should.include?('File Patterns')
end

it 'checks if any file patterns are absolute for on demand resources' do
@spec.on_demand_resources = {
'Tag1' => { :paths => '/Resources', :category => :download_on_demand },
'Tag2' => '/MyResources',
}
results = @analyzer.analyze
results.count.should.be.equal(1)
expected = 'patterns must be relative'
results.first.message.should.include?(expected)
results.first.attribute_name.should.include?('File Patterns')
end

it 'checks if a specification is empty' do
consumer = Specification::Consumer
consumer.any_instance.stubs(:source_files).returns([])
Expand Down
20 changes: 20 additions & 0 deletions spec/specification/linter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,26 @@ def result_should_include(*values)

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

it 'checks on demand resources category is a valid value' do
@spec.on_demand_resources = {
'Level1' => { :paths => 'File1.png', :category => :unknown },
'Level2' => 'File2.png',
'Level3' => ['File3.png'],
'Level4' => { :paths => 'File4.png', :category => :weird },
}
results.count.should == 2
results[0].attribute_name.should == 'on_demand_resources'
results[0].type.should == :error
results[0].message.should == 'Invalid on demand resources category value `unknown`. ' \
'Available options are `download_on_demand, prefetched, initial_install`.'
results[1].attribute_name.should == 'on_demand_resources'
results[1].type.should == :error
results[1].message.should == 'Invalid on demand resources category value `weird`. ' \
'Available options are `download_on_demand, prefetched, initial_install`.'
end

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

it 'accepts valid scheme values' do
@spec.scheme = { :launch_arguments => ['Arg1'], :environment_variables => { 'Key1' => 'Val1' },
:code_coverage => true }
Expand Down

0 comments on commit b3b2436

Please sign in to comment.