cocoapods 0.5.1 → 0.6.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +229 -2
- data/README.md +50 -20
- data/bin/pod +3 -2
- data/lib/cocoapods.rb +23 -9
- data/lib/cocoapods/command.rb +71 -30
- data/lib/cocoapods/command/error_report.rb +102 -0
- data/lib/cocoapods/command/install.rb +27 -19
- data/lib/cocoapods/command/list.rb +51 -8
- data/lib/cocoapods/command/presenter.rb +61 -0
- data/lib/cocoapods/command/presenter/cocoa_pod.rb +123 -0
- data/lib/cocoapods/command/push.rb +102 -0
- data/lib/cocoapods/command/repo.rb +70 -14
- data/lib/cocoapods/command/search.rb +7 -10
- data/lib/cocoapods/command/setup.rb +76 -15
- data/lib/cocoapods/command/spec.rb +581 -97
- data/lib/cocoapods/config.rb +23 -26
- data/lib/cocoapods/dependency.rb +86 -40
- data/lib/cocoapods/downloader.rb +30 -18
- data/lib/cocoapods/downloader/git.rb +125 -15
- data/lib/cocoapods/downloader/http.rb +73 -0
- data/lib/cocoapods/downloader/mercurial.rb +3 -9
- data/lib/cocoapods/downloader/subversion.rb +3 -9
- data/lib/cocoapods/executable.rb +26 -3
- data/lib/cocoapods/generator/acknowledgements.rb +37 -0
- data/lib/cocoapods/generator/acknowledgements/markdown.rb +38 -0
- data/lib/cocoapods/generator/acknowledgements/plist.rb +63 -0
- data/lib/cocoapods/generator/copy_resources_script.rb +8 -4
- data/lib/cocoapods/generator/documentation.rb +99 -0
- data/lib/cocoapods/generator/dummy_source.rb +14 -0
- data/lib/cocoapods/installer.rb +140 -109
- data/lib/cocoapods/installer/target_installer.rb +78 -83
- data/lib/cocoapods/installer/user_project_integrator.rb +162 -0
- data/lib/cocoapods/local_pod.rb +240 -0
- data/lib/cocoapods/platform.rb +41 -18
- data/lib/cocoapods/podfile.rb +234 -21
- data/lib/cocoapods/project.rb +67 -0
- data/lib/cocoapods/resolver.rb +62 -32
- data/lib/cocoapods/sandbox.rb +63 -0
- data/lib/cocoapods/source.rb +42 -20
- data/lib/cocoapods/specification.rb +294 -271
- data/lib/cocoapods/specification/set.rb +10 -28
- data/lib/cocoapods/specification/statistics.rb +112 -0
- metadata +124 -11
- data/lib/cocoapods/xcodeproj_pods.rb +0 -111
data/lib/cocoapods/config.rb
CHANGED
@@ -10,16 +10,23 @@ module Pod
|
|
10
10
|
@instance = instance
|
11
11
|
end
|
12
12
|
|
13
|
-
attr_accessor :repos_dir, :project_root, :project_pods_root
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
attr_accessor :repos_dir, :project_root, :project_pods_root
|
14
|
+
attr_accessor :clean, :verbose, :silent
|
15
|
+
attr_accessor :generate_docs, :doc_install
|
16
|
+
attr_accessor :integrate_targets
|
17
|
+
attr_accessor :git_cache_size
|
18
|
+
|
19
|
+
alias_method :clean?, :clean
|
20
|
+
alias_method :verbose?, :verbose
|
21
|
+
alias_method :silent?, :silent
|
22
|
+
alias_method :generate_docs?, :generate_docs
|
23
|
+
alias_method :doc_install?, :doc_install
|
24
|
+
alias_method :integrate_targets?, :integrate_targets
|
17
25
|
|
18
26
|
def initialize
|
19
27
|
@repos_dir = Pathname.new(File.expand_path("~/.cocoapods"))
|
20
|
-
@
|
21
|
-
@
|
22
|
-
@silent = false
|
28
|
+
@verbose = @silent = false
|
29
|
+
@clean = @generate_docs = @doc_install = @integrate_targets = true
|
23
30
|
end
|
24
31
|
|
25
32
|
def project_root
|
@@ -31,13 +38,7 @@ module Pod
|
|
31
38
|
end
|
32
39
|
|
33
40
|
def project_podfile
|
34
|
-
|
35
|
-
@project_podfile = project_root + 'Podfile'
|
36
|
-
unless @project_podfile.exist?
|
37
|
-
@project_podfile = project_root.glob('*.podspec').first
|
38
|
-
end
|
39
|
-
end
|
40
|
-
@project_podfile
|
41
|
+
@project_podfile ||= project_root + 'Podfile'
|
41
42
|
end
|
42
43
|
|
43
44
|
def headers_symlink_root
|
@@ -45,25 +46,21 @@ module Pod
|
|
45
46
|
end
|
46
47
|
|
47
48
|
# Returns the spec at the pat returned from `project_podfile`.
|
48
|
-
def
|
49
|
-
|
50
|
-
if project_podfile
|
51
|
-
if project_podfile.basename.to_s == 'Podfile'
|
52
|
-
@rootspec = Podfile.from_file(project_podfile)
|
53
|
-
else
|
54
|
-
@rootspec = Specification.from_file(project_podfile)
|
55
|
-
end
|
56
|
-
end
|
49
|
+
def podfile
|
50
|
+
@podfile ||= begin
|
51
|
+
Podfile.from_file(project_podfile) if project_podfile.exist?
|
57
52
|
end
|
58
|
-
@rootspec
|
59
53
|
end
|
54
|
+
attr_writer :podfile
|
60
55
|
|
61
56
|
def ios?
|
62
|
-
|
57
|
+
# TODO: deprecate in 0.7
|
58
|
+
podfile.target_definitions[:default].platform == :ios if podfile
|
63
59
|
end
|
64
60
|
|
65
61
|
def osx?
|
66
|
-
|
62
|
+
# TODO: deprecate in 0.7
|
63
|
+
podfile.target_definitions[:default].platform == :osx if podfile
|
67
64
|
end
|
68
65
|
|
69
66
|
module Mixin
|
data/lib/cocoapods/dependency.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
module Gem
|
2
2
|
end
|
3
3
|
require 'rubygems/dependency'
|
4
|
+
require 'open-uri'
|
4
5
|
|
5
6
|
module Pod
|
6
7
|
class Dependency < Gem::Dependency
|
7
|
-
attr_accessor :only_part_of_other_pod
|
8
|
-
alias_method :only_part_of_other_pod?, :only_part_of_other_pod
|
9
|
-
|
10
|
-
attr_accessor :external_spec_source
|
11
8
|
|
9
|
+
attr_reader :external_source
|
12
10
|
attr_accessor :specification
|
13
11
|
|
14
12
|
def initialize(*name_and_version_requirements, &block)
|
@@ -19,7 +17,7 @@ module Pod
|
|
19
17
|
|
20
18
|
elsif !name_and_version_requirements.empty? && block.nil?
|
21
19
|
if name_and_version_requirements.last.is_a?(Hash)
|
22
|
-
@
|
20
|
+
@external_source = ExternalSources.from_params(name_and_version_requirements[0].split('/').first, name_and_version_requirements.pop)
|
23
21
|
end
|
24
22
|
super(*name_and_version_requirements)
|
25
23
|
|
@@ -27,19 +25,24 @@ module Pod
|
|
27
25
|
raise Informative, "A dependency needs either a name and version requirements, " \
|
28
26
|
"a source hash, or a block which defines a podspec."
|
29
27
|
end
|
30
|
-
@only_part_of_other_pod = false
|
31
28
|
end
|
32
29
|
|
33
30
|
def ==(other)
|
34
|
-
super &&
|
35
|
-
@only_part_of_other_pod == other.only_part_of_other_pod &&
|
36
|
-
(@specification ? @specification == other.specification : @external_spec_source == other.external_spec_source)
|
31
|
+
super && (@specification ? @specification == other.specification : @external_source == other.external_source)
|
37
32
|
end
|
38
33
|
|
39
34
|
def subspec_dependency?
|
40
35
|
@name.include?('/')
|
41
36
|
end
|
42
37
|
|
38
|
+
def inline?
|
39
|
+
@inline_podspec
|
40
|
+
end
|
41
|
+
|
42
|
+
def external?
|
43
|
+
!@external_source.nil?
|
44
|
+
end
|
45
|
+
|
43
46
|
# In case this is a dependency for a subspec, e.g. 'RestKit/Networking',
|
44
47
|
# this returns 'RestKit', which is what the Pod::Source needs to know to
|
45
48
|
# retrieve the correct Set from disk.
|
@@ -58,11 +61,9 @@ module Pod
|
|
58
61
|
|
59
62
|
def to_s
|
60
63
|
version = ''
|
61
|
-
if
|
62
|
-
version <<
|
63
|
-
|
64
|
-
version << ", tag `#{source[:tag]}'" if source[:tag]
|
65
|
-
elsif @inline_podspec
|
64
|
+
if external?
|
65
|
+
version << @external_source.description
|
66
|
+
elsif inline?
|
66
67
|
version << "defined in Podfile"
|
67
68
|
elsif @version_requirements != Gem::Requirement.default
|
68
69
|
version << @version_requirements.to_s
|
@@ -70,32 +71,8 @@ module Pod
|
|
70
71
|
version.empty? ? @name : "#{@name} (#{version})"
|
71
72
|
end
|
72
73
|
|
73
|
-
|
74
|
-
|
75
|
-
def specification
|
76
|
-
@specification ||= begin
|
77
|
-
if @external_spec_source
|
78
|
-
config = Config.instance
|
79
|
-
pod_root = config.project_pods_root + @name
|
80
|
-
spec = nil
|
81
|
-
if @external_spec_source[:podspec]
|
82
|
-
config.project_pods_root.mkpath
|
83
|
-
spec = config.project_pods_root + "#{@name}.podspec"
|
84
|
-
source = @external_spec_source[:podspec]
|
85
|
-
# can be http, file, etc
|
86
|
-
require 'open-uri'
|
87
|
-
puts " * Fetching podspec for `#{@name}' from: #{source}" unless config.silent?
|
88
|
-
open(source) do |io|
|
89
|
-
spec.open('w') { |f| f << io.read }
|
90
|
-
end
|
91
|
-
else
|
92
|
-
puts " * Pre-downloading: `#{@name}'" unless config.silent?
|
93
|
-
Downloader.for_source(pod_root, @external_spec_source).download
|
94
|
-
spec = pod_root + "#{@name}.podspec"
|
95
|
-
end
|
96
|
-
Specification.from_file(spec)
|
97
|
-
end
|
98
|
-
end
|
74
|
+
def specification_from_sandbox(sandbox, platform)
|
75
|
+
@external_source.specification_from_sandbox(sandbox, platform)
|
99
76
|
end
|
100
77
|
|
101
78
|
# Taken from RubyGems 1.3.7
|
@@ -134,5 +111,74 @@ module Pod
|
|
134
111
|
end
|
135
112
|
end
|
136
113
|
|
114
|
+
module ExternalSources
|
115
|
+
def self.from_params(name, params)
|
116
|
+
if params.key?(:git)
|
117
|
+
GitSource.new(name, params)
|
118
|
+
elsif params.key?(:podspec)
|
119
|
+
PodspecSource.new(name, params)
|
120
|
+
else
|
121
|
+
raise Informative, "Unknown external source parameters for #{name}: #{params}"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class AbstractExternalSource
|
126
|
+
include Config::Mixin
|
127
|
+
|
128
|
+
attr_reader :name, :params
|
129
|
+
|
130
|
+
def initialize(name, params)
|
131
|
+
@name, @params = name, params
|
132
|
+
end
|
133
|
+
|
134
|
+
def specification_from_sandbox(sandbox, platform)
|
135
|
+
if local_pod = sandbox.installed_pod_named(name, platform)
|
136
|
+
local_pod.top_specification
|
137
|
+
else
|
138
|
+
copy_external_source_into_sandbox(sandbox)
|
139
|
+
local_pod = sandbox.installed_pod_named(name, platform)
|
140
|
+
local_pod.clean if config.clean? && local_pod.exists?
|
141
|
+
local_pod.top_specification
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def ==(other_source)
|
146
|
+
return if other_source.nil?
|
147
|
+
name == other_source.name && params == other_source.params
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class GitSource < AbstractExternalSource
|
152
|
+
def copy_external_source_into_sandbox(sandbox)
|
153
|
+
puts " * Pre-downloading: '#{name}'" unless config.silent?
|
154
|
+
Downloader.for_target(sandbox.root + name, @params).tap do |downloader|
|
155
|
+
downloader.download
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def description
|
160
|
+
"from `#{@params[:git]}'".tap do |description|
|
161
|
+
description << ", commit `#{@params[:commit]}'" if @params[:commit]
|
162
|
+
description << ", tag `#{@params[:tag]}'" if @params[:tag]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# can be http, file, etc
|
168
|
+
class PodspecSource < AbstractExternalSource
|
169
|
+
def copy_external_source_into_sandbox(sandbox)
|
170
|
+
output_path = sandbox.root + "Local Podspecs/#{name}.podspec"
|
171
|
+
output_path.dirname.mkpath
|
172
|
+
puts " * Fetching podspec for `#{name}' from: #{@params[:podspec]}" unless config.silent?
|
173
|
+
open(@params[:podspec]) do |io|
|
174
|
+
output_path.open('w') { |f| f << io.read }
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def description
|
179
|
+
"from `#{@params[:podspec]}'"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
137
183
|
end
|
138
184
|
end
|
data/lib/cocoapods/downloader.rb
CHANGED
@@ -1,34 +1,46 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
1
3
|
module Pod
|
2
4
|
class Downloader
|
3
5
|
autoload :Git, 'cocoapods/downloader/git'
|
6
|
+
autoload :GitHub, 'cocoapods/downloader/git'
|
4
7
|
autoload :Mercurial, 'cocoapods/downloader/mercurial'
|
5
8
|
autoload :Subversion, 'cocoapods/downloader/subversion'
|
9
|
+
autoload :Http, 'cocoapods/downloader/http'
|
6
10
|
|
7
11
|
extend Executable
|
8
12
|
|
9
|
-
def self.
|
10
|
-
|
11
|
-
|
12
|
-
Git.new(pod_root, url, options)
|
13
|
-
elsif url = options.delete(:hg)
|
14
|
-
Mercurial.new(pod_root, url, options)
|
15
|
-
elsif url = options.delete(:svn)
|
16
|
-
Subversion.new(pod_root, url, options)
|
17
|
-
else
|
18
|
-
raise "Unsupported download strategy `#{source.inspect}'."
|
19
|
-
end
|
13
|
+
def self.for_pod(pod)
|
14
|
+
spec = pod.top_specification
|
15
|
+
for_target(pod.root, spec.source.dup)
|
20
16
|
end
|
21
17
|
|
22
|
-
attr_reader :
|
18
|
+
attr_reader :target_path, :url, :options
|
23
19
|
|
24
|
-
def initialize(
|
25
|
-
@
|
20
|
+
def initialize(target_path, url, options)
|
21
|
+
@target_path, @url, @options = target_path, url, options
|
22
|
+
@target_path.mkpath
|
26
23
|
end
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
private
|
26
|
+
|
27
|
+
def self.for_target(target_path, options)
|
28
|
+
options = options.dup
|
29
|
+
if url = options.delete(:git)
|
30
|
+
if url.to_s =~ /github.com/
|
31
|
+
GitHub.new(target_path, url, options)
|
32
|
+
else
|
33
|
+
Git.new(target_path, url, options)
|
34
|
+
end
|
35
|
+
elsif url = options.delete(:hg)
|
36
|
+
Mercurial.new(target_path, url, options)
|
37
|
+
elsif url = options.delete(:svn)
|
38
|
+
Subversion.new(target_path, url, options)
|
39
|
+
elsif url = options.delete(:http)
|
40
|
+
Http.new(target_path, url, options)
|
41
|
+
else
|
42
|
+
raise "Unsupported download strategy `#{options.inspect}'."
|
43
|
+
end
|
32
44
|
end
|
33
45
|
end
|
34
46
|
end
|
@@ -1,46 +1,156 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'zlib'
|
4
|
+
require 'digest/sha1'
|
5
|
+
|
1
6
|
module Pod
|
2
7
|
class Downloader
|
3
8
|
class Git < Downloader
|
9
|
+
include Config::Mixin
|
4
10
|
executable :git
|
5
11
|
|
12
|
+
MAX_CACHE_SIZE = 500
|
13
|
+
|
6
14
|
def download
|
7
|
-
|
8
|
-
if
|
15
|
+
create_cache unless cache_exist?
|
16
|
+
puts '-> Cloning git repo' if config.verbose?
|
17
|
+
if options[:tag]
|
9
18
|
download_tag
|
10
|
-
elsif
|
19
|
+
elsif options[:commit]
|
11
20
|
download_commit
|
12
21
|
else
|
13
22
|
download_head
|
14
23
|
end
|
24
|
+
removed_cached_repos_if_needed
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_cache
|
28
|
+
puts "-> Creating cache git repo (#{cache_path})" if config.verbose?
|
29
|
+
cache_path.rmtree if cache_path.exist?
|
30
|
+
cache_path.mkpath
|
31
|
+
git "clone '#{url}' #{cache_path}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def removed_cached_repos_if_needed
|
35
|
+
return unless caches_dir.exist?
|
36
|
+
Dir.chdir(caches_dir) do
|
37
|
+
repos = Pathname.new(caches_dir).children.select { |c| c.directory? }.sort_by(&:ctime)
|
38
|
+
while caches_size >= MAX_CACHE_SIZE && !repos.empty?
|
39
|
+
dir = repos.shift
|
40
|
+
puts '->'.yellow << " Removing git cache for `#{origin_url(dir)}'" if config.verbose?
|
41
|
+
dir.rmtree
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def cache_path
|
47
|
+
@cache_path ||= caches_dir + "#{Digest::SHA1.hexdigest(url.to_s)}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def cache_exist?
|
51
|
+
cache_path.exist? && origin_url(cache_path).to_s == url.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
def origin_url(dir)
|
55
|
+
Dir.chdir(dir) { `git config remote.origin.url`.chomp }
|
56
|
+
end
|
57
|
+
|
58
|
+
def caches_dir
|
59
|
+
Pathname.new(File.expand_path("~/Library/Caches/CocoaPods/Git"))
|
60
|
+
end
|
61
|
+
|
62
|
+
def clone_url
|
63
|
+
cache_path
|
64
|
+
end
|
65
|
+
|
66
|
+
def caches_size
|
67
|
+
# expressed in Mb
|
68
|
+
`du -cm`.split("\n").last.to_i
|
69
|
+
end
|
70
|
+
|
71
|
+
def update_cache
|
72
|
+
puts "-> Updating cache git repo (#{cache_path})" if config.verbose?
|
73
|
+
Dir.chdir(cache_path) do
|
74
|
+
git "reset --hard HEAD"
|
75
|
+
git "clean -d -x -f"
|
76
|
+
git "pull"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def ref_exists?(ref)
|
81
|
+
Dir.chdir(cache_path) { git "rev-list --max-count=1 #{ref}" }
|
82
|
+
$? == 0
|
83
|
+
end
|
84
|
+
|
85
|
+
def ensure_ref_exists(ref)
|
86
|
+
return if ref_exists?(ref)
|
87
|
+
# Skip pull if not needed
|
88
|
+
update_cache
|
89
|
+
raise Informative, "[!] Cache unable to find git reference `#{ref}' for `#{url}'.".red unless ref_exists?(ref)
|
15
90
|
end
|
16
91
|
|
17
92
|
def download_head
|
18
|
-
|
93
|
+
update_cache
|
94
|
+
git "clone '#{clone_url}' '#{target_path}'"
|
19
95
|
end
|
20
96
|
|
21
97
|
def download_tag
|
22
|
-
|
23
|
-
Dir.chdir(
|
98
|
+
ensure_ref_exists(options[:tag])
|
99
|
+
Dir.chdir(target_path) do
|
24
100
|
git "init"
|
25
|
-
git "remote add origin '#{
|
26
|
-
git "fetch origin tags/#{
|
101
|
+
git "remote add origin '#{clone_url}'"
|
102
|
+
git "fetch origin tags/#{options[:tag]}"
|
27
103
|
git "reset --hard FETCH_HEAD"
|
28
104
|
git "checkout -b activated-pod-commit"
|
29
105
|
end
|
30
106
|
end
|
31
107
|
|
32
108
|
def download_commit
|
33
|
-
|
34
|
-
|
35
|
-
|
109
|
+
ensure_ref_exists(options[:commit])
|
110
|
+
git "clone '#{clone_url}' '#{target_path}'"
|
111
|
+
Dir.chdir(target_path) do
|
112
|
+
git "checkout -b activated-pod-commit #{options[:commit]}"
|
36
113
|
end
|
37
114
|
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class GitHub < Git
|
118
|
+
def download_head
|
119
|
+
download_only? ? download_and_extract_tarball('master') : super
|
120
|
+
end
|
121
|
+
|
122
|
+
def download_tag
|
123
|
+
download_only? ? download_and_extract_tarball(options[:tag]) : super
|
124
|
+
end
|
38
125
|
|
39
|
-
def
|
40
|
-
super
|
41
|
-
|
126
|
+
def download_commit
|
127
|
+
download_only? ? download_and_extract_tarball(options[:commit]) : super
|
128
|
+
end
|
129
|
+
|
130
|
+
def tarball_url_for(id)
|
131
|
+
original_url, username, reponame = *(url.match(/[:\/]([\w\-]+)\/([\w\-]+)\.git/).to_a)
|
132
|
+
"https://github.com/#{username}/#{reponame}/tarball/#{id}"
|
133
|
+
end
|
134
|
+
|
135
|
+
def tmp_path
|
136
|
+
target_path + "tarball.tar.gz"
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def download_only?
|
142
|
+
@options[:download_only]
|
143
|
+
end
|
144
|
+
|
145
|
+
def download_and_extract_tarball(id)
|
146
|
+
File.open(tmp_path, "w+") do |tmpfile|
|
147
|
+
open tarball_url_for(id) do |archive|
|
148
|
+
tmpfile.write Zlib::GzipReader.new(archive).read
|
149
|
+
end
|
150
|
+
|
151
|
+
system "tar xf #{tmpfile.path} -C #{target_path} --strip-components 1"
|
152
|
+
end
|
42
153
|
end
|
43
154
|
end
|
44
155
|
end
|
45
156
|
end
|
46
|
-
|