class Pod::Source

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"

Constants

DEFAULT_SPECS_BRANCH

The default branch in which the specs are stored

Attributes

metadata[R]

@return [Pod::Source::Metadata] The metadata for this source.

repo[R]

@return [Pathname] The path where the source is stored.

Public Class Methods

new(repo) click to toggle source

@param [Pathname, String] repo @see repo.

# File lib/cocoapods-core/source.rb, line 28
def initialize(repo)
  @repo = Pathname(repo).expand_path
  @versions_by_name = {}
  refresh_metadata
end

Public Instance Methods

<=>(other) click to toggle source

@return [Integer] compares a source with another one for sorting

purposes.

@note 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.
# File lib/cocoapods-core/source.rb, line 73
def <=>(other)
  name <=> other.name
end
all_specs() click to toggle source

@return [Array<Specification>] all the specifications contained by the

source.
# File lib/cocoapods-core/source.rb, line 219
def all_specs
  glob = specs_dir.join('*/' * metadata.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
git?() click to toggle source
# File lib/cocoapods-core/source.rb, line 370
def git?
  repo.join('.git').exist? && !repo_git(%w(rev-parse HEAD)).empty?
end
indexable?() click to toggle source
# File lib/cocoapods-core/source.rb, line 374
def indexable?
  true
end
inspect() click to toggle source

@return [String] A description suitable for debugging.

# File lib/cocoapods-core/source.rb, line 79
def inspect
  "#<#{self.class} name:#{name} type:#{type}>"
end
metadata_path() click to toggle source

@return [Pathname] The path at which source metadata is stored.

# File lib/cocoapods-core/source.rb, line 119
def metadata_path
  repo + 'CocoaPods-version.yml'
end
name() click to toggle source

@return [String] The name of the source.

# File lib/cocoapods-core/source.rb, line 36
def name
  repo.basename.to_s
end
Also aliased as: to_s
pod_path(name) click to toggle source

@param [String] name The name of the pod.

@return [Pathname] The path at which the specs for the given pod are

stored.
# File lib/cocoapods-core/source.rb, line 113
def pod_path(name)
  specs_dir.join(*metadata.path_fragment(name))
end
pod_sets() click to toggle source

@return [Array<Sets>] the sets of all the Pods.

# File lib/cocoapods-core/source.rb, line 246
def pod_sets
  pods.map { |pod_name| set(pod_name) }
end
pods() click to toggle source

@return [Array<String>] the list of the name of all the Pods.

# 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('*/' * metadata.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) click to toggle source

Returns pod names for given array of specification paths.

@param [Array<String>] spec_paths

Array of file path names for specifications. Path strings should be relative to the source path.

@return [Array<String>] the list of the name of Pods corresponding to specification paths.

# 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
search_by_name(query, full_text_search = false) click to toggle source

@return [Array<Set>] The list of the sets that contain the search term.

@param [String] query

the search term. Can be a regular expression.

@param [Bool] full_text_search

whether the search should be limited to the name of the Pod or
should include also the author, the summary, and the description.

@note full text search requires to load the specification for each pod,

hence is considerably slower.

@todo Rename to search

# 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.authors.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) click to toggle source

Returns the set for the Pod with the given name.

@param [String] pod_name

The name of the Pod.

@return [Sets] the set.

# File lib/cocoapods-core/source.rb, line 240
def set(pod_name)
  Specification::Set.new(pod_name, self)
end
specification(name, version) click to toggle source

@return [Specification] the specification for a given version of Pod.

@param @see specification_path

# File lib/cocoapods-core/source.rb, line 187
def specification(name, version)
  Specification.from_file(specification_path(name, version))
end
specification_path(name, version) click to toggle source

Returns the path of the specification with the given name and version.

@param [String] name

the name of the Pod.

@param [Version,String] version

the version for the specification.

@return [Pathname] The path of the specification.

# 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() click to toggle source

@return [Pathname] The directory where the specs are stored.

@note 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.
# 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() click to toggle source

@return [Hash{String=>{String=>Specification}}] the static representation

of all the specifications grouped first by name and then by
version.
# 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_s()
Alias for: name
to_yaml() click to toggle source

@return [String] the YAML encoded {to_hash} representation.

# File lib/cocoapods-core/source.rb, line 411
def to_yaml
  require 'yaml'
  to_hash.to_yaml
end
type() click to toggle source

@return [String] The type of the source.

# File lib/cocoapods-core/source.rb, line 60
def type
  git? ? 'git' : 'file system'
end
update(show_output) click to toggle source

Updates the local clone of the source repo.

@param [Bool] show_output

@return [Array<String>] changed_spec_paths

Returns the list of changed spec paths.
# 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
  refresh_metadata
  if version = metadata.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
updateable?() click to toggle source
# File lib/cocoapods-core/source.rb, line 366
def updateable?
  git?
end
url() click to toggle source

@return [String] The URL of the source.

@note 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.
# 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!() click to toggle source
# File lib/cocoapods-core/source.rb, line 378
def verify_compatibility!
  return if metadata.compatible?(CORE_VERSION)

  version_msg = if metadata.minimum_cocoapods_version == metadata.maximum_cocoapods_version
                  metadata.minimum_cocoapods_version
                else
                  "#{metadata.minimum_cocoapods_version} - #{metadata.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) click to toggle source

@return [Array<Version>] all the available versions for the Pod, sorted

from highest to lowest.

@param [String] name

the name of the Pod.
# 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

Private Instance Methods

diff_until_commit_hash(commit_hash) click to toggle source
# 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
git_commit_hash() click to toggle source
# File lib/cocoapods-core/source.rb, line 444
def git_commit_hash
  repo_git(%w(rev-parse HEAD))
end
git_tracking_branch() click to toggle source
# 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
load_spec_gracefully(name) click to toggle source

Loads the specification for the given Pod gracefully.

@param [String] name

the name of the Pod.

@return [Specification] The specification for the last version of the

Pod.

@return [Nil] If the spec could not be loaded.

# 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
refresh_metadata() click to toggle source
# File lib/cocoapods-core/source.rb, line 440
def refresh_metadata
  @metadata = Metadata.from_file(metadata_path)
end
repo_git(args, include_error: false) click to toggle source
# 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
unchanged_github_repo?() click to toggle source
# 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_git_repo(show_output = false) click to toggle source
# 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