picolena 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. data/History.txt +11 -0
  2. data/Manifest.txt +11 -6
  3. data/config/files_to_clean +12 -0
  4. data/config/hoe.rb +7 -3
  5. data/lib/picolena/{templates/config/initializers/001_prepare_and_load_custom_config.rb → config/basic.rb} +14 -19
  6. data/lib/picolena/config/title_and_names_and_links.yml +26 -0
  7. data/lib/picolena/picolena_generator.rb +8 -3
  8. data/lib/picolena/templates/app/controllers/application.rb +10 -3
  9. data/lib/picolena/templates/app/controllers/documents_controller.rb +26 -7
  10. data/lib/picolena/templates/app/helpers/application_helper.rb +1 -4
  11. data/lib/picolena/templates/app/helpers/documents_helper.rb +29 -7
  12. data/lib/picolena/templates/app/models/document.rb +53 -19
  13. data/lib/picolena/templates/app/models/finder.rb +30 -14
  14. data/lib/picolena/templates/app/views/documents/_document.html.haml +5 -2
  15. data/lib/picolena/templates/app/views/documents/cached.html.haml +8 -0
  16. data/lib/picolena/templates/app/views/documents/{show_content.html.haml → content.html.haml} +1 -1
  17. data/lib/picolena/templates/app/views/documents/show.html.haml +1 -1
  18. data/lib/picolena/templates/config/boot.rb +4 -4
  19. data/lib/picolena/templates/config/initializers/001_load_custom_config.rb +3 -0
  20. data/lib/picolena/templates/config/initializers/{002_indexed_dirs.rb → 002_load_indexed_dirs.rb} +1 -1
  21. data/lib/picolena/templates/config/initializers/003_load_white_list_IPs.rb +8 -0
  22. data/lib/picolena/templates/config/initializers/005_load_custom_title_and_names_and_links.rb +5 -0
  23. data/lib/picolena/templates/config/routes.rb +1 -1
  24. data/lib/picolena/templates/lang/ui/de.yml +2 -4
  25. data/lib/picolena/templates/lang/ui/en.yml +2 -4
  26. data/lib/picolena/templates/lang/ui/es.yml +3 -5
  27. data/lib/picolena/templates/lang/ui/fr.yml +3 -5
  28. data/lib/picolena/templates/lib/core_exts.rb +1 -1
  29. data/lib/picolena/templates/lib/ff.rb +4 -4
  30. data/lib/picolena/templates/spec/controllers/documents_controller_spec.rb +9 -8
  31. data/lib/picolena/templates/spec/models/basic_finder_spec.rb +3 -10
  32. data/lib/picolena/templates/spec/models/document_spec.rb +2 -2
  33. data/lib/picolena/templates/spec/models/finder_spec.rb +30 -9
  34. data/lib/picolena/templates/spec/models/host_indexing_system_spec.rb +12 -6
  35. data/lib/picolena/version.rb +1 -1
  36. data/lib/rubigen_ext.rb +3 -3
  37. data/tasks/hack.rake +17 -0
  38. data/tasks/rspec.rake +6 -20
  39. data/tasks/test.rake +3 -0
  40. data/website/index.html +2 -2
  41. data.tar.gz.sig +0 -0
  42. metadata +24 -10
  43. metadata.gz.sig +0 -0
  44. data/lib/picolena/templates/config/initializers/003_white_list_IPs.rb +0 -8
  45. data/spec/picolena_spec.rb +0 -3
  46. data/tasks/default.rake +0 -1
data/History.txt CHANGED
@@ -1,3 +1,14 @@
1
+ == 0.1.1 2008-04-12
2
+
3
+ * major enhancement:
4
+ * cache à la Google
5
+
6
+ * minor enhancements:
7
+ * easier configuration. Every picolena specific conf files in config/custom
8
+ * lots of refactoring
9
+
10
+ * bug fixes
11
+
1
12
  == 0.1.0 2008-04-08
2
13
 
3
14
  * minor enhancements:
data/Manifest.txt CHANGED
@@ -4,10 +4,13 @@ Manifest.txt
4
4
  README.txt
5
5
  Rakefile
6
6
  bin/picolena
7
+ config/files_to_clean
7
8
  config/hoe.rb
8
9
  config/requirements.rb
9
10
  lib/picolena/USAGE
11
+ lib/picolena/config/basic.rb
10
12
  lib/picolena/config/indexed_directories.yml
13
+ lib/picolena/config/title_and_names_and_links.yml
11
14
  lib/picolena/config/white_list_ip.yml
12
15
  lib/picolena/picolena_generator.rb
13
16
  lib/picolena/templates/MIT-LICENSE
@@ -19,19 +22,21 @@ lib/picolena/templates/app/helpers/documents_helper.rb
19
22
  lib/picolena/templates/app/models/document.rb
20
23
  lib/picolena/templates/app/models/finder.rb
21
24
  lib/picolena/templates/app/views/documents/_document.html.haml
25
+ lib/picolena/templates/app/views/documents/cached.html.haml
26
+ lib/picolena/templates/app/views/documents/content.html.haml
22
27
  lib/picolena/templates/app/views/documents/index.html.haml
23
28
  lib/picolena/templates/app/views/documents/show.html.haml
24
- lib/picolena/templates/app/views/documents/show_content.html.haml
25
29
  lib/picolena/templates/app/views/layouts/application.html.haml
26
30
  lib/picolena/templates/config/boot.rb
27
31
  lib/picolena/templates/config/environment.rb
28
32
  lib/picolena/templates/config/environments/development.rb
29
33
  lib/picolena/templates/config/environments/production.rb
30
34
  lib/picolena/templates/config/environments/test.rb
31
- lib/picolena/templates/config/initializers/001_prepare_and_load_custom_config.rb
32
- lib/picolena/templates/config/initializers/002_indexed_dirs.rb
33
- lib/picolena/templates/config/initializers/003_white_list_IPs.rb
35
+ lib/picolena/templates/config/initializers/001_load_custom_config.rb
36
+ lib/picolena/templates/config/initializers/002_load_indexed_dirs.rb
37
+ lib/picolena/templates/config/initializers/003_load_white_list_IPs.rb
34
38
  lib/picolena/templates/config/initializers/004_load_filters.rb
39
+ lib/picolena/templates/config/initializers/005_load_custom_title_and_names_and_links.rb
35
40
  lib/picolena/templates/config/routes.rb
36
41
  lib/picolena/templates/lang/ui/de.yml
37
42
  lib/picolena/templates/lang/ui/en.yml
@@ -765,13 +770,13 @@ script/destroy
765
770
  script/generate
766
771
  script/txt2html
767
772
  setup.rb
768
- spec/picolena_spec.rb
769
- tasks/default.rake
770
773
  tasks/deployment.rake
771
774
  tasks/environment.rake
775
+ tasks/hack.rake
772
776
  tasks/rdoc.rake
773
777
  tasks/ri.rake
774
778
  tasks/rspec.rake
779
+ tasks/test.rake
775
780
  tasks/website.rake
776
781
  website/index.html
777
782
  website/index.txt
@@ -0,0 +1,12 @@
1
+ lib/picolena/templates/LICENSE
2
+ lib/picolena/templates/README
3
+ lib/picolena/templates/config/custom/picolena.rb
4
+ lib/picolena/templates/config/custom/indexed_directories.yml
5
+ lib/picolena/templates/config/custom/white_list_ip.yml
6
+ lib/picolena/templates/config/custom/title_and_names_and_links.yml
7
+ lib/picolena/templates/log
8
+ lib/picolena/templates/spec/test_dirs/indexed/others/bäñüßé.txt
9
+ lib/picolena/templates/tmp
10
+ lib/picolena/templates/vendor
11
+ lib/picolena/templates/coverage
12
+ lib/picolena/templates/doc
data/config/hoe.rb CHANGED
@@ -54,17 +54,21 @@ hoe = Hoe.new(GEM_NAME, VERS) do |p|
54
54
  p.url = HOMEPATH
55
55
  p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
56
56
  p.test_globs = ["spec/picolena_spec.rb"]
57
- p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
57
+
58
+ files_to_clean = File.readlines(File.join(File.dirname(__FILE__),'files_to_clean')).collect{|line| line.chomp}
59
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']+files_to_clean #An array of file patterns to delete on clean.
58
60
 
59
61
  # == Optional
60
62
  p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
61
63
  p.extra_deps = [ ['rails', '>= 2.0.2'],
62
- #Ferret 0.11.6 is not yet available for win32
64
+ # Ferret 0.11.6 is not yet available for win32
65
+ # FIXME: How to require 0.11.6 for *nix and 0.11.5 for win32?
63
66
  ['ferret', '>= 0.11.5'],
64
67
  ['haml', '>= 1.8.2'],
65
68
  ['rubyzip', '>= 0.9.1'],
66
69
  ['rubigen', '>= 1.2.4'],
67
- ['paginator', '>= 1.1.0']
70
+ ['paginator', '>= 1.1.0'],
71
+ ['rspec', '>= 1.1.3']
68
72
  ]
69
73
 
70
74
  #p.spec_extras = {} # A hash of extra values to set in the gemspec.
@@ -1,16 +1,3 @@
1
- ### You should not modify this file if you'd like to customize your search engine.
2
- ### Please modify config/custom.rb instead.
3
- ### A template config/custom.rb will be created the first time you launch your web server.
4
-
5
-
6
- custom_config_file = File.join(RAILS_ROOT, 'config/custom.rb')
7
-
8
- File.open(custom_config_file,'w'){|custom|
9
- custom.puts <<-DEFAULT_CONF
10
- ### This file has been automatically generated the first time you launched your web server.
11
- ### You should add custom requirements here, they will be loaded everytime you restart the web server.
12
-
13
-
14
1
  # Specify indexes path.
15
2
  # Storage should be sufficient in order to store all indexed data.
16
3
  IndexesSavePath=File.join(RAILS_ROOT, 'tmp/ferret_indexes/')
@@ -27,14 +14,22 @@ Globalite.language = :en
27
14
  # Specify which locale should be used by Ferret
28
15
  Ferret.locale = "en_US.UTF-8"
29
16
 
17
+
30
18
  # Results per page
31
19
  ResultsPerPage = 10
32
20
 
21
+
22
+ # Length of "probably unique id" 's
23
+ # Those id's are used to characterize every document, thus allowing tiny URLs in Controllers
24
+ # HashLength = 10
25
+ # Document.new("whatever.pdf").probably_unique_id => "bbuxhynait"
26
+ # HashLength = 20
27
+ # Document.new("whatever.pdf").probably_unique_id => "jfzjkyfkfkbbuxhynait"
28
+ # The more documents you have, the bigger HashLength should be in order to avoid collisions.
29
+ # It would not be wise (and specs won't pass) to specify HashLength smaller than 10.
30
+ HashLength = 10
31
+
32
+
33
33
  # Specify the default Levenshtein distance when using FuzzyQuery
34
34
  # see http://ferret.davebalmain.com/api/classes/Ferret/QueryParser.html for more information.
35
- Ferret::Search::FuzzyQuery.default_min_similarity=0.6
36
- DEFAULT_CONF
37
- } unless File.readable?(custom_config_file)
38
-
39
- require 'ferret'
40
- require custom_config_file
35
+ Ferret::Search::FuzzyQuery.default_min_similarity=0.6
@@ -0,0 +1,26 @@
1
+ ## Link to a website, located in the bottom-left corner.
2
+
3
+ website_name: Picolena v<%= version %>
4
+ website_url: http://picolena.devjavu.com/
5
+
6
+ ## Link to a backup search engine, if no document was found for a given query.
7
+
8
+ backup_search_engine_name: Google?
9
+ backup_search_engine_url: http://www.google.com/search?q=
10
+ #backup_search_engine_name: Yahoo!
11
+ #backup_search_engine_url: http://search.yahoo.com/search?p=
12
+
13
+
14
+ ## Fields that are not blank will overwrite localization.
15
+ ## Leave them as they are if you're happy with the current localization.
16
+
17
+ # page_title: Picolena Search Engine
18
+ page_title:
19
+ # help: Help
20
+ help:
21
+ # help_file: /help/PicolenaHowTo-en.pdf
22
+ help_file:
23
+ # type_your_query_here: Type your query here
24
+ type_your_query_here:
25
+ # search: Search!
26
+ search:
@@ -2,7 +2,7 @@ require 'tempfile'
2
2
  require 'fileutils'
3
3
  require 'pathname'
4
4
 
5
- class PicolenaGenerator < RubiGen::Base
5
+ class PicolenaGenerator < RubiGen::Base #:nodoc:
6
6
 
7
7
  DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
8
8
  Config::CONFIG['ruby_install_name'])
@@ -58,12 +58,15 @@ class PicolenaGenerator < RubiGen::Base
58
58
  end
59
59
 
60
60
  # Picolena configuration files
61
- m.file '../config/white_list_ip.yml', 'config/white_list_ip.yml'
62
- m.template '../config/indexed_directories.yml', 'config/indexed_directories.yml', :assigns => {:directories_to_index => @directories_to_index}
61
+ m.file '../config/white_list_ip.yml', 'config/custom/white_list_ip.yml'
62
+ m.file '../config/basic.rb', 'config/custom/picolena.rb'
63
+ m.template '../config/indexed_directories.yml', 'config/custom/indexed_directories.yml', :assigns => {:directories_to_index => @directories_to_index}
64
+ m.template '../config/title_and_names_and_links.yml', 'config/custom/title_and_names_and_links.yml', :assigns => {:version => Picolena::VERSION::STRING}
63
65
 
64
66
  # README, License & Rakefile
65
67
  m.file 'MIT-LICENSE', 'LICENSE'
66
68
  m.file '../../../README.txt', 'README'
69
+ m.file '../../../README.txt', 'doc/README_FOR_APP'
67
70
  m.file 'Rakefile', 'Rakefile'
68
71
 
69
72
  unless options[:no_index]
@@ -128,6 +131,8 @@ EOS
128
131
  config
129
132
  config/environments
130
133
  config/initializers
134
+ config/custom
135
+ doc
131
136
  lang/ui
132
137
  lib
133
138
  lib/filters
@@ -1,13 +1,18 @@
1
+ # ApplicationController just checks every incoming request according to the remote IP address.
2
+ #
3
+ # The request is sent to DocumentsController only if the IP is included in the white list.
4
+ # Otherwise, it returns "Access denied" 403.
5
+
1
6
  class ApplicationController < ActionController::Base
2
7
  session :disabled => true
3
8
  before_filter :should_only_be_available_for_white_list_IPs, :except=> :access_denied
4
9
 
5
- # In case of an unknown IP address
10
+ # Returns 403 status in case of an unknown remote IP address
6
11
  def access_denied
7
- render :text=>'Access denied', :status => 403
12
+ render :text=>request.inspect, :status => 403
8
13
  end
9
14
 
10
- # In case route hasn't been recognised
15
+ # Redirects to documents_url in case route hasn't been recognised
11
16
  def unknown_request
12
17
  flash[:warning]="Unknown URL"
13
18
  redirect_to documents_url
@@ -15,6 +20,8 @@ class ApplicationController < ActionController::Base
15
20
 
16
21
  private
17
22
 
23
+ # Tries to match remote IP address with the white list defined in config/custom/white_list_ip.yml
24
+ # Redirects to :access_denied if the remote IP is not white listed.
18
25
  def should_only_be_available_for_white_list_IPs
19
26
  unless request.remote_ip =~ WhiteListIPs
20
27
  redirect_to :controller => 'application', :action=>'access_denied'
@@ -1,5 +1,13 @@
1
+ # Core controller of Picolena search-engine.
2
+ # DocumentsController
3
+ # - treats queries
4
+ # - launches searches
5
+ # - returns matching documents
6
+ # - displays document content
7
+ # - displays cached content.
8
+
1
9
  class DocumentsController < ApplicationController
2
- before_filter :check_if_valid_link, :only=> [:download, :show_content]
10
+ before_filter :check_if_valid_link, :only=> [:download, :content, :cached]
3
11
 
4
12
  # Actually doesn't check anything at all. Just a redirect to show_document(query)
5
13
  #
@@ -16,7 +24,7 @@ class DocumentsController < ApplicationController
16
24
  page=params[:page]||1
17
25
  finder=Finder.new(@query,page)
18
26
  finder.execute!
19
- pager=::Paginator.new(finder.total_hits, ResultsPerPage) do |offset, per_page|
27
+ pager=::Paginator.new(finder.total_hits, ResultsPerPage) do
20
28
  finder.matching_documents
21
29
  end
22
30
  @matching_documents=pager.page(page)
@@ -25,22 +33,33 @@ class DocumentsController < ApplicationController
25
33
  end
26
34
 
27
35
 
28
- # Download the file whose md5 path's checksum is given.
36
+ # Download the file whose probably_unique_id is given.
29
37
  # If the checksum is incorrect, redirect to documents_url via no_valid_link
30
38
  def download
31
- send_file @document.complete_path
39
+ send_file @document.complete_path
32
40
  end
33
41
 
34
- def show_content
42
+ # Returns the content of the document identified by probably_unique_id, as it is *now*.
43
+ def content
44
+ end
45
+
46
+ # Returns the content of the document identified by probably_unique_id, as it was at the time it was indexed.
47
+ # similar to Google cache.
48
+ def cached
35
49
  end
36
50
 
37
51
  private
38
52
 
53
+ # Returns corresponding document for any given "probably unique id"
54
+ # Redirects to no_valid_link if:
55
+ # there are more than one matching document (hash collision)
56
+ # there is no matching document (wrong hash)
39
57
  def check_if_valid_link
40
- @md5_hash=params[:id]
41
- @document=Finder.new("md5:"<<@md5_hash).matching_document rescue no_valid_link
58
+ @probably_unique_id=params[:id]
59
+ @document=Document.find_by_unique_id(@probably_unique_id) rescue no_valid_link
42
60
  end
43
61
 
62
+ # Flashes a warning and redirects to documents_url.
44
63
  def no_valid_link
45
64
  flash[:warning]="no valid link"
46
65
  redirect_to documents_url
@@ -1,6 +1,3 @@
1
1
  # Methods added to this helper will be available to all templates in the application.
2
- module ApplicationHelper
3
- def nothing_found?
4
- @matching_documents.nil? or @matching_documents.entries.empty?
5
- end
2
+ module ApplicationHelper #:nodoc:
6
3
  end
@@ -1,10 +1,19 @@
1
1
  module DocumentsHelper
2
+ # Returns true if no document as been found for a given query.
3
+ def nothing_found?
4
+ @matching_documents.nil? or @matching_documents.entries.empty?
5
+ end
6
+
7
+ # Very basic pagination.
8
+ # Provides liks to Next, Prev and FirstPage when needed.
2
9
  def should_paginate(page,query)
3
10
  [(link_to("&larr;&larr;", :action => :show, :id => query, :page => 1) if page.number>2),
4
11
  (link_to("&larr;", :action => :show, :id => query, :page => page.prev.number) if page.prev?),
5
12
  (link_to("&rarr;", :action => :show, :id => query, :page => page.next.number) if page.next?)].compact.join(" | ")
6
13
  end
7
14
 
15
+ # Returns a localized sentence like "Results 1-10 of 12 for Zimbabwe (0.472s)" or
16
+ # "Résultats 1-2 parmi 2 pour whatever (0.012s)"
8
17
  def describe_results(page, total_hits, dt, query)
9
18
  [:results.l,
10
19
  content_tag(:strong,"#{page.first_item_number}-#{page.last_item_number}"),
@@ -16,20 +25,25 @@ module DocumentsHelper
16
25
  ].join(' ')
17
26
  end
18
27
 
28
+ # Returns the time needed to treat the query and launch the search, with a ms precision : (0.472s)
19
29
  def show_time_needed(dt)
20
30
  content_tag(:small,'('<<number_with_precision(dt,3)<<'s)')
21
31
  end
22
-
32
+
33
+ # When possible, highlights content of the document that match the query.
23
34
  def highlight_matching_content(document)
24
35
  content_tag(:ul,document.matching_content.collect{|sentence|
25
36
  content_tag(:li,h(sentence).gsub(/&lt;&lt;(.*?)&gt;&gt;/,'<strong>\1</strong>').gsub(/\v|\f/,''))
26
37
  }) if document.matching_content
27
38
  end
28
39
 
29
- def icon_and_filename_for(result)
30
- [icon_for(result.extname),result.filename].join("&nbsp;")
40
+ # Returns icon and filename for any given document.
41
+ def icon_and_filename_for(document)
42
+ [icon_for(document.extname),document.filename].join("&nbsp;")
31
43
  end
32
44
 
45
+ # Returns the location (if avaible) of the filetype icon.
46
+ # TODO: Move this hash to a .yml config file.
33
47
  def icon_for(filetype)
34
48
  pic_for_exts={
35
49
  :xls=>%w{xls xlsx ods},
@@ -53,18 +67,26 @@ module DocumentsHelper
53
67
  image_tag("icons/#{pic.first}.png") if pic
54
68
  end
55
69
 
56
- def google?(query)
57
- link_to "Google?", "http://www.google.de/search?q=#{query}"
70
+ # Returns a link to a backup search engine that could maybe find more results for the same query.
71
+ def link_to_backup_search_engine(query)
72
+ link_to :backup_search_engine_name.l, :backup_search_engine_url.l<<query
58
73
  end
59
74
 
75
+ # For any indexed document, returns a link to its containing directory.
60
76
  def link_to_containing_directory(document)
61
77
  link_name=image_tag('icons/remote_folder.png')<<'&nbsp;'<<content_tag(:small,document.alias_path)
62
78
  link_to link_name, document.alias_path, :target=>'_blank'
63
79
  end
64
80
 
81
+ # For any indexed document, returns a link to show its content.
65
82
  def link_to_plain_text_content(document)
66
- return unless document.supported?
67
83
  link_name=image_tag('icons/plain_text_small.png')<<'&nbsp;'<<content_tag(:small,:text_content.l)
68
- link_to link_name, show_content_document_path(document.md5)
84
+ link_to link_name, content_document_path(document.probably_unique_id)
85
+ end
86
+
87
+ # For any indexed document, returns a link to show its cached content.
88
+ def link_to_cached_content(document)
89
+ link_name="("<<content_tag(:small,:cached.l)<<")"
90
+ link_to link_name, cached_document_path(document.probably_unique_id)
69
91
  end
70
92
  end
@@ -1,64 +1,98 @@
1
+ # Document class retrieves information from filesystem and the index for any given document.
1
2
  class Document
2
3
  attr_reader :complete_path
3
- attr_accessor :user, :score, :matching_content
4
+ attr_accessor :user, :score, :matching_content, :index_id
4
5
 
5
- def initialize(complete_path)
6
- @complete_path=complete_path
6
+ def initialize(path)
7
+ #To ensure @complete_path is an absolute direction.
8
+ @complete_path=File.expand_path(path)
7
9
  validate_existence_of_file
8
10
  validate_in_indexed_directory
9
11
  end
10
12
 
11
- def to_param
12
- id
13
- end
14
-
15
- def to_s
16
- filename
17
- end
13
+ alias_method :to_param, :id
18
14
 
19
15
  #Delegating properties to File::method_name(complete_path)
20
16
  [:dirname, :basename, :extname, :size?, :file?, :read, :ext_as_sym].each{|method_name|
21
17
  define_method(method_name){File.send(method_name,complete_path)}
22
18
  }
23
19
  alias_method :size, :size?
24
- alias_method :content, :read
25
20
  alias_method :filename, :basename
21
+ alias_method :to_s, :basename
26
22
 
23
+ # Returns filename without extension
24
+ # "buildings.odt" => "buildings"
27
25
  def basename
28
26
  filename.chomp(extname)
29
27
  end
30
-
31
- def absolute_dirname
32
- Pathname.new(dirname).realpath.to_s
33
- end
34
28
 
29
+ # End users should not always know where documents are stored internally.
30
+ # An alias path can be specified in config/indexed_directories.yml
31
+ #
32
+ # For example, with:
33
+ # "/media/wiki_dump/" : "http://www.mycompany.com/wiki/"
34
+ #
35
+ # The documents
36
+ # "/media/wiki_dump/organigram.odp"
37
+ # will be displayed as being:
38
+ # "http://www.mycompany.com/wiki/organigram.odp"
35
39
  def alias_path
36
40
  original_dir=indexed_directory
37
41
  alias_dir=IndexedDirectories[original_dir]
38
- absolute_dirname.sub(original_dir,alias_dir)
42
+ dirname.sub(original_dir,alias_dir)
39
43
  end
40
44
 
41
- def md5
42
- @md5=complete_path.base26_hash
45
+ # Returns an id for this document.
46
+ # This id will be used in Controllers in order to get tiny urls.
47
+ # Since it's a base26 hash of the absolute filename, it can only be "probably unique".
48
+ # For huge amount of indexed documents, it would be wise to increase HashLength in config/custom/picolena.rb
49
+ def probably_unique_id
50
+ @probably_unique_id||=complete_path.base26_hash
43
51
  end
44
52
 
53
+ # Returns true iff some Filter has been defined to convert it to plain text.
54
+ # Document.new("presentation.pdf").supported? => true
55
+ # Document.new("presentation.some_weird_extension").supported? => false
45
56
  def supported?
46
57
  PlainText.supported_extensions.include?(self.ext_as_sym)
47
58
  end
48
59
 
60
+ # Retrieves content as it is *now*.
49
61
  def content
50
62
  PlainText.extract_content_from(complete_path)
51
63
  end
52
64
 
65
+ # Cache à la Google.
66
+ # Returns content as it was at the time it was indexed.
67
+ def cached
68
+ get_index_id! unless index_id
69
+ Finder.index[index_id][:content]
70
+ end
71
+
72
+ # Returns the last modification date before the document got indexed.
73
+ # Useful to know how old a document is, and to which version the cache corresponds.
74
+ def date
75
+ get_index_id! unless index_id
76
+ Finder.index[index_id][:date].sub(/(\d{4})(\d{2})(\d{2})/,'\1-\2-\3')
77
+ end
78
+
53
79
  private
54
80
 
81
+ def get_index_id!
82
+ @index_id = Document.find_by_unique_id(probably_unique_id).index_id
83
+ end
84
+
85
+ def self.find_by_unique_id(some_id)
86
+ Finder.new("probably_unique_id:"<<some_id).matching_document
87
+ end
88
+
55
89
  def in_indexed_directory?
56
90
  !indexed_directory.nil?
57
91
  end
58
92
 
59
93
  def indexed_directory
60
94
  IndexedDirectories.keys.find{|indexed_dir|
61
- absolute_dirname.starts_with?(indexed_dir)
95
+ dirname.starts_with?(indexed_dir)
62
96
  }
63
97
  end
64
98
 
@@ -1,14 +1,21 @@
1
1
  require 'ff'
2
2
 
3
3
  class Finder
4
- attr_reader :index, :query
4
+ #FIXME: Should not use all those class methods to access index.
5
+
6
+ attr_reader :query
7
+
8
+ def self.index
9
+ # caching index @@index ||=
10
+ # causes ferret-0.11.6/lib/ferret/index.rb:768: [BUG] Segmentation fault
11
+ Ferret::Index::Index.new(:path => IndexSavePath, :analyzer=>Analyzer)
12
+ end
5
13
 
6
14
  def initialize(raw_query,page=1,results_per_page=ResultsPerPage)
7
15
  query_parser = Ferret::QueryParser.new(:fields => [:content, :file, :basename, :filetype, :date], :or_default => false, :analyzer=>Analyzer)
8
16
  @query = query_parser.parse(convert_to_english(raw_query))
9
17
  @raw_query= raw_query
10
18
  Finder.ensure_that_index_exists_on_disk
11
- @index = Ferret::Index::Index.new(:path => IndexSavePath, :analyzer=>Analyzer)
12
19
  @per_page=results_per_page
13
20
  @offset=(page.to_i-1)*results_per_page
14
21
  validate_that_index_has_documents
@@ -18,16 +25,17 @@ class Finder
18
25
  @matching_documents=[]
19
26
  start=Time.now
20
27
  begin
21
- top_docs=index.search(query, :limit => @per_page, :offset=>@offset)
28
+ top_docs=Finder.index.search(query, :limit => @per_page, :offset=>@offset)
22
29
  top_docs.hits.each{|hit|
23
- ferret_doc,score=hit.doc,hit.score
30
+ index_id,score=hit.doc,hit.score
24
31
  begin
25
- found_doc=Document.new(index[ferret_doc][:complete_path])
26
- found_doc.matching_content=index.highlight(query, ferret_doc,
32
+ found_doc=Document.new(Finder.index[index_id][:complete_path])
33
+ found_doc.matching_content=Finder.index.highlight(query, index_id,
27
34
  :field => :content, :excerpt_length => 80,
28
35
  :pre_tag => "<<", :post_tag => ">>"
29
36
  ) unless @raw_query=~/^\*+\.\w*$/
30
37
  found_doc.score=score
38
+ found_doc.index_id=index_id
31
39
  @matching_documents<<found_doc
32
40
  rescue Errno::ENOENT
33
41
  #"File has been moved/deleted!"
@@ -37,14 +45,20 @@ class Finder
37
45
  @time_needed=Time.now-start
38
46
  @total_hits=top_docs.total_hits
39
47
  ensure
40
- index.close
48
+ #index.close
41
49
  end
42
50
  end
43
51
 
52
+ # Returns true if it has been executed.
44
53
  def executed?
45
54
  @executed
46
55
  end
47
56
 
57
+ # To ensure that
58
+ # matching_documents
59
+ # total_hits
60
+ # time_needed
61
+ # methods are called only after the index has been searched.
48
62
  [:matching_documents, :total_hits, :time_needed].each{|attribute_name|
49
63
  define_method(attribute_name){
50
64
  execute! unless executed?
@@ -52,18 +66,19 @@ class Finder
52
66
  }
53
67
  }
54
68
 
69
+ # Returns true if index is existing.
55
70
  def self.has_index?
56
71
  index_filename and File.exists?(index_filename)
57
72
  end
58
73
 
74
+ # Returns true if there's at least one document indexed.
59
75
  def has_documents?
60
- index.size>0
61
- end
62
-
63
- def self.up_to_date?
64
- IndexedDirectories.keys.all?{|dir| File.mtime(index_filename) > File.mtime(dir)}
76
+ Finder.index.size>0
65
77
  end
66
78
 
79
+ # Returns matching document for any given query, if only
80
+ # exactly one document is found.
81
+ # Raises otherwise.
67
82
  def matching_document
68
83
  case matching_documents.size
69
84
  when 0
@@ -77,7 +92,8 @@ class Finder
77
92
 
78
93
  private
79
94
 
80
- def convert_to_english(str)
95
+ # Convert query keywords to english so they can be parsed by Ferret.
96
+ def convert_to_english(query)
81
97
  to_en={
82
98
  /\b#{:AND.l}\b/=>'AND',
83
99
  /\b#{:OR.l}\b/=>'OR',
@@ -87,7 +103,7 @@ class Finder
87
103
  /#{:date.l}:/ => 'date:',
88
104
  /\b#{:LIKE.l}\s+(\S+)/=>'\1~'
89
105
  }
90
- to_en.inject(str){|mem,non_english_to_english_keyword|
106
+ to_en.inject(query){|mem,non_english_to_english_keyword|
91
107
  mem.gsub(*non_english_to_english_keyword)
92
108
  }
93
109
  end
@@ -1,7 +1,10 @@
1
1
  %h2
2
- =link_to icon_and_filename_for(document), download_document_path(document.md5)
2
+ =link_to icon_and_filename_for(document), download_document_path(document.probably_unique_id)
3
3
  %small=number_to_percentage(document.score*100, :precision=>1)
4
4
  =highlight_matching_content(document)
5
5
  %p=link_to_containing_directory(document)
6
- %p=link_to_plain_text_content(document)
6
+ - if document.supported?
7
+ %p
8
+ =link_to_plain_text_content(document)
9
+ =link_to_cached_content(document)
7
10
  %hr/
@@ -0,0 +1,8 @@
1
+ %h2
2
+ =link_to icon_and_filename_for(@document), download_document_path(@probably_unique_id)
3
+ (
4
+ =:as_it_was_indexed_on.l
5
+ =@document.date
6
+ )
7
+ %p=link_to_containing_directory(@document)
8
+ %blockquote=h(@document.cached).gsub(/\n/,'<br/>')
@@ -1,3 +1,3 @@
1
- %h2=link_to icon_and_filename_for(@document), download_document_path(@md5_hash)
1
+ %h2=link_to icon_and_filename_for(@document), download_document_path(@probably_unique_id)
2
2
  %p=link_to_containing_directory(@document)
3
3
  %blockquote=h(@document.content).gsub(/\n/,'<br/>')
@@ -2,7 +2,7 @@
2
2
  .info_bar
3
3
  %p
4
4
  -if nothing_found? then
5
- %span{:class=>'pagination'}=google?(@query)
5
+ %span{:class=>'pagination'}=link_to_backup_search_engine(@query)
6
6
  =:nothing_found_for.l
7
7
  %strong=@query
8
8
  =show_time_needed(@time_needed)
@@ -3,7 +3,7 @@
3
3
 
4
4
  RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
5
5
 
6
- module Rails
6
+ module Rails #:nodoc:
7
7
  class << self
8
8
  def boot!
9
9
  unless booted?
@@ -34,20 +34,20 @@ module Rails
34
34
  end
35
35
  end
36
36
 
37
- class Boot
37
+ class Boot #:nodoc:
38
38
  def run
39
39
  load_initializer
40
40
  Rails::Initializer.run(:set_load_path)
41
41
  end
42
42
  end
43
43
 
44
- class VendorBoot < Boot
44
+ class VendorBoot < Boot #:nodoc:
45
45
  def load_initializer
46
46
  require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
47
47
  end
48
48
  end
49
49
 
50
- class GemBoot < Boot
50
+ class GemBoot < Boot #:nodoc:
51
51
  def load_initializer
52
52
  self.class.load_rubygems
53
53
  load_rails_gem
@@ -0,0 +1,3 @@
1
+ custom_config_file = File.join(RAILS_ROOT, 'config/custom/picolena.rb')
2
+ require 'ferret'
3
+ require custom_config_file
@@ -1,5 +1,5 @@
1
1
  #Loading directories to be indexed
2
- indexed_dir_config_file=['config/indexed_directories.yml', 'config/indexed_directories.yml.template'].find{|f| File.file?(f)}
2
+ indexed_dir_config_file='config/custom/indexed_directories.yml'
3
3
  IndexedDirectories={}
4
4
  YAML.load_file(indexed_dir_config_file)[RAILS_ENV].each_pair{|abs_or_rel_path, alias_path|
5
5
  IndexedDirectories[Pathname(abs_or_rel_path).realpath.to_s]=alias_path
@@ -0,0 +1,8 @@
1
+ #Deny all, Allow only IPs described in config/custom/white_list_ip.yml
2
+ white_list_ip_config_file='config/custom/white_list_ip.yml'
3
+ WhiteListIPs=Regexp.new(
4
+ "^("<<
5
+ YAML.load_file(white_list_ip_config_file)["Allow"].collect{|ip|
6
+ ip.downcase.include?("all") ? /.*/ : Regexp.escape(ip)
7
+ }.join("|")<<")"
8
+ ) rescue /^(127\.0\.0\.1|0\.0\.0\.0)/
@@ -0,0 +1,5 @@
1
+ custom_localization_yml=File.join(RAILS_ROOT,'config/custom/title_and_names_and_links.yml')
2
+
3
+ YAML.load_file(custom_localization_yml).each{|key_name, custom_translation|
4
+ Globalite.localizations[key_name.to_sym]=custom_translation unless custom_translation.blank?
5
+ }
@@ -1,5 +1,5 @@
1
1
  ActionController::Routing::Routes.draw do |map|
2
- map.resources :documents, :collection=>{:check_query=>:post}, :member=>{:download=>:get, :show_content=>:get}
2
+ map.resources :documents, :collection=>{:check_query=>:post}, :member=>{:download=>:get, :content=>:get, :cached=>:get}
3
3
  map.connect 'documents/:id', :controller=>'documents', :action=>'show', :id => /.*/
4
4
  map.connect 'access_denied', :controller=> 'application', :action => 'access_denied'
5
5
  map.connect "*anything", :controller=>'application', :action => 'unknown_request'
@@ -9,10 +9,8 @@ results: Ergebnisse
9
9
  of: von
10
10
  for: für
11
11
  text_content: Text-Inhalt
12
-
13
- ## Link to a website, located in the bottom-left corner.
14
- website_name: Picolena
15
- website_url: http://picolena.devjavu.com/
12
+ cached: cached
13
+ as_it_was_indexed_on: wie am
16
14
 
17
15
  ## Boolean operators
18
16
  AND: UND
@@ -9,10 +9,8 @@ results: Results
9
9
  of: of
10
10
  for: for
11
11
  text_content: Text content
12
-
13
- ## Link to a website, located in the bottom-left corner.
14
- website_name: Picolena
15
- website_url: http://picolena.devjavu.com/
12
+ cached: cached
13
+ as_it_was_indexed_on: as it was indexed on
16
14
 
17
15
  ## Boolean operators
18
16
  AND: AND
@@ -8,11 +8,9 @@ nothing_found_for: Ningún documento encontrado por
8
8
  results: Resultados
9
9
  of: de
10
10
  for: por
11
- text_content: ver_contenido
12
-
13
- ## Link to a website, located in the bottom-left corner.
14
- website_name: Picolena
15
- website_url: http://picolena.devjavu.com/
11
+ text_content: ver contenido
12
+ cached: caché
13
+ as_it_was_indexed_on: como fue indexado el
16
14
 
17
15
  ## Boolean operators
18
16
  AND: Y
@@ -8,11 +8,9 @@ nothing_found_for: Rien trouvé pour
8
8
  results: Résultats
9
9
  of: parmi
10
10
  for: pour
11
- text_content: contenu
12
-
13
- ## Link to a website, located in the bottom-left corner.
14
- website_name: Picolena
15
- website_url: http://picolena.devjavu.com/
11
+ text_content: voir le contenu
12
+ cached: cached
13
+ as_it_was_indexed_on: comme indexé le
16
14
 
17
15
  ## Boolean operators
18
16
  AND: ET
@@ -17,7 +17,7 @@ end
17
17
 
18
18
  class String
19
19
  # Creates a "probably unique" id with the desired length, composed only of lowercase letters.
20
- def base26_hash(length=10)
20
+ def base26_hash(length=HashLength)
21
21
  Digest::MD5.hexdigest(self).to_i(16).to_s(26).tr('0-9a-p', 'a-z')[-length,length]
22
22
  end
23
23
  end
@@ -20,11 +20,11 @@ def index_file(index, filename, mime_type=nil)
20
20
  complete_path=File.expand_path(filename)
21
21
  fields = {
22
22
  :complete_path=> complete_path,
23
- :md5 => complete_path.base26_hash,
23
+ :probably_unique_id => complete_path.base26_hash,
24
24
  :file => File.basename(filename),
25
25
  :basename => File.basename(filename, File.extname(filename)).gsub(/_/,' '),
26
26
  :filetype => File.extname(filename),
27
- :date => File.mtime(filename).strftime("%Y%m%d")
27
+ :date => File.mtime(filename).strftime("%Y%m%d%H%M")
28
28
  }
29
29
 
30
30
  if mime_type then
@@ -112,6 +112,6 @@ def add_fields(index)
112
112
  index.field_infos.add_field(:basename, :store => :no, :index => :yes, :boost => 1.5)
113
113
  index.field_infos.add_field(:file, :store => :no, :index => :yes, :boost => 1.5)
114
114
  index.field_infos.add_field(:filetype, :store => :no, :index => :yes, :boost => 1.5)
115
- index.field_infos.add_field(:date, :store=>:no, :index=>:yes)
116
- index.field_infos.add_field(:md5, :store=>:no, :index=>:yes)
115
+ index.field_infos.add_field(:date, :store=>:yes, :index=>:yes)
116
+ index.field_infos.add_field(:probably_unique_id, :store=>:no, :index=>:yes)
117
117
  end
@@ -8,17 +8,18 @@ describe "DocumentsController called from unknown IP" do
8
8
  end
9
9
 
10
10
  it "should deny access" do
11
- WhiteListIPs=/Something that won't match/
11
+ # Displays a warning otherwise
12
+ Object.send(:remove_const, :WhiteListIPs) && WhiteListIPs=/Something that won't match/
12
13
  get 'index'
13
14
  response.should be_redirect
14
15
  response.should redirect_to(:controller=>'application', :action=>'access_denied')
15
- WhiteListIPs=/^0\.0\.0\.0/
16
+ Object.send(:remove_const, :WhiteListIPs) && WhiteListIPs=/^0\.0\.0\.0/
16
17
  get 'index'
17
18
  response.should be_success
18
19
  end
19
20
 
20
21
  after(:all) do
21
- WhiteListIPs=@backup
22
+ Object.send(:remove_const, :WhiteListIPs) && WhiteListIPs=@backup
22
23
  end
23
24
  end
24
25
 
@@ -96,18 +97,18 @@ describe DocumentsController do
96
97
  response.should be_success
97
98
  assigns[:matching_documents].entries.should_not be_empty
98
99
  d=assigns[:matching_documents].entries.first
99
- get 'download', :id=>d.md5
100
+ get 'download', :id=>d.probably_unique_id
100
101
  assigns[:document].complete_path == d.complete_path
101
102
  response.should be_success
102
103
  end
103
104
 
104
105
  it "GET 'download' should redirect if wrong id" do
105
- md5="Not a document".base26_hash
106
- get 'download', :id=>md5
106
+ probably_unique_id="Not a document".base26_hash
107
+ get 'download', :id=>probably_unique_id
107
108
  response.should be_redirect
108
109
  response.should redirect_to(documents_url)
109
- md5='Whatever'
110
- get 'download', :id=>md5
110
+ probably_unique_id='Whatever'
111
+ get 'download', :id=>probably_unique_id
111
112
  response.should be_redirect
112
113
  response.should redirect_to(documents_url)
113
114
  end
@@ -17,7 +17,7 @@ describe "Finder without index on disk" do
17
17
  IndexedDirectories.replace({'spec/test_dirs/indexed/just_one_doc'=>'//justonedoc/'})
18
18
  lambda {@finder_with_new_index=Finder.new("test moi")}.should change(Finder, :has_index?).from(false).to(true)
19
19
  File.exists?(File.join(@new_index_path,'_0.cfs')).should be_true
20
- @finder_with_new_index.index.size.should >0
20
+ Finder.index.size.should >0
21
21
  end
22
22
 
23
23
  it "should raise if index is still empty after trying to create it" do
@@ -75,21 +75,14 @@ describe "Basic Finder" do
75
75
  @finder=Finder.new("some query")
76
76
  lambda {@finder.execute!}.should change(@finder, :executed?).from(false).to(true)
77
77
  end
78
-
79
- it "should know if index is up to date" do
80
- Finder.has_index?.should be_true
81
- Finder.should respond_to(:up_to_date?)
82
- Finder.should be_up_to_date
83
- end
84
-
78
+
85
79
  it "should not warn anything if index is up to date"
86
80
 
87
81
  it "should warn if index is not up to date"
88
82
 
89
83
  fields.each_pair do |description,field_name|
90
84
  it "should index #{description} as :#{field_name}" do
91
- @finder=Finder.new("some query")
92
- @finder.index.field_infos[field_name].should be_an_instance_of(Ferret::Index::FieldInfo)
85
+ Finder.index.field_infos[field_name].should be_an_instance_of(Ferret::Index::FieldInfo)
93
86
  end
94
87
  end
95
88
 
@@ -2,9 +2,9 @@ require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
3
  basic_pdf_attribute={
4
4
  :size=>9380,
5
- :dirname=>'spec/test_dirs/indexed/basic',
5
+ :dirname=>File.join(RAILS_ROOT, 'spec/test_dirs/indexed/basic'),
6
6
  :basename=>'basic',
7
- :complete_path=>'spec/test_dirs/indexed/basic/basic.pdf',
7
+ :complete_path=>File.join(RAILS_ROOT, '/spec/test_dirs/indexed/basic/basic.pdf'),
8
8
  :extname=>'.pdf',
9
9
  :filename=>'basic.pdf'
10
10
  }
@@ -1,13 +1,19 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
+ def revert_changes!(file,content)
4
+ File.open(file,'w'){|might_have_been_modified|
5
+ might_have_been_modified.write content
6
+ }
7
+ end
8
+
3
9
  describe Finder do
4
10
  before(:all) do
5
11
  # SVN doesn't like non-ascii filenames.
6
- File.open('spec/test_dirs/indexed/others/bäñüßé.txt','w'){|weird_file|
7
- weird_file.write "just to know if files are indexed with utf8 filenames"
8
- }
9
-
12
+ revert_changes!('spec/test_dirs/indexed/others/bäñüßé.txt',"just to know if files are indexed with utf8 filenames")
10
13
 
14
+ # To be sure this file has the right content
15
+ revert_changes!("spec/test_dirs/indexed/others/placeholder.txt","Absorption and Adsorption cooling machines!!!")
16
+
11
17
  once_upon_a_time=Time.local(1982,2,16,20,42)
12
18
  a_bit_later=Time.local(1983,12,9,9)
13
19
  nineties=Time.local(1990)
@@ -41,10 +47,9 @@ describe Finder do
41
47
  end
42
48
 
43
49
  it "should give a boost to basename, filename and filetype in index" do
44
- @finder=Finder.new("some query")
45
- @finder.index.field_infos[:basename].boost.should > 1.0
46
- @finder.index.field_infos[:file].boost.should > 1.0
47
- @finder.index.field_infos[:filetype].boost.should > 1.0
50
+ Finder.index.field_infos[:basename].boost.should > 1.0
51
+ Finder.index.field_infos[:file].boost.should > 1.0
52
+ Finder.index.field_infos[:filetype].boost.should > 1.0
48
53
  end
49
54
 
50
55
  it "should also index unreadable files with known mimetypes" do
@@ -85,7 +90,7 @@ describe Finder do
85
90
 
86
91
  it "should find documents according to their modification date" do
87
92
  Finder.new("date:<1982").matching_documents.should be_empty
88
- Finder.new("19831209").matching_document.basename.should == "office2003-word-template"
93
+ Finder.new("19831209*").matching_document.basename.should == "office2003-word-template"
89
94
  Finder.new("date:<1983").matching_document.filename.should == "basic.pdf"
90
95
  Finder.new("date:>=1989 AND date:<=1992").matching_document.filename.should == "placeholder.txt"
91
96
  end
@@ -195,6 +200,22 @@ describe Finder do
195
200
  Finder.new("Thumbs.db").matching_documents.should be_empty
196
201
  Finder.new("filetype:db").matching_documents.should_not be_empty
197
202
  end
203
+
204
+ it "should keep content cached" do
205
+ filename = "spec/test_dirs/indexed/others/placeholder.txt"
206
+ content_before = "Absorption and Adsorption cooling machines!!!"
207
+ some_doc=Document.new(filename)
208
+ some_doc.content.should == content_before
209
+ File.open(filename,'a'){|doc|
210
+ doc.write("This line should not be indexed. It shouldn't be found in cache")
211
+ }
212
+ some_doc.content.should_not == content_before
213
+ some_doc.cached.should == content_before
214
+ end
215
+
216
+ after(:all) do
217
+ revert_changes!("spec/test_dirs/indexed/others/placeholder.txt","Absorption and Adsorption cooling machines!!!")
218
+ end
198
219
 
199
220
  # Not sure about this spec!
200
221
  # English, or German?
@@ -7,17 +7,23 @@ describe "Host indexing system" do
7
7
  end
8
8
  end
9
9
 
10
- it "should know which IP addresses are allowed (config/white_list_ip.yml)" do
11
- File.should be_readable('config/white_list_ip.yml')
10
+ it "should know which IP addresses are allowed (config/custom/white_list_ip.yml)" do
11
+ File.should be_readable('config/custom/white_list_ip.yml')
12
12
  end
13
13
 
14
- it "should know which directories are to be indexed (config/indexed_directories.yml)" do
15
- File.should be_readable('config/indexed_directories.yml')
14
+ it "should know which directories are to be indexed (config/custom/indexed_directories.yml)" do
15
+ File.should be_readable('config/custom/indexed_directories.yml')
16
16
  end
17
17
 
18
- # it would probably take ages to find a string whose hash == "picolena" :(
19
18
  it "should be able to calculate base26 hash from strings" do
19
+ "test_dirs/indexed/010/decrepito.pdf".base26_hash(5).should == "rails"
20
+ "test_dirs/indexed/migrations/000_restreins.rb".base26_hash(5).should == "ricou"
21
+ # it would probably take ages to find a string whose hash == "picolena" :(
20
22
  "test_dirs/indexed/1148/plots.odt".base26_hash(8).should == "picolehn"
21
- "whatever.pdf".base26_hash.should == "bbuxhynait"
23
+ "whatever.pdf".base26_hash(10).should == "bbuxhynait"
24
+ end
25
+
26
+ it "should not use too small a hash for Document#probably_unique_id" do
27
+ HashLength.should_not < 10
22
28
  end
23
29
  end
@@ -2,7 +2,7 @@ module Picolena #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 0
5
+ TINY = 1
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/lib/rubigen_ext.rb CHANGED
@@ -1,6 +1,6 @@
1
- module RubiGen
2
- module Commands
3
- class Create
1
+ module RubiGen #:nodoc:
2
+ module Commands #:nodoc:
3
+ class Create #:nodoc:
4
4
  # Launch given Rake task in destination_path
5
5
  def rake(task_name)
6
6
  logger.rake task_name
data/tasks/hack.rake ADDED
@@ -0,0 +1,17 @@
1
+ desc 'Create development picolena structure inside lib/picolena/templates'
2
+ task :lets_hack do
3
+ picolena_root=File.join(File.dirname(__FILE__),'..')
4
+ Dir.chdir(picolena_root){
5
+ system("ruby bin/picolena lib/picolena/templates/spec/test_dirs --skip --no-index --no-spec --destination=lib/picolena/templates")
6
+ }
7
+ puts <<-EXPLAIN
8
+
9
+ You now have a complete picolena installation in:
10
+ #{File.expand_path(File.join(File.dirname(__FILE__),'../lib/picolena/templates'))}
11
+
12
+ You can now hack and submit patches!
13
+
14
+ Once done, you can remove those files by typing:
15
+ rake clean
16
+ EXPLAIN
17
+ end
data/tasks/rspec.rake CHANGED
@@ -1,20 +1,6 @@
1
- begin
2
- require 'spec'
3
- rescue LoadError
4
- require 'rubygems'
5
- require 'spec'
6
- end
7
- begin
8
- require 'spec/rake/spectask'
9
- rescue LoadError
10
- puts <<-EOS
11
- To use rspec for testing you must install rspec gem:
12
- gem install rspec
13
- EOS
14
- exit(0)
15
- end
16
-
17
- desc "Run the specs under spec/models"
18
- Spec::Rake::SpecTask.new do |t|
19
- t.spec_files = FileList['spec/**/*_spec.rb']
20
- end
1
+ desc 'Create a temporary picolena structure and launch specs from it'
2
+ task :spec => :clean do
3
+ require 'pathname'
4
+ picolena_bin=Pathname(File.join(File.dirname(__FILE__),'../bin/picolena')).realpath.to_s
5
+ system("ruby #{picolena_bin} --spec-only")
6
+ end
data/tasks/test.rake ADDED
@@ -0,0 +1,3 @@
1
+ Rake::Task[:test].abandon
2
+
3
+ task :test => :spec
data/website/index.html CHANGED
@@ -33,7 +33,7 @@
33
33
  <h1>Picolena</h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/picolena"; return false'>
35
35
  <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/picolena" class="numbers">0.1.0</a>
36
+ <a href="http://rubyforge.org/projects/picolena" class="numbers">0.1.1</a>
37
37
  </div>
38
38
  <h1>&#x2192; &#8216;picolena&#8217;</h1>
39
39
 
@@ -114,7 +114,7 @@ ruby script/server</code></pre>
114
114
 
115
115
  <p>Comments are welcome. Send an email to <a href="mailto:eric_duminil@rubyforge.org">Eric Duminil</a> email via the <a href="http://groups.google.com/group/picolena">forum</a></p>
116
116
  <p class="coda">
117
- <a href="eric_duminil@rubyforge.org">Eric DUMINIL</a>, 8th April 2008<br>
117
+ <a href="eric_duminil@rubyforge.org">Eric DUMINIL</a>, 12th April 2008<br>
118
118
  Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>,
119
119
  by Daniel Cadenas via <a href="http://depgraph.rubyforge.org/">DepGraph</a>
120
120
  </p>
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: picolena
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Duminil
@@ -30,7 +30,7 @@ cert_chain:
30
30
  qvI9FgPZ1QTG5uZAlBbk6d6JU2XfpA==
31
31
  -----END CERTIFICATE-----
32
32
 
33
- date: 2008-04-09 00:00:00 +02:00
33
+ date: 2008-04-12 00:00:00 +02:00
34
34
  default_executable:
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
@@ -87,6 +87,15 @@ dependencies:
87
87
  - !ruby/object:Gem::Version
88
88
  version: 1.1.0
89
89
  version:
90
+ - !ruby/object:Gem::Dependency
91
+ name: rspec
92
+ version_requirement:
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 1.1.3
98
+ version:
90
99
  description: Picolena is a lightweight ferret-powered documents search engine written in Ruby on rails
91
100
  email:
92
101
  - eric_duminil@rubyforge.org
@@ -129,10 +138,13 @@ files:
129
138
  - README.txt
130
139
  - Rakefile
131
140
  - bin/picolena
141
+ - config/files_to_clean
132
142
  - config/hoe.rb
133
143
  - config/requirements.rb
134
144
  - lib/picolena/USAGE
145
+ - lib/picolena/config/basic.rb
135
146
  - lib/picolena/config/indexed_directories.yml
147
+ - lib/picolena/config/title_and_names_and_links.yml
136
148
  - lib/picolena/config/white_list_ip.yml
137
149
  - lib/picolena/picolena_generator.rb
138
150
  - lib/picolena/templates/MIT-LICENSE
@@ -144,19 +156,21 @@ files:
144
156
  - lib/picolena/templates/app/models/document.rb
145
157
  - lib/picolena/templates/app/models/finder.rb
146
158
  - lib/picolena/templates/app/views/documents/_document.html.haml
159
+ - lib/picolena/templates/app/views/documents/cached.html.haml
160
+ - lib/picolena/templates/app/views/documents/content.html.haml
147
161
  - lib/picolena/templates/app/views/documents/index.html.haml
148
162
  - lib/picolena/templates/app/views/documents/show.html.haml
149
- - lib/picolena/templates/app/views/documents/show_content.html.haml
150
163
  - lib/picolena/templates/app/views/layouts/application.html.haml
151
164
  - lib/picolena/templates/config/boot.rb
152
165
  - lib/picolena/templates/config/environment.rb
153
166
  - lib/picolena/templates/config/environments/development.rb
154
167
  - lib/picolena/templates/config/environments/production.rb
155
168
  - lib/picolena/templates/config/environments/test.rb
156
- - lib/picolena/templates/config/initializers/001_prepare_and_load_custom_config.rb
157
- - lib/picolena/templates/config/initializers/002_indexed_dirs.rb
158
- - lib/picolena/templates/config/initializers/003_white_list_IPs.rb
169
+ - lib/picolena/templates/config/initializers/001_load_custom_config.rb
170
+ - lib/picolena/templates/config/initializers/002_load_indexed_dirs.rb
171
+ - lib/picolena/templates/config/initializers/003_load_white_list_IPs.rb
159
172
  - lib/picolena/templates/config/initializers/004_load_filters.rb
173
+ - lib/picolena/templates/config/initializers/005_load_custom_title_and_names_and_links.rb
160
174
  - lib/picolena/templates/config/routes.rb
161
175
  - lib/picolena/templates/lang/ui/de.yml
162
176
  - lib/picolena/templates/lang/ui/en.yml
@@ -890,13 +904,13 @@ files:
890
904
  - script/generate
891
905
  - script/txt2html
892
906
  - setup.rb
893
- - spec/picolena_spec.rb
894
- - tasks/default.rake
895
907
  - tasks/deployment.rake
896
908
  - tasks/environment.rake
909
+ - tasks/hack.rake
897
910
  - tasks/rdoc.rake
898
911
  - tasks/ri.rake
899
912
  - tasks/rspec.rake
913
+ - tasks/test.rake
900
914
  - tasks/website.rake
901
915
  - website/index.html
902
916
  - website/index.txt
@@ -931,5 +945,5 @@ rubygems_version: 1.1.0
931
945
  signing_key:
932
946
  specification_version: 2
933
947
  summary: Picolena is a lightweight ferret-powered documents search engine written in Ruby on rails
934
- test_files:
935
- - spec/picolena_spec.rb
948
+ test_files: []
949
+
metadata.gz.sig CHANGED
Binary file
@@ -1,8 +0,0 @@
1
- #Deny all, Allow only IPs described in config/white_list_ip.yml
2
- white_list_ip_config_file=['config/white_list_ip.yml', 'config/white_list_ip.yml.template'].find{|f| File.file?(f)}
3
- WhiteListIPs=Regexp.new(
4
- "^("<<
5
- YAML.load_file(white_list_ip_config_file)["Allow"].collect{|ip|
6
- ip.downcase.include?("all") ? /.*/ : Regexp.escape(ip)
7
- }.join("|")<<")"
8
- ) rescue /^(127\.0\.0\.1|0\.0\.0\.0)/
@@ -1,3 +0,0 @@
1
- require 'pathname'
2
- picolena_bin=Pathname(File.join(File.dirname(__FILE__),'../bin/picolena')).realpath.to_s
3
- system("ruby #{picolena_bin} --spec-only")
data/tasks/default.rake DELETED
@@ -1 +0,0 @@
1
- Rake::Task[:default].prerequisites.clear