cocoapods 0.0.1
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/LICENSE +19 -0
- data/README.md +184 -0
- data/bin/pod +9 -0
- data/lib/cocoapods.rb +32 -0
- data/lib/cocoapods/command.rb +88 -0
- data/lib/cocoapods/command/install.rb +48 -0
- data/lib/cocoapods/command/repo.rb +60 -0
- data/lib/cocoapods/command/setup.rb +32 -0
- data/lib/cocoapods/command/spec.rb +28 -0
- data/lib/cocoapods/config.rb +49 -0
- data/lib/cocoapods/dependency.rb +39 -0
- data/lib/cocoapods/downloader.rb +55 -0
- data/lib/cocoapods/executable.rb +13 -0
- data/lib/cocoapods/installer.rb +62 -0
- data/lib/cocoapods/resolver.rb +24 -0
- data/lib/cocoapods/source.rb +31 -0
- data/lib/cocoapods/specification.rb +203 -0
- data/lib/cocoapods/specification/set.rb +82 -0
- data/lib/cocoapods/version.rb +9 -0
- data/lib/cocoapods/xcode/config.rb +33 -0
- data/lib/cocoapods/xcode/project.rb +132 -0
- data/xcode-project-templates/cocoa-touch-static-library/Pods-Prefix.pch +7 -0
- data/xcode-project-templates/cocoa-touch-static-library/Pods.xcconfig +1 -0
- data/xcode-project-templates/cocoa-touch-static-library/Pods.xcodeproj/project.pbxproj +232 -0
- metadata +90 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
module Pod
|
2
|
+
class Command
|
3
|
+
class Setup < Command
|
4
|
+
def self.banner
|
5
|
+
%{Setup CocoaPods environment:
|
6
|
+
|
7
|
+
$ pod setup
|
8
|
+
|
9
|
+
Creates a directory at `~/.cocoapods' which will hold your spec-repos.
|
10
|
+
This is where it will create a clone of the public `master' spec-repo from:
|
11
|
+
|
12
|
+
https://github.com/alloy/cocoapods-specs}
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(argv)
|
16
|
+
super unless argv.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
def master_repo_url
|
20
|
+
'git://github.com/alloy/cocoapods-specs.git'
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_master_repo_command
|
24
|
+
@command ||= Repo.new(ARGV.new(['add', 'master', master_repo_url]))
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
add_master_repo_command.run
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Pod
|
2
|
+
class Command
|
3
|
+
class Spec < Command
|
4
|
+
def self.banner
|
5
|
+
%{Managing PodSpec files:
|
6
|
+
|
7
|
+
$ pod help spec
|
8
|
+
|
9
|
+
pod spec create NAME
|
10
|
+
Creates a directory for your new pod, named `NAME', with a default
|
11
|
+
directory structure and accompanying `NAME.podspec'.
|
12
|
+
|
13
|
+
pod spec init NAME
|
14
|
+
Creates a PodSpec, in the current working dir, called `NAME.podspec'.
|
15
|
+
Use this for existing libraries.
|
16
|
+
|
17
|
+
pod spec lint NAME
|
18
|
+
Validates `NAME.podspec' from a local spec-repo. In case `NAME' is
|
19
|
+
omitted, it defaults to the PodSpec in the current working dir.
|
20
|
+
|
21
|
+
pod spec push REMOTE
|
22
|
+
Validates `NAME.podspec' in the current working dir, copies it to the
|
23
|
+
local clone of the `REMOTE' spec-repo, and pushes it to the `REMOTE'
|
24
|
+
spec-repo. In case `REMOTE' is omitted, it defaults to `master'.}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Config
|
5
|
+
def self.instance
|
6
|
+
@instance ||= new
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.instance=(instance)
|
10
|
+
@instance = instance
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :repos_dir, :project_pods_root, :clean, :verbose, :silent
|
14
|
+
alias_method :clean?, :clean
|
15
|
+
alias_method :verbose?, :verbose
|
16
|
+
alias_method :silent?, :silent
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@repos_dir = Pathname.new(File.expand_path("~/.cocoapods"))
|
20
|
+
@clean = true
|
21
|
+
@verbose = false
|
22
|
+
@silent = false
|
23
|
+
end
|
24
|
+
|
25
|
+
def project_root
|
26
|
+
Pathname.pwd
|
27
|
+
end
|
28
|
+
|
29
|
+
def project_pods_root
|
30
|
+
@project_pods_root ||= project_root + 'Pods'
|
31
|
+
end
|
32
|
+
|
33
|
+
def project_podfile
|
34
|
+
unless @project_podfile
|
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
|
+
end
|
42
|
+
|
43
|
+
module Mixin
|
44
|
+
def config
|
45
|
+
Config.instance
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Gem
|
2
|
+
end
|
3
|
+
require 'rubygems/dependency'
|
4
|
+
|
5
|
+
module Pod
|
6
|
+
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
|
+
def initialize(name, *version_requirements)
|
11
|
+
super
|
12
|
+
@only_part_of_other_pod = false
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(other)
|
16
|
+
super && @only_part_of_other_pod == other.only_part_of_other_pod
|
17
|
+
end
|
18
|
+
|
19
|
+
# Taken from a newer version of RubyGems
|
20
|
+
unless public_method_defined?(:merge)
|
21
|
+
def merge other
|
22
|
+
unless name == other.name then
|
23
|
+
raise ArgumentError,
|
24
|
+
"#{self} and #{other} have different names"
|
25
|
+
end
|
26
|
+
|
27
|
+
default = Gem::Requirement.default
|
28
|
+
self_req = self.requirement
|
29
|
+
other_req = other.requirement
|
30
|
+
|
31
|
+
return self.class.new name, self_req if other_req == default
|
32
|
+
return self.class.new name, other_req if self_req == default
|
33
|
+
|
34
|
+
self.class.new name, self_req.as_list.concat(other_req.as_list)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Pod
|
2
|
+
class Downloader
|
3
|
+
def self.for_source(pod_root, source)
|
4
|
+
options = source.dup
|
5
|
+
if url = options.delete(:git)
|
6
|
+
Git.new(pod_root, url, options)
|
7
|
+
else
|
8
|
+
raise "Unsupported download strategy `#{source.inspect}'."
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :pod_root, :url, :options
|
13
|
+
|
14
|
+
def initialize(pod_root, url, options)
|
15
|
+
@pod_root, @url, @options = pod_root, url, options
|
16
|
+
end
|
17
|
+
|
18
|
+
class Git < Downloader
|
19
|
+
extend Executable
|
20
|
+
executable :git
|
21
|
+
|
22
|
+
def download
|
23
|
+
if @options[:tag]
|
24
|
+
download_tag
|
25
|
+
elsif @options[:commit]
|
26
|
+
download_commit
|
27
|
+
else
|
28
|
+
raise "Either a tag or a commit has to be specified."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def download_tag
|
33
|
+
@pod_root.mkdir
|
34
|
+
Dir.chdir(@pod_root) do
|
35
|
+
git "init"
|
36
|
+
git "remote add origin '#{@url}'"
|
37
|
+
git "fetch origin tags/#{@options[:tag]}"
|
38
|
+
git "reset --hard FETCH_HEAD"
|
39
|
+
git "checkout -b activated-pod-commit"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def download_commit
|
44
|
+
git "clone '#{@url}' '#{@pod_root}'"
|
45
|
+
Dir.chdir(@pod_root) do
|
46
|
+
git "checkout -b activated-pod-commit #{@options[:commit]}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def clean
|
51
|
+
(@pod_root + '.git').rmtree
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Pod
|
2
|
+
# TODO the static library needs an extra xcconfig which sets the values from issue #1.
|
3
|
+
# Or we could edit the project.pbxproj file, but that seems like more work...
|
4
|
+
class Installer
|
5
|
+
include Config::Mixin
|
6
|
+
|
7
|
+
def initialize(specification)
|
8
|
+
@specification = specification
|
9
|
+
end
|
10
|
+
|
11
|
+
def dependent_specification_sets
|
12
|
+
@dependent_specification_sets ||= Resolver.new(@specification).resolve
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_specification_sets
|
16
|
+
dependent_specification_sets.reject(&:only_part_of_other_pod?)
|
17
|
+
end
|
18
|
+
|
19
|
+
def source_files
|
20
|
+
source_files = []
|
21
|
+
build_specification_sets.each do |set|
|
22
|
+
spec = set.specification
|
23
|
+
spec.read(:source_files).each do |pattern|
|
24
|
+
pattern = spec.pod_destroot + pattern
|
25
|
+
pattern = pattern + '*.{h,m,mm,c,cpp}' if pattern.directory?
|
26
|
+
pattern.glob.each do |file|
|
27
|
+
source_files << file.relative_path_from(config.project_pods_root)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
source_files
|
32
|
+
end
|
33
|
+
|
34
|
+
def xcconfig
|
35
|
+
@xcconfig ||= Xcode::Config.new({
|
36
|
+
# in a workspace this is where the static library headers should be found
|
37
|
+
'USER_HEADER_SEARCH_PATHS' => '$(BUILT_PRODUCTS_DIR)',
|
38
|
+
# search the user headers
|
39
|
+
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
|
40
|
+
})
|
41
|
+
end
|
42
|
+
|
43
|
+
def xcodeproj
|
44
|
+
@xcodeproj ||= Xcode::Project.ios_static_library
|
45
|
+
end
|
46
|
+
|
47
|
+
def generate_project
|
48
|
+
source_files.each { |file| xcodeproj.add_source_file(file) }
|
49
|
+
build_specification_sets.each do |set|
|
50
|
+
xcconfig << set.specification.read(:xcconfig)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def install!
|
55
|
+
puts "Installing dependencies of: #{@specification.defined_in_file}" unless config.silent?
|
56
|
+
generate_project
|
57
|
+
build_specification_sets.each { |set| set.specification.install! }
|
58
|
+
xcodeproj.create_in(config.project_pods_root)
|
59
|
+
xcconfig.create_in(config.project_pods_root)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Pod
|
2
|
+
class Resolver
|
3
|
+
def initialize(specification)
|
4
|
+
@specification = specification
|
5
|
+
end
|
6
|
+
|
7
|
+
def resolve
|
8
|
+
@sets = []
|
9
|
+
find_dependency_sets(@specification)
|
10
|
+
@sets
|
11
|
+
end
|
12
|
+
|
13
|
+
def find_dependency_sets(specification)
|
14
|
+
specification.read(:dependencies).each do |dependency|
|
15
|
+
set = Source.search(dependency)
|
16
|
+
set.required_by(specification)
|
17
|
+
unless @sets.include?(set)
|
18
|
+
@sets << set
|
19
|
+
find_dependency_sets(set.specification)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Pod
|
2
|
+
class Source
|
3
|
+
def self.all
|
4
|
+
@sources ||= begin
|
5
|
+
repos_dir = Config.instance.repos_dir
|
6
|
+
unless repos_dir.exist?
|
7
|
+
raise Informative, "No spec repos found in `#{repos_dir}'. " \
|
8
|
+
"To fetch the `master' repo run: $ pod setup"
|
9
|
+
end
|
10
|
+
repos_dir.children.select(&:directory?).map { |repo| new(repo) }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.search(dependency)
|
15
|
+
all.map { |source| source.search(dependency) }.compact.first ||
|
16
|
+
raise(Informative, "Unable to find a pod named `#{dependency.name}'")
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :repo
|
20
|
+
|
21
|
+
def initialize(repo)
|
22
|
+
@repo = repo
|
23
|
+
end
|
24
|
+
|
25
|
+
def search(dependency)
|
26
|
+
if dir = @repo.children.find { |c| c.basename.to_s == dependency.name }
|
27
|
+
Specification::Set.by_pod_dir(dir)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
module Pod
|
2
|
+
class Specification
|
3
|
+
autoload :Set, 'cocoapods/specification/set'
|
4
|
+
|
5
|
+
def self.from_podfile(path)
|
6
|
+
if path.exist?
|
7
|
+
spec = new
|
8
|
+
spec.instance_eval(path.read)
|
9
|
+
spec.defined_in_file = path
|
10
|
+
spec
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.from_podspec(path)
|
15
|
+
spec = eval(path.read, nil, path.to_s)
|
16
|
+
spec.defined_in_file = path
|
17
|
+
spec
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_accessor :defined_in_file
|
21
|
+
|
22
|
+
def initialize(&block)
|
23
|
+
@dependencies = []
|
24
|
+
@xcconfig = {}
|
25
|
+
instance_eval(&block) if block_given?
|
26
|
+
end
|
27
|
+
|
28
|
+
# Attributes
|
29
|
+
|
30
|
+
def read(name)
|
31
|
+
instance_variable_get("@#{name}")
|
32
|
+
end
|
33
|
+
|
34
|
+
def name(name)
|
35
|
+
@name = name
|
36
|
+
end
|
37
|
+
|
38
|
+
def version(version)
|
39
|
+
@version = Version.new(version)
|
40
|
+
end
|
41
|
+
|
42
|
+
def authors(*names_and_email_addresses)
|
43
|
+
list = names_and_email_addresses
|
44
|
+
unless list.first.is_a?(Hash)
|
45
|
+
authors = list.last.is_a?(Hash) ? list.pop : {}
|
46
|
+
list.each { |name| authors[name] = nil }
|
47
|
+
end
|
48
|
+
@authors = authors || list
|
49
|
+
end
|
50
|
+
alias_method :author, :authors
|
51
|
+
|
52
|
+
def homepage(url)
|
53
|
+
@homepage = url
|
54
|
+
end
|
55
|
+
|
56
|
+
def summary(summary)
|
57
|
+
@summary = summary
|
58
|
+
@description ||= summary
|
59
|
+
end
|
60
|
+
|
61
|
+
def description(description)
|
62
|
+
@description = description
|
63
|
+
end
|
64
|
+
|
65
|
+
def part_of(name, *version_requirements)
|
66
|
+
part_of_dependency(name, *version_requirements)
|
67
|
+
@part_of.only_part_of_other_pod = true
|
68
|
+
end
|
69
|
+
|
70
|
+
def part_of_dependency(name, *version_requirements)
|
71
|
+
@part_of = dependency(name, *version_requirements)
|
72
|
+
end
|
73
|
+
|
74
|
+
def source_files(*patterns)
|
75
|
+
@source_files = patterns.map { |p| Pathname.new(p) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def source(remote)
|
79
|
+
@source = remote
|
80
|
+
end
|
81
|
+
|
82
|
+
attr_reader :dependencies
|
83
|
+
def dependency(name, *version_requirements)
|
84
|
+
dep = Dependency.new(name, *version_requirements)
|
85
|
+
@dependencies << dep
|
86
|
+
dep
|
87
|
+
end
|
88
|
+
|
89
|
+
def xcconfig(hash)
|
90
|
+
@xcconfig = hash
|
91
|
+
end
|
92
|
+
|
93
|
+
# Not attributes
|
94
|
+
|
95
|
+
include Config::Mixin
|
96
|
+
|
97
|
+
def ==(other)
|
98
|
+
self.class === other &&
|
99
|
+
@name && @name == other.read(:name) &&
|
100
|
+
@version && @version == other.read(:version)
|
101
|
+
end
|
102
|
+
|
103
|
+
def dependency_by_name(name)
|
104
|
+
@dependencies.find { |d| d.name == name }
|
105
|
+
end
|
106
|
+
|
107
|
+
def part_of_specification_set
|
108
|
+
if @part_of
|
109
|
+
Set.by_specification_name(@part_of.name)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Returns the specification for the pod that this pod's source is a part of.
|
114
|
+
def part_of_specification
|
115
|
+
(set = part_of_specification_set) && set.specification
|
116
|
+
end
|
117
|
+
|
118
|
+
def pod_destroot
|
119
|
+
return if from_podfile?
|
120
|
+
if part_of_other_pod?
|
121
|
+
part_of_specification.pod_destroot
|
122
|
+
else
|
123
|
+
config.project_pods_root + "#{@name}-#{@version}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def part_of_other_pod?
|
128
|
+
!@part_of.nil?
|
129
|
+
end
|
130
|
+
|
131
|
+
def from_podfile?
|
132
|
+
@name.nil? && @version.nil?
|
133
|
+
end
|
134
|
+
|
135
|
+
def to_s
|
136
|
+
if from_podfile?
|
137
|
+
"podfile at `#{@defined_in_file}'"
|
138
|
+
else
|
139
|
+
"`#{@name}' version `#{@version}'"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def inspect
|
144
|
+
"#<#{self.class.name} for #{to_s}>"
|
145
|
+
end
|
146
|
+
|
147
|
+
# Install and download hooks
|
148
|
+
|
149
|
+
# Places the activated specification in the project's pods directory.
|
150
|
+
#
|
151
|
+
# Override this if you need to perform work before or after activating the
|
152
|
+
# pod. Eg:
|
153
|
+
#
|
154
|
+
# Pod::Spec.new do
|
155
|
+
# def install!
|
156
|
+
# # pre-install
|
157
|
+
# super
|
158
|
+
# # post-install
|
159
|
+
# end
|
160
|
+
# end
|
161
|
+
def install!
|
162
|
+
puts "==> Installing: #{self}" unless config.silent?
|
163
|
+
config.project_pods_root.mkpath
|
164
|
+
require 'fileutils'
|
165
|
+
FileUtils.cp(@defined_in_file, config.project_pods_root)
|
166
|
+
|
167
|
+
# In case this spec is part of another pod's source, we need to dowload
|
168
|
+
# the other pod's source.
|
169
|
+
(part_of_specification || self).download_if_necessary!
|
170
|
+
end
|
171
|
+
|
172
|
+
def download_if_necessary!
|
173
|
+
if pod_destroot.exist?
|
174
|
+
puts " * Skipping download of #{self}, pod already downloaded" unless config.silent?
|
175
|
+
else
|
176
|
+
puts " * Downloading: #{self}" unless config.silent?
|
177
|
+
download!
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Downloads the source of the pod and places it in the project's pods
|
182
|
+
# directory.
|
183
|
+
#
|
184
|
+
# Override this if you need to perform work before or after downloading the
|
185
|
+
# pod, or if you need to implement custom dowloading. Eg:
|
186
|
+
#
|
187
|
+
# Pod::Spec.new do
|
188
|
+
# def download!
|
189
|
+
# # pre-download
|
190
|
+
# super # or custom downloading
|
191
|
+
# # post-download
|
192
|
+
# end
|
193
|
+
# end
|
194
|
+
def download!
|
195
|
+
downloader = Downloader.for_source(pod_destroot, @source)
|
196
|
+
downloader.download
|
197
|
+
downloader.clean if config.clean
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
Spec = Specification
|
203
|
+
end
|