cocoapods 0.5.1 → 0.6.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|