Class: Pod::Source

Inherits:
Object
  • Object
show all
Defined in:
lib/cocoapods-core/source.rb,
lib/cocoapods-core/source/acceptor.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"

Defined Under Namespace

Classes: Acceptor, Aggregate, HealthReporter

Instance Attribute Summary collapse

Queering the source collapse

Searching the source collapse

Representations collapse

Private Helpers collapse

Instance Method Summary collapse

Constructor Details

#initialize(repo) ⇒ Source


23
24
25
# File 'lib/cocoapods-core/source.rb', line 23

def initialize(repo)
  @repo = Pathname.new(repo)
end

Instance Attribute Details

#repoPathname (readonly)


19
20
21
# File 'lib/cocoapods-core/source.rb', line 19

def repo
  @repo
end

Instance Method Details

#<=>(other) ⇒ Integer

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.

Returns compares a source with another one for sorting purposes.


67
68
69
# File 'lib/cocoapods-core/source.rb', line 67

def <=>(other)
  name <=> other.name
end

#all_specsArray<Specification>


155
156
157
158
159
160
161
162
163
164
165
# File 'lib/cocoapods-core/source.rb', line 155

def all_specs
  specs = pods.map do |name|
    begin
      versions(name).map { |version| specification(name, version) }
    rescue
      CoreUI.warn "Skipping `#{name}` because the podspec contains errors."
      next
    end
  end
  specs.flatten.compact
end

#fuzzy_search(query) ⇒ Set, Nil

Returns the set of the Pod whose name fuzzily matches the given query.


254
255
256
257
258
259
260
# File 'lib/cocoapods-core/source.rb', line 254

def fuzzy_search(query)
  require 'fuzzy_match'
  pod_name = FuzzyMatch.new(pods).find(query)
  if pod_name
    search(pod_name)
  end
end

#inspectString


73
74
75
# File 'lib/cocoapods-core/source.rb', line 73

def inspect
  "#<#{self.class} name:#{name} type:#{type}>"
end

#load_spec_gracefully(name) ⇒ Specification, Nil (private)

Loads the specification for the given Pod gracefully.


301
302
303
304
305
306
307
308
309
# File 'lib/cocoapods-core/source.rb', line 301

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

#nameString Also known as: to_s


29
30
31
# File 'lib/cocoapods-core/source.rb', line 29

def name
  repo.basename.to_s
end

#pod_setsArray<Sets>


180
181
182
# File 'lib/cocoapods-core/source.rb', line 180

def pod_sets
  pods.map { |pod_name| set(pod_name) }
end

#podsArray<String>


85
86
87
88
89
90
91
92
93
94
# File 'lib/cocoapods-core/source.rb', line 85

def pods
  unless specs_dir
    raise Informative, "Unable to find a source named: `#{name}`"
  end
  specs_dir_as_string = specs_dir.to_s
  Dir.entries(specs_dir).select do |entry|
    valid_name = entry[0, 1] != '.'
    valid_name && File.directory?(File.join(specs_dir_as_string, entry))
  end.sort
end

#search(query) ⇒ Set

TODO:

Rename to #load_set

Note:

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.


197
198
199
200
201
202
203
204
205
206
207
# File 'lib/cocoapods-core/source.rb', line 197

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 specs_dir.children.select(&:directory?).map(&:basename).map(&:to_s).include?(query.to_s)
    set(query)
  end
end

#search_by_name(query, full_text_search = false) ⇒ Array<Set>

TODO:

Rename to #search

Note:

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.


223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/cocoapods-core/source.rb', line 223

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) ⇒ Sets

Returns the set for the Pod with the given name.


174
175
176
# File 'lib/cocoapods-core/source.rb', line 174

def set(pod_name)
  Specification::Set.new(pod_name, self)
end

#specification(name, version) ⇒ Specification


123
124
125
# File 'lib/cocoapods-core/source.rb', line 123

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.

Raises:

  • (ArgumentError)

137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/cocoapods-core/source.rb', line 137

def specification_path(name, version)
  raise ArgumentError, 'No name' unless name
  raise ArgumentError, 'No version' unless version
  path = specs_dir + 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_dirPathname (private)

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 the are stored in a dedicated folder.

Returns The directory where the specs are stored.


318
319
320
321
322
323
324
325
326
327
# File 'lib/cocoapods-core/source.rb', line 318

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_hashHash{String=>{String=>Specification}}


271
272
273
274
275
276
277
278
# File 'lib/cocoapods-core/source.rb', line 271

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_yamlString


282
283
284
285
# File 'lib/cocoapods-core/source.rb', line 282

def to_yaml
  require 'yaml'
  to_hash.to_yaml
end

#typeString


54
55
56
# File 'lib/cocoapods-core/source.rb', line 54

def type
  'file system'
end

#urlString

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.

Returns The URL of the source.


40
41
42
43
44
45
46
47
48
49
50
# File 'lib/cocoapods-core/source.rb', line 40

def url
  Dir.chdir(repo) do
    remote = `git config --get remote.origin.url`.chomp

    if $?.success?
      remote
    elsif (repo + '.git').exist?
      "file://#{repo}/.git"
    end
  end
end

#versions(name) ⇒ Array<Version>

Returns all the available versions for the Pod, sorted from highest to lowest.

Raises:

  • (ArgumentError)

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/cocoapods-core/source.rb', line 102

def versions(name)
  return nil unless specs_dir
  raise ArgumentError, 'No name' unless name
  pod_dir = specs_dir + name
  return unless pod_dir.exist?
  pod_dir.children.map do |v|
    basename = v.basename.to_s
    begin
      Version.new(basename) if v.directory? && basename[0, 1] != '.'
    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