Commit 11616843 authored by Fabio Pelosin's avatar Fabio Pelosin

Merge pull request #219 from CocoaPods/pod-push

Pod push, pod spec lint, and minor changes
parents f9e77af9 7f7aa877
......@@ -38,7 +38,6 @@ GEM
faraday_middleware (~> 0.8)
hashie (~> 1.2)
multi_json (~> 1.0)
open4 (1.3.0)
pry (0.9.8.4)
coderay (~> 1.0.5)
method_source (~> 0.7.1)
......@@ -64,7 +63,6 @@ DEPENDENCIES
kicker
mocha-on-bacon
octokit
open4
pry
rake
rb-fsevent
......
......@@ -29,7 +29,6 @@ Gem::Specification.new do |s|
"you are upgrading, first run: $ pod setup"
s.add_runtime_dependency 'xcodeproj', '~> 0.1.0'
s.add_runtime_dependency 'popen4', '~> 0.1.2'
s.add_runtime_dependency 'colored', '~> 1.2'
s.add_runtime_dependency 'escape', '~> 0.0.4'
s.add_development_dependency 'bacon', '~> 1.1'
......
......@@ -39,3 +39,7 @@ class Pathname
end
end
if ENV['COCOA_PODS_ENV'] == 'development'
require 'pry'
require 'awesome_print'
end
......@@ -6,6 +6,7 @@ module Pod
autoload :Install, 'cocoapods/command/install'
autoload :List, 'cocoapods/command/list'
autoload :Presenter, 'cocoapods/command/presenter'
autoload :Push, 'cocoapods/command/push'
autoload :Repo, 'cocoapods/command/repo'
autoload :Search, 'cocoapods/command/search'
autoload :Setup, 'cocoapods/command/setup'
......@@ -18,12 +19,13 @@ module Pod
def message
[
@command_class.banner,
'',
'Options',
'-------',
@command_class.banner.gsub(/\$ pod (.*)/, '$ pod \1'.green),
'',
options
'Options:',
'',
options,
"\n",
].join("\n")
end
......@@ -45,14 +47,10 @@ module Pod
end
def self.banner
"To see help for the available commands run:\n" \
"\n" \
" * $ pod setup --help\n" \
" * $ pod search --help\n" \
" * $ pod list --help\n" \
" * $ pod install --help\n" \
" * $ pod repo --help\n" \
" * $ pod spec --help"
commands = ['install', 'list', 'push', 'repo', 'search', 'setup', 'spec'].sort
banner = "\nTo see help for the available commands run:\n\n"
commands.each {|cmd| banner << " * $ pod #{cmd.green} --help\n"}
banner
end
def self.options
......@@ -97,6 +95,7 @@ module Pod
when 'list' then List
when 'setup' then Setup
when 'spec' then Spec
when 'push' then Push
end
if show_help || command_class.nil?
......
......@@ -2,7 +2,7 @@ module Pod
class Command
class Presenter
def self.options
" --stats Show additional stats (like GitHub watchers and forks)\n"
[["--stats", "Show additional stats (like GitHub watchers and forks)"]]
end
autoload :CocoaPod, 'cocoapods/command/presenter/cocoa_pod'
......@@ -43,18 +43,15 @@ module Pod
txt.strip.gsub(/(.{1,#{col}})( +|$)\n?|(.{#{col}})/, indent + "\\1\\3\n")
end
def detail(title, value, preferred_indentation = 8)
# 8 is the length of Homepage
def detail(title, value)
return '' if !value
number_of_spaces = ((preferred_indentation - title.length) > 0) ? (preferred_indentation - title.length) : 0
spaces = ' ' * number_of_spaces
''.tap do |t|
t << " - #{title}:"
t << " - #{title}:".ljust(16)
if value.class == Array
separator = "\n - "
t << separator + value.join(separator)
t << separator << value.join(separator)
else
t << " #{spaces + value.to_s}\n"
t << value.to_s << "\n"
end
end
end
......
require 'fileutils'
module Pod
class Command
class Push < Command
def self.banner
%{Pushing new specifications to a spec-repo:
$ pod push [REPO]
Validates `*.podspec' in the current working dir, updates
the local copy of the repository named REPO, adds specifications
to REPO, and finally it pushes REPO to its remote.}
end
def self.options
[["--allow-warnings", "Allows to push if warnings are not evitable"]].concat(super)
end
extend Executable
executable :git
def initialize(argv)
@allow_warnings = argv.option('--allow-warnings')
@repo = argv.shift_argument
super unless argv.empty? && @repo
end
def run
validate_podspec_files
check_repo_status
update_repo
add_specs_to_repo
push_repo
end
private
def update_repo
puts "Updating the `#{@repo}' repo\n".yellow unless config.silent
# show the output of git even if not verbose
Dir.chdir(repo_dir) { puts `git pull 2>&1` }
end
def push_repo
puts "\nPushing the `#{@repo}' repo\n".yellow unless config.silent
Dir.chdir(repo_dir) { puts `git push 2>&1` }
end
def repo_dir
dir = config.repos_dir + @repo
raise Informative, "[!] `#{@repo}' repo not found".red unless dir.exist?
dir
end
def check_repo_status
# TODO: add specs for staged and unstaged files (tested manually)
clean = Dir.chdir(repo_dir) { `git status --porcelain 2>&1` } == ''
raise Informative, "[!] `#{@repo}' repo not clean".red unless clean
end
def podspec_files
files = Pathname.glob("*.podspec")
raise Informative, "[!] Couldn't find .podspec file in current directory".red if files.empty?
files
end
def validate_podspec_files
puts "\nValidating specs".yellow unless config.silent
lint_argv = ["lint"]
lint_argv << "--only-errors" if @allow_warnings
lint_argv << "--silent" if config.silent
all_valid = Spec.new(ARGV.new(lint_argv)).run
end
def add_specs_to_repo
puts "\nAdding the specs to the #{@repo} repo\n".yellow unless config.silent
podspec_files.each do |spec_file|
spec = Pod::Specification.from_file(spec_file)
output_path = File.join(repo_dir, spec.name, spec.version.to_s)
if Pathname.new(output_path).exist?
message = "[Fix] #{spec}"
elsif Pathname.new(File.join(repo_dir, spec.name)).exist?
message = "[Update] #{spec}"
else
message = "[Add] #{spec}"
end
puts " - #{message}" unless config.silent
FileUtils.mkdir_p(output_path)
FileUtils.cp(Pathname.new(spec.name+'.podspec'), output_path)
Dir.chdir(repo_dir) do
git("add #{spec.name}")
git("commit -m '#{message}'")
end
end
end
end
end
end
# encoding: utf-8
require 'net/https'
require 'uri'
require 'octokit'
require 'json'
module Pod
class Command
class Spec < Command
def self.banner
%{Managing PodSpec files:
$ pod spec create [NAME]
$ pod spec create [https://github.com/USER/REPO]
$ pod spec create [ NAME | https://github.com/USER/REPO ]
Creates a PodSpec, in the current working dir, called `NAME.podspec'.
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.
$ pod spec lint [ NAME.podspec | REPO ]
$ pod spec lint [NAME.podspec]
Validates `NAME.podspec'. In case `NAME.podspec' is omitted, it defaults
to `*.podspec' in the current working dir. If the name of a repo is
provided it validates all its specs.}
end
Validates `NAME.podspec'. In case `NAME.podspec' is omitted, it defaults
to `*.podspec' in the current working dir.}
def self.options
[ ["--quick", "Lint skips checks that would require to donwload and build the spec"],
["--only-errors", "Lint validates even if warnings are present"] ].concat(super)
end
def initialize(argv)
args = argv.arguments
unless (args[0] == 'create' && args.size == 2) ||
(args[0] == 'lint' && args.size <= 2)
@action = argv.shift_argument
if @action == 'create'
@name_or_url = argv.shift_argument
@url = argv.shift_argument
super if @name_or_url.nil?
elsif @action == 'lint'
@quick = argv.option('--quick')
@only_errors = argv.option('--only-errors')
@repo_or_podspec = argv.shift_argument unless argv.empty?
super unless argv.size <= 1
else
super
end
@action, @name_or_url = args.first(2)
super unless argv.empty?
end
def run
......@@ -37,64 +46,265 @@ module Pod
end
def create
if repo_id = @name_or_url[/github.com\/([^\/\.]*\/[^\/\.]*)\.*/, 1]
if repo_id_match = (@url || @name_or_url).match(/github.com\/([^\/\.]*\/[^\/\.]*)\.*/)
require 'octokit'
repo_id = repo_id_match[1]
data = github_data_for_template(repo_id)
data[:name] = @name_or_url if @url
puts semantic_versioning_notice(repo_id, data[:name]) if data[:version] == '0.0.1'
else
data = default_data_for_template(@name_or_url)
end
spec = spec_template(data)
(Pathname.pwd + "#{data[:name]}.podspec").open('w') { |f| f << spec }
puts "\nSpecification created at #{data[:name]}.podspec\n".green
puts "\nSpecification created at #{data[:name]}.podspec".green
end
def lint
name = @name_or_url
file = name ? Pathname.new(name) : Pathname.pwd.glob('*.podspec').first
spec = Specification.from_file(file)
puts "\nThe #{spec.name} specification contains all the required attributes.".green if spec.validate!
warnings = []
warnings << 'The name of the specification should match the name of the podspec file' unless path_matches_name?(file, spec)
warnings << 'Missing license[:type]' unless spec.license && spec.license[:type]
warnings << 'Missing license[:file] or [:text]' unless spec.license && (spec.license[:file] || spec.license[:text])
warnings << "Github repositories should end in `.git'" if spec.source[:git] =~ /github.com/ && spec.source[:git] !~ /.*\.git/
warnings << "Github repositories should end in `.git'" if spec.source[:git] =~ /github.com/ && spec.source[:git] !~ /.*\.git/
warnings << "The description should end with a dot" if spec.description && spec.description !~ /.*\./
warnings << "The summary should end with a dot" if spec.summary !~ /.*\./
unless warnings.empty?
puts "\n[!] The #{spec.name} specification raised the following warnings".yellow
warnings.each { |warn| puts ' - '+ warn }
if (is_repo = repo_with_name_exist(@repo_or_podspec))
files = (config.repos_dir + @repo_or_podspec).glob('**/*.podspec')
else
if @repo_or_podspec
files = [Pathname.new(@repo_or_podspec)]
raise Informative, "[!] Unable to find a spec named #{@repo_or_podspec}".red unless files[0].exist?
else
files = Pathname.pwd.glob('*.podspec')
raise Informative, "[!] No specs found in the current directory".red if files.empty?
end
end
puts
all_valid = lint_specs_files(files, is_repo)
if all_valid
puts (files.count == 1 ? "#{@repo_or_podspec} passed validation" : "All the specs passed validation").green
else
message = (files.count == 1 ? "[!] The spec did not pass validation" : "[!] Not all specs passed validation").red
raise Informative, message
end
end
private
def path_matches_name?(path, spec)
(path.dirname + "#{spec.name}.podspec").to_s == @name_or_url
def repo_with_name_exist(name)
name && (config.repos_dir + name).exist?
end
def suggested_ref_and_version(repo)
tags = Octokit.tags(:username => repo['owner']['login'], :repo => repo['name']).map {|tag| tag["name"]}
versions_tags = {}
tags.each do |tag|
clean_tag = tag.gsub(/^v(er)? ?/,'')
versions_tags[Gem::Version.new(clean_tag)] = tag if Gem::Version.correct?(clean_tag)
# Takes an array of podspec files and lints them all
#
# It returns true if **all** the files passed validation
#
def lint_specs_files(files, is_repo)
all_valid = true
files.each do |file|
file = file.realpath
file_spec = Specification.from_file(file)
specs = file_spec.recursive_subspecs.any? ? file_spec.recursive_subspecs : [file_spec]
specs.each do |spec|
# Show immediatly which pod is being processed.
# This line will be overwritten once the result is known
print " -> #{spec}\r" unless config.silent? || is_repo
$stdout.flush
# If the spec doesn't validate it raises and informative
spec.validate!
warnings = warnings_for_spec(spec, file, is_repo)
deprecations = deprecation_notices_for_spec(spec, file, is_repo)
if is_repo || @quick
build_messages, file_patterns_errors = [], []
else
set_up_lint_environment
build_messages = build_errors_for_spec(spec, file, is_repo)
file_patterns_errors = file_patterns_errors_for_spec(spec, file, is_repo)
tear_down_lint_environment
end
build_errors = build_messages.select {|msg| msg.include?('error')}
build_warnings = build_messages - build_errors
# Errors compromise the functionality of a spec, warnings can be ignored
all = warnings + deprecations + build_messages + file_patterns_errors
errors = file_patterns_errors + build_errors
warnings = all - errors
if @only_errors
all_valid = false unless errors.empty?
else
# avoid to fail validation for xcode warnings
all_valid = false unless (all - build_warnings).empty?
end
clean_duplicate_platfrom_messages(errors)
clean_duplicate_platfrom_messages(warnings)
# This overwrites the previously printed text
unless config.silent?
if errors.empty? && warnings.empty?
puts " -> ".green + "#{spec} passed validation" unless is_repo
elsif errors.empty?
puts " -> ".yellow + spec.to_s
else
puts " -> ".red + spec.to_s
end
end
warnings.each {|msg| puts " - WARN | #{msg}"} unless config.silent?
errors.each {|msg| puts " - ERROR | #{msg}"} unless config.silent?
puts unless config.silent? || ( is_repo && all.flatten.empty? )
end
end
version = versions_tags.keys.sort.last || '0.0.1'
data = {:version => version}
if version == '0.0.1'
branches = Octokit.branches(:username => repo['owner']['login'], :repo => repo['name'])
master_name = repo['master_branch'] || 'master'
master = branches.select {|branch| branch['name'] == master_name }.first
data[:ref_type] = ':commit'
data[:ref] = master['commit']['sha']
else
data[:ref_type] = ':tag'
data[:ref] = versions_tags[version]
all_valid
end
def tmp_dir
Pathname.new('/tmp/CocoaPods/Lint')
end
def set_up_lint_environment
tmp_dir.mkpath
@original_config = Config.instance.clone
config.project_root = tmp_dir
config.project_pods_root = tmp_dir + 'Pods'
config.silent = !config.verbose
config.integrate_targets = false
config.doc_install = false
end
def tear_down_lint_environment
tmp_dir.rmtree
Config.instance = @original_config
end
def clean_duplicate_platfrom_messages(messages)
duplicate_candiates = messages.select {|l| l.include?("ios: ")}
duplicated = duplicate_candiates.select {|l| messages.include?(l.gsub(/ios: /,'osx: ')) }
duplicated.uniq.each do |l|
clean = l.gsub(/ios: /,'')
messages.insert(messages.index(l), clean)
messages.delete(l)
messages.delete('osx: ' + clean)
end
end
# It checks a spec for minor non fatal defects
#
# It returns a array of messages
#
def warnings_for_spec(spec, file, is_repo)
license = spec.license
source = spec.source
text = file.read
warnings = []
warnings << "The name of the spec should match the name of the file" unless path_matches_name?(file, spec)
warnings << "Missing license[:type]" unless license && license[:type]
warnings << "Github repositories should end in `.git'" if source && source[:git] =~ /github.com/ && source[:git] !~ /.*\.git/
warnings << "The description should end with a dot" if spec.description && spec.description !~ /.*\./
warnings << "The summary should end with a dot" if spec.summary !~ /.*\./
warnings << "Missing license[:file] or [:text]" unless license && (license[:file] || license[:text])
warnings << "Comments must be deleted" if text =~ /^\w*#\n\w*#/ # allow a single line comment as it is generally used in subspecs
warnings
end
def path_matches_name?(file, spec)
spec_name = spec.name.match(/[^\/]*/)[0]
file.basename.to_s == spec_name + '.podspec'
end
# It reads a podspec file and checks for strings corresponding
# to a feature that are or will be deprecated
#
# It returns a array of messages
#
def deprecation_notices_for_spec(spec, file, is_repo)
text = file.read
deprecations = []
deprecations << "`config.ios?' and `config.osx' will be removed in version 0.7" if text. =~ /config\..os?/
deprecations << "Currently there is no known reason to use the `post_install' hook" if text. =~ /post_install/
deprecations
end
# It creates a podfile in memory and builds a library containing
# the pod for all available platfroms with xcodebuild.
#
# It returns a array of messages
#
def build_errors_for_spec(spec, file, is_repo)
messages = []
platform_names(spec).each do |platform_name|
podfile = podfile_from_spec(spec, file, platform_name)
Installer.new(podfile).install!
return messages if `which xcodebuild`.strip.empty?
output = Dir.chdir(config.project_pods_root) { `xcodebuild 2>&1` }
clean_output = process_xcode_build_output(output).map {|l| "#{platform_name}: #{l}"}
messages += clean_output
puts("\n" + output) if config.verbose?
end
messages
end
def podfile_from_spec(spec, file, platform_name)
podfile = Pod::Podfile.new do
platform platform_name
dependency spec.name, :podspec => file.realpath.to_s
end
end
def process_xcode_build_output(output)
output_by_line = output.split("\n")
selected_lines = output_by_line.select do |l|
l.include?('error') && !l.include?('error generated.')\
|| l.include?('warning') && !l.include?('warning generated.')\
|| l.include?('note')
end
# Remove the unnecessary tmp path
selected_lines.map {|l| l.gsub(/\/tmp\/CocoaPods\/Lint\/Pods\//,'')}
end
# It checks that every file pattern specified in a spec yields
# at least one file. It requires the pods to be alredy present
# in the current working directory under Pods/spec.name
#
# It returns a array of messages
#
def file_patterns_errors_for_spec(spec, file, is_repo)
Dir.chdir(config.project_pods_root + spec.name ) do
messages = []
messages += check_spec_files_exists(spec, :source_files)
messages += check_spec_files_exists(spec, :resources)
messages.compact
end
end
def check_spec_files_exists(spec, accessor)
result = []
platform_names(spec).each do |platform_name|
patterns = spec.send(accessor)[platform_name]
unless patterns.empty?
patterns.each do |pattern|
result << "#{platform_name}: [#{accessor} = '#{pattern}'] -> did not match any file" if Pathname.pwd.glob(pattern).empty?
end
end
end
result
end
def platform_names(spec)
spec.platform.name ? [spec.platform.name] : [:ios, :osx]
end
# Templates and github information retrival for spec create
def default_data_for_template(name)
data = {}
data[:name] = name
data[:version] = '0.0.1'
data[:summary] = "A short description of #{name}."
data[:homepage] = "http://EXAMPLE/#{name}"
data[:author_name] = `git config --get user.name`.strip
data[:author_email] = `git config --get user.email`.strip
data[:source_url] = "http://EXAMPLE/#{name}.git"
data[:ref_type] = ':tag'
data[:ref] = '0.0.1'
data
end
......@@ -113,17 +323,25 @@ module Pod
data.merge suggested_ref_and_version(repo)
end
def default_data_for_template(name)
data = {}
data[:name] = name
data[:version] = '0.0.1'
data[:summary] = "A short description of #{name}."
data[:homepage] = "http://EXAMPLE/#{name}"
data[:author_name] = `git config --get user.name`.strip
data[:author_email] = `git config --get user.email`.strip
data[:source_url] = "http://EXAMPLE/#{name}.git"
data[:ref_type] = ':tag'
data[:ref] = '0.0.1'
def suggested_ref_and_version(repo)
tags = Octokit.tags(:username => repo['owner']['login'], :repo => repo['name']).map {|tag| tag["name"]}
versions_tags = {}
tags.each do |tag|
clean_tag = tag.gsub(/^v(er)? ?/,'')
versions_tags[Gem::Version.new(clean_tag)] = tag if Gem::Version.correct?(clean_tag)
end
version = versions_tags.keys.sort.last || '0.0.1'
data = {:version => version}
if version == '0.0.1'
branches = Octokit.branches(:username => repo['owner']['login'], :repo => repo['name'])
master_name = repo['master_branch'] || 'master'
master = branches.select {|branch| branch['name'] == master_name }.first
data[:ref_type] = ':commit'
data[:ref] = master['commit']['sha']
else
data[:ref_type] = ':tag'
data[:ref] = versions_tags[version]
end
data
end
......@@ -241,7 +459,7 @@ Pod::Spec.new do |s|
# s.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(SDKROOT)/usr/include/libxml2' }
end
SPEC
SPEC
end
def semantic_versioning_notice(repo_id, repo)
......
......@@ -53,16 +53,12 @@ module Pod
end
def ios?
require 'colored'
caller.find { |line| line =~ /^(.+.podspec):\d*/ }
puts "[!] The use of `config.ios?` is deprecated and will be removed in version 0.7.#{" Called from: #{$1}" if $1}".red
# TODO: deprecate in 0.7
podfile.target_definitions[:default].platform == :ios if podfile
end
def osx?
require 'colored'
caller.find { |line| line =~ /^(.+.podspec):\d*/ }
puts "[!] The use of `config.osx?` is deprecated and will be removed in version 0.7.#{" Called from: #{$1}" if $1}".red
# TODO: deprecate in 0.7
podfile.target_definitions[:default].platform == :osx if podfile
end
......
......@@ -3,19 +3,19 @@ module Pod
attr_reader :specification
attr_reader :sandbox
attr_reader :platform
def initialize(specification, sandbox, platform)
@specification, @sandbox, @platform = specification, sandbox, platform
end
def self.from_podspec(podspec, sandbox, platform)
new(Specification.from_file(podspec), sandbox, platform)
end
def root
@sandbox.root + specification.name
end
def to_s
if specification.local?
"#{specification} [LOCAL]"
......@@ -23,28 +23,28 @@ module Pod
specification.to_s
end
end
def name
specification.name
end
def create
root.mkpath unless exists?
end
def exists?
root.exist?
end
def chdir(&block)
create
Dir.chdir(root, &block)
end
def implode
root.rmtree if exists?
end
def clean
clean_paths.each { |path| FileUtils.rm_rf(path) }
end
......@@ -54,19 +54,19 @@ module Pod
@sandbox.root + specification.name + prefix_header
end
end
def source_files
expanded_paths(specification.source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => true)
end
def absolute_source_files
expanded_paths(specification.source_files, :glob => '*.{h,m,mm,c,cpp}')
end
def clean_paths
expanded_paths(specification.clean_paths)
end
def resources
expanded_paths(specification.resources, :relative_to_sandbox => true)
end
......@@ -74,19 +74,19 @@ module Pod
def header_files
source_files.select { |f| f.extname == '.h' }
end
def link_headers
copy_header_mappings.each do |namespaced_path, files|
@sandbox.add_header_files(namespaced_path, files)
end
end
def add_to_target(target)
implementation_files.each do |file|
target.add_source_file(file, nil, specification.compiler_flags[@platform.name].strip)
end
end
def requires_arc?
specification.requires_arc
end
......@@ -94,13 +94,13 @@ module Pod
def dependencies
specification.dependencies[@platform.name]
end
private
def implementation_files
source_files.select { |f| f.extname != '.h' }
end
def relative_root
root.relative_path_from(@sandbox.root)
end
......@@ -115,7 +115,7 @@ module Pod
mappings
end
end
def expanded_paths(platforms_with_patterns, options = {})
patterns = platforms_with_patterns.is_a?(Hash) ? platforms_with_patterns[@platform.name] : platforms_with_patterns
patterns.map do |pattern|
......
......@@ -4,7 +4,7 @@ module Pod
include Config::Mixin
attr_reader :name, :target_dependencies
attr_accessor :xcodeproj, :link_with, :platform, :parent, :exclusive
def initialize(name, options = {})
......@@ -64,7 +64,8 @@ module Pod
# Returns a path, which is relative to the project_root, relative to the
# `$(SRCROOT)` of the user's project.
def relative_to_srcroot(path)
(config.project_root + path).relative_path_from(xcodeproj.dirname)
raise Informative, "[!] Unable to find an Xcode project to integrate".red unless xcodeproj || !config.integrate_targets
xcodeproj ? (config.project_root + path).relative_path_from(xcodeproj.dirname) : path
end
def relative_pods_root
......@@ -368,7 +369,7 @@ module Pod
# This is used as a workaround for a compiler bug with non-ARC projects.
# (see https://github.com/CocoaPods/CocoaPods/issues/142)
#
# This was originally done automatically but libtool as of Xcode 4.3.2 no
# This was originally done automatically but libtool as of Xcode 4.3.2 no
# longer seems to support the -fobjc-arc flag. Therefore it now has to be
# enabled explicitly using this method.
#
......@@ -397,7 +398,7 @@ module Pod
def generate_bridge_support?
@generate_bridge_support
end
def set_arc_compatibility_flag?
@set_arc_compatibility_flag
end
......
......@@ -436,7 +436,7 @@ module Pod
end
# Override the getters to always return the value of the top level parent spec.
[:version, :summary, :platform, :license, :authors, :requires_arc, :compiler_flags, :documentation].each do |attr|
[:version, :summary, :platform, :license, :authors, :requires_arc, :compiler_flags, :documentation, :homepage].each do |attr|
define_method(attr) { top_level_parent.send(attr) }
end
......
require File.expand_path('../../../spec_helper', __FILE__)
describe Pod::Command::Push do
extend SpecHelper::Command
extend SpecHelper::Git
extend SpecHelper::TemporaryDirectory
it "complains for wrong parameters" do
lambda { run_command('push') }.should.raise Pod::Command::Help
lambda { run_command('push', '--allow-warnings') }.should.raise Pod::Command::Help
lambda { run_command('push', '--wrong-option') }.should.raise Pod::Command::Help
end
it "complains if it can't find the repo" do
repo1 = add_repo('repo1', fixture('spec-repos/master'))
Dir.chdir(fixture('banana-lib')) do
lambda { run_command('push', 'repo2') }.should.raise Pod::Informative
end
end
it "complains if it can't find a spec" do
repo1 = add_repo('repo1', fixture('spec-repos/master'))
lambda { run_command('push', 'repo1') }.should.raise Pod::Informative
end
it "it raises if the pod is not validated" do
repo1 = add_repo('repo1', fixture('spec-repos/master'))
git('repo1', 'checkout master') # checkout master, because the fixture is a submodule
repo2 = add_repo('repo2', repo1.dir)
git_config('repo2', 'remote.origin.url').should == (tmp_repos_path + 'repo1').to_s
Dir.chdir(fixture('banana-lib')) do
lambda { command('push', 'repo2', '--silent').run }.should.raise Pod::Informative
end
# (repo1.dir + 'BananaLib/1.0/BananaLib.podspec').read.should.include 'Added!'
end
before do
# prepare the repos
@upstream = add_repo('upstream', fixture('spec-repos/master'))
git('upstream', 'checkout -b master') # checkout master, because the fixture is a submodule
@local_repo = add_repo('local_repo', @upstream.dir)
git_config('local_repo', 'remote.origin.url').should == (tmp_repos_path + 'upstream').to_s
git('upstream', 'checkout -b no-master') # checkout no-master, to allow push in a non-bare repository
# prepare the spec
spec_fix = (fixture('spec-repos') + 'master/JSONKit/1.4/JSONKit.podspec').read
spec_add = spec_fix.gsub(/https:\/\/github\.com\/johnezang\/JSONKit\.git/, fixture('integration/JSONKit').to_s)
spec_add.gsub!(/'JSONKit'/, "'PushTest'")
File.open(temporary_directory + 'JSONKit.podspec', 'w') {|f| f.write(spec_fix) }
File.open(temporary_directory + 'PushTest.podspec', 'w') {|f| f.write(spec_add) }
end
it "refuses to push if the repo is not clean" do
File.open(@local_repo.dir + 'README', 'w') {|f| f.write('Added!') }
(@local_repo.dir + 'README').read.should.include 'Added!'
cmd = command('push', 'local_repo')
cmd.expects(:validate_podspec_files).returns(true)
Dir.chdir(temporary_directory) { lambda { cmd.run }.should.raise Pod::Informative }
git('upstream', 'checkout master') # checkout master, because the fixture is a submodule
(@upstream.dir + 'PushTest/1.4/PushTest.podspec').should.not.exist?
end
it "sucessfully pushes a spec" do
cmd = command('push', 'local_repo')
cmd.expects(:validate_podspec_files).returns(true)
Dir.chdir(temporary_directory) { cmd.run }
cmd.output.should.include('[Add] PushTest (1.4)')
cmd.output.should.include('[Fix] JSONKit (1.4)')
git('upstream', 'checkout master') # checkout master, because the fixture is a submodule
(@upstream.dir + 'PushTest/1.4/PushTest.podspec').read.should.include('PushTest')
end
end
......@@ -3,6 +3,7 @@ require File.expand_path('../../../spec_helper', __FILE__)
describe "Pod::Command::Search" do
extend SpecHelper::Command
extend SpecHelper::Git
extend SpecHelper::TemporaryDirectory
before do
config.repos_dir = fixture('spec-repos')
......@@ -19,6 +20,7 @@ describe "Pod::Command::Search" do
end
it "complains for wrong parameters" do
lambda { run_command('search') }.should.raise Pod::Command::Help
lambda { run_command('search', 'too', 'many') }.should.raise Pod::Command::Help
lambda { run_command('search', 'too', '--wrong') }.should.raise Pod::Command::Help
lambda { run_command('search', '--wrong') }.should.raise Pod::Command::Help
......
require File.expand_path('../../../spec_helper', __FILE__)
describe "Pod::Command::Spec" do
describe Pod::Command::Spec do
extend SpecHelper::Command
extend SpecHelper::Github
extend SpecHelper::TemporaryDirectory
it "runs with correct parameters" do
lambda{ run_command('spec', 'create', 'Bananas') }.should.not.raise
expect_github_repo_request
expect_github_user_request
expect_github_tags_request
lambda{ run_command('spec', 'create', 'https://github.com/lukeredpath/libPusher.git') }.should.not.raise
end
it "complains for wrong parameters" do
lambda { run_command('spec') }.should.raise Pod::Command::Help
lambda { run_command('spec', 'create') }.should.raise Pod::Command::Help
lambda { run_command('spec', '--create') }.should.raise Pod::Command::Help
lambda { run_command('spec', 'NAME') }.should.raise Pod::Command::Help
lambda { run_command('spec', 'createa') }.should.raise Pod::Command::Help
lambda { run_command('spec', 'create') }.should.raise Pod::Command::Help
lambda { run_command('lint', 'agument1', '2') }.should.raise Pod::Command::Help
end
end
describe "Pod::Command::Spec create" do
extend SpecHelper::Command
extend SpecHelper::Github
extend SpecHelper::TemporaryDirectory
extend SpecHelper::Git
it "creates a new podspec stub file" do
run_command('spec', 'create', 'Bananas')
......@@ -50,6 +50,22 @@ describe "Pod::Command::Spec" do
spec.source.should == { :git => 'https://github.com/lukeredpath/libPusher.git', :tag => 'v1.3' }
end
it "accepts the a name when creating a podspec form github" do
expect_github_repo_request
expect_github_user_request
expect_github_tags_request
run_command('spec', 'create', 'other_name', 'https://github.com/lukeredpath/libPusher.git')
path = temporary_directory + 'other_name.podspec'
spec = Pod::Specification.from_file(path)
spec.name.should == 'other_name'
spec.license.should == { :type => "MIT", :file => "LICENSE" }
spec.version.should == Pod::Version.new('1.3')
spec.summary.should == 'An Objective-C interface to Pusher (pusherapp.com)'
spec.homepage.should == 'https://github.com/lukeredpath/libPusher'
spec.authors.should == {"Luke Redpath"=>"luke@lukeredpath.co.uk"}
spec.source.should == { :git => 'https://github.com/lukeredpath/libPusher.git', :tag => 'v1.3' }
end
it "correctly suggests the head commit if a suitable tag is not available on github" do
expect_github_repo_request
expect_github_user_request
......@@ -71,8 +87,96 @@ describe "Pod::Command::Spec" do
output.should.include 'MARKDOWN TEMPLATE'
output.should.include 'Please add semantic version tags'
end
end
describe "Pod::Command::Spec lint" do
extend SpecHelper::Command
extend SpecHelper::TemporaryDirectory
extend SpecHelper::Git
before do
config.repos_dir = fixture('spec-repos')
end
after do
config.repos_dir = tmp_repos_path
end
it "lints a repo" do
# the fixture master repo has warnings and does not validates
lambda { run_command('spec', 'lint', 'master') }.should.raise Pod::Informative
end
it "lints a repo with --only-errors option and show the warnings" do
output = run_command('spec', 'lint', 'master', '--only-errors')
output.should.include "passed validation"
output.should.include "WARN"
end
it "complains if no repo name or url are provided and there a no specs in the current working directory" do
Dir.chdir(fixture('spec-repos') + 'master/JSONKit/') do
lambda { command('spec', 'lint').run }.should.raise Pod::Informative
end
end
it "lints the current working directory" do
Dir.chdir(fixture('spec-repos') + 'master/JSONKit/1.4/') do
output = command('spec', 'lint', '--quick', '--only-errors').run
output.should.include "passed validation"
end
end
it "lints a givent podspec" do
spec_file = fixture('spec-repos') + 'master/JSONKit/1.4/JSONKit.podspec'
output = run_command('spec', 'lint', '--quick', spec_file)
output.should.include "passed validation"
end
before do
spec = (fixture('spec-repos') + 'master/JSONKit/1.4/JSONKit.podspec').read
spec.gsub!(/https:\/\/github\.com\/johnezang\/JSONKit\.git/, fixture('integration/JSONKit').to_s)
spec.gsub!(/s\.source_files = 'JSONKit\.\*'/, "s.source_files = 'JSONKit.*'\ns.resources = 'WRONG_FOLDER'")
File.open(temporary_directory + 'JSONKit.podspec', 'w') {|f| f.write(spec) }
end
it "fails if there are warnings" do
cmd = command('spec', 'lint', '--quick')
Dir.chdir(temporary_directory) { lambda { cmd.run }.should.raise Pod::Informative }
cmd.output.should.include "- WARN | Missing license[:file] or [:text]"
end
it "respects the --only-errors option" do
cmd = command('spec', 'lint', '--quick', '--only-errors')
Dir.chdir(temporary_directory) { lambda { cmd.run }.should.not.raise Pod::Informative }
cmd.output.should.include "- WARN | Missing license[:file] or [:text]"
cmd.output.should.include "passed validation"
end
it "respects the --quick option" do
cmd = command('spec', '--quick', 'lint')
Dir.chdir(temporary_directory) { lambda { cmd.run }.should.raise Pod::Informative }
cmd.output.should.not.include "JSONKit/JSONKit.m:1640:27: warning: equality comparison with extraneous parentheses"
end
it "uses xcodebuild to generate warnings and checks for file patterns" do
# those two checks are merged because pod install is computationally expensive
cmd = command('spec', 'lint')
Dir.chdir(temporary_directory) { lambda { cmd.run }.should.raise Pod::Informative }
unless `which xcodebuild`.strip.empty?
cmd.output.should.include "JSONKit/JSONKit.m:1640:27: warning: equality comparison with extraneous parentheses"
end
cmd.output.should.include "- ERROR | [resources = 'WRONG_FOLDER'] -> did not match any file"
end
before do
spec = (fixture('spec-repos') + 'master/JSONKit/1.4/JSONKit.podspec').read
spec.gsub!(/s\.source_files = 'JSONKit\.\*'/, "s.source_files = 'JSONKit.*'\n if config.ios?\nend")
File.open(temporary_directory + 'JSONKit.podspec', 'w') {|f| f.write(spec) }
end
it "produces deprecation notices" do
cmd = command('spec', '--quick', 'lint')
Dir.chdir(temporary_directory) { lambda { cmd.run }.should.raise Pod::Informative }
cmd.output.should.include "- WARN | `config.ios?' and `config.osx' will be removed in version 0.7"
end
end
......@@ -48,7 +48,7 @@ describe "Pod::Podfile" do
Pod::Podfile.new {}.should.not.generate_bridge_support
Pod::Podfile.new { generate_bridge_support! }.should.generate_bridge_support
end
it 'specifies that ARC compatibility flag should be generated' do
Pod::Podfile.new { set_arc_compatibility_flag! }.should.set_arc_compatibility_flag
end
......@@ -260,6 +260,15 @@ describe "Pod::Podfile" do
@target_definition.relative_pods_root.should == '${SRCROOT}/../Pods'
end
it "simply returns the $(PODS_ROOT) path if no xcodeproj file is available and doesn't needs to integrate" do
config.integrate_targets.should.equal true
config.integrate_targets = false
@target_definition.relative_pods_root.should == '${SRCROOT}/../Pods'
@target_definition.stubs(:xcodeproj).returns(nil)
@target_definition.relative_pods_root.should == '${SRCROOT}/Pods'
config.integrate_targets = true
end
it "returns the xcconfig file path relative to the project's $(SRCROOT)" do
@target_definition.xcconfig_relative_path.should == '../Pods/Pods.xcconfig'
end
......@@ -271,6 +280,17 @@ describe "Pod::Podfile" do
end
describe "concerning validations" do
it "raises if it should integrate and can't find an xcodeproj" do
config.integrate_targets.should.equal true
target_definition = Pod::Podfile.new {}.target_definitions[:default]
target_definition.stubs(:xcodeproj).returns(nil)
exception = lambda {
target_definition.relative_pods_root
}.should.raise Pod::Informative
exception.message.should.include "Xcode project"
end
xit "raises if no platform is specified" do
exception = lambda {
Pod::Podfile.new {}.validate!
......
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