cocoapods 0.32.1 → 0.33.0

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.
@@ -1,4 +1,5 @@
1
1
  require 'fileutils'
2
+ require 'cocoapods/command/repo/push'
2
3
 
3
4
  module Pod
4
5
  class Command
@@ -17,7 +18,11 @@ module Pod
17
18
  remote can later be referred to by `NAME`.
18
19
  DESC
19
20
 
20
- self.arguments = 'NAME URL [BRANCH]'
21
+ self.arguments = [
22
+ ['NAME', :required],
23
+ ['URL', :required],
24
+ ['BRANCH', :optional]
25
+ ]
21
26
 
22
27
  def self.options
23
28
  [
@@ -63,7 +68,9 @@ module Pod
63
68
  this will update all spec-repos in `~/.cocoapods/repos`.
64
69
  DESC
65
70
 
66
- self.arguments = '[NAME]'
71
+ self.arguments = [
72
+ ['NAME', :optional]
73
+ ]
67
74
 
68
75
  def initialize(argv)
69
76
  @name = argv.shift_argument
@@ -86,7 +93,9 @@ module Pod
86
93
  will lint all the spec-repos known to CocoaPods.
87
94
  DESC
88
95
 
89
- self.arguments = '[ NAME | DIRECTORY ]'
96
+ self.arguments = [
97
+ ['NAME | DIRECTORY', :optional]
98
+ ]
90
99
 
91
100
  def self.options
92
101
  [["--only-errors", "Lint presents only the errors"]].concat(super)
@@ -152,7 +161,9 @@ module Pod
152
161
  Deletes the remote named `NAME` from the local spec-repos directory at `~/.cocoapods/repos/.`
153
162
  DESC
154
163
 
155
- self.arguments = 'NAME'
164
+ self.arguments = [
165
+ ['NAME', :required]
166
+ ]
156
167
 
157
168
  def initialize(argv)
158
169
  @name = argv.shift_argument
@@ -0,0 +1,199 @@
1
+ require 'fileutils'
2
+ require 'active_support/core_ext/string/inflections'
3
+
4
+ module Pod
5
+ class Command
6
+ class Repo < Command
7
+ class Push < Repo
8
+ self.summary = 'Push new specifications to a spec-repo'
9
+
10
+ self.description = <<-DESC
11
+ Validates NAME.podspec or `*.podspec' in the current working dir, creates
12
+ a directory and version folder for the pod in the local copy of
13
+ REPO (~/.cocoapods/repos/[REPO]), copies the podspec file into the version
14
+ directory, and finally it pushes REPO to its remote.
15
+ DESC
16
+
17
+ self.arguments = [
18
+ ['REPO', :required],
19
+ ['NAME.podspec', :optional]
20
+ ]
21
+
22
+ def self.options
23
+ [ ["--allow-warnings", "Allows pushing even if there are warnings"],
24
+ ["--local-only", "Does not perform the step of pushing REPO to its remote"] ].concat(super)
25
+ end
26
+
27
+ def initialize(argv)
28
+ @allow_warnings = argv.flag?('allow-warnings')
29
+ @local_only = argv.flag?('local-only')
30
+ @repo = argv.shift_argument
31
+ @podspec = argv.shift_argument
32
+ super
33
+ end
34
+
35
+ def validate!
36
+ super
37
+ help! "A spec-repo name is required." unless @repo
38
+ end
39
+
40
+ def run
41
+ check_if_master_repo
42
+ validate_podspec_files
43
+ check_repo_status
44
+ update_repo
45
+ add_specs_to_repo
46
+ push_repo unless @local_only
47
+ end
48
+
49
+ #---------------------------------------------------------------------#
50
+
51
+ private
52
+
53
+ # @!group Push sub-steps
54
+
55
+ extend Executable
56
+ executable :git
57
+
58
+ # Temporary check to ensure that users do not push accidentally private
59
+ # specs to the master repo.
60
+ #
61
+ def check_if_master_repo
62
+ remotes = Dir.chdir(repo_dir) { `git remote -v 2>&1` }
63
+ master_repo_urls = [
64
+ 'git@github.com:CocoaPods/Specs.git',
65
+ 'https://github.com/CocoaPods/Specs.git',
66
+ ]
67
+ is_master_repo = master_repo_urls.any? do |url|
68
+ remotes.include?(url)
69
+ end
70
+
71
+ if is_master_repo
72
+ raise Informative, "To push to the CocoaPods master repo use " \
73
+ "the `pod trunk push` command.\n\nIf you are using a fork of " \
74
+ "the master repo for private purposes we recommend to migrate " \
75
+ "to a clean private repo. To disable this check remove the " \
76
+ "remote pointing to the CocoaPods master repo."
77
+ end
78
+ end
79
+
80
+
81
+ # Performs a full lint against the podspecs.
82
+ #
83
+ def validate_podspec_files
84
+ UI.puts "\nValidating #{'spec'.pluralize(count)}".yellow
85
+ podspec_files.each do |podspec|
86
+ validator = Validator.new(podspec)
87
+ validator.only_errors = @allow_warnings
88
+ begin
89
+ validator.validate
90
+ rescue Exception
91
+ raise Informative, "The `#{podspec}` specification does not validate."
92
+ end
93
+ raise Informative, "The `#{podspec}` specification does not validate." unless validator.validated?
94
+ end
95
+ end
96
+
97
+ # Checks that the repo is clean.
98
+ #
99
+ # @raise If the repo is not clean.
100
+ #
101
+ # @todo Add specs for staged and unstaged files.
102
+ #
103
+ # @todo Gracefully handle the case where source is not under git
104
+ # source control.
105
+ #
106
+ # @return [void]
107
+ #
108
+ def check_repo_status
109
+ clean = Dir.chdir(repo_dir) { `git status --porcelain 2>&1` } == ''
110
+ raise Informative, "The repo `#{@repo}` is not clean" unless clean
111
+ end
112
+
113
+ # Updates the git repo against the remote.
114
+ #
115
+ # @return [void]
116
+ #
117
+ def update_repo
118
+ UI.puts "Updating the `#{@repo}' repo\n".yellow
119
+ Dir.chdir(repo_dir) { UI.puts `git pull 2>&1` }
120
+ end
121
+
122
+ # Commits the podspecs to the source, which should be a git repo.
123
+ #
124
+ # @note The pre commit hook of the repo is skipped as the podspecs have
125
+ # already been linted.
126
+ #
127
+ # @return [void]
128
+ #
129
+ def add_specs_to_repo
130
+ UI.puts "\nAdding the #{'spec'.pluralize(count)} to the `#{@repo}' repo\n".yellow
131
+ podspec_files.each do |spec_file|
132
+ spec = Pod::Specification.from_file(spec_file)
133
+ output_path = File.join(repo_dir, spec.name, spec.version.to_s)
134
+ if Pathname.new(output_path).exist?
135
+ message = "[Fix] #{spec}"
136
+ elsif Pathname.new(File.join(repo_dir, spec.name)).exist?
137
+ message = "[Update] #{spec}"
138
+ else
139
+ message = "[Add] #{spec}"
140
+ end
141
+
142
+ FileUtils.mkdir_p(output_path)
143
+ FileUtils.cp(spec_file, output_path)
144
+ Dir.chdir(repo_dir) do
145
+ # only commit if modified
146
+ if git!("status --porcelain 2>&1").include?(spec.name)
147
+ UI.puts " - #{message}"
148
+ git!("add #{spec.name}")
149
+ git!("commit --no-verify -m '#{message}'")
150
+ else
151
+ UI.puts " - [No change] #{spec}"
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ # Pushes the git repo against the remote.
158
+ #
159
+ # @return [void]
160
+ #
161
+ def push_repo
162
+ UI.puts "\nPushing the `#{@repo}' repo\n".yellow
163
+ Dir.chdir(repo_dir) { UI.puts `git push origin master 2>&1` }
164
+ end
165
+
166
+ #---------------------------------------------------------------------#
167
+
168
+ private
169
+
170
+ # @!group Private helpers
171
+
172
+ # @return [Pathname] The directory of the repository.
173
+ #
174
+ def repo_dir
175
+ dir = config.repos_dir + @repo
176
+ raise Informative, "`#{@repo}` repo not found" unless dir.exist?
177
+ dir
178
+ end
179
+
180
+ # @return [Array<Pathname>] The path of the specifications to push.
181
+ #
182
+ def podspec_files
183
+ files = Pathname.glob(@podspec || "*.podspec")
184
+ raise Informative, "Couldn't find any .podspec file in current directory" if files.empty?
185
+ files
186
+ end
187
+
188
+ # @return [Integer] The number of the podspec files to push.
189
+ #
190
+ def count
191
+ podspec_files.count
192
+ end
193
+
194
+ #---------------------------------------------------------------------#
195
+
196
+ end
197
+ end
198
+ end
199
+ end
@@ -9,7 +9,9 @@ module Pod
9
9
  description of the pods.
10
10
  DESC
11
11
 
12
- self.arguments = 'QUERY'
12
+ self.arguments = [
13
+ ['QUERY', :required]
14
+ ]
13
15
 
14
16
  def self.options
15
17
  [
@@ -18,7 +18,9 @@ module Pod
18
18
  If a GitHub url is passed the spec is prepopulated.
19
19
  DESC
20
20
 
21
- self.arguments = '[ NAME | https://github.com/USER/REPO ]'
21
+ self.arguments = [
22
+ ['NAME | https://github.com/USER/REPO', :optional]
23
+ ]
22
24
 
23
25
  def initialize(argv)
24
26
  @name_or_url, @url = argv.shift_argument, argv.shift_argument
@@ -56,7 +58,9 @@ module Pod
56
58
  the argument is omitted, it defaults to the current working dir.
57
59
  DESC
58
60
 
59
- self.arguments = '[ NAME.podspec | DIRECTORY | http://PATH/NAME.podspec, ... ]'
61
+ self.arguments = [
62
+ ['NAME.podspec | DIRECTORY | http://PATH/NAME.podspec, ...', :optional]
63
+ ]
60
64
 
61
65
  def self.options
62
66
  [ ["--quick", "Lint skips checks that would require to download and build the spec"],
@@ -148,7 +152,9 @@ module Pod
148
152
  Prints the path of 'NAME.podspec'
149
153
  DESC
150
154
 
151
- self.arguments = '[ NAME ]'
155
+ self.arguments = [
156
+ ['NAME', :optional]
157
+ ]
152
158
 
153
159
  def self.options
154
160
  [["--show-all", "Print all versions of the given podspec"]].concat(super)
@@ -180,7 +186,9 @@ module Pod
180
186
  Prints 'NAME.podspec' to standard output.
181
187
  DESC
182
188
 
183
- self.arguments = '[ NAME ]'
189
+ self.arguments = [
190
+ ['NAME', :optional]
191
+ ]
184
192
 
185
193
  def self.options
186
194
  [["--show-all", "Pick from all versions of the given podspec"]].concat(super)
@@ -220,7 +228,9 @@ module Pod
220
228
  Opens 'NAME.podspec' to be edited.
221
229
  DESC
222
230
 
223
- self.arguments = '[ NAME ]'
231
+ self.arguments = [
232
+ ['NAME', :optional]
233
+ ]
224
234
 
225
235
  def self.options
226
236
  [["--show-all", "Pick which spec to edit from all available versions of the given podspec"]].concat(super)
@@ -342,7 +352,7 @@ module Pod
342
352
  # @return [Pathname] the absolute path of the given spec and source
343
353
  #
344
354
  def pathname_from_spec(spec, source)
345
- config.repos_dir + "#{source}/#{spec.name}/#{spec.version}/#{spec.name}.podspec"
355
+ Pathname(spec.defined_in_file)
346
356
  end
347
357
 
348
358
  # @return [String] of spec paths one on each line
@@ -71,7 +71,7 @@ module Pod
71
71
  output = stdout.join("\n") + stderr.join("\n")
72
72
  unless status.success?
73
73
  if raise_on_failure
74
- raise Informative, "#{name} #{command}\n\n#{output}"
74
+ raise Informative, "#{full_command}\n\n#{output}"
75
75
  else
76
76
  UI.message("[!] Failed: #{full_command}".red)
77
77
  end
@@ -1,6 +1,6 @@
1
1
  module Pod
2
2
  # The version of the cocoapods command line tool.
3
3
  #
4
- VERSION = '0.32.1' unless defined? Pod::VERSION
4
+ VERSION = '0.33.0' unless defined? Pod::VERSION
5
5
  end
6
6
 
@@ -90,6 +90,7 @@ module Pod
90
90
  download_dependencies
91
91
  generate_pods_project
92
92
  integrate_user_project if config.integrate_targets?
93
+ perform_post_install_actions
93
94
  end
94
95
 
95
96
  def resolve_dependencies
@@ -164,9 +165,10 @@ module Pod
164
165
  #
165
166
  def analyze
166
167
  if lockfile && lockfile.cocoapods_version > Version.new(VERSION)
167
- STDERR.puts '[!] The version of CocoaPods used to generate the lockfile is '\
168
- 'higher than the version of the current executable. Incompatibility ' \
169
- 'issues may arise.'.yellow
168
+ STDERR.puts '[!] The version of CocoaPods used to generate ' \
169
+ "the lockfile (#{lockfile.cocoapods_version}) is "\
170
+ "higher than the version of the current executable (#{VERSION}). " \
171
+ 'Incompatibility issues may arise.'.yellow
170
172
  end
171
173
 
172
174
  analyzer = Analyzer.new(sandbox, podfile, lockfile)
@@ -286,6 +288,32 @@ module Pod
286
288
  end
287
289
  end
288
290
 
291
+ # Performs any post-installation actions
292
+ #
293
+ # @return [void]
294
+ #
295
+ def perform_post_install_actions
296
+ warn_for_deprecations
297
+ end
298
+
299
+ # Prints a warning for any pods that are deprecated
300
+ #
301
+ # @return [void]
302
+ #
303
+ def warn_for_deprecations
304
+ deprecated_pods = root_specs.select do |spec|
305
+ spec.deprecated || spec.deprecated_in_favor_of
306
+ end
307
+ deprecated_pods.each do |spec|
308
+ if spec.deprecated_in_favor_of
309
+ UI.warn "#{spec.name} has been deprecated in " \
310
+ "favor of #{spec.deprecated_in_favor_of}"
311
+ else
312
+ UI.warn "#{spec.name} has been deprecated"
313
+ end
314
+ end
315
+ end
316
+
289
317
  # Creates the Pods project from scratch if it doesn't exists.
290
318
  #
291
319
  # @return [void]
@@ -467,42 +495,11 @@ module Pod
467
495
  #
468
496
  def run_pre_install_hooks
469
497
  UI.message "- Running pre install hooks" do
470
- analysis_result.specifications.each do |spec|
471
- executed = false
472
- libraries_using_spec(spec).each do |lib|
473
- lib_representation = library_rep(lib)
474
- executed ||= run_spec_pre_install_hook(spec, lib_representation)
475
- end
476
- UI.message "- #{spec.name}" if executed
477
- end
478
-
479
498
  executed = run_podfile_pre_install_hook
480
499
  UI.message "- Podfile" if executed
481
500
  end
482
501
  end
483
502
 
484
- # Runs the pre install hook of the given specification with the given
485
- # library representation.
486
- #
487
- # @param [Specification] spec
488
- # The spec for which the pre install hook should be run.
489
- #
490
- # @param [Hooks::LibraryRepresentation] lib_representation
491
- # The library representation to be passed as an argument to the
492
- # hook.
493
- #
494
- # @raise Raises an informative if the hooks raises.
495
- #
496
- # @return [Bool] Whether the hook was run.
497
- #
498
- def run_spec_pre_install_hook(spec, lib_representation)
499
- spec.pre_install!(pod_rep(spec.root.name), lib_representation)
500
- rescue => e
501
- raise Informative, "An error occurred while processing the pre-install " \
502
- "hook of #{spec}." \
503
- "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
504
- end
505
-
506
503
  # Runs the pre install hook of the Podfile
507
504
  #
508
505
  # @raise Raises an informative if the hooks raises.
@@ -526,42 +523,11 @@ module Pod
526
523
  #
527
524
  def run_post_install_hooks
528
525
  UI.message "- Running post install hooks" do
529
- analysis_result.specifications.each do |spec|
530
- executed = false
531
- libraries_using_spec(spec).each do |lib|
532
- lib_representation = library_rep(lib)
533
- executed ||= run_spec_post_install_hook(spec, lib_representation)
534
- end
535
- UI.message "- #{spec.name}" if executed
536
- end
537
526
  executed = run_podfile_post_install_hook
538
527
  UI.message "- Podfile" if executed
539
528
  end
540
529
  end
541
530
 
542
-
543
- # Runs the post install hook of the given specification with the given
544
- # library representation.
545
- #
546
- # @param [Specification] spec
547
- # The spec for which the post install hook should be run.
548
- #
549
- # @param [Hooks::LibraryRepresentation] lib_representation
550
- # The library representation to be passed as an argument to the
551
- # hook.
552
- #
553
- # @raise Raises an informative if the hooks raises.
554
- #
555
- # @return [Bool] Whether the hook was run.
556
- #
557
- def run_spec_post_install_hook(spec, lib_representation)
558
- spec.post_install!(lib_representation)
559
- rescue => e
560
- raise Informative, "An error occurred while processing the post-install " \
561
- "hook of #{spec}." \
562
- "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
563
- end
564
-
565
531
  # Runs the post install hook of the Podfile
566
532
  #
567
533
  # @raise Raises an informative if the hooks raises.