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,162 @@
1
+ #
2
+ # deindexer.rb - deindexer implementation
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 'ftools'
13
+ require 'langscan'
14
+
15
+ module Gonzui
16
+ class Deindexer
17
+ include Util
18
+
19
+ def initialize(config, dbm, normalized_path)
20
+ @config = config
21
+ @dbm = dbm
22
+ @normalized_path = normalized_path
23
+ @path_id = @dbm.get_path_id(@normalized_path)
24
+ @package_id = @dbm.get_package_id_from_path_id(@path_id)
25
+ @package_name = @dbm.get_package_name(@package_id)
26
+ end
27
+
28
+ private
29
+ def deindex_content
30
+ word_ids = @dbm.get_word_ids(@path_id)
31
+ word_ids.each {|word_id|
32
+ package_word_id = AutoPack.pack_id2(@package_id, word_id)
33
+ @dbm.pkgwordid_pathids.delete_both(package_word_id, @path_id)
34
+ unless @dbm.pkgwordid_pathids.has_key?(package_word_id)
35
+ @dbm.wordid_pkgids.delete_both(word_id, @package_id)
36
+ end
37
+
38
+ unless @dbm.wordid_pkgids.has_key?(word_id)
39
+ word = @dbm.wordid_word[word_id]
40
+ assert_non_nil(word)
41
+ @dbm.wordid_word.delete(word_id)
42
+ @dbm.word_wordid.delete(word)
43
+ @dbm.decrease_counter(:nwords)
44
+ end
45
+ path_word_id = AutoPack.pack_id2(@path_id, word_id)
46
+ @dbm.pathwordid_info.delete(path_word_id)
47
+ }
48
+ @dbm.pathid_wordids.delete(@path_id)
49
+ @dbm.pathid_bols.delete(@path_id)
50
+ end
51
+
52
+ def remove_digest
53
+ format_id = @dbm.get_format_id_from_path_id(@path_id)
54
+ digest = @dbm.get_digest(@path_id)
55
+
56
+ format_abbrev = @dbm.get_format_abbrev(format_id)
57
+ content = @dbm.get_content(@path_id)
58
+ @dbm.pathid_digest.delete(@path_id)
59
+ end
60
+
61
+ def remove_property(get_id, get_abbrev, get_name, make_key, get_ncontents,
62
+ counter_name, abbr_id, id_abbr, id_name)
63
+ id = @dbm.send(get_id, @path_id)
64
+ abbrev = @dbm.send(get_abbrev, id)
65
+ @dbm.decrease_counter(@dbm.send(make_key, abbrev))
66
+ ncontents = @dbm.send(get_ncontents, id)
67
+ if ncontents == 0
68
+ name = @dbm.send(get_name, id)
69
+ @dbm.send(id_name).delete(id)
70
+ @dbm.send(id_abbr).delete(id)
71
+ @dbm.send(abbr_id).delete(abbrev)
72
+ @dbm.decrease_counter(counter_name)
73
+ end
74
+ end
75
+
76
+ def remove_format
77
+ remove_property(:get_format_id_from_path_id,
78
+ :get_format_abbrev,
79
+ :get_format_name,
80
+ :make_ncontents_by_format_key,
81
+ :get_ncontents_by_format_id,
82
+ :nformats,
83
+ :fabbr_fmtid,
84
+ :fmtid_fabbr,
85
+ :fmtid_fmt)
86
+ end
87
+
88
+ def remove_license
89
+ remove_property(:get_license_id_from_path_id,
90
+ :get_license_abbrev,
91
+ :get_license_name,
92
+ :make_ncontents_by_license_key,
93
+ :get_ncontents_by_license_id,
94
+ :nlicenses,
95
+ :labbr_lcsid,
96
+ :lcsid_labbr,
97
+ :lcsid_lcs)
98
+ end
99
+
100
+ def remove_package_if_necessary
101
+ return unless package_empty?
102
+ @dbm.pkg_pkgid.delete(@package_name)
103
+ @dbm.pkgid_pkg.delete(@package_id)
104
+ @dbm.pkgid_fmtids.delete(@package_id)
105
+ @dbm.pkgid_lcsids.delete(@package_id)
106
+ @dbm.pkgid_src.delete(@package_id)
107
+ @dbm.pkgid_options.delete(@package_id)
108
+ @dbm.decrease_counter(:npackages)
109
+ end
110
+
111
+ def remove_path
112
+ path = @dbm.get_path(@path_id)
113
+ @dbm.path_pathid.delete(@normalized_path)
114
+ @dbm.pathid_path.delete(@path_id)
115
+ @dbm.pkgid_pathids.delete_both(@package_id, @path_id)
116
+ end
117
+
118
+ def remove_content_common
119
+ remove_format
120
+ remove_license
121
+ @dbm.pathid_content.delete(@path_id)
122
+ @dbm.pathid_pkgid.delete(@path_id)
123
+ @dbm.pathid_info.delete(@path_id)
124
+ @dbm.pathid_hash.delete(@path_id)
125
+ @dbm.decrease_counter(:ncontents)
126
+ vprintf("removed: %s", @normalized_path)
127
+ end
128
+
129
+ def remove_binary_content
130
+ remove_content_common
131
+ end
132
+
133
+ def remove_indexed_content
134
+ deindex_content
135
+ remove_digest
136
+ nlines = @dbm.get_content_info(@path_id).nlines
137
+ @dbm.decrease_counter(:ncontents_indexed)
138
+ @dbm.decrease_counter(:nlines_indexed, nlines)
139
+
140
+ remove_content_common
141
+ end
142
+
143
+ def remove_content
144
+ if @dbm.binary_content?(@path_id)
145
+ remove_binary_content
146
+ else
147
+ remove_indexed_content
148
+ end
149
+ end
150
+
151
+ def package_empty?
152
+ @dbm.get_path_ids(@package_id).empty?
153
+ end
154
+
155
+ public
156
+ def deindex
157
+ remove_path
158
+ remove_content
159
+ remove_package_if_necessary
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,49 @@
1
+ #
2
+ # delta.rb - byte-oriented delta compression implementation
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 'gonzui/delta.so'
13
+
14
+ module Gonzui
15
+ module DeltaDumper
16
+ PACK_FORMAT = "w*"
17
+
18
+ module_function
19
+ def dump_tuples(klass, list)
20
+ encode_tuples(list, klass::DeltaSize, klass::UnitSize)
21
+ return list.pack(PACK_FORMAT)
22
+ end
23
+
24
+ def undump_tuples(klass, dump)
25
+ list = dump.unpack(PACK_FORMAT)
26
+ decode_tuples(list, klass::DeltaSize, klass::UnitSize)
27
+ #
28
+ # Make an array of arrays for convinence of the caller
29
+ # [1,2,3,4,5,6] => [[1,2], [3,4], [5,6] if UnitSize is 2
30
+ #
31
+ values = (0...(list.length / klass::UnitSize)).map {|i|
32
+ list[i * klass::UnitSize, klass::UnitSize]
33
+ }
34
+ return values
35
+ end
36
+
37
+ def dump_fixnums(list)
38
+ encode_fixnums(list).pack(PACK_FORMAT)
39
+ end
40
+
41
+ def undump_fixnums(dump)
42
+ decode_fixnums(dump.unpack(PACK_FORMAT))
43
+ end
44
+
45
+ alias dump_ids dump_fixnums
46
+ alias undump_ids undump_fixnums
47
+ module_function :dump_ids, :undump_ids
48
+ end
49
+ end
@@ -0,0 +1,347 @@
1
+ #
2
+ # extractor.rb - a package extraction library
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 'find'
13
+ require 'ftools'
14
+
15
+ module Gonzui
16
+ class ExtractorError < GonzuiError; end
17
+
18
+ module Extractor
19
+ extend Util
20
+ ExtractorRegistry = {}
21
+
22
+ module_function
23
+ def extnames
24
+ ExtractorRegistry.keys
25
+ end
26
+
27
+ def get_archive_extname(file_name)
28
+ ExtractorRegistry.keys.each {|extname|
29
+ pattern = Regexp.new(Regexp.quote(extname) + '$') #'
30
+ return extname if pattern.match(file_name)
31
+ }
32
+ return nil
33
+ end
34
+
35
+ def supported_file?(file_name)
36
+ ExtractorRegistry.include?(get_archive_extname(file_name))
37
+ end
38
+
39
+ def suppress_archive_extname(file_name)
40
+ extname = get_archive_extname(file_name)
41
+ pattern = Regexp.new(Regexp.quote(extname) + '$') #'
42
+ return file_name.gsub(pattern, "")
43
+ end
44
+
45
+ def new(config, file_name)
46
+ extname = get_archive_extname(file_name)
47
+ if klass = ExtractorRegistry[extname]
48
+ return klass.new(config, file_name)
49
+ else
50
+ raise ExtractorError.new("#{extname}: unsupported archive")
51
+ end
52
+ end
53
+
54
+ def register(klass)
55
+ klass.commands.each {|command|
56
+ return unless command_exist?(command)
57
+ }
58
+ klass.extnames.each {|extname|
59
+ assert(!ExtractorRegistry.include?(extname))
60
+ ExtractorRegistry[extname] = klass
61
+ }
62
+ end
63
+ end
64
+
65
+ class AbstractExtractor
66
+ include Util
67
+ include TemporaryDirectoryUtil
68
+
69
+ def initialize(config, file_name)
70
+ @config = config
71
+ @archive_directory = nil
72
+ @file_name = file_name
73
+ @extracted_files = []
74
+ raise ExtractorError.new("#{@file_name}: no such file") unless
75
+ File.file?(@file_name)
76
+ set_temporary_directory(config.temporary_directory)
77
+ end
78
+
79
+ private
80
+ def run_extract_command(command_line, file_name)
81
+ cd = "cd"
82
+ cd << " /d" if (/mswin|mingw|bccwin/ =~ RUBY_PLATFORM)
83
+ command_line = sprintf("#{cd} %s && %s",
84
+ shell_escape(self.temporary_directory),
85
+ command_line)
86
+ status = system(command_line)
87
+ raise ExtractorError.new("#{file_name}: unable to extract a file") if
88
+ status == false
89
+ end
90
+
91
+ # Well-mannered archive doesn't scatter files when extracted.
92
+ def has_single_directory?(directory)
93
+ entries = Dir.entries_without_dots(directory)
94
+ entries.length == 1 and
95
+ File.directory?(File.join(directory, entries.first))
96
+ end
97
+
98
+ # Gather scattered files in to a single directory.
99
+ def arrange_extracted_files
100
+ package_name =
101
+ Extractor.suppress_archive_extname(File.basename(@file_name))
102
+ new_directory = File.join(self.temporary_directory, package_name)
103
+
104
+ if has_single_directory?(self.temporary_directory)
105
+ entries = Dir.entries_without_dots(self.temporary_directory)
106
+ entry = entries.first
107
+ old_directory = File.join(self.temporary_directory, entry)
108
+ if old_directory != new_directory
109
+ File.rename(old_directory, new_directory)
110
+ end
111
+ return
112
+ end
113
+
114
+ entries = Dir.entries_without_dots(self.temporary_directory)
115
+ tmp_name = entries.max || 'tmp'
116
+ tmp_name += '.tmp'
117
+ tmp_directory = File.join(self.temporary_directory, tmp_name)
118
+
119
+ File.mkpath(tmp_directory)
120
+
121
+ entries.each {|entry|
122
+ from = File.join(self.temporary_directory, entry)
123
+ to = File.join(tmp_directory, entry)
124
+ File.rename(from, to)
125
+ }
126
+ File.rename(tmp_directory, new_directory)
127
+ end
128
+
129
+ def raise_error_if_empty_archive?
130
+ entries = Dir.entries_without_dots(self.temporary_directory)
131
+ raise ExtractorError.new("#{@file_name}: empty package") if
132
+ entries.length == 0
133
+ end
134
+
135
+ def get_archive_directory
136
+ unless has_single_directory?(self.temporary_directory)
137
+ raise "#{@file_name}: is not well extracted"
138
+ end
139
+ entry = Dir.entries_without_dots(self.temporary_directory).first
140
+ return File.join(self.temporary_directory, entry)
141
+ end
142
+
143
+ public
144
+ def extract
145
+ prepare_temporary_directory
146
+ begin
147
+ do_extract
148
+ FileUtils.fix_permission(self.temporary_directory)
149
+ raise_error_if_empty_archive?
150
+ arrange_extracted_files
151
+ return get_archive_directory
152
+ rescue ExtractorError => e
153
+ clean_temporary_directory
154
+ raise(e)
155
+ end
156
+ end
157
+
158
+ def clean
159
+ clean_temporary_directory
160
+ end
161
+ end
162
+
163
+ class TarGzipExtractor < AbstractExtractor
164
+ def self.commands
165
+ ["tar", "gzip"]
166
+ end
167
+
168
+ def self.extnames
169
+ [".tar.gz", ".tgz"]
170
+ end
171
+
172
+ def do_extract
173
+ command_line = sprintf("gzip -d -c %s | tar xf -",
174
+ shell_escape(File.expand_path(@file_name)))
175
+ run_extract_command(command_line, @file_name)
176
+ end
177
+
178
+ Extractor.register(self)
179
+ end
180
+
181
+ class TarBzip2Extractor < AbstractExtractor
182
+ def self.commands
183
+ ["tar", "bzip2"]
184
+ end
185
+
186
+ def self.extnames
187
+ [".tar.bz2"]
188
+ end
189
+
190
+ def do_extract
191
+ command_line = sprintf("bzip2 -d -c %s | tar xf -",
192
+ shell_escape(File.expand_path(@file_name)))
193
+ run_extract_command(command_line, @file_name)
194
+ end
195
+
196
+ Extractor.register(self)
197
+ end
198
+
199
+ class TarCompressExtractor < AbstractExtractor
200
+ def self.commands
201
+ ["tar", "uncompress"]
202
+ end
203
+
204
+ def self.extnames
205
+ [".tar.Z"]
206
+ end
207
+
208
+ def do_extract
209
+ command_line = sprintf("uncompress -c %s | tar xf -",
210
+ shell_escape(File.expand_path(@file_name)))
211
+ run_extract_command(command_line, @file_name)
212
+ end
213
+
214
+ Extractor.register(self)
215
+ end
216
+
217
+ class ZipExtractor < AbstractExtractor
218
+ def self.commands
219
+ ["unzip"]
220
+ end
221
+
222
+ def self.extnames
223
+ [".zip"]
224
+ end
225
+
226
+ def do_extract
227
+ command_line = sprintf("unzip -q %s",
228
+ shell_escape(File.expand_path(@file_name)))
229
+ run_extract_command(command_line, @file_name)
230
+ end
231
+
232
+ Extractor.register(self)
233
+ end
234
+
235
+ class TarExtractor < AbstractExtractor
236
+ def self.commands
237
+ ["tar"]
238
+ end
239
+
240
+ def self.extnames
241
+ [".tar"]
242
+ end
243
+
244
+ def do_extract
245
+ command_line = sprintf("tar xf %s",
246
+ shell_escape(File.expand_path(@file_name)))
247
+ run_extract_command(command_line, @file_name)
248
+ end
249
+
250
+ Extractor.register(self)
251
+ end
252
+
253
+ class LZHExtractor < AbstractExtractor
254
+ def self.commands
255
+ ["lha"]
256
+ end
257
+
258
+ def self.extnames
259
+ [".lzh"]
260
+ end
261
+
262
+ def do_extract
263
+ command_line = sprintf("lha -eq %s",
264
+ shell_escape(File.expand_path(@file_name)))
265
+ run_extract_command(command_line, @file_name)
266
+ end
267
+
268
+ Extractor.register(self)
269
+ end
270
+
271
+ class SRPMExtractor < AbstractExtractor
272
+ def self.commands
273
+ ["rpm", "rpmbuild"]
274
+ end
275
+
276
+ def self.extnames
277
+ [".src.rpm"]
278
+ end
279
+
280
+ RPMTemporaryDirectories = ["BUILD", "SOURCES", "SPECS"]
281
+ def prepare_rpm_directories
282
+ RPMTemporaryDirectories.each {|dirname|
283
+ Dir.mkdir(File.join(self.temporary_directory, dirname))
284
+ }
285
+ end
286
+
287
+ def clean_rpm_directories
288
+ RPMTemporaryDirectories.each {|dirname|
289
+ path = File.join(self.temporary_directory, dirname)
290
+ FileUtils.rm_rff(path)
291
+ }
292
+ end
293
+
294
+ def find_spec_file(spec_directory)
295
+ base_name = Dir.entries_without_dots(spec_directory).first
296
+ raise ExtractorError.new("spec file not found") unless
297
+ File.extname(base_name) == ".spec"
298
+ return File.join(spec_directory, base_name)
299
+ end
300
+
301
+ def do_extract_internal
302
+ options = "--nodeps --rmsource"
303
+ common = sprintf("rpmbuild --define '_topdir %s' %s",
304
+ self.temporary_directory, options)
305
+ command_line = sprintf("rpm --define '_topdir %s' -i %s",
306
+ self.temporary_directory,
307
+ shell_escape(File.expand_path(@file_name)))
308
+ status = system(command_line)
309
+ raise ExtractorError.new("rpm command failed") if status == false
310
+ spec_directory = File.join(self.temporary_directory, "SPECS")
311
+ spec_file_name = find_spec_file(spec_directory)
312
+ command_line = sprintf("%s -bp %s", common, shell_escape(spec_file_name))
313
+ # FIXME: --target=i686 is a kludge for ExclusiveArch
314
+ command_line << sprintf("|| %s --target=i686 -bp %s",
315
+ common, shell_escape(spec_file_name))
316
+ unless @config.verbose
317
+ command_line = sprintf("(%s) >/dev/null 2>&1", command_line)
318
+ end
319
+ run_extract_command(command_line, @file_name)
320
+
321
+ build_directory = File.join(self.temporary_directory, "BUILD")
322
+ unless has_single_directory?(build_directory)
323
+ raise ExtractorError.new("BUILD should contain a single directory")
324
+ end
325
+ base_name = Dir.entries_without_dots(build_directory).first
326
+ package_name = File.basename(@file_name, ".src.rpm")
327
+ src = File.join(build_directory, base_name)
328
+ dest = File.join(self.temporary_directory, package_name)
329
+ File.rename(src, dest)
330
+
331
+ unless FileTest.exist?(File.join(dest, File.basename(spec_file_name)))
332
+ FileUtils.mv(spec_file_name, dest)
333
+ end
334
+ end
335
+
336
+ def do_extract
337
+ prepare_rpm_directories
338
+ begin
339
+ do_extract_internal
340
+ ensure
341
+ clean_rpm_directories
342
+ end
343
+ end
344
+
345
+ Extractor.register(self)
346
+ end
347
+ end