Commit 01bc7727 authored by Fabio Pelosin's avatar Fabio Pelosin

[UserInterface] First attempt to extract UI Logic.

parent e9261526
## 0.15.0 (unreleased)
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/master...b0.15.0)
###### Enhancements
- Support for `header_mappings_dir` attribute in subspecs.
- Refactored UI.
## 0.14.0.rc2 ## 0.14.0.rc2
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.14.0.rc1...0.14.0.rc2) [CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.14.0.rc1...0.14.0.rc2)
......
...@@ -41,6 +41,7 @@ module Pod ...@@ -41,6 +41,7 @@ module Pod
autoload :Source, 'cocoapods/source' autoload :Source, 'cocoapods/source'
autoload :Spec, 'cocoapods/specification' autoload :Spec, 'cocoapods/specification'
autoload :Specification, 'cocoapods/specification' autoload :Specification, 'cocoapods/specification'
autoload :UserInterface, 'cocoapods/user_interface'
autoload :Version, 'cocoapods/version' autoload :Version, 'cocoapods/version'
autoload :Pathname, 'pathname' autoload :Pathname, 'pathname'
......
...@@ -7,14 +7,15 @@ module Pod ...@@ -7,14 +7,15 @@ module Pod
class Downloader class Downloader
class Git < Downloader class Git < Downloader
include Config::Mixin include Config::Mixin
include UserInterface::Mixin
executable :git executable :git
MAX_CACHE_SIZE = 500 MAX_CACHE_SIZE = 500
def download def download
create_cache unless cache_exist? create_cache unless cache_exist?
puts '-> Cloning git repo' if config.verbose? ui_title(' > Cloning git repo', '', 3) do
if options[:tag] if options[:tag]
download_tag download_tag
elsif options[:branch] elsif options[:branch]
...@@ -24,13 +25,13 @@ module Pod ...@@ -24,13 +25,13 @@ module Pod
else else
download_head download_head
end end
Dir.chdir(target_path) { git! "submodule update --init" } if options[:submodules] Dir.chdir(target_path) { git! "submodule update --init" } if options[:submodules]
end
prune_cache prune_cache
end end
def create_cache def create_cache
puts "-> Creating cache git repo (#{cache_path})" if config.verbose? ui_title " > Creating cache git repo (#{cache_path})"
cache_path.rmtree if cache_path.exist? cache_path.rmtree if cache_path.exist?
cache_path.mkpath cache_path.mkpath
clone(url, cache_path) clone(url, cache_path)
...@@ -42,7 +43,7 @@ module Pod ...@@ -42,7 +43,7 @@ module Pod
repos = Pathname.new(caches_dir).children.select { |c| c.directory? }.sort_by(&:ctime) repos = Pathname.new(caches_dir).children.select { |c| c.directory? }.sort_by(&:ctime)
while caches_size >= MAX_CACHE_SIZE && !repos.empty? while caches_size >= MAX_CACHE_SIZE && !repos.empty?
dir = repos.shift dir = repos.shift
puts '->'.yellow << " Removing git cache for `#{origin_url(dir)}'" if config.verbose? ui_message "#{'->'.yellow} Removing git cache for `#{origin_url(dir)}'"
dir.rmtree dir.rmtree
end end
end end
...@@ -74,7 +75,7 @@ module Pod ...@@ -74,7 +75,7 @@ module Pod
end end
def update_cache def update_cache
puts "-> Updating cache git repo (#{cache_path})" if config.verbose? ui_title " > Updating cache git repo (#{cache_path})"
Dir.chdir(cache_path) do Dir.chdir(cache_path) do
git! "reset --hard HEAD" git! "reset --hard HEAD"
git! "clean -d -x -f" git! "clean -d -x -f"
...@@ -138,7 +139,7 @@ module Pod ...@@ -138,7 +139,7 @@ module Pod
git! "remote add upstream '#{@url}'" # we need to add the original url, not the cache url git! "remote add upstream '#{@url}'" # we need to add the original url, not the cache url
git! "fetch -q upstream" # refresh the branches git! "fetch -q upstream" # refresh the branches
git! "checkout --track -b activated-pod-commit upstream/#{options[:branch]}" # create a new tracking branch git! "checkout --track -b activated-pod-commit upstream/#{options[:branch]}" # create a new tracking branch
puts "Just downloaded and checked out branch: #{options[:branch]} from upstream #{clone_url}" if config.verbose? ui_message("Just downloaded and checked out branch: #{options[:branch]} from upstream #{clone_url}")
end end
end end
......
...@@ -16,10 +16,11 @@ module Pod ...@@ -16,10 +16,11 @@ module Pod
def download def download
@filename = filename_with_type type @filename = filename_with_type type
@download_path = target_path + @filename @download_path = target_path + @filename
ui_title(' > Downloading from HTTP', '', 3) do
download_file @download_path download_file @download_path
extract_with_type @download_path, type extract_with_type @download_path, type
end end
end
def type def type
options[:type] || type_with_url(url) options[:type] || type_with_url(url)
......
...@@ -4,12 +4,14 @@ module Pod ...@@ -4,12 +4,14 @@ module Pod
executable :hg executable :hg
def download def download
ui_title(' > Cloning mercurial repo', '', 3) do
if options[:revision] if options[:revision]
download_revision download_revision
else else
download_head download_head
end end
end end
end
def download_head def download_head
hg! "clone \"#{url}\" \"#{target_path}\"" hg! "clone \"#{url}\" \"#{target_path}\""
......
...@@ -8,12 +8,16 @@ module Pod ...@@ -8,12 +8,16 @@ module Pod
end end
def download def download
ui_title(' > Exporting subversion repo', '', 3) do
svn! %|export "#{reference_url}" "#{target_path}"| svn! %|export "#{reference_url}" "#{target_path}"|
end end
end
def download_head def download_head
ui_title(' > Exporting subversion repo', '', 3) do
svn! %|export "#{trunk_url}" "#{target_path}"| svn! %|export "#{trunk_url}" "#{target_path}"|
end end
end
def reference_url def reference_url
result = url.dup result = url.dup
......
...@@ -2,13 +2,17 @@ require 'open4' ...@@ -2,13 +2,17 @@ require 'open4'
module Pod module Pod
module Executable module Executable
class Indenter < ::Array class Indenter < ::Array
include UserInterface::Mixin
include Config::Mixin
attr_accessor :indent attr_accessor :indent
attr_accessor :io attr_accessor :io
def initialize(io = nil, indent = ' ') def initialize(io = nil)
@io = io @io = io
@indent = indent @indent = ' ' * UserInterface.instance.indentation_level
end end
def <<(value) def <<(value)
...@@ -19,6 +23,7 @@ module Pod ...@@ -19,6 +23,7 @@ module Pod
end end
def executable(name) def executable(name)
include UserInterface::Mixin
bin = `which #{name}`.strip bin = `which #{name}`.strip
base_method = "base_" << name.to_s base_method = "base_" << name.to_s
define_method(base_method) do |command, should_raise| define_method(base_method) do |command, should_raise|
...@@ -27,20 +32,19 @@ module Pod ...@@ -27,20 +32,19 @@ module Pod
end end
full_command = "#{bin} #{command}" full_command = "#{bin} #{command}"
if Config.instance.verbose? if Config.instance.verbose?
puts " $ #{full_command}" ui_message("$ #{full_command}")
stdout, stderr = Indenter.new(STDOUT), Indenter.new(STDERR) stdout, stderr = Indenter.new(STDOUT), Indenter.new(STDERR)
else else
stdout, stderr = Indenter.new, Indenter.new stdout, stderr = Indenter.new, Indenter.new
end end
status = Open4.spawn(full_command, :stdout => stdout, :stderr => stderr, :status => true) status = Open4.spawn(full_command, :stdout => stdout, :stderr => stderr, :status => true)
# TODO not sure that we should be silent in case of a failure.
output = stdout.join("\n") + stderr.join("\n") # TODO will this suffice? output = stdout.join("\n") + stderr.join("\n") # TODO will this suffice?
unless status.success? unless status.success?
if should_raise if should_raise
raise Informative, "#{name} #{command}\n\n#{output}" raise Informative, "#{name} #{command}\n\n#{output}"
else else
puts((Config.instance.verbose? ? ' ' : '') << "[!] Failed: #{full_command}".red) unless Config.instance.silent? ui_message("[!] Failed: #{full_command}".red)
end end
end end
output output
......
...@@ -6,6 +6,7 @@ module Pod ...@@ -6,6 +6,7 @@ module Pod
autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator' autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator'
include Config::Mixin include Config::Mixin
include UserInterface::Mixin
attr_reader :resolver, :sandbox, :lockfile attr_reader :resolver, :sandbox, :lockfile
...@@ -49,13 +50,8 @@ module Pod ...@@ -49,13 +50,8 @@ module Pod
def install_dependencies! def install_dependencies!
pods.sort_by { |pod| pod.top_specification.name.downcase }.each do |pod| pods.sort_by { |pod| pod.top_specification.name.downcase }.each do |pod|
should_install = @resolver.should_install?(pod.top_specification.name) || !pod.exists? should_install = @resolver.should_install?(pod.top_specification.name) || !pod.exists?
unless config.silent?
marker = config.verbose ? "\n-> ".green : ''
puts marker << ( should_install ? "Installing #{pod}".green : "Using #{pod}" )
end
if should_install if should_install
ui_title("Installing #{pod}".green, "-> ".green) do
unless pod.downloaded? unless pod.downloaded?
pod.implode pod.implode
download_pod(pod) download_pod(pod)
...@@ -67,6 +63,9 @@ module Pod ...@@ -67,6 +63,9 @@ module Pod
# pre-downloaded in AbstractExternalSource#specification_from_sandbox. # pre-downloaded in AbstractExternalSource#specification_from_sandbox.
pod.clean! if config.clean? pod.clean! if config.clean?
end end
else
ui_title("Using #{pod}", "-> ".green)
end
end end
end end
...@@ -89,10 +88,10 @@ module Pod ...@@ -89,10 +88,10 @@ module Pod
def generate_docs(pod) def generate_docs(pod)
doc_generator = Generator::Documentation.new(pod) doc_generator = Generator::Documentation.new(pod)
if ( config.generate_docs? && !doc_generator.already_installed? ) if ( config.generate_docs? && !doc_generator.already_installed? )
puts "-> Installing documentation" if config.verbose? ui_title " > Installing documentation"
doc_generator.generate(config.doc_install?) doc_generator.generate(config.doc_install?)
else else
puts "-> Using existing documentation" if config.verbose? ui_title " > Using existing documentation"
end end
end end
...@@ -100,48 +99,47 @@ module Pod ...@@ -100,48 +99,47 @@ module Pod
# #
def remove_deleted_dependencies! def remove_deleted_dependencies!
resolver.removed_pods.each do |pod_name| resolver.removed_pods.each do |pod_name|
marker = config.verbose ? "\n-> ".red : '' ui_title("Removing #{pod_name}", "-> ".red) do
path = sandbox.root + pod_name path = sandbox.root + pod_name
puts marker << "Removing #{pod_name}".red
path.rmtree if path.exist? path.rmtree if path.exist?
end end
end end
end
def install! def install!
@sandbox.prepare_for_install @sandbox.prepare_for_install
ui_title "Resolving dependencies of `#{@podfile.defined_in_file}'" do
print_title "Resolving dependencies of: #{@podfile.defined_in_file}"
specs_by_target specs_by_target
end
print_title "Removing deleted dependencies" unless resolver.removed_pods.empty? ui_title "Removing deleted dependencies" do
remove_deleted_dependencies! remove_deleted_dependencies!
end unless resolver.removed_pods.empty?
print_title "Installing dependencies" ui_title "Installing dependencies" do
install_dependencies! install_dependencies!
print_title("Generating support files\n", false)
target_installers.each do |target_installer|
pods_for_target = pods_by_target[target_installer.target_definition]
target_installer.install!(pods_for_target, @sandbox)
acknowledgements_path = target_installer.target_definition.acknowledgements_path
Generator::Acknowledgements.new(target_installer.target_definition,
pods_for_target).save_as(acknowledgements_path)
generate_dummy_source(target_installer)
end end
puts "- Running post install hooks" if config.verbose? ui_title("Generating support files", '', 2) do
generate_target_support_files
ui_message "- Running post install hooks" do
# Post install hooks run _before_ saving of project, so that they can alter it before saving. # Post install hooks run _before_ saving of project, so that they can alter it before saving.
run_post_install_hooks run_post_install_hooks
end
puts "- Writing Xcode project file to `#{@sandbox.project_path}'" if config.verbose? ui_message "- Writing Xcode project file to `#{@sandbox.project_path}'" do
project.save_as(@sandbox.project_path) project.save_as(@sandbox.project_path)
end
puts "- Writing lockfile in `#{config.project_lockfile}'\n\n" if config.verbose? ui_message "- Writing lockfile in `#{config.project_lockfile}'" do
@lockfile = Lockfile.generate(@podfile, specs_by_target.values.flatten) @lockfile = Lockfile.generate(@podfile, specs_by_target.values.flatten)
@lockfile.write_to_disk(config.project_lockfile) @lockfile.write_to_disk(config.project_lockfile)
end
UserProjectIntegrator.new(@podfile).integrate! if config.integrate_targets? UserProjectIntegrator.new(@podfile).integrate! if config.integrate_targets?
end end
end
def run_post_install_hooks def run_post_install_hooks
# we loop over target installers instead of pods, because we yield the target installer # we loop over target installers instead of pods, because we yield the target installer
...@@ -155,6 +153,17 @@ module Pod ...@@ -155,6 +153,17 @@ module Pod
@podfile.post_install!(self) @podfile.post_install!(self)
end end
def generate_target_support_files
target_installers.each do |target_installer|
pods_for_target = pods_by_target[target_installer.target_definition]
target_installer.install!(pods_for_target, @sandbox)
acknowledgements_path = target_installer.target_definition.acknowledgements_path
Generator::Acknowledgements.new(target_installer.target_definition,
pods_for_target).save_as(acknowledgements_path)
generate_dummy_source(target_installer)
end
end
def generate_dummy_source(target_installer) def generate_dummy_source(target_installer)
class_name_identifier = target_installer.target_definition.label class_name_identifier = target_installer.target_definition.label
dummy_source = Generator::DummySource.new(class_name_identifier) dummy_source = Generator::DummySource.new(class_name_identifier)
...@@ -198,15 +207,5 @@ module Pod ...@@ -198,15 +207,5 @@ module Pod
end end
result result
end end
private
def print_title(title, only_verbose = true)
if config.verbose?
puts "\n" + title.yellow
elsif !config.silent? && !only_verbose
puts title
end
end
end end
end end
...@@ -2,6 +2,7 @@ module Pod ...@@ -2,6 +2,7 @@ module Pod
class Installer class Installer
class TargetInstaller class TargetInstaller
include Config::Mixin include Config::Mixin
include UserInterface::Mixin
attr_reader :podfile, :project, :target_definition, :target attr_reader :podfile, :project, :target_definition, :target
attr_accessor :requires_arc attr_accessor :requires_arc
...@@ -97,21 +98,25 @@ module Pod ...@@ -97,21 +98,25 @@ module Pod
end end
def create_files(pods, sandbox) def create_files(pods, sandbox)
if @podfile.generate_bridge_support?
bridge_support_metadata_path = sandbox.root + @target_definition.bridge_support_name bridge_support_metadata_path = sandbox.root + @target_definition.bridge_support_name
puts "- Generating BridgeSupport metadata file at `#{bridge_support_metadata_path}'" if config.verbose? ui_message "- Generating BridgeSupport metadata file at `#{bridge_support_metadata_path}'" do
bridge_support_generator_for(pods, sandbox).save_as(bridge_support_metadata_path) bridge_support_generator_for(pods, sandbox).save_as(bridge_support_metadata_path)
copy_resources_script_for(pods).resources << @target_definition.bridge_support_name copy_resources_script_for(pods).resources << @target_definition.bridge_support_name
end end if @podfile.generate_bridge_support?
puts "- Generating xcconfig file at `#{sandbox.root + @target_definition.xcconfig_name}'" if config.verbose?
ui_message "- Generating xcconfig file at `#{sandbox.root + @target_definition.xcconfig_name}'" do
xcconfig.save_as(sandbox.root + @target_definition.xcconfig_name) xcconfig.save_as(sandbox.root + @target_definition.xcconfig_name)
@target_definition.xcconfig = xcconfig @target_definition.xcconfig = xcconfig
end
puts "- Generating prefix header at `#{sandbox.root + @target_definition.prefix_header_name}'" if config.verbose? ui_message "- Generating prefix header at `#{sandbox.root + @target_definition.prefix_header_name}'" do
save_prefix_header_as(sandbox.root + @target_definition.prefix_header_name, pods) save_prefix_header_as(sandbox.root + @target_definition.prefix_header_name, pods)
puts "- Generating copy resources script at `#{sandbox.root + @target_definition.copy_resources_script_name}'" if config.verbose? end
ui_message "- Generating copy resources script at `#{sandbox.root + @target_definition.copy_resources_script_name}'" do
copy_resources_script_for(pods).save_as(sandbox.root + @target_definition.copy_resources_script_name) copy_resources_script_for(pods).save_as(sandbox.root + @target_definition.copy_resources_script_name)
end end
end
private private
......
...@@ -3,6 +3,7 @@ require 'colored' ...@@ -3,6 +3,7 @@ require 'colored'
module Pod module Pod
class Resolver class Resolver
include Config::Mixin include Config::Mixin
include UserInterface::Mixin
# @return [Bool] Whether the resolver should find the pods to install or # @return [Bool] Whether the resolver should find the pods to install or
# the pods to update. # the pods to update.
...@@ -66,37 +67,27 @@ module Pod ...@@ -66,37 +67,27 @@ module Pod
@specs_by_target = {} @specs_by_target = {}
@pods_from_external_sources = [] @pods_from_external_sources = []
@pods_to_lock = [] @pods_to_lock = []
@log_indent = 0
if @lockfile if @lockfile
puts "\nFinding added, modified or removed dependencies:".green if config.verbose?
@pods_by_state = @lockfile.detect_changes_with_podfile(podfile) @pods_by_state = @lockfile.detect_changes_with_podfile(podfile)
if config.verbose? ui_title "Finding added, modified or removed dependencies:" do
marks = {:added => "A".green, :changed => "M".yellow, :removed => "R".red, :unchanged => "-" }
@pods_by_state.each do |symbol, pod_names| @pods_by_state.each do |symbol, pod_names|
case symbol
when :added
mark = "A".green
when :changed
mark = "M".yellow
when :removed
mark = "R".red
when :unchanged
mark = "-"
end
pod_names.each do |pod_name| pod_names.each do |pod_name|
puts " #{mark} " << pod_name ui_message("#{marks[symbol]} #{pod_name}", '',2)
end
end end
end end
end if config.verbose?
@pods_to_lock = (lockfile.pods_names - @pods_by_state[:added] - @pods_by_state[:changed] - @pods_by_state[:removed]).uniq @pods_to_lock = (lockfile.pods_names - @pods_by_state[:added] - @pods_by_state[:changed] - @pods_by_state[:removed]).uniq
end end
@podfile.target_definitions.values.each do |target_definition| @podfile.target_definitions.values.each do |target_definition|
puts "\nResolving dependencies for target `#{target_definition.name}' (#{target_definition.platform}):".green if config.verbose? ui_title "Resolving dependencies for target `#{target_definition.name}' (#{target_definition.platform}):" do
@loaded_specs = [] @loaded_specs = []
find_dependency_specs(@podfile, target_definition.dependencies, target_definition) find_dependency_specs(@podfile, target_definition.dependencies, target_definition)
@specs_by_target[target_definition] = @cached_specs.values_at(*@loaded_specs).sort_by(&:name) @specs_by_target[target_definition] = @cached_specs.values_at(*@loaded_specs).sort_by(&:name)
end end
end
@cached_specs.values.sort_by(&:name) @cached_specs.values.sort_by(&:name)
@specs_by_target @specs_by_target
...@@ -187,14 +178,12 @@ module Pod ...@@ -187,14 +178,12 @@ module Pod
# @return [void] # @return [void]
# #
def find_dependency_specs(dependent_specification, dependencies, target_definition) def find_dependency_specs(dependent_specification, dependencies, target_definition)
@log_indent += 1
dependencies.each do |dependency| dependencies.each do |dependency|
# Replace the dependency with a more specific one if the pod is already installed. # Replace the dependency with a more specific one if the pod is already installed.
if !update_mode && @pods_to_lock.include?(dependency.name) if !update_mode && @pods_to_lock.include?(dependency.name)
dependency = lockfile.dependency_for_installed_pod_named(dependency.name) dependency = lockfile.dependency_for_installed_pod_named(dependency.name)
end end
ui_message("- #{dependency}", '', 2) do
puts ' ' * @log_indent + "- #{dependency}" if config.verbose?
set = find_cached_set(dependency, target_definition.platform) set = find_cached_set(dependency, target_definition.platform)
set.required_by(dependency, dependent_specification.to_s) set.required_by(dependency, dependent_specification.to_s)
...@@ -212,7 +201,7 @@ module Pod ...@@ -212,7 +201,7 @@ module Pod
end end
validate_platform(spec || @cached_specs[dependency.name], target_definition) validate_platform(spec || @cached_specs[dependency.name], target_definition)
end end
@log_indent -= 1 end
end end
# Ensures that a spec is compatible with platform of a target. # Ensures that a spec is compatible with platform of a target.
......
module Pod
class UserInterface
include Config::Mixin
def self.instance
@instance ||= new
end
def initialize
@indentation_level = 0
@title_level = 0
@title_colors = %w|yellow green|
end
attr_accessor :indentation_level, :title_level
def title(title, verbose_prefix = '')
if config.verbose?
title = "\n#{title}" if @title_level < 2
title = verbose_prefix + title if config.verbose?
if (color = @title_colors[@title_level])
title = title.send(color)
end
puts "#{title}"
elsif title_level < 2
puts title
end
end
def message(message, verbose_prefix = '')
message = verbose_prefix + message if config.verbose?
puts_indented message if config.verbose?
end
def puts(message)
super(message) unless config.silent?
end
def puts_indented(message)
indented = wrap_string(message, " " * indentation_level)
puts(indented)
end
# adapted from http://blog.macromates.com/2006/wrapping-text-with-regular-expressions/
def wrap_string(txt, indent)
width = `stty size`.split(' ')[1].to_i - indent.length
txt.strip.gsub(/(.{1,#{width}})( +|$)\n?|(.{#{width}})/, indent + "\\1\\3\n")
end
module Mixin
def ui_title(title, verbose_prefix = '', relative_indentation = 0)
UserInterface.instance.title(title)
UserInterface.instance.indentation_level += relative_indentation
UserInterface.instance.title_level += 1
yield if block_given?
UserInterface.instance.indentation_level -= relative_indentation
UserInterface.instance.title_level -= 1
end
def ui_message(message, verbose_prefix = '', relative_indentation = 0)
UserInterface.instance.indentation_level += relative_indentation
UserInterface.instance.message(message)
yield if block_given?
UserInterface.instance.indentation_level -= relative_indentation
end
def ui_verbose(message)
UserInterface.instance.puts(message)
end
# def ui_progress_start(count)
# end
# def ui_progress_increase(message = nil, ammount = 1)
# end
# def ui_progress_complete()
# 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