cocoapods 0.32.1 → 0.33.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +97 -1
- data/lib/cocoapods/command.rb +4 -10
- data/lib/cocoapods/command/help.rb +3 -1
- data/lib/cocoapods/command/init.rb +3 -1
- data/lib/cocoapods/command/inter_process_communication.rb +9 -5
- data/lib/cocoapods/command/lib.rb +4 -1
- data/lib/cocoapods/command/outdated.rb +64 -15
- data/lib/cocoapods/command/project.rb +9 -7
- data/lib/cocoapods/command/push.rb +5 -160
- data/lib/cocoapods/command/repo.rb +15 -4
- data/lib/cocoapods/command/repo/push.rb +199 -0
- data/lib/cocoapods/command/search.rb +3 -1
- data/lib/cocoapods/command/spec.rb +16 -6
- data/lib/cocoapods/executable.rb +1 -1
- data/lib/cocoapods/gem_version.rb +1 -1
- data/lib/cocoapods/installer.rb +31 -65
- data/lib/cocoapods/installer/user_project_integrator.rb +7 -6
- data/lib/cocoapods/sources_manager.rb +28 -5
- data/lib/cocoapods/user_interface.rb +2 -2
- data/lib/cocoapods/user_interface/error_report.rb +15 -1
- data/lib/cocoapods/validator.rb +24 -27
- metadata +85 -16
@@ -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 =
|
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 =
|
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 =
|
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 =
|
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
|
@@ -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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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
|
-
|
355
|
+
Pathname(spec.defined_in_file)
|
346
356
|
end
|
347
357
|
|
348
358
|
# @return [String] of spec paths one on each line
|
data/lib/cocoapods/executable.rb
CHANGED
@@ -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, "#{
|
74
|
+
raise Informative, "#{full_command}\n\n#{output}"
|
75
75
|
else
|
76
76
|
UI.message("[!] Failed: #{full_command}".red)
|
77
77
|
end
|
data/lib/cocoapods/installer.rb
CHANGED
@@ -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
|
168
|
-
|
169
|
-
|
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.
|