Class: Pod::Source
- Inherits:
-
Object
- Object
- Pod::Source
- Defined in:
- lib/cocoapods-core/source.rb,
lib/cocoapods-core/source/manager.rb,
lib/cocoapods-core/source/acceptor.rb,
lib/cocoapods-core/source/metadata.rb,
lib/cocoapods-core/source/aggregate.rb,
lib/cocoapods-core/source/health_reporter.rb
Overview
The Source class is responsible to manage a collection of podspecs.
The backing store of the podspecs collection is an implementation detail abstracted from the rest of CocoaPods.
The default implementation uses a git repo as a backing store, where the podspecs are namespaced as:
"#{SPEC_NAME}/#{VERSION}/#{SPEC_NAME}.podspec"
Direct Known Subclasses
Defined Under Namespace
Classes: Acceptor, Aggregate, HealthReporter, Manager, Metadata
Constant Summary collapse
- DEFAULT_SPECS_BRANCH =
The default branch in which the specs are stored
'master'.freeze
Paths collapse
-
#repo ⇒ Pathname
readonly
The path where the source is stored.
Instance Attribute Summary collapse
-
#metadata ⇒ Pod::Source::Metadata
readonly
The metadata for this source.
Paths collapse
-
#metadata_path ⇒ Pathname
The path at which source metadata is stored.
-
#pod_path(name) ⇒ Pathname
The path at which the specs for the given pod are stored.
-
#specs_dir ⇒ Pathname
The directory where the specs are stored.
Querying the source collapse
-
#all_specs ⇒ Array<Specification>
All the specifications contained by the source.
-
#pod_sets ⇒ Array<Sets>
The sets of all the Pods.
-
#pods ⇒ Array<String>
The list of the name of all the Pods.
-
#pods_for_specification_paths(spec_paths) ⇒ Array<String>
Returns pod names for given array of specification paths.
-
#set(pod_name) ⇒ Sets
Returns the set for the Pod with the given name.
-
#specification(name, version) ⇒ Specification
The specification for a given version of Pod.
-
#specification_path(name, version) ⇒ Pathname
Returns the path of the specification with the given name and version.
-
#versions(name) ⇒ Array<Version>
All the available versions for the Pod, sorted from highest to lowest.
Searching the source collapse
-
#fuzzy_search(query) ⇒ Set, Nil
Returns the set of the Pod whose name fuzzily matches the given query.
-
#search(query) ⇒ Set
A set for a given dependency.
-
#search_by_name(query, full_text_search = false) ⇒ Array<Set>
The list of the sets that contain the search term.
Updating the source collapse
- #git? ⇒ Boolean
- #indexable? ⇒ Boolean
-
#update(show_output) ⇒ Array<String>
Updates the local clone of the source repo.
- #updateable? ⇒ Boolean
- #verify_compatibility! ⇒ Object
Representations collapse
-
#to_hash ⇒ Hash{String=>{String=>Specification}}
The static representation of all the specifications grouped first by name and then by version.
-
#to_yaml ⇒ String
The YAML encoded #to_hash representation.
Private Helpers collapse
- #diff_until_commit_hash(commit_hash) ⇒ Object private
- #git_commit_hash ⇒ Object private
- #git_tracking_branch ⇒ Object private
-
#load_spec_gracefully(name) ⇒ Specification, Nil
private
Loads the specification for the given Pod gracefully.
- #refresh_metadata ⇒ Object private
- #repo_git(args, include_error: false) ⇒ Object private
- #unchanged_github_repo? ⇒ Boolean private
- #update_git_repo(show_output = false) ⇒ Object private
Instance Method Summary collapse
-
#<=>(other) ⇒ Integer
Compares a source with another one for sorting purposes.
-
#initialize(repo) ⇒ Source
constructor
A new instance of Source.
-
#inspect ⇒ String
A description suitable for debugging.
-
#name ⇒ String
(also: #to_s)
The name of the source.
-
#type ⇒ String
The type of the source.
-
#url ⇒ String
The URL of the source.
Constructor Details
#initialize(repo) ⇒ Source
Returns a new instance of Source.
28 29 30 31 32 |
# File 'lib/cocoapods-core/source.rb', line 28 def initialize(repo) @repo = Pathname(repo). @versions_by_name = {} end |
Instance Attribute Details
#metadata ⇒ Pod::Source::Metadata (readonly)
Returns The metadata for this source.
24 25 26 |
# File 'lib/cocoapods-core/source.rb', line 24 def @metadata end |
#repo ⇒ Pathname (readonly)
Returns The path where the source is stored.
88 89 90 |
# File 'lib/cocoapods-core/source.rb', line 88 def repo @repo end |
Instance Method Details
#<=>(other) ⇒ Integer
Source are compared by the alphabetical order of their name, and this convention should be used in any case where sources need to be disambiguated.
Returns compares a source with another one for sorting purposes.
73 74 75 |
# File 'lib/cocoapods-core/source.rb', line 73 def <=>(other) name <=> other.name end |
#all_specs ⇒ Array<Specification>
Returns all the specifications contained by the source.
219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/cocoapods-core/source.rb', line 219 def all_specs glob = specs_dir.join('*/' * .prefix_lengths.size, '*', '*', '*.podspec{.json,}') specs = Pathname.glob(glob).map do |path| begin Specification.from_file(path) rescue CoreUI.warn "Skipping `#{path.relative_path_from(repo)}` because the " \ 'podspec contains errors.' next end end specs.compact end |
#diff_until_commit_hash(commit_hash) ⇒ Object (private)
459 460 461 |
# File 'lib/cocoapods-core/source.rb', line 459 def diff_until_commit_hash(commit_hash) repo_git(%W(diff --name-only #{commit_hash}..HEAD)).split("\n") end |
#fuzzy_search(query) ⇒ Set, Nil
Returns the set of the Pod whose name fuzzily matches the given query.
333 334 335 336 337 338 339 |
# File 'lib/cocoapods-core/source.rb', line 333 def fuzzy_search(query) require 'fuzzy_match' pod_name = FuzzyMatch.new(pods).find(query) if pod_name search(pod_name) end end |
#git? ⇒ Boolean
370 371 372 |
# File 'lib/cocoapods-core/source.rb', line 370 def git? repo.join('.git').exist? && !repo_git(%w(rev-parse HEAD)).empty? end |
#git_commit_hash ⇒ Object (private)
444 445 446 |
# File 'lib/cocoapods-core/source.rb', line 444 def git_commit_hash repo_git(%w(rev-parse HEAD)) end |
#git_tracking_branch ⇒ Object (private)
454 455 456 457 |
# File 'lib/cocoapods-core/source.rb', line 454 def git_tracking_branch path = repo.join('.git', 'cocoapods_branch') path.file? ? path.read.strip : DEFAULT_SPECS_BRANCH end |
#indexable? ⇒ Boolean
374 375 376 |
# File 'lib/cocoapods-core/source.rb', line 374 def indexable? true end |
#inspect ⇒ String
Returns A description suitable for debugging.
79 80 81 |
# File 'lib/cocoapods-core/source.rb', line 79 def inspect "#<#{self.class} name:#{name} type:#{type}>" end |
#load_spec_gracefully(name) ⇒ Specification, Nil (private)
Loads the specification for the given Pod gracefully.
430 431 432 433 434 435 436 437 438 |
# File 'lib/cocoapods-core/source.rb', line 430 def load_spec_gracefully(name) versions = versions(name) version = versions.sort.last if versions specification(name, version) if version rescue Informative Pod::CoreUI.warn "Skipping `#{name}` because the podspec " \ 'contains errors.' nil end |
#metadata_path ⇒ Pathname
Returns The path at which source metadata is stored.
119 120 121 |
# File 'lib/cocoapods-core/source.rb', line 119 def repo + 'CocoaPods-version.yml' end |
#name ⇒ String Also known as: to_s
Returns The name of the source.
36 37 38 |
# File 'lib/cocoapods-core/source.rb', line 36 def name repo.basename.to_s end |
#pod_path(name) ⇒ Pathname
Returns The path at which the specs for the given pod are stored.
113 114 115 |
# File 'lib/cocoapods-core/source.rb', line 113 def pod_path(name) specs_dir.join(*.path_fragment(name)) end |
#pod_sets ⇒ Array<Sets>
Returns the sets of all the Pods.
246 247 248 |
# File 'lib/cocoapods-core/source.rb', line 246 def pod_sets pods.map { |pod_name| set(pod_name) } end |
#pods ⇒ Array<String>
Returns the list of the name of all the Pods.
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/cocoapods-core/source.rb', line 131 def pods unless specs_dir raise Informative, "Unable to find a source named: `#{name}`" end glob = specs_dir.join('*/' * .prefix_lengths.size, '*') Pathname.glob(glob).reduce([]) do |pods, entry| pods << entry.basename.to_s if entry.directory? pods end.sort end |
#pods_for_specification_paths(spec_paths) ⇒ Array<String>
Returns pod names for given array of specification paths.
149 150 151 152 153 154 155 156 |
# File 'lib/cocoapods-core/source.rb', line 149 def pods_for_specification_paths(spec_paths) spec_paths.map do |path| absolute_path = repo + path relative_path = absolute_path.relative_path_from(specs_dir) # The first file name returned by 'each_filename' is the pod name relative_path.each_filename.first end end |
#refresh_metadata ⇒ Object (private)
440 441 442 |
# File 'lib/cocoapods-core/source.rb', line 440 def @metadata = Metadata.from_file() end |
#repo_git(args, include_error: false) ⇒ Object (private)
463 464 465 466 467 |
# File 'lib/cocoapods-core/source.rb', line 463 def repo_git(args, include_error: false) command = "env -u GIT_CONFIG git -C \"#{repo}\" " << args.join(' ') command << ' 2>&1' if include_error (`#{command}` || '').strip end |
#search(query) ⇒ Set
Rename to #load_set
This method is optimized for fast lookups by name, i.e. it does not require iterating through #pod_sets
Returns a set for a given dependency. The set is identified by the name of the dependency and takes into account subspecs.
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/cocoapods-core/source.rb', line 263 def search(query) unless specs_dir raise Informative, "Unable to find a source named: `#{name}`" end if query.is_a?(Dependency) query = query.root_name end if (versions = @versions_by_name[query]) && !versions.empty? set = set(query) return set if set.specification_name == query end found = [] Pathname.glob(pod_path(query)) do |path| next unless Dir.foreach(path).any? { |child| child != '.' && child != '..' } found << path.basename.to_s end if [query] == found set = set(query) set if set.specification_name == query end end |
#search_by_name(query, full_text_search = false) ⇒ Array<Set>
Rename to #search
full text search requires to load the specification for each pod, hence is considerably slower.
Returns The list of the sets that contain the search term.
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/cocoapods-core/source.rb', line 302 def search_by_name(query, full_text_search = false) regexp_query = /#{query}/i if full_text_search pod_sets.reject do |set| texts = [] begin s = set.specification texts << s.name texts += s..keys texts << s.summary texts << s.description rescue CoreUI.warn "Skipping `#{set.name}` because the podspec " \ 'contains errors.' end texts.grep(regexp_query).empty? end else names = pods.grep(regexp_query) names.map { |pod_name| set(pod_name) } end end |
#set(pod_name) ⇒ Sets
Returns the set for the Pod with the given name.
240 241 242 |
# File 'lib/cocoapods-core/source.rb', line 240 def set(pod_name) Specification::Set.new(pod_name, self) end |
#specification(name, version) ⇒ Specification
Returns the specification for a given version of Pod.
187 188 189 |
# File 'lib/cocoapods-core/source.rb', line 187 def specification(name, version) Specification.from_file(specification_path(name, version)) end |
#specification_path(name, version) ⇒ Pathname
Returns the path of the specification with the given name and version.
201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/cocoapods-core/source.rb', line 201 def specification_path(name, version) raise ArgumentError, 'No name' unless name raise ArgumentError, 'No version' unless version path = pod_path(name) + version.to_s specification_path = path + "#{name}.podspec.json" unless specification_path.exist? specification_path = path + "#{name}.podspec" end unless specification_path.exist? raise StandardError, "Unable to find the specification #{name} " \ "(#{version}) in the #{self.name} source." end specification_path end |
#specs_dir ⇒ Pathname
In previous versions of CocoaPods they used to be stored in the root of the repo. This lead to issues, especially with the GitHub interface and now they are stored in a dedicated folder.
Returns The directory where the specs are stored.
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/cocoapods-core/source.rb', line 97 def specs_dir @specs_dir ||= begin specs_sub_dir = repo + 'Specs' if specs_sub_dir.exist? specs_sub_dir elsif repo.exist? repo end end end |
#to_hash ⇒ Hash{String=>{String=>Specification}}
Returns the static representation of all the specifications grouped first by name and then by version.
400 401 402 403 404 405 406 407 |
# File 'lib/cocoapods-core/source.rb', line 400 def to_hash hash = {} all_specs.each do |spec| hash[spec.name] ||= {} hash[spec.name][spec.version.version] = spec.to_hash end hash end |
#to_yaml ⇒ String
Returns the YAML encoded #to_hash representation.
411 412 413 414 |
# File 'lib/cocoapods-core/source.rb', line 411 def to_yaml require 'yaml' to_hash.to_yaml end |
#type ⇒ String
Returns The type of the source.
60 61 62 |
# File 'lib/cocoapods-core/source.rb', line 60 def type git? ? 'git' : 'file system' end |
#unchanged_github_repo? ⇒ Boolean (private)
469 470 471 472 |
# File 'lib/cocoapods-core/source.rb', line 469 def unchanged_github_repo? return unless url =~ /github.com/ !GitHub.modified_since_commit(url, git_commit_hash) end |
#update(show_output) ⇒ Array<String>
Updates the local clone of the source repo.
351 352 353 354 355 356 357 358 359 360 361 362 363 364 |
# File 'lib/cocoapods-core/source.rb', line 351 def update(show_output) return [] if unchanged_github_repo? prev_commit_hash = git_commit_hash update_git_repo(show_output) @versions_by_name.clear if version = .last_compatible_version(Version.new(CORE_VERSION)) tag = "v#{version}" CoreUI.warn "Using the `#{tag}` tag of the `#{name}` source because " \ "it is the last version compatible with CocoaPods #{CORE_VERSION}." repo_git(['checkout', tag]) end diff_until_commit_hash(prev_commit_hash) end |
#update_git_repo(show_output = false) ⇒ Object (private)
448 449 450 451 452 |
# File 'lib/cocoapods-core/source.rb', line 448 def update_git_repo(show_output = false) repo_git(['checkout', git_tracking_branch]) output = repo_git(%w(pull --ff-only), :include_error => true) CoreUI.puts output if show_output end |
#updateable? ⇒ Boolean
366 367 368 |
# File 'lib/cocoapods-core/source.rb', line 366 def updateable? git? end |
#url ⇒ String
In the past we had used git ls-remote --get-url
, but this could
lead to an issue when finding a source based on its URL when git
is configured to rewrite URLs with the url.<base>.insteadOf
option. See https://github.com/CocoaPods/CocoaPods/issues/2724.
Returns The URL of the source.
47 48 49 50 51 52 53 54 55 56 |
# File 'lib/cocoapods-core/source.rb', line 47 def url @url ||= begin remote = repo_git(%w(config --get remote.origin.url)) if !remote.empty? remote elsif (repo + '.git').exist? "file://#{repo}/.git" end end end |
#verify_compatibility! ⇒ Object
378 379 380 381 382 383 384 385 386 387 388 389 |
# File 'lib/cocoapods-core/source.rb', line 378 def verify_compatibility! return if .compatible?(CORE_VERSION) version_msg = if .minimum_cocoapods_version == .maximum_cocoapods_version .minimum_cocoapods_version else "#{.minimum_cocoapods_version} - #{.maximum_cocoapods_version}" end raise Informative, "The `#{name}` repo requires " \ "CocoaPods #{version_msg} (currently using #{CORE_VERSION})\n" \ 'Update CocoaPods, or checkout the appropriate tag in the repo.' end |
#versions(name) ⇒ Array<Version>
Returns all the available versions for the Pod, sorted from highest to lowest.
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/cocoapods-core/source.rb', line 164 def versions(name) return nil unless specs_dir raise ArgumentError, 'No name' unless name pod_dir = pod_path(name) return unless pod_dir.exist? @versions_by_name[name] ||= pod_dir.children.map do |v| next nil unless v.directory? basename = v.basename.to_s next unless basename[0, 1] != '.' begin Version.new(basename) rescue ArgumentError raise Informative, 'An unexpected version directory ' \ "`#{basename}` was encountered for the " \ "`#{pod_dir}` Pod in the `#{name}` repository." end end.compact.sort.reverse end |