gonzui 1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/AUTHORS.txt +9 -0
  2. data/History.txt +5539 -0
  3. data/Manifest.txt +115 -0
  4. data/PostInstall.txt +17 -0
  5. data/README.rdoc +149 -0
  6. data/Rakefile +28 -0
  7. data/bin/gonzui-db +167 -0
  8. data/bin/gonzui-import +177 -0
  9. data/bin/gonzui-remove +58 -0
  10. data/bin/gonzui-search +68 -0
  11. data/bin/gonzui-server +176 -0
  12. data/bin/gonzui-update +53 -0
  13. data/data/gonzui/catalog/catalog.ja +80 -0
  14. data/data/gonzui/doc/favicon.ico +0 -0
  15. data/data/gonzui/doc/folder.png +0 -0
  16. data/data/gonzui/doc/gonzui.css +279 -0
  17. data/data/gonzui/doc/gonzui.js +111 -0
  18. data/data/gonzui/doc/text.png +0 -0
  19. data/data/gonzuirc.sample +29 -0
  20. data/ext/autopack/autopack.c +88 -0
  21. data/ext/autopack/extconf.rb +3 -0
  22. data/ext/delta/delta.c +147 -0
  23. data/ext/delta/extconf.rb +5 -0
  24. data/ext/texttokenizer/extconf.rb +5 -0
  25. data/ext/texttokenizer/texttokenizer.c +93 -0
  26. data/ext/xmlformatter/extconf.rb +5 -0
  27. data/ext/xmlformatter/xmlformatter.c +207 -0
  28. data/lib/gonzui.rb +59 -0
  29. data/lib/gonzui/apt.rb +193 -0
  30. data/lib/gonzui/bdbdbm.rb +118 -0
  31. data/lib/gonzui/cmdapp.rb +14 -0
  32. data/lib/gonzui/cmdapp/app.rb +175 -0
  33. data/lib/gonzui/cmdapp/search.rb +134 -0
  34. data/lib/gonzui/config.rb +117 -0
  35. data/lib/gonzui/content.rb +19 -0
  36. data/lib/gonzui/dbm.rb +673 -0
  37. data/lib/gonzui/deindexer.rb +162 -0
  38. data/lib/gonzui/delta.rb +49 -0
  39. data/lib/gonzui/extractor.rb +347 -0
  40. data/lib/gonzui/fetcher.rb +309 -0
  41. data/lib/gonzui/gettext.rb +144 -0
  42. data/lib/gonzui/importer.rb +84 -0
  43. data/lib/gonzui/indexer.rb +316 -0
  44. data/lib/gonzui/info.rb +80 -0
  45. data/lib/gonzui/license.rb +100 -0
  46. data/lib/gonzui/logger.rb +48 -0
  47. data/lib/gonzui/monitor.rb +177 -0
  48. data/lib/gonzui/progressbar.rb +235 -0
  49. data/lib/gonzui/remover.rb +38 -0
  50. data/lib/gonzui/searcher.rb +330 -0
  51. data/lib/gonzui/searchquery.rb +235 -0
  52. data/lib/gonzui/searchresult.rb +111 -0
  53. data/lib/gonzui/updater.rb +254 -0
  54. data/lib/gonzui/util.rb +415 -0
  55. data/lib/gonzui/vcs.rb +128 -0
  56. data/lib/gonzui/webapp.rb +25 -0
  57. data/lib/gonzui/webapp/advsearch.rb +123 -0
  58. data/lib/gonzui/webapp/filehandler.rb +24 -0
  59. data/lib/gonzui/webapp/jsfeed.rb +61 -0
  60. data/lib/gonzui/webapp/markup.rb +445 -0
  61. data/lib/gonzui/webapp/search.rb +269 -0
  62. data/lib/gonzui/webapp/servlet.rb +319 -0
  63. data/lib/gonzui/webapp/snippet.rb +155 -0
  64. data/lib/gonzui/webapp/source.rb +37 -0
  65. data/lib/gonzui/webapp/stat.rb +137 -0
  66. data/lib/gonzui/webapp/top.rb +63 -0
  67. data/lib/gonzui/webapp/uri.rb +140 -0
  68. data/lib/gonzui/webapp/webrick.rb +48 -0
  69. data/script/console +10 -0
  70. data/script/destroy +14 -0
  71. data/script/generate +14 -0
  72. data/script/makemanifest.rb +21 -0
  73. data/tasks/extconf.rake +13 -0
  74. data/tasks/extconf/autopack.rake +43 -0
  75. data/tasks/extconf/delta.rake +43 -0
  76. data/tasks/extconf/texttokenizer.rake +43 -0
  77. data/tasks/extconf/xmlformatter.rake +43 -0
  78. data/test/_external_tools.rb +13 -0
  79. data/test/_test-util.rb +142 -0
  80. data/test/foo/Makefile.foo +66 -0
  81. data/test/foo/bar.c +5 -0
  82. data/test/foo/bar.h +6 -0
  83. data/test/foo/foo.c +25 -0
  84. data/test/foo/foo.spec +33 -0
  85. data/test/test_apt.rb +42 -0
  86. data/test/test_autopack_extn.rb +7 -0
  87. data/test/test_bdbdbm.rb +79 -0
  88. data/test/test_cmdapp-app.rb +35 -0
  89. data/test/test_cmdapp-search.rb +99 -0
  90. data/test/test_config.rb +28 -0
  91. data/test/test_content.rb +15 -0
  92. data/test/test_dbm.rb +171 -0
  93. data/test/test_deindexer.rb +50 -0
  94. data/test/test_delta.rb +66 -0
  95. data/test/test_extractor.rb +78 -0
  96. data/test/test_fetcher.rb +75 -0
  97. data/test/test_gettext.rb +50 -0
  98. data/test/test_gonzui.rb +11 -0
  99. data/test/test_helper.rb +10 -0
  100. data/test/test_importer.rb +56 -0
  101. data/test/test_indexer.rb +37 -0
  102. data/test/test_info.rb +82 -0
  103. data/test/test_license.rb +49 -0
  104. data/test/test_logger.rb +60 -0
  105. data/test/test_monitor.rb +23 -0
  106. data/test/test_searcher.rb +37 -0
  107. data/test/test_searchquery.rb +27 -0
  108. data/test/test_searchresult.rb +43 -0
  109. data/test/test_texttokenizer.rb +47 -0
  110. data/test/test_updater.rb +95 -0
  111. data/test/test_util.rb +149 -0
  112. data/test/test_vcs.rb +61 -0
  113. data/test/test_webapp-markup.rb +42 -0
  114. data/test/test_webapp-util.rb +19 -0
  115. data/test/test_webapp-xmlformatter.rb +19 -0
  116. metadata +291 -0
@@ -0,0 +1,309 @@
1
+ #
2
+ # fetcher.rb - fetch contents from various sources
3
+ #
4
+ # Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
5
+ # All rights reserved.
6
+ # This is free software with ABSOLUTELY NO WARRANTY.
7
+ #
8
+ # You can redistribute it and/or modify it under the terms of
9
+ # the GNU General Public License version 2.
10
+ #
11
+
12
+ require 'open-uri'
13
+ require 'webrick/httputils'
14
+ require 'ftools'
15
+
16
+ module Gonzui
17
+ class FetcherError < GonzuiError; end
18
+ class FetchFailed < FetcherError; end
19
+
20
+ module Fetcher
21
+ extend Util
22
+ FetcherRegistory = {}
23
+
24
+ module_function
25
+ def new(config, source_uri, options = {})
26
+ klass = FetcherRegistory[source_uri.scheme]
27
+ if klass.nil?
28
+ raise FetcherError.new("#{source_uri.scheme}: unsupported scheme")
29
+ end
30
+ if source_uri.path.nil?
31
+ raise FetcherError.new("#{source_uri.to_s}: malformed URI")
32
+ end
33
+ fetcher = klass.new(config, source_uri, options)
34
+ if fetcher.need_extraction? # fallback to FileFetcher
35
+ extractor = fetcher.get_extractor
36
+ directory = extractor.extract
37
+ fetcher.finish
38
+
39
+ source_uri = URI.from_path(directory)
40
+ fetcher = FileFetcher.new(config, source_uri, options)
41
+ fetcher.add_finishing_proc(lambda { extractor.clean })
42
+ end
43
+ return fetcher
44
+ end
45
+
46
+ def register(klass)
47
+ FetcherRegistory[klass.scheme] = klass
48
+ end
49
+ end
50
+
51
+ class AbstractFetcher
52
+ include Util
53
+
54
+ def initialize(config, source_uri, options = {})
55
+ @config = config
56
+ @source_uri = source_uri
57
+ @exclude_pattern = (options[:exclude_pattern] or @config.exclude_pattern)
58
+ @finishing_procs = []
59
+ @base_uri = source_uri
60
+ end
61
+
62
+ public
63
+ def add_finishing_proc (proc)
64
+ @finishing_procs.push(proc)
65
+ end
66
+
67
+ def collect
68
+ raise NotImplementedError.new
69
+ end
70
+
71
+ def exclude?(relative_path)
72
+ @exclude_pattern.match(relative_path)
73
+ end
74
+
75
+ def fetch(relative_path)
76
+ raise NotImplementedError.new
77
+ end
78
+
79
+ def finish
80
+ @finishing_procs.each {|proc| proc.call }
81
+ end
82
+
83
+ def get_extractor
84
+ raise NotImplementedError.new
85
+ end
86
+
87
+ def need_extraction?
88
+ raise NotImplementedError.new
89
+ end
90
+
91
+ def package_name
92
+ File.basename(@base_uri.path)
93
+ end
94
+ end
95
+
96
+ class FileFetcher < AbstractFetcher
97
+ def self.scheme
98
+ "file"
99
+ end
100
+
101
+ def initialize(config, source_uri, options)
102
+ super(config, source_uri, options)
103
+ begin
104
+ File.ftype(source_uri.path)
105
+ rescue => e
106
+ raise FetchFailed.new(e.message)
107
+ end
108
+ end
109
+
110
+ private
111
+ def restore_path(relative_path)
112
+ File.join(@base_uri.path, relative_path)
113
+ end
114
+
115
+ public
116
+ def need_extraction?
117
+ not File.directory?(@source_uri.path)
118
+ end
119
+
120
+ def get_extractor
121
+ return Extractor.new(@config, @source_uri.path)
122
+ end
123
+
124
+ def fetch(relative_path)
125
+ path = restore_path(relative_path)
126
+ content = File.read(path)
127
+ mtime = File.mtime(path)
128
+ return Content.new(content, mtime, path)
129
+ end
130
+
131
+ def collect
132
+ directory = @base_uri.path
133
+ relative_paths = []
134
+ Dir.all_files(directory).map {|file_name|
135
+ next if exclude?(file_name)
136
+ relative_path = File.relative_path(file_name, directory)
137
+ relative_paths.push(relative_path)
138
+ }
139
+ return relative_paths
140
+ end
141
+
142
+ Fetcher.register(self)
143
+ end
144
+
145
+ # FIXME: very ad hoc implementation
146
+ class HTTPFetcher < AbstractFetcher
147
+ include TemporaryDirectoryUtil
148
+ def self.scheme
149
+ "http"
150
+ end
151
+
152
+ def initialize(config, source_uri, options)
153
+ super(config, source_uri, options)
154
+ begin
155
+ open(source_uri.to_s) {|f|
156
+ @content = f.read
157
+ @content_type = f.content_type
158
+ @base_uri = f.base_uri
159
+ }
160
+ rescue OpenURI::HTTPError => e
161
+ raise FetchFailed.new("#{source_uri.to_s}: #{e.message}")
162
+ end
163
+
164
+ # http://example.com/foo/index.html => http://example.com/foo/
165
+ unless /\/$/.match(@base_uri.path) #/
166
+ @base_uri.path = File.dirname(@base_uri.path) + "/"
167
+ end
168
+ set_temporary_directory(@config.temporary_directory)
169
+ end
170
+
171
+ def restore_uri(relative_path)
172
+ u = @base_uri.to_s + relative_path
173
+ URI.parse(u)
174
+ end
175
+
176
+ public
177
+ def need_extraction?
178
+ @content_type != "text/html"
179
+ end
180
+
181
+ def get_extractor
182
+ prepare_temporary_directory
183
+ tmp_name = File.join(self.temporary_directory,
184
+ File.basename(@source_uri.path))
185
+ File.open(tmp_name, "w") {|f| f.write(@content) }
186
+ add_finishing_proc(lambda { clean_temporary_directory })
187
+ return Extractor.new(@config, tmp_name)
188
+ end
189
+
190
+ def fetch(relative_path)
191
+ uri = restore_uri(relative_path)
192
+ content = mtime = nil
193
+ open(uri.to_s) {|f|
194
+ content = f.read
195
+ mtime = f.last_modified
196
+ }
197
+ return Content.new(content, mtime)
198
+ end
199
+
200
+ def collect
201
+ relative_paths = []
202
+ @content.scan(/href=(["'])(.*?)\1/i).each {|qmark, link|
203
+ u = URI.parse(link)
204
+ next if u.path.nil?
205
+ u.path.chomp!("/")
206
+ next unless u.relative?
207
+ next if /^\./.match(u.path)
208
+ next if exclude?(u.path)
209
+ relative_paths.push(u.path)
210
+ }
211
+ return relative_paths
212
+ end
213
+
214
+ Fetcher.register(self)
215
+ end
216
+
217
+ class AptFetcher < AbstractFetcher
218
+ def self.scheme
219
+ "apt-get"
220
+ end
221
+
222
+ def need_extraction?
223
+ true
224
+ end
225
+
226
+ def get_extractor
227
+ package_name = @source_uri.path.prechop
228
+ return AptGet.new(@config, package_name)
229
+ end
230
+
231
+ Fetcher.register(self)
232
+ end
233
+
234
+ class CVSFetcher < AbstractFetcher
235
+ def self.scheme
236
+ "cvs"
237
+ end
238
+
239
+ def need_extraction?
240
+ true
241
+ end
242
+
243
+ def get_extractor
244
+ query = WEBrick::HTTPUtils.parse_query(@source_uri.query)
245
+ prefix = query["prefix"]
246
+ mozule = query["module"]
247
+ assert_non_nil(mozule)
248
+ root = @source_uri.path
249
+ root = @source_uri.host + ":" + root if @source_uri.host
250
+ root = prefix + "@" + root if prefix
251
+ return CVS.new(@config, root, mozule)
252
+ end
253
+
254
+ Fetcher.register(self)
255
+ end
256
+
257
+ class SubversionFetcher < AbstractFetcher
258
+ def self.scheme
259
+ "svn"
260
+ end
261
+
262
+ def need_extraction?
263
+ true
264
+ end
265
+
266
+ def get_extractor
267
+ query = WEBrick::HTTPUtils.parse_query(@source_uri.query)
268
+ mozule = query["module"]
269
+ assert_non_nil(mozule)
270
+ uri = @source_uri.dup
271
+ uri.scheme = query["original_scheme"] if query["original_scheme"]
272
+ uri.query = nil
273
+ root = uri.to_s
274
+ # FIXME: kludge for replacing file:/home/... ->
275
+ # file:///home/... because subversion doesn't allow
276
+ # the former URI.
277
+ root.gsub!(%r!^file:/+!, "file:///") if uri.scheme == "file"
278
+ return Subversion.new(@config, root, mozule)
279
+ end
280
+
281
+ Fetcher.register(self)
282
+ end
283
+
284
+ class GitFetcher < AbstractFetcher
285
+ def self.scheme
286
+ "git"
287
+ end
288
+
289
+ def need_extraction?
290
+ true
291
+ end
292
+
293
+ def get_extractor
294
+ query = WEBrick::HTTPUtils.parse_query(@source_uri.query)
295
+ mozule = query["module"]
296
+ uri = @source_uri.dup
297
+ uri.scheme = query["original_scheme"] if query["original_scheme"]
298
+ uri.query = nil
299
+ root = uri.to_s
300
+ # FIXME: kludge for replacing file:/home/... ->
301
+ # file:///home/... because git doesn't allow
302
+ # the former URI.
303
+ root.gsub!(%r!^file:/+!, "file:///") if uri.scheme == "file"
304
+ return Git.new(@config, root, mozule)
305
+ end
306
+
307
+ Fetcher.register(self)
308
+ end
309
+ end
@@ -0,0 +1,144 @@
1
+ #
2
+ # gettext.rb - a simple gettext-like module
3
+ #
4
+ # Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
5
+ # All rights reserved.
6
+ # This is free software with ABSOLUTELY NO WARRANTY.
7
+ #
8
+ # You can redistribute it and/or modify it under the terms of
9
+ # the GNU General Public License version 2.
10
+ #
11
+
12
+ module Gonzui
13
+ module GetText
14
+ def gettext(text)
15
+ return text unless @gettext_catalog
16
+ return (@gettext_catalog[text] or text)
17
+ end
18
+ alias :_ :gettext
19
+
20
+ def gettext_noop(text)
21
+ text
22
+ end
23
+ alias :N_ :gettext_noop
24
+
25
+ def set_catalog(catalog)
26
+ @gettext_catalog = catalog
27
+ end
28
+
29
+ def load_catalog(file_name)
30
+ return eval(File.read(file_name))
31
+ end
32
+ end
33
+
34
+ class CatalogRepository
35
+ include GetText
36
+
37
+ def initialize(directory)
38
+ @catalogs = {}
39
+ Dir.entries(directory).each {|entry|
40
+ file_name = File.join(directory, entry)
41
+ if m = /^catalog\.([\w.-]+)$/.match(File.basename(file_name))
42
+ lang = m[1]
43
+ catalog = load_catalog(file_name)
44
+ @catalogs[lang] = catalog
45
+ end
46
+ }
47
+ @catalogs["en"] = Hash.new {|h, k| k }
48
+ end
49
+
50
+ public
51
+ def choose(lang_name)
52
+ @catalogs[lang_name]
53
+ end
54
+
55
+ def each
56
+ @catalogs.each {|lang_name, catalog|
57
+ yield(lang_name, catalog)
58
+ }
59
+ end
60
+ end
61
+
62
+
63
+ class CatalogValidator
64
+ def initialize(source_file_name, messages)
65
+ @source_file_name = source_file_name
66
+ @gettext_catalog = messages
67
+ @error_messages = []
68
+ end
69
+ attr_reader :error_messages
70
+
71
+ def read_file_with_numbering(file_name)
72
+ content = ''
73
+ File.open(file_name).each_with_index {|line, idx|
74
+ lineno = idx + 1
75
+ content << line.gsub(/\bN?_\(/, "_[#{lineno}](")
76
+ }
77
+ content
78
+ end
79
+
80
+ def collect_messages(content)
81
+ messages = []
82
+ while content.sub!(/\bN?_\[(\d+)\]\(("(?:\\"|.)*?").*?\)/m, "")
83
+ lineno = $1.to_i
84
+ message = eval($2)
85
+ messages.push([lineno, message])
86
+ end
87
+ messages
88
+ end
89
+
90
+ def validate
91
+ @gettext_catalog or return
92
+ content = read_file_with_numbering(@source_file_name)
93
+ messages = collect_messages(content)
94
+ messages.each {|lineno, message|
95
+ translated_message = @gettext_catalog[message]
96
+ if not translated_message
97
+ message =
98
+ sprintf("%s:%d: %s", @source_file_name, lineno, message.inspect)
99
+ @error_messages.push(message)
100
+ elsif message.count("%") != translated_message.count("%")
101
+ message = sprintf("%s:%d: %s => # of %% mismatch.",
102
+ @source_file_name,
103
+ lineno, message.inspect, translated_message)
104
+ @error_messages.push(message)
105
+ end
106
+ }
107
+ end
108
+
109
+ def ok?
110
+ @error_messages.empty?
111
+ end
112
+ end
113
+ end
114
+
115
+ if __FILE__ == $0
116
+ include Gonzui
117
+ include Gonzui::GetText
118
+
119
+ def main
120
+ if ARGV.length < 2
121
+ puts "usage: ruby catalog-validator.rb <catalog directory> <source...>"
122
+ exit
123
+ end
124
+
125
+ catalog_directory = ARGV.shift
126
+ catalog_repository = CatalogRepository.new(catalog_directory)
127
+
128
+ ok = true
129
+ catalog_repository.each {|lang_name, catalog|
130
+ set_catalog(catalog)
131
+ ARGV.each {|source_file|
132
+ validator = CatalogValidator.new(source_file, catalog)
133
+ validator.validate
134
+ validator.error_messages.each {|message|
135
+ printf("%s: %s\n", lang_name, message)
136
+ }
137
+ ok = (ok and validator.ok?)
138
+ }
139
+ }
140
+ if ok then exit else exit(1) end
141
+ end
142
+
143
+ main
144
+ end