cocoapods 0.15.1 → 0.15.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,29 @@
1
1
  ## Master
2
2
 
3
- [CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.15.1...master)
3
+ [CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.15.1...master) • [Xcodeproj](https://github.com/CocoaPods/Xcodeproj/compare/0.3.4...master)
4
+
5
+ ## 0.15.2
6
+
7
+ [CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.15.1...0.15.2)
8
+
9
+ ###### Enhancements
10
+
11
+ - Added support for `.hh` headers.
12
+ [#576](https://github.com/CocoaPods/CocoaPods/pull/576)
13
+
14
+ ###### Bug fixes
15
+
16
+ - Restored support for running CocoaPods without a terminal.
17
+ [#575](https://github.com/CocoaPods/CocoaPods/issues/575)
18
+ [#577](https://github.com/CocoaPods/CocoaPods/issues/577)
19
+ - The git cache now always uses a barebones repo preventing a number of related issues.
20
+ [#581](https://github.com/CocoaPods/CocoaPods/issues/581)
21
+ [#569](https://github.com/CocoaPods/CocoaPods/issues/569)
22
+ - Improved fix for the issue that lead to empty directories for Pods.
23
+ [#572](https://github.com/CocoaPods/CocoaPods/issues/572)
24
+ [#602](https://github.com/CocoaPods/CocoaPods/issues/602)
25
+ - Xcodeproj robustness against invalid values, such as malformed UTF8.
26
+ [#592](https://github.com/CocoaPods/CocoaPods/issues/592)
4
27
 
5
28
  ## 0.15.1
6
29
 
@@ -12,7 +12,7 @@ unless Gem::Version::Requirement.new('>= 1.4.0').satisfied_by?(Gem::Version.new(
12
12
  end
13
13
 
14
14
  module Pod
15
- VERSION = '0.15.1'
15
+ VERSION = '0.15.2'
16
16
 
17
17
  class PlainInformative < StandardError
18
18
  end
@@ -57,13 +57,6 @@ module Pod
57
57
  end
58
58
  end
59
59
 
60
- class Pathname
61
- def glob(pattern = '')
62
- Dir.glob((self + pattern).to_s).map { |f| Pathname.new(f) }
63
- end
64
- end
65
-
66
60
  if ENV['COCOA_PODS_ENV'] == 'development'
67
- require 'letters'
68
61
  require 'awesome_print'
69
62
  end
@@ -1,4 +1,5 @@
1
1
  require 'fileutils'
2
+ require 'active_support/core_ext/string/inflections'
2
3
 
3
4
  module Pod
4
5
  class Command
@@ -66,12 +67,18 @@ module Pod
66
67
 
67
68
  def podspec_files
68
69
  files = Pathname.glob(@podspec || "*.podspec")
69
- raise Informative, "[!] Couldn't find .podspec file in current directory".red if files.empty?
70
+ raise Informative, "[!] Couldn't find any .podspec file in current directory".red if files.empty?
70
71
  files
71
72
  end
72
73
 
74
+ # @return [Integer] The number of the podspec files to push.
75
+ #
76
+ def count
77
+ podspec_files.count
78
+ end
79
+
73
80
  def validate_podspec_files
74
- UI.puts "\nValidating specs".yellow unless config.silent
81
+ UI.puts "\nValidating #{'spec'.pluralize(count)}".yellow unless config.silent
75
82
  lint_argv = ["lint"]
76
83
  lint_argv << "--only-errors" if @allow_warnings
77
84
  lint_argv << "--silent" if config.silent
@@ -82,7 +89,7 @@ module Pod
82
89
  end
83
90
 
84
91
  def add_specs_to_repo
85
- UI.puts "\nAdding the specs to the #{@repo} repo\n".yellow unless config.silent
92
+ UI.puts "\nAdding the #{'spec'.pluralize(count)} to the `#{@repo}' repo\n".yellow unless config.silent
86
93
  podspec_files.each do |spec_file|
87
94
  spec = Pod::Specification.from_file(spec_file)
88
95
  output_path = File.join(repo_dir, spec.name, spec.version.to_s)
@@ -90,7 +90,7 @@ module Pod
90
90
  dirs.each do |dir|
91
91
  check_versions(dir)
92
92
  UI.puts "\nLinting spec repo `#{dir.realpath.basename}'\n".yellow
93
- podspecs = dir.glob('**/*.podspec')
93
+ podspecs = Pathname.glob( dir + '**/*.podspec')
94
94
  invalid_count = 0
95
95
 
96
96
  podspecs.each do |podspec|
@@ -1,5 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require 'active_support/core_ext/string/inflections'
4
+
3
5
  module Pod
4
6
  class Command
5
7
  class Spec < Command
@@ -104,8 +106,8 @@ module Pod
104
106
  UI.puts unless config.silent?
105
107
  end
106
108
 
107
- UI.puts "Analyzed #{podspecs_to_lint.count} podspecs files.\n\n" unless config.silent?
108
109
  count = podspecs_to_lint.count
110
+ UI.puts "Analyzed #{count} #{'podspec'.pluralize(count)}.\n\n" unless config.silent?
109
111
  if invalid_count == 0
110
112
  lint_passed_message = count == 1 ? "#{podspecs_to_lint.first.basename} passed validation." : "All the specs passed validation."
111
113
  UI.puts lint_passed_message.green << "\n\n" unless config.silent?
@@ -136,7 +138,7 @@ module Pod
136
138
  end
137
139
  files << output_path
138
140
  else if (pathname = Pathname.new(path)).directory?
139
- files += pathname.glob('**/*.podspec')
141
+ files += Pathname.glob(pathname + '**/*.podspec')
140
142
  raise Informative, "No specs found in the current directory." if files.empty?
141
143
  else
142
144
  files << (pathname = Pathname.new(path))
@@ -1,17 +1,19 @@
1
1
  require 'open-uri'
2
- require 'tempfile'
2
+ # require 'tempfile'
3
3
  require 'zlib'
4
4
  require 'digest/sha1'
5
5
 
6
6
  module Pod
7
7
  class Downloader
8
+
9
+ # Concreted Downloader class that provides support for specifications with
10
+ # git sources.
11
+ #
8
12
  class Git < Downloader
9
13
  include Config::Mixin
10
14
 
11
15
  executable :git
12
16
 
13
- MAX_CACHE_SIZE = 500
14
-
15
17
  def download
16
18
  create_cache unless cache_exist?
17
19
  UI.section(' > Cloning git repo', '', 1) do
@@ -29,89 +31,26 @@ module Pod
29
31
  prune_cache
30
32
  end
31
33
 
32
- def create_cache
33
- UI.section(" > Creating cache git repo (#{cache_path})",'',1) do
34
- cache_path.rmtree if cache_path.exist?
35
- cache_path.mkpath
36
- git! %Q|clone --mirror "#{url}" "#{cache_path}"|
37
- end
38
- end
39
-
40
- def prune_cache
41
- return unless caches_dir.exist?
42
- Dir.chdir(caches_dir) do
43
- repos = Pathname.new(caches_dir).children.select { |c| c.directory? }.sort_by(&:ctime)
44
- while caches_size >= MAX_CACHE_SIZE && !repos.empty?
45
- dir = repos.shift
46
- UI.message "#{'->'.yellow} Removing git cache for `#{origin_url(dir)}'"
47
- dir.rmtree
48
- end
49
- end
50
- end
51
-
52
- def cache_path
53
- @cache_path ||= caches_dir + "#{Digest::SHA1.hexdigest(url.to_s)}"
54
- end
55
-
56
- def cache_exist?
57
- cache_path.exist? && origin_url(cache_path).to_s == url.to_s
58
- end
59
-
60
- def origin_url(dir)
61
- Dir.chdir(dir) { `git config remote.origin.url`.chomp }
62
- end
63
34
 
64
- def caches_dir
65
- Pathname.new(File.expand_path("~/Library/Caches/CocoaPods/Git"))
66
- end
35
+ # @!group Download implementations
67
36
 
37
+ # @return [Pathname] The clone URL, which resolves to the cache path.
38
+ #
68
39
  def clone_url
69
40
  cache_path
70
41
  end
71
42
 
72
- def caches_size
73
- # expressed in Mb
74
- `du -cm`.split("\n").last.to_i
75
- end
76
-
77
- def update_cache
78
- UI.section(" > Updating cache git repo (#{cache_path})",'',1) do
79
- Dir.chdir(cache_path) do
80
- if git("config core.bare").chomp == "true"
81
- git! "remote update"
82
- else
83
- git! "reset --hard HEAD"
84
- git! "clean -d -x -f"
85
- git! "pull origin master"
86
- git! "fetch --tags"
87
- end
88
- end
43
+ # @return [void] Convenience method to perform clones operations.
44
+ #
45
+ def clone(from, to)
46
+ UI.section(" > Cloning to Pods folder",'',1) do
47
+ git! %Q|clone "#{from}" "#{to}"|
89
48
  end
90
49
  end
91
50
 
92
- def ref_exists?(ref)
93
- Dir.chdir(cache_path) { git "rev-list --max-count=1 #{ref}" }
94
- $? == 0
95
- end
96
-
97
- def ensure_ref_exists(ref)
98
- return if ref_exists?(ref)
99
- # Skip pull if not needed
100
- update_cache
101
- raise Informative, "[!] Cache unable to find git reference `#{ref}' for `#{url}'.".red unless ref_exists?(ref)
102
- end
103
-
104
- def branch_exists?(branch)
105
- Dir.chdir(cache_path) { git "branch --all | grep #{branch}$" } # check for remote branch and do suffix matching ($ anchor)
106
- $? == 0
107
- end
108
-
109
- def ensure_remote_branch_exists(branch)
110
- return if branch_exists?(branch)
111
- update_cache
112
- raise Informative, "[!] Cache unable to find git reference `#{branch}' for `#{url}' (#{$?}).".red unless branch_exists?(branch)
113
- end
114
-
51
+ # @return [void] Checkouts the HEAD of the git source in the destination
52
+ # path.
53
+ #
115
54
  def download_head
116
55
  if cache_exist?
117
56
  update_cache
@@ -123,6 +62,9 @@ module Pod
123
62
  Dir.chdir(target_path) { git! "submodule update --init" } if options[:submodules]
124
63
  end
125
64
 
65
+ # @return [void] Checkouts a specific tag of the git source in the
66
+ # destination path.
67
+ #
126
68
  def download_tag
127
69
  ensure_ref_exists(options[:tag])
128
70
  Dir.chdir(target_path) do
@@ -134,6 +76,9 @@ module Pod
134
76
  end
135
77
  end
136
78
 
79
+ # @return [void] Checkouts a specific commit of the git source in the
80
+ # destination path.
81
+ #
137
82
  def download_commit
138
83
  ensure_ref_exists(options[:commit])
139
84
  clone(clone_url, target_path)
@@ -142,6 +87,9 @@ module Pod
142
87
  end
143
88
  end
144
89
 
90
+ # @return [void] Checkouts the HEAD of a specific branch of the git
91
+ # source in the destination path.
92
+ #
145
93
  def download_branch
146
94
  ensure_remote_branch_exists(options[:branch])
147
95
  clone(clone_url, target_path)
@@ -153,13 +101,135 @@ module Pod
153
101
  end
154
102
  end
155
103
 
156
- def clone(from, to)
157
- UI.section(" > Cloning to Pods folder",'',1) do
158
- git! %Q|clone "#{from}" "#{to}"|
104
+
105
+
106
+ # @!group Checking references
107
+
108
+ # @return [Bool] Wether a reference (commit SHA or tag)
109
+ #
110
+ def ref_exists?(ref)
111
+ Dir.chdir(cache_path) { git "rev-list --max-count=1 #{ref}" }
112
+ $? == 0
113
+ end
114
+
115
+ # @return [void] Checks if a reference exists in the cache and updates
116
+ # only if necessary.
117
+ #
118
+ # @raises if after the update the reference can't be found.
119
+ #
120
+ def ensure_ref_exists(ref)
121
+ return if ref_exists?(ref)
122
+ update_cache
123
+ raise Informative, "[!] Cache unable to find git reference `#{ref}' for `#{url}'.".red unless ref_exists?(ref)
124
+ end
125
+
126
+ # @return [Bool] Wether a branch exists in the cache.
127
+ #
128
+ def branch_exists?(branch)
129
+ Dir.chdir(cache_path) { git "branch --all | grep #{branch}$" } # check for remote branch and do suffix matching ($ anchor)
130
+ $? == 0
131
+ end
132
+
133
+ # @return [void] Checks if a branch exists in the cache and updates
134
+ # only if necessary.
135
+ #
136
+ # @raises if after the update the branch can't be found.
137
+ #
138
+ def ensure_remote_branch_exists(branch)
139
+ return if branch_exists?(branch)
140
+ update_cache
141
+ raise Informative, "[!] Cache unable to find git reference `#{branch}' for `#{url}' (#{$?}).".red unless branch_exists?(branch)
142
+ end
143
+
144
+
145
+ # @!group Cache
146
+
147
+ # The maximum allowed size for the cache expressed in Mb.
148
+ #
149
+ MAX_CACHE_SIZE = 500
150
+
151
+ # @return [Pathname] The directory where the cache for the current git
152
+ # repo is stored.
153
+ #
154
+ # @note The name of the directory is the SHA1 hash value of the URL of
155
+ # the git repo.
156
+ #
157
+ def cache_path
158
+ @cache_path ||= caches_root + "#{Digest::SHA1.hexdigest(url.to_s)}"
159
+ end
160
+
161
+ # @return [Pathname] The directory where the git caches are stored.
162
+ #
163
+ def caches_root
164
+ Pathname.new(File.expand_path("~/Library/Caches/CocoaPods/Git"))
165
+ end
166
+
167
+ # @return [Integer] The global size of the git cache expressed in Mb.
168
+ #
169
+ def caches_size
170
+ `du -cm`.split("\n").last.to_i
171
+ end
172
+
173
+ # @return [Bool] Wether the cache exits.
174
+ #
175
+ # @note The previous implementation of the cache didn't use a barebone
176
+ # git repo. This method takes into account this fact and checks
177
+ # that the cache is actually a barebone repo. If the cache was not
178
+ # barebone it will be deleted and recreated.
179
+ #
180
+ def cache_exist?
181
+ cache_path.exist? &&
182
+ cache_origin_url(cache_path).to_s == url.to_s &&
183
+ Dir.chdir(cache_path) { git("config core.bare").chomp == "true" }
184
+ end
185
+
186
+ # @return [String] The origin URL of the cache with the given directory.
187
+ #
188
+ # @param [String] dir The directory of the cache.
189
+ #
190
+ def cache_origin_url(dir)
191
+ Dir.chdir(dir) { `git config remote.origin.url`.chomp }
192
+ end
193
+
194
+ # @return [void] Creates the barebone repo that will serve as the cache
195
+ # for the current repo.
196
+ #
197
+ def create_cache
198
+ UI.section(" > Creating cache git repo (#{cache_path})",'',1) do
199
+ cache_path.rmtree if cache_path.exist?
200
+ cache_path.mkpath
201
+ git! %Q|clone --mirror "#{url}" "#{cache_path}"|
202
+ end
203
+ end
204
+
205
+ # @return [void] Updates the barebone repo used as a cache against its
206
+ # remote.
207
+ #
208
+ def update_cache
209
+ UI.section(" > Updating cache git repo (#{cache_path})",'',1) do
210
+ Dir.chdir(cache_path) { git! "remote update" }
211
+ end
212
+ end
213
+
214
+ # @return [void] Deletes the oldest caches until they the global size is
215
+ # below the maximum allowed.
216
+ #
217
+ def prune_cache
218
+ return unless caches_root.exist?
219
+ Dir.chdir(caches_root) do
220
+ repos = Pathname.new(caches_root).children.select { |c| c.directory? }.sort_by(&:ctime)
221
+ while caches_size >= MAX_CACHE_SIZE && !repos.empty?
222
+ dir = repos.shift
223
+ UI.message "#{'->'.yellow} Removing git cache for `#{cache_origin_url(dir)}'"
224
+ dir.rmtree
225
+ end
159
226
  end
160
227
  end
161
228
  end
162
229
 
230
+ # This class allows to download tarballs from GitHub and is not currently
231
+ # being used by CocoaPods as the git cache is preferable.
232
+ #
163
233
  class GitHub < Git
164
234
  def download_head
165
235
  download_only? ? download_and_extract_tarball('master') : super
@@ -163,14 +163,15 @@ module Pod
163
163
  #
164
164
  # @return [Array<Strings>] The paths that can be deleted.
165
165
  #
166
- # @note The Paths are downcased to prevent issues. See #568.
166
+ # @note Implementation detail: Don't use Dir#glob as there is an
167
+ # unexplained issue (#568, #572 and #602).
167
168
  #
168
169
  def clean_paths
169
- used = used_files.map(&:downcase)
170
- files = Dir.glob(root + "**/*", File::FNM_DOTMATCH).map(&:downcase)
170
+ cached_used = used_files
171
+ files = Pathname.glob(root + "**/*", File::FNM_DOTMATCH | File::FNM_CASEFOLD).map(&:to_s)
171
172
 
172
173
  files.reject! do |candidate|
173
- candidate.end_with?('.', '..') || used.any? do |path|
174
+ candidate.end_with?('.', '..') || cached_used.any? do |path|
174
175
  path.include?(candidate) || candidate.include?(path)
175
176
  end
176
177
  end
@@ -240,7 +241,7 @@ module Pod
240
241
  # {Specification}.
241
242
  #
242
243
  def source_files_by_spec
243
- options = {:glob => '*.{h,hpp,m,mm,c,cpp}'}
244
+ options = {:glob => '*.{h,hpp,hh,m,mm,c,cpp}'}
244
245
  paths_by_spec(:source_files, options)
245
246
  end
246
247
 
@@ -262,7 +263,7 @@ module Pod
262
263
  def header_files_by_spec
263
264
  result = {}
264
265
  source_files_by_spec.each do |spec, paths|
265
- headers = paths.select { |f| f.extname == '.h' || f.extname == '.hpp' }
266
+ headers = paths.select { |f| f.extname == '.h' || f.extname == '.hpp' || f.extname == '.hh' }
266
267
  result[spec] = headers unless headers.empty?
267
268
  end
268
269
  result
@@ -276,7 +277,7 @@ module Pod
276
277
  # header files (i.e. the build ones) are intended to be public.
277
278
  #
278
279
  def public_header_files_by_spec
279
- public_headers = paths_by_spec(:public_header_files, :glob => '*.{h,hpp}')
280
+ public_headers = paths_by_spec(:public_header_files, :glob => '*.{h,hpp,hh}')
280
281
  build_headers = header_files_by_spec
281
282
 
282
283
  result = {}
@@ -379,7 +380,7 @@ module Pod
379
380
  if (public_h = public_headers[spec]) && !public_h.empty?
380
381
  result += public_h
381
382
  elsif (source_f = source_files[spec]) && !source_f.empty?
382
- build_h = source_f.select { |f| f.extname == '.h' || f.extname == '.hpp' }
383
+ build_h = source_f.select { |f| f.extname == '.h' || f.extname == '.hpp' || f.extname == '.hh' }
383
384
  result += build_h unless build_h.empty?
384
385
  end
385
386
  end
@@ -433,7 +434,7 @@ module Pod
433
434
  # (the files the need to compiled) of the pod.
434
435
  #
435
436
  def implementation_files
436
- relative_source_files.reject { |f| f.extname == '.h' || f.extname == '.hpp' }
437
+ relative_source_files.reject { |f| f.extname == '.h' || f.extname == '.hpp' || f.extname == '.hh' }
437
438
  end
438
439
 
439
440
  # @return [Pathname] The path of the pod relative from the sandbox.
@@ -476,7 +477,7 @@ module Pod
476
477
  # included in the linker search paths.
477
478
  #
478
479
  def headers_excluded_from_search_paths
479
- options = { :glob => '*.{h,hpp}' }
480
+ options = { :glob => '*.{h,hpp,hh}' }
480
481
  paths = paths_by_spec(:exclude_header_search_paths, options)
481
482
  paths.values.compact.uniq
482
483
  end
@@ -35,7 +35,7 @@ module Pod
35
35
  if @path
36
36
  @path
37
37
  else
38
- xcodeprojs = config.project_root.glob('*.xcodeproj')
38
+ xcodeprojs = Pathname.glob(config.project_root + '*.xcodeproj')
39
39
  if xcodeprojs.size == 1
40
40
  @path = xcodeprojs.first
41
41
  end
@@ -196,8 +196,9 @@ module Pod
196
196
 
197
197
  # @!group Helpers
198
198
 
199
- # Wraps a string taking into account the width of the terminal and an
200
- # option indent. Adapted from http://blog.macromates.com/2006/wrapping-text-with-regular-expressions/
199
+ # @return [String] Wraps a string taking into account the width of the
200
+ # terminal and an option indent. Adapted from
201
+ # http://blog.macromates.com/2006/wrapping-text-with-regular-expressions/
201
202
  #
202
203
  # @param [String] txt The string to wrap
203
204
  #
@@ -205,8 +206,12 @@ module Pod
205
206
  #
206
207
  # @return [String] The formatted string.
207
208
  #
209
+ # @note If CocoaPods is not being run in a terminal or the width of the
210
+ # terminal is too small a width of 80 is assumed.
211
+ #
208
212
  def wrap_string(txt, indent = '')
209
213
  width = `stty size`.split(' ')[1].to_i - indent.length
214
+ width = 80 unless width >= 10
210
215
  txt.strip.gsub(/(.{1,#{width}})( +|$)\n?|(.{#{width}})/, indent + "\\1\\3\n")
211
216
  end
212
217
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.1
4
+ version: 0.15.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,24 +10,24 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-10-04 00:00:00.000000000 Z
13
+ date: 2012-10-19 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: xcodeproj
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
- - - ! '>='
20
+ - - ~>
21
21
  - !ruby/object:Gem::Version
22
- version: 0.3.4
22
+ version: 0.3.5
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  none: false
27
27
  requirements:
28
- - - ! '>='
28
+ - - ~>
29
29
  - !ruby/object:Gem::Version
30
- version: 0.3.4
30
+ version: 0.3.5
31
31
  - !ruby/object:Gem::Dependency
32
32
  name: faraday
33
33
  requirement: !ruby/object:Gem::Requirement
@@ -256,7 +256,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
256
256
  version: '0'
257
257
  segments:
258
258
  - 0
259
- hash: -3399336200991652352
259
+ hash: -1344889839066477359
260
260
  required_rubygems_version: !ruby/object:Gem::Requirement
261
261
  none: false
262
262
  requirements: