racknga 0.9.1 → 0.9.2

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.
data/Gemfile ADDED
@@ -0,0 +1,30 @@
1
+ # -*- mode: ruby; coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2011 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ source "http://rubygems.org/"
19
+
20
+ gem "rroonga"
21
+ gem "rack"
22
+
23
+ group :development, :test do
24
+ gem "test-unit"
25
+ gem "test-unit-notify"
26
+ gem "test-unit-capybara"
27
+ gem "rake"
28
+ gem "jeweler"
29
+ gem "yard"
30
+ end
data/README.textile ADDED
@@ -0,0 +1,52 @@
1
+ h1. README
2
+
3
+ h2. Name
4
+
5
+ racknga
6
+
7
+ h2. Description
8
+
9
+ Rack middlewares that use rroonga features and
10
+ middlewares/utilities that don't use rroonga features.
11
+
12
+ * "rroonga":http://groonga.rubyforge.org/
13
+ * "Rack":http://rack.rubyforge.org/
14
+
15
+ h2. Authors
16
+
17
+ * Kouhei Sutou <kou@clear-code.com>
18
+
19
+ h2. License
20
+
21
+ LGPL 2.1 or later. See license/lgpl-2.1.txt for details.
22
+
23
+ (Kouhei Sutou has a right to change the license
24
+ including contributed patches.)
25
+
26
+ h2. Dependencies
27
+
28
+ * Ruby >= 1.9.1
29
+ * rroonga
30
+ * Rack
31
+
32
+ h2. Suggested libraries
33
+
34
+ * jpmobile
35
+
36
+ h2. Install
37
+
38
+ <pre>
39
+ % sudo gem install racknga
40
+ </pre>
41
+
42
+ h2. Documents
43
+
44
+ http://groonga.rubyforge.org/racknga/en/
45
+
46
+ h2. Mailing list
47
+
48
+ http://rubyforge.org/mailman/listinfo/groonga-users-en
49
+
50
+ h2. Thanks
51
+
52
+ * ...
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8; mode: ruby -*-
2
2
  #
3
- # Copyright (C) 2010 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2010-2011 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -17,21 +17,15 @@
17
17
 
18
18
  require 'English'
19
19
 
20
- require 'find'
21
20
  require 'fileutils'
22
21
  require 'pathname'
23
22
  require 'erb'
24
23
  require 'rubygems'
25
- gem 'rdoc'
26
- require 'hoe'
27
-
28
- ENV["NODOT"] = "yes"
29
-
30
- base_dir = Pathname(__FILE__).dirname
31
- truncate_base_dir = Proc.new do |path|
32
- path.relative_path_from(base_dir)
33
- end
24
+ require 'jeweler'
25
+ require "rake/clean"
26
+ require "yard"
34
27
 
28
+ base_dir = Pathname.new(__FILE__).dirname
35
29
  racknga_lib_dir = base_dir + 'lib'
36
30
  $LOAD_PATH.unshift(racknga_lib_dir.to_s)
37
31
 
@@ -40,150 +34,276 @@ def guess_version
40
34
  Racknga::VERSION
41
35
  end
42
36
 
43
- manifest = base_dir + "Manifest.txt"
44
- manifest_contents = []
45
- base_dir_included_components = %w(AUTHORS Rakefile
46
- README.rdoc README.ja.rdoc
47
- NEWS.rdoc NEWS.ja.rdoc
48
- rroonga-build.rb extconf.rb pkg-config.rb)
49
- excluded_components = %w(.cvsignore .gdb_history CVS depend Makefile doc pkg
50
- .svn .git doc data .test-result tmp)
51
- excluded_suffixes = %w(.png .ps .pdf .o .so .a .txt .~)
52
- unless ENV["RUBY_CC_VERSION"]
53
- excluded_components << "vendor"
54
- end
55
- base_dir.find do |target|
56
- target = truncate_base_dir[target]
57
- components = target.to_s.split(File::SEPARATOR)
58
- if components.size == 1 and !target.directory?
59
- next unless base_dir_included_components.include?(components[0])
37
+ ENV["VERSION"] ||= guess_version
38
+ version = ENV["VERSION"].dup
39
+ project = nil
40
+ spec = nil
41
+ Jeweler::Tasks.new do |_spec|
42
+ spec = _spec
43
+ spec.name = 'racknga'
44
+ spec.version = version
45
+ spec.rubyforge_project = 'groonga'
46
+ spec.homepage = "http://groonga.rubyforge.org/"
47
+ authors_file = File.join(base_dir, "AUTHORS")
48
+ authors = []
49
+ emails = []
50
+ File.readlines(authors_file).each do |line|
51
+ if /\s*<([^<>]*)>$/ =~ line
52
+ authors << $PREMATCH
53
+ emails << $1
54
+ end
60
55
  end
61
- Find.prune if (excluded_components - components) != excluded_components
62
- next if excluded_suffixes.include?(File.extname(target))
63
- manifest_contents << target if File.file?(target)
56
+ spec.authors = authors
57
+ spec.email = emails
58
+ spec.summary = "A Rack middleware collection for rroonga features."
59
+ spec.description = <<-EOD.gsub(/\n/, ' ').strip
60
+ Racknga is a Rack middlewares that uses rroonga features.
61
+ EOD
62
+ spec.license = "LGPLv2.1 or later"
63
+ spec.files = FileList["lib/**/*.rb",
64
+ "{license,munin,doc/text/}/**/*",
65
+ "example/*.rb",
66
+ "AUTHORS",
67
+ "Rakefile",
68
+ "Gemfile",
69
+ "README*"]
70
+ spec.test_files = FileList["test/**/*.rb"]
64
71
  end
65
72
 
66
- File.open(manifest, "w") do |f|
67
- f.puts manifest_contents.sort.join("\n")
73
+ Rake::Task["release"].prerequisites.clear
74
+ Jeweler::RubygemsDotOrgTasks.new do
68
75
  end
69
76
 
70
- # For Hoe's no user friendly default behavior. :<
71
- File.open("README.txt", "w") {|file| file << "= Dummy README\n== XXX\n"}
72
- FileUtils.cp("NEWS.rdoc", "History.txt")
73
- at_exit do
74
- FileUtils.rm_f("README.txt")
75
- FileUtils.rm_f("History.txt")
76
- FileUtils.rm_f(manifest)
77
+ reference_base_dir = Pathname.new("doc/reference")
78
+ doc_en_dir = reference_base_dir + "en"
79
+ html_base_dir = Pathname.new("doc/html")
80
+ html_reference_dir = html_base_dir + spec.name
81
+ YARD::Rake::YardocTask.new do |task|
82
+ task.options += ["--title", spec.name]
83
+ task.options += ["--readme", "README.textile"]
84
+ task.options += ["--files", "doc/text/**/*"]
85
+ task.options += ["--output-dir", doc_en_dir.to_s]
86
+ task.options += ["--charset", "utf-8"]
77
87
  end
78
88
 
79
- def cleanup_white_space(entry)
80
- entry.gsub(/(\A\n+|\n+\z)/, '') + "\n"
81
- end
82
-
83
- ENV["VERSION"] ||= guess_version
84
- version = ENV["VERSION"]
85
- project = nil
86
- Hoe.spec('racknga') do
87
- Hoe::Test::SUPPORTED_TEST_FRAMEWORKS[:testunit2] = "test/run-test.rb"
88
- project = self
89
- project.version = version.dup
90
- project.rubyforge_name = 'groonga'
91
- authors = File.join(base_dir, "AUTHORS")
92
- project.author = File.readlines(authors).collect do |line|
93
- if /\s*<[^<>]*>$/ =~ line
94
- $PREMATCH
95
- else
96
- nil
89
+ task :yard do
90
+ doc_en_dir.find do |path|
91
+ next if path.extname != ".html"
92
+ html = path.read
93
+ html = html.gsub(/<div id="footer">.+<\/div>/m,
94
+ "<div id=\"footer\"></div>")
95
+ path.open("w") do |html_file|
96
+ html_file.print(html)
97
97
  end
98
- end.compact
99
- project.email = ['groonga-users-en@rubyforge.org',
100
- 'groonga-dev@lists.sourceforge.jp']
101
- project.url = 'http://groonga.rubyforge.org/'
102
- project.testlib = :testunit2
103
- project.test_globs = ["test/run-test.rb"]
104
- project.extra_deps += [["rroonga"],
105
- ["rack"]]
106
- project.spec_extras = {
107
- :extra_rdoc_files => Dir.glob("**/*.rdoc"),
108
- :licenses => ["LGPL 2.1 or later"]
109
- }
110
- project.readme_file = "README.ja.rdoc"
111
-
112
- news_of_current_release = File.read("NEWS.rdoc").split(/^==\s.*$/)[1]
113
- project.changes = cleanup_white_space(news_of_current_release)
114
-
115
- entries = File.read("README.rdoc").split(/^==\s(.*)$/)
116
- description = cleanup_white_space(entries[entries.index("Description") + 1])
117
- project.summary, project.description, = description.split(/\n\n+/, 3)
118
-
119
- project.remote_rdoc_dir = "racknga"
120
- end
121
-
122
- ObjectSpace.each_object(Rake::RDocTask) do |rdoc_task|
123
- options = rdoc_task.options
124
- t_option_index = options.index("--title") || options.index("-t")
125
- rdoc_task.options[t_option_index, 2] = [] if t_option_index
126
- rdoc_task.title = "racknga - #{version}"
98
+ end
127
99
  end
128
100
 
129
- task :publish_docs => [:prepare_docs_for_publishing]
130
-
131
-
132
101
  include ERB::Util
133
102
 
134
- def apply_template(file, head, header, footer)
135
- content = File.read(file)
136
- content = content.sub(/lang="en"/, 'lang="ja"')
103
+ def apply_template(content, paths, templates, language)
104
+ content = content.sub(/lang="en"/, "lang=\"#{language}\"")
137
105
 
138
106
  title = nil
139
- content = content.sub(/<title>(.+?)<\/title>/) do
107
+ content = content.sub(/<title>(.+?)<\/title>/m) do
140
108
  title = $1
141
- head.result(binding)
109
+ templates[:head].result(binding)
142
110
  end
143
111
 
144
112
  content = content.sub(/<body(?:.*?)>/) do |body_start|
145
- "#{body_start}\n#{header.result(binding)}\n"
113
+ "#{body_start}\n#{templates[:header].result(binding)}\n"
146
114
  end
147
115
 
148
116
  content = content.sub(/<\/body/) do |body_end|
149
- "\n#{footer.result(binding)}\n#{body_end}"
117
+ "\n#{templates[:footer].result(binding)}\n#{body_end}"
150
118
  end
151
119
 
152
- File.open(file, "w") do |file|
153
- file.print(content)
154
- end
120
+ content
155
121
  end
156
122
 
157
123
  def erb_template(name)
158
- file = File.join("html", "#{name}.html.erb")
124
+ file = File.join("doc/templates", "#{name}.html.erb")
159
125
  template = File.read(file)
160
126
  erb = ERB.new(template, nil, "-")
161
127
  erb.filename = file
162
128
  erb
163
129
  end
164
130
 
165
- task :prepare_docs_for_publishing do
166
- head = erb_template("head")
167
- header = erb_template("header")
168
- footer = erb_template("footer")
169
- Find.find("doc") do |file|
170
- if /\.html\z/ =~ file and /_(?:c|rb)\.html\z/ !~ file
171
- apply_template(file, head, header, footer)
131
+ def rsync_to_rubyforge(spec, source, destination, options={})
132
+ config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
133
+ host = "#{config["username"]}@rubyforge.org"
134
+
135
+ rsync_args = "-av --exclude '*.erb' --chmod=ug+w"
136
+ rsync_args << " --delete" if options[:delete]
137
+ remote_dir = "/var/www/gforge-projects/#{spec.rubyforge_project}/"
138
+ sh("rsync #{rsync_args} #{source} #{host}:#{remote_dir}#{destination}")
139
+ end
140
+
141
+ def rake(*arguments)
142
+ ruby($0, *arguments)
143
+ end
144
+
145
+ namespace :reference do
146
+ translate_languages = [:ja]
147
+ supported_languages = [:en, *translate_languages]
148
+ html_files = FileList[doc_en_dir + "**/*.html"].to_a
149
+
150
+ directory reference_base_dir.to_s
151
+ CLOBBER.include(reference_base_dir.to_s)
152
+
153
+ po_dir = "doc/po"
154
+ pot_file = "#{po_dir}/#{spec.name}.pot"
155
+ namespace :pot do
156
+ directory po_dir
157
+ file pot_file => [po_dir, *html_files] do |t|
158
+ sh("xml2po", "--keep-entities", "--output", t.name, *html_files)
172
159
  end
160
+
161
+ desc "Generates pot file."
162
+ task :generate => pot_file
173
163
  end
174
- end
175
164
 
176
- task :publish_html do
177
- config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
178
- host = "#{config["username"]}@rubyforge.org"
165
+ namespace :po do
166
+ translate_languages.each do |language|
167
+ namespace language do
168
+ po_file = "#{po_dir}/#{language}.po"
169
+
170
+ if File.exist?(po_file)
171
+ file po_file => html_files do |t|
172
+ sh("xml2po", "--keep-entities", "--update", t.name, *html_files)
173
+ end
174
+ else
175
+ file po_file => pot_file do |t|
176
+ sh("msginit",
177
+ "--input=#{pot_file}",
178
+ "--output=#{t.name}",
179
+ "--locale=#{language}")
180
+ end
181
+ end
182
+
183
+ desc "Updates po file for #{language}."
184
+ task :update => po_file
185
+ end
186
+ end
187
+
188
+ desc "Updates po files."
189
+ task :update do
190
+ rake("clobber")
191
+ rake("yard")
192
+ translate_languages.each do |language|
193
+ rake("reference:po:#{language}:update")
194
+ end
195
+ end
196
+ end
197
+
198
+ namespace :translate do
199
+ translate_languages.each do |language|
200
+ po_file = "#{po_dir}/#{language}.po"
201
+ translate_doc_dir = "#{reference_base_dir}/#{language}"
202
+
203
+ desc "Translates documents to #{language}."
204
+ task language => [po_file, reference_base_dir, *html_files] do
205
+ doc_en_dir.find do |path|
206
+ base_path = path.relative_path_from(doc_en_dir)
207
+ translated_path = "#{translate_doc_dir}/#{base_path}"
208
+ if path.directory?
209
+ mkdir_p(translated_path)
210
+ next
211
+ end
212
+ case path.extname
213
+ when ".html"
214
+ sh("xml2po --keep-entities " +
215
+ "--po-file #{po_file} --language #{language} " +
216
+ "#{path} > #{translated_path}")
217
+ else
218
+ cp(path.to_s, translated_path, :preserve => true)
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
224
+
225
+ translate_task_names = translate_languages.collect do |language|
226
+ "reference:translate:#{language}"
227
+ end
228
+ desc "Translates references."
229
+ task :translate => translate_task_names
230
+
231
+ desc "Generates references."
232
+ task :generate => [:yard, :translate]
233
+
234
+ namespace :publication do
235
+ task :prepare do
236
+ supported_languages.each do |language|
237
+ raw_reference_dir = reference_base_dir + language.to_s
238
+ prepared_reference_dir = html_reference_dir + language.to_s
239
+ rm_rf(prepared_reference_dir.to_s)
240
+ head = erb_template("head.#{language}")
241
+ header = erb_template("header.#{language}")
242
+ footer = erb_template("footer.#{language}")
243
+ raw_reference_dir.find do |path|
244
+ relative_path = path.relative_path_from(raw_reference_dir)
245
+ prepared_path = prepared_reference_dir + relative_path
246
+ if path.directory?
247
+ mkdir_p(prepared_path.to_s)
248
+ else
249
+ case path.basename.to_s
250
+ when /(?:file|method|class)_list\.html\z/
251
+ cp(path.to_s, prepared_path.to_s)
252
+ when /\.html\z/
253
+ relative_dir_path = relative_path.dirname
254
+ current_path = relative_dir_path + path.basename
255
+ if current_path.basename.to_s == "index.html"
256
+ current_path = current_path.dirname
257
+ end
258
+ top_path = html_base_dir.relative_path_from(prepared_path.dirname)
259
+ package_path = top_path + spec.name
260
+ paths = {
261
+ :top => top_path,
262
+ :current => current_path,
263
+ :package => package_path,
264
+ }
265
+ templates = {
266
+ :head => head,
267
+ :header => header,
268
+ :footer => footer
269
+ }
270
+ content = apply_template(File.read(path.to_s),
271
+ paths,
272
+ templates,
273
+ language)
274
+ File.open(prepared_path.to_s, "w") do |file|
275
+ file.print(content)
276
+ end
277
+ else
278
+ cp(path.to_s, prepared_path.to_s)
279
+ end
280
+ end
281
+ end
282
+ end
283
+ File.open("#{html_reference_dir}/.htaccess", "w") do |file|
284
+ file.puts("RedirectMatch permanent ^/#{spec.name}/$ " +
285
+ "#{spec.homepage}#{spec.name}/en/")
286
+ end
287
+ end
288
+ end
179
289
 
180
- rsync_args = "-av --exclude '*.erb' --exclude '*.svg' --exclude .svn"
181
- remote_dir = "/var/www/gforge-projects/#{project.rubyforge_name}/"
182
- sh "rsync #{rsync_args} html/ #{host}:#{remote_dir}"
290
+ desc "Upload document to rubyforge."
291
+ task :publish => [:generate, "reference:publication:prepare"] do
292
+ rsync_to_rubyforge(spec, "#{html_reference_dir}/", spec.name)
293
+ end
294
+ end
295
+
296
+ namespace :html do
297
+ desc "Publish HTML to Web site."
298
+ task :publish do
299
+ rsync_to_rubyforge(spec, "#{html_base_dir}/", "")
300
+ end
183
301
  end
184
302
 
303
+ desc "Upload document to rubyforge."
304
+ task :publish => ["reference:publish"]
305
+
306
+ desc "Tag the current revision."
185
307
  task :tag do
186
308
  sh("git tag -a #{version} -m 'release #{version}!!!'")
187
309
  end
188
-
189
- task(:release).prerequisites.reject! {|name| name == "clean"}
@@ -0,0 +1,32 @@
1
+ h1. NEWS
2
+
3
+ h2. 0.9.2: 2011-08-07
4
+
5
+ h3. Improvments
6
+
7
+ * [munin] Supported Passenger 3 support.
8
+ * [munin] Removed Passenger 2 support.
9
+ * [middleware][jsonp] Improved browser compatibility by using
10
+ "text/javascript" for Content-Type.
11
+ * [middleware][cache] Improved checksum robustness by using
12
+ SHA1 instead of MD5.
13
+ * [middleware][cache] Supported 4096 >= length URL.
14
+ * [exception-mail-notifier] Supported limited mailing.
15
+ * [middleware][instance-name] Added.
16
+ * Added NginixAccessLogParser.
17
+ * Documented middlewares.
18
+
19
+ h2. 0.9.1: 2010-11-11
20
+
21
+ * Improved cache validation.
22
+ * Supported caches per User-Agent.
23
+ * Added a JSONP middleware.
24
+ * Added a HTTP Range support middleware.
25
+ * Added a logging access to groogna databsae middleware.
26
+ * Added Munin plugins for Passenger.
27
+ * Changed license to LGPLv2.1 or later from LGPLv2.1.
28
+ * Supported will_paginate.
29
+
30
+ h2. 0.9.0: 2010-07-04
31
+
32
+ * Initial release!
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2010 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2010-2011 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -21,7 +21,13 @@ require 'fileutils'
21
21
  require 'groonga'
22
22
 
23
23
  module Racknga
24
+ # This is a cache database based on groonga. It is used by
25
+ # Racknga::Middleware::Cache.
26
+ #
27
+ # Normally, #purge_old_responses is only used for cache
28
+ # maintenance.
24
29
  class CacheDatabase
30
+ # @param [String] database_path the path for cache database.
25
31
  def initialize(database_path)
26
32
  @database_path = database_path
27
33
  @context = Groonga::Context.new(:encoding => :none)
@@ -40,14 +46,23 @@ module Racknga
40
46
  configurations["default"]
41
47
  end
42
48
 
49
+ # Purges old responses. To clear old caches, you should
50
+ # call this method periodically or after data update.
51
+ #
52
+ # You can call this method by the different
53
+ # process from your Rack application
54
+ # process. (e.g. cron.) It's multi process safe.
43
55
  def purge_old_responses
44
56
  age_modulo = 2 ** 32
45
57
  age = configuration.age
46
58
  previous_age = (age - 1).modulo(age_modulo)
47
59
  configuration.age = (age + 1).modulo(age_modulo)
48
60
 
49
- responses.each do |response|
50
- response.delete if response.age == previous_age
61
+ target_responses = responses.select do |record|
62
+ record.age == previous_age
63
+ end
64
+ target_responses.each do |response|
65
+ response.key.delete
51
66
  end
52
67
  end
53
68