Commit 86c03f40 authored by Eloy Durán's avatar Eloy Durán

First pass at using the extracted CLI lib CLAide.

parent 835a0faf
...@@ -2,6 +2,9 @@ source "http://rubygems.org" ...@@ -2,6 +2,9 @@ source "http://rubygems.org"
gemspec gemspec
# TODO
gem "cli_aide", :git => "git://github.com/alloy/CLAide.git"
group :development do group :development do
gem "xcodeproj", :git => "git://github.com/CocoaPods/Xcodeproj.git" gem "xcodeproj", :git => "git://github.com/CocoaPods/Xcodeproj.git"
gem "mocha", "~> 0.11.4" gem "mocha", "~> 0.11.4"
......
...@@ -6,6 +6,12 @@ GIT ...@@ -6,6 +6,12 @@ GIT
activesupport (~> 3.2.6) activesupport (~> 3.2.6)
colored (~> 1.2) colored (~> 1.2)
GIT
remote: git://github.com/alloy/CLAide.git
revision: 914c38cabeae22c946e96952b32708edf5e5030a
specs:
cli_aide (0.0.1)
GIT GIT
remote: https://github.com/alloy/kicker.git remote: https://github.com/alloy/kicker.git
revision: 6430787ebf8b9305acc2d2f89ae5cf01d2cd5488 revision: 6430787ebf8b9305acc2d2f89ae5cf01d2cd5488
...@@ -87,6 +93,7 @@ PLATFORMS ...@@ -87,6 +93,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
awesome_print awesome_print
bacon bacon
cli_aide!
cocoapods! cocoapods!
github-markup github-markup
kicker! kicker!
......
...@@ -13,4 +13,4 @@ end ...@@ -13,4 +13,4 @@ end
require 'cocoapods' require 'cocoapods'
Pod::Command.run(*ARGV) Pod::Command.run(ARGV)
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
$:.unshift File.expand_path('../lib', __FILE__) $:.unshift File.expand_path('../lib', __FILE__)
require 'cocoapods' require 'cocoapods/version'
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.name = "cocoapods" s.name = "cocoapods"
......
...@@ -11,10 +11,11 @@ unless Gem::Version::Requirement.new('>= 1.4.0').satisfied_by?(Gem::Version.new( ...@@ -11,10 +11,11 @@ unless Gem::Version::Requirement.new('>= 1.4.0').satisfied_by?(Gem::Version.new(
exit 1 exit 1
end end
module Pod require 'cocoapods/version'
VERSION = '0.16.0.rc2' require 'cli_aide'
class PlainInformative < StandardError module Pod
class PlainInformative < CLIAide::Command::Informative
end end
class Informative < PlainInformative class Informative < PlainInformative
...@@ -41,7 +42,7 @@ module Pod ...@@ -41,7 +42,7 @@ module Pod
autoload :Spec, 'cocoapods/specification' autoload :Spec, 'cocoapods/specification'
autoload :Specification, 'cocoapods/specification' autoload :Specification, 'cocoapods/specification'
autoload :UI, 'cocoapods/user_interface' autoload :UI, 'cocoapods/user_interface'
autoload :Version, 'cocoapods/version' autoload :Version, 'cocoapods/version_class'
autoload :Pathname, 'pathname' autoload :Pathname, 'pathname'
autoload :FileList, 'cocoapods/file_list' autoload :FileList, 'cocoapods/file_list'
......
require 'colored' require 'colored'
require 'active_support/core_ext/string/inflections'
require 'active_support/core_ext/string/strip.rb'
module Pod module Pod
class Command class Command < CLIAide::Command
autoload :ErrorReport, 'cocoapods/command/error_report' autoload :ErrorReport, 'cocoapods/command/error_report'
autoload :Install, 'cocoapods/command/install'
autoload :List, 'cocoapods/command/list'
autoload :Linter, 'cocoapods/command/linter' autoload :Linter, 'cocoapods/command/linter'
autoload :Outdated, 'cocoapods/command/outdated'
autoload :Push, 'cocoapods/command/push'
autoload :Repo, 'cocoapods/command/repo'
autoload :Search, 'cocoapods/command/search'
autoload :Setup, 'cocoapods/command/setup'
autoload :Spec, 'cocoapods/command/spec'
autoload :Update, 'cocoapods/command/update'
class Help < Informative
def initialize(command_class, argv, unrecognized_command = nil)
@command_class, @argv, @unrecognized_command = command_class, argv, unrecognized_command
end
def message
message = [
'',
@command_class.banner.gsub(/\$ pod (.*)/, '$ pod \1'.green),
'',
'Options:',
'',
options,
"\n",
].join("\n")
message << "[!] Unrecognized command: `#{@unrecognized_command}'\n".red if @unrecognized_command
message << "[!] Unrecognized argument#{@argv.count > 1 ? 's' : ''}: `#{@argv.join(' - ')}'\n".red unless @argv.empty?
message
end
private self.abstract_command = true
self.description = 'CocoaPods, the Objective-C library package manager.'
def options
options = @command_class.options
keys = options.map(&:first)
key_size = keys.inject(0) { |size, key| key.size > size ? key.size : size }
options.map { |key, desc| " #{key.ljust(key_size)} #{desc}" }.join("\n")
end
end
class ARGV < Array
def options; select { |x| x.to_s[0,1] == '-' }; end
def arguments; self - options; end
def option(name); !!delete(name); end
def shift_argument; (arg = arguments[0]) && delete(arg); end
end
def self.banner
commands = ['install', 'update', 'outdated', 'list', 'push', 'repo', 'search', 'setup', 'spec'].sort
banner = "To see help for the available commands run:\n\n"
banner + commands.map { |cmd| " * $ pod #{cmd.green} --help" }.join("\n")
end
def self.options def self.options
[ [
['--help', 'Show help information'],
['--silent', 'Print nothing'], ['--silent', 'Print nothing'],
['--no-color', 'Print output without color'], ['--no-color', 'Print output without color'],
['--verbose', 'Print more information while working'],
['--version', 'Prints the version of CocoaPods'], ['--version', 'Prints the version of CocoaPods'],
] ].concat(super)
end
def self.run(*argv)
sub_command = parse(*argv)
unless sub_command.is_a?(Setup) || ENV['SKIP_SETUP']
Setup.new(ARGV.new).run_if_needed
end
sub_command.run
UI.puts
rescue Interrupt
puts "[!] Cancelled".red
Config.instance.verbose? ? raise : exit(1)
rescue Exception => e
if e.is_a?(PlainInformative) || ENV['COCOA_PODS_ENV'] == 'development' # also catches Informative
puts e.message
puts *e.backtrace if Config.instance.verbose? || ENV['COCOA_PODS_ENV'] == 'development'
else
puts ErrorReport.report(e)
end
exit 1
end end
def self.parse(*argv) #def self.run(argv)
argv = ARGV.new(argv) #super
if argv.option('--version') #p Config.instance.verbose?
puts VERSION #end
exit!(0)
end #def self.run(*argv)
#sub_command = parse(*argv)
show_help = argv.option('--help') #unless sub_command.is_a?(Setup) || ENV['SKIP_SETUP']
Config.instance.silent = argv.option('--silent') #Setup.new(ARGV.new).run_if_needed
Config.instance.verbose = argv.option('--verbose') #end
#sub_command.run
String.send(:define_method, :colorize) { |string , _| string } if argv.option( '--no-color' ) #UI.puts
command_class = case command_argument = argv.shift_argument #rescue Interrupt
when 'install' then Install #puts "[!] Cancelled".red
when 'list' then List #Config.instance.verbose? ? raise : exit(1)
when 'outdated' then Outdated
when 'push' then Push #rescue Exception => e
when 'repo' then Repo #if e.is_a?(PlainInformative) || ENV['COCOA_PODS_ENV'] == 'development' # also catches Informative
when 'search' then Search #puts e.message
when 'setup' then Setup #puts *e.backtrace if Config.instance.verbose? || ENV['COCOA_PODS_ENV'] == 'development'
when 'spec' then Spec #else
when 'update' then Update #puts ErrorReport.report(e)
end #end
#exit 1
#end
#def self.parse(*argv)
#argv = ARGV.new(argv)
#if argv.option('--version')
#puts VERSION
#exit!(0)
#end
#show_help = argv.option('--help')
#Config.instance.silent = argv.option('--silent')
#Config.instance.verbose = argv.option('--verbose')
#String.send(:define_method, :colorize) { |string , _| string } if argv.option( '--no-color' )
#command_class = case command_argument = argv.shift_argument
#when 'install' then Install
#when 'list' then List
#when 'outdated' then Outdated
#when 'push' then Push
#when 'repo' then Repo
#when 'search' then Search
#when 'setup' then Setup
#when 'spec' then Spec
#when 'update' then Update
#end
#if command_class.nil?
#raise Help.new(self, argv, command_argument)
#elsif show_help
#raise Help.new(command_class, argv)
#else
#command_class.new(argv)
#end
#end
if command_class.nil? def initialize(argv)
raise Help.new(self, argv, command_argument) super
elsif show_help config.verbose = verbose?
raise Help.new(command_class, argv)
else
command_class.new(argv)
end
end end
include Config::Mixin include Config::Mixin
def initialize(argv)
raise Help.new(self.class, argv)
end
private private
def verify_podfile_exists! def verify_podfile_exists!
...@@ -145,3 +102,11 @@ module Pod ...@@ -145,3 +102,11 @@ module Pod
end end
end end
require 'cocoapods/command/list'
require 'cocoapods/command/outdated'
require 'cocoapods/command/project'
require 'cocoapods/command/push'
require 'cocoapods/command/repo'
require 'cocoapods/command/search'
require 'cocoapods/command/setup'
require 'cocoapods/command/spec'
module Pod module Pod
class Command class Command
class List < Command class List < Command
def self.banner self.summary = 'Lists all available pods.'
%{List all pods:
$ pod list
Lists all available pods.
$ pod list new
Lists the pods introduced in the master repository since the last check.}
end
def self.options def self.options
[[ [[
...@@ -24,51 +14,59 @@ module Pod ...@@ -24,51 +14,59 @@ module Pod
executable :git executable :git
def initialize(argv) def initialize(argv)
@update = argv.option('--update') @update = argv.flag?('update')
@stats = argv.option('--stats') @stats = argv.flag?('stats')
@new = argv.option('new') super
super unless argv.empty?
end end
def list_all def run
update_if_necessary!
sets = Source.all_sets sets = Source.all_sets
sets.each { |set| UI.pod(set, :name) } sets.each { |set| UI.pod(set, :name) }
UI.puts "\n#{sets.count} pods were found" UI.puts "\n#{sets.count} pods were found"
end end
def list_new def update_if_necessary!
days = [1,2,3,5,8] if @update && config.verbose?
dates, groups = {}, {} UI.section("\nUpdating Spec Repositories\n".yellow) do
days.each {|d| dates[d] = Time.now - 60 * 60 * 24 * d} Repo.new(ARGV.new(["update"])).run
sets = Source.all_sets end
creation_dates = Pod::Specification::Statistics.instance.creation_dates(sets) end
end
class New < List
self.summary = 'Lists the pods introduced in the master repository since the last check.'
def run
update_if_necessary!
sets.each do |set| days = [1,2,3,5,8]
set_date = creation_dates[set.name] dates, groups = {}, {}
days.each do |d| days.each {|d| dates[d] = Time.now - 60 * 60 * 24 * d}
if set_date >= dates[d] sets = Source.all_sets
groups[d] = [] unless groups[d] creation_dates = Pod::Specification::Statistics.instance.creation_dates(sets)
groups[d] << set
break sets.each do |set|
set_date = creation_dates[set.name]
days.each do |d|
if set_date >= dates[d]
groups[d] = [] unless groups[d]
groups[d] << set
break
end
end end
end end
end days.reverse.each do |d|
days.reverse.each do |d| sets = groups[d]
sets = groups[d] next unless sets
next unless sets UI.section("\nPods added in the last #{"day".pluralize(d)}".yellow) do
UI.section("\nPods added in the last #{"day".pluralize(d)}".yellow) do sorted = sets.sort_by {|s| creation_dates[s.name]}
sorted = sets.sort_by {|s| creation_dates[s.name]} sorted.each { |set| UI.pod(set, (@stats ? :stats : :name)) }
sorted.each { |set| UI.pod(set, (@stats ? :stats : :name)) } end
end end
end end
end end
def run
UI.section("\nUpdating Spec Repositories\n".yellow) do
Repo.new(ARGV.new(["update"])).run
end if @update && config.verbose?
@new ? list_new : list_all
end
end end
end end
end end
module Pod module Pod
class Command class Command
class Outdated < Command class Outdated < Command
def self.banner self.summary = 'Show outdated project dependencies.'
%{Show outdated pods:
$ pod outdated self.description = <<-DESC
Shows the outdated pods in the current Podfile.lock, but only those from
Shows the outdated pods in the current Podfile.lock, but only those from spec repos, not those from local/external sources or `:head' versions.
spec repos, not those from local/external sources or `:head' versions.} DESC
end
def self.options def self.options
[["--no-update", "Skip running `pod repo update` before install"]].concat(super) [["--no-update", "Skip running `pod repo update` before install"]].concat(super)
end end
def initialize(argv) def initialize(argv)
config.skip_repo_update = argv.option('--no-update') config.skip_repo_update = argv.flag?('update', true)
super unless argv.empty? super
end end
def run def run
......
module Pod module Pod
class Command class Command
class Install < Command module Project
def self.banner
%{Installing dependencies of a project:
$ pod install
Downloads all dependencies defined in `Podfile' and creates an Xcode
Pods library project in `./Pods'.
The Xcode project file should be specified in your `Podfile` like this:
xcodeproj 'path/to/XcodeProject'
If no xcodeproj is specified, then a search for an Xcode project will
be made. If more than one Xcode project is found, the command will
raise an error.
This will configure the project to reference the Pods static library,
add a build configuration file, and add a post build script to copy
Pod resources.}
end
def self.options def self.options
[ [
["--no-clean", "Leave SCM dirs like `.git' and `.svn' intact after downloading"], ["--no-clean", "Leave SCM dirs like `.git' and `.svn' intact after downloading"],
...@@ -32,11 +11,11 @@ module Pod ...@@ -32,11 +11,11 @@ module Pod
end end
def initialize(argv) def initialize(argv)
config.clean = !argv.option('--no-clean') config.clean = argv.flag?('clean', true)
config.generate_docs = !argv.option('--no-doc') config.generate_docs = argv.flag?('doc', true)
config.integrate_targets = !argv.option('--no-integrate') config.integrate_targets = argv.flag?('integrate', true)
config.skip_repo_update = argv.option('--no-update') config.skip_repo_update = !argv.flag?('update', true)
super unless argv.empty? super
end end
def run_install_with_update(update) def run_install_with_update(update)
...@@ -45,11 +24,48 @@ module Pod ...@@ -45,11 +24,48 @@ module Pod
resolver.update_mode = update resolver.update_mode = update
Installer.new(resolver).install! Installer.new(resolver).install!
end end
end
class Install < Command
include Project
self.summary = 'Installs dependencies of a project.'
self.description = <<-DESC
Downloads all dependencies defined in `Podfile' and creates an Xcode
Pods library project in `./Pods'.
The Xcode project file should be specified in your `Podfile` like this:
xcodeproj 'path/to/XcodeProject'
If no xcodeproj is specified, then a search for an Xcode project will
be made. If more than one Xcode project is found, the command will
raise an error.
This will configure the project to reference the Pods static library,
add a build configuration file, and add a post build script to copy
Pod resources.
DESC
def run def run
verify_podfile_exists! verify_podfile_exists!
run_install_with_update(false) run_install_with_update(false)
end end
end end
class Update < Command
include Project
self.summary = 'Update outdated project dependencies.'
def run
verify_podfile_exists!
verify_lockfile_exists!
run_install_with_update(true)
end
end
end end
end end
...@@ -4,16 +4,16 @@ require 'active_support/core_ext/string/inflections' ...@@ -4,16 +4,16 @@ require 'active_support/core_ext/string/inflections'
module Pod module Pod
class Command class Command
class Push < Command class Push < Command
def self.banner self.summary = 'Push new specifications to a spec-repo.'
%{Pushing new specifications to a spec-repo:
$ pod push REPO [NAME.podspec] self.description = <<-DESC
Validates NAME.podspec or `*.podspec' in the current working dir, creates
a directory and version folder for the pod in the local copy of
REPO (~/.cocoapods/[REPO]), copies the podspec file into the version directory,
and finally it pushes REPO to its remote.
DESC
Validates NAME.podspec or `*.podspec' in the current working dir, creates self.arguments = 'REPO [NAME.podspec]'
a directory and version folder for the pod in the local copy of
REPO (~/.cocoapods/[REPO]), copies the podspec file into the version directory,
and finally it pushes REPO to its remote.}
end
def self.options def self.options
[ ["--allow-warnings", "Allows to push if warnings are not evitable"], [ ["--allow-warnings", "Allows to push if warnings are not evitable"],
...@@ -24,11 +24,16 @@ module Pod ...@@ -24,11 +24,16 @@ module Pod
executable :git executable :git
def initialize(argv) def initialize(argv)
@allow_warnings = argv.option('--allow-warnings') @allow_warnings = argv.flag?('allow-warnings')
@local_only = argv.option('--local-only') @local_only = argv.flag?('local-only')
@repo = argv.shift_argument @repo = argv.shift_argument
@podspec = argv.shift_argument @podspec = argv.shift_argument
super unless argv.empty? && @repo super
end
def validate_argv!
super
help! "A spec-repo name is required." unless @repo
end end
def run def run
......
...@@ -3,133 +3,158 @@ require 'fileutils' ...@@ -3,133 +3,158 @@ require 'fileutils'
module Pod module Pod
class Command class Command
class Repo < Command class Repo < Command
def self.banner self.abstract_command = true
%{Managing spec-repos:
$ pod repo add NAME URL [BRANCH] # TODO should not show a usage banner!
self.summary = 'Managed spec repos.'
Clones `URL' in the local spec-repos directory at `~/.cocoapods'. The class Add < Repo
remote can later be referred to by `NAME'. self.summary = 'Add a spec repo.'
$ pod repo update [NAME] self.description = <<-DESC
Clones `URL' in the local spec-repos directory at `~/.cocoapods'. The
remote can later be referred to by `NAME'.
DESC
Updates the local clone of the spec-repo `NAME'. If `NAME' is omitted self.arguments = 'NAME URL [BRANCH]'
this will update all spec-repos in `~/.cocoapods'.
$ pod repo lint [NAME | DIRECTORY] def initialize(argv)
@name, @url, @branch = argv.shift_argument, argv.shift_argument, argv.shift_argument
Lints the spec-repo `NAME'. If a directory is provided it is assumed super
to be the root of a repo. Finally, if NAME is not provided this will end
lint all the spec-repos known to CocoaPods.}
end
def self.options
[["--only-errors", "Lint presents only the errors"]].concat(super)
end
extend Executable def validate_argv!
executable :git super
unless @name && @url
help! "Adding a repo needs a `NAME' and a `URL."
end
end
def initialize(argv) def run
case @action = argv.arguments[0] UI.section("Cloning spec repo `#{@name}' from `#{@url}'#{" (branch `#{@branch}')" if @branch}") do
when 'add' config.repos_dir.mkpath
unless (@name = argv.arguments[1]) && (@url = argv.arguments[2]) Dir.chdir(config.repos_dir) { git!("clone '#{@url}' #{@name}") }
raise Informative, "#{@action == 'add' ? 'Adding' : 'Updating the remote of'} a repo needs a `name' and a `url'." Dir.chdir(dir) { git!("checkout #{@branch}") } if @branch
check_versions(dir)
end end
@branch = argv.arguments[3]
when 'update'
@name = argv.arguments[1]
when 'lint'
@name = argv.arguments[1]
@only_errors = argv.option('--only-errors')
else
super
end end
end end
def dir class Update < Repo
config.repos_dir + @name self.summary = 'Update a spec repo.'
end
def run self.description = <<-DESC
send @action.gsub('-', '_') Updates the local clone of the spec-repo `NAME'. If `NAME' is omitted
end this will update all spec-repos in `~/.cocoapods'.
DESC
def add self.arguments = '[NAME]'
UI.section("Cloning spec repo `#{@name}' from `#{@url}'#{" (branch `#{@branch}')" if @branch}") do
config.repos_dir.mkpath def initialize(argv)
Dir.chdir(config.repos_dir) { git!("clone '#{@url}' #{@name}") } @name = argv.shift_argument
Dir.chdir(dir) { git!("checkout #{@branch}") } if @branch super
check_versions(dir)
end end
end
def update def run
dirs = @name ? [dir] : config.repos_dir.children.select {|c| c.directory?} dirs = @name ? [dir] : config.repos_dir.children.select {|c| c.directory?}
dirs.each do |dir| dirs.each do |dir|
UI.section "Updating spec repo `#{dir.basename}'" do UI.section "Updating spec repo `#{dir.basename}'" do
Dir.chdir(dir) do Dir.chdir(dir) do
`git rev-parse >/dev/null 2>&1` `git rev-parse >/dev/null 2>&1`
if $?.exitstatus.zero? if $?.exitstatus.zero?
git!("pull") git!("pull")
else else
UI.message "Not a git repository" UI.message "Not a git repository"
end
end end
end end
check_versions(dir)
end end
check_versions(dir)
end end
end end
def lint class Lint < Repo
if @name self.summary = 'Validates all specs in a repo.'
dirs = File.exists?(@name) ? [ Pathname.new(@name) ] : [ dir ]
else self.description = <<-DESC
dirs = config.repos_dir.children.select {|c| c.directory?} Lints the spec-repo `NAME'. If a directory is provided it is assumed
to be the root of a repo. Finally, if `NAME' is not provided this
will lint all the spec-repos known to CocoaPods.
DESC
self.arguments = '[ NAME | DIRECTORY ]'
def self.options
[["--only-errors", "Lint presents only the errors"]].concat(super)
end
def initialize(argv)
@name = argv.shift_argument
@only_errors = argv.flag?('only-errors')
super
end end
dirs.each do |dir|
check_versions(dir)
UI.puts "\nLinting spec repo `#{dir.realpath.basename}'\n".yellow
podspecs = Pathname.glob( dir + '**/*.podspec')
invalid_count = 0
podspecs.each do |podspec|
linter = Linter.new(podspec)
linter.quick = true
linter.repo_path = dir
linter.lint
case linter.result_type
when :error
invalid_count += 1
color = :red
should_display = true
when :warning
color = :yellow
should_display = !@only_errors
end
if should_display def run
UI.puts " -> ".send(color) << linter.spec_name if @name
print_messages('ERROR', linter.errors) dirs = File.exists?(@name) ? [ Pathname.new(@name) ] : [ dir ]
unless @only_errors else
print_messages('WARN', linter.warnings) dirs = config.repos_dir.children.select {|c| c.directory?}
print_messages('NOTE', linter.notes) end
dirs.each do |dir|
check_versions(dir)
UI.puts "\nLinting spec repo `#{dir.realpath.basename}'\n".yellow
podspecs = Pathname.glob( dir + '**/*.podspec')
invalid_count = 0
podspecs.each do |podspec|
linter = Linter.new(podspec)
linter.quick = true
linter.repo_path = dir
linter.lint
case linter.result_type
when :error
invalid_count += 1
color = :red
should_display = true
when :warning
color = :yellow
should_display = !@only_errors
end
if should_display
UI.puts " -> ".send(color) << linter.spec_name
print_messages('ERROR', linter.errors)
unless @only_errors
print_messages('WARN', linter.warnings)
print_messages('NOTE', linter.notes)
end
UI.puts unless config.silent?
end end
UI.puts unless config.silent?
end end
end UI.puts "Analyzed #{podspecs.count} podspecs files.\n\n" unless config.silent?
UI.puts "Analyzed #{podspecs.count} podspecs files.\n\n" unless config.silent?
if invalid_count == 0 if invalid_count == 0
UI.puts "All the specs passed validation.".green << "\n\n" unless config.silent? UI.puts "All the specs passed validation.".green << "\n\n" unless config.silent?
else else
raise Informative, "#{invalid_count} podspecs failed validation." raise Informative, "#{invalid_count} podspecs failed validation."
end
end end
end end
end end
extend Executable
executable :git
# TODO some of the following methods can probably move to one of the subclasses.
protected
def dir
config.repos_dir + @name
end
def print_messages(type, messages) def print_messages(type, messages)
return if config.silent? return if config.silent?
messages.each {|msg| UI.puts " - #{type.ljust(5)} | #{msg}"} messages.each {|msg| UI.puts " - #{type.ljust(5)} | #{msg}"}
......
module Pod module Pod
class Command class Command
class Search < Command class Search < Command
def self.banner self.summary = 'Search available pods.'
%{Search pods:
$ pod search [QUERY] self.description = <<-DESC
Searches for pods, ignoring case, whose name matches `QUERY'. If the
`--full' option is specified, this will also search in the summary and
description of the pods.
DESC
Searches for pods, ignoring case, whose name matches `QUERY'. If the self.arguments = '[QUERY]'
`--full' option is specified, this will also search in the summary and
description of the pods.}
end
def self.options def self.options
[[ [[
...@@ -19,10 +19,10 @@ module Pod ...@@ -19,10 +19,10 @@ module Pod
end end
def initialize(argv) def initialize(argv)
@full_text_search = argv.option('--full') @full_text_search = argv.flag?('full')
@stats = argv.option('--stats') @stats = argv.flag?('stats')
@query = argv.shift_argument @query = argv.shift_argument
super unless argv.empty? && @query super
end end
def run def run
......
module Pod module Pod
class Command class Command
class Setup < Command class Setup < Command
def self.banner self.summary = 'Setup the CocoaPods environment.'
%{Setup CocoaPods environment:
$ pod setup self.description = <<-DESC
Creates a directory at `~/.cocoapods' which will hold your spec-repos.
This is where it will create a clone of the public `master' spec-repo from:
Creates a directory at `~/.cocoapods' which will hold your spec-repos. https://github.com/CocoaPods/Specs
This is where it will create a clone of the public `master' spec-repo from:
https://github.com/CocoaPods/Specs If the clone already exists, it will ensure that it is up-to-date.
DESC
If the clone already exists, it will ensure that it is up-to-date.}
end
def self.options def self.options
[["--push", "Use this option to enable push access once granted"]].concat(super) [["--push", "Use this option to enable push access once granted"]].concat(super)
...@@ -22,8 +20,8 @@ module Pod ...@@ -22,8 +20,8 @@ module Pod
executable :git executable :git
def initialize(argv) def initialize(argv)
@push_option = argv.option('--push') @push_option = argv.flag?('push')
super unless argv.empty? super
end end
def dir def dir
...@@ -75,7 +73,7 @@ module Pod ...@@ -75,7 +73,7 @@ module Pod
end end
def update_master_repo def update_master_repo
Repo.new(ARGV.new(['update', 'master'])).run Repo::Update.run(['master'])
end end
def set_master_repo_branch def set_master_repo_branch
......
...@@ -5,118 +5,127 @@ require 'active_support/core_ext/string/inflections' ...@@ -5,118 +5,127 @@ require 'active_support/core_ext/string/inflections'
module Pod module Pod
class Command class Command
class Spec < Command class Spec < Command
def self.banner # TODO should not show a usage banner!
%{Managing PodSpec files: self.summary = 'Managing PodSpec files'
$ pod spec create [ NAME | https://github.com/USER/REPO ] class Create < Spec
self.summary = 'Create spec file stub.'
Creates a PodSpec, in the current working dir, called `NAME.podspec'. self.description = <<-DESC
If a GitHub url is passed the spec is prepopulated. Creates a PodSpec, in the current working dir, called `NAME.podspec'.
If a GitHub url is passed the spec is prepopulated.
DESC
$ pod spec lint [ NAME.podspec | DIRECTORY | http://PATH/NAME.podspec, ... ] self.arguments = '[ NAME | https://github.com/USER/REPO ]'
Validates `NAME.podspec'. If a directory is provided it validates def initialize(argv)
the podspec files found, including subfolders. In case @url, @name_or_url = argv.shift_argument, argv.shift_argument
the argument is omitted, it defaults to the current working dir.} super
end end
def self.options
[ ["--quick", "Lint skips checks that would require to download and build the spec"],
["--local", "Lint a podspec against the local files contained in its directory"],
["--only-errors", "Lint validates even if warnings are present"],
["--no-clean", "Lint leaves the build directory intact for inspection"] ].concat(super)
end
def initialize(argv) def validate_argv!
@action = argv.shift_argument
if @action == 'create'
@name_or_url = argv.shift_argument
@url = argv.shift_argument
super if @name_or_url.nil?
super unless argv.empty?
elsif @action == 'lint'
@quick = argv.option('--quick')
@local = argv.option('--local')
@only_errors = argv.option('--only-errors')
@no_clean = argv.option('--no-clean')
@podspecs_paths = argv
else
super super
help! "A pod name or repo URL is required." unless @name_or_url
end end
end
def run def run
send @action if repo_id_match = (@url || @name_or_url).match(/github.com\/([^\/\.]*\/[^\/\.]*)\.*/)
end # This is to make sure Faraday doesn't warn the user about the `system_timer` gem missing.
old_warn, $-w = $-w, nil
begin
require 'faraday'
ensure
$-w = old_warn
end
require 'octokit'
def create repo_id = repo_id_match[1]
if repo_id_match = (@url || @name_or_url).match(/github.com\/([^\/\.]*\/[^\/\.]*)\.*/) data = github_data_for_template(repo_id)
# This is to make sure Faraday doesn't warn the user about the `system_timer` gem missing. data[:name] = @name_or_url if @url
old_warn, $-w = $-w, nil UI.puts semantic_versioning_notice(repo_id, data[:name]) if data[:version] == '0.0.1'
begin else
require 'faraday' data = default_data_for_template(@name_or_url)
ensure
$-w = old_warn
end end
require 'octokit' spec = spec_template(data)
(Pathname.pwd + "#{data[:name]}.podspec").open('w') { |f| f << spec }
repo_id = repo_id_match[1] UI.puts "\nSpecification created at #{data[:name]}.podspec".green
data = github_data_for_template(repo_id)
data[:name] = @name_or_url if @url
UI.puts semantic_versioning_notice(repo_id, data[:name]) if data[:version] == '0.0.1'
else
data = default_data_for_template(@name_or_url)
end end
spec = spec_template(data)
(Pathname.pwd + "#{data[:name]}.podspec").open('w') { |f| f << spec }
UI.puts "\nSpecification created at #{data[:name]}.podspec".green
end end
def lint class Lint < Spec
UI.puts self.summary = 'Validates a spec file.'
invalid_count = 0
podspecs_to_lint.each do |podspec|
linter = Linter.new(podspec)
linter.quick = @quick
linter.local = @local
linter.no_clean = @no_clean
# Show immediatly which pod is being processed.
print " -> #{linter.spec_name}\r" unless config.silent?
$stdout.flush
linter.lint
case linter.result_type
when :error
invalid_count += 1
color = :red
when :warning
invalid_count += 1 unless @only_errors
color = :yellow
else
color = :green
end
# This overwrites the previously printed text self.description = <<-DESC
UI.puts " -> ".send(color) << linter.spec_name unless config.silent? Validates `NAME.podspec'. If a directory is provided it validates
print_messages('ERROR', linter.errors) the podspec files found, including subfolders. In case
print_messages('WARN', linter.warnings) the argument is omitted, it defaults to the current working dir.
print_messages('NOTE', linter.notes) DESC
UI.puts unless config.silent? self.arguments = '[ NAME.podspec | DIRECTORY | http://PATH/NAME.podspec, ... ]'
def self.options
[ ["--quick", "Lint skips checks that would require to download and build the spec"],
["--local", "Lint a podspec against the local files contained in its directory"],
["--only-errors", "Lint validates even if warnings are present"],
["--no-clean", "Lint leaves the build directory intact for inspection"] ].concat(super)
end end
count = podspecs_to_lint.count def initialize(argv)
UI.puts "Analyzed #{count} #{'podspec'.pluralize(count)}.\n\n" unless config.silent? @quick = argv.flag?('quick')
if invalid_count == 0 @local = argv.flag?('local')
lint_passed_message = count == 1 ? "#{podspecs_to_lint.first.basename} passed validation." : "All the specs passed validation." @only_errors = argv.flag?('only-errors')
UI.puts lint_passed_message.green << "\n\n" unless config.silent? @no_clean = argv.flag?('clean', false)
else @podspecs_paths = argv.arguments!
raise Informative, count == 1 ? "The spec did not pass validation." : "#{invalid_count} out of #{count} specs failed validation." super
end
def run
UI.puts
invalid_count = 0
podspecs_to_lint.each do |podspec|
linter = Linter.new(podspec)
linter.quick = @quick
linter.local = @local
linter.no_clean = @no_clean
# Show immediatly which pod is being processed.
print " -> #{linter.spec_name}\r" unless config.silent?
$stdout.flush
linter.lint
case linter.result_type
when :error
invalid_count += 1
color = :red
when :warning
invalid_count += 1 unless @only_errors
color = :yellow
else
color = :green
end
# This overwrites the previously printed text
UI.puts " -> ".send(color) << linter.spec_name unless config.silent?
print_messages('ERROR', linter.errors)
print_messages('WARN', linter.warnings)
print_messages('NOTE', linter.notes)
UI.puts unless config.silent?
end
count = podspecs_to_lint.count
UI.puts "Analyzed #{count} #{'podspec'.pluralize(count)}.\n\n" unless config.silent?
if invalid_count == 0
lint_passed_message = count == 1 ? "#{podspecs_to_lint.first.basename} passed validation." : "All the specs passed validation."
UI.puts lint_passed_message.green << "\n\n" unless config.silent?
else
raise Informative, count == 1 ? "The spec did not pass validation." : "#{invalid_count} out of #{count} specs failed validation."
end
podspecs_tmp_dir.rmtree if podspecs_tmp_dir.exist?
end end
podspecs_tmp_dir.rmtree if podspecs_tmp_dir.exist?
end end
# TODO some of the following methods can probably move to one of the subclasses.
private private
def print_messages(type, messages) def print_messages(type, messages)
......
module Pod
class Command
class Update < Install
def self.banner
%{Updating dependencies of a project:
$ pod update
Updates all dependencies.}
end
def self.options
[["--no-update", "Skip running `pod repo update` before install"]].concat(super)
end
def initialize(argv)
config.skip_repo_update = argv.option('--no-update')
super unless argv.empty?
end
def run
verify_podfile_exists!
verify_lockfile_exists!
run_install_with_update(true)
end
end
end
end
module Pod module Pod
class Version < Gem::Version VERSION = '0.16.0.rc2'
# @returns A Version described by its #to_s method.
#
# @TODO The `from' part of the regexp should be remove before 1.0.0.
#
def self.from_string(string)
if string =~ /HEAD (based on|from) (.*)/
v = Version.new($2)
v.head = true
v
else
Version.new(string)
end
end
attr_accessor :head
alias_method :head?, :head
def to_s
head? ? "HEAD based on #{super}" : super
end
end
end end
module Pod
class Version < Gem::Version
# @returns A Version described by its #to_s method.
#
# @TODO The `from' part of the regexp should be remove before 1.0.0.
#
def self.from_string(string)
if string =~ /HEAD (based on|from) (.*)/
v = Version.new($2)
v.head = true
v
else
Version.new(string)
end
end
attr_accessor :head
alias_method :head?, :head
def to_s
head? ? "HEAD based on #{super}" : super
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