Commit f8065208 authored by Fabio Pelosin's avatar Fabio Pelosin

[SourcesManager] Add support for the search index

parent 2714e56d
## 0.17.0.rc4
## 0.17
### 0.17.0.rc6
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.17.0.rc5...0.17.0.rc6)
[cocoapods-core](https://github.com/CocoaPods/Core/compare/0.17.0.rc5...0.17.0.rc6)
###### Bug fixes
###### Ancillary enhancements
- CocoaPods now maintains a search index which is updated incrementally instead
of analyzing all the specs every time. The search index can be updated
manually with the `pod ipc update-search-index` command.
- Enhancements to the `pod repo lint` command.
- CocoaPods will not create anymore the pre commit hook in the master repo
during setup. If already created it is possible remove it deleting the
`~/.cocoapods/master/.git/hooks/pre-commit` path.
- Improved support for linting and validating specs repo.
### 0.17.0.rc5
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.17.0.rc4...0.17.0.rc5)
[cocoapods-core](https://github.com/CocoaPods/Core/compare/0.17.0.rc4...0.17.0.rc5)
###### Bug fixes
- The `--no-clean` argument is not ignored anymore by the installer.
- Proper handling of file patterns ending with a slash.
- More user errors are raised as an informative.
### 0.17.0.rc4
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.17.0.rc3...0.17.0.rc4)
###### Bug fixes
......@@ -23,7 +52,7 @@
- The `podspec` option of the `pod` directive of the Podfile DSL now accepts
folders.
## 0.17.0.rc3
### 0.17.0.rc3
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.17.0.rc2...0.17.0.rc3
[Xcodeproj](https://github.com/CocoaPods/Xcodeproj/compare/0.5.0...0.5.1))
......@@ -46,7 +75,7 @@
- General improvements to `pod ipc`.
- Added `pod ipc repl` subcommand.
## 0.17.0.rc2
### 0.17.0.rc2
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.17.0.rc1...0.17.0.rc2)
[cocoapods-core](https://github.com/CocoaPods/Core/compare/0.17.0.rc1...0.17.0.rc2)
......@@ -61,7 +90,7 @@
attribute.
[#823](https://github.com/CocoaPods/CocoaPods/issues/823)
## 0.17.0.rc1
### 0.17.0.rc1
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.16.4...0.17.0.rc1)
[Xcodeproj](https://github.com/CocoaPods/Xcodeproj/compare/0.4.3...0.5.0)
[cocoapods-core](https://github.com/CocoaPods/Core)
......
......@@ -100,6 +100,30 @@ module Pod
#-----------------------------------------------------------------------#
class UpdateSearchIndex < IPC
self.summary = 'Updates the search index.'
self.description = <<-DESC
Updates the search index and prints its path to standard output.
The search index is a YAML encoded dictionary where the keys
are the names of the Pods and the values are a dictionary containing
the following information:
- version
- summary
- description
- authors
DESC
def run
SourcesManager.updated_search_index
output_pipe.puts(SourcesManager.search_index_path)
end
end
#-----------------------------------------------------------------------#
class Repl < IPC
END_OF_OUTPUT_SIGNAL = "\n\r"
......
......@@ -63,17 +63,58 @@ module Pod
# @return [Array<Set>] The sets that contain the search term.
#
def search_by_name(query, full_text_search = false)
result = aggregate.search_by_name(query, full_text_search)
if result.empty?
set_names = []
updated_search_index.each do |name, set_data|
text = name.dup
if full_text_search
text << set_data['authors'].to_s if set_data['authors']
text << set_data['summary'] if set_data['summary']
text << set_data['description'] if set_data['description']
end
set_names << name if text.downcase.include?(query.downcase)
end
sets = set_names.map { |name| aggregate.represenative_set(name) }
if sets.empty?
extra = ", author, summary, or description" if full_text_search
raise Informative "Unable to find a pod with name#{extra} matching `#{query}`"
raise Informative, "Unable to find a pod with name#{extra} matching `#{query}`"
end
result
sets
end
#-----------------------------------------------------------------------#
# Creates or updates the search data and returns it. The search data
# groups by name the following information for each set:
#
# - version
# - summary
# - description
# - authors
#
# @return [Hash{String => String}] The up to date search data.
#
def updated_search_index
if search_index_path.exist?
stored_index = YAML.load(search_index_path.read)
search_index = aggregate.update_search_index(stored_index)
else
search_index = aggregate.generate_search_index
end
File.open(search_index_path, 'w') {|f| f.write(search_index.to_yaml) }
search_index
end
# @return [Pathname] The path where the search index should be stored.
#
def search_index_path
caches_path = Pathname.new(File.expand_path(CACHE_ROOT))
caches_path + 'search_index.yaml'
end
public
# @!group Updating Sources
#-----------------------------------------------------------------------#
extend Executable
executable :git
......@@ -87,10 +128,10 @@ module Pod
#
def update(source_name = nil, show_output = false)
if source_name
source = aggregate.all.find { |s| s.name == source_name }
raise Informative, "Unable to find the `#{source_name}` repo." unless source
raise Informative, "The `#{source_name}` repo is not a git repo." unless git_repo?(source.repo)
sources = [source]
specified_source = aggregate.all.find { |s| s.name == source_name }
raise Informative, "Unable to find the `#{source_name}` repo." unless specified_source
raise Informative, "The `#{source_name}` repo is not a git repo." unless git_repo?(specified_source.repo)
sources = [specified_source]
else
sources = aggregate.all.select { |source| git_repo?(source.repo) }
end
......@@ -195,9 +236,10 @@ module Pod
yaml_file.exist? ? YAML.load_file(yaml_file) : {}
end
#-----------------------------------------------------------------------#
public
# @!group Master repo
#-----------------------------------------------------------------------#
# @return [Pathname] The path of the master repo.
#
......@@ -213,6 +255,10 @@ module Pod
def master_repo_functional?
master_repo_dir.exist? && repo_compatible?(master_repo_dir)
end
#-----------------------------------------------------------------------#
end
end
end
......@@ -7,6 +7,7 @@ module Pod
Command::IPC::Spec.any_instance.stubs(:output_pipe).returns(UI)
Command::IPC::Podfile.any_instance.stubs(:output_pipe).returns(UI)
Command::IPC::List.any_instance.stubs(:output_pipe).returns(UI)
Command::IPC::UpdateSearchIndex.any_instance.stubs(:output_pipe).returns(UI)
Command::IPC::Repl.any_instance.stubs(:output_pipe).returns(UI)
end
......@@ -56,6 +57,18 @@ module Pod
#-------------------------------------------------------------------------#
describe Command::IPC::UpdateSearchIndex do
it "updates the search index and prints its path to STDOUT" do
SourcesManager.expects(:updated_search_index)
out = run_command('ipc', 'update-search-index')
out.should.include(SourcesManager.search_index_path.to_s)
end
end
#-------------------------------------------------------------------------#
describe Command::IPC::Repl do
it "prints the version of CocoaPods as its first message" do
......
......@@ -3,31 +3,74 @@ require File.expand_path('../../spec_helper', __FILE__)
module Pod
describe SourcesManager do
before do
@test_source = Source.new(fixture('spec-repos/test_repo'))
SourcesManager.stubs(:search_index_path).returns(temporary_directory + 'search_index.yaml')
end
#-------------------------------------------------------------------------#
describe "In general" do
before do
Source::Aggregate.any_instance.stubs(:all).returns([@test_source])
end
#--------------------------------------#
it "returns all the sources" do
Source::Aggregate.any_instance.unstub(:all)
SourcesManager.all.map(&:name).should == %w[master test_repo]
end
it "returns all the sets" do
SourcesManager.all_sets.map(&:name).should.include?('Chameleon')
SourcesManager.all_sets.map(&:name).should.include?('BananaLib')
end
it "searches for the set of a dependency" do
set = SourcesManager.search(Dependency.new('Chameleon'))
set = SourcesManager.search(Dependency.new('BananaLib'))
set.class.should == Specification::Set
set.name.should == 'Chameleon'
set.name.should == 'BananaLib'
end
it "raises if it not able to find a pod for the given dependency" do
should.raise Informative do
set = SourcesManager.search(Dependency.new('Windows-Lib'))
end.message.should.match /Unable to find.*Windows-Lib/
end
it "searches sets by name" do
sets = SourcesManager.search_by_name('Chameleon')
sets = SourcesManager.search_by_name('BananaLib')
sets.all?{ |s| s.class == Specification::Set}.should.be.true
sets.any?{ |s| s.name == 'Chameleon'}.should.be.true
sets.any?{ |s| s.name == 'BananaLib'}.should.be.true
end
it "can perform a full text search of the sets" do
sets = SourcesManager.search_by_name('Drop in sharing', true)
Source::Aggregate.any_instance.stubs(:all).returns([@test_source])
sets = SourcesManager.search_by_name('Chunky', true)
sets.all?{ |s| s.class == Specification::Set}.should.be.true
sets.any?{ |s| s.name == 'ShareKit'}.should.be.true
sets.any?{ |s| s.name == 'BananaLib'}.should.be.true
end
it "generates the search index before performing a search if it doesn't exits" do
Source::Aggregate.any_instance.stubs(:all).returns([@test_source])
Source::Aggregate.any_instance.expects(:generate_search_index).returns({'BananaLib' => {}})
Source::Aggregate.any_instance.expects(:update_search_index).never
sets = SourcesManager.search_by_name('BananaLib')
end
it "updates the search index before performing a search if it exits" do
FileUtils.touch(SourcesManager.search_index_path)
Source::Aggregate.any_instance.stubs(:all).returns([@test_source])
Source::Aggregate.any_instance.expects(:generate_search_index).never
Source::Aggregate.any_instance.expects(:update_search_index).returns({'BananaLib' => {}})
sets = SourcesManager.search_by_name('BananaLib')
end
it "returns the path of the search index" do
SourcesManager.unstub(:search_index_path)
path = SourcesManager.search_index_path.to_s
path.should.match %r[Library/Caches/CocoaPods/search_index.yaml]
end
end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment