cocoapods 1.0.0.beta.6 → 1.0.0.beta.7
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -0
- data/lib/cocoapods.rb +2 -1
- data/lib/cocoapods/command.rb +1 -1
- data/lib/cocoapods/command/init.rb +4 -4
- data/lib/cocoapods/command/install.rb +1 -1
- data/lib/cocoapods/command/inter_process_communication.rb +3 -3
- data/lib/cocoapods/command/list.rb +1 -1
- data/lib/cocoapods/command/outdated.rb +1 -1
- data/lib/cocoapods/command/repo/add.rb +1 -1
- data/lib/cocoapods/command/repo/lint.rb +6 -6
- data/lib/cocoapods/command/repo/list.rb +2 -2
- data/lib/cocoapods/command/repo/push.rb +13 -15
- data/lib/cocoapods/command/repo/update.rb +1 -1
- data/lib/cocoapods/command/setup.rb +2 -2
- data/lib/cocoapods/command/spec.rb +1 -1
- data/lib/cocoapods/config.rb +5 -0
- data/lib/cocoapods/core_overrides.rb +1 -0
- data/lib/cocoapods/downloader.rb +5 -18
- data/lib/cocoapods/downloader/request.rb +1 -10
- data/lib/cocoapods/gem_version.rb +1 -1
- data/lib/cocoapods/generator/copy_resources_script.rb +17 -17
- data/lib/cocoapods/generator/embed_frameworks_script.rb +2 -2
- data/lib/cocoapods/generator/info_plist_file.rb +1 -0
- data/lib/cocoapods/installer.rb +3 -1
- data/lib/cocoapods/installer/analyzer.rb +4 -4
- data/lib/cocoapods/installer/target_installer/pod_target_installer.rb +1 -1
- data/lib/cocoapods/resolver.rb +9 -6
- data/lib/cocoapods/sandbox/path_list.rb +1 -1
- data/lib/cocoapods/sources_manager.rb +42 -539
- data/lib/cocoapods/user_interface.rb +4 -0
- data/lib/cocoapods/user_interface/error_report.rb +1 -1
- data/lib/cocoapods/validator.rb +1 -1
- metadata +26 -55
@@ -96,8 +96,8 @@ module Pod
|
|
96
96
|
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
|
97
97
|
# Use the current code_sign_identitiy
|
98
98
|
echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
|
99
|
-
echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \\"$1\\""
|
100
|
-
/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1"
|
99
|
+
echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \\"$1\\""
|
100
|
+
/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1"
|
101
101
|
fi
|
102
102
|
}
|
103
103
|
|
@@ -116,6 +116,7 @@ module Pod
|
|
116
116
|
}
|
117
117
|
|
118
118
|
info['CFBundleExecutable'] = '${EXECUTABLE_NAME}' if bundle_package_type != :bndl
|
119
|
+
info['CFBundleVersion'] = '1' if bundle_package_type == :bndl
|
119
120
|
info['UIRequiredDeviceCapabilities'] = %w(arm64) if target.platform.name == :tvos
|
120
121
|
|
121
122
|
info
|
data/lib/cocoapods/installer.rb
CHANGED
@@ -249,7 +249,9 @@ module Pod
|
|
249
249
|
|
250
250
|
remainder = whitelisted_configs - all_user_configurations
|
251
251
|
unless remainder.empty?
|
252
|
-
raise Informative,
|
252
|
+
raise Informative,
|
253
|
+
"Unknown #{'configuration'.pluralize(remainder.size)} whitelisted: #{remainder.sort.to_sentence}. " \
|
254
|
+
"CocoaPods found #{all_user_configurations.sort.to_sentence}, did you mean one of these?"
|
253
255
|
end
|
254
256
|
end
|
255
257
|
|
@@ -216,8 +216,8 @@ module Pod
|
|
216
216
|
#
|
217
217
|
def update_repositories
|
218
218
|
sources.each do |source|
|
219
|
-
if
|
220
|
-
|
219
|
+
if source.git?
|
220
|
+
config.sources_manager.update(source.name)
|
221
221
|
else
|
222
222
|
UI.message "Skipping `#{source.name}` update because the repository is not a git source repository."
|
223
223
|
end
|
@@ -628,7 +628,7 @@ module Pod
|
|
628
628
|
#
|
629
629
|
# When no explicit Podfile sources are defined, this defaults to the
|
630
630
|
# master spec repository.
|
631
|
-
# available sources ({
|
631
|
+
# available sources ({config.sources_manager.all}).
|
632
632
|
#
|
633
633
|
# @return [Array<Source>] the sources to be used in finding
|
634
634
|
# specifications, as specified by the {#podfile} or all sources.
|
@@ -650,7 +650,7 @@ module Pod
|
|
650
650
|
end
|
651
651
|
|
652
652
|
sources.uniq.map do |source_url|
|
653
|
-
|
653
|
+
config.sources_manager.find_or_create_source_with_url(source_url)
|
654
654
|
end
|
655
655
|
end
|
656
656
|
end
|
@@ -177,7 +177,7 @@ module Pod
|
|
177
177
|
c.build_settings['PRODUCT_NAME'] = bundle_name
|
178
178
|
relative_info_plist_path = info_plist_path.relative_path_from(sandbox.root)
|
179
179
|
c.build_settings['INFOPLIST_FILE'] = relative_info_plist_path.to_s
|
180
|
-
c.build_settings['CONFIGURATION_BUILD_DIR'] = target.configuration_build_dir
|
180
|
+
c.build_settings['CONFIGURATION_BUILD_DIR'] = target.configuration_build_dir('$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)')
|
181
181
|
|
182
182
|
# Set the correct device family for this bundle, based on the platform
|
183
183
|
device_family_by_platform = {
|
data/lib/cocoapods/resolver.rb
CHANGED
@@ -350,7 +350,7 @@ module Pod
|
|
350
350
|
#
|
351
351
|
def aggregate_for_dependency(dependency)
|
352
352
|
if dependency && dependency.podspec_repo
|
353
|
-
return
|
353
|
+
return Config.instance.sources_manager.aggregate_for_dependency(dependency)
|
354
354
|
else
|
355
355
|
@aggregate ||= Source::Aggregate.new(sources)
|
356
356
|
end
|
@@ -420,11 +420,14 @@ module Pod
|
|
420
420
|
elsif !conflict.existing
|
421
421
|
conflict.requirements.values.flatten.each do |r|
|
422
422
|
if search_for(r).empty?
|
423
|
-
# There
|
424
|
-
message << "\n\nNone of
|
425
|
-
"\nYou have either
|
426
|
-
|
427
|
-
|
423
|
+
# There are no existing specification inside any of the spec repos with given requirements.
|
424
|
+
message << "\n\nNone of your spec sources contain a spec satisfying the dependency: `#{r}`." \
|
425
|
+
"\n\nYou have either:" \
|
426
|
+
"\n * out-of-date source repos which you can update with `pod repo update`." \
|
427
|
+
"\n * mistyped the name or version." \
|
428
|
+
"\n * not added the source repo that hosts the Podspec to your Podfile." \
|
429
|
+
"\n\nNote: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by default."
|
430
|
+
|
428
431
|
else
|
429
432
|
message << "\n\nSpecs satisfying the `#{r}` dependency were found, " \
|
430
433
|
'but they required a higher minimum deployment target.'
|
@@ -49,7 +49,7 @@ module Pod
|
|
49
49
|
end
|
50
50
|
root_length = root.to_s.length + 1
|
51
51
|
escaped_root = escape_path_for_glob(root)
|
52
|
-
paths = Dir.glob(escaped_root + '**/*', File::FNM_DOTMATCH)
|
52
|
+
paths = Dir.glob(escaped_root + '**/*', File::FNM_DOTMATCH).sort_by(&:upcase)
|
53
53
|
absolute_dirs = paths.select { |path| File.directory?(path) }
|
54
54
|
relative_dirs = absolute_dirs.map { |p| p[root_length..-1] }
|
55
55
|
absolute_paths = paths.reject { |p| p == "#{root}/." || p == "#{root}/.." }
|
@@ -1,49 +1,8 @@
|
|
1
|
-
|
2
|
-
# Manages all the sources known to the running CocoaPods Instance.
|
3
|
-
#
|
4
|
-
class SourcesManager
|
5
|
-
class << self
|
6
|
-
include Config::Mixin
|
7
|
-
|
8
|
-
# @return [Source::Aggregate] The aggregate of all the sources with the
|
9
|
-
# known Pods.
|
10
|
-
#
|
11
|
-
def aggregate
|
12
|
-
return Source::Aggregate.new([]) unless config.repos_dir.exist?
|
13
|
-
dirs = config.repos_dir.children.select(&:directory?)
|
14
|
-
aggregate_with_repos(dirs)
|
15
|
-
end
|
16
|
-
|
17
|
-
# @return [Source::Aggregate] The aggregate of the sources from repos.
|
18
|
-
#
|
19
|
-
# @param [Dependency] dependency
|
20
|
-
# The dependency for which to find or build the appropriate.
|
21
|
-
# aggregate. If the dependency specifies a source podspec repo
|
22
|
-
# then only that source will be used, otherwise all sources
|
23
|
-
# will be used.
|
24
|
-
#
|
25
|
-
def aggregate_for_dependency(dependency)
|
26
|
-
if dependency.podspec_repo
|
27
|
-
source = source_with_url(dependency.podspec_repo)
|
28
|
-
raise StandardError, '[Bug] Failed to find known source with the URL ' \
|
29
|
-
"#{dependency.podspec_repo.inspect}" if source.nil?
|
30
|
-
|
31
|
-
aggregate_with_repos([source_dir(source.name)])
|
32
|
-
else
|
33
|
-
aggregate
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# @return [Array<Source>] The list of the sources with the given names.
|
38
|
-
#
|
39
|
-
# @param [Array<#to_s>] names
|
40
|
-
# The names of the sources.
|
41
|
-
#
|
42
|
-
def sources(names)
|
43
|
-
dirs = names.map { |name| source_dir(name) }
|
44
|
-
dirs.map { |repo| source_from_path(repo) }
|
45
|
-
end
|
1
|
+
require 'cocoapods-core/source'
|
46
2
|
|
3
|
+
module Pod
|
4
|
+
class Source
|
5
|
+
class Manager
|
47
6
|
# Returns the source whose {Source#url} is equal to `url`, adding the repo
|
48
7
|
# in a manner similarly to `pod repo add` if it is not found.
|
49
8
|
#
|
@@ -66,16 +25,21 @@ module Pod
|
|
66
25
|
else
|
67
26
|
Command::Repo::Add.parse([name, url]).run
|
68
27
|
end
|
69
|
-
rescue Informative
|
70
|
-
|
71
|
-
"named `#{name}`.\
|
28
|
+
rescue Informative => e
|
29
|
+
message = "Unable to add a source with url `#{url}` " \
|
30
|
+
"named `#{name}`.\n"
|
31
|
+
message << "(#{e})\n" if Config.instance.verbose?
|
32
|
+
message << 'You can try adding it manually in ' \
|
72
33
|
'`~/.cocoapods/repos` or via `pod repo add`.'
|
34
|
+
raise Informative, message
|
73
35
|
ensure
|
74
36
|
UI.title_level = previous_title_level
|
75
37
|
end
|
76
38
|
source = source_with_url(url)
|
77
39
|
end
|
78
40
|
|
41
|
+
raise "Unable to create a source with URL #{url}" unless source
|
42
|
+
|
79
43
|
source
|
80
44
|
end
|
81
45
|
|
@@ -93,219 +57,14 @@ module Pod
|
|
93
57
|
find_or_create_source_with_url(name_or_url)
|
94
58
|
end
|
95
59
|
|
96
|
-
# @return [Array<Source>] The list of all the sources known to this
|
97
|
-
# installation of CocoaPods.
|
98
|
-
#
|
99
|
-
def all
|
100
|
-
return [] unless config.repos_dir.exist?
|
101
|
-
dirs = config.repos_dir.children.select(&:directory?)
|
102
|
-
dirs.map { |repo| source_from_path(repo) }
|
103
|
-
end
|
104
|
-
|
105
|
-
# @return [Array<Source>] The CocoaPods Master Repo source.
|
106
|
-
#
|
107
|
-
def master
|
108
|
-
sources(['master']).select { |s| s.repo.directory? }
|
109
|
-
end
|
110
|
-
|
111
|
-
# Search the appropriate sources to match the set for the given dependency.
|
112
|
-
#
|
113
|
-
# @return [Set, nil] a set for a given dependency including all the
|
114
|
-
# {Source} that contain the Pod. If no sources containing the
|
115
|
-
# Pod where found it returns nil.
|
116
|
-
#
|
117
|
-
# @raise If no source can be found that includes the dependency.
|
118
|
-
#
|
119
|
-
def search(dependency)
|
120
|
-
aggregate_for_dependency(dependency).search(dependency)
|
121
|
-
end
|
122
|
-
|
123
|
-
# Search all the sources with the given search term.
|
124
|
-
#
|
125
|
-
# @param [String] query
|
126
|
-
# The search term.
|
127
|
-
#
|
128
|
-
# @param [Bool] full_text_search
|
129
|
-
# Whether the search should be limited to the name of the Pod or
|
130
|
-
# should include also the author, the summary, and the
|
131
|
-
# description.
|
132
|
-
#
|
133
|
-
# @raise If no source including the set can be found.
|
134
|
-
#
|
135
|
-
# @return [Array<Set>] The sets that contain the search term.
|
136
|
-
#
|
137
|
-
def search_by_name(query, full_text_search = false)
|
138
|
-
query_word_regexps = query.split.map { |word| /#{word}/i }
|
139
|
-
if full_text_search
|
140
|
-
query_word_results_hash = {}
|
141
|
-
updated_search_index.each_value do |word_spec_hash|
|
142
|
-
word_spec_hash.each_pair do |word, spec_symbols|
|
143
|
-
query_word_regexps.each do |query_word_regexp|
|
144
|
-
set = (query_word_results_hash[query_word_regexp] ||= Set.new)
|
145
|
-
set.merge(spec_symbols) if word =~ query_word_regexp
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
found_set_symbols = query_word_results_hash.values.reduce(:&)
|
150
|
-
found_set_symbols ||= []
|
151
|
-
sets = found_set_symbols.map do |symbol|
|
152
|
-
aggregate.representative_set(symbol.to_s)
|
153
|
-
end
|
154
|
-
# Remove nil values because representative_set return nil if no pod is found in any of the sources.
|
155
|
-
sets.compact!
|
156
|
-
else
|
157
|
-
sets = aggregate.search_by_name(query, false)
|
158
|
-
end
|
159
|
-
if sets.empty?
|
160
|
-
extra = ', author, summary, or description' if full_text_search
|
161
|
-
raise Informative, "Unable to find a pod with name#{extra}" \
|
162
|
-
"matching `#{query}`"
|
163
|
-
end
|
164
|
-
sorted_sets(sets, query_word_regexps)
|
165
|
-
end
|
166
|
-
|
167
|
-
# Returns given set array by sorting it in-place.
|
168
|
-
#
|
169
|
-
# @param [Array<Set>] sets
|
170
|
-
# Array of sets to be sorted.
|
171
|
-
#
|
172
|
-
# @param [Array<Regexp>] query_word_regexps
|
173
|
-
# Array of regexp objects for user query.
|
174
|
-
#
|
175
|
-
# @return [Array<Set>] Given sets parameter itself after sorting it in-place.
|
176
|
-
#
|
177
|
-
def sorted_sets(sets, query_word_regexps)
|
178
|
-
sets.sort_by! do |set|
|
179
|
-
pre_match_length = nil
|
180
|
-
found_query_index = nil
|
181
|
-
found_query_count = 0
|
182
|
-
query_word_regexps.each_with_index do |q, idx|
|
183
|
-
if (m = set.name.match(/#{q}/i))
|
184
|
-
pre_match_length ||= (m.pre_match.length)
|
185
|
-
found_query_index ||= idx
|
186
|
-
found_query_count += 1
|
187
|
-
end
|
188
|
-
end
|
189
|
-
pre_match_length ||= 1000
|
190
|
-
found_query_index ||= 1000
|
191
|
-
[-found_query_count, pre_match_length, found_query_index, set.name.downcase]
|
192
|
-
end
|
193
|
-
sets
|
194
|
-
end
|
195
|
-
|
196
|
-
# Returns the search data. If a saved search data exists, retrieves it from file and returns it.
|
197
|
-
# Else, creates the search data from scratch, saves it to file system, and returns it.
|
198
|
-
# Search data is grouped by source repos. For each source, it contains a hash where keys are words
|
199
|
-
# and values are the pod names containing corresponding word.
|
200
|
-
#
|
201
|
-
# For each source, list of unique words are generated from the following spec information.
|
202
|
-
# - version
|
203
|
-
# - summary
|
204
|
-
# - description
|
205
|
-
# - authors
|
206
|
-
#
|
207
|
-
# @return [Hash{String => Hash{String => Array<String>}}] The up to date search data.
|
208
|
-
#
|
209
|
-
def updated_search_index
|
210
|
-
index = stored_search_index || {}
|
211
|
-
all.each do |source|
|
212
|
-
source_name = source.name
|
213
|
-
unless index[source_name]
|
214
|
-
UI.print "Creating search index for spec repo '#{source_name}'.."
|
215
|
-
index[source_name] = aggregate.generate_search_index_for_source(source)
|
216
|
-
UI.puts ' Done!'
|
217
|
-
end
|
218
|
-
end
|
219
|
-
save_search_index(index)
|
220
|
-
index
|
221
|
-
end
|
222
|
-
|
223
|
-
# Returns the search data stored in the file system.
|
224
|
-
# If existing data in the file system is not valid, returns nil.
|
225
|
-
#
|
226
|
-
def stored_search_index
|
227
|
-
unless @updated_search_index
|
228
|
-
if search_index_path.exist?
|
229
|
-
require 'json'
|
230
|
-
index = JSON.parse(search_index_path.read)
|
231
|
-
if index && index.is_a?(Hash) # TODO: should we also check if hash has correct hierarchy?
|
232
|
-
return @updated_search_index = index
|
233
|
-
end
|
234
|
-
end
|
235
|
-
@updated_search_index = nil
|
236
|
-
end
|
237
|
-
@updated_search_index
|
238
|
-
end
|
239
|
-
|
240
|
-
# Stores given search data in the file system.
|
241
|
-
# @param [Hash] index
|
242
|
-
# Index to be saved in file system
|
243
|
-
#
|
244
|
-
def save_search_index(index)
|
245
|
-
require 'json'
|
246
|
-
@updated_search_index = index
|
247
|
-
search_index_path.open('w') do |io|
|
248
|
-
io.write(@updated_search_index.to_json)
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
# Allows to clear the search index.
|
253
|
-
#
|
254
|
-
attr_writer :updated_search_index
|
255
|
-
|
256
60
|
# @return [Pathname] The path where the search index should be stored.
|
257
61
|
#
|
258
62
|
def search_index_path
|
259
|
-
Config.instance.search_index_file
|
63
|
+
@search_index_path ||= Config.instance.search_index_file
|
260
64
|
end
|
261
65
|
|
262
66
|
# @!group Updating Sources
|
263
67
|
|
264
|
-
extend Executable
|
265
|
-
executable :git
|
266
|
-
|
267
|
-
# Updates the stored search index if there are changes in spec repos while updating them.
|
268
|
-
# Update is performed incrementally. Only the changed pods' search data is re-generated and updated.
|
269
|
-
# @param [Hash{Source => Array<String>}] changed_spec_paths
|
270
|
-
# A hash containing changed specification paths for each source.
|
271
|
-
#
|
272
|
-
def update_search_index_if_needed(changed_spec_paths)
|
273
|
-
search_index = stored_search_index
|
274
|
-
return unless search_index
|
275
|
-
changed_spec_paths.each_pair do |source, spec_paths|
|
276
|
-
index_for_source = search_index[source.name]
|
277
|
-
next unless index_for_source && spec_paths.length > 0
|
278
|
-
updated_pods = source.pods_for_specification_paths(spec_paths)
|
279
|
-
|
280
|
-
new_index = aggregate.generate_search_index_for_changes_in_source(source, spec_paths)
|
281
|
-
# First traverse search_index and update existing words
|
282
|
-
# Removed traversed words from new_index after adding to search_index,
|
283
|
-
# so that only non existing words will remain in new_index after enumeration completes.
|
284
|
-
index_for_source.each_pair do |word, _|
|
285
|
-
if new_index[word]
|
286
|
-
index_for_source[word] |= new_index[word]
|
287
|
-
else
|
288
|
-
index_for_source[word] -= updated_pods
|
289
|
-
end
|
290
|
-
end
|
291
|
-
# Now add non existing words remained in new_index to search_index
|
292
|
-
index_for_source.merge!(new_index)
|
293
|
-
end
|
294
|
-
save_search_index(search_index)
|
295
|
-
end
|
296
|
-
|
297
|
-
# Updates search index for changed pods in background
|
298
|
-
# @param [Hash{Source => Array<String>}] changed_spec_paths
|
299
|
-
# A hash containing changed specification paths for each source.
|
300
|
-
#
|
301
|
-
def update_search_index_if_needed_in_background(changed_spec_paths)
|
302
|
-
Process.fork do
|
303
|
-
Process.daemon
|
304
|
-
update_search_index_if_needed(changed_spec_paths)
|
305
|
-
exit
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
68
|
# Updates the local clone of the spec-repo with the given name or of all
|
310
69
|
# the git repos if the name is omitted.
|
311
70
|
#
|
@@ -327,298 +86,14 @@ module Pod
|
|
327
86
|
UI.section "Updating spec repo `#{source.name}`" do
|
328
87
|
changed_source_paths = source.update(show_output)
|
329
88
|
changed_spec_paths[source] = changed_source_paths if changed_source_paths.count > 0
|
330
|
-
|
89
|
+
source.verify_compatibility!
|
331
90
|
end
|
332
91
|
end
|
333
92
|
# Perform search index update operation in background.
|
334
93
|
update_search_index_if_needed_in_background(changed_spec_paths)
|
335
94
|
end
|
336
|
-
|
337
|
-
# Returns whether a source is a GIT repo.
|
338
|
-
#
|
339
|
-
# @param [Pathname] dir
|
340
|
-
# The directory where the source is stored.
|
341
|
-
#
|
342
|
-
# @return [Bool] Whether the given source is a GIT repo.
|
343
|
-
#
|
344
|
-
def git_repo?(dir)
|
345
|
-
Dir.chdir(dir) do
|
346
|
-
Executable.capture_command('git', %w(rev-parse), :capture => :none).success?
|
347
|
-
end
|
348
|
-
end
|
349
|
-
|
350
|
-
# Checks the version information of the source with the given directory.
|
351
|
-
# It raises if the source is not compatible and if there is CocoaPods
|
352
|
-
# update it informs the user.
|
353
|
-
#
|
354
|
-
# @param [Pathname] dir
|
355
|
-
# The directory where the source is stored.
|
356
|
-
#
|
357
|
-
# @raise If the source is not compatible.
|
358
|
-
#
|
359
|
-
# @return [void]
|
360
|
-
#
|
361
|
-
def check_version_information(dir)
|
362
|
-
versions = version_information(dir)
|
363
|
-
unless repo_compatible?(dir)
|
364
|
-
min = versions['min']
|
365
|
-
max = versions['max']
|
366
|
-
version_msg = (min == max) ? min : "#{min} - #{max}"
|
367
|
-
raise Informative, "The `#{dir.basename}` repo requires " \
|
368
|
-
"CocoaPods #{version_msg} (currently using #{Pod::VERSION})\n".red +
|
369
|
-
'Update CocoaPods, or checkout the appropriate tag in the repo.'
|
370
|
-
end
|
371
|
-
|
372
|
-
if config.new_version_message? && cocoapods_update?(versions)
|
373
|
-
last = versions['last']
|
374
|
-
rc = Gem::Version.new(last).prerelease?
|
375
|
-
install_message = needs_sudo? ? 'sudo ' : ''
|
376
|
-
install_message << 'gem install cocoapods'
|
377
|
-
install_message << ' --pre' if rc
|
378
|
-
message = [
|
379
|
-
"CocoaPods #{last} is available.".green,
|
380
|
-
"To update use: `#{install_message}`".green,
|
381
|
-
("[!] This is a test version we'd love you to try.".yellow if rc),
|
382
|
-
("Until we reach version 1.0 the features of CocoaPods can and will change.\n" \
|
383
|
-
'We strongly recommend that you use the latest version at all times.'.yellow unless rc),
|
384
|
-
'',
|
385
|
-
'For more information, see https://blog.cocoapods.org ' \
|
386
|
-
'and the CHANGELOG for this version at ' \
|
387
|
-
"https://github.com/CocoaPods/CocoaPods/releases/tag/#{last}".green,
|
388
|
-
'',
|
389
|
-
].compact.join("\n")
|
390
|
-
UI.puts("\n#{message}\n")
|
391
|
-
end
|
392
|
-
end
|
393
|
-
|
394
|
-
# Returns whether a source is compatible with the current version of
|
395
|
-
# CocoaPods.
|
396
|
-
#
|
397
|
-
# @param [Pathname] dir
|
398
|
-
# The directory where the source is stored.
|
399
|
-
#
|
400
|
-
# @return [Bool] whether the source is compatible.
|
401
|
-
#
|
402
|
-
def repo_compatible?(dir)
|
403
|
-
versions = version_information(dir)
|
404
|
-
|
405
|
-
min = versions['min']
|
406
|
-
max = versions['max']
|
407
|
-
bin_version = Gem::Version.new(Pod::VERSION)
|
408
|
-
supports_min = !min || bin_version >= Gem::Version.new(min)
|
409
|
-
supports_max = !max || bin_version <= Gem::Version.new(max)
|
410
|
-
supports_min && supports_max
|
411
|
-
end
|
412
|
-
|
413
|
-
# Checks whether there is a CocoaPods given the version information of a
|
414
|
-
# repo.
|
415
|
-
#
|
416
|
-
# @param [Hash] version_information
|
417
|
-
# The version information of a repository.
|
418
|
-
#
|
419
|
-
# @return [Bool] whether there is an update.
|
420
|
-
#
|
421
|
-
def cocoapods_update?(version_information)
|
422
|
-
version = version_information['last']
|
423
|
-
version && Gem::Version.new(version) > Gem::Version.new(Pod::VERSION)
|
424
|
-
end
|
425
|
-
|
426
|
-
# Returns the contents of the `CocoaPods-version.yml` file, which stores
|
427
|
-
# information about CocoaPods versions.
|
428
|
-
#
|
429
|
-
# This file is a hash with the following keys:
|
430
|
-
#
|
431
|
-
# - last: the last version of CocoaPods known to the source.
|
432
|
-
# - min: the minimum version of CocoaPods supported by the source.
|
433
|
-
# - max: the maximum version of CocoaPods supported by the source.
|
434
|
-
#
|
435
|
-
# @param [Pathname] dir
|
436
|
-
# The directory where the source is stored.
|
437
|
-
#
|
438
|
-
# @return [Hash] the versions information from the repo.
|
439
|
-
#
|
440
|
-
def version_information(dir)
|
441
|
-
require 'yaml'
|
442
|
-
yaml_file = dir + 'CocoaPods-version.yml'
|
443
|
-
return {} unless yaml_file.exist?
|
444
|
-
begin
|
445
|
-
YAMLHelper.load_file(yaml_file)
|
446
|
-
rescue Informative
|
447
|
-
raise Informative, "There was an error reading '#{yaml_file}'.\n" \
|
448
|
-
'Please consult https://blog.cocoapods.org/' \
|
449
|
-
'Repairing-Our-Broken-Specs-Repository/ ' \
|
450
|
-
'for more information.'
|
451
|
-
end
|
452
|
-
end
|
453
|
-
|
454
|
-
# @!group Master repo
|
455
|
-
|
456
|
-
# @return [Pathname] The path of the master repo.
|
457
|
-
#
|
458
|
-
def master_repo_dir
|
459
|
-
config.repos_dir + 'master'
|
460
|
-
end
|
461
|
-
|
462
|
-
# @return [Bool] Checks if the master repo is usable.
|
463
|
-
#
|
464
|
-
# @note Note this is used to automatically setup the master repo if
|
465
|
-
# needed.
|
466
|
-
#
|
467
|
-
def master_repo_functional?
|
468
|
-
master_repo_dir.exist? && repo_compatible?(master_repo_dir)
|
469
|
-
end
|
470
|
-
|
471
|
-
private
|
472
|
-
|
473
|
-
# @return [Source] The Source at a given path.
|
474
|
-
#
|
475
|
-
# @param [Pathname] path
|
476
|
-
# The local file path to one podspec repo.
|
477
|
-
#
|
478
|
-
def source_from_path(path)
|
479
|
-
return Source.new(path) unless path.basename.to_s == 'master'
|
480
|
-
MasterSource.new(path)
|
481
|
-
end
|
482
|
-
|
483
|
-
# @return [Source::Aggregate] The aggregate of the sources from repos.
|
484
|
-
#
|
485
|
-
# @param [Array<Pathname>] repos
|
486
|
-
# The local file paths to one or more podspec repo caches.
|
487
|
-
#
|
488
|
-
def aggregate_with_repos(repos)
|
489
|
-
sources = repos.map { |path| source_from_path(path) }
|
490
|
-
@aggregates_by_repos ||= {}
|
491
|
-
@aggregates_by_repos[repos] ||= Source::Aggregate.new(sources)
|
492
|
-
end
|
493
|
-
|
494
|
-
# @return [Bool] Whether the given path is writable by the current user.
|
495
|
-
#
|
496
|
-
# @param [#to_s] path
|
497
|
-
# The path.
|
498
|
-
#
|
499
|
-
def path_writable?(path)
|
500
|
-
Pathname(path).dirname.writable?
|
501
|
-
end
|
502
|
-
|
503
|
-
# @return [Bool] Whether `gem install` probably needs `sudo` to succeed.
|
504
|
-
#
|
505
|
-
def needs_sudo?
|
506
|
-
!path_writable?(__FILE__)
|
507
|
-
end
|
508
|
-
|
509
|
-
# @return [Source] The git source with the given name. If no git source
|
510
|
-
# with given name is found it raises.
|
511
|
-
#
|
512
|
-
# @param [String] name
|
513
|
-
# The name of the source.
|
514
|
-
#
|
515
|
-
def git_source_named(name)
|
516
|
-
specified_source = aggregate.sources.find { |s| s.name == name }
|
517
|
-
unless specified_source
|
518
|
-
raise Informative, "Unable to find the `#{name}` repo."
|
519
|
-
end
|
520
|
-
unless git_repo?(specified_source.repo)
|
521
|
-
raise Informative, "The `#{name}` repo is not a git repo."
|
522
|
-
end
|
523
|
-
specified_source
|
524
|
-
end
|
525
|
-
|
526
|
-
# @return [Source] The list of the git sources.
|
527
|
-
#
|
528
|
-
def git_sources
|
529
|
-
all.select do |source|
|
530
|
-
git_repo?(source.repo)
|
531
|
-
end
|
532
|
-
end
|
533
|
-
|
534
|
-
# @return [Pathname] The path of the source with the given name.
|
535
|
-
#
|
536
|
-
# @param [String] name
|
537
|
-
# The name of the source.
|
538
|
-
#
|
539
|
-
def source_dir(name)
|
540
|
-
if dir = config.repos_dir + name
|
541
|
-
dir
|
542
|
-
else
|
543
|
-
raise Informative, "Unable to find the `#{name}` repo."
|
544
|
-
end
|
545
|
-
end
|
546
|
-
|
547
|
-
# @return [Source] The source whose {Source#url} is equal to `url`.
|
548
|
-
#
|
549
|
-
# @param [String] url
|
550
|
-
# The URL of the source.
|
551
|
-
#
|
552
|
-
def source_with_url(url)
|
553
|
-
url = url.downcase.gsub(/.git$/, '')
|
554
|
-
aggregate.sources.find do |source|
|
555
|
-
source.url && source.url.downcase.gsub(/.git$/, '') == url
|
556
|
-
end
|
557
|
-
end
|
558
|
-
|
559
|
-
# Returns a suitable repository name for `url`.
|
560
|
-
#
|
561
|
-
# @example A GitHub.com URL
|
562
|
-
#
|
563
|
-
# name_for_url('https://github.com/Artsy/Specs.git')
|
564
|
-
# # "artsy"
|
565
|
-
# name_for_url('https://github.com/Artsy/Specs.git')
|
566
|
-
# # "artsy-1"
|
567
|
-
#
|
568
|
-
# @example A non-Github.com URL
|
569
|
-
#
|
570
|
-
# name_for_url('https://sourceforge.org/Artsy/Specs.git')
|
571
|
-
# # sourceforge-artsy-specs
|
572
|
-
#
|
573
|
-
# @example A file URL
|
574
|
-
#
|
575
|
-
# name_for_url('file:///Artsy/Specs.git')
|
576
|
-
# # artsy-specs
|
577
|
-
#
|
578
|
-
# @param [#to_s] url
|
579
|
-
# The URL of the source.
|
580
|
-
#
|
581
|
-
# @return [String] A suitable repository name for `url`.
|
582
|
-
#
|
583
|
-
def name_for_url(url)
|
584
|
-
base_from_host_and_path = lambda do |host, path|
|
585
|
-
if host
|
586
|
-
base = host.split('.')[-2] || host
|
587
|
-
base += '-'
|
588
|
-
else
|
589
|
-
base = ''
|
590
|
-
end
|
591
|
-
|
592
|
-
base + path.gsub(/.git$/, '').gsub(/^\//, '').split('/').join('-')
|
593
|
-
end
|
594
|
-
|
595
|
-
case url.to_s.downcase
|
596
|
-
when %r{github.com[:/]+cocoapods/specs}
|
597
|
-
base = 'master'
|
598
|
-
when %r{github.com[:/]+(.+)/(.+)}
|
599
|
-
base = Regexp.last_match[1]
|
600
|
-
when /^\S+@(\S+)[:\/]+(.+)$/
|
601
|
-
host, path = Regexp.last_match.captures
|
602
|
-
base = base_from_host_and_path[host, path]
|
603
|
-
when URI.regexp
|
604
|
-
url = URI(url.downcase)
|
605
|
-
base = base_from_host_and_path[url.host, url.path]
|
606
|
-
else
|
607
|
-
base = url.to_s.downcase
|
608
|
-
end
|
609
|
-
|
610
|
-
name = base
|
611
|
-
infinity = 1.0 / 0
|
612
|
-
(1..infinity).each do |i|
|
613
|
-
break unless source_dir(name).exist?
|
614
|
-
name = "#{base}-#{i}"
|
615
|
-
end
|
616
|
-
name
|
617
|
-
end
|
618
95
|
end
|
619
|
-
end
|
620
96
|
|
621
|
-
class Source
|
622
97
|
extend Executable
|
623
98
|
executable :git
|
624
99
|
|
@@ -649,5 +124,33 @@ module Pod
|
|
649
124
|
end
|
650
125
|
super
|
651
126
|
end
|
127
|
+
|
128
|
+
def verify_compatibility!
|
129
|
+
super
|
130
|
+
latest_cocoapods_version = metadata.latest_cocoapods_version && Gem::Version.create(metadata.latest_cocoapods_version)
|
131
|
+
return unless Config.instance.new_version_message? &&
|
132
|
+
latest_cocoapods_version &&
|
133
|
+
latest_cocoapods_version > Gem::Version.new(Pod::VERSION)
|
134
|
+
|
135
|
+
rc = latest_cocoapods_version.prerelease?
|
136
|
+
install_message = !Pathname(__FILE__).dirname.writable? ? 'sudo ' : ''
|
137
|
+
install_message << 'gem install cocoapods'
|
138
|
+
install_message << ' --pre' if rc
|
139
|
+
message = [
|
140
|
+
'',
|
141
|
+
"CocoaPods #{latest_cocoapods_version} is available.".green,
|
142
|
+
"To update use: `#{install_message}`".green,
|
143
|
+
("[!] This is a test version we'd love you to try.".yellow if rc),
|
144
|
+
("Until we reach version 1.0 the features of CocoaPods can and will change.\n" \
|
145
|
+
'We strongly recommend that you use the latest version at all times.'.yellow unless rc),
|
146
|
+
'',
|
147
|
+
'For more information, see https://blog.cocoapods.org ' \
|
148
|
+
'and the CHANGELOG for this version at ' \
|
149
|
+
"https://github.com/CocoaPods/CocoaPods/releases/tag/#{latest_cocoapods_version}".green,
|
150
|
+
'',
|
151
|
+
'',
|
152
|
+
].compact.join("\n")
|
153
|
+
UI.puts(message)
|
154
|
+
end
|
652
155
|
end
|
653
156
|
end
|