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
## 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
* 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
[Kyle Fuller](https://github.com/kylef)
[#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.
[Ash Furrow](https://github.com/AshFurrow)
[#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
[Fabio Pelosin](https://github.com/fabiopelosin)
[#1143](https://github.com/CocoaPods/CocoaPods/pull/1143)
[Core#19](https://github.com/CocoaPods/Core/pull/19)
* The `Pods` directory has been reorganized. This might require manual
intervention in projects where files generated by CocoaPods have manually been
imported into the user's project (common with the acknowledgements files).
......
......@@ -7,7 +7,7 @@ GIT
GIT
remote: https://github.com/CocoaPods/Core.git
revision: afe219baa5a4854067145825d0c141e43eee0e6a
revision: b9dcb24367e8215637cdee840af58a9f0bf62568
branch: master
specs:
cocoapods-core (0.34.0.rc2)
......
......@@ -318,12 +318,6 @@ module Pod
def resolve_dependencies
specs_by_target = nil
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)
specs_by_target = resolver.resolve
end
......@@ -367,6 +361,33 @@ module Pod
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
# Returns the path of the user project that the {TargetDefinition}
......
......@@ -23,6 +23,30 @@ module Pod
dirs.map { |repo| Source.new(repo) }
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
# installation of CocoaPods.
#
......@@ -31,7 +55,7 @@ module Pod
dirs.map { |repo| Source.new(repo) }
end
# @return [Source] The CocoaPods Master Repo source.
# @return [Array<Source>] The CocoaPods Master Repo source.
#
def master
sources(['master'])
......@@ -343,6 +367,57 @@ module Pod
raise Informative, "Unable to find the `#{name}` repo."
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
......@@ -465,6 +465,49 @@ module Pod
e.message.should.match /Targets with different platforms/
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
......@@ -101,6 +101,62 @@ module Pod
path = SourcesManager.search_index_path.to_s
path.should.match %r{Library/Caches/CocoaPods/search_index.yaml}
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
#-------------------------------------------------------------------------#
......
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