Commit 34a68534 authored by Fabio Pelosin's avatar Fabio Pelosin

Introduced Pod `update`, `outdated`.

See #131, #191.

- The installer is initialized with a resolver. The resolver is responsible of
  indicating which specs must be installed/reinstalled.
- It was introduced a slight change in the format of the Podfile.lock.
- The specification set was simplified to receive and handle Pod::Dependency
  instead of Pod::Specification. With this change it also appears to be more
  robust.

A this stage it appears to be working. However the support, for external and
head dependencies is weak.
parent 02232337
...@@ -32,6 +32,7 @@ module Pod ...@@ -32,6 +32,7 @@ module Pod
autoload :Executable, 'cocoapods/executable' autoload :Executable, 'cocoapods/executable'
autoload :Installer, 'cocoapods/installer' autoload :Installer, 'cocoapods/installer'
autoload :LocalPod, 'cocoapods/local_pod' autoload :LocalPod, 'cocoapods/local_pod'
autoload :Lockfile, 'cocoapods/lockfile'
autoload :Platform, 'cocoapods/platform' autoload :Platform, 'cocoapods/platform'
autoload :Podfile, 'cocoapods/podfile' autoload :Podfile, 'cocoapods/podfile'
autoload :Project, 'cocoapods/project' autoload :Project, 'cocoapods/project'
......
...@@ -6,12 +6,14 @@ module Pod ...@@ -6,12 +6,14 @@ module Pod
autoload :Install, 'cocoapods/command/install' autoload :Install, 'cocoapods/command/install'
autoload :List, 'cocoapods/command/list' autoload :List, 'cocoapods/command/list'
autoload :Linter, 'cocoapods/command/linter' autoload :Linter, 'cocoapods/command/linter'
autoload :Outdated, 'cocoapods/command/outdated'
autoload :Presenter, 'cocoapods/command/presenter' autoload :Presenter, 'cocoapods/command/presenter'
autoload :Push, 'cocoapods/command/push' autoload :Push, 'cocoapods/command/push'
autoload :Repo, 'cocoapods/command/repo' autoload :Repo, 'cocoapods/command/repo'
autoload :Search, 'cocoapods/command/search' autoload :Search, 'cocoapods/command/search'
autoload :Setup, 'cocoapods/command/setup' autoload :Setup, 'cocoapods/command/setup'
autoload :Spec, 'cocoapods/command/spec' autoload :Spec, 'cocoapods/command/spec'
autoload :Update, 'cocoapods/command/update'
class Help < Informative class Help < Informative
def initialize(command_class, argv) def initialize(command_class, argv)
...@@ -99,13 +101,15 @@ module Pod ...@@ -99,13 +101,15 @@ module Pod
String.send(:define_method, :colorize) { |string , _| string } if argv.option( '--no-color' ) String.send(:define_method, :colorize) { |string , _| string } if argv.option( '--no-color' )
command_class = case argv.shift_argument command_class = case argv.shift_argument
when 'install' then Install when 'install' then Install
when 'repo' then Repo when 'list' then List
when 'search' then Search when 'outdated' then Outdated
when 'list' then List when 'push' then Push
when 'setup' then Setup when 'repo' then Repo
when 'spec' then Spec when 'search' then Search
when 'push' then Push when 'setup' then Setup
when 'spec' then Spec
when 'update' then Update
end end
if show_help || command_class.nil? if show_help || command_class.nil?
......
...@@ -6,7 +6,7 @@ module Pod ...@@ -6,7 +6,7 @@ module Pod
$ pod install $ pod install
Downloads all dependencies defined in `Podfile' and creates an Xcode Downloads all dependencies updated in `Podfile' and creates an Xcode
Pods library project in `./Pods'. Pods library project in `./Pods'.
The Xcode project file should be specified in your `Podfile` like this: The Xcode project file should be specified in your `Podfile` like this:
...@@ -50,7 +50,9 @@ module Pod ...@@ -50,7 +50,9 @@ module Pod
Repo.new(ARGV.new(["update"])).run Repo.new(ARGV.new(["update"])).run
end end
Installer.new(podfile).install! sandbox = Sandbox.new(config.project_pods_root)
resolver = Resolver.new(podfile, config.lockfile, sandbox)
Installer.new(resolver).install!
end end
end end
end end
......
...@@ -103,7 +103,9 @@ module Pod ...@@ -103,7 +103,9 @@ module Pod
def install_pod def install_pod
podfile = podfile_from_spec podfile = podfile_from_spec
config.verbose config.verbose
installer = Installer.new(podfile) sandbox = Sandbox.new(config.project_pods_root)
resolver = Resolver.new(podfile, nil, sandbox)
installer = Installer.new(resolver)
installer.install! installer.install!
@pod = installer.pods.find { |pod| pod.top_specification == spec } @pod = installer.pods.find { |pod| pod.top_specification == spec }
config.silent config.silent
......
module Pod
class Command
class Outdated < Command
def self.banner
%{Updates dependencies of a project:
$ pod outdated
Shows the dependencies that would be installed by `pod update'. }
end
def self.options
[
["--no-update", "Skip running `pod repo update` before install"],
].concat(super)
end
def initialize(argv)
@update_repo = !argv.option('--no-update')
super unless argv.empty?
end
def run
unless podfile = config.podfile
raise Informative, "No `Podfile' found in the current working directory."
end
unless lockfile = config.lockfile
raise Informative, "No `Podfile.lock' found in the current working directory, run `pod install'."
end
# if @update_repo
# print_title 'Updating Spec Repositories', true
# Re"o.new(ARGV.new(["update"])).run
# end
sandbox = Sandbox.new(config.project_pods_root)
resolver = Resolver.new(podfile, lockfile, sandbox)
resolver.update_mode = true
resolver.resolve
specs_to_install = resolver.specs_to_install
if specs_to_install.empty?
puts "\nNo updates are available.\n".yellow
else
puts "\nThe following updates are available:".green
puts " - " << specs_to_install.join("\n - ") << "\n\n"
end
end
end
end
end
module Pod
class Command
class Update < Command
def self.banner
%{Updates dependencies of a project:
$ pod update
Updates all dependencies installed by `pod install`. It doesn't
install new dependencies. }
end
def self.options
[
["--no-clean", "Leave SCM dirs like `.git' and `.svn' intact after downloading"],
["--no-doc", "Skip documentation generation with appledoc"],
["--no-integrate", "Skip integration of the Pods libraries in the Xcode project(s)"],
["--no-update", "Skip running `pod repo update` before install"],
].concat(super)
end
def initialize(argv)
config.clean = !argv.option('--no-clean')
config.generate_docs = !argv.option('--no-doc')
config.integrate_targets = !argv.option('--no-integrate')
@update_repo = !argv.option('--no-update')
super unless argv.empty?
end
def run
unless podfile = config.podfile
raise Informative, "No `Podfile' found in the current working directory."
end
unless lockfile = config.lockfile
raise Informative, "No `Podfile.lock' found in the current working directory, run `pod install'."
end
# if @update_repo
# print_title 'Updating Spec Repositories', true
# Repo.new(ARGV.new(["update"])).run
# end
sandbox = Sandbox.new(config.project_pods_root)
resolver = Resolver.new(podfile, lockfile, sandbox)
resolver.update_mode = true
Installer.new(resolver).install!
end
end
end
end
...@@ -41,6 +41,10 @@ module Pod ...@@ -41,6 +41,10 @@ module Pod
@project_podfile ||= project_root + 'Podfile' @project_podfile ||= project_root + 'Podfile'
end end
def project_lockfile
@project_lockfile ||= project_root + 'Podfile.lock'
end
def headers_symlink_root def headers_symlink_root
@headers_symlink_root ||= "#{project_pods_root}/Headers" @headers_symlink_root ||= "#{project_pods_root}/Headers"
end end
...@@ -53,6 +57,12 @@ module Pod ...@@ -53,6 +57,12 @@ module Pod
end end
attr_writer :podfile attr_writer :podfile
def lockfile
@lockfile ||= begin
Lockfile.from_file(project_lockfile) if project_lockfile.exist?
end
end
module Mixin module Mixin
def config def config
Config.instance Config.instance
......
...@@ -7,19 +7,12 @@ module Pod ...@@ -7,19 +7,12 @@ module Pod
include Config::Mixin include Config::Mixin
attr_reader :sandbox attr_reader :resolver, :sandbox, :lockfile
def initialize(podfile)
@podfile = podfile
# FIXME: pass this into the installer as a parameter
@sandbox = Sandbox.new(config.project_pods_root)
@resolver = Resolver.new(@podfile, @sandbox)
# TODO: remove in 0.7 (legacy support for config.ios? and config.osx?)
config.podfile = podfile
end
def lock_file def initialize(resolver)
config.project_root + 'Podfile.lock' @resolver = resolver
@podfile = resolver.podfile
@sandbox = resolver.sandbox
end end
def project def project
...@@ -46,6 +39,9 @@ module Pod ...@@ -46,6 +39,9 @@ module Pod
def install_dependencies! def install_dependencies!
pods.each do |pod| pods.each do |pod|
name = pod.top_specification.name
should_install = @resolver.should_install?(name) || !pod.exists?
unless config.silent? unless config.silent?
marker = config.verbose ? "\n-> ".green : '' marker = config.verbose ? "\n-> ".green : ''
if subspec_name = pod.top_specification.preferred_dependency if subspec_name = pod.top_specification.preferred_dependency
...@@ -54,20 +50,22 @@ module Pod ...@@ -54,20 +50,22 @@ module Pod
name = pod.to_s name = pod.to_s
end end
name << " [HEAD]" if pod.top_specification.version.head? name << " [HEAD]" if pod.top_specification.version.head?
puts marker << ( pod.exists? ? "Using #{name}" : "Installing #{name}".green ) puts marker << ( should_install ? "Installing #{name}".green : "Using #{name}" )
end end
download_pod(pod) unless pod.exists? if should_install
pod.implode
# This will not happen if the pod existed before we started the install download_pod(pod)
# process. # This will not happen if the pod existed before we started the install
if pod.downloaded? # process.
# The docs need to be generated before cleaning because the if pod.downloaded?
# documentation is created for all the subspecs. # The docs need to be generated before cleaning because the
generate_docs(pod) # documentation is created for all the subspecs.
# Here we clean pod's that just have been downloaded or have been generate_docs(pod)
# pre-downloaded in AbstractExternalSource#specification_from_sandbox. # Here we clean pod's that just have been downloaded or have been
pod.clean! if config.clean? # pre-downloaded in AbstractExternalSource#specification_from_sandbox.
pod.clean! if config.clean?
end
end end
end end
end end
...@@ -117,8 +115,6 @@ module Pod ...@@ -117,8 +115,6 @@ module Pod
generate_dummy_source(target_installer) generate_dummy_source(target_installer)
end end
generate_lock_file!(specifications)
puts "- Running post install hooks" if config.verbose? puts "- Running post install hooks" if config.verbose?
# 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
...@@ -126,6 +122,10 @@ module Pod ...@@ -126,6 +122,10 @@ module Pod
puts "- Writing Xcode project file to `#{@sandbox.project_path}'\n\n" if config.verbose? puts "- Writing Xcode project file to `#{@sandbox.project_path}'\n\n" if config.verbose?
project.save_as(@sandbox.project_path) project.save_as(@sandbox.project_path)
puts "- Writing lockfile in `#{lockfile.defined_in_file}'\n\n" if config.verbose?
@lockfile = Lockfile.create(config.project_lockfile, @podfile, specs_by_target.values.flatten)
@lockfile.write_to_disk
UserProjectIntegrator.new(@podfile).integrate! if config.integrate_targets? UserProjectIntegrator.new(@podfile).integrate! if config.integrate_targets?
end end
...@@ -133,7 +133,7 @@ module Pod ...@@ -133,7 +133,7 @@ module Pod
# 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
# to the spec post install hook. # to the spec post install hook.
target_installers.each do |target_installer| target_installers.each do |target_installer|
specs_by_target[target_installer.target_definition].each do |spec| @specs_by_target[target_installer.target_definition].each do |spec|
spec.post_install(target_installer) spec.post_install(target_installer)
end end
end end
...@@ -141,44 +141,6 @@ module Pod ...@@ -141,44 +141,6 @@ module Pod
@podfile.post_install!(self) @podfile.post_install!(self)
end end
def generate_lock_file!(specs)
lock_file.open('w') do |file|
file.puts "PODS:"
# Get list of [name, dependencies] pairs.
pod_and_deps = specs.map do |spec|
[spec.to_s, spec.dependencies.map(&:to_s).sort]
end.uniq
# Merge dependencies of ios and osx version of the same pod.
tmp = {}
pod_and_deps.each do |name, deps|
if tmp[name]
tmp[name].concat(deps).uniq!
else
tmp[name] = deps
end
end
pod_and_deps = tmp
# Sort by name and print
pod_and_deps.sort_by(&:first).each do |name, deps|
if deps.empty?
file.puts " - #{name}"
else
file.puts " - #{name}:"
deps.each { |dep| file.puts " - #{dep}" }
end
end
file.puts
file.puts "DEPENDENCIES:"
@podfile.dependencies.map(&:to_s).sort.each do |dep|
file.puts " - #{dep}"
end
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)
...@@ -192,15 +154,6 @@ module Pod ...@@ -192,15 +154,6 @@ module Pod
target_installer.target.source_build_phases.first << project_file target_installer.target.source_build_phases.first << project_file
end end
def specs_by_target
@specs_by_target ||= @resolver.resolve
end
# @return [Array<Specification>] All dependencies that have been resolved.
def specifications
specs_by_target.values.flatten
end
# @return [Array<LocalPod>] A list of LocalPod instances for each # @return [Array<LocalPod>] A list of LocalPod instances for each
# dependency that is not a download-only one. # dependency that is not a download-only one.
def pods def pods
...@@ -219,6 +172,14 @@ module Pod ...@@ -219,6 +172,14 @@ module Pod
result result
end end
def specifications
specs_by_target.values.flatten
end
def specs_by_target
@specs_by_target ||= @resolver.resolve
end
private private
def print_title(title, only_verbose = true) def print_title(title, only_verbose = true)
......
module Pod
class Lockfile
# @return [Lockfile] Returns the Lockfile saved in path.
#
def self.from_file(path)
Lockfile.new(path)
end
# @return [Lockfile] Creates a new Lockfile ready to be saved in path.
#
def self.create(path, podfile, specs)
Lockfile.new(path, podfile, specs)
end
attr_reader :defined_in_file, :podfile, :specs, :dictionary_reppresenation
# @param [Pathname] the path of the Lockfile.
# If no other value is provided the Lockfile is read from this path.
# @param [Podfile] the Podfile to use for generating the Lockfile.
# @param [specs] the specs installed.
#
def initialize(path, podfile = nil, specs = nil)
@defined_in_file = path
if podfile && specs
@podfile = podfile
@specs = specs
else
yaml = YAML.load(File.open(path))
if yaml && Version.new(yaml["COCOAPODS"]) >= Version.new("0.10")
@dictionary_reppresenation = yaml
end
end
end
# @return [Array<Dependency>] The dependencies used during the last install.
#
def podfile_dependencies
return [] unless to_dict
dependencies = to_dict['DEPENDENCIES'] | []
dependencies.map { |dep|
match_data = dep.match(/(\S*)( (.*))/)
Dependency.new(match_data[1], match_data[2].gsub(/[()]/,''))
}
end
# @return [Array<Dependency>] The dependencies that require exactly,
# the installed pods.
#
def installed_dependencies
return [] unless to_dict
pods = to_dict['PODS'] | []
pods.map { |pod|
name_and_version = pod.is_a?(String) ? pod : pod.keys[0]
match_data = name_and_version.match(/(\S*)( (.*))/)
Dependency.new(match_data[1], match_data[2].gsub(/[()]/,''))
}
end
# @return [void] Writes the Lockfile to path.
#
def write_to_disk
File.open(defined_in_file, 'w') {|f| f.write(to_yaml) }
end
# @return [String] A string useful to represent the Lockfile in a message
# presented to the user.
#
def to_s
"Podfile.lock"
end
# @return [String] The YAML representation of the Lockfile, used for
# serialization.
#
def to_yaml
to_dict.to_yaml
end
# @return [Dictionary] The Dictionary representation of the Lockfile.
#
def to_dict
return @dictionary_reppresenation if @dictionary_reppresenation
return nil unless @podfile && @specs
# Get list of [name, dependencies] pairs.
pod_and_deps = specs.map do |spec|
[spec.to_s, spec.dependencies.map(&:to_s).sort]
end.uniq
# Merge dependencies of ios and osx version of the same pod.
tmp = {}
pod_and_deps.each do |name, deps|
if tmp[name]
tmp[name].concat(deps).uniq!
else
tmp[name] = deps
end
end
pod_and_deps = tmp.sort_by(&:first).map do |name, deps|
deps.empty? ? name : {name => deps}
end
dict = {}
dict["PODS"] = pod_and_deps
dict["DEPENDENCIES"] = podfile.dependencies.map(&:to_s).sort
# dict["SPECS_CHECKSUM"] =
# dict["HEAD_SPECS_INFO"] =
dict["COCOAPODS"] = VERSION
dict
end
end
end
...@@ -4,34 +4,111 @@ module Pod ...@@ -4,34 +4,111 @@ module Pod
class Resolver class Resolver
include Config::Mixin include Config::Mixin
attr_reader :podfile, :sandbox attr_reader :podfile, :lockfile, :sandbox
attr_accessor :cached_sets, :cached_sources attr_accessor :cached_sets, :cached_sources, :update_mode
def initialize(podfile, sandbox) def initialize(podfile, lockfile, sandbox)
@podfile = podfile @podfile = podfile
@sandbox = sandbox @lockfile = lockfile
@sandbox = sandbox
@cached_sets = {} @cached_sets = {}
@cached_sources = Source::Aggregate.new @cached_sources = Source::Aggregate.new
@log_indent = 0; @log_indent = 0;
end
def installed_dependencies
@installed_dependencies ||= lockfile ? lockfile.installed_dependencies : []
end
def should_install?(name)
names_of_pods_installs = specs_to_install.map(&:name)
names_of_pods_installs.include?(name)
end
def specs_to_install
if update_mode
specs = @targets_and_specs.values.flatten
outdated_specs = []
specs.each do |spec|
if spec_outdated?(spec)
outdated_specs << spec
end
end
outdated_specs
else
specs = @targets_and_specs.values.flatten
outdated_specs = []
specs.each do |spec|
unless spec_installed?(spec)
outdated_specs << spec
end
end
outdated_specs
# Implement this forces the installer to install only the specs that don't have a folder.
# Should install also if there was a change in the podfile
# Disambiguate dependecies before resolution?
[]
end
end
def specs_by_target
@targets_and_specs
end end
def resolve def resolve
if lockfile
if config.verbose?
puts "\nInstalled podfile dependencies detected in: #{lockfile.defined_in_file}".green
lockfile.podfile_dependencies.each {|dependency| puts " - #{dependency}" }
puts "\nInstalled pods versions detected in: #{lockfile.defined_in_file}".green
lockfile.installed_dependencies.each {|dependency| puts " - #{dependency}" }
end
end
unless update_mode || !lockfile
puts "\nLocking dependencies to installed versions:".green if config.verbose?
# Add the installed specs which are still compatible with podfile
# requirements to activated
installed_dependencies.each do |dependency|
compatible_with_podfile = dependency && true
if compatible_with_podfile
puts " - #{dependency}" if config.verbose?
set = find_cached_set(dependency, nil)
set.required_by(dependency, lockfile.to_s)
end
end
end
@specs = {} @specs = {}
targets_and_specs = {} @targets_and_specs = {}
@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? puts "\nResolving dependencies for target `#{target_definition.name}' (#{target_definition.platform})".green if config.verbose?
@loaded_specs = [] @loaded_specs = []
find_dependency_specs(@podfile, target_definition.dependencies, target_definition) find_dependency_specs(@podfile, target_definition.dependencies, target_definition)
targets_and_specs[target_definition] = @specs.values_at(*@loaded_specs).sort_by(&:name) @targets_and_specs[target_definition] = @specs.values_at(*@loaded_specs).sort_by(&:name)
end end
@specs.values.sort_by(&:name) @specs.values.sort_by(&:name)
targets_and_specs @targets_and_specs
end end
private private
def dependency_installed?(dependency)
installed_dependencies.any?{ |installed_dependency| installed_dependency.name == dependency.name }
end
def spec_installed?(spec)
installed_dependencies.any?{ |installed_dependency| installed_dependency.name == spec.name }
end
def spec_outdated?(spec)
installed_dependency = installed_dependencies.find{|installed_dependency| installed_dependency.name == spec.name }
installed_dependency && !installed_dependency.matches_spec?(spec)
end
def find_cached_set(dependency, platform) def find_cached_set(dependency, platform)
set_name = dependency.name.split('/').first set_name = dependency.name.split('/').first
@cached_sets[set_name] ||= begin @cached_sets[set_name] ||= begin
...@@ -58,9 +135,16 @@ module Pod ...@@ -58,9 +135,16 @@ module Pod
dependencies.each do |dependency| dependencies.each do |dependency|
puts ' ' * @log_indent + "- #{dependency}" if config.verbose? 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(dependent_specification) set.required_by(dependency, dependent_specification.to_s)
if update_mode
mode_wants_spec = dependency_installed?(dependency)
else
mode_wants_spec = true
end
# Ensure we don't resolve the same spec twice for one target # Ensure we don't resolve the same spec twice for one target
unless @loaded_specs.include?(dependency.name) if mode_wants_spec && !@loaded_specs.include?(dependency.name)
spec = set.specification_by_name(dependency.name) spec = set.specification_by_name(dependency.name)
@loaded_specs << spec.name @loaded_specs << spec.name
@specs[spec.name] = spec @specs[spec.name] = spec
...@@ -69,8 +153,8 @@ module Pod ...@@ -69,8 +153,8 @@ module Pod
spec.version.head = dependency.head? spec.version.head = dependency.head?
# And recursively load the dependencies of the spec. # And recursively load the dependencies of the spec.
find_dependency_specs(spec, spec.dependencies, target_definition) if spec.dependencies find_dependency_specs(spec, spec.dependencies, target_definition) if spec.dependencies
validate_platform!(spec || @specs[dependency.name], target_definition)
end end
validate_platform!(spec || @specs[dependency.name], target_definition)
end end
@log_indent -= 1 @log_indent -= 1
end end
......
...@@ -6,22 +6,18 @@ module Pod ...@@ -6,22 +6,18 @@ module Pod
def initialize(pod_dir) def initialize(pod_dir)
@pod_dir = pod_dir @pod_dir = pod_dir
@required_by = [] @required_by = []
@dependencies = []
end end
def required_by(specification) def required_by(dependency, dependent_name)
# Skip subspecs because the can't require a different version of the top level parent
return if !specification.podfile? && specification.top_level_parent.name == name
dependency = specification.dependency_by_top_level_spec_name(name)
# TODO we don’t actually do anything in our Version subclass. Maybe we should just remove that.
unless @required_by.empty? || dependency.requirement.satisfied_by?(Gem::Version.new(required_version.to_s)) unless @required_by.empty? || dependency.requirement.satisfied_by?(Gem::Version.new(required_version.to_s))
# TODO add graph that shows which dependencies led to this. raise Informative, "#{dependent_name} tries to activate `#{dependency}', " \
raise Informative, "#{specification} tries to activate `#{dependency}', " \
"but already activated version `#{required_version}' " \ "but already activated version `#{required_version}' " \
"by #{@required_by.join(', ')}." "by #{@required_by.join(', ')}."
end end
@specification = nil @specification = nil
@required_by << specification @required_by << dependent_name
@dependencies << dependency
end end
def specification_by_name(name) def specification_by_name(name)
...@@ -29,8 +25,8 @@ module Pod ...@@ -29,8 +25,8 @@ module Pod
end end
def dependency def dependency
@required_by.inject(Dependency.new(name)) do |previous, spec| @dependencies.inject(Dependency.new(name)) do |previous, dependency|
previous.merge(spec.dependency_by_top_level_spec_name(name).to_top_level_spec_dependency) previous.merge(dependency.to_top_level_spec_dependency)
end end
end end
...@@ -74,6 +70,7 @@ module Pod ...@@ -74,6 +70,7 @@ module Pod
def initialize(specification) def initialize(specification)
@specification = specification @specification = specification
@required_by = [] @required_by = []
@dependencies = []
end end
def name def name
...@@ -84,9 +81,9 @@ module Pod ...@@ -84,9 +81,9 @@ module Pod
self.class === other && name == other.name self.class === other && name == other.name
end end
def required_by(specification) def required_by(dependency, dependent_name)
before = @specification before = @specification
super(specification) super(dependency, dependent_name)
ensure ensure
@specification = before @specification = before
end end
......
require File.expand_path('../../../spec_helper', __FILE__)
describe Pod::Command::Outdated do
extend SpecHelper::Command
extend SpecHelper::TemporaryDirectory
extend SpecHelper::TemporaryRepos
it "tells the user that no Podfile was found in the current working dir" do
exception = lambda { run_command('outdated','--no-update') }.should.raise Pod::Informative
exception.message.should.include "No `Podfile' found in the current working directory."
end
it "tells the user that no Lockfile was found in the current working dir" do
file = temporary_directory + 'Podfile'
File.open(file, 'w') {|f| f.write('platform :ios') }
Dir.chdir(temporary_directory) do
exception = lambda { run_command('outdated','--no-update') }.should.raise Pod::Informative
exception.message.should.include "No `Podfile.lock' found in the current working directory"
end
end
end
require File.expand_path('../../../spec_helper', __FILE__)
describe Pod::Command::Update do
extend SpecHelper::Command
extend SpecHelper::TemporaryDirectory
extend SpecHelper::TemporaryRepos
it "tells the user that no Podfile was found in the current working dir" do
exception = lambda { run_command('update','--no-update') }.should.raise Pod::Informative
exception.message.should.include "No `Podfile' found in the current working directory."
end
it "tells the user that no Lockfile was found in the current working dir" do
file = temporary_directory + 'Podfile'
File.open(file, 'w') {|f| f.write('platform :ios') }
Dir.chdir(temporary_directory) do
exception = lambda { run_command('update','--no-update') }.should.raise Pod::Informative
exception.message.should.include "No `Podfile.lock' found in the current working directory"
end
end
end
...@@ -70,10 +70,12 @@ else ...@@ -70,10 +70,12 @@ else
end end
# Note that we are *not* using the stubbed SpecHelper::Installer subclass. # Note that we are *not* using the stubbed SpecHelper::Installer subclass.
installer = Pod::Installer.new(podfile)
resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(config.project_pods_root))
installer = Pod::Installer.new(resolver)
installer.install! installer.install!
YAML.load(installer.lock_file.read).should == { installer.lockfile.to_dict.tap {|d| d.delete("COCOAPODS") }.should == {
'PODS' => ['SSToolkit (0.1.3)'], 'PODS' => ['SSToolkit (0.1.3)'],
'DEPENDENCIES' => ["SSToolkit (from `#{url}', commit `#{commit}')"] 'DEPENDENCIES' => ["SSToolkit (from `#{url}', commit `#{commit}')"]
} }
...@@ -88,10 +90,12 @@ else ...@@ -88,10 +90,12 @@ else
pod 'Reachability', :podspec => url pod 'Reachability', :podspec => url
end end
installer = SpecHelper::Installer.new(podfile)
resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(config.project_pods_root))
installer = SpecHelper::Installer.new(resolver)
installer.install! installer.install!
YAML.load(installer.lock_file.read).should == { installer.lockfile.to_dict.tap {|d| d.delete("COCOAPODS") }.should == {
'PODS' => [ 'Reachability (1.2.3)' ], 'PODS' => [ 'Reachability (1.2.3)' ],
# 'DOWNLOAD_ONLY' => ["ASIHTTPRequest (1.8.1)"], # 'DOWNLOAD_ONLY' => ["ASIHTTPRequest (1.8.1)"],
'DEPENDENCIES' => ["Reachability (from `#{url}')"] 'DEPENDENCIES' => ["Reachability (from `#{url}')"]
...@@ -111,7 +115,8 @@ else ...@@ -111,7 +115,8 @@ else
end end
end end
installer = SpecHelper::Installer.new(podfile) resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(config.project_pods_root))
installer = SpecHelper::Installer.new(resolver)
installer.install! installer.install!
dummy = (config.project_pods_root + 'PodsDummy_Pods.m').read dummy = (config.project_pods_root + 'PodsDummy_Pods.m').read
...@@ -134,7 +139,8 @@ else ...@@ -134,7 +139,8 @@ else
end end
end end
installer = SpecHelper::Installer.new(podfile) resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(config.project_pods_root))
installer = SpecHelper::Installer.new(resolver)
installer.install! installer.install!
dummy = (config.project_pods_root + 'PodsDummy_Pods_AnotherTarget.m').read dummy = (config.project_pods_root + 'PodsDummy_Pods_AnotherTarget.m').read
...@@ -160,10 +166,11 @@ else ...@@ -160,10 +166,11 @@ else
end end
Pod::Specification.any_instance.stubs(:preserve_paths).returns(['CHANGELOG.md']) Pod::Specification.any_instance.stubs(:preserve_paths).returns(['CHANGELOG.md'])
installer = SpecHelper::Installer.new(podfile) resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(config.project_pods_root))
installer = SpecHelper::Installer.new(resolver)
installer.install! installer.install!
YAML.load(installer.lock_file.read).should == { installer.lockfile.to_dict.tap {|d| d.delete("COCOAPODS") }.should == {
'PODS' => ['JSONKit (1.2)', 'SSZipArchive (0.1.0)'], 'PODS' => ['JSONKit (1.2)', 'SSZipArchive (0.1.0)'],
'DEPENDENCIES' => ["JSONKit (defined in Podfile)", "SSZipArchive (defined in Podfile)"] 'DEPENDENCIES' => ["JSONKit (defined in Podfile)", "SSZipArchive (defined in Podfile)"]
} }
...@@ -188,11 +195,12 @@ else ...@@ -188,11 +195,12 @@ else
end end
end end
installer = SpecHelper::Installer.new(podfile) resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(config.project_pods_root))
installer = SpecHelper::Installer.new(resolver)
installer.install! installer.install!
# TODO might be nicer looking to not show the dependencies of the top level spec for each subspec (Reachability). # TODO might be nicer looking to not show the dependencies of the top level spec for each subspec (Reachability).
YAML.load(installer.lock_file.read).should == { installer.lockfile.to_dict.should == {
"PODS" => [{ "ASIHTTPRequest (1.8.1)" => ["ASIHTTPRequest/ASIWebPageRequest (= 1.8.1)", "PODS" => [{ "ASIHTTPRequest (1.8.1)" => ["ASIHTTPRequest/ASIWebPageRequest (= 1.8.1)",
"ASIHTTPRequest/CloudFiles (= 1.8.1)", "ASIHTTPRequest/CloudFiles (= 1.8.1)",
"ASIHTTPRequest/S3 (= 1.8.1)", "ASIHTTPRequest/S3 (= 1.8.1)",
...@@ -201,7 +209,8 @@ else ...@@ -201,7 +209,8 @@ else
{ "ASIHTTPRequest/CloudFiles (1.8.1)" => ["Reachability"] }, { "ASIHTTPRequest/CloudFiles (1.8.1)" => ["Reachability"] },
{ "ASIHTTPRequest/S3 (1.8.1)" => ["Reachability"] }, { "ASIHTTPRequest/S3 (1.8.1)" => ["Reachability"] },
"JSONKit (1.4)", "Reachability (3.0.0)"], "JSONKit (1.4)", "Reachability (3.0.0)"],
"DEPENDENCIES" => ["ASIHTTPRequest", "JSONKit (= 1.4)"] "DEPENDENCIES" => ["ASIHTTPRequest", "JSONKit (= 1.4)"],
"COCOAPODS" => Pod::VERSION
} }
should_xcodebuild(podfile.target_definitions[:ios_target]) should_xcodebuild(podfile.target_definitions[:ios_target])
...@@ -227,7 +236,8 @@ else ...@@ -227,7 +236,8 @@ else
pod 'JSONKit', '1.4' pod 'JSONKit', '1.4'
pod 'SSToolkit', '1.0.0' pod 'SSToolkit', '1.0.0'
end end
installer = SpecHelper::Installer.new(podfile) resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(config.project_pods_root))
installer = SpecHelper::Installer.new(resolver)
installer.install! installer.install!
doc = (config.project_pods_root + 'Documentation/JSONKit/html/index.html').read doc = (config.project_pods_root + 'Documentation/JSONKit/html/index.html').read
...@@ -258,7 +268,8 @@ else ...@@ -258,7 +268,8 @@ else
end end
end end
SpecHelper::Installer.new(podfile).install! resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(config.project_pods_root))
SpecHelper::Installer.new(resolver).install!
project = Pod::Project.new(config.project_pods_root + 'Pods.xcodeproj') project = Pod::Project.new(config.project_pods_root + 'Pods.xcodeproj')
project.targets.first.build_configurations.map do |config| project.targets.first.build_configurations.map do |config|
config.build_settings['GCC_ENABLE_OBJC_GC'] config.build_settings['GCC_ENABLE_OBJC_GC']
...@@ -277,10 +288,11 @@ else ...@@ -277,10 +288,11 @@ else
pod 'SSZipArchive', '< 2' pod 'SSZipArchive', '< 2'
end end
installer = SpecHelper::Installer.new(podfile) resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(config.project_pods_root))
installer = SpecHelper::Installer.new(resolver)
installer.install! installer.install!
lock_file_contents = { lockfile_contents = {
'PODS' => [ 'PODS' => [
# { 'ASIHTTPRequest (1.8.1)' => ["Reachability"] }, # { 'ASIHTTPRequest (1.8.1)' => ["Reachability"] },
# { 'ASIWebPageRequest (1.8.1)' => ["ASIHTTPRequest (= 1.8.1)"] }, # { 'ASIWebPageRequest (1.8.1)' => ["ASIHTTPRequest (= 1.8.1)"] },
...@@ -293,15 +305,16 @@ else ...@@ -293,15 +305,16 @@ else
"JSONKit (>= 1.0)", "JSONKit (>= 1.0)",
"Reachability (> 2.0.5)", "Reachability (> 2.0.5)",
"SSZipArchive (< 2)", "SSZipArchive (< 2)",
] ],
"COCOAPODS" => Pod::VERSION
} }
unless platform == :ios unless platform == :ios
# No Reachability is required by ASIHTTPRequest on OSX # No Reachability is required by ASIHTTPRequest on OSX
lock_file_contents['DEPENDENCIES'].delete_at(1) lockfile_contents['DEPENDENCIES'].delete_at(1)
lock_file_contents['PODS'].delete_at(1) lockfile_contents['PODS'].delete_at(1)
# lock_file_contents['PODS'][0] = 'ASIHTTPRequest (1.8.1)' # lockfile_contents['PODS'][0] = 'ASIHTTPRequest (1.8.1)'
end end
YAML.load(installer.lock_file.read).should == lock_file_contents installer.lockfile.to_dict.should == lockfile_contents
root = config.project_pods_root root = config.project_pods_root
(root + 'Pods.xcconfig').read.should == installer.target_installers.first.xcconfig.to_s (root + 'Pods.xcconfig').read.should == installer.target_installers.first.xcconfig.to_s
...@@ -320,10 +333,11 @@ else ...@@ -320,10 +333,11 @@ else
pod 'Reachability', '2.0.4' # only 2.0.4 is part of ASIHTTPRequest’s source. pod 'Reachability', '2.0.4' # only 2.0.4 is part of ASIHTTPRequest’s source.
end end
installer = SpecHelper::Installer.new(spec) resolver = Pod::Resolver.new(spec, nil, Pod::Sandbox.new(config.project_pods_root))
installer = SpecHelper::Installer.new(resolver)
installer.install! installer.install!
YAML.load(installer.lock_file.read).should == { installer.lockfile.to_dict.tap {|d| d.delete("COCOAPODS") }.should == {
# 'PODS' => [{ 'Reachability (2.0.4)' => ["ASIHTTPRequest (>= 1.8)"] }], # 'PODS' => [{ 'Reachability (2.0.4)' => ["ASIHTTPRequest (>= 1.8)"] }],
'PODS' => [ 'Reachability (2.0.4)' ], 'PODS' => [ 'Reachability (2.0.4)' ],
# 'DOWNLOAD_ONLY' => ["ASIHTTPRequest (1.8.1)"], # 'DOWNLOAD_ONLY' => ["ASIHTTPRequest (1.8.1)"],
...@@ -339,7 +353,8 @@ else ...@@ -339,7 +353,8 @@ else
pod 'SSZipArchive' pod 'SSZipArchive'
end end
installer = SpecHelper::Installer.new(spec) resolver = Pod::Resolver.new(spec, nil, Pod::Sandbox.new(config.project_pods_root))
installer = SpecHelper::Installer.new(resolver)
target_definition = installer.target_installers.first.target_definition target_definition = installer.target_installers.first.target_definition
installer.specs_by_target[target_definition].first.resources = 'LICEN*', 'Readme.*' installer.specs_by_target[target_definition].first.resources = 'LICEN*', 'Readme.*'
installer.install! installer.install!
...@@ -356,7 +371,8 @@ else ...@@ -356,7 +371,8 @@ else
xcodeproj 'dummy' xcodeproj 'dummy'
pod 'JSONKit' pod 'JSONKit'
end end
installer = SpecHelper::Installer.new(spec) resolver = Pod::Resolver.new(spec, nil, Pod::Sandbox.new(config.project_pods_root))
installer = SpecHelper::Installer.new(resolver)
installer.install! installer.install!
spec = Pod::Podfile.new do spec = Pod::Podfile.new do
...@@ -364,7 +380,8 @@ else ...@@ -364,7 +380,8 @@ else
xcodeproj 'dummy' xcodeproj 'dummy'
pod 'SSZipArchive' pod 'SSZipArchive'
end end
installer = SpecHelper::Installer.new(spec) resolver = Pod::Resolver.new(spec, nil, Pod::Sandbox.new(config.project_pods_root))
installer = SpecHelper::Installer.new(resolver)
installer.install! installer.install!
project = Pod::Project.new(config.project_pods_root + 'Pods.xcodeproj') project = Pod::Project.new(config.project_pods_root + 'Pods.xcodeproj')
...@@ -380,7 +397,9 @@ else ...@@ -380,7 +397,9 @@ else
pod 'ASIHTTPRequest' pod 'ASIHTTPRequest'
end end
installer = Pod::Installer.new(podfile) resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(fixture('integration')))
resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(config.project_pods_root))
installer = Pod::Installer.new(resolver)
installer.install! installer.install!
project = Xcodeproj::Project.new(config.project_pods_root + 'Pods.xcodeproj') project = Xcodeproj::Project.new(config.project_pods_root + 'Pods.xcodeproj')
...@@ -431,7 +450,8 @@ else ...@@ -431,7 +450,8 @@ else
pod 'SSZipArchive' pod 'SSZipArchive'
end end
installer = SpecHelper::Installer.new(podfile) resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(config.project_pods_root))
installer = SpecHelper::Installer.new(resolver)
installer.install! installer.install!
workspace = Xcodeproj::Workspace.new_from_xcworkspace(temporary_directory + 'ASIHTTPRequest.xcworkspace') workspace = Xcodeproj::Workspace.new_from_xcworkspace(temporary_directory + 'ASIHTTPRequest.xcworkspace')
...@@ -458,7 +478,8 @@ else ...@@ -458,7 +478,8 @@ else
pod 'ASIHTTPRequest' pod 'ASIHTTPRequest'
end end
installer = Pod::Installer.new(podfile) resolver = Pod::Resolver.new(podfile, nil, Pod::Sandbox.new(config.project_pods_root))
installer = Pod::Installer.new(resolver)
installer.install! installer.install!
root = config.project_pods_root root = config.project_pods_root
......
...@@ -14,7 +14,10 @@ module Pod ...@@ -14,7 +14,10 @@ module Pod
xcodeproj 'MyProject' xcodeproj 'MyProject'
pod 'JSONKit' pod 'JSONKit'
end end
@xcconfig = Installer.new(podfile).target_installers.first.xcconfig.to_hash
sandbox = Sandbox.new(fixture('integration'))
resolver = Resolver.new(podfile, nil, sandbox)
@xcconfig = Installer.new(resolver).target_installers.first.xcconfig.to_hash
end end
it "sets the header search paths where installed Pod headers can be found" do it "sets the header search paths where installed Pod headers can be found" do
...@@ -35,7 +38,10 @@ module Pod ...@@ -35,7 +38,10 @@ module Pod
platform :osx platform :osx
pod 'ASIHTTPRequest' pod 'ASIHTTPRequest'
end end
installer = Installer.new(podfile)
sandbox = Sandbox.new(fixture('integration'))
resolver = Resolver.new(podfile, nil, sandbox)
installer = Installer.new(resolver)
pods = installer.specifications.map do |spec| pods = installer.specifications.map do |spec|
LocalPod.new(spec, installer.sandbox, podfile.target_definitions[:default].platform) LocalPod.new(spec, installer.sandbox, podfile.target_definitions[:default].platform)
end end
...@@ -51,7 +57,8 @@ module Pod ...@@ -51,7 +57,8 @@ module Pod
pod 'JSONKit' pod 'JSONKit'
end end
end end
installer = Installer.new(podfile) resolver = Resolver.new(podfile, nil, Sandbox.new(fixture('integration')))
installer = Installer.new(resolver)
installer.target_installers.map(&:target_definition).map(&:name).should == [:not_empty] installer.target_installers.map(&:target_definition).map(&:name).should == [:not_empty]
end end
...@@ -61,7 +68,8 @@ module Pod ...@@ -61,7 +68,8 @@ module Pod
platform :ios platform :ios
xcodeproj path, 'App Store' => :release xcodeproj path, 'App Store' => :release
end end
installer = Installer.new(podfile) resolver = Resolver.new(podfile, nil, Sandbox.new(fixture('integration')))
installer = Installer.new(resolver)
installer.project.build_configurations.map(&:name).sort.should == ['App Store', 'Debug', 'Release', 'Test'] installer.project.build_configurations.map(&:name).sort.should == ['App Store', 'Debug', 'Release', 'Test']
end end
...@@ -70,7 +78,8 @@ module Pod ...@@ -70,7 +78,8 @@ module Pod
platform :ios platform :ios
pod 'JSONKit', :head pod 'JSONKit', :head
end end
installer = Installer.new(podfile) resolver = Resolver.new(podfile, nil, Sandbox.new(fixture('integration')))
installer = Installer.new(resolver)
pod = installer.pods.first pod = installer.pods.first
downloader = stub('Downloader') downloader = stub('Downloader')
......
require File.expand_path('../../spec_helper', __FILE__)
describe "Pod::Lockfile" do
extend SpecHelper::TemporaryDirectory
def sample
text = <<-LOCKFILE.strip_heredoc
---
PODS:
- BananaLib (1.0):
- monkey (< 1.0.9, ~> 1.0.1)
- monkey (1.0.8)
DEPENDENCIES:
- BananaLib (~> 1.0)
COCOAPODS: #{Pod::VERSION}
LOCKFILE
end
def podfile
Pod::Podfile.new do
platform :ios
pod 'BananaLib', '~>1.0'
end
end
def specs
specs = [
Pod::Specification.from_file(fixture('banana-lib/BananaLib.podspec')),
Pod::Specification.new do |s|
s.name = "monkey"
s.version = "1.0.8"
end
]
specs.each { |s| s.activate_platform(:ios) }
specs
end
def tmp_path
temporary_directory + 'Podfile.lock'
end
it "loads from a file" do
File.open(tmp_path, 'w') {|f| f.write(sample) }
lockfile = Pod::Lockfile.from_file(tmp_path)
lockfile.defined_in_file.should == tmp_path
lockfile.to_yaml.should == sample
end
before do
@lockfile = Pod::Lockfile.create(tmp_path, podfile, specs)
end
it "generates a valid YAML representation" do
@lockfile.to_yaml.should == sample
end
it "generates a valid Dictionary representation" do
@lockfile.to_dict.should == YAML.load(sample)
end
it "returns the Podfile dependencies" do
@lockfile.podfile_dependencies.should == [
Pod::Dependency.new("BananaLib", "~> 1.0")
]
end
it "returns the dependencies for the installed pods" do
@lockfile.installed_dependencies.should == [
Pod::Dependency.new("BananaLib", "= 1.0"),
Pod::Dependency.new("monkey", "= 1.0.8")
]
end
it "can check if it is compatible with a file" do
File.open(tmp_path, 'w') {|f| f.write(sample.gsub("COCOAPODS: #{Pod::VERSION}", "")) }
lockfile = Pod::Lockfile.from_file(tmp_path)
lockfile.to_dict.should == nil
end
it "serializes correctly `:head' dependencies" do
podfile = Pod::Podfile.new do
platform :ios
pod 'BananaLib', :head
end
specs = [
Pod::Specification.new do |s|
s.name = "BananaLib"
s.version = "1.0"
end,
Pod::Specification.new do |s|
s.name = "monkey"
s.version = "1.0.8"
end
]
specs.each { |s| s.activate_platform(:ios) }
lockfile = Pod::Lockfile.create(tmp_path, podfile, specs)
lockfile.to_dict["DEPENDENCIES"][0].should == "BananaLib [HEAD]"
end
it "serializes correctly external dependencies" do
podfile = Pod::Podfile.new do
platform :ios
pod 'BananaLib', :git => "www.example.com"
end
specs = [
Pod::Specification.new do |s|
s.name = "BananaLib"
s.version = "1.0"
end,
Pod::Specification.new do |s|
s.name = "monkey"
s.version = "1.0.8"
end
]
specs.each { |s| s.activate_platform(:ios) }
lockfile = Pod::Lockfile.create(tmp_path, podfile, specs)
lockfile.to_dict["DEPENDENCIES"][0].should == "BananaLib (from `www.example.com')"
end
xit "reads `:heads' dependencies correctly" do
end
xit "reads external dependencies dependencies correctly" do
end
end
...@@ -10,7 +10,7 @@ module Pod ...@@ -10,7 +10,7 @@ module Pod
pod 'BlocksKit' pod 'BlocksKit'
# pod 'ASIWebPageRequest' # pod 'ASIWebPageRequest'
end end
@resolver = Resolver.new(@podfile, stub('sandbox')) @resolver = Resolver.new(@podfile, nil, stub('sandbox'))
end end
it "holds the context state, such as cached specification sets" do it "holds the context state, such as cached specification sets" do
...@@ -73,7 +73,7 @@ module Pod ...@@ -73,7 +73,7 @@ module Pod
pod 'RestKit/Network' pod 'RestKit/Network'
pod 'RestKit/ObjectMapping/XML' pod 'RestKit/ObjectMapping/XML'
end end
resolver = Resolver.new(@podfile, stub('sandbox')) resolver = Resolver.new(@podfile, nil, stub('sandbox'))
resolver.resolve.values.flatten.map(&:name).sort.should == %w{ resolver.resolve.values.flatten.map(&:name).sort.should == %w{
FileMD5Hash FileMD5Hash
ISO8601DateFormatter ISO8601DateFormatter
...@@ -93,7 +93,7 @@ module Pod ...@@ -93,7 +93,7 @@ module Pod
platform :ios platform :ios
pod 'RestKit' pod 'RestKit'
end end
resolver = Resolver.new(@podfile, stub('sandbox')) resolver = Resolver.new(@podfile, nil, stub('sandbox'))
resolver.resolve.values.flatten.map(&:name).sort.should == %w{ resolver.resolve.values.flatten.map(&:name).sort.should == %w{
FileMD5Hash FileMD5Hash
ISO8601DateFormatter ISO8601DateFormatter
...@@ -139,7 +139,7 @@ module Pod ...@@ -139,7 +139,7 @@ module Pod
end end
end end
end end
resolver = Resolver.new(@podfile, stub('sandbox')) resolver = Resolver.new(@podfile, nil, stub('sandbox'))
specs = resolver.resolve.values.flatten.map(&:name).sort specs = resolver.resolve.values.flatten.map(&:name).sort
specs.should.not.include 'RestKit/ObjectMapping/XML' specs.should.not.include 'RestKit/ObjectMapping/XML'
specs.should == %w{ specs.should == %w{
...@@ -175,7 +175,7 @@ module Pod ...@@ -175,7 +175,7 @@ module Pod
end end
end end
@podfile.dependencies.first.external_source.stubs(:specification_from_sandbox).returns(spec) @podfile.dependencies.first.external_source.stubs(:specification_from_sandbox).returns(spec)
resolver = Resolver.new(@podfile, stub('sandbox')) resolver = Resolver.new(@podfile, nil, stub('sandbox'))
resolver.resolve.values.flatten.map(&:name).sort.should == %w{ MainSpec/FirstSubSpec MainSpec/FirstSubSpec/SecondSubSpec } resolver.resolve.values.flatten.map(&:name).sort.should == %w{ MainSpec/FirstSubSpec MainSpec/FirstSubSpec/SecondSubSpec }
end end
...@@ -185,10 +185,48 @@ module Pod ...@@ -185,10 +185,48 @@ module Pod
pod 'FileMD5Hash' pod 'FileMD5Hash'
pod 'JSONKit', :head pod 'JSONKit', :head
end end
resolver = Resolver.new(podfile, stub('sandbox')) resolver = Resolver.new(podfile, nil, stub('sandbox'))
filemd5hash, jsonkit = resolver.resolve.values.first.sort_by(&:name) filemd5hash, jsonkit = resolver.resolve.values.first.sort_by(&:name)
filemd5hash.version.should.not.be.head filemd5hash.version.should.not.be.head
jsonkit.version.should.be.head jsonkit.version.should.be.head
end end
xit "raises if it finds two conflicting dependencies" do
end
describe "Concerning the Lockfile" do
xit "accepts a nil lockfile" do
lambda { Resolver.new(@podfile, nil, stub('sandbox'))}.should.not.raise
end
xit "detects the pods that need to be installed" do
end
xit "detects the pods that don't need to be installed" do
end
xit "detects the pods that can be updated" do
end
xit "doesn't install new pods in `update_mode'" do
end
xit "handles correctly pods with external source" do
end
xit "it always suggest to update pods in head mode" do
end
xit "it prevents a pod from upgrading during an install" do
end
end
end end
end end
...@@ -14,23 +14,23 @@ describe "Pod::Specification::Set" do ...@@ -14,23 +14,23 @@ describe "Pod::Specification::Set" do
end end
it "checks if the dependency of the specification is compatible with existing requirements" do it "checks if the dependency of the specification is compatible with existing requirements" do
@set.required_by(Pod::Spec.new { |s| s.dependency 'CocoaLumberjack', '1.2' }) @set.required_by(Pod::Dependency.new('CocoaLumberjack', '1.2'), 'Spec')
@set.required_by(Pod::Spec.new { |s| s.dependency 'CocoaLumberjack', '< 1.2.1' }) @set.required_by(Pod::Dependency.new('CocoaLumberjack', '< 1.2.1'), 'Spec')
@set.required_by(Pod::Spec.new { |s| s.dependency 'CocoaLumberjack', '> 1.1' }) @set.required_by(Pod::Dependency.new('CocoaLumberjack', '> 1.1'), 'Spec')
@set.required_by(Pod::Spec.new { |s| s.dependency 'CocoaLumberjack', '~> 1.2.0' }) @set.required_by(Pod::Dependency.new('CocoaLumberjack', '~> 1.2.0'), 'Spec')
@set.required_by(Pod::Spec.new { |s| s.dependency 'CocoaLumberjack' }) @set.required_by(Pod::Dependency.new('CocoaLumberjack'), 'Spec')
lambda { lambda {
@set.required_by(Pod::Spec.new { |s| s.dependency 'CocoaLumberjack', '< 1.0' }) @set.required_by(Pod::Dependency.new('CocoaLumberjack', '< 1.0' ), 'Spec')
}.should.raise Pod::Informative }.should.raise Pod::Informative
end end
it "raises if the required version doesn't exist" do it "raises if the required version doesn't exist" do
@set.required_by(Pod::Spec.new { |s| s.dependency 'CocoaLumberjack', '< 1.0' }) @set.required_by(Pod::Dependency.new('CocoaLumberjack', '< 1.0'), 'Spec')
lambda { @set.required_version }.should.raise Pod::Informative lambda { @set.required_version }.should.raise Pod::Informative
end end
before do before do
@set.required_by(Pod::Spec.new { |s| s.dependency 'CocoaLumberjack', '< 1.2.1' }) @set.required_by(Pod::Dependency.new('CocoaLumberjack', '< 1.2.1'), 'Spec')
end end
it "returns the version required for the dependency" do it "returns the version required for the dependency" do
...@@ -49,4 +49,9 @@ describe "Pod::Specification::Set" do ...@@ -49,4 +49,9 @@ describe "Pod::Specification::Set" do
`touch #{fixture('spec-repos/master/CocoaLumberjack/.DS_Store')}` `touch #{fixture('spec-repos/master/CocoaLumberjack/.DS_Store')}`
lambda { @set.versions }.should.not.raise lambda { @set.versions }.should.not.raise
end end
it "raises if a version is incompatible with the activated version" do
spec = Pod::Dependency.new('CocoaLumberjack', '1.2.1')
lambda { @set.required_by(spec, 'Spec') }.should.raise Pod::Informative
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