Class: Pod::Source::Manager
- Inherits:
-
Object
- Object
- Pod::Source::Manager
- Defined in:
- lib/cocoapods-core/source/manager.rb
Master repo collapse
-
#search_index_path ⇒ Pathname
The path where the search index should be stored.
-
#updated_search_index ⇒ Hash{String => Hash{String => Array<String>}}
Returns the search data.
Instance Attribute Summary collapse
-
#repos_dir ⇒ Pathname
readonly
The directory that contains the source repo directories.
Master repo collapse
-
#aggregate_with_repos(repos) ⇒ Source::Aggregate
private
The aggregate of the sources from repos.
- #canonic_url(url) ⇒ Object private
-
#indexable_sources ⇒ Source
private
The list of the indexable sources.
-
#master_repo_dir ⇒ Pathname
The path of the master repo.
-
#master_repo_functional? ⇒ Boolean
Checks if the master repo is usable.
-
#name_for_url(url) ⇒ String
private
Returns a suitable repository name for
url
. -
#save_search_index(index) ⇒ Object
Stores given search data in the file system.
-
#search(dependency) ⇒ Set?
Search the appropriate sources to match the set for the given dependency.
-
#search_by_name(query, full_text_search = false) ⇒ Array<Set>
Search all the sources with the given search term.
-
#sorted_sets(sets, query_word_regexps) ⇒ Array<Set>
Returns given set array by sorting it in-place.
-
#source_dir(name) ⇒ Pathname
private
The path of the source with the given name.
-
#source_from_path(path) ⇒ Source
private
The Source at a given path.
-
#source_with_name(name) ⇒ Source
private
The source with the given name.
-
#source_with_url(url) ⇒ Source
private
The source whose #url is equal to
url
. -
#stored_search_index ⇒ Object
Returns the search data stored in the file system.
-
#trunk_repo_hostname ⇒ Object
private
Returns hostname for for
trunk
URL. -
#update_search_index_if_needed(changed_spec_paths) ⇒ Object
Updates the stored search index if there are changes in spec repos while updating them.
-
#update_search_index_if_needed_in_background(changed_spec_paths) ⇒ Object
Updates search index for changed pods in background.
-
#updateable_source_named(name) ⇒ Source
private
The updateable source with the given name.
-
#updateable_sources ⇒ Source
private
The list of the updateable sources.
Instance Method Summary collapse
-
#aggregate ⇒ Source::Aggregate
The aggregate of all the sources with the known Pods.
-
#aggregate_for_dependency(dependency) ⇒ Source::Aggregate
The aggregate of the sources from repos.
-
#all ⇒ Array<Source>
The list of all the sources known to this installation of CocoaPods.
-
#all_non_indexable ⇒ Array<Source>
The list of all the non-indexable sources known to this installation of CocoaPods.
-
#initialize(repos_dir) ⇒ Manager
constructor
A new instance of Manager.
-
#master ⇒ Array<Source>
The CocoaPods Master Repo source.
-
#source_repos ⇒ Array<Pathname>
The source repo directories.
-
#sources(names) ⇒ Array<Source>
The list of the sources with the given names.
Constructor Details
#initialize(repos_dir) ⇒ Manager
Returns a new instance of Manager.
11 12 13 |
# File 'lib/cocoapods-core/source/manager.rb', line 11 def initialize(repos_dir) @repos_dir = Pathname(repos_dir). end |
Instance Attribute Details
#repos_dir ⇒ Pathname (readonly)
Returns The directory that contains the source repo directories.
9 10 11 |
# File 'lib/cocoapods-core/source/manager.rb', line 9 def repos_dir @repos_dir end |
#search_index_path ⇒ Pathname
Returns The path where the search index should be stored.
302 303 304 |
# File 'lib/cocoapods-core/source/manager.rb', line 302 def search_index_path @search_index_path end |
#updated_search_index ⇒ Hash{String => Hash{String => Array<String>}}
Returns the search data. If a saved search data exists, retrieves it from file and returns it. Else, creates the search data from scratch, saves it to file system, and returns it. Search data is grouped by source repos. For each source, it contains a hash where keys are words and values are the pod names containing corresponding word.
For each source, list of unique words are generated from the following spec information.
- version
- summary
- description
- authors
198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/cocoapods-core/source/manager.rb', line 198 def updated_search_index index = stored_search_index || {} indexable_sources.each do |source| source_name = source.name unless index[source_name] CoreUI.print "Creating search index for spec repo '#{source_name}'.." index[source_name] = aggregate.generate_search_index_for_source(source) CoreUI.puts ' Done!' end end save_search_index(index) index end |
Instance Method Details
#aggregate ⇒ Source::Aggregate
Returns The aggregate of all the sources with the known Pods.
25 26 27 |
# File 'lib/cocoapods-core/source/manager.rb', line 25 def aggregate aggregate_with_repos(source_repos) end |
#aggregate_for_dependency(dependency) ⇒ Source::Aggregate
Returns The aggregate of the sources from repos.
37 38 39 40 41 42 43 44 |
# File 'lib/cocoapods-core/source/manager.rb', line 37 def aggregate_for_dependency(dependency) return aggregate if dependency.podspec_repo.nil? source = source_with_url(dependency.podspec_repo) || source_with_name(dependency.podspec_repo) return aggregate if source.nil? aggregate_with_repos([source.repo]) end |
#aggregate_with_repos(repos) ⇒ Source::Aggregate (private)
Returns The aggregate of the sources from repos.
330 331 332 333 334 |
# File 'lib/cocoapods-core/source/manager.rb', line 330 def aggregate_with_repos(repos) sources = repos.map { |path| source_from_path(path) } @aggregates_by_repos ||= {} @aggregates_by_repos[repos] ||= Source::Aggregate.new(sources) end |
#all ⇒ Array<Source>
Returns The list of all the sources known to this installation of CocoaPods.
59 60 61 |
# File 'lib/cocoapods-core/source/manager.rb', line 59 def all aggregate.sources end |
#all_non_indexable ⇒ Array<Source>
Returns The list of all the non-indexable sources known to this installation of CocoaPods.
66 67 68 |
# File 'lib/cocoapods-core/source/manager.rb', line 66 def all_non_indexable aggregate.sources.reject(&:indexable?) end |
#canonic_url(url) ⇒ Object (private)
398 399 400 |
# File 'lib/cocoapods-core/source/manager.rb', line 398 def canonic_url(url) url.downcase.gsub(/\.git$/, '').gsub(%r{\/$}, '') end |
#indexable_sources ⇒ Source (private)
Returns The list of the indexable sources.
372 373 374 |
# File 'lib/cocoapods-core/source/manager.rb', line 372 def indexable_sources all.select(&:indexable?) end |
#master ⇒ Array<Source>
Returns The CocoaPods Master Repo source.
72 73 74 |
# File 'lib/cocoapods-core/source/manager.rb', line 72 def master sources([Pod::TrunkSource::TRUNK_REPO_NAME]).select { |s| s.repo.directory? } end |
#master_repo_dir ⇒ Pathname
Returns The path of the master repo.
80 81 82 |
# File 'lib/cocoapods-core/source/manager.rb', line 80 def master_repo_dir source_dir(Pod::TrunkSource::TRUNK_REPO_NAME) end |
#master_repo_functional? ⇒ Boolean
Note this is used to automatically setup the master repo if needed.
Returns Checks if the master repo is usable.
89 90 91 92 |
# File 'lib/cocoapods-core/source/manager.rb', line 89 def master_repo_functional? return false unless master_repo = master.first master_repo..compatible?(CORE_VERSION) end |
#name_for_url(url) ⇒ String (private)
Returns a suitable repository name for url
.
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 |
# File 'lib/cocoapods-core/source/manager.rb', line 426 def name_for_url(url) base_from_host_and_path = lambda do |host, path| if host && !host.empty? domain = PublicSuffix.parse(host) rescue nil base = [domain&.sld || host] base = [] if base == %w(github) else base = [] end path = path.gsub(/.git$/, '').gsub(%r{^/}, '').split('/') path.pop if path.last == 'specs' (base + path).join('-') end valid_url = lambda do |url| url =~ URI.regexp && (URI(url) rescue false) end valid_scp_url = lambda do |url| valid_url['scp://' + url] end url = url.to_s.downcase case url when %r{https://#{Regexp.quote(trunk_repo_hostname)}}i # Main CDN repo base = Pod::TrunkSource::TRUNK_REPO_NAME when valid_url # HTTPS URL or something similar url = valid_url[url] base = base_from_host_and_path[url.host, url.path] when valid_scp_url # SCP-style URLs for private git repos url = valid_scp_url[url] base = base_from_host_and_path[url.host, url.path] when %r{(?:git|ssh|https?|[a-z0-9_-]+@([-\w.]+)):(\/\/)?(.*?)(\.git)?(\/?|\#[-\d\w._]+?)$}i # Additional SCP-style URLs for private git repos host, _, path = Regexp.last_match.captures base = base_from_host_and_path[host, path] else # This is nearly impossible, with all the previous cases raise Informative, "Couldn't determine repo name for URL: #{url}" end name = base (1..).each do |i| break unless source_dir(name).exist? name = "#{base}-#{i}" end name end |
#save_search_index(index) ⇒ Object
Stores given search data in the file system.
288 289 290 291 292 293 294 |
# File 'lib/cocoapods-core/source/manager.rb', line 288 def save_search_index(index) require 'json' @updated_search_index = index search_index_path.open('w') do |io| io.write(@updated_search_index.to_json) end end |
#search(dependency) ⇒ Set?
Search the appropriate sources to match the set for the given dependency.
102 103 104 |
# File 'lib/cocoapods-core/source/manager.rb', line 102 def search(dependency) aggregate_for_dependency(dependency).search(dependency) end |
#search_by_name(query, full_text_search = false) ⇒ Array<Set>
Search all the sources with the given search term.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/cocoapods-core/source/manager.rb', line 120 def search_by_name(query, full_text_search = false) query_word_regexps = query.split.map { |word| /#{word}/i } if full_text_search query_word_results_hash = {} updated_search_index.each_value do |word_spec_hash| word_spec_hash.each_pair do |word, spec_names| query_word_regexps.each do |query_word_regexp| set = (query_word_results_hash[query_word_regexp] ||= Set.new) set.merge(spec_names) if word =~ query_word_regexp end end end found_set_names = query_word_results_hash.values.reduce(:&) found_set_names ||= [] sets_from_non_indexable = all_non_indexable.map { |s| s.search_by_name(query, true) }.flatten found_set_names += sets_from_non_indexable.map(&:name).flatten.uniq sets = found_set_names.map do |name| aggregate.representative_set(name) end # Remove nil values because representative_set return nil if no pod is found in any of the sources. sets.compact! else sets = aggregate.search_by_name(query, false) end if sets.empty? extra = ', author, summary, or description' if full_text_search raise Informative, "Unable to find a pod with name#{extra} " \ "matching `#{query}`" end sorted_sets(sets, query_word_regexps) end |
#sorted_sets(sets, query_word_regexps) ⇒ Array<Set>
Returns given set array by sorting it in-place.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/cocoapods-core/source/manager.rb', line 166 def sorted_sets(sets, query_word_regexps) sets.sort_by! do |set| pre_match_length = nil found_query_index = nil found_query_count = 0 query_word_regexps.each_with_index do |q, idx| if (m = set.name.match(/#{q}/i)) pre_match_length ||= m.pre_match.length found_query_index ||= idx found_query_count += 1 end end pre_match_length ||= 1000 found_query_index ||= 1000 [-found_query_count, pre_match_length, found_query_index, set.name.downcase] end sets end |
#source_dir(name) ⇒ Pathname (private)
Returns The path of the source with the given name.
381 382 383 |
# File 'lib/cocoapods-core/source/manager.rb', line 381 def source_dir(name) repos_dir + name end |
#source_from_path(path) ⇒ Source (private)
Returns The Source at a given path.
311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/cocoapods-core/source/manager.rb', line 311 def source_from_path(path) @sources_by_path ||= Hash.new do |hash, key| hash[key] = case when key.basename.to_s == Pod::TrunkSource::TRUNK_REPO_NAME TrunkSource.new(key) when (key + '.url').exist? CDNSource.new(key) else Source.new(key) end end @sources_by_path[path] end |
#source_repos ⇒ Array<Pathname>
Returns The source repo directories.
17 18 19 20 |
# File 'lib/cocoapods-core/source/manager.rb', line 17 def source_repos return [] unless repos_dir.exist? repos_dir.children.select(&:directory?).sort_by { |d| d.basename.to_s.downcase } end |
#source_with_name(name) ⇒ Source (private)
Returns The source with the given name.
341 342 343 344 345 |
# File 'lib/cocoapods-core/source/manager.rb', line 341 def source_with_name(name) source = sources([name]).first return nil unless source.repo.exist? source end |
#source_with_url(url) ⇒ Source (private)
Returns The source whose Pod::Source#url is equal to url
.
390 391 392 393 394 395 396 |
# File 'lib/cocoapods-core/source/manager.rb', line 390 def source_with_url(url) url = canonic_url(url) url = 'https://github.com/cocoapods/specs' if url =~ %r{github.com[:/]+cocoapods/specs} all.find do |source| source.url && canonic_url(source.url) == url end end |
#sources(names) ⇒ Array<Source>
Returns The list of the sources with the given names.
51 52 53 54 |
# File 'lib/cocoapods-core/source/manager.rb', line 51 def sources(names) dirs = names.map { |name| source_dir(name) } dirs.map { |repo| source_from_path(repo) } end |
#stored_search_index ⇒ Object
Returns the search data stored in the file system. If existing data in the file system is not valid, returns nil.
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/cocoapods-core/source/manager.rb', line 264 def stored_search_index @updated_search_index ||= begin if search_index_path.exist? require 'json' begin index = JSON.parse(search_index_path.read) unless index # JSON.parse("null") => nil search_index_path.delete return nil end index if index.is_a?(Hash) # TODO: should we also check if hash has correct hierarchy? rescue JSON::ParserError search_index_path.delete nil end end end end |
#trunk_repo_hostname ⇒ Object (private)
Returns hostname for for trunk
URL.
483 484 485 |
# File 'lib/cocoapods-core/source/manager.rb', line 483 def trunk_repo_hostname URI.parse(TrunkSource::TRUNK_REPO_URL).host.downcase.freeze end |
#update_search_index_if_needed(changed_spec_paths) ⇒ Object
Updates the stored search index if there are changes in spec repos while updating them. Update is performed incrementally. Only the changed pods' search data is re-generated and updated.
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/cocoapods-core/source/manager.rb', line 217 def update_search_index_if_needed(changed_spec_paths) search_index = stored_search_index return unless search_index changed_spec_paths.each_pair do |source, spec_paths| next unless source.indexable? index_for_source = search_index[source.name] next unless index_for_source && !spec_paths.empty? updated_pods = source.pods_for_specification_paths(spec_paths) new_index = aggregate.generate_search_index_for_changes_in_source(source, spec_paths) # First traverse search_index and update existing words # Remove traversed words from new_index after adding to search_index, # so that only non existing words will remain in new_index after enumeration completes. index_for_source.each_pair do |word, _| if new_index[word] index_for_source[word] |= new_index[word] new_index.delete(word) else index_for_source[word] -= updated_pods end end # Now add non existing words remained in new_index to search_index index_for_source.merge!(new_index) end save_search_index(search_index) end |
#update_search_index_if_needed_in_background(changed_spec_paths) ⇒ Object
Updates search index for changed pods in background
249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/cocoapods-core/source/manager.rb', line 249 def update_search_index_if_needed_in_background(changed_spec_paths) if Gem.win_platform? update_search_index_if_needed(changed_spec_paths) return end Process.fork do Process.daemon update_search_index_if_needed(changed_spec_paths) exit end end |
#updateable_source_named(name) ⇒ Source (private)
Returns The updateable source with the given name. If no updateable source with given name is found it raises.
353 354 355 356 357 358 359 360 361 362 |
# File 'lib/cocoapods-core/source/manager.rb', line 353 def updateable_source_named(name) specified_source = source_with_name(name) unless specified_source raise Informative, "Unable to find the `#{name}` repo." end unless specified_source.updateable? raise Informative, "The `#{name}` repo is not a updateable repo." end specified_source end |
#updateable_sources ⇒ Source (private)
Returns The list of the updateable sources.
366 367 368 |
# File 'lib/cocoapods-core/source/manager.rb', line 366 def updateable_sources all.select(&:updateable?) end |