Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
C
cocoapods
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gengmeiios
cocoapods
Commits
1baebf67
Commit
1baebf67
authored
Nov 24, 2012
by
Fabio Pelosin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Resolver] Clean-up and specs update.
parent
ff745f82
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
510 additions
and
485 deletions
+510
-485
resolver.rb
lib/cocoapods/resolver.rb
+163
-96
resolver_spec.rb
spec/unit/resolver_spec.rb
+347
-389
No files found.
lib/cocoapods/resolver.rb
View file @
1baebf67
...
@@ -5,186 +5,253 @@ module Pod
...
@@ -5,186 +5,253 @@ module Pod
#
#
# Its current implementation is naive, in the sense that it can't do full
# Its current implementation is naive, in the sense that it can't do full
# automatic resolves like Bundler:
# automatic resolves like Bundler:
#
# [how-does-bundler-bundle](http://patshaughnessy.net/2011/9/24/how-does-bundler-bundle)
# http://patshaughnessy.net/2011/9/24/how-does-bundler-bundle
#
#
# Another important aspect to keep in mind of the current implementation
# Another important aspect to keep in mind of the current implementation
# is that the order of the dependencies matters.
# is that the order of the dependencies matters.
#
#
class
Resolver
class
Resolver
include
Config
::
Mixin
include
Config
::
Mixin
# @return [Sandbox]
T
he Sandbox used by the resolver to find external
# @return [Sandbox]
t
he Sandbox used by the resolver to find external
# dependencies.
#
dependencies.
#
#
attr_reader
:sandbox
attr_reader
:sandbox
# @return [Podfile]
T
he Podfile used by the resolver.
# @return [Podfile]
t
he Podfile used by the resolver.
#
#
attr_reader
:podfile
attr_reader
:podfile
# @return [Array<Dependency>]
T
he list of dependencies locked to a specific
# @return [Array<Dependency>]
t
he list of dependencies locked to a specific
# version.
#
version.
#
#
attr_reader
:locked_dependencies
attr_reader
:locked_dependencies
# @return [Bool]
W
hether the resolver should update the external specs
# @return [Bool]
w
hether the resolver should update the external specs
#
in the resolution process. This option is used for detecting changes
#
in the resolution process. This option is used for detecting
#
in with the Podfile without affecting the existing Pods installation
#
changes in with the Podfile without affecting the existing Pods
#
(see `pod outdated`).
#
installation
#
#
# @TODO: This implementation is not clean, because if the spec doesn't
# @note This option is used by `pod outdated`.
# exists the sandbox will actually download it and result modified.
#
# @TODO: This implementation is not clean, because if the spec doesn't
# exists the sandbox will actually download and modify the
# installation.
#
#
attr_accessor
:update_external_specs
attr_accessor
:update_external_specs
# @param [Sandbox] sandbox @see sandbox
# @param [Podfile] podfile @see podfile
# @param [Array<Dependency>] locked_dependencies @see locked_dependencies
#
def
initialize
(
sandbox
,
podfile
,
locked_dependencies
=
[])
def
initialize
(
sandbox
,
podfile
,
locked_dependencies
=
[])
@sandbox
=
sandbox
@sandbox
=
sandbox
@podfile
=
podfile
@podfile
=
podfile
@locked_dependencies
=
locked_dependencies
@locked_dependencies
=
locked_dependencies
end
end
# @return [Hash{Podfile::TargetDefinition => Array<Specification>}]
#-------------------------------------------------------------------------#
# Returns the resolved specifications grouped by target.
#
attr_reader
:specs_by_target
# @return [Array<Specification>] All The specifications loaded by the
# @!group Resolution
# resolver.
#
def
specs
@cached_specs
.
values
.
uniq
end
# @return [Array<Strings>] The name of the pods that have an
public
# external source.
#
# @TODO: Add an attribute to the specification class?
#
attr_reader
:pods_from_external_sources
# Identifies the specifications that should be installed.
#
# @return [Hash{TargetDefinition => Array<Specification>}] specs_by_target
# @return [Hash{TargetDefinition => Array<Specification>}] specs_by_target
#
Identifies the specifications that should be installed according
#
the specifications that need to be installed grouped by target
#
whether the resolver is in update mode or not
.
#
definition
.
#
#
def
resolve
def
resolve
@cached_sources
=
Source
::
Aggregate
.
new
(
config
.
repos_dir
)
@cached_sources
=
Source
::
Aggregate
.
new
(
config
.
repos_dir
)
@cached_sets
=
{}
@cached_sets
=
{}
@cached_specs
=
{}
@cached_specs
=
{}
@specs_by_target
=
{}
@specs_by_target
=
{}
@pods_from_external_sources
=
[]
#
@pods_from_external_sources = []
podfile
.
target_definitions
.
values
.
each
do
|
target
_definition
|
podfile
.
target_definitions
.
values
.
each
do
|
target
|
UI
.
section
"Resolving dependencies for target `
#{
target
_definition
.
name
}
' (
#{
target_definition
.
platform
}
)"
do
UI
.
section
"Resolving dependencies for target `
#{
target
.
name
}
' (
#{
target
.
platform
}
)"
do
@loaded_specs
=
[]
@loaded_specs
=
[]
find_dependency_specs
(
podfile
,
target_definition
.
dependencies
,
target_definition
)
find_dependency_specs
(
podfile
,
target
.
dependencies
,
target
)
@specs_by_target
[
target_definition
]
=
@cached_specs
.
values_at
(
*
@loaded_specs
).
sort_by
(
&
:name
)
specs
=
cached_specs
.
values_at
(
*
@loaded_specs
).
sort_by
(
&
:name
)
specs_by_target
[
target
]
=
specs
end
end
end
end
@
cached_specs
.
values
.
sort_by
(
&
:name
)
cached_specs
.
values
.
sort_by
(
&
:name
)
@
specs_by_target
specs_by_target
end
end
#-----------------------------------------------------------------------#
# @return [Hash{Podfile::TargetDefinition => Array<Specification>}]
# returns the resolved specifications grouped by target.
#
# @note The returned specifications can be subspecs.
#
attr_reader
:specs_by_target
private
# @return [Array<Specification>] All the specifications resolved.
#
def
specs
specs_by_target
.
values
.
flatten
.
uniq
end
# @return [Array<Set>] A cache of the sets used to resolve the dependencies.
# @return [Array<Strings>] The name of the pods that have an
# external source.
#
# TODO: Not sure if needed.
#
#
attr_reader
:cached_set
s
# attr_reader :pods_from_external_source
s
#-------------------------------------------------------------------------#
# !@ Resolution context
private
# @return [Source::Aggregate] A cache of the sources needed to find the
# @return [Source::Aggregate] A cache of the sources needed to find the
# podspecs.
# podspecs.
#
# TODO: Cache the sources globally?
#
attr_accessor
:cached_sources
# @return [Hash<String => Set>] A cache that keeps tracks of the sets
# loaded by the resolution process.
#
# @note Sets keep track of the TODO:
#
#
attr_
reader
:cached_source
s
attr_
accessor
:cached_set
s
# @return [void] Resolves recursively the dependencies of a specification
# and stores them in @cached_specs
#
#
# @param [Specification] dependent_specification
# The specification whose dependencies are being resolved.
#
#
# @param [Array<Dependency>] dependencies
attr_accessor
:cached_specs
# The dependencies of the specification.
#
#
attr_writer
:specs_by_target
#-------------------------------------------------------------------------#
# !@ Resolution helpers
private
# Resolves recursively the dependencies of a specification and stores them
# in the @cached_specs ivar.
#
# @param [Podfile, Specification] dependent_spec
# the specification whose dependencies are being resolved.
#
# @param [Array<Dependency>] dependencies
# the dependencies of the specification.
#
# @param [TargetDefinition] target_definition
# the target definition that owns the specification.
#
# @note If there is a locked dependency with the same name of a
# given dependency the locked one is used in place of the
# dependency of the specification. In this way it is possible to
# not updated the installed pods without without introducing
# dependencies in other target definitions.
# TODO: Just add the requirement to the set?
# TODO: Use root name?
#
# @note The recursive process checks if a dependency has already been
# loaded to prevent an infinite loop. For this reason the
# @loaded_specs ivar must be cleaned when changing target
# definition.
#
#
# TODO: The set class should be aware whether it is in head mode.
#
#
# @param [TargetDefinition] target_definition
# @return [void]
# The target definition that owns the specification.
#
#
def
find_dependency_specs
(
dependent_spec
ification
,
dependencies
,
target_definition
)
def
find_dependency_specs
(
dependent_spec
,
dependencies
,
target_definition
)
dependencies
.
each
do
|
dependency
|
dependencies
.
each
do
|
dependency
|
# Replace the dependency with a more specific one if the pod is already
locked_dep
=
locked_dependencies
.
find
{
|
ld
|
ld
.
name
==
dependency
.
name
}
# installed.
# @TODO: check for compatibility?
locked_dep
=
locked_dependencies
.
find
{
|
locked
|
locked
.
name
==
dependency
.
name
}
dependency
=
locked_dep
if
locked_dep
dependency
=
locked_dep
if
locked_dep
UI
.
message
(
"-
#{
dependency
}
"
,
''
,
2
)
do
UI
.
message
(
"-
#{
dependency
}
"
,
''
,
2
)
do
set
=
find_cached_set
(
dependency
,
target_definition
.
platform
)
set
=
find_cached_set
(
dependency
,
target_definition
.
platform
)
set
.
required_by
(
dependency
,
dependent_spec
ification
.
to_s
)
set
.
required_by
(
dependency
,
dependent_spec
.
to_s
)
# Ensure we don't resolve the same spec twice for one target
unless
@loaded_specs
.
include?
(
dependency
.
name
)
if
@loaded_specs
.
include?
(
dependency
.
name
)
validate_platform
(
@cached_specs
[
dependency
.
name
],
target_definition
)
else
spec
=
set
.
specification
.
subspec_by_name
(
dependency
.
name
)
spec
=
set
.
specification
.
subspec_by_name
(
dependency
.
name
)
@pods_from_external_sources
<<
spec
.
pod_name
if
dependency
.
external?
@loaded_specs
<<
spec
.
name
@loaded_specs
<<
spec
.
name
@cached_specs
[
spec
.
name
]
=
spec
cached_specs
[
spec
.
name
]
=
spec
# Configure the specification
# @pods_from_external_sources << spec.root_name if dependency.external?
validate_platform
(
spec
,
target_definition
)
spec
.
activate_platform
(
target_definition
.
platform
)
spec
.
activate_platform
(
target_definition
.
platform
)
spec
.
version
.
head
=
dependency
.
head?
spec
.
version
.
head
=
dependency
.
head?
# And recursively load the dependencies of the spec.
find_dependency_specs
(
spec
,
spec
.
dependencies
,
target_definition
)
validate_platform
(
spec
,
target_definition
)
find_dependency_specs
(
spec
,
spec
.
dependencies
,
target_definition
)
end
end
end
end
end
end
end
end
# @return [Set] The cached set for a given dependency.
# Loads or returns a previously initialized {Set} for the given dependency.
#
# @param [Dependency] dependency
# the dependency for which the set is needed.
# TODO: check dependency.specification
#
# @param [Platform] platform
# the platform on which the dependency is needed this is used by
# the sandbox to locate external sources.
# TODO why?
#
# @note If the {#update_external_specs} flag is activated the
# dependencies with external sources are always resolved against
# the remote. Otherwise the specification is retrieved from the
# sandbox that fetches the external source only if needed.
#
# TODO If the set is loaded from a normal source and then from an
# external one that information is lost.
#
#
# If the update_external_specs flag is activated the dependencies with
# @return [Set] the cached set for a given dependency.
# external sources are always resolved against the remote. Otherwise the
# specification is retrieved from the sandbox that fetches the external
# source only if needed.
#
#
def
find_cached_set
(
dependency
,
platform
)
def
find_cached_set
(
dependency
,
platform
)
set_name
=
dependency
.
name
.
split
(
'/'
).
first
name
=
dependency
.
root_name
@cached_sets
[
set_name
]
||=
begin
unless
cached_sets
[
name
]
if
dependency
.
specification
if
dependency
.
specification
Specification
::
Set
::
External
.
new
(
dependency
.
specification
)
set
=
Specification
::
Set
::
External
.
new
(
dependency
.
specification
)
elsif
external_source
=
dependency
.
external_source
elsif
dependency
.
external_source
if
update_external_specs
set
=
set_from_external_source
(
dependency
,
platform
)
external_source
=
ExternalSources
.
from_dependency
(
dependency
)
spec
=
external_source
.
specification_from_external
(
@sandbox
,
platform
)
else
external_source
=
ExternalSources
.
from_dependency
(
dependency
)
spec
=
external_source
.
specification_from_sandbox
(
@sandbox
,
platform
)
end
set
=
Specification
::
Set
::
External
.
new
(
spec
)
if
dependency
.
subspec_dependency?
@cached_sets
[
dependency
.
root_name
]
||=
set
end
set
else
else
cached_sources
.
search
(
dependency
)
set
=
cached_sources
.
search
(
dependency
)
end
end
cached_sets
[
name
]
=
set
end
end
cached_sets
[
name
]
end
end
# @return [void] Ensures that a spec is compatible with the platform of a
# Returns a new set created from an external source
# target.
#
def
set_from_external_source
(
dependency
,
platform
)
source
=
ExternalSources
.
from_dependency
(
dependency
)
spec
=
if
update_external_specs
source
.
specification_from_external
(
@sandbox
,
platform
)
else
source
.
specification_from_sandbox
(
@sandbox
,
platform
)
end
set
=
Specification
::
Set
::
External
.
new
(
spec
)
set
end
# Ensures that a spec is compatible with the platform of a target.
#
#
# @raises If the spec is not supported by the target.
# @raises If the spec is not supported by the target.
#
#
# @return [void]
#
def
validate_platform
(
spec
,
target
)
def
validate_platform
(
spec
,
target
)
unless
spec
.
available_platforms
.
any?
{
|
p
latform
|
target
.
platform
.
supports?
(
platform
)
}
unless
spec
.
available_platforms
.
any?
{
|
p
|
target
.
platform
.
supports?
(
p
)
}
raise
Informative
,
"The platform of the target `
#{
target
.
name
}
' "
\
raise
Informative
,
"The platform of the target `
#{
target
.
name
}
` "
\
"(
#{
target
.
platform
}
) is not compatible with `
#{
spec
}
' which "
\
"(
#{
target
.
platform
}
) is not compatible with `
#{
spec
}
` which has "
\
"
has
a minimum requirement of
#{
spec
.
available_platforms
.
join
(
' - '
)
}
."
"a minimum requirement of
#{
spec
.
available_platforms
.
join
(
' - '
)
}
."
end
end
end
end
end
end
...
...
spec/unit/resolver_spec.rb
View file @
1baebf67
...
@@ -2,450 +2,408 @@ require File.expand_path('../../spec_helper', __FILE__)
...
@@ -2,450 +2,408 @@ require File.expand_path('../../spec_helper', __FILE__)
module
Pod
module
Pod
describe
Resolver
do
describe
Resolver
do
before
do
describe
"In general"
do
config
.
repos_dir
=
fixture
(
'spec-repos'
)
@podfile
=
Podfile
.
new
do
platform
:ios
pod
'BlocksKit'
,
'1.5.2'
end
@resolver
=
Resolver
.
new
(
config
.
sandbox
,
@podfile
)
end
it
"holds the context state, such as cached specification sets"
do
@resolver
.
resolve
cached_sets
=
@resolver
.
send
(
:cached_sets
)
cached_sets
.
values
.
sort_by
(
&
:name
).
should
==
[
Source
.
search_by_name
(
'A2DynamicDelegate'
).
first
,
Source
.
search_by_name
(
'BlocksKit'
).
first
,
Source
.
search_by_name
(
'libffi'
).
first
].
sort_by
(
&
:name
)
end
it
"returns all specs needed for the dependency"
do
specs
=
@resolver
.
resolve
.
values
.
flatten
specs
.
map
(
&
:class
).
uniq
.
should
==
[
Specification
]
specs
.
map
(
&
:name
).
sort
.
should
==
%w{ A2DynamicDelegate BlocksKit libffi }
end
it
"does not raise if all dependencies match the platform of the root spec (Podfile)"
do
@podfile
.
platform
:ios
,
'6.0'
lambda
{
@resolver
.
resolve
}.
should
.
not
.
raise
@podfile
.
platform
:osx
,
'10.7'
lambda
{
@resolver
.
resolve
}.
should
.
not
.
raise
end
it
"raises once any of the dependencies does not match the platform of its podfile target"
do
set
=
Source
.
search_by_name
(
'BlocksKit'
).
first
cached_sets
=
@resolver
.
send
(
:cached_sets
)
@resolver
.
stubs
(
:cached_sets
).
returns
({
'BlocksKit'
=>
set
})
def
set
.
stub_platform
=
(
platform
);
@stubbed_platform
=
platform
;
end
def
set
.
specification
;
spec
=
super
;
spec
.
platform
=
@stubbed_platform
;
spec
;
end
@podfile
.
platform
:ios
set
.
stub_platform
=
:ios
lambda
{
@resolver
.
resolve
}.
should
.
not
.
raise
set
.
stub_platform
=
:osx
lambda
{
@resolver
.
resolve
}.
should
.
raise
Pod
::
StandardError
@podfile
.
platform
:osx
set
.
stub_platform
=
:osx
lambda
{
@resolver
.
resolve
}.
should
.
not
.
raise
set
.
stub_platform
=
:ios
lambda
{
@resolver
.
resolve
}.
should
.
raise
Pod
::
StandardError
end
it
"raises once any of the dependencies does not have a deployment_target compatible with its podfile target"
do
set
=
Source
.
search_by_name
(
'BlocksKit'
).
first
@resolver
.
stubs
(
:cached_sets
).
returns
({
'BlocksKit'
=>
set
})
@podfile
.
platform
:ios
,
"4.0"
Specification
.
any_instance
.
stubs
(
:available_platforms
).
returns
([
Platform
.
new
(
:ios
,
'4.0'
),
Platform
.
new
(
:osx
,
'10.7'
)
])
lambda
{
@resolver
.
resolve
}.
should
.
not
.
raise
Specification
.
any_instance
.
stubs
(
:available_platforms
).
returns
([
Platform
.
new
(
:ios
,
'5.0'
),
Platform
.
new
(
:osx
,
'10.7'
)
])
lambda
{
@resolver
.
resolve
}.
should
.
raise
Pod
::
StandardError
end
it
"resolves subspecs"
do
@podfile
=
Podfile
.
new
do
platform
:ios
pod
'RestKit/Network'
pod
'RestKit/ObjectMapping/XML'
end
resolver
=
Resolver
.
new
(
@podfile
,
nil
,
stub
(
'sandbox'
))
resolver
.
resolve
.
values
.
flatten
.
map
(
&
:name
).
sort
.
should
==
%w{
FileMD5Hash
ISO8601DateFormatter
LibComponentLogging-Core
LibComponentLogging-NSLog
NSData+Base64
RestKit/Network
RestKit/ObjectMapping/XML
SOCKit
XMLReader
cocoa-oauth
}
end
it
"includes all the subspecs of a specification node"
do
@podfile
=
Podfile
.
new
do
platform
:ios
pod
'RestKit'
end
resolver
=
Resolver
.
new
(
@podfile
,
nil
,
stub
(
'sandbox'
))
resolver
.
resolve
.
values
.
flatten
.
map
(
&
:name
).
sort
.
should
==
%w{
FileMD5Hash
ISO8601DateFormatter
JSONKit
LibComponentLogging-Core
LibComponentLogging-NSLog
NSData+Base64
RestKit
RestKit/JSON
RestKit/Network
RestKit/ObjectMapping/CoreData
RestKit/ObjectMapping/JSON
RestKit/UI
SOCKit
cocoa-oauth
}
end
# TODO inline podspecs are deprecated
xit
"it includes only the main subspec of a specification node"
do
spec
=
Spec
.
new
do
|
s
|
s
.
name
=
'RestKit'
s
.
version
=
'9999990.10.0'
s
.
preferred_dependency
=
'JSON'
s
.
subspec
'JSON'
do
|
js
|
js
.
dependency
'RestKit/Network'
js
.
dependency
'RestKit/UI'
js
.
dependency
'RestKit/ObjectMapping/JSON'
js
.
dependency
'RestKit/ObjectMapping/CoreData'
end
s
.
subspec
'Network'
do
|
ns
|
ns
.
dependency
'LibComponentLogging-NSLog'
,
'>= 1.0.4'
end
s
.
subspec
'UI'
s
.
subspec
'ObjectMapping'
do
|
os
|
os
.
subspec
'JSON'
os
.
subspec
'XML'
os
.
subspec
'CoreData'
end
end
@podfile
=
Podfile
.
new
do
platform
:ios
pod
'RestKit'
end
Set
.
any_instance
.
stubs
(
:specification
).
returns
(
spec
)
resolver
=
Resolver
.
new
(
@podfile
,
nil
,
stub
(
'sandbox'
))
resolver
.
find_cached_set
()
specs
=
resolver
.
resolve
.
values
.
flatten
.
map
(
&
:name
).
sort
specs
.
should
.
not
.
include
'RestKit/ObjectMapping/XML'
spec
=
resolver
.
specs_by_target
.
values
.
first
.
first
spec
.
name
.
should
==
'test'
spec
.
version
.
should
==
'9999990.10.0'
specs
.
should
==
%w{
LibComponentLogging-Core
LibComponentLogging-NSLog
RestKit
RestKit/JSON
RestKit/Network
RestKit/ObjectMapping/CoreData
RestKit/ObjectMapping/JSON
RestKit/UI
}
end
it
"resolves subspecs with external constraints"
do
@podfile
=
Podfile
.
new
do
platform
:ios
pod
'MainSpec/FirstSubSpec'
,
:git
=>
'GIT-URL'
end
spec
=
Spec
.
new
do
|
s
|
s
.
name
=
'MainSpec'
s
.
version
=
'1.2.3'
s
.
platform
=
:ios
s
.
license
=
'MIT'
s
.
author
=
'Joe the Plumber'
s
.
summary
=
'A spec with subspecs'
s
.
source
=
{
:git
=>
'/some/url'
}
s
.
requires_arc
=
true
s
.
subspec
'FirstSubSpec'
do
|
fss
|
fss
.
source_files
=
'some/file'
fss
.
subspec
'SecondSubSpec'
end
end
ExternalSources
::
GitSource
.
any_instance
.
stubs
(
:specification_from_sandbox
).
returns
(
spec
)
resolver
=
Resolver
.
new
(
@podfile
,
nil
,
stub
(
'sandbox'
))
resolver
.
resolve
.
values
.
flatten
.
map
(
&
:name
).
sort
.
should
==
%w{ MainSpec/FirstSubSpec MainSpec/FirstSubSpec/SecondSubSpec }
end
it
"marks a specification's version to be a `bleeding edge' version"
do
podfile
=
Podfile
.
new
do
platform
:ios
pod
'FileMD5Hash'
pod
'JSONKit'
,
:head
end
resolver
=
Resolver
.
new
(
podfile
,
nil
,
stub
(
'sandbox'
))
filemd5hash
,
jsonkit
=
resolver
.
resolve
.
values
.
first
.
sort_by
(
&
:name
)
filemd5hash
.
version
.
should
.
not
.
be
.
head
jsonkit
.
version
.
should
.
be
.
head
end
it
"accepts a nil lockfile"
do
lambda
{
Resolver
.
new
(
@podfile
,
nil
,
stub
(
'sandbox'
))}.
should
.
not
.
raise
end
it
"raises if it finds two conflicting dependencies"
do
podfile
=
Podfile
.
new
do
platform
:ios
pod
'JSONKit'
,
"1.4"
pod
'JSONKit'
,
"1.5pre"
end
resolver
=
Resolver
.
new
(
podfile
,
nil
,
stub
(
'sandbox'
))
lambda
{
resolver
.
resolve
}.
should
.
raise
Pod
::
StandardError
end
describe
"Concerning Installation mode"
do
before
do
before
do
config
.
repos_dir
=
fixture
(
'spec-repos'
)
config
.
repos_dir
=
fixture
(
'spec-repos'
)
@podfile
=
Podfile
.
new
do
@podfile
=
Podfile
.
new
do
platform
:ios
platform
:ios
pod
'BlocksKit'
,
'1.5.2'
pod
'BlocksKit'
,
'1.5.2'
pod
'JSONKit'
end
end
@specs
=
[
locked_deps
=
[
Dependency
.
new
(
'BlocksKit'
,
'1.5.2'
)]
Specification
.
new
do
|
s
|
@resolver
=
Resolver
.
new
(
config
.
sandbox
,
@podfile
,
locked_deps
)
s
.
name
=
"BlocksKit"
s
.
version
=
"1.5.2"
end
,
Specification
.
new
do
|
s
|
s
.
name
=
"JSONKit"
s
.
version
=
"1.4"
end
]
@specs
.
each
{
|
s
|
s
.
activate_platform
(
:ios
)
}
@lockfile
=
Lockfile
.
generate
(
@podfile
,
@specs
)
@resolver
=
Resolver
.
new
(
@podfile
,
@lockfile
,
stub
(
'sandbox'
))
end
end
it
"doesn't install pods still compatible with the Podfile"
do
it
"returns the sandbox"
do
@resolver
.
resolve
@resolver
.
sandbox
.
should
==
config
.
sandbox
@resolver
.
should_install?
(
"BlocksKit"
).
should
.
be
.
false
@resolver
.
should_install?
(
"JSONKit"
).
should
.
be
.
false
end
end
it
"doesn't update the version of pods still compatible with the Podfile"
do
it
"returns the podfile"
do
installed
=
@resolver
.
resolve
.
values
.
flatten
.
map
(
&
:to_s
)
@resolver
.
podfile
.
should
==
@podfile
installed
.
should
.
include?
"JSONKit (1.4)"
end
end
it
"doesn't include pods removed from the Podfile"
do
it
"returns the locked dependencies"
do
podfile
=
Podfile
.
new
{
platform
:ios
;
pod
'JSONKit'
}
@resolver
.
locked_dependencies
.
should
==
[
Dependency
.
new
(
'BlocksKit'
,
'1.5.2'
)]
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
@resolver
.
resolve
.
values
.
flatten
.
map
(
&
:name
).
should
==
%w{ JSONKit }
end
end
it
"reinstalls pods updated in the Podfile"
do
it
"allows to specify whether the external sources should be updated against the remote"
do
podfile
=
Podfile
.
new
do
# TODO
platform
:ios
@resolver
.
update_external_specs
=
true
pod
'JSONKit'
,
'1.5pre'
@resolver
.
update_external_specs
.
should
.
be
.
true
pod
'BlocksKit'
,
'1.5.2'
end
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
installed
=
@resolver
.
resolve
.
values
.
flatten
.
map
(
&
:to_s
)
installed
.
should
.
include?
"BlocksKit (1.5.2)"
installed
.
should
.
include?
"JSONKit (1.5pre)"
end
end
it
"installs pods added to the Podfile"
do
#--------------------------------------#
podfile
=
Podfile
.
new
do
platform
:ios
pod
'JSONKit'
pod
'BlocksKit'
pod
'libPusher'
,
'1.3'
# New pod
end
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
installed
=
@resolver
.
resolve
.
values
.
flatten
.
map
(
&
:to_s
)
installed
.
should
.
include?
"libPusher (1.3)"
end
it
"handles head pods"
do
it
"resolves the specification of the podfile"
do
podfile
=
Podfile
.
new
do
target_definition
=
@podfile
.
target_definitions
[
:default
]
platform
:ios
specs
=
@resolver
.
resolve
[
target_definition
]
pod
'JSONKit'
,
:head
# Existing pod switched to head mode
specs
.
map
(
&
:to_s
).
should
==
[
pod
'libPusher'
,
:head
# New pod
"A2DynamicDelegate (2.0.2)"
,
end
"BlocksKit (1.5.2)"
,
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
"libffi (3.0.11)"
@resolver
.
resolve
]
@resolver
.
should_install?
(
"JSONKit"
).
should
.
be
.
true
@resolver
.
should_install?
(
"libPusher"
).
should
.
be
.
true
end
it
"handles pods from external dependencies"
do
podfile
=
Podfile
.
new
do
platform
:ios
pod
'libPusher'
,
:git
=>
'GIT-URL'
end
spec
=
Spec
.
new
do
|
s
|
s
.
name
=
'libPusher'
s
.
version
=
'1.3'
end
ExternalSources
::
GitSource
.
any_instance
.
stubs
(
:specification_from_sandbox
).
returns
(
spec
)
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
@resolver
.
resolve
@resolver
.
should_install?
(
"JSONKit"
).
should
.
be
.
false
end
end
it
"doesn't updates the repos if there no change in the pods"
do
it
"returns the resolved specifications grouped by target definition"
do
podfile
=
Podfile
.
new
do
platform
:ios
pod
'BlocksKit'
pod
'JSONKit'
end
config
.
skip_repo_update
=
false
Command
::
Repo
.
any_instance
.
expects
(
:run
).
never
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
@resolver
.
resolve
@resolver
.
resolve
target_definition
=
@podfile
.
target_definitions
[
:default
]
specs
=
@resolver
.
specs_by_target
[
target_definition
]
specs
.
map
(
&
:to_s
).
should
==
[
"A2DynamicDelegate (2.0.2)"
,
"BlocksKit (1.5.2)"
,
"libffi (3.0.11)"
]
end
end
it
"updates the repos if there is a new pod"
do
it
"returns all the resolved specifications"
do
podfile
=
Podfile
.
new
do
platform
:ios
pod
'BlocksKit'
pod
'JSONKit'
pod
'libPusher'
# New pod
end
config
.
skip_repo_update
=
false
Command
::
Repo
::
Update
.
any_instance
.
expects
(
:run
).
once
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
@resolver
.
resolve
@resolver
.
resolve
@resolver
.
specs
.
map
(
&
:class
).
uniq
.
should
==
[
Specification
]
@resolver
.
specs
.
map
(
&
:to_s
).
should
==
[
"A2DynamicDelegate (2.0.2)"
,
"BlocksKit (1.5.2)"
,
"libffi (3.0.11)"
]
end
end
it
"doesn't update the repos if config indicate to skip it in any case"
do
xit
"returns the specifications that originated from external sources"
do
podfile
=
Podfile
.
new
do
platform
:ios
pod
'BlocksKit'
pod
'JSONKit'
,
:head
#changed to head
pod
'libPusher'
# New pod
end
config
.
skip_repo_update
=
true
Command
::
Repo
::
Update
.
any_instance
.
expects
(
:run
).
never
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
@resolver
.
resolve
end
it
"updates the repos if there is a new pod"
do
podfile
=
Podfile
.
new
do
platform
:ios
pod
'BlocksKit'
pod
'JSONKit'
,
:head
#changed to head
end
config
.
skip_repo_update
=
false
Command
::
Repo
::
Update
.
any_instance
.
expects
(
:run
).
once
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
@resolver
.
resolve
end
end
end
end
describe
"Concerning Update mode"
do
#-------------------------------------------------------------------------#
describe
"Resolution"
do
before
do
before
do
config
.
repos_dir
=
fixture
(
'spec-repos'
)
config
.
repos_dir
=
fixture
(
'spec-repos'
)
previous_podfile
=
Podfile
.
new
do
platform
:ios
pod
'JSONKit'
pod
'libPusher'
end
@specs
=
[
Specification
.
new
do
|
s
|
s
.
name
=
"libPusher"
s
.
version
=
"1.3"
end
,
Specification
.
new
do
|
s
|
s
.
name
=
"JSONKit"
s
.
version
=
"1.4"
end
]
@specs
.
each
{
|
s
|
s
.
activate_platform
(
:ios
)
}
@lockfile
=
Lockfile
.
generate
(
previous_podfile
,
@specs
)
@podfile
=
Podfile
.
new
do
@podfile
=
Podfile
.
new
do
platform
:ios
platform
:ios
,
'6.0'
pod
'BlocksKit'
,
'1.5.2'
pod
'BlocksKit'
,
'1.5.2'
pod
'JSONKit'
pod
'libPusher'
end
end
@resolver
=
Resolver
.
new
(
@podfile
,
@lockfile
,
stub
(
'sandbox'
))
@resolver
=
Resolver
.
new
(
config
.
sandbox
,
@podfile
)
@resolver
.
update_mode
=
true
end
end
it
"identifies the pods that can be updated"
do
installed
=
@resolver
.
resolve
.
values
.
flatten
.
map
(
&
:to_s
)
it
"holds the context state, such as cached specification sets"
do
installed
.
should
.
include?
"JSONKit (999.999.999)"
@resolver
.
resolve
@resolver
.
should_install?
(
"JSONKit"
).
should
.
be
.
true
cached_sets
=
@resolver
.
send
(
:cached_sets
)
cached_sets
.
values
.
sort_by
(
&
:name
).
should
==
[
Source
.
search_by_name
(
'A2DynamicDelegate'
).
first
,
Source
.
search_by_name
(
'BlocksKit'
).
first
,
Source
.
search_by_name
(
'libffi'
).
first
].
sort_by
(
&
:name
)
end
end
it
"respects the constraints of the podfile"
do
it
"raises once any of the dependencies does not match the platform of its podfile target"
do
podfile
=
Podfile
.
new
do
Specification
.
any_instance
.
stubs
(
:available_platforms
).
returns
([
Platform
.
new
(
:ios
,
'999'
)])
platform
:ios
e
=
lambda
{
@resolver
.
resolve
}.
should
.
raise
Informative
pod
'BlocksKit'
,
'1.5.2'
e
.
message
.
should
.
match
(
/platform .* not compatible/
)
pod
'JSONKit'
,
'1.4'
end
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
@resolver
.
update_mode
=
true
installed
=
@resolver
.
resolve
.
values
.
flatten
.
map
(
&
:to_s
)
installed
.
should
.
include?
"JSONKit (1.4)"
@resolver
.
should_install?
(
"JSONKit"
).
should
.
be
.
false
end
end
it
"installs new pods"
do
it
"does not raise if all dependencies are supported by the platform of the target definition"
do
installed
=
@resolver
.
resolve
.
values
.
flatten
.
map
(
&
:to_s
)
lambda
{
@resolver
.
resolve
}.
should
.
not
.
raise
installed
.
join
(
' '
).
should
.
include?
(
'BlocksKit'
)
@resolver
.
should_install?
(
"BlocksKit"
).
should
.
be
.
true
end
end
it
"i
t always suggests to update pods in head m
ode"
do
it
"i
ncludes all the subspecs of a specification n
ode"
do
podfile
=
Podfile
.
new
do
@
podfile
=
Podfile
.
new
do
platform
:ios
platform
:ios
pod
'
libPusher'
,
:head
pod
'
RestKit'
end
end
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
resolver
=
Resolver
.
new
(
config
.
sandbox
,
@podfile
)
@resolver
.
update_mode
=
true
resolver
.
resolve
.
values
.
flatten
.
map
(
&
:name
).
sort
.
should
==
%w{
@resolver
.
resolve
FileMD5Hash
@resolver
.
should_install?
(
"libPusher"
).
should
.
be
.
true
ISO8601DateFormatter
JSONKit
LibComponentLogging-Core
LibComponentLogging-NSLog
NSData+Base64
RestKit
RestKit/JSON
RestKit/Network
RestKit/ObjectMapping/CoreData
RestKit/ObjectMapping/JSON
RestKit/UI
SOCKit
cocoa-oauth
}
end
end
it
"always updates the repos even if there is change in the pods"
do
it
"resolves subspecs with external constraints"
do
@podfile
=
Podfile
.
new
do
platform
:ios
pod
'MainSpec/FirstSubSpec'
,
:git
=>
'GIT-URL'
end
spec
=
Spec
.
new
do
|
s
|
s
.
name
=
'MainSpec'
s
.
version
=
'1.2.3'
s
.
platform
=
:ios
s
.
license
=
'MIT'
s
.
author
=
'Joe the Plumber'
s
.
summary
=
'A spec with subspecs'
s
.
source
=
{
:git
=>
'/some/url'
}
s
.
requires_arc
=
true
s
.
subspec
'FirstSubSpec'
do
|
fss
|
fss
.
source_files
=
'some/file'
fss
.
subspec
'SecondSubSpec'
end
end
ExternalSources
::
GitSource
.
any_instance
.
stubs
(
:specification_from_sandbox
).
returns
(
spec
)
resolver
=
Resolver
.
new
(
config
.
sandbox
,
@podfile
)
resolver
.
resolve
.
values
.
flatten
.
map
(
&
:name
).
sort
.
should
==
%w{ MainSpec/FirstSubSpec MainSpec/FirstSubSpec/SecondSubSpec }
end
it
"marks a specification's version to be a `bleeding edge' version"
do
podfile
=
Podfile
.
new
do
podfile
=
Podfile
.
new
do
platform
:ios
platform
:ios
pod
'
JSONKit
'
pod
'
FileMD5Hash
'
pod
'
libPusher'
pod
'
JSONKit'
,
:head
end
end
config
.
skip_repo_update
=
false
resolver
=
Resolver
.
new
(
config
.
sandbox
,
podfile
)
Command
::
Repo
::
Update
.
any_instance
.
expects
(
:run
).
once
filemd5hash
,
jsonkit
=
resolver
.
resolve
.
values
.
first
.
sort_by
(
&
:name
)
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
filemd5hash
.
version
.
should
.
not
.
be
.
head
@resolver
.
update_mode
=
true
jsonkit
.
version
.
should
.
be
.
head
@resolver
.
resolve
end
end
# TODO: stub the specification resolution for the sandbox
it
"raises if it finds two conflicting dependencies"
do
xit
"it always suggests to update pods from external sources"
do
podfile
=
Podfile
.
new
do
podfile
=
Podfile
.
new
do
platform
:ios
platform
:ios
pod
'libPusher'
,
:git
=>
"example.com"
pod
'JSONKit'
,
"1.4"
pod
'JSONKit'
,
"1.5pre"
end
end
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
resolver
=
Resolver
.
new
(
config
.
sandbox
,
podfile
)
@resolver
.
update_mode
=
true
e
=
lambda
{
resolver
.
resolve
}.
should
.
raise
Pod
::
StandardError
@resolver
.
resolve
e
.
message
.
should
.
match
(
/already activated version/
)
@resolver
.
should_install?
(
"libPusher"
).
should
.
be
.
true
end
end
end
# describe "Concerning Installation mode" do
# before do
# config.repos_dir = fixture('spec-repos')
# @podfile = Podfile.new do
# platform :ios
# pod 'BlocksKit', '1.5.2'
# pod 'JSONKit'
# end
# @specs = [
# Specification.new do |s|
# s.name = "BlocksKit"
# s.version = "1.5.2"
# end,
# Specification.new do |s|
# s.name = "JSONKit"
# s.version = "1.4"
# end ]
# @specs.each { |s| s.activate_platform(:ios) }
# @resolver = Resolver.new(@podfile, @lockfile, stub('sandbox'))
# end
# it "doesn't install pods still compatible with the Podfile" do
# @resolver.resolve
# @resolver.should_install?("BlocksKit").should.be.false
# @resolver.should_install?("JSONKit").should.be.false
# end
# it "doesn't update the version of pods still compatible with the Podfile" do
# installed = @resolver.resolve.values.flatten.map(&:to_s)
# installed.should.include? "JSONKit (1.4)"
# end
# it "doesn't include pods removed from the Podfile" do
# podfile = Podfile.new { platform :ios; pod 'JSONKit' }
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# @resolver.resolve.values.flatten.map(&:name).should == %w{ JSONKit }
# end
# it "reinstalls pods updated in the Podfile" do
# podfile = Podfile.new do
# platform :ios
# pod 'JSONKit', '1.5pre'
# pod 'BlocksKit', '1.5.2'
# end
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# installed = @resolver.resolve.values.flatten.map(&:to_s)
# installed.should.include? "BlocksKit (1.5.2)"
# installed.should.include? "JSONKit (1.5pre)"
# end
# it "installs pods added to the Podfile" do
# podfile = Podfile.new do
# platform :ios
# pod 'JSONKit'
# pod 'BlocksKit'
# pod 'libPusher', '1.3' # New pod
# end
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# installed = @resolver.resolve.values.flatten.map(&:to_s)
# installed.should.include? "libPusher (1.3)"
# end
# it "handles head pods" do
# podfile = Podfile.new do
# platform :ios
# pod 'JSONKit', :head # Existing pod switched to head mode
# pod 'libPusher', :head # New pod
# end
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# @resolver.resolve
# @resolver.should_install?("JSONKit").should.be.true
# @resolver.should_install?("libPusher").should.be.true
# end
# it "handles pods from external dependencies" do
# podfile = Podfile.new do
# platform :ios
# pod 'libPusher', :git => 'GIT-URL'
# end
# spec = Spec.new do |s|
# s.name = 'libPusher'
# s.version = '1.3'
# end
# ExternalSources::GitSource.any_instance.stubs(:specification_from_sandbox).returns(spec)
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# @resolver.resolve
# @resolver.should_install?("JSONKit").should.be.false
# end
# it "doesn't updates the repos if there no change in the pods" do
# podfile = Podfile.new do
# platform :ios
# pod 'BlocksKit'
# pod 'JSONKit'
# end
# config.skip_repo_update = false
# Command::Repo.any_instance.expects(:run).never
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# @resolver.resolve
# end
# it "updates the repos if there is a new pod" do
# podfile = Podfile.new do
# platform :ios
# pod 'BlocksKit'
# pod 'JSONKit'
# pod 'libPusher' # New pod
# end
# config.skip_repo_update = false
# Command::Repo::Update.any_instance.expects(:run).once
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# @resolver.resolve
# end
# it "doesn't update the repos if config indicate to skip it in any case" do
# podfile = Podfile.new do
# platform :ios
# pod 'BlocksKit'
# pod 'JSONKit', :head #changed to head
# pod 'libPusher' # New pod
# end
# config.skip_repo_update = true
# Command::Repo::Update.any_instance.expects(:run).never
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# @resolver.resolve
# end
# it "updates the repos if there is a new pod" do
# podfile = Podfile.new do
# platform :ios
# pod 'BlocksKit'
# pod 'JSONKit', :head #changed to head
# end
# config.skip_repo_update = false
# Command::Repo::Update.any_instance.expects(:run).once
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# @resolver.resolve
# end
# end
# describe "Concerning Update mode" do
# before do
# config.repos_dir = fixture('spec-repos')
# previous_podfile = Podfile.new do
# platform :ios
# pod 'JSONKit'
# pod 'libPusher'
# end
# @specs = [
# Specification.new do |s|
# s.name = "libPusher"
# s.version = "1.3"
# end,
# Specification.new do |s|
# s.name = "JSONKit"
# s.version = "1.4"
# end ]
# @specs.each { |s| s.activate_platform(:ios) }
# @lockfile = Lockfile.generate(previous_podfile, @specs)
# @podfile = Podfile.new do
# platform :ios
# pod 'BlocksKit', '1.5.2'
# pod 'JSONKit'
# pod 'libPusher'
# end
# @resolver = Resolver.new(@podfile, @lockfile, stub('sandbox'))
# @resolver.update_mode = true
# end
# it "identifies the pods that can be updated" do
# installed = @resolver.resolve.values.flatten.map(&:to_s)
# installed.should.include? "JSONKit (999.999.999)"
# @resolver.should_install?("JSONKit").should.be.true
# end
# it "respects the constraints of the podfile" do
# podfile = Podfile.new do
# platform :ios
# pod 'BlocksKit', '1.5.2'
# pod 'JSONKit', '1.4'
# end
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# @resolver.update_mode = true
# installed = @resolver.resolve.values.flatten.map(&:to_s)
# installed.should.include? "JSONKit (1.4)"
# @resolver.should_install?("JSONKit").should.be.false
# end
# it "installs new pods" do
# installed = @resolver.resolve.values.flatten.map(&:to_s)
# installed.join(' ').should.include?('BlocksKit')
# @resolver.should_install?("BlocksKit").should.be.true
# end
# it "it always suggests to update pods in head mode" do
# podfile = Podfile.new do
# platform :ios
# pod 'libPusher', :head
# end
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# @resolver.update_mode = true
# @resolver.resolve
# @resolver.should_install?("libPusher").should.be.true
# end
# it "always updates the repos even if there is change in the pods" do
# podfile = Podfile.new do
# platform :ios
# pod 'JSONKit'
# pod 'libPusher'
# end
# config.skip_repo_update = false
# Command::Repo::Update.any_instance.expects(:run).once
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# @resolver.update_mode = true
# @resolver.resolve
# end
# # TODO: stub the specification resolution for the sandbox
# xit "it always suggests to update pods from external sources" do
# podfile = Podfile.new do
# platform :ios
# pod 'libPusher', :git => "example.com"
# end
# @resolver = Resolver.new(podfile, @lockfile, stub('sandbox'))
# @resolver.update_mode = true
# @resolver.resolve
# @resolver.should_install?("libPusher").should.be.true
# end
# end
end
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment