Skip to content

Commit

Permalink
[Source] Add support for data providers
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiopelosin committed Dec 2, 2013
1 parent 415cdf3 commit 582a227
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 222 deletions.
192 changes: 104 additions & 88 deletions lib/cocoapods-core/source.rb
Expand Up @@ -2,6 +2,7 @@
require 'cocoapods-core/source/aggregate'
require 'cocoapods-core/source/health_reporter'
require 'cocoapods-core/source/abstract_data_provider'
require 'cocoapods-core/source/file_system_data_provider'
require 'cocoapods-core/source/github_data_provider'

module Pod
Expand All @@ -18,20 +19,31 @@ module Pod
#
class Source

# @return [Pathname] the location of the repo of the source.
# @return [AbstractDataProvider] the data provider for this source.
#
attr_reader :repo
attr_accessor :data_provider

# @param [Pathname, String] repo @see #repo.
#
def initialize(repo)
@repo = Pathname.new(repo)
def initialize(repo = nil)
# TODO: Temporary solution to aide the transition
if repo.is_a?(String) || repo.is_a?(Pathname)
@data_provider = FileSystemDataProvider.new(repo)
else
@data_provider = repo
end
end

# @return [String] the name of the source.
# @return [String] The name of the source.
#
def name
repo.basename.to_s
data_provider.name
end

# @return [String] The type of the source.
#
def type
data_provider.type
end

alias_method :to_s, :name
Expand All @@ -47,37 +59,27 @@ def <=>(other)
name <=> other.name
end

#-------------------------------------------------------------------------#
# @return [String] A description suitable for debugging.
#
def inspect
"#<#{self.class} name:#{name} type:#{type}>"
end

public

# @!group Queering the source
#-------------------------------------------------------------------------#

# @return [Array<String>] the list of the name of all the Pods.
#
# @note Using Pathname#children is sensibly slower.
#
def pods
specs_dir_as_string = specs_dir.to_s
Dir.entries(specs_dir).select do |entry|
valid_name = !(entry == '.' || entry == '..' || entry == '.git')
valid_name && File.directory?(File.join(specs_dir_as_string, entry))
pods = data_provider.pods
unless pods
raise Informative, "Unable to find the #{data_provider.type} source " \
"named: `#{data_provider.name}`"
end
end

# Returns the set for the Pod with the given name.
#
# @param [String] pod_name
# The name of the Pod.
#
# @return [Sets] the set.
#
def set(pod_name)
Specification::Set.new(pod_name, self)
end

# @return [Array<Sets>] the sets of all the Pods.
#
def pod_sets
pods.map { |pod_name| set(pod_name) }
pods
end

# @return [Array<Version>] all the available versions for the Pod, sorted
Expand All @@ -87,43 +89,21 @@ def pod_sets
# the name of the Pod.
#
def versions(name)
pod_dir = specs_dir + name
return unless pod_dir.exist?
pod_dir.children.map do |v|
basename = v.basename.to_s
Version.new(basename) if v.directory? && basename[0, 1] != '.'
end.compact.sort.reverse
versions = data_provider.versions(name)
versions.map { |version| Version.new(version) } if versions
end

# @return [Specification] the specification for a given version of Pod.
#
# @param @see specification_path
#
def specification(name, version)
Specification.from_file(specification_path(name, version))
end

# 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.
#
def specification_path(name, version)
path = specs_dir + name + version.to_s
specification_path = path + "#{name}.podspec.yaml"
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 #{name} source."
spec = data_provider.specification(name, version.to_s)
unless spec
raise Informative, "Unable to find the specification for #{name} " \
"#{version} in the `#{data_provider.name}` source."
end
specification_path
spec
end

# @return [Array<Specification>] all the specifications contained by the
Expand All @@ -141,9 +121,43 @@ def all_specs
specs.flatten.compact
end

#-------------------------------------------------------------------------#
# Returns the set for the Pod with the given name.
#
# @param [String] pod_name
# The name of the Pod.
#
# @return [Sets] the set.
#
def set(pod_name)
Specification::Set.new(pod_name, self)
end

# @return [Array<Sets>] the sets of all the Pods.
#
def pod_sets
pods.map { |pod_name| set(pod_name) }
end

# 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.
#
# @todo Remove.
#
def specification_path(name, version)
data_provider.specification_path(name, version)
end

public

# @!group Searching the source
#-------------------------------------------------------------------------#

# @return [Set] a set for a given dependency. The set is identified by the
# name of the dependency and takes into account subspecs.
Expand Down Expand Up @@ -173,18 +187,22 @@ def search(query)
# @note full text search requires to load the specification for each pod,
# hence is considerably slower.
#
# @todo Rename to #search
#
def search_by_name(query, full_text_search = false)
if full_text_search
pod_sets.map do |set|
begin
s = set.specification
text = "#{s.name} #{s.authors} #{s.summary} #{s.description}"
rescue
CoreUI.warn "Skipping `#{set.name}` because the podspec " \
"contains errors."
if data_provider.is_a?(FileSystemDataProvider)
names = pods.select do |pod|
if spec = load_spec_gracefully(pod)
text = "#{spec.name} #{spec.authors}"
text << " #{spec.summary} #{spec.description}"
text.downcase.include?(query.downcase)
end
end
set if text && text.downcase.include?(query.downcase)
end.compact
else
[]
end
names.map { |pod_name| set(pod_name) }
else
names = pods.select { |name| name.downcase.include?(query.downcase) }
names.map { |pod_name| set(pod_name) }
Expand All @@ -207,9 +225,10 @@ def fuzzy_search(query)
end
end

#-------------------------------------------------------------------------#
public

# @!group Representations
#-------------------------------------------------------------------------#

# @return [Hash{String=>{String=>Specification}}] the static representation
# of all the specifications grouped first by name and then by
Expand All @@ -233,29 +252,26 @@ def to_yaml

private

#-------------------------------------------------------------------------#

# @group Private Helpers
#-------------------------------------------------------------------------#

# @return [Pathname] The directory where the specs are stored.
# Loads the specification for the given Pod gracefully.
#
# @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.
# @param [String] name
# the name of the Pod.
#
def specs_dir
unless @specs_dir
specs_sub_dir = repo + 'Specs'
if specs_sub_dir.exist?
@specs_dir = specs_sub_dir
elsif repo.exist?
@specs_dir = repo
else
raise Informative, "Unable to find a source named: `#{name}`"
end
end
@specs_dir
# @return [Specification] The specification for the last version of the
# Pod.
# @return [Nil] If the spec could not be loaded.
#
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

#-------------------------------------------------------------------------#
Expand Down
2 changes: 1 addition & 1 deletion lib/cocoapods-core/source/health_reporter.rb
Expand Up @@ -124,7 +124,7 @@ def check_spec_path(name, version, spec)
# @return [void]
#
def check_stray_specs
all_paths = Pathname.glob(source.repo + '**/*.podspec{,.yaml}')
all_paths = Pathname.glob(source.data_provider.repo + '**/*.podspec{,.yaml}')
stray_specs = all_paths - report.analyzed_paths
stray_specs.each do |path|
report.add_message(:error, "Stray spec", path)
Expand Down
2 changes: 1 addition & 1 deletion lib/cocoapods-core/specification/set/statistics.rb
Expand Up @@ -220,7 +220,7 @@ def save_cache
def compute_creation_date(set)
date = get_value(set, :creation_date)
unless date
Dir.chdir(set.sources.first.repo) do
Dir.chdir(set.sources.first.data_provider.repo) do
git_log = `git log --first-parent --format=%ct "#{set.name}"`
creation_date = git_log.split("\n").last.to_i
date = Time.at(creation_date)
Expand Down

0 comments on commit 582a227

Please sign in to comment.