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
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Sandbox
|
5
|
+
attr_reader :root
|
6
|
+
|
7
|
+
HEADERS_DIR = "Headers"
|
8
|
+
|
9
|
+
def initialize(path)
|
10
|
+
@root = Pathname.new(path)
|
11
|
+
@header_search_paths = [HEADERS_DIR]
|
12
|
+
|
13
|
+
FileUtils.mkdir_p(@root)
|
14
|
+
end
|
15
|
+
|
16
|
+
def implode
|
17
|
+
root.rmtree
|
18
|
+
end
|
19
|
+
|
20
|
+
def headers_root
|
21
|
+
root + HEADERS_DIR
|
22
|
+
end
|
23
|
+
|
24
|
+
def project_path
|
25
|
+
root + "Pods.xcodeproj"
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_header_file(namespace_path, relative_header_path)
|
29
|
+
namespaced_header_path = headers_root + namespace_path
|
30
|
+
namespaced_header_path.mkpath unless File.exist?(namespaced_header_path)
|
31
|
+
source = (root + relative_header_path).relative_path_from(namespaced_header_path)
|
32
|
+
Dir.chdir(namespaced_header_path) { FileUtils.ln_sf(source, relative_header_path.basename)}
|
33
|
+
@header_search_paths << namespaced_header_path.relative_path_from(root)
|
34
|
+
namespaced_header_path + relative_header_path.basename
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_header_files(namespace_path, relative_header_paths)
|
38
|
+
relative_header_paths.map { |path| add_header_file(namespace_path, path) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def header_search_paths
|
42
|
+
@header_search_paths.uniq.map { |path| "${PODS_ROOT}/#{path}" }
|
43
|
+
end
|
44
|
+
|
45
|
+
def prepare_for_install
|
46
|
+
headers_root.rmtree if headers_root.exist?
|
47
|
+
end
|
48
|
+
|
49
|
+
def podspec_for_name(name)
|
50
|
+
if spec_path = Dir[root + "#{name}/*.podspec"].first
|
51
|
+
Pathname.new(spec_path)
|
52
|
+
elsif spec_path = Dir[root + "Local Podspecs/#{name}.podspec"].first
|
53
|
+
Pathname.new(spec_path)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def installed_pod_named(name, platform)
|
58
|
+
if spec_path = podspec_for_name(name)
|
59
|
+
LocalPod.from_podspec(spec_path, self, platform)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/cocoapods/source.rb
CHANGED
@@ -1,29 +1,51 @@
|
|
1
1
|
module Pod
|
2
2
|
class Source
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
class Aggregate
|
4
|
+
def all
|
5
|
+
@sources ||= begin
|
6
|
+
repos_dir = Config.instance.repos_dir
|
7
|
+
unless repos_dir.exist?
|
8
|
+
raise Informative, "No spec repos found in `#{repos_dir}'. " \
|
9
|
+
"To fetch the `master' repo run: $ pod setup"
|
10
|
+
end
|
11
|
+
repos_dir.children.select(&:directory?).map { |repo| Source.new(repo) }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def all_sets
|
16
|
+
all.map(&:pod_sets).flatten
|
17
|
+
end
|
18
|
+
|
19
|
+
def search(dependency)
|
20
|
+
all.map { |s| s.search(dependency) }.compact.first ||
|
21
|
+
raise(Informative, "[!] Unable to find a pod named `#{dependency.name}'".red)
|
22
|
+
end
|
23
|
+
|
24
|
+
def search_by_name(query, full_text_search)
|
25
|
+
result = all.map { |s| s.search_by_name(query, full_text_search) }.flatten
|
26
|
+
if result.empty?
|
27
|
+
extra = ", author, summary, or description" if full_text_search
|
28
|
+
raise(Informative, "Unable to find a pod with name" \
|
29
|
+
"#{extra} matching `#{query}'")
|
9
30
|
end
|
10
|
-
|
31
|
+
result
|
11
32
|
end
|
12
33
|
end
|
13
34
|
|
35
|
+
def self.all
|
36
|
+
Aggregate.new.all
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.all_sets
|
40
|
+
Aggregate.new.all_sets
|
41
|
+
end
|
42
|
+
|
14
43
|
def self.search(dependency)
|
15
|
-
|
16
|
-
raise(Informative, "Unable to find a pod named `#{dependency.name}'")
|
44
|
+
Aggregate.new.search(dependency)
|
17
45
|
end
|
18
46
|
|
19
|
-
def self.search_by_name(
|
20
|
-
|
21
|
-
if result.empty?
|
22
|
-
extra = ", summary, or description" if full_text_search
|
23
|
-
raise(Informative, "Unable to find a pod with name" \
|
24
|
-
"#{extra} matching `#{query}'")
|
25
|
-
end
|
26
|
-
result
|
47
|
+
def self.search_by_name(name, full_text_search)
|
48
|
+
Aggregate.new.search_by_name(name, full_text_search)
|
27
49
|
end
|
28
50
|
|
29
51
|
attr_reader :repo
|
@@ -35,7 +57,7 @@ module Pod
|
|
35
57
|
def pod_sets
|
36
58
|
@repo.children.map do |child|
|
37
59
|
if child.directory? && child.basename.to_s != '.git'
|
38
|
-
Specification::Set.
|
60
|
+
Specification::Set.new(child)
|
39
61
|
end
|
40
62
|
end.compact
|
41
63
|
end
|
@@ -46,7 +68,7 @@ module Pod
|
|
46
68
|
set.name == dependency.top_level_spec_name &&
|
47
69
|
# Now either check if it's a dependency on the top level spec, or if it's not
|
48
70
|
# check if the requested subspec exists in the top level spec.
|
49
|
-
|
71
|
+
set.specification.subspec_by_name(dependency.name)
|
50
72
|
end
|
51
73
|
end
|
52
74
|
|
@@ -54,7 +76,7 @@ module Pod
|
|
54
76
|
pod_sets.map do |set|
|
55
77
|
text = if full_text_search
|
56
78
|
s = set.specification
|
57
|
-
"#{s.name} #{s.summary} #{s.description}"
|
79
|
+
"#{s.name} #{s.authors} #{s.summary} #{s.description}"
|
58
80
|
else
|
59
81
|
set.name
|
60
82
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'xcodeproj/config'
|
2
|
+
|
1
3
|
module Pod
|
2
4
|
extend Config::Mixin
|
3
5
|
|
@@ -6,166 +8,293 @@ module Pod
|
|
6
8
|
end
|
7
9
|
|
8
10
|
class Specification
|
9
|
-
autoload :Set,
|
11
|
+
autoload :Set, 'cocoapods/specification/set'
|
12
|
+
autoload :Statistics, 'cocoapods/specification/statistics'
|
13
|
+
|
14
|
+
### Initalization
|
10
15
|
|
11
16
|
# The file is expected to define and return a Pods::Specification.
|
12
|
-
|
17
|
+
# If name is equals to nil it returns the top level Specification,
|
18
|
+
# otherwise it returned the specification with the name that matches
|
19
|
+
def self.from_file(path, subspec_name = nil)
|
13
20
|
unless path.exist?
|
14
21
|
raise Informative, "No podspec exists at path `#{path}'."
|
15
22
|
end
|
16
|
-
spec = Pod._eval_podspec(path)
|
23
|
+
spec = ::Pod._eval_podspec(path)
|
17
24
|
spec.defined_in_file = path
|
18
|
-
spec
|
25
|
+
spec.subspec_by_name(subspec_name)
|
19
26
|
end
|
20
27
|
|
21
|
-
|
28
|
+
def initialize(parent = nil, name = nil)
|
29
|
+
@parent, @name = parent, name
|
30
|
+
@define_for_platforms = [:osx, :ios]
|
31
|
+
@clean_paths, @subspecs = [], []
|
32
|
+
@deployment_target = {}
|
33
|
+
unless parent
|
34
|
+
@source = {:git => ''}
|
35
|
+
end
|
22
36
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
37
|
+
# multi-platform attributes
|
38
|
+
%w[ source_files resources preserve_paths exclude_header_search_paths frameworks libraries dependencies compiler_flags].each do |attr|
|
39
|
+
instance_variable_set( "@#{attr}", { :ios => [], :osx => [] } )
|
40
|
+
end
|
41
|
+
@xcconfig = { :ios => Xcodeproj::Config.new, :osx => Xcodeproj::Config.new }
|
27
42
|
|
28
|
-
|
29
|
-
def post_initialize
|
30
|
-
@dependencies, @source_files, @resources, @clean_paths, @subspecs = [], [], [], [], []
|
31
|
-
@platform = Platform.new(nil)
|
32
|
-
@xcconfig = Xcodeproj::Config.new
|
43
|
+
yield self if block_given?
|
33
44
|
end
|
34
45
|
|
35
|
-
|
36
|
-
|
37
|
-
attr_accessor :name
|
38
|
-
attr_accessor :homepage
|
39
|
-
attr_accessor :description
|
40
|
-
attr_accessor :source
|
41
|
-
attr_accessor :license
|
46
|
+
### Meta programming
|
42
47
|
|
43
|
-
|
44
|
-
|
45
|
-
|
48
|
+
# Creates a top level attribute reader. A lambda can
|
49
|
+
# be passed to process the ivar before returning it
|
50
|
+
def self.top_attr_reader(attr, read_lambda = nil)
|
51
|
+
define_method(attr) do
|
52
|
+
ivar = instance_variable_get("@#{attr}")
|
53
|
+
@parent ? top_level_parent.send(attr) : ( read_lambda ? read_lambda.call(self, ivar) : ivar )
|
54
|
+
end
|
46
55
|
end
|
47
56
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
57
|
+
# Creates a top level attribute writer. A lambda can
|
58
|
+
# be passed to initalize the value
|
59
|
+
def self.top_attr_writer(attr, init_lambda = nil)
|
60
|
+
define_method("#{attr}=") do |value|
|
61
|
+
raise Informative, "Can't set `#{attr}' for subspecs." if @parent
|
62
|
+
instance_variable_set("@#{attr}", init_lambda ? init_lambda.call(value) : value);
|
53
63
|
end
|
54
|
-
@authors = authors || list.first
|
55
64
|
end
|
56
|
-
alias_method :author=, :authors=
|
57
|
-
attr_reader :authors
|
58
65
|
|
66
|
+
# Creates a top level attribute accessor. A lambda can
|
67
|
+
# be passed to initialize the value in the attribute writer.
|
68
|
+
def self.top_attr_accessor(attr, writer_labmda = nil)
|
69
|
+
top_attr_reader attr
|
70
|
+
top_attr_writer attr, writer_labmda
|
71
|
+
end
|
59
72
|
|
60
|
-
|
61
|
-
|
73
|
+
# Returns the value of the attribute for the active platform
|
74
|
+
# chained with the upstream specifications. The ivar must store
|
75
|
+
# the platform specific values as an array.
|
76
|
+
def self.pltf_chained_attr_reader(attr)
|
77
|
+
define_method(attr) do
|
78
|
+
active_plaform_check
|
79
|
+
ivar_value = instance_variable_get("@#{attr}")[active_platform]
|
80
|
+
@parent ? @parent.send(attr) + ivar_value : ( ivar_value )
|
81
|
+
end
|
62
82
|
end
|
63
|
-
attr_reader :summary
|
64
83
|
|
65
|
-
def
|
66
|
-
|
84
|
+
def active_plaform_check
|
85
|
+
raise Informative, "#{self.inspect} not activated for a platform before consumption." unless active_platform
|
67
86
|
end
|
68
87
|
|
69
|
-
|
70
|
-
|
71
|
-
|
88
|
+
# Attribute writer that works in conjuction with the PlatformProxy.
|
89
|
+
def self.platform_attr_writer(attr, block = nil)
|
90
|
+
define_method("#{attr}=") do |value|
|
91
|
+
current = instance_variable_get("@#{attr}")
|
92
|
+
@define_for_platforms.each do |platform|
|
93
|
+
block ? current[platform] = block.call(value, current[platform]) : current[platform] = value
|
94
|
+
end
|
95
|
+
end
|
72
96
|
end
|
73
|
-
attr_reader :part_of
|
74
97
|
|
75
|
-
def
|
76
|
-
|
98
|
+
def self.pltf_chained_attr_accessor(attr, block = nil)
|
99
|
+
pltf_chained_attr_reader(attr)
|
100
|
+
platform_attr_writer(attr, block)
|
77
101
|
end
|
78
102
|
|
79
|
-
|
80
|
-
|
103
|
+
# The PlatformProxy works in conjuction with Specification#_on_platform.
|
104
|
+
# It allows a syntax like `spec.ios.source_files = file`
|
105
|
+
class PlatformProxy
|
106
|
+
def initialize(specification, platform)
|
107
|
+
@specification, @platform = specification, platform
|
108
|
+
end
|
109
|
+
|
110
|
+
%w{ source_files= resource= resources= xcconfig= framework= frameworks= library= libraries= compiler_flags= deployment_target= dependency }.each do |method|
|
111
|
+
define_method(method) do |args|
|
112
|
+
@specification._on_platform(@platform) do
|
113
|
+
@specification.send(method, args)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
81
117
|
end
|
82
|
-
attr_reader :source_files
|
83
118
|
|
84
|
-
def
|
85
|
-
|
119
|
+
def ios
|
120
|
+
PlatformProxy.new(self, :ios)
|
86
121
|
end
|
87
|
-
attr_reader :resources
|
88
|
-
alias_method :resource=, :resources=
|
89
122
|
|
90
|
-
def
|
91
|
-
|
123
|
+
def osx
|
124
|
+
PlatformProxy.new(self, :osx)
|
92
125
|
end
|
93
|
-
|
126
|
+
|
127
|
+
### Deprecated attributes - TODO: remove once master repo and fixtures have been updated
|
128
|
+
|
129
|
+
attr_writer :part_of_dependency
|
130
|
+
attr_writer :part_of
|
131
|
+
|
132
|
+
top_attr_accessor :clean_paths, lambda { |patterns| pattern_list(patterns) }
|
94
133
|
alias_method :clean_path=, :clean_paths=
|
95
134
|
|
96
|
-
|
97
|
-
|
135
|
+
### Regular attributes
|
136
|
+
|
137
|
+
attr_accessor :parent
|
138
|
+
attr_accessor :preferred_dependency
|
139
|
+
|
140
|
+
def name
|
141
|
+
@parent ? "#{@parent.name}/#{@name}" : @name
|
98
142
|
end
|
99
|
-
|
143
|
+
attr_writer :name
|
144
|
+
|
145
|
+
### Attributes that return the first value defined in the chain
|
100
146
|
|
101
|
-
def
|
102
|
-
|
103
|
-
self.xcconfig = { 'OTHER_LDFLAGS' => frameworks.join(' -framework ').strip }
|
147
|
+
def platform
|
148
|
+
@platform || ( @parent ? @parent.platform : nil )
|
104
149
|
end
|
105
|
-
alias_method :framework=, :frameworks=
|
106
150
|
|
107
|
-
def
|
108
|
-
|
109
|
-
self.xcconfig = { 'OTHER_LDFLAGS' => libraries.join(' -l').strip }
|
151
|
+
def platform=(platform)
|
152
|
+
@platform = Platform.new(*platform)
|
110
153
|
end
|
111
|
-
alias_method :library=, :libraries=
|
112
154
|
|
113
|
-
|
114
|
-
|
155
|
+
# If not platform is specified all the platforms are returned.
|
156
|
+
def available_platforms
|
157
|
+
platform.nil? ? @define_for_platforms.map { |platform| Platform.new(platform, deployment_target(platform)) } : [ platform ]
|
115
158
|
end
|
116
|
-
|
117
|
-
|
159
|
+
|
160
|
+
### Top level attributes. These attributes represent the unique features of pod and can't be specified by subspecs.
|
161
|
+
|
162
|
+
top_attr_accessor :defined_in_file
|
163
|
+
top_attr_accessor :source
|
164
|
+
top_attr_accessor :homepage
|
165
|
+
top_attr_accessor :summary
|
166
|
+
top_attr_accessor :documentation
|
167
|
+
top_attr_accessor :requires_arc
|
168
|
+
top_attr_accessor :license, lambda { |l| ( l.kind_of? String ) ? { :type => l } : l }
|
169
|
+
top_attr_accessor :version, lambda { |v| Version.new(v) }
|
170
|
+
top_attr_accessor :authors, lambda { |a| parse_authors(a) }
|
171
|
+
top_attr_accessor :header_mappings_dir, lambda { |file| Pathname.new(file) } # If not provided the headers files are flattened
|
172
|
+
top_attr_accessor :prefix_header_file, lambda { |file| Pathname.new(file) }
|
173
|
+
top_attr_accessor :prefix_header_contents
|
174
|
+
|
175
|
+
top_attr_reader :description, lambda {|instance, ivar| ivar || instance.summary }
|
176
|
+
top_attr_writer :description
|
177
|
+
|
178
|
+
top_attr_reader :header_dir, lambda {|instance, ivar| ivar || instance.pod_destroot_name }
|
179
|
+
top_attr_writer :header_dir, lambda {|dir| Pathname.new(dir) }
|
180
|
+
|
181
|
+
alias_method :author=, :authors=
|
182
|
+
|
183
|
+
def self.parse_authors(*names_and_email_addresses)
|
184
|
+
list = names_and_email_addresses.flatten
|
185
|
+
unless list.first.is_a?(Hash)
|
186
|
+
authors = list.last.is_a?(Hash) ? list.pop : {}
|
187
|
+
list.each { |name| authors[name] = nil }
|
188
|
+
end
|
189
|
+
authors || list.first
|
118
190
|
end
|
119
191
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
192
|
+
### Attributes **with** multiple platform support
|
193
|
+
|
194
|
+
pltf_chained_attr_accessor :source_files, lambda {|value, current| pattern_list(value) }
|
195
|
+
pltf_chained_attr_accessor :resources, lambda {|value, current| pattern_list(value) }
|
196
|
+
pltf_chained_attr_accessor :preserve_paths, lambda {|value, current| pattern_list(value) } # Paths that should not be cleaned
|
197
|
+
pltf_chained_attr_accessor :exclude_header_search_paths, lambda {|value, current| pattern_list(value) } # Headers to be excluded from being added to search paths (RestKit)
|
198
|
+
pltf_chained_attr_accessor :frameworks, lambda {|value, current| (current << value).flatten }
|
199
|
+
pltf_chained_attr_accessor :libraries, lambda {|value, current| (current << value).flatten }
|
200
|
+
|
201
|
+
alias_method :resource=, :resources=
|
202
|
+
alias_method :framework=, :frameworks=
|
203
|
+
alias_method :library=, :libraries=
|
204
|
+
|
205
|
+
platform_attr_writer :xcconfig, lambda {|value, current| current.tap { |c| c.merge!(value) } }
|
206
|
+
|
207
|
+
def xcconfig
|
208
|
+
raw_xconfig.dup.
|
209
|
+
tap { |x| x.libraries.merge libraries }.
|
210
|
+
tap { |x| x.frameworks.merge frameworks }
|
125
211
|
end
|
126
212
|
|
127
|
-
def
|
128
|
-
@
|
213
|
+
def raw_xconfig
|
214
|
+
@parent ? @parent.raw_xconfig.merge(@xcconfig[active_platform]) : @xcconfig[active_platform]
|
129
215
|
end
|
130
|
-
attr_reader :platform
|
131
216
|
|
132
|
-
|
217
|
+
|
218
|
+
def compiler_flags
|
219
|
+
if @parent
|
220
|
+
chained = @compiler_flags[active_platform].clone
|
221
|
+
# TODO hack to get the parent's compiler flags without it being
|
222
|
+
# converted to a String by Specification#compiler_flags.
|
223
|
+
chained.unshift @parent.instance_variable_get(:@compiler_flags)[active_platform]
|
224
|
+
else
|
225
|
+
chained = @compiler_flags[active_platform].clone
|
226
|
+
chained.unshift '-fobjc-arc' if @requires_arc
|
227
|
+
chained.unshift ''
|
228
|
+
end
|
229
|
+
chained.join(' ')
|
230
|
+
end
|
231
|
+
|
232
|
+
platform_attr_writer :compiler_flags, lambda {|value, current| current << value }
|
133
233
|
|
134
234
|
def dependency(*name_and_version_requirements)
|
135
235
|
name, *version_requirements = name_and_version_requirements.flatten
|
236
|
+
raise Informative, "A specification can't require self as a subspec" if name == self.name
|
237
|
+
raise Informative, "A subspec can't require one of its parents specifications" if @parent && @parent.name.include?(name)
|
136
238
|
dep = Dependency.new(name, *version_requirements)
|
137
|
-
@
|
239
|
+
@define_for_platforms.each do |platform|
|
240
|
+
@dependencies[platform] << dep
|
241
|
+
end
|
138
242
|
dep
|
139
243
|
end
|
140
|
-
attr_reader :dependencies
|
141
244
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
245
|
+
# External dependencies are inherited by subspecs
|
246
|
+
def external_dependencies(all_platforms = false)
|
247
|
+
active_plaform_check unless all_platforms
|
248
|
+
result = all_platforms ? @dependencies.values.flatten : @dependencies[active_platform]
|
249
|
+
result += parent.external_dependencies if parent
|
250
|
+
result
|
146
251
|
end
|
147
|
-
attr_reader :subspecs
|
148
252
|
|
149
|
-
#
|
253
|
+
# A specification inherits the preferred_dependency or
|
254
|
+
# all the compatible subspecs as dependencies
|
255
|
+
def subspec_dependencies
|
256
|
+
active_plaform_check
|
257
|
+
specs = preferred_dependency ? [subspec_by_name("#{name}/#{preferred_dependency}")] : subspecs
|
258
|
+
specs.compact \
|
259
|
+
.select { |s| s.supports_platform?(active_platform) } \
|
260
|
+
.map { |s| Dependency.new(s.name, version) }
|
261
|
+
end
|
150
262
|
|
151
|
-
|
152
|
-
|
263
|
+
def dependencies
|
264
|
+
external_dependencies + subspec_dependencies
|
265
|
+
end
|
153
266
|
|
154
267
|
include Config::Mixin
|
155
|
-
|
156
|
-
def
|
157
|
-
|
268
|
+
|
269
|
+
def top_level_parent
|
270
|
+
@parent ? @parent.top_level_parent : self
|
158
271
|
end
|
159
|
-
|
160
|
-
def
|
161
|
-
|
272
|
+
|
273
|
+
def subspec?
|
274
|
+
!@parent.nil?
|
162
275
|
end
|
163
276
|
|
164
|
-
def
|
165
|
-
|
277
|
+
def subspec(name, &block)
|
278
|
+
subspec = Specification.new(self, name, &block)
|
279
|
+
@subspecs << subspec
|
280
|
+
subspec
|
281
|
+
end
|
282
|
+
attr_reader :subspecs
|
283
|
+
|
284
|
+
def recursive_subspecs
|
285
|
+
unless @recursive_subspecs
|
286
|
+
mapper = lambda do |spec|
|
287
|
+
spec.subspecs.map do |subspec|
|
288
|
+
[subspec, *mapper.call(subspec)]
|
289
|
+
end.flatten
|
290
|
+
end
|
291
|
+
@recursive_subspecs = mapper.call self
|
292
|
+
end
|
293
|
+
@recursive_subspecs
|
166
294
|
end
|
167
295
|
|
168
296
|
def subspec_by_name(name)
|
297
|
+
return self if name.nil? || name == self.name
|
169
298
|
# Remove this spec's name from the beginning of the name we’re looking for
|
170
299
|
# and take the first component from the remainder, which is the spec we need
|
171
300
|
# to find now.
|
@@ -175,38 +304,24 @@ module Pod
|
|
175
304
|
# If this was the last component in the name, then return the subspec,
|
176
305
|
# otherwise we recursively keep calling subspec_by_name until we reach the
|
177
306
|
# last one and return that
|
178
|
-
remainder.empty? ? subspec : subspec.subspec_by_name(name)
|
179
|
-
end
|
180
|
-
|
181
|
-
def ==(other)
|
182
|
-
object_id == other.object_id ||
|
183
|
-
(self.class === other &&
|
184
|
-
name && name == other.name &&
|
185
|
-
version && version == other.version)
|
186
|
-
end
|
187
307
|
|
188
|
-
|
189
|
-
|
308
|
+
raise Informative, "Unable to find a subspec named `#{name}'." unless subspec
|
309
|
+
remainder.empty? ? subspec : subspec.subspec_by_name(name)
|
190
310
|
end
|
191
311
|
|
192
|
-
def
|
193
|
-
|
194
|
-
Set.by_specification_name(part_of.name)
|
195
|
-
end
|
312
|
+
def local?
|
313
|
+
!source.nil? && !source[:local].nil?
|
196
314
|
end
|
197
315
|
|
198
|
-
|
199
|
-
|
200
|
-
(set = part_of_specification_set) && set.specification
|
316
|
+
def local_path
|
317
|
+
Pathname.new(File.expand_path(source[:local]))
|
201
318
|
end
|
202
319
|
|
203
320
|
def pod_destroot
|
204
|
-
if
|
205
|
-
part_of_specification.pod_destroot
|
206
|
-
elsif local?
|
321
|
+
if local?
|
207
322
|
local_path
|
208
323
|
else
|
209
|
-
config.project_pods_root +
|
324
|
+
config.project_pods_root + top_level_parent.name
|
210
325
|
end
|
211
326
|
end
|
212
327
|
|
@@ -216,15 +331,7 @@ module Pod
|
|
216
331
|
end
|
217
332
|
end
|
218
333
|
|
219
|
-
def
|
220
|
-
!part_of.nil?
|
221
|
-
end
|
222
|
-
|
223
|
-
def podfile?
|
224
|
-
false
|
225
|
-
end
|
226
|
-
|
227
|
-
def pattern_list(patterns)
|
334
|
+
def self.pattern_list(patterns)
|
228
335
|
if patterns.is_a?(Array) && (!defined?(Rake) || !patterns.is_a?(Rake::FileList))
|
229
336
|
patterns
|
230
337
|
else
|
@@ -232,121 +339,14 @@ module Pod
|
|
232
339
|
end
|
233
340
|
end
|
234
341
|
|
235
|
-
# Returns all resource files of this pod, but relative to the
|
236
|
-
# project pods root.
|
237
|
-
def expanded_resources
|
238
|
-
files = []
|
239
|
-
resources.each do |pattern|
|
240
|
-
pattern = pod_destroot + pattern
|
241
|
-
pattern.glob.each do |file|
|
242
|
-
files << file.relative_path_from(config.project_pods_root)
|
243
|
-
end
|
244
|
-
end
|
245
|
-
files
|
246
|
-
end
|
247
|
-
|
248
|
-
# Returns full paths to clean for this pod.
|
249
|
-
def expanded_clean_paths
|
250
|
-
files = []
|
251
|
-
clean_paths.each do |pattern|
|
252
|
-
pattern = pod_destroot + pattern
|
253
|
-
pattern.glob.each do |file|
|
254
|
-
files << file
|
255
|
-
end
|
256
|
-
end
|
257
|
-
files
|
258
|
-
end
|
259
|
-
|
260
|
-
# Returns all source files of this pod including header files,
|
261
|
-
# but relative to the project pods root.
|
262
|
-
#
|
263
|
-
# If the pattern is the path to a directory, the pattern will
|
264
|
-
# automatically glob for c, c++, Objective-C, and Objective-C++
|
265
|
-
# files.
|
266
|
-
def expanded_source_files
|
267
|
-
files = []
|
268
|
-
source_files.each do |pattern|
|
269
|
-
pattern = pod_destroot + pattern
|
270
|
-
pattern = pattern + '*.{h,m,mm,c,cpp}' if pattern.directory?
|
271
|
-
pattern.glob.each do |file|
|
272
|
-
files << file.relative_path_from(config.project_pods_root)
|
273
|
-
end
|
274
|
-
end
|
275
|
-
files
|
276
|
-
end
|
277
|
-
|
278
|
-
def implementation_files
|
279
|
-
expanded_source_files.select { |f| f.extname != '.h' }
|
280
|
-
end
|
281
|
-
|
282
|
-
# Returns only the header files of this pod.
|
283
|
-
def header_files
|
284
|
-
expanded_source_files.select { |f| f.extname == '.h' }
|
285
|
-
end
|
286
|
-
|
287
342
|
# This method takes a header path and returns the location it should have
|
288
343
|
# in the pod's header dir.
|
289
344
|
#
|
290
345
|
# By default all headers are copied to the pod's header dir without any
|
291
|
-
# namespacing.
|
292
|
-
#
|
346
|
+
# namespacing. However if the top level attribute accessor header_mappings_dir
|
347
|
+
# is specified the namespacing will be preserved from that directory.
|
293
348
|
def copy_header_mapping(from)
|
294
|
-
from.basename
|
295
|
-
end
|
296
|
-
|
297
|
-
# See copy_header_mapping.
|
298
|
-
def copy_header_mappings
|
299
|
-
header_files.inject({}) do |mappings, from|
|
300
|
-
from_without_prefix = from.relative_path_from(pod_destroot_name)
|
301
|
-
to = header_dir + copy_header_mapping(from_without_prefix)
|
302
|
-
(mappings[to.dirname] ||= []) << from
|
303
|
-
mappings
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
# Returns a list of search paths where the pod's headers can be found. This
|
308
|
-
# includes the pod's header dir root and any other directories that might
|
309
|
-
# have been added by overriding the copy_header_mapping/copy_header_mappings
|
310
|
-
# methods.
|
311
|
-
def header_search_paths
|
312
|
-
dirs = [header_dir] + copy_header_mappings.keys
|
313
|
-
dirs.map { |dir| %{"$(PODS_ROOT)/Headers/#{dir}"} }
|
314
|
-
end
|
315
|
-
|
316
|
-
def to_s
|
317
|
-
"#{name} (#{version})"
|
318
|
-
end
|
319
|
-
|
320
|
-
def inspect
|
321
|
-
"#<#{self.class.name} for #{to_s}>"
|
322
|
-
end
|
323
|
-
|
324
|
-
def validate!
|
325
|
-
missing = []
|
326
|
-
missing << "`name'" unless name
|
327
|
-
missing << "`version'" unless version
|
328
|
-
missing << "`summary'" unless summary
|
329
|
-
missing << "`homepage'" unless homepage
|
330
|
-
missing << "`author(s)'" unless authors
|
331
|
-
missing << "either `source' or `part_of'" unless source || part_of
|
332
|
-
missing << "`source_files'" if source_files.empty? && subspecs.empty?
|
333
|
-
# TODO
|
334
|
-
# * validate subspecs
|
335
|
-
|
336
|
-
incorrect = []
|
337
|
-
allowed = [nil, :ios, :osx]
|
338
|
-
incorrect << ["`platform'", allowed] unless allowed.include?(platform.name)
|
339
|
-
|
340
|
-
no_errors_found = missing.empty? && incorrect.empty?
|
341
|
-
|
342
|
-
unless no_errors_found
|
343
|
-
message = "The following #{(missing + incorrect).size == 1 ? 'attribute is' : 'attributes are'}:\n"
|
344
|
-
message << "* missing: #{missing.join(", ")}" unless missing.empty?
|
345
|
-
message << "* incorrect: #{incorrect.map { |x| "#{x[0]} (#{x[1..-1]})" }.join(", ")}" unless incorrect.empty?
|
346
|
-
raise Informative, message
|
347
|
-
end
|
348
|
-
|
349
|
-
no_errors_found
|
349
|
+
header_mappings_dir ? from.relative_path_from(header_mappings_dir) : from.basename
|
350
350
|
end
|
351
351
|
|
352
352
|
# This is a convenience method which gets called after all pods have been
|
@@ -365,53 +365,76 @@ module Pod
|
|
365
365
|
def post_install(target)
|
366
366
|
end
|
367
367
|
|
368
|
-
|
369
|
-
|
368
|
+
def podfile?
|
369
|
+
false
|
370
|
+
end
|
370
371
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
372
|
+
# This is used by the specification set
|
373
|
+
def dependency_by_top_level_spec_name(name)
|
374
|
+
external_dependencies(true).each do |dep|
|
375
|
+
return dep if dep.top_level_spec_name == name
|
376
|
+
end
|
377
|
+
end
|
376
378
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
dependency(@parent.name, version) if @parent.is_a?(Subspec)
|
379
|
+
def to_s
|
380
|
+
"#{name} (#{version})"
|
381
|
+
end
|
381
382
|
|
382
|
-
|
383
|
-
|
383
|
+
def inspect
|
384
|
+
"#<#{self.class.name} for #{to_s}>"
|
385
|
+
end
|
384
386
|
|
385
|
-
|
387
|
+
def ==(other)
|
388
|
+
object_id == other.object_id ||
|
389
|
+
(self.class === other &&
|
390
|
+
name && name == other.name &&
|
391
|
+
version && version == other.version)
|
392
|
+
end
|
386
393
|
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
394
|
+
# Returns whether the specification is supported in a given platform
|
395
|
+
def supports_platform?(*platform)
|
396
|
+
platform = platform[0].is_a?(Platform) ? platform[0] : Platform.new(*platform)
|
397
|
+
available_platforms.any? { |p| platform.supports?(p) }
|
398
|
+
end
|
392
399
|
|
393
|
-
|
394
|
-
|
395
|
-
|
400
|
+
# Defines the active platform for comsumption of the specification and
|
401
|
+
# returns self for method chainability.
|
402
|
+
# The active platform must the the same accross the chain so attributes
|
403
|
+
# that are inherited can be correctly resolved.
|
404
|
+
def activate_platform(*platform)
|
405
|
+
platform = platform[0].is_a?(Platform) ? platform[0] : Platform.new(*platform)
|
406
|
+
raise Informative, "#{to_s} is not compatible with #{platform}." unless supports_platform?(platform)
|
407
|
+
top_level_parent.active_platform = platform.to_sym
|
408
|
+
self
|
409
|
+
end
|
396
410
|
|
397
|
-
|
398
|
-
# but need to think if there's a better way to do this.
|
411
|
+
top_attr_accessor :active_platform
|
399
412
|
|
400
|
-
|
401
|
-
@summary ? @summary : top_level_parent.summary
|
402
|
-
end
|
413
|
+
### Not attributes
|
403
414
|
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
415
|
+
# @visibility private
|
416
|
+
#
|
417
|
+
# This is used by PlatformProxy to assign attributes for the scoped platform.
|
418
|
+
def _on_platform(platform)
|
419
|
+
before, @define_for_platforms = @define_for_platforms, [platform]
|
420
|
+
yield
|
421
|
+
ensure
|
422
|
+
@define_for_platforms = before
|
423
|
+
end
|
408
424
|
|
409
|
-
|
410
|
-
|
411
|
-
|
425
|
+
# @visibility private
|
426
|
+
#
|
427
|
+
# This is multi-platform and to support
|
428
|
+
# subspecs with different platforms is is resolved as the
|
429
|
+
# first non nil value accross the chain.
|
430
|
+
def deployment_target=(version)
|
431
|
+
raise Informative, "The deployment target must be defined per platform like `s.ios.deployment_target = '5.0'`." unless @define_for_platforms.count == 1
|
432
|
+
@deployment_target[@define_for_platforms.first] = version
|
412
433
|
end
|
413
434
|
|
435
|
+
def deployment_target(platform)
|
436
|
+
@deployment_target[platform] || ( @parent ? @parent.deployment_target(platform) : nil )
|
437
|
+
end
|
414
438
|
end
|
415
|
-
|
416
439
|
Spec = Specification
|
417
440
|
end
|