cocoapods 0.32.1 → 0.33.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.