From ec23ebf9a8d1591673abc2ce12775c36b493401a Mon Sep 17 00:00:00 2001 From: Dimitris Koutsogiorgas Date: Thu, 28 Sep 2017 12:23:52 -0700 Subject: [PATCH] Add podspec `script_phases` DSL --- CHANGELOG.md | 4 + .../podfile/target_definition.rb | 12 +- lib/cocoapods-core/specification.rb | 38 +++++-- lib/cocoapods-core/specification/consumer.rb | 26 ++++- lib/cocoapods-core/specification/dsl.rb | 43 ++++++- lib/cocoapods-core/specification/linter.rb | 17 +++ .../specification/root_attribute_accessors.rb | 25 +---- .../vcr_cassettes/MasterSource_fetch.yml | 105 +++++++++++++++++- .../vcr_cassettes/MasterSource_nofetch.yml | 105 +++++++++++++++++- spec/specification/consumer_spec.rb | 41 +++++++ spec/specification/dsl_spec.rb | 12 +- spec/specification/json_spec.rb | 38 +++++++ spec/specification/linter_spec.rb | 13 +++ 13 files changed, 431 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55c3b453a..2b940aafc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ##### Enhancements +* Add podspec `script_phases` DSL + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#413](https://github.com/CocoaPods/Core/pull/413) + * Update commments/docs to indicate prefix_header=false will skip pch generation [Paul Beusterien](https://github.com/paulb777) [#412](https://github.com/CocoaPods/Core/pull/412) diff --git a/lib/cocoapods-core/podfile/target_definition.rb b/lib/cocoapods-core/podfile/target_definition.rb index f553b47d1..c2bb8c210 100644 --- a/lib/cocoapods-core/podfile/target_definition.rb +++ b/lib/cocoapods-core/podfile/target_definition.rb @@ -585,12 +585,6 @@ def store_podspec(options = nil) #--------------------------------------# - SCRIPT_PHASE_REQUIRED_KEYS = [:name, :script].freeze - - SCRIPT_PHASE_OPTIONAL_KEYS = [:shell_path, :input_files, :output_files, :show_env_vars_in_log].freeze - - ALL_SCRIPT_PHASE_KEYS = (SCRIPT_PHASE_REQUIRED_KEYS + SCRIPT_PHASE_OPTIONAL_KEYS).freeze - # Stores the script phase to add for this target definition. # # @param [Hash] options @@ -602,12 +596,12 @@ def store_podspec(options = nil) # def store_script_phase(options) option_keys = options.keys - unrecognized_keys = option_keys - ALL_SCRIPT_PHASE_KEYS + unrecognized_keys = option_keys - Specification::ALL_SCRIPT_PHASE_KEYS unless unrecognized_keys.empty? raise StandardError, "Unrecognized options `#{unrecognized_keys}` in shell script `#{options}` within `#{name}` target. " \ - "Available options are `#{ALL_SCRIPT_PHASE_KEYS}`." + "Available options are `#{Specification::ALL_SCRIPT_PHASE_KEYS}`." end - missing_required_keys = SCRIPT_PHASE_REQUIRED_KEYS - option_keys + missing_required_keys = Specification::SCRIPT_PHASE_REQUIRED_KEYS - option_keys unless missing_required_keys.empty? raise StandardError, "Missing required shell script phase options `#{missing_required_keys.join(', ')}`" end diff --git a/lib/cocoapods-core/specification.rb b/lib/cocoapods-core/specification.rb index 0b264d294..afe4fedf7 100644 --- a/lib/cocoapods-core/specification.rb +++ b/lib/cocoapods-core/specification.rb @@ -352,6 +352,12 @@ def prefix_header_file attributes_hash['prefix_header_file'] end + # @return [ArrayString}>] The script_phases value. + # + def script_phases + Specification.convert_keys_to_symbol(attributes_hash['script_phases']) + end + #-------------------------------------------------------------------------# public @@ -376,11 +382,6 @@ def local? # # @overload supported_on_platform?(symbolic_name, deployment_target) # - # @param [Symbol] symbolic_name - # the name of the platform which is checked for support. - # - # @param [String] deployment_target - # the deployment target which is checked for support. # def supported_on_platform?(*platform) platform = Platform.new(*platform) @@ -462,7 +463,7 @@ def platform_hash # @param [Object] value # the value to store. # - # @param [Symbol] platform. + # @param [Symbol] platform_name # If provided the attribute is stored only for the given platform. # # @note If the provides value is Hash the keys are converted to a string. @@ -471,7 +472,7 @@ def platform_hash # def store_attribute(name, value, platform_name = nil) name = name.to_s - value = convert_keys_to_string(value) if value.is_a?(Hash) + value = Specification.convert_keys_to_string(value) if value.is_a?(Hash) value = value.strip_heredoc.strip if value.respond_to?(:strip_heredoc) if platform_name platform_name = platform_name.to_s @@ -495,8 +496,6 @@ def store_attribute(name, value, platform_name = nil) end end - private - # Converts the keys of the given hash to a string. # # @param [Object] value @@ -504,16 +503,33 @@ def store_attribute(name, value, platform_name = nil) # # @return [Hash] the hash with the strings instead of the keys. # - def convert_keys_to_string(value) + def self.convert_keys_to_string(value) return unless value result = {} value.each do |key, subvalue| - subvalue = convert_keys_to_string(subvalue) if subvalue.is_a?(Hash) + subvalue = Specification.convert_keys_to_string(subvalue) if subvalue.is_a?(Hash) result[key.to_s] = subvalue end result end + # Converts the keys of the given hash to a string. + # + # @param [Object] value + # the value that needs to be stripped from the Symbols. + # + # @return [Hash] the hash with the strings instead of the keys. + # + def self.convert_keys_to_symbol(value) + return unless value + result = {} + value.each do |key, subvalue| + subvalue = Specification.convert_keys_to_symbol(subvalue) if subvalue.is_a?(Hash) + result[key.to_sym] = subvalue + end + result + end + #-------------------------------------------------------------------------# public diff --git a/lib/cocoapods-core/specification/consumer.rb b/lib/cocoapods-core/specification/consumer.rb index aef64fe53..8a2c46900 100644 --- a/lib/cocoapods-core/specification/consumer.rb +++ b/lib/cocoapods-core/specification/consumer.rb @@ -179,6 +179,11 @@ def user_target_xcconfig # spec_attr_accessor :resource_bundles + # @return [ArrayString}>] An array of hashes where each hash + # represents a script phase. + # + spec_attr_accessor :script_phases + # @return [Array] A hash where the key represents the # paths of the resources to copy and the values the paths of # the resources that should be copied. @@ -324,7 +329,11 @@ def merge_values(attr, existing_value, new_value) # def prepare_value(attr, value) if attr.container == Array - value = [*value].compact + value = if value.is_a?(Hash) + [value] + else + [*value].compact + end end hook_name = prepare_hook_name(attr) @@ -362,6 +371,21 @@ def _prepare_prefix_header_contents(value) end end + # Converts the array of hashes (script phases) where keys are strings into symbols. + # + # @param [ArrayString}>] value. + # The value of the attribute as specified by the user. + # + # @return [ArrayString}>] the script phases array with symbols for each hash instead of strings. + # + def _prepare_script_phases(value) + if value + value.map do |script_phase| + Specification.convert_keys_to_symbol(script_phase) + end + end + end + # Ensures that the file patterns of the resource bundles are contained in # an array. # diff --git a/lib/cocoapods-core/specification/dsl.rb b/lib/cocoapods-core/specification/dsl.rb index 8af5bdb6b..fcd43e978 100644 --- a/lib/cocoapods-core/specification/dsl.rb +++ b/lib/cocoapods-core/specification/dsl.rb @@ -1134,7 +1134,7 @@ def dependency(*args) #------------------# - # @!method resource_bundles=(*frameworks) + # @!method resource_bundles=(*resource_bundles) # # This attribute allows to define the name and the file of the resource # bundles which should be built for the Pod. They are specified as a @@ -1272,6 +1272,47 @@ def dependency(*args) attribute :module_map, :root_only => true + #------------------# + + SCRIPT_PHASE_REQUIRED_KEYS = [:name, :script].freeze + + SCRIPT_PHASE_OPTIONAL_KEYS = [:shell_path, :input_files, :output_files, :show_env_vars_in_log].freeze + + ALL_SCRIPT_PHASE_KEYS = (SCRIPT_PHASE_REQUIRED_KEYS + SCRIPT_PHASE_OPTIONAL_KEYS).freeze + + # @!method script_phases=(*script_phases) + # + # This attribute allows to define a script phase to execute as part of compilation of the Pod. + # Unlike a prepare command, script phases execute as part of `xcodebuild` they can also utilize all environment + # variables that are set during compilation. + # + # A Pod can provide multiple script phases to execute and they will be added in the order they were + # declared. + # + # @example + # + # spec.script_phase = { :name => 'Hello World', :script => 'echo "Hello World"' } + # + # @example + # + # spec.script_phase = { :name => 'Hello World', :script => 'puts "Hello World"', :shell_path => '/usr/bin/ruby' } } + # + # @example + # + # spec.script_phases = [ + # { :name => 'Hello World', :script => 'echo "Hello World"' }, + # { :name => 'Hello Ruby World', :script => 'puts "Hello World"', :shell_path => '/usr/bin/ruby' } }, + # ] + # + # @param [ArrayString}>] script_phases + # A hash where the keys are the names of the script phases + # and the values represent the content and additional options. + # + attribute :script_phases, + :types => [Hash], + :container => Array, + :singularize => true + #-----------------------------------------------------------------------# # @!group Subspecs diff --git a/lib/cocoapods-core/specification/linter.rb b/lib/cocoapods-core/specification/linter.rb index ec18a2c1a..063828891 100644 --- a/lib/cocoapods-core/specification/linter.rb +++ b/lib/cocoapods-core/specification/linter.rb @@ -394,6 +394,23 @@ def _validate_test_type(t) end end + # Performs validations related to the `script_phases` attribute. + # + def _validate_script_phases(s) + s.each do |script_phase| + keys = script_phase.keys + unrecognized_keys = keys - Specification::ALL_SCRIPT_PHASE_KEYS + unless unrecognized_keys.empty? + results.add_error('script_phases', "Unrecognized options `#{unrecognized_keys}` in script phase `#{script_phase[:name]}`. " \ + "Available options are `#{Specification::ALL_SCRIPT_PHASE_KEYS}`.") + end + missing_required_keys = Specification::SCRIPT_PHASE_REQUIRED_KEYS - keys + unless missing_required_keys.empty? + results.add_error('script_phases', "Missing required shell script phase options `#{missing_required_keys.join(', ')}` in script phase `#{script_phase[:name]}`.") + end + end + end + # Performs validations related to github sources. # def perform_github_source_checks(s) diff --git a/lib/cocoapods-core/specification/root_attribute_accessors.rb b/lib/cocoapods-core/specification/root_attribute_accessors.rb index 8bbf28735..26b15c03e 100644 --- a/lib/cocoapods-core/specification/root_attribute_accessors.rb +++ b/lib/cocoapods-core/specification/root_attribute_accessors.rb @@ -92,7 +92,7 @@ def license if license.is_a?(String) { :type => license } elsif license.is_a?(Hash) - license = convert_keys_to_symbol(license) + license = Specification.convert_keys_to_symbol(license) license[:text] = license[:text].strip_heredoc if license[:text] license else @@ -110,7 +110,7 @@ def homepage # should be retrieved. # def source - convert_keys_to_symbol(attributes_hash['source']) + Specification.convert_keys_to_symbol(attributes_hash['source']) end # @return [String] A short description of the Pod. @@ -187,27 +187,6 @@ def module_map end #---------------------------------------------------------------------# - - private - - # Converts the keys of the given hash to a string. - # - # @param [Object] value - # the value that needs to be stripped from the Symbols. - # - # @return [Hash] the hash with the strings instead of the keys. - # - def convert_keys_to_symbol(value) - return unless value - result = {} - value.each do |key, subvalue| - subvalue = convert_keys_to_symbol(subvalue) if subvalue.is_a?(Hash) - result[key.to_sym] = subvalue - end - result - end - - #---------------------------------------------------------------------# end end end diff --git a/spec/fixtures/vcr_cassettes/MasterSource_fetch.yml b/spec/fixtures/vcr_cassettes/MasterSource_fetch.yml index abfec50aa..40a9dfb9a 100644 --- a/spec/fixtures/vcr_cassettes/MasterSource_fetch.yml +++ b/spec/fixtures/vcr_cassettes/MasterSource_fetch.yml @@ -71,4 +71,107 @@ http_interactions: string: 570c31dea8def019ec563be2326e053cc937e084 http_version: recorded_at: Wed, 09 Mar 2016 21:44:05 GMT -recorded_with: VCR 2.9.3 +- request: + method: get + uri: https://api.github.com/repos/dnkoutso/Core/commits/master + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - CocoaPods + Accept: + - application/vnd.github.chitauri-preview+sha + If-None-Match: + - '"4287d59a38ebb96af14009a6cb8434ce44480dbf"' + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + response: + status: + code: 200 + message: OK + headers: + Date: + - Fri, 29 Sep 2017 19:50:55 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Server: + - GitHub.com + Status: + - 200 OK + X-Ratelimit-Limit: + - '60' + X-Ratelimit-Remaining: + - '58' + X-Ratelimit-Reset: + - '1506718255' + Cache-Control: + - public, max-age=60, s-maxage=60 + Vary: + - Accept + - Accept-Encoding + Etag: + - W/"23884682188bf1e3e31208d5dc823c0c" + Last-Modified: + - Wed, 27 Sep 2017 15:25:59 GMT + X-Github-Media-Type: + - github.v3; param=chitauri-preview; format=sha + Access-Control-Expose-Headers: + - ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, + X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval + Access-Control-Allow-Origin: + - "*" + Content-Security-Policy: + - default-src 'none' + Strict-Transport-Security: + - max-age=31536000; includeSubdomains; preload + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + X-Xss-Protection: + - 1; mode=block + X-Runtime-Rack: + - '0.041130' + X-Github-Request-Id: + - 9660:15E9C:217A022:2C28F00:59CEA41F + body: + encoding: ASCII-8BIT + string: '{"sha":"283ac03a69984faab02c03ad65871966f7581481","commit":{"author":{"name":"Dimitris + Koutsogiorgas","email":"dnkoutso@gmail.com","date":"2017-09-27T15:25:59Z"},"committer":{"name":"GitHub","email":"noreply@github.com","date":"2017-09-27T15:25:59Z"},"message":"Merge + pull request #412 from paulb777/skip-pch2\n\nUpdate comments/docs to indicate + :skip will skip pch generation","tree":{"sha":"d682ef63ea8822fd497bf5afe61db3e6631beca8","url":"https://api.github.com/repos/dnkoutso/Core/git/trees/d682ef63ea8822fd497bf5afe61db3e6631beca8"},"url":"https://api.github.com/repos/dnkoutso/Core/git/commits/283ac03a69984faab02c03ad65871966f7581481","comment_count":0},"url":"https://api.github.com/repos/dnkoutso/Core/commits/283ac03a69984faab02c03ad65871966f7581481","html_url":"https://github.com/dnkoutso/Core/commit/283ac03a69984faab02c03ad65871966f7581481","comments_url":"https://api.github.com/repos/dnkoutso/Core/commits/283ac03a69984faab02c03ad65871966f7581481/comments","author":{"login":"dnkoutso","id":310370,"avatar_url":"https://avatars2.githubusercontent.com/u/310370?v=4","gravatar_id":"","url":"https://api.github.com/users/dnkoutso","html_url":"https://github.com/dnkoutso","followers_url":"https://api.github.com/users/dnkoutso/followers","following_url":"https://api.github.com/users/dnkoutso/following{/other_user}","gists_url":"https://api.github.com/users/dnkoutso/gists{/gist_id}","starred_url":"https://api.github.com/users/dnkoutso/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dnkoutso/subscriptions","organizations_url":"https://api.github.com/users/dnkoutso/orgs","repos_url":"https://api.github.com/users/dnkoutso/repos","events_url":"https://api.github.com/users/dnkoutso/events{/privacy}","received_events_url":"https://api.github.com/users/dnkoutso/received_events","type":"User","site_admin":false},"committer":{"login":"web-flow","id":19864447,"avatar_url":"https://avatars3.githubusercontent.com/u/19864447?v=4","gravatar_id":"","url":"https://api.github.com/users/web-flow","html_url":"https://github.com/web-flow","followers_url":"https://api.github.com/users/web-flow/followers","following_url":"https://api.github.com/users/web-flow/following{/other_user}","gists_url":"https://api.github.com/users/web-flow/gists{/gist_id}","starred_url":"https://api.github.com/users/web-flow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/web-flow/subscriptions","organizations_url":"https://api.github.com/users/web-flow/orgs","repos_url":"https://api.github.com/users/web-flow/repos","events_url":"https://api.github.com/users/web-flow/events{/privacy}","received_events_url":"https://api.github.com/users/web-flow/received_events","type":"User","site_admin":false},"parents":[{"sha":"811811b839932dd5aeb02dc90dfb55db89c6bedd","url":"https://api.github.com/repos/dnkoutso/Core/commits/811811b839932dd5aeb02dc90dfb55db89c6bedd","html_url":"https://github.com/dnkoutso/Core/commit/811811b839932dd5aeb02dc90dfb55db89c6bedd"},{"sha":"37b3a48e8b125c318f4c49ca2430cd51f9b632ea","url":"https://api.github.com/repos/dnkoutso/Core/commits/37b3a48e8b125c318f4c49ca2430cd51f9b632ea","html_url":"https://github.com/dnkoutso/Core/commit/37b3a48e8b125c318f4c49ca2430cd51f9b632ea"}],"stats":{"total":34,"additions":29,"deletions":5},"files":[{"sha":"55c3b453ac99aabeb2b9949ad723658b071dfc5f","filename":"CHANGELOG.md","status":"modified","additions":3,"deletions":1,"changes":4,"blob_url":"https://github.com/dnkoutso/Core/blob/283ac03a69984faab02c03ad65871966f7581481/CHANGELOG.md","raw_url":"https://github.com/dnkoutso/Core/raw/283ac03a69984faab02c03ad65871966f7581481/CHANGELOG.md","contents_url":"https://api.github.com/repos/dnkoutso/Core/contents/CHANGELOG.md?ref=283ac03a69984faab02c03ad65871966f7581481","patch":"@@ + -4,7 +4,9 @@\n \n ##### Enhancements\n \n-* None. \n+* Update commments/docs + to indicate prefix_header=false will skip pch generation \n+ [Paul Beusterien](https://github.com/paulb777)\n+ [#412](https://github.com/CocoaPods/Core/pull/412)\n + \n ##### Bug Fixes\n "},{"sha":"0b264d2948d5cd39c9e08b70f39055dada9ea146","filename":"lib/cocoapods-core/specification.rb","status":"modified","additions":6,"deletions":0,"changes":6,"blob_url":"https://github.com/dnkoutso/Core/blob/283ac03a69984faab02c03ad65871966f7581481/lib/cocoapods-core/specification.rb","raw_url":"https://github.com/dnkoutso/Core/raw/283ac03a69984faab02c03ad65871966f7581481/lib/cocoapods-core/specification.rb","contents_url":"https://api.github.com/repos/dnkoutso/Core/contents/lib/cocoapods-core/specification.rb?ref=283ac03a69984faab02c03ad65871966f7581481","patch":"@@ + -346,6 +346,12 @@ def consumer(platform)\n @consumers[platform] ||= + Consumer.new(self, platform)\n end\n \n+ # @return [Bool, String] The + prefix_header_file value.\n+ #\n+ def prefix_header_file\n+ attributes_hash[''prefix_header_file'']\n+ end\n+\n #-------------------------------------------------------------------------#\n + \n public"},{"sha":"8af5bdb6b13a70ed4c430fe4f1166b135174e79a","filename":"lib/cocoapods-core/specification/dsl.rb","status":"modified","additions":15,"deletions":4,"changes":19,"blob_url":"https://github.com/dnkoutso/Core/blob/283ac03a69984faab02c03ad65871966f7581481/lib/cocoapods-core/specification/dsl.rb","raw_url":"https://github.com/dnkoutso/Core/raw/283ac03a69984faab02c03ad65871966f7581481/lib/cocoapods-core/specification/dsl.rb","contents_url":"https://api.github.com/repos/dnkoutso/Core/contents/lib/cocoapods-core/specification/dsl.rb?ref=283ac03a69984faab02c03ad65871966f7581481","patch":"@@ + -855,20 +855,31 @@ def dependency(*args)\n #\n # A path to a + prefix header file to inject in the prefix header of the\n # pod project.\n+ # `false` + indicates that the default CocoaPods prefix header should not\n+ # be + generated.\n+ # `true` is the default and indicates that the default + CocoaPods prefix\n+ # header should be generated.\n #\n # ---\n #\n- # This + attribute is __not recommended__ as Pods should not pollute the\n- # prefix + header of other libraries or of the user project.\n+ # The file path + options is __not recommended__ as Pods should not\n+ # pollute the + prefix header of other libraries or of the user project.\n+ #\n #\n # @example\n #\n # spec.prefix_header_file + = ''iphone/include/prefix.pch''\n #\n- # @param [String] path\n- # The + path to the prefix header file.\n+ # @example\n+ #\n+ # spec.prefix_header_file + = false\n+ #\n+ # @param [Bool, String] path\n+ # The + path to the prefix header file or whether to disable\n+ # prefix_header + generation.\n #\n attribute :prefix_header_file,\n+ :types + => [TrueClass, FalseClass, String],\n :inherited => true\n + \n #------------------#"},{"sha":"5060ab22aed2aab60dccc0c040d15bbdb315ef7f","filename":"spec/specification/dsl_spec.rb","status":"modified","additions":5,"deletions":0,"changes":5,"blob_url":"https://github.com/dnkoutso/Core/blob/283ac03a69984faab02c03ad65871966f7581481/spec/specification/dsl_spec.rb","raw_url":"https://github.com/dnkoutso/Core/raw/283ac03a69984faab02c03ad65871966f7581481/spec/specification/dsl_spec.rb","contents_url":"https://api.github.com/repos/dnkoutso/Core/contents/spec/specification/dsl_spec.rb?ref=283ac03a69984faab02c03ad65871966f7581481","patch":"@@ + -269,6 +269,11 @@ module Pod\n @spec.attributes_hash[''prefix_header_file''].should + == ''iphone/include/prefix.pch''\n end\n \n+ it ''allows to skip + prefix header file generation'' do\n+ @spec.prefix_header_file = false\n+ @spec.attributes_hash[''prefix_header_file''].should + == false\n+ end\n+\n it ''allows to specify a directory to use + for the headers'' do\n @spec.header_dir = ''Three20Core''\n @spec.attributes_hash[''header_dir''].should + == ''Three20Core''"}]}' + http_version: + recorded_at: Fri, 29 Sep 2017 19:50:56 GMT +recorded_with: VCR 3.0.3 diff --git a/spec/fixtures/vcr_cassettes/MasterSource_nofetch.yml b/spec/fixtures/vcr_cassettes/MasterSource_nofetch.yml index 16223b3f2..9358fb564 100644 --- a/spec/fixtures/vcr_cassettes/MasterSource_nofetch.yml +++ b/spec/fixtures/vcr_cassettes/MasterSource_nofetch.yml @@ -71,4 +71,107 @@ http_interactions: string: 570c31dea8def019ec563be2326e053cc937e084 http_version: recorded_at: Wed, 09 Mar 2016 21:44:04 GMT -recorded_with: VCR 2.9.3 +- request: + method: get + uri: https://api.github.com/repos/dnkoutso/Core/commits/master + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - CocoaPods + Accept: + - application/vnd.github.chitauri-preview+sha + If-None-Match: + - '"4287d59a38ebb96af14009a6cb8434ce44480dbf"' + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + response: + status: + code: 200 + message: OK + headers: + Date: + - Fri, 29 Sep 2017 19:50:55 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Server: + - GitHub.com + Status: + - 200 OK + X-Ratelimit-Limit: + - '60' + X-Ratelimit-Remaining: + - '59' + X-Ratelimit-Reset: + - '1506718255' + Cache-Control: + - public, max-age=60, s-maxage=60 + Vary: + - Accept + - Accept-Encoding + Etag: + - W/"23884682188bf1e3e31208d5dc823c0c" + Last-Modified: + - Wed, 27 Sep 2017 15:25:59 GMT + X-Github-Media-Type: + - github.v3; param=chitauri-preview; format=sha + Access-Control-Expose-Headers: + - ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, + X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval + Access-Control-Allow-Origin: + - "*" + Content-Security-Policy: + - default-src 'none' + Strict-Transport-Security: + - max-age=31536000; includeSubdomains; preload + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + X-Xss-Protection: + - 1; mode=block + X-Runtime-Rack: + - '0.107276' + X-Github-Request-Id: + - 85CF:15E9C:217A017:2C28EF0:59CEA41E + body: + encoding: ASCII-8BIT + string: '{"sha":"283ac03a69984faab02c03ad65871966f7581481","commit":{"author":{"name":"Dimitris + Koutsogiorgas","email":"dnkoutso@gmail.com","date":"2017-09-27T15:25:59Z"},"committer":{"name":"GitHub","email":"noreply@github.com","date":"2017-09-27T15:25:59Z"},"message":"Merge + pull request #412 from paulb777/skip-pch2\n\nUpdate comments/docs to indicate + :skip will skip pch generation","tree":{"sha":"d682ef63ea8822fd497bf5afe61db3e6631beca8","url":"https://api.github.com/repos/dnkoutso/Core/git/trees/d682ef63ea8822fd497bf5afe61db3e6631beca8"},"url":"https://api.github.com/repos/dnkoutso/Core/git/commits/283ac03a69984faab02c03ad65871966f7581481","comment_count":0},"url":"https://api.github.com/repos/dnkoutso/Core/commits/283ac03a69984faab02c03ad65871966f7581481","html_url":"https://github.com/dnkoutso/Core/commit/283ac03a69984faab02c03ad65871966f7581481","comments_url":"https://api.github.com/repos/dnkoutso/Core/commits/283ac03a69984faab02c03ad65871966f7581481/comments","author":{"login":"dnkoutso","id":310370,"avatar_url":"https://avatars2.githubusercontent.com/u/310370?v=4","gravatar_id":"","url":"https://api.github.com/users/dnkoutso","html_url":"https://github.com/dnkoutso","followers_url":"https://api.github.com/users/dnkoutso/followers","following_url":"https://api.github.com/users/dnkoutso/following{/other_user}","gists_url":"https://api.github.com/users/dnkoutso/gists{/gist_id}","starred_url":"https://api.github.com/users/dnkoutso/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dnkoutso/subscriptions","organizations_url":"https://api.github.com/users/dnkoutso/orgs","repos_url":"https://api.github.com/users/dnkoutso/repos","events_url":"https://api.github.com/users/dnkoutso/events{/privacy}","received_events_url":"https://api.github.com/users/dnkoutso/received_events","type":"User","site_admin":false},"committer":{"login":"web-flow","id":19864447,"avatar_url":"https://avatars3.githubusercontent.com/u/19864447?v=4","gravatar_id":"","url":"https://api.github.com/users/web-flow","html_url":"https://github.com/web-flow","followers_url":"https://api.github.com/users/web-flow/followers","following_url":"https://api.github.com/users/web-flow/following{/other_user}","gists_url":"https://api.github.com/users/web-flow/gists{/gist_id}","starred_url":"https://api.github.com/users/web-flow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/web-flow/subscriptions","organizations_url":"https://api.github.com/users/web-flow/orgs","repos_url":"https://api.github.com/users/web-flow/repos","events_url":"https://api.github.com/users/web-flow/events{/privacy}","received_events_url":"https://api.github.com/users/web-flow/received_events","type":"User","site_admin":false},"parents":[{"sha":"811811b839932dd5aeb02dc90dfb55db89c6bedd","url":"https://api.github.com/repos/dnkoutso/Core/commits/811811b839932dd5aeb02dc90dfb55db89c6bedd","html_url":"https://github.com/dnkoutso/Core/commit/811811b839932dd5aeb02dc90dfb55db89c6bedd"},{"sha":"37b3a48e8b125c318f4c49ca2430cd51f9b632ea","url":"https://api.github.com/repos/dnkoutso/Core/commits/37b3a48e8b125c318f4c49ca2430cd51f9b632ea","html_url":"https://github.com/dnkoutso/Core/commit/37b3a48e8b125c318f4c49ca2430cd51f9b632ea"}],"stats":{"total":34,"additions":29,"deletions":5},"files":[{"sha":"55c3b453ac99aabeb2b9949ad723658b071dfc5f","filename":"CHANGELOG.md","status":"modified","additions":3,"deletions":1,"changes":4,"blob_url":"https://github.com/dnkoutso/Core/blob/283ac03a69984faab02c03ad65871966f7581481/CHANGELOG.md","raw_url":"https://github.com/dnkoutso/Core/raw/283ac03a69984faab02c03ad65871966f7581481/CHANGELOG.md","contents_url":"https://api.github.com/repos/dnkoutso/Core/contents/CHANGELOG.md?ref=283ac03a69984faab02c03ad65871966f7581481","patch":"@@ + -4,7 +4,9 @@\n \n ##### Enhancements\n \n-* None. \n+* Update commments/docs + to indicate prefix_header=false will skip pch generation \n+ [Paul Beusterien](https://github.com/paulb777)\n+ [#412](https://github.com/CocoaPods/Core/pull/412)\n + \n ##### Bug Fixes\n "},{"sha":"0b264d2948d5cd39c9e08b70f39055dada9ea146","filename":"lib/cocoapods-core/specification.rb","status":"modified","additions":6,"deletions":0,"changes":6,"blob_url":"https://github.com/dnkoutso/Core/blob/283ac03a69984faab02c03ad65871966f7581481/lib/cocoapods-core/specification.rb","raw_url":"https://github.com/dnkoutso/Core/raw/283ac03a69984faab02c03ad65871966f7581481/lib/cocoapods-core/specification.rb","contents_url":"https://api.github.com/repos/dnkoutso/Core/contents/lib/cocoapods-core/specification.rb?ref=283ac03a69984faab02c03ad65871966f7581481","patch":"@@ + -346,6 +346,12 @@ def consumer(platform)\n @consumers[platform] ||= + Consumer.new(self, platform)\n end\n \n+ # @return [Bool, String] The + prefix_header_file value.\n+ #\n+ def prefix_header_file\n+ attributes_hash[''prefix_header_file'']\n+ end\n+\n #-------------------------------------------------------------------------#\n + \n public"},{"sha":"8af5bdb6b13a70ed4c430fe4f1166b135174e79a","filename":"lib/cocoapods-core/specification/dsl.rb","status":"modified","additions":15,"deletions":4,"changes":19,"blob_url":"https://github.com/dnkoutso/Core/blob/283ac03a69984faab02c03ad65871966f7581481/lib/cocoapods-core/specification/dsl.rb","raw_url":"https://github.com/dnkoutso/Core/raw/283ac03a69984faab02c03ad65871966f7581481/lib/cocoapods-core/specification/dsl.rb","contents_url":"https://api.github.com/repos/dnkoutso/Core/contents/lib/cocoapods-core/specification/dsl.rb?ref=283ac03a69984faab02c03ad65871966f7581481","patch":"@@ + -855,20 +855,31 @@ def dependency(*args)\n #\n # A path to a + prefix header file to inject in the prefix header of the\n # pod project.\n+ # `false` + indicates that the default CocoaPods prefix header should not\n+ # be + generated.\n+ # `true` is the default and indicates that the default + CocoaPods prefix\n+ # header should be generated.\n #\n # ---\n #\n- # This + attribute is __not recommended__ as Pods should not pollute the\n- # prefix + header of other libraries or of the user project.\n+ # The file path + options is __not recommended__ as Pods should not\n+ # pollute the + prefix header of other libraries or of the user project.\n+ #\n #\n # @example\n #\n # spec.prefix_header_file + = ''iphone/include/prefix.pch''\n #\n- # @param [String] path\n- # The + path to the prefix header file.\n+ # @example\n+ #\n+ # spec.prefix_header_file + = false\n+ #\n+ # @param [Bool, String] path\n+ # The + path to the prefix header file or whether to disable\n+ # prefix_header + generation.\n #\n attribute :prefix_header_file,\n+ :types + => [TrueClass, FalseClass, String],\n :inherited => true\n + \n #------------------#"},{"sha":"5060ab22aed2aab60dccc0c040d15bbdb315ef7f","filename":"spec/specification/dsl_spec.rb","status":"modified","additions":5,"deletions":0,"changes":5,"blob_url":"https://github.com/dnkoutso/Core/blob/283ac03a69984faab02c03ad65871966f7581481/spec/specification/dsl_spec.rb","raw_url":"https://github.com/dnkoutso/Core/raw/283ac03a69984faab02c03ad65871966f7581481/spec/specification/dsl_spec.rb","contents_url":"https://api.github.com/repos/dnkoutso/Core/contents/spec/specification/dsl_spec.rb?ref=283ac03a69984faab02c03ad65871966f7581481","patch":"@@ + -269,6 +269,11 @@ module Pod\n @spec.attributes_hash[''prefix_header_file''].should + == ''iphone/include/prefix.pch''\n end\n \n+ it ''allows to skip + prefix header file generation'' do\n+ @spec.prefix_header_file = false\n+ @spec.attributes_hash[''prefix_header_file''].should + == false\n+ end\n+\n it ''allows to specify a directory to use + for the headers'' do\n @spec.header_dir = ''Three20Core''\n @spec.attributes_hash[''header_dir''].should + == ''Three20Core''"}]}' + http_version: + recorded_at: Fri, 29 Sep 2017 19:50:56 GMT +recorded_with: VCR 3.0.3 diff --git a/spec/specification/consumer_spec.rb b/spec/specification/consumer_spec.rb index 11982ba3d..2d9835fe0 100644 --- a/spec/specification/consumer_spec.rb +++ b/spec/specification/consumer_spec.rb @@ -279,6 +279,47 @@ module Pod test_consumer = Specification::Consumer.new(test_spec, :ios) test_consumer.requires_app_host?.should.be.true end + + #------------------# + + it 'returns the script phases in correct format when using a string for value' do + @spec.script_phases = { :name => 'Hello World', :script => 'echo "Hello World"' } + @consumer.script_phases.should == [{ :name => 'Hello World', :script => 'echo "Hello World"' }] + end + + it 'returns the script phases in correct format when using a hash for value' do + @spec.script_phases = { :name => 'Hello Ruby World', :script => 'puts "Hello Ruby World"', :shell_path => 'usr/bin/ruby' } + @consumer.script_phases.should == [{ :name => 'Hello Ruby World', :script => 'puts "Hello Ruby World"', :shell_path => 'usr/bin/ruby' }] + end + + it 'returns the script phases in correct format when using both string and hash for values' do + @spec.script_phases = [ + { :name => 'Hello World', :script => 'echo "Hello World"' }, + { :name => 'Hello Ruby World', :script => 'puts "Hello Ruby World"', :shell_path => 'usr/bin/ruby' }, + ] + @consumer.script_phases.should == [ + { :name => 'Hello World', :script => 'echo "Hello World"' }, + { :name => 'Hello Ruby World', :script => 'puts "Hello Ruby World"', :shell_path => 'usr/bin/ruby' }, + ] + end + + it 'handles multi-platform script phases' do + @spec.ios.script_phases = { :name => 'Hello World iOS', :script => 'echo "Hello World iOS"' } + @consumer.script_phases.should == [{ :name => 'Hello World iOS', :script => 'echo "Hello World iOS"' }] + end + + it 'returns both global and multi platform script phases' do + @spec.script_phases = { :name => 'Hello World', :script => 'echo "Hello World"' } + @spec.ios.script_phases = { :name => 'Hello World iOS', :script => 'echo "Hello World iOS"' } + @consumer.script_phases.should == [ + { :name => 'Hello World', :script => 'echo "Hello World"' }, + { :name => 'Hello World iOS', :script => 'echo "Hello World iOS"' }, + ] + end + + it 'returns the empty hash if no script phases have been specified' do + @consumer.script_phases.should == [] + end end #-------------------------------------------------------------------------# diff --git a/spec/specification/dsl_spec.rb b/spec/specification/dsl_spec.rb index 5060ab22a..00d178051 100644 --- a/spec/specification/dsl_spec.rb +++ b/spec/specification/dsl_spec.rb @@ -293,6 +293,16 @@ module Pod @spec.module_map = 'module.modulemap' @spec.attributes_hash['module_map'].should == 'module.modulemap' end + + it 'allows to specify the script phases shipped with the Pod' do + @spec.script_phases = { 'HelloWorld' => 'echo "Hello World"' } + @spec.attributes_hash['script_phases'].should == { 'HelloWorld' => 'echo "Hello World"' } + end + + it 'allows to specify the script phases shipped with the Pod as a hash' do + @spec.script_phases = { 'HelloWorld' => { :script => 'puts "Hello World"', :shell_path => '/usr/bin/ruby' } } + @spec.attributes_hash['script_phases'].should == { 'HelloWorld' => { 'script' => 'puts "Hello World"', 'shell_path' => '/usr/bin/ruby' } } + end end #-----------------------------------------------------------------------------# @@ -464,7 +474,7 @@ module Pod end singularized.map { |attr| attr.name.to_s }.sort.should == %w( authors compiler_flags default_subspecs frameworks libraries - preserve_paths resource_bundles resources screenshots + preserve_paths resource_bundles resources screenshots script_phases vendored_frameworks vendored_libraries weak_frameworks ) end diff --git a/spec/specification/json_spec.rb b/spec/specification/json_spec.rb index 82b59d771..e3beb729a 100644 --- a/spec/specification/json_spec.rb +++ b/spec/specification/json_spec.rb @@ -115,6 +115,18 @@ module Pod }] end + it 'writes script phases' do + @spec.script_phases = [ + { :name => 'Hello World', :script => 'echo "Hello World"' }, + { :name => 'Hello Ruby World', :script => 'puts "Hello Ruby World"', :shell_path => 'usr/bin/ruby' }, + ] + hash = @spec.to_hash + hash['script_phases'].should == [ + { :name => 'Hello World', :script => 'echo "Hello World"' }, + { :name => 'Hello Ruby World', :script => 'puts "Hello Ruby World"', :shell_path => 'usr/bin/ruby' }, + ] + end + it 'writes test type for test subspec' do @spec.test_spec {} hash = @spec.to_hash @@ -158,6 +170,23 @@ module Pod result.test_specs.first.test_type.should.equal :unit end + it 'can load script phases from hash' do + hash = { + 'name' => 'BananaLib', + 'version' => '1.0', + 'script_phases' => [ + { :name => 'Hello World', :script => 'echo "Hello World"' }, + { :name => 'Hello Ruby World', :script => 'puts "Hello World"', :shell_path => '/usr/bin/ruby' }, + ], + } + result = Specification.from_hash(hash) + result.script_phases.count.should.equal 2 + result.script_phases.should == [ + { :name => 'Hello World', :script => 'echo "Hello World"' }, + { :name => 'Hello Ruby World', :script => 'puts "Hello World"', :shell_path => '/usr/bin/ruby' }, + ] + end + it 'can load test specification from 1.3.0 hash format' do hash = { 'name' => 'BananaLib', @@ -187,6 +216,15 @@ module Pod result.test_specs.first.test_type.should.equal :unit end + it 'can load script phases from json' do + json = '{"script_phases": [{"name": "Hello World", "script": "echo \"Hello World\""}]}' + result = Specification.from_json(json) + result.script_phases.count.should.equal 1 + result.script_phases.should == [ + { 'name' => 'Hello World', 'script' => 'echo "Hello World"' } + ] + end + it 'can be safely converted back and forth to a hash' do result = Specification.from_hash(@spec.to_hash) result.should == @spec diff --git a/spec/specification/linter_spec.rb b/spec/specification/linter_spec.rb index e257c6642..e2654777e 100644 --- a/spec/specification/linter_spec.rb +++ b/spec/specification/linter_spec.rb @@ -457,6 +457,19 @@ def result_should_include(*values) #------------------# + it 'checks script phases include the required keys' do + @spec.script_phases = { :name => 'Hello World' } + result_should_include('script_phases', 'Missing required shell script phase options `script` in script phase `Hello World`.') + end + + it 'checks script phases include the required keys' do + @spec.script_phases = { :name => 'Hello World', :script => 'echo "Hello World"', :unknown => 'unknown' } + result_should_include('script_phases', 'Unrecognized options `[:unknown]` in script phase `Hello World`. ' \ + 'Available options are `[:name, :script, :shell_path, :input_files, :output_files, :show_env_vars_in_log]`.') + end + + #------------------# + it 'accepts valid frameworks' do @spec.frameworks = %w(AddressBook Audio-Frameworks) @linter.lint