Commit de33fb21 authored by Kyle Fuller's avatar Kyle Fuller

Merge pull request #2830 from CocoaPods/seg-hooks-plugin-name

[HooksManager] Show the name of the source for each hook that is run in verbose mode
parents 24d8d491 928da4fb
...@@ -4,6 +4,24 @@ To install or update CocoaPods see this [guide](http://docs.cocoapods.org/guides ...@@ -4,6 +4,24 @@ To install or update CocoaPods see this [guide](http://docs.cocoapods.org/guides
To install release candidates run `[sudo] gem install cocoapods --pre` To install release candidates run `[sudo] gem install cocoapods --pre`
## Master
##### Breaking
* Only the hooks specified by usage of the `plugin` directive of the `Podfile`
will be run. Additionally, plugins that depend on hooks will have to update to
specify their 'plugin name' when registering the hooks in order to make it
possible for those hooks to be run.
[Samuel Giddins](https://github.com/segiddins)
[#2640](https://github.com/CocoaPods/CocoaPods/issues/2640)
##### Enhancements
* Show the name of the source for each hook that is run in verbose mode.
[Samuel Giddins](https://github.com/segiddins)
[#2639](https://github.com/CocoaPods/CocoaPods/issues/2639)
## 0.35.0 ## 0.35.0
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.34.4...0.35.0) [CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.34.4...0.35.0)
......
...@@ -14,8 +14,8 @@ gemspec ...@@ -14,8 +14,8 @@ gemspec
gem 'json', '1.7.7' gem 'json', '1.7.7'
group :development do group :development do
#cp_gem 'claide', 'CLAide' cp_gem 'claide', 'CLAide'
cp_gem 'cocoapods-core', 'Core' cp_gem 'cocoapods-core', 'Core', 'seg-podfile-plugins'
cp_gem 'cocoapods-downloader', 'cocoapods-downloader' cp_gem 'cocoapods-downloader', 'cocoapods-downloader'
cp_gem 'cocoapods-plugins', 'cocoapods-plugins' cp_gem 'cocoapods-plugins', 'cocoapods-plugins'
cp_gem 'cocoapods-trunk', 'cocoapods-trunk' cp_gem 'cocoapods-trunk', 'cocoapods-trunk'
......
GIT GIT
remote: https://github.com/CocoaPods/Core.git remote: https://github.com/CocoaPods/CLAide.git
revision: 8d0a5072f64a780dc3f7ef919a66bf82dcfc524d revision: b1eccc296b68b1a432e42ecf0c4b799d8551c75c
branch: master branch: master
specs:
claide (0.7.0)
GIT
remote: https://github.com/CocoaPods/Core.git
revision: e3ab1ae538f10500d5cb0035f458c71d308e68ad
branch: seg-podfile-plugins
specs: specs:
cocoapods-core (0.35.0) cocoapods-core (0.35.0)
activesupport (>= 3.2.15) activesupport (>= 3.2.15)
...@@ -88,7 +95,6 @@ GEM ...@@ -88,7 +95,6 @@ GEM
parser (>= 2.2.0.pre.3, < 3.0) parser (>= 2.2.0.pre.3, < 3.0)
awesome_print (1.2.0) awesome_print (1.2.0)
bacon (1.2.0) bacon (1.2.0)
claide (0.7.0)
clintegracon (0.6.0) clintegracon (0.6.0)
colored (~> 1.2) colored (~> 1.2)
diffy diffy
...@@ -162,6 +168,7 @@ DEPENDENCIES ...@@ -162,6 +168,7 @@ DEPENDENCIES
awesome_print awesome_print
bacon bacon
bundler (~> 1.3) bundler (~> 1.3)
claide!
clintegracon clintegracon
cocoapods! cocoapods!
cocoapods-core! cocoapods-core!
......
...@@ -29,7 +29,7 @@ module Pod ...@@ -29,7 +29,7 @@ module Pod
self.command = 'pod' self.command = 'pod'
self.version = VERSION self.version = VERSION
self.description = 'CocoaPods, the Objective-C library package manager.' self.description = 'CocoaPods, the Objective-C library package manager.'
self.plugin_prefix = 'cocoapods' self.plugin_prefixes = %w(claide cocoapods)
[Install, Update, Outdated, IPC::Podfile, IPC::Repl].each { |c| c.send(:include, ProjectDirectory) } [Install, Update, Outdated, IPC::Podfile, IPC::Repl].each { |c| c.send(:include, ProjectDirectory) }
......
require 'rubygems'
module Pod module Pod
# Provides support for the hook system of CocoaPods. The system is designed # Provides support for the hook system of CocoaPods. The system is designed
# especially for plugins. Interested clients can register to notifications by # especially for plugins. Interested clients can register to notifications by
...@@ -14,27 +16,70 @@ module Pod ...@@ -14,27 +16,70 @@ module Pod
# from CocoaPods 1.0). # from CocoaPods 1.0).
# #
module HooksManager module HooksManager
# Represents a single registered hook.
#
class Hook
# @return [String]
# The name of the hook's notification.
#
attr_reader :plugin_name
# @return [String]
# The name of the plugin the hook came from.
#
attr_reader :name
# @return [Proc]
# The block.
#
attr_reader :block
# @param [String] name @see {#name}.
#
# @param [String] plugin_name @see {#plugin_name}.
#
# @param [Proc] block @see {#block}.
#
def initialize(name, plugin_name, block)
raise ArgumentError, 'Missing name' unless name
raise ArgumentError, 'Missing block' unless block
UI.warn '[Hooks] The use of hooks without specifying a `plugin_name` ' \
'has been deprecated.' unless plugin_name
@name = name
@plugin_name = plugin_name
@block = block
end
end
class << self class << self
# @return [Hash{Symbol => Proc}] The list of the blocks that are # @return [Hash{Symbol => Array<Proc>}] The list of the blocks that are
# registered for each notification name. # registered for each notification name.
# #
attr_reader :registrations attr_reader :registrations
# Registers a block for the hook with the given name. # Registers a block for the hook with the given name.
# #
# @param [Symbol] name # @param [String] plugin_name
# The name of the plugin the hook comes from.
#
# @param [Symbol] hook_name
# The name of the notification. # The name of the notification.
# #
# @param [Proc] block # @param [Proc] block
# The block. # The block.
# #
def register(name, &block) def register(plugin_name, hook_name = nil, &block)
raise ArgumentError, 'Missing name' unless name # TODO: Backwards compatibility with nameless plugins from CP 0.34
raise ArgumentError, 'Missing block' unless block if hook_name.nil?
hook_name = plugin_name
plugin_name = nil
end
@registrations ||= {} @registrations ||= {}
@registrations[name] ||= [] @registrations[hook_name] ||= []
@registrations[name] << block @registrations[hook_name] << Hook.new(hook_name, plugin_name, block)
end end
# Runs all the registered blocks for the hook with the given name. # Runs all the registered blocks for the hook with the given name.
...@@ -45,14 +90,28 @@ module Pod ...@@ -45,14 +90,28 @@ module Pod
# @param [Object] context # @param [Object] context
# The context object which should be passed to the blocks. # The context object which should be passed to the blocks.
# #
def run(name, context) # @param [Hash<String, Hash>] whitelisted_plugins
# The plugins that should be run, in the form of a hash keyed by
# plugin name, where the values are the custom options that should
# be passed to the hook's block if it supports taking a second
# argument.
#
def run(name, context, whitelisted_plugins = nil)
raise ArgumentError, 'Missing name' unless name raise ArgumentError, 'Missing name' unless name
raise ArgumentError, 'Missing options' unless context raise ArgumentError, 'Missing options' unless context
if @registrations if registrations
blocks = @registrations[name] hooks = registrations[name]
if blocks if hooks
blocks.each do |block| UI.message "- Running #{name.to_s.gsub('_', ' ')} hooks" do
hooks.each do |hook|
next if whitelisted_plugins && !whitelisted_plugins.key?(hook.plugin_name)
UI.message "- #{hook.plugin_name || 'unknown plugin'} from " \
"`#{hook.block.source_location.first}`" do
block = hook.block
if block.arity > 1
block.call(context, whitelisted_plugins[hook.plugin_name])
else
block.call(context) block.call(context)
end end
end end
...@@ -60,4 +119,7 @@ module Pod ...@@ -60,4 +119,7 @@ module Pod
end end
end end
end end
end
end
end
end end
...@@ -97,6 +97,7 @@ module Pod ...@@ -97,6 +97,7 @@ module Pod
def prepare def prepare
UI.message 'Preparing' do UI.message 'Preparing' do
sandbox.prepare sandbox.prepare
ensure_plugins_are_installed!
Migrator.migrate(sandbox) Migrator.migrate(sandbox)
end end
end end
...@@ -323,7 +324,23 @@ module Pod ...@@ -323,7 +324,23 @@ module Pod
# #
def run_plugins_post_install_hooks def run_plugins_post_install_hooks
context = HooksContext.generate(sandbox, aggregate_targets) context = HooksContext.generate(sandbox, aggregate_targets)
HooksManager.run(:post_install, context) HooksManager.run(:post_install, context, podfile.plugins)
end
# Ensures that all plugins specified in the {#podfile} are loaded.
#
# @return [void]
#
def ensure_plugins_are_installed!
require 'claide/command/plugin_manager'
loaded_plugins = Command::PluginManager.specifications.map(&:name)
podfile.plugins.keys.each do |plugin|
unless loaded_plugins.include? plugin
raise Informative, "Your Podfile requires that the plugin `#{plugin}` be installed. Please install it and try installation again."
end
end
end end
# Prints a warning for any pods that are deprecated # Prints a warning for any pods that are deprecated
......
...@@ -294,7 +294,7 @@ module Pod ...@@ -294,7 +294,7 @@ module Pod
string string
else else
first_space = ' ' * indent first_space = ' ' * indent
indented = CLAide::Helper.wrap_with_indent(string, indent, 9999) indented = CLAide::Command::Banner::TextWrapper.wrap_with_indent(string, indent, 9999)
first_space + indented first_space + indented
end end
end end
......
...@@ -114,7 +114,7 @@ EOS ...@@ -114,7 +114,7 @@ EOS
end end
def installed_plugins def installed_plugins
CLAide::Command::PluginsHelper.specifications. CLAide::Command::PluginManager.specifications.
reduce({}) { |hash, s| hash.tap { |h| h[s.name] = s.version.to_s } } reduce({}) { |hash, s| hash.tap { |h| h[s.name] = s.version.to_s } }
end end
......
Subproject commit 20622f4674797be935cbf1cd5d7ca5c96390f407 Subproject commit a59b7985755a64a86f83d966ef6c8740067ea10f
...@@ -4,13 +4,17 @@ module Pod ...@@ -4,13 +4,17 @@ module Pod
describe HooksManager do describe HooksManager do
before do before do
@hooks_manager = Pod::HooksManager @hooks_manager = Pod::HooksManager
@hooks_manager.instance_variable_set(:@registrations, nil)
end end
describe 'register' do describe 'register' do
it 'allows to register a block for a notification with a given name' do it 'allows to register a block for a notification with a given name' do
@hooks_manager.register(:post_install) {} @hooks_manager.register('plugin', :post_install) {}
@hooks_manager.registrations[:post_install].count.should == 1 @hooks_manager.registrations[:post_install].count.should == 1
@hooks_manager.registrations[:post_install].first.class.should == Proc hook = @hooks_manager.registrations[:post_install].first
hook.class.should == HooksManager::Hook
hook.name.should == :post_install
hook.plugin_name.should == 'plugin'
end end
it 'raises if no name is given' do it 'raises if no name is given' do
...@@ -24,6 +28,11 @@ module Pod ...@@ -24,6 +28,11 @@ module Pod
@hooks_manager.register(:post_install) @hooks_manager.register(:post_install)
end end
end end
it 'warns if no plugin name is given' do
@hooks_manager.register(:post_install) {}
UI.warnings.should.match /hooks without.*deprecated/
end
end end
describe 'run' do describe 'run' do
...@@ -49,6 +58,26 @@ module Pod ...@@ -49,6 +58,26 @@ module Pod
end end
end end
it 'only runs hooks from the allowed plugins' do
@hooks_manager.register('plugin', :post_install) do |_options|
raise 'Should not be called'
end
should.not.raise do
@hooks_manager.run(:post_install, Object.new, 'plugin2' => {})
end
end
it 'passed along user-specified options when the hook block has arity 2' do
@hooks_manager.register('plugin', :post_install) do |_options, user_options|
user_options['key'].should == 'value'
end
should.not.raise do
@hooks_manager.run(:post_install, Object.new, 'plugin' => {'key' => 'value'})
end
end
it 'raises if no name is given' do it 'raises if no name is given' do
should.raise ArgumentError do should.raise ArgumentError do
@hooks_manager.run(nil, Object.new) {} @hooks_manager.run(nil, Object.new) {}
...@@ -60,6 +89,20 @@ module Pod ...@@ -60,6 +89,20 @@ module Pod
@hooks_manager.run(:post_install, nil) @hooks_manager.run(:post_install, nil)
end end
end end
it 'prints a message in verbose mode when any hooks are run' do
config.verbose = true
@hooks_manager.register(:post_install) {}
@hooks_manager.run(:post_install, Object.new)
UI.output.should.match /- Running post install hooks/
end
it 'prints a message in verbose mode for each hook run' do
config.verbose = true
@hooks_manager.register('plugin', :post_install) {}
@hooks_manager.run(:post_install, Object.new)
UI.output.should.match %r{- plugin from `spec/unit/hooks_manager_spec.rb`}
end
end end
end end
end end
...@@ -53,6 +53,7 @@ module Pod ...@@ -53,6 +53,7 @@ module Pod
@installer.stubs(:generate_pods_project) @installer.stubs(:generate_pods_project)
@installer.stubs(:integrate_user_project) @installer.stubs(:integrate_user_project)
@installer.stubs(:run_plugins_post_install_hooks) @installer.stubs(:run_plugins_post_install_hooks)
@installer.stubs(:ensure_plugins_are_installed!)
@installer.stubs(:perform_post_install_actions) @installer.stubs(:perform_post_install_actions)
end end
...@@ -501,9 +502,36 @@ module Pod ...@@ -501,9 +502,36 @@ module Pod
it 'runs plugins post install hook' do it 'runs plugins post install hook' do
context = stub context = stub
Installer::HooksContext.expects(:generate).returns(context) Installer::HooksContext.expects(:generate).returns(context)
HooksManager.expects(:run).with(:post_install, context) HooksManager.expects(:run).with(:post_install, context, {})
@installer.send(:run_plugins_post_install_hooks) @installer.send(:run_plugins_post_install_hooks)
end end
it 'only runs the podfile-specified post-install hooks' do
context = stub
Installer::HooksContext.expects(:generate).returns(context)
plugins_hash = {'cocoapods-keys' => {'keyring' => 'Eidolon'}}
@installer.podfile.stubs(:plugins).returns(plugins_hash)
HooksManager.expects(:run).with(:post_install, context, plugins_hash)
@installer.send(:run_plugins_post_install_hooks)
end
it 'raises if a podfile-specified plugin is not loaded' do
@installer.podfile.stubs(:plugins).returns('cocoapods-keys' => {})
Command::PluginManager.stubs(:specifications).returns([])
should.raise Informative do
@installer.send(:ensure_plugins_are_installed!)
end.message.should.match /require.*plugin.*`cocoapods-keys`/
end
it 'does not raise if all podfile-specified plugins are loaded' do
@installer.podfile.stubs(:plugins).returns('cocoapods-keys' => {})
spec = stub
spec.stubs(:name).returns('cocoapods-keys')
Command::PluginManager.stubs(:specifications).returns([spec])
should.not.raise do
@installer.send(:ensure_plugins_are_installed!)
end
end
end end
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment