Commit d99e21ac authored by Samuel E. Giddins's avatar Samuel E. Giddins

Merge pull request #2513 from CocoaPods/podfile-source-url

Allow the specification of a source URL in a Podfile
parents d132d9d7 539744f8
...@@ -4,6 +4,28 @@ To install or update CocoaPods see this [guide](http://docs.cocoapods.org/guides ...@@ -4,6 +4,28 @@ To install or update CocoaPods see this [guide](http://docs.cocoapods.org/guides
## Master ## Master
##### Breaking
* Add support for loading podspecs from *only* specific spec-repos via
`sources`. By default, when there are no sources specified in a Podfile all
source repos will be used. This has always been the case.
However, this implicit use of sources is now deprecated.
Once you specify specific sources, **no** repos wil be included by
default. For example:
source 'https://banana.com/corp/private-spec-repo.git'
source 'https://github.com/CocoaPods/Specs.git'
Any source URLs specified that have not yet been added will be cloned before
resolution begins.
[François Benaiteau](https://github.com/netbe)
[Fabio Pelosin](https://github.com/fabiopelosin)
[Samuel Giddins](https://github.com/segiddins)
[#1143](https://github.com/CocoaPods/CocoaPods/pull/1143)
[Core#19](https://github.com/CocoaPods/Core/pull/19)
[Core#170](https://github.com/CocoaPods/Core/issues/170)
[#2515](https://github.com/CocoaPods/CocoaPods/issues/2515)
##### Bug Fixes ##### Bug Fixes
* Works around an Xcode issue where linting would fail even though `xcodebuild` * Works around an Xcode issue where linting would fail even though `xcodebuild`
...@@ -34,7 +56,7 @@ To install or update CocoaPods see this [guide](http://docs.cocoapods.org/guides ...@@ -34,7 +56,7 @@ To install or update CocoaPods see this [guide](http://docs.cocoapods.org/guides
[Kyle Fuller](https://github.com/kylef) [Kyle Fuller](https://github.com/kylef)
[#2147](https://github.com/CocoaPods/CocoaPods/issues/2147) [#2147](https://github.com/CocoaPods/CocoaPods/issues/2147)
* Fixes an issue where `pod init` would not add `source 'master'` to newly * Fixes an issue where `pod init` would not add `source 'master'` to newly
created Podfiles. created Podfiles.
[Ash Furrow](https://github.com/AshFurrow) [Ash Furrow](https://github.com/AshFurrow)
[#2473](https://github.com/CocoaPods/CocoaPods/issues/2473) [#2473](https://github.com/CocoaPods/CocoaPods/issues/2473)
...@@ -60,7 +82,7 @@ To install or update CocoaPods see this [guide](http://docs.cocoapods.org/guides ...@@ -60,7 +82,7 @@ To install or update CocoaPods see this [guide](http://docs.cocoapods.org/guides
[Fabio Pelosin](https://github.com/fabiopelosin) [Fabio Pelosin](https://github.com/fabiopelosin)
[#1143](https://github.com/CocoaPods/CocoaPods/pull/1143) [#1143](https://github.com/CocoaPods/CocoaPods/pull/1143)
[Core#19](https://github.com/CocoaPods/Core/pull/19) [Core#19](https://github.com/CocoaPods/Core/pull/19)
* The `Pods` directory has been reorganized. This might require manual * The `Pods` directory has been reorganized. This might require manual
intervention in projects where files generated by CocoaPods have manually been intervention in projects where files generated by CocoaPods have manually been
imported into the user's project (common with the acknowledgements files). imported into the user's project (common with the acknowledgements files).
......
...@@ -7,7 +7,7 @@ GIT ...@@ -7,7 +7,7 @@ GIT
GIT GIT
remote: https://github.com/CocoaPods/Core.git remote: https://github.com/CocoaPods/Core.git
revision: afe219baa5a4854067145825d0c141e43eee0e6a revision: b9dcb24367e8215637cdee840af58a9f0bf62568
branch: master branch: master
specs: specs:
cocoapods-core (0.34.0.rc2) cocoapods-core (0.34.0.rc2)
......
...@@ -318,12 +318,6 @@ module Pod ...@@ -318,12 +318,6 @@ module Pod
def resolve_dependencies def resolve_dependencies
specs_by_target = nil specs_by_target = nil
UI.section "Resolving dependencies of #{UI.path podfile.defined_in_file}" do UI.section "Resolving dependencies of #{UI.path podfile.defined_in_file}" do
if podfile.sources.empty?
sources = SourcesManager.master
else
sources = SourcesManager.sources(podfile.sources)
end
resolver = Resolver.new(sandbox, podfile, locked_dependencies, sources) resolver = Resolver.new(sandbox, podfile, locked_dependencies, sources)
specs_by_target = resolver.resolve specs_by_target = resolver.resolve
end end
...@@ -367,6 +361,33 @@ module Pod ...@@ -367,6 +361,33 @@ module Pod
private private
# Returns the sources used to query for specifications
#
# @note Currently, this defaults to {SourcesManager.all} when no
# Podfile sources are defined, but this implicit declaration of
# sources is deprecated.
#
# @return [Array<Source>] the sources to be used in finding
# specifications, as specified by the {#podfile}.
#
def sources
@sources ||= begin
sources = podfile.sources
if sources.empty?
SourcesManager.all.tap do |all|
UI.warn all.reduce("The use of implicit sources has been " \
"deprecated. To replicate the previous behavior, add the " \
"following to your Podfile:") \
{ |w, s| w << "\nsource '#{s.url}'" }
end
else
sources.map do |url|
SourcesManager.find_or_create_source_with_url(url)
end
end
end
end
# @!group Analysis sub-steps # @!group Analysis sub-steps
# Returns the path of the user project that the {TargetDefinition} # Returns the path of the user project that the {TargetDefinition}
......
...@@ -23,6 +23,30 @@ module Pod ...@@ -23,6 +23,30 @@ module Pod
dirs.map { |repo| Source.new(repo) } dirs.map { |repo| Source.new(repo) }
end end
# Returns the source whose {Source#url} is equal to `url`, adding the repo
# in a manner similarly to `pod repo add` if it is not found.
#
# @raise If no source with the given `url` could be created,
#
# @return [Source] The source whose {Source#url} is equal to `url`,
#
# @param [String] url
# The URL of the source.
#
def find_or_create_source_with_url(url)
unless source = source_with_url(url)
name = name_for_url(url)
Command::Repo::Add.new(CLAide::ARGV.new([name, url])).run
source = source_with_url(url)
end
unless source
raise Informative, "Unable to add a source with url `#{url}` named " \
"`#{name}`.\nYou can add it manually via `pod repo add NAME " \
"#{url}`.\n\n#{output}"
end
source
end
# @return [Array<Source>] The list of all the sources known to this # @return [Array<Source>] The list of all the sources known to this
# installation of CocoaPods. # installation of CocoaPods.
# #
...@@ -31,7 +55,7 @@ module Pod ...@@ -31,7 +55,7 @@ module Pod
dirs.map { |repo| Source.new(repo) } dirs.map { |repo| Source.new(repo) }
end end
# @return [Source] The CocoaPods Master Repo source. # @return [Array<Source>] The CocoaPods Master Repo source.
# #
def master def master
sources(['master']) sources(['master'])
...@@ -343,6 +367,57 @@ module Pod ...@@ -343,6 +367,57 @@ module Pod
raise Informative, "Unable to find the `#{name}` repo." raise Informative, "Unable to find the `#{name}` repo."
end end
end end
# @return [Source] The source whose {Source#url} is equal to `url`.
#
# @param [String] url
# The URL of the source.
#
def source_with_url(url)
url = url.downcase
aggregate.sources.find { |s| s.url.downcase == url }
end
# Returns a suitable repository name for `url`.
#
# @example A GitHub.com URL
#
# name_for_url('https://github.com/Artsy/Specs.git')
# # "artsy"
# name_for_url('https://github.com/Artsy/Specs.git')
# # "artsy-1"
#
# @example A non-Github.com URL
#
# name_for_url('https://sourceforge.org/Artsy/Specs.git')
# # sourceforge-artsy-specs
#
# @param [#to_s] url
# The URL of the source.
#
# @return [String] A suitable repository name for `url`.
#
def name_for_url(url)
case url.downcase
when %r{github.com(:|/)cocoapods/specs}
base = 'master'
when %r{github.com(:|/)(.+)/(.+)}
base = Regexp.last_match[2]
else
raise Informative,
"`#{url}` is not a valid URL." unless url =~ URI.regexp
url = URI(url.downcase)
base = url.host.split('.')[-2] +
url.path.gsub(/.git$/, '').split('/').join('-')
end
name = base
infinity = 1.0 / 0
(1..infinity).each do |i|
break unless source_dir(name).exist?
name = "#{base}-#{i}"
end
name
end
end end
end end
end end
...@@ -465,6 +465,49 @@ module Pod ...@@ -465,6 +465,49 @@ module Pod
e.message.should.match /Targets with different platforms/ e.message.should.match /Targets with different platforms/
end end
end end
#--------------------------------------#
describe '#sources' do
describe 'when there are no explicit sources' do
it 'defaults to all sources' do
@analyzer.send(:sources).map(&:url).should ==
SourcesManager.all.map(&:url)
end
it 'prints a warning about the deprecation of implicit sources' do
@analyzer.send(:sources)
UI.warnings.should.match /implicit(.+)sources(.+)deprecated/
end
it 'prints a warning about how to add explicit sources' do
@analyzer.send(:sources)
UI.warnings.should.
match %r{^source 'https://github.com/CocoaPods/Specs.git'$}
end
end
describe 'when there are explicit sources' do
it 'raises if no specs repo with that URL could be added' do
podfile = Podfile.new do
source 'not-a-git-repo'
end
@analyzer.instance_variable_set(:@podfile, podfile)
should.raise Informative do
@analyzer.send(:sources)
end.message.should.match /not a valid URL/
end
it 'fetches a specs repo that is specified by the podfile' do
podfile = Podfile.new do
source 'https://github.com/artsy/Specs.git'
end
@analyzer.instance_variable_set(:@podfile, podfile)
SourcesManager.expects(:find_or_create_source_with_url).once
@analyzer.send(:sources)
end
end
end
end end
end end
end end
...@@ -101,6 +101,62 @@ module Pod ...@@ -101,6 +101,62 @@ module Pod
path = SourcesManager.search_index_path.to_s path = SourcesManager.search_index_path.to_s
path.should.match %r{Library/Caches/CocoaPods/search_index.yaml} path.should.match %r{Library/Caches/CocoaPods/search_index.yaml}
end end
describe 'managing sources by URL' do
describe 'generating a repo name from a URL' do
it 'uses `master` for the master CocoaPods repository' do
url = 'https://github.com/CocoaPods/Specs.git'
Pathname.any_instance.stubs(:exist?).
returns(false).then.returns(true)
SourcesManager.send(:name_for_url, url).should == 'master'
url = 'git@github.com:CocoaPods/Specs.git'
Pathname.any_instance.stubs(:exist?).
returns(false).then.returns(true)
SourcesManager.send(:name_for_url, url).should == 'master'
end
it 'uses the organization name for github.com URLs' do
url = 'https://github.com/segiddins/banana.git'
SourcesManager.send(:name_for_url, url).should == 'segiddins'
end
it 'uses a combination of host and path for other URLs' do
url = 'https://sourceforge.org/Artsy/Specs.git'
SourcesManager.send(:name_for_url, url).
should == 'sourceforge-artsy-specs'
end
it 'appends a number to the name if the base name dir exists' do
url = 'https://github.com/segiddins/banana.git'
Pathname.any_instance.stubs(:exist?).
returns(true).then.returns(false)
SourcesManager.send(:name_for_url, url).should == 'segiddins-1'
url = 'https://sourceforge.org/Artsy/Specs.git'
Pathname.any_instance.stubs(:exist?).
returns(true).then.returns(false)
SourcesManager.send(:name_for_url, url).
should == 'sourceforge-artsy-specs-1'
end
end
describe 'finding or creating a source by URL' do
it 'returns an existing matching source' do
Source.any_instance.stubs(:url).returns('url')
SourcesManager.expects(:name_for_url).never
SourcesManager.find_or_create_source_with_url('url').url.
should == 'url'
end
it 'runs `pod repo add` when there is no matching source' do
Command::Repo::Add.any_instance.stubs(:run).once
SourcesManager.stubs(:source_with_url).returns(nil).then.returns('Source')
SourcesManager.find_or_create_source_with_url('https://banana.com/local/specs.git').
should == 'Source'
end
end
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