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
#
# Its current implementation is naive, in the sense that it can't do full
# automatic resolves like Bundler:
#
# http://patshaughnessy.net/2011/9/24/how-does-bundler-bundle
# [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
# is that the order of the dependencies matters.
#
class
Resolver
include
Config
::
Mixin
# @return [Sandbox]
T
he Sandbox used by the resolver to find external
# dependencies.
# @return [Sandbox]
t
he Sandbox used by the resolver to find external
#
dependencies.
#
attr_reader
:sandbox
# @return [Podfile]
T
he Podfile used by the resolver.
# @return [Podfile]
t
he Podfile used by the resolver.
#
attr_reader
:podfile
# @return [Array<Dependency>]
T
he list of dependencies locked to a specific
# version.
# @return [Array<Dependency>]
t
he list of dependencies locked to a specific
#
version.
#
attr_reader
:locked_dependencies
# @return [Bool]
W
hether the resolver should update the external specs
#
in the resolution process. This option is used for detecting changes
#
in with the Podfile without affecting the existing Pods installation
#
(see `pod outdated`).
# @return [Bool]
w
hether the resolver should update the external specs
#
in the resolution process. This option is used for detecting
#
changes in with the Podfile without affecting the existing Pods
#
installation
#
# @TODO: This implementation is not clean, because if the spec doesn't
# exists the sandbox will actually download it and result modified.
# @note This option is used by `pod outdated`.
#
# @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
# @param [Sandbox] sandbox @see sandbox
# @param [Podfile] podfile @see podfile
# @param [Array<Dependency>] locked_dependencies @see locked_dependencies
#
def
initialize
(
sandbox
,
podfile
,
locked_dependencies
=
[])
@sandbox
=
sandbox
@podfile
=
podfile
@locked_dependencies
=
locked_dependencies
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
# resolver.
#
def
specs
@cached_specs
.
values
.
uniq
end
# @!group Resolution
# @return [Array<Strings>] The name of the pods that have an
# external source.
#
# @TODO: Add an attribute to the specification class?
#
attr_reader
:pods_from_external_sources
public
# Identifies the specifications that should be installed.
#
# @return [Hash{TargetDefinition => Array<Specification>}] specs_by_target
#
Identifies the specifications that should be installed according
#
whether the resolver is in update mode or not
.
#
the specifications that need to be installed grouped by target
#
definition
.
#
def
resolve
@cached_sources
=
Source
::
Aggregate
.
new
(
config
.
repos_dir
)
@cached_sets
=
{}
@cached_specs
=
{}
@specs_by_target
=
{}
@pods_from_external_sources
=
[]
#
@pods_from_external_sources = []
podfile
.
target_definitions
.
values
.
each
do
|
target
_definition
|
UI
.
section
"Resolving dependencies for target `
#{
target
_definition
.
name
}
' (
#{
target_definition
.
platform
}
)"
do
podfile
.
target_definitions
.
values
.
each
do
|
target
|
UI
.
section
"Resolving dependencies for target `
#{
target
.
name
}
' (
#{
target
.
platform
}
)"
do
@loaded_specs
=
[]
find_dependency_specs
(
podfile
,
target_definition
.
dependencies
,
target_definition
)
@specs_by_target
[
target_definition
]
=
@cached_specs
.
values_at
(
*
@loaded_specs
).
sort_by
(
&
:name
)
find_dependency_specs
(
podfile
,
target
.
dependencies
,
target
)
specs
=
cached_specs
.
values_at
(
*
@loaded_specs
).
sort_by
(
&
:name
)
specs_by_target
[
target
]
=
specs
end
end
@
cached_specs
.
values
.
sort_by
(
&
:name
)
@
specs_by_target
cached_specs
.
values
.
sort_by
(
&
:name
)
specs_by_target
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
# 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
# The dependencies of the specification.
attr_accessor
:cached_specs
#
#
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
# The target definition that owns the specification.
# @return [void]
#
def
find_dependency_specs
(
dependent_spec
ification
,
dependencies
,
target_definition
)
def
find_dependency_specs
(
dependent_spec
,
dependencies
,
target_definition
)
dependencies
.
each
do
|
dependency
|
# Replace the dependency with a more specific one if the pod is already
# installed.
# @TODO: check for compatibility?
locked_dep
=
locked_dependencies
.
find
{
|
locked
|
locked
.
name
==
dependency
.
name
}
locked_dep
=
locked_dependencies
.
find
{
|
ld
|
ld
.
name
==
dependency
.
name
}
dependency
=
locked_dep
if
locked_dep
UI
.
message
(
"-
#{
dependency
}
"
,
''
,
2
)
do
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
if
@loaded_specs
.
include?
(
dependency
.
name
)
validate_platform
(
@cached_specs
[
dependency
.
name
],
target_definition
)
else
unless
@loaded_specs
.
include?
(
dependency
.
name
)
spec
=
set
.
specification
.
subspec_by_name
(
dependency
.
name
)
@pods_from_external_sources
<<
spec
.
pod_name
if
dependency
.
external?
@loaded_specs
<<
spec
.
name
@cached_specs
[
spec
.
name
]
=
spec
# Configure the specification
cached_specs
[
spec
.
name
]
=
spec
# @pods_from_external_sources << spec.root_name if dependency.external?
validate_platform
(
spec
,
target_definition
)
spec
.
activate_platform
(
target_definition
.
platform
)
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
# @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
# external sources are always resolved against the remote. Otherwise the
# specification is retrieved from the sandbox that fetches the external
# source only if needed.
# @return [Set] the cached set for a given dependency.
#
def
find_cached_set
(
dependency
,
platform
)
set_name
=
dependency
.
name
.
split
(
'/'
).
first
@cached_sets
[
set_name
]
||=
begin
name
=
dependency
.
root_name
unless
cached_sets
[
name
]
if
dependency
.
specification
Specification
::
Set
::
External
.
new
(
dependency
.
specification
)
elsif
external_source
=
dependency
.
external_source
if
update_external_specs
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
set
=
Specification
::
Set
::
External
.
new
(
dependency
.
specification
)
elsif
dependency
.
external_source
set
=
set_from_external_source
(
dependency
,
platform
)
else
cached_sources
.
search
(
dependency
)
set
=
cached_sources
.
search
(
dependency
)
end
cached_sets
[
name
]
=
set
end
cached_sets
[
name
]
end
# @return [void] Ensures that a spec is compatible with the platform of a
# target.
# Returns a new set created from an external source
#
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.
#
# @return [void]
#
def
validate_platform
(
spec
,
target
)
unless
spec
.
available_platforms
.
any?
{
|
p
latform
|
target
.
platform
.
supports?
(
platform
)
}
raise
Informative
,
"The platform of the target `
#{
target
.
name
}
' "
\
"(
#{
target
.
platform
}
) is not compatible with `
#{
spec
}
' which "
\
"
has
a minimum requirement of
#{
spec
.
available_platforms
.
join
(
' - '
)
}
."
unless
spec
.
available_platforms
.
any?
{
|
p
|
target
.
platform
.
supports?
(
p
)
}
raise
Informative
,
"The platform of the target `
#{
target
.
name
}
` "
\
"(
#{
target
.
platform
}
) is not compatible with `
#{
spec
}
` which has "
\
"a minimum requirement of
#{
spec
.
available_platforms
.
join
(
' - '
)
}
."
end
end
end
...
...
spec/unit/resolver_spec.rb
View file @
1baebf67
...
...
@@ -2,450 +2,408 @@ require File.expand_path('../../spec_helper', __FILE__)
module
Pod
describe
Resolver
do
before
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
describe
"In general"
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
)
}
@lockfile
=
Lockfile
.
generate
(
@podfile
,
@specs
)
@resolver
=
Resolver
.
new
(
@podfile
,
@lockfile
,
stub
(
'sandbox'
))
locked_deps
=
[
Dependency
.
new
(
'BlocksKit'
,
'1.5.2'
)]
@resolver
=
Resolver
.
new
(
config
.
sandbox
,
@podfile
,
locked_deps
)
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
it
"returns the sandbox"
do
@resolver
.
sandbox
.
should
==
config
.
sandbox
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)"
it
"returns the podfile"
do
@resolver
.
podfile
.
should
==
@podfile
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 }
it
"returns the locked dependencies"
do
@resolver
.
locked_dependencies
.
should
==
[
Dependency
.
new
(
'BlocksKit'
,
'1.5.2'
)]
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)"
it
"allows to specify whether the external sources should be updated against the remote"
do
# TODO
@resolver
.
update_external_specs
=
true
@resolver
.
update_external_specs
.
should
.
be
.
true
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
it
"resolves the specification of the podfile"
do
target_definition
=
@podfile
.
target_definitions
[
:default
]
specs
=
@resolver
.
resolve
[
target_definition
]
specs
.
map
(
&
:to_s
).
should
==
[
"A2DynamicDelegate (2.0.2)"
,
"BlocksKit (1.5.2)"
,
"libffi (3.0.11)"
]
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'
))
it
"returns the resolved specifications grouped by target definition"
do
@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
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'
))
it
"returns all the resolved specifications"
do
@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
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
xit
"returns the specifications that originated from external sources"
do
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
#-------------------------------------------------------------------------#
describe
"Resolution"
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
platform
:ios
,
'6.0'
pod
'BlocksKit'
,
'1.5.2'
pod
'JSONKit'
pod
'libPusher'
end
@resolver
=
Resolver
.
new
(
@podfile
,
@lockfile
,
stub
(
'sandbox'
))
@resolver
.
update_mode
=
true
@resolver
=
Resolver
.
new
(
config
.
sandbox
,
@podfile
)
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
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
"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
it
"raises once any of the dependencies does not match the platform of its podfile target"
do
Specification
.
any_instance
.
stubs
(
:available_platforms
).
returns
([
Platform
.
new
(
:ios
,
'999'
)])
e
=
lambda
{
@resolver
.
resolve
}.
should
.
raise
Informative
e
.
message
.
should
.
match
(
/platform .* not compatible/
)
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
it
"does not raise if all dependencies are supported by the platform of the target definition"
do
lambda
{
@resolver
.
resolve
}.
should
.
not
.
raise
end
it
"i
t always suggests to update pods in head m
ode"
do
podfile
=
Podfile
.
new
do
it
"i
ncludes all the subspecs of a specification n
ode"
do
@
podfile
=
Podfile
.
new
do
platform
:ios
pod
'
libPusher'
,
:head
pod
'
RestKit'
end
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
@resolver
.
update_mode
=
true
@resolver
.
resolve
@resolver
.
should_install?
(
"libPusher"
).
should
.
be
.
true
resolver
=
Resolver
.
new
(
config
.
sandbox
,
@podfile
)
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
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
platform
:ios
pod
'
JSONKit
'
pod
'
libPusher'
pod
'
FileMD5Hash
'
pod
'
JSONKit'
,
:head
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
resolver
=
Resolver
.
new
(
config
.
sandbox
,
podfile
)
filemd5hash
,
jsonkit
=
resolver
.
resolve
.
values
.
first
.
sort_by
(
&
:name
)
filemd5hash
.
version
.
should
.
not
.
be
.
head
jsonkit
.
version
.
should
.
be
.
head
end
# TODO: stub the specification resolution for the sandbox
xit
"it always suggests to update pods from external sources"
do
it
"raises if it finds two conflicting dependencies"
do
podfile
=
Podfile
.
new
do
platform
:ios
pod
'libPusher'
,
:git
=>
"example.com"
pod
'JSONKit'
,
"1.4"
pod
'JSONKit'
,
"1.5pre"
end
@resolver
=
Resolver
.
new
(
podfile
,
@lockfile
,
stub
(
'sandbox'
))
@resolver
.
update_mode
=
true
@resolver
.
resolve
@resolver
.
should_install?
(
"libPusher"
).
should
.
be
.
true
resolver
=
Resolver
.
new
(
config
.
sandbox
,
podfile
)
e
=
lambda
{
resolver
.
resolve
}.
should
.
raise
Pod
::
StandardError
e
.
message
.
should
.
match
(
/already activated version/
)
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
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