| 15 | | def prompt(msg) |
| 16 | | STDERR.print "#{msg} [Yna]: " |
| 17 | | while true |
| 18 | | case STDIN.gets.chomp! |
| 19 | | when /^(y(es)?)?$/i: return true |
| 20 | | when /^no?$/i: return false |
| 21 | | when /^a(bort)?$/i: fail('aborted') |
| 22 | | else |
| 23 | | STDERR.print "Sorry, I don't understand. Please type y, n or a: " |
| 24 | | end |
| 25 | | end |
| 26 | | end |
| 27 | | |
| 28 | | windows = (RUBY_PLATFORM =~ /win/) rescue nil |
| 29 | | SUDO = windows ? "" : "sudo " |
| 30 | | |
| 31 | | |
| 32 | | task :default => 'test:unit' |
| 33 | | #task :default => :build do |
| | 31 | EXT = "ferret_ext.so" |
| | 32 | EXT_SRC = FileList["../c/src/*.[c]", "../c/include/*.h", |
| | 33 | "../c/lib/libstemmer_c/src_c/*.[ch]", |
| | 34 | "../c/lib/libstemmer_c/runtime/*.[ch]", |
| | 35 | "../c/lib/libstemmer_c/libstemmer/*.[ch]", |
| | 36 | "../c/lib/libstemmer_c/include/libstemmer.h"] |
| | 37 | EXT_SRC.exclude('../**/ind.[ch]') |
| | 38 | |
| | 39 | EXT_SRC_DEST = EXT_SRC.map {|fn| File.join("ext", File.basename(fn))} |
| | 40 | SRC = (FileList["ext/*.[ch]"] + EXT_SRC_DEST).uniq |
| | 41 | |
| | 42 | CLEAN.include(FileList['**/*.o', '**/*.obj', 'InstalledFiles', |
| | 43 | '.config', 'ext/cferret.c']) |
| | 44 | CLOBBER.include(FileList['ext/*.so'], 'ext/Makefile', EXT_SRC_DEST) |
| | 45 | POLISH = Rake::FileList.new.include(FileList['**/*.so'], 'ext/Makefile') |
| | 46 | |
| | 47 | desc "Clean specifically for the release." |
| | 48 | task :polish => [:clean] do |
| | 49 | POLISH.each { |fn| rm_r fn rescue nil } |
| | 50 | end |
| | 51 | |
| | 52 | desc "Run tests with Valgrind" |
| | 53 | task :valgrind do |
| | 54 | sh "valgrind --gen-suppressions=yes --suppressions=ferret_valgrind.supp " + |
| | 55 | "--leak-check=yes --show-reachable=yes -v ruby test/test_all.rb" |
| | 56 | #sh "valgrind --suppressions=ferret_valgrind.supp " + |
| | 57 | # "--leak-check=yes --show-reachable=yes -v ruby test/unit/index/tc_index_reader.rb" |
| | 58 | #valgrind --gen-suppressions=yes --suppressions=ferret_valgrind.supp --leak-check=yes --show-reachable=yes -v ruby test/test_all.rb |
| | 59 | end |
| | 60 | |
| | 61 | task :default => :test_all |
| | 62 | #task :default => :ext do |
| 37 | | BZLIB_SRC = FileList["../c/lib/bzlib/*.h"] + |
| 38 | | FileList["../c/lib/bzlib/*.c"].map do |fn| |
| 39 | | fn.gsub(%r{/([^/]*.c)}, '/BZ_\1') |
| 40 | | end |
| 41 | | ############################################################################## |
| 42 | | # Building |
| 43 | | ############################################################################## |
| 44 | | |
| 45 | | task :build => 'build:compile' |
| 46 | | namespace :build do |
| 47 | | EXT = "ferret_ext.so" |
| 48 | | # Note: libstemmer.[h] is necessary so that the file isn't included when it |
| 49 | | # doesn't exist. It needs to have one regular expression element. |
| 50 | | EXT_SRC = FileList["../c/src/*.[ch]", "../c/include/*.h", |
| 51 | | "../c/lib/bzlib/*.[ch]", |
| 52 | | "../c/lib/libstemmer_c/src_c/*.[ch]", |
| 53 | | "../c/lib/libstemmer_c/runtime/*.[ch]", |
| 54 | | "../c/lib/libstemmer_c/libstemmer/*.[ch]", |
| 55 | | "../c/lib/libstemmer_c/include/libstemmer.[h]"] |
| 56 | | EXT_SRC.exclude('../c/**/ind.[ch]', |
| 57 | | '../c/**/symbol.[ch]', |
| 58 | | '../c/include/threading.h', |
| 59 | | '../c/include/scanner.h', |
| 60 | | '../c/include/internal.h', |
| 61 | | '../c/src/lang.c', |
| 62 | | '../c/include/lang.h') |
| 63 | | |
| 64 | | EXT_SRC_MAP = {} |
| 65 | | EXT_SRC_DEST = EXT_SRC.map do |fn| |
| 66 | | ext_fn = File.join("ext", File.basename(fn)) |
| 67 | | if fn =~ /.c$/ and fn =~ /(bzlib|stemmer)/ |
| 68 | | prefix = $1.upcase |
| 69 | | ext_fn.gsub!(/ext\//, "ext/#{prefix}_") |
| 70 | | end |
| 71 | | EXT_SRC_MAP[fn] = ext_fn |
| 72 | | end |
| 73 | | SRC = FileList["ext/*.[ch]", EXT_SRC_DEST, 'ext/internal.h'].uniq |
| 74 | | |
| 75 | | CLEAN.include ['**/*.o', '**/*.obj', '.config', 'ext/cferret.c'] |
| 76 | | CLOBBER.include ['doc/api', 'ext/*.so', 'ext/Makefile', |
| 77 | | 'ext/internal.h', EXT_SRC_DEST] |
| 78 | | |
| 79 | | # The following block creates file tasks for all of the c files. They |
| 80 | | # belong in the ../c directory in source the working copy and they need |
| 81 | | # to be linked to in the ext directory |
| 82 | | EXT_SRC.each do |fn| |
| 83 | | dest_fn = EXT_SRC_MAP[fn] |
| 84 | | # prepend lib files to avoid conflicts |
| 85 | | file dest_fn => fn do |t| |
| 86 | | ln fn, dest_fn |
| 87 | | |
| 88 | | if fn =~ /stemmer/ |
| 89 | | # flatten the directory structure for lib_stemmer |
| 90 | | open(dest_fn) do |in_f| |
| 91 | | open(dest_fn + ".out", "w") do |out_f| |
| 92 | | in_f.each do |line| |
| 93 | | out_f.write(line.sub(/(#include ["<])[.a-z_\/]*\//, '\1')) |
| 94 | | end |
| 95 | | end |
| | 66 | desc "Run all tests" |
| | 67 | task :test_all => [ :test_units ] |
| | 68 | |
| | 69 | desc "Generate API documentation" |
| | 70 | task :doc => [ :appdoc ] |
| | 71 | |
| | 72 | desc "run unit tests in test/unit" |
| | 73 | Rake::TestTask.new("test_units" => :ext) do |t| |
| | 74 | t.libs << "test/unit" |
| | 75 | t.pattern = 'test/unit/t[cs]_*.rb' |
| | 76 | #t.pattern = 'test/unit/search/tc_index_searcher.rb' |
| | 77 | t.verbose = true |
| | 78 | end |
| | 79 | |
| | 80 | desc "Generate documentation for the application" |
| | 81 | rd = Rake::RDocTask.new("appdoc") do |rdoc| |
| | 82 | rdoc.rdoc_dir = 'doc/api' |
| | 83 | rdoc.title = "Ferret Search Library Documentation" |
| | 84 | rdoc.options << '--line-numbers' |
| | 85 | rdoc.options << '--inline-source' |
| | 86 | rdoc.options << '--charset=utf-8' |
| | 87 | rdoc.rdoc_files.include('README') |
| | 88 | rdoc.rdoc_files.include('TODO') |
| | 89 | rdoc.rdoc_files.include('TUTORIAL') |
| | 90 | rdoc.rdoc_files.include('MIT-LICENSE') |
| | 91 | rdoc.rdoc_files.include('lib/**/*.rb') |
| | 92 | rdoc.rdoc_files.include('ext/r_*.c') |
| | 93 | rdoc.rdoc_files.include('ext/ferret.c') |
| | 94 | end |
| | 95 | |
| | 96 | EXT_SRC.each do |fn| |
| | 97 | dest_fn = File.join("ext", File.basename(fn)) |
| | 98 | file dest_fn => fn do |t| |
| | 99 | begin |
| | 100 | raise "copy for release" if ENV["REL"] |
| | 101 | ln_s File.join("..", fn), dest_fn |
| | 102 | rescue Exception => e |
| | 103 | cp File.expand_path(fn), dest_fn |
| | 104 | end |
| | 105 | |
| | 106 | if fn =~ /stemmer/ |
| | 107 | # flatten the directory structure for lib_stemmer |
| | 108 | open(dest_fn) do |in_f| |
| | 109 | open(dest_fn + ".out", "w") do |out_f| |
| | 110 | in_f.each {|line| out_f.write(line.sub(/(#include ["<])[.a-z_\/]*\//) {"#{$1}"})} |
| 99 | | end |
| 100 | | end if File.exists?("../c") |
| 101 | | |
| 102 | | file 'ext/internal.h' => '../c/include/internal.h' do |
| 103 | | File.open('ext/internal.h', 'w') do |f| |
| 104 | | File.readlines('../c/include/internal.h').each do |l| |
| 105 | | next if l =~ /ALLOC/ and l !~ /ZERO|MP_/ |
| 106 | | f.puts(l) |
| 107 | | end |
| 108 | | end |
| 109 | | end |
| 110 | | |
| 111 | | desc "Build the extension (ferret_ext.so). You'll need a C compiler and Make." |
| 112 | | task :compile => ["ext/#{EXT}"] + SRC |
| 113 | | |
| 114 | | file "ext/#{EXT}" => "ext/Makefile" do |
| 115 | | cd "ext" |
| 116 | | if windows and ENV['make'].nil? |
| 117 | | begin |
| 118 | | sh "nmake" |
| 119 | | rescue Exception => e |
| 120 | | path = ':\Program Files\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT' |
| 121 | | if File.exists? "f#{path}" |
| 122 | | sh "f#{path}" |
| 123 | | elsif File.exists? "c#{path}" |
| 124 | | sh "c#{path}" |
| 125 | | else |
| 126 | | say |
| 127 | | say "***************************************************************" |
| 128 | | say "You need to have Visual C++ 6 to build Ferret on Windows." |
| 129 | | say "If you have it installed, you may need to run;" |
| 130 | | say ' C:\Program Files\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT' |
| 131 | | say "***************************************************************" |
| 132 | | say |
| 133 | | raise e |
| 134 | | end |
| 135 | | sh "nmake" |
| 136 | | end |
| 137 | | else |
| 138 | | sh "make" |
| 139 | | end |
| 140 | | cd ".." |
| 141 | | end |
| 142 | | |
| 143 | | file "ext/Makefile" => SRC do |
| 144 | | cd "ext" |
| 145 | | `ruby extconf.rb` |
| 146 | | cd ".." |
| 147 | | end |
| 148 | | end |
| 149 | | |
| 150 | | ############################################################################## |
| 151 | | # Testing |
| 152 | | ############################################################################## |
| 153 | | |
| 154 | | task :test => 'test:units' |
| 155 | | namespace :test do |
| 156 | | desc "Run tests with Valgrind" |
| 157 | | task :valgrind do |
| 158 | | sh "valgrind --suppressions=ferret_valgrind.supp " + |
| 159 | | "--leak-check=yes --show-reachable=yes " + |
| 160 | | "-v ruby test/unit/index/tc_index_reader.rb" |
| 161 | | end |
| 162 | | |
| 163 | | desc "Run all tests" |
| 164 | | task :all => [ :units ] |
| 165 | | |
| 166 | | desc "run unit tests in test/unit" |
| 167 | | Rake::TestTask.new("units" => :build) do |t| |
| 168 | | t.libs << "test/unit" |
| 169 | | t.pattern = 'test/unit/t[cs]_*.rb' |
| 170 | | t.verbose = true |
| 171 | | end |
| 172 | | task :unit => :units |
| 173 | | |
| 174 | | desc "run tests using locally installed gem" |
| 175 | | Rake::TestTask.new("installed") do |t| |
| 176 | | t.libs << "test/unit" |
| 177 | | t.ruby_opts << '-rtest/test_installed' |
| 178 | | t.pattern = 'test/unit/t[cs]_*.rb' |
| 179 | | t.verbose = true |
| 180 | | end |
| 181 | | end |
| 182 | | |
| 183 | | ############################################################################## |
| 184 | | # Documentation |
| 185 | | ############################################################################## |
| 186 | | |
| 187 | | desc "Generate API documentation" |
| 188 | | task :doc => 'doc:rdoc' |
| 189 | | namespace :doc do |
| 190 | | if allison = Gem.cache.search('allison').last |
| 191 | | allison_template = File.join(allison.full_gem_path, 'lib/allison.rb') |
| 192 | | end |
| 193 | | desc "Generate documentation for the application" |
| 194 | | $rd = Rake::RDocTask.new do |rdoc| |
| 195 | | rdoc.rdoc_dir = 'doc/api' |
| 196 | | rdoc.title = "Ferret Search Library Documentation" |
| 197 | | rdoc.options << '--line-numbers' |
| 198 | | rdoc.options << '--inline-source' |
| 199 | | rdoc.options << '--charset=utf-8' |
| 200 | | rdoc.template = allison_template if allison_template |
| 201 | | rdoc.rdoc_files.include('README') |
| 202 | | rdoc.rdoc_files.include('TODO') |
| 203 | | rdoc.rdoc_files.include('TUTORIAL') |
| 204 | | rdoc.rdoc_files.include('MIT-LICENSE') |
| 205 | | rdoc.rdoc_files.include('lib/**/*.rb') |
| 206 | | rdoc.rdoc_files.include('ext/r_*.c') |
| 207 | | rdoc.rdoc_files.include('ext/ferret.c') |
| 208 | | end |
| 209 | | |
| 210 | | desc "Look for TODO and FIXME tags in the code" |
| 211 | | task :todo do |
| 212 | | FileList['**/*.rb', 'ext/*.[ch]'].egrep /[#*].*(FIXME|TODO|TBD)/i |
| 213 | | end |
| 214 | | end |
| 215 | | |
| 216 | | ############################################################################## |
| 217 | | # Packaging and Installing |
| 218 | | ############################################################################## |
| | 113 | mv dest_fn + ".out", dest_fn |
| | 114 | end |
| | 115 | end |
| | 116 | end if File.exists?("../c") |
| | 117 | |
| | 118 | desc "Build the extension" |
| | 119 | task :ext => ["ext/#{EXT}"] + SRC do |
| | 120 | rm_f 'ext/mem_pool.*' |
| | 121 | rm_f 'ext/defines.h' |
| | 122 | end |
| | 123 | |
| | 124 | file "ext/#{EXT}" => ["ext/Makefile"] do |
| | 125 | cp "ext/inc/lang.h", "ext/lang.h" |
| | 126 | cp "ext/inc/threading.h", "ext/threading.h" |
| | 127 | cd "ext" |
| | 128 | if (/mswin/ =~ RUBY_PLATFORM) and ENV['make'].nil? |
| | 129 | begin |
| | 130 | sh "nmake" |
| | 131 | rescue Exception => e |
| | 132 | puts |
| | 133 | puts "**********************************************************************" |
| | 134 | puts "You may need to call VCVARS32.BAT to set the environment variables." |
| | 135 | puts ' "f:\Program Files\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT"' |
| | 136 | puts "**********************************************************************" |
| | 137 | puts |
| | 138 | raise e |
| | 139 | end |
| | 140 | else |
| | 141 | sh "make" |
| | 142 | end |
| | 143 | cd ".." |
| | 144 | end |
| | 145 | |
| | 146 | file "ext/lang.h" => ["ext/inc/lang.h"] do |
| | 147 | rm_f "ext/lang.h" |
| | 148 | cp "ext/inc/lang.h", "ext/lang.h" |
| | 149 | end |
| | 150 | |
| | 151 | file "ext/threading.h" => ["ext/inc/threading.h"] do |
| | 152 | rm_f "ext/threading.h" |
| | 153 | cp "ext/inc/threading.h", "ext/threading.h" |
| | 154 | end |
| | 155 | |
| | 156 | file "ext/Makefile" => SRC do |
| | 157 | cd "ext" |
| | 158 | `ruby extconf.rb` |
| | 159 | cd ".." |
| | 160 | end |
| | 161 | |
| | 162 | # Make Parsers --------------------------------------------------------------- |
| | 163 | |
| | 164 | RACC_SRC = FileList["lib/**/*.y"] |
| | 165 | RACC_OUT = RACC_SRC.collect { |fn| fn.sub(/\.y$/, '.tab.rb') } |
| | 166 | |
| | 167 | task :parsers => RACC_OUT |
| | 168 | rule(/\.tab\.rb$/ => [proc {|tn| tn.sub(/\.tab\.rb$/, '.y')}]) do |t| |
| | 169 | sh "racc #{t.source}" |
| | 170 | end |
| | 171 | |
| | 172 | # Create Packages ------------------------------------------------------------ |
| 233 | | |
| 234 | | spec = Gem::Specification.new do |s| |
| | 187 | PKG_FILES.exclude('**/*.o') |
| | 188 | PKG_FILES.exclude('**/Makefile') |
| | 189 | PKG_FILES.exclude('ext/ferret_ext.so') |
| | 190 | |
| | 191 | |
| | 192 | if ! defined?(Gem) |
| | 193 | puts "Package Target requires RubyGEMs" |
| | 194 | else |
| | 195 | spec = Gem::Specification.new do |s| |
| | 196 | |
| | 197 | #### Basic information. |
| | 198 | s.name = 'ferret' |
| | 199 | s.version = PKG_VERSION |
| | 200 | s.summary = "Ruby indexing library." |
| | 201 | s.description = <<-EOF |
| | 202 | Ferret is a port of the Java Lucene project. It is a powerful |
| | 203 | indexing and search library. |
| | 204 | EOF |
| | 205 | |
| | 206 | #### Dependencies and requirements. |
| | 207 | s.add_dependency('rake') |
| | 208 | s.files = PKG_FILES.to_a |
| | 209 | s.extensions << "ext/extconf.rb" |
| | 210 | s.require_path = 'lib' |
| | 211 | s.autorequire = 'ferret' |
| | 212 | s.bindir = 'bin' |
| | 213 | s.executables = ['ferret-browser'] |
| | 214 | s.default_executable = 'ferret-browser' |
| | 215 | |
| | 216 | #### Author and project details. |
| | 217 | s.author = "David Balmain" |
| | 218 | s.email = "dbalmain@gmail.com" |
| | 219 | s.homepage = "http://ferret.davebalmain.com/trac" |
| | 220 | s.rubyforge_project = "ferret" |
| | 221 | |
| | 222 | s.has_rdoc = true |
| | 223 | s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a |
| | 224 | s.rdoc_options << |
| | 225 | '--title' << 'Ferret -- Ruby Indexer' << |
| | 226 | '--main' << 'README' << '--line-numbers' << |
| | 227 | 'TUTORIAL' << 'TODO' |
| | 228 | |
| | 229 | if RUBY_PLATFORM =~ /mswin/ |
| | 230 | s.files = PKG_FILES.to_a + ["ext/#{EXT}"] |
| | 231 | s.extensions.clear |
| | 232 | s.platform = Gem::Platform::WIN32 |
| | 233 | end |
| | 234 | end |
| | 235 | |
| | 236 | package_task = Rake::GemPackageTask.new(spec) do |pkg| |
| | 237 | unless RUBY_PLATFORM =~ /mswin/ |
| | 238 | pkg.need_zip = true |
| | 239 | pkg.need_tar = true |
| | 240 | end |
| | 241 | end |
| | 242 | end |
| | 243 | |
| | 244 | # Support Tasks ------------------------------------------------------ |
| | 245 | |
| | 246 | desc "Look for TODO and FIXME tags in the code" |
| | 247 | task :todo do |
| | 248 | FileList['**/*.rb'].egrep /#.*(FIXME|TODO|TBD)/ |
| | 249 | end |
| | 250 | # -------------------------------------------------------------------- |
| | 251 | # Creating a release |
| | 252 | |
| | 253 | desc "Make a new release" |
| | 254 | task :release => [ |
| | 255 | :prerelease, |
| | 256 | :polish, |
| | 257 | :test_all, |
| | 258 | :update_version, |
| | 259 | :package, |
| | 260 | :tag] do |
| | 261 | announce |
| | 262 | announce "**************************************************************" |
| | 263 | announce "* Release #{PKG_VERSION} Complete." |
| | 264 | announce "* Packages ready to upload." |
| | 265 | announce "**************************************************************" |
| | 266 | announce |
| | 267 | end |
| | 268 | |
| | 269 | # Validate that everything is ready to go for a release. |
| | 270 | task :prerelease do |
| | 271 | announce |
| | 272 | announce "**************************************************************" |
| | 273 | announce "* Making RubyGem Release #{PKG_VERSION}" |
| | 274 | announce "* (current version #{CURRENT_VERSION})" |
| | 275 | announce "**************************************************************" |
| | 276 | announce |
| | 277 | |
| | 278 | # Is a release number supplied? |
| | 279 | unless ENV['REL'] |
| | 280 | fail "Usage: rake release REL=x.y.z [REUSE=tag_suffix]" |
| | 281 | end |
| | 282 | |
| | 283 | # Is the release different than the current release. |
| | 284 | # (or is REUSE set?) |
| | 285 | if PKG_VERSION == CURRENT_VERSION && ! ENV['REUSE'] |
| | 286 | fail "Current version is #{PKG_VERSION}, must specify REUSE=tag_suffix to reuse version" |
| | 287 | end |
| | 288 | |
| | 289 | # Are all source files checked in? |
| | 290 | data = `svn -q --ignore-externals status` |
| | 291 | unless data =~ /^$/ |
| | 292 | fail "'svn -q status' is not clean ... do you have unchecked-in files?" |
| | 293 | end |
| 236 | | #### Basic information. |
| 237 | | s.name = 'ferret' |
| 238 | | s.version = Ferret::VERSION |
| 239 | | s.summary = "Ruby indexing library." |
| 240 | | s.description = "Ferret is a super fast, highly configurable search library." |
| 241 | | |
| 242 | | #### Dependencies and requirements. |
| 243 | | s.add_dependency('rake') |
| 244 | | s.files = PKG_FILES.to_a |
| 245 | | s.extensions << "ext/extconf.rb" |
| 246 | | s.require_path = 'lib' |
| 247 | | s.bindir = 'bin' |
| 248 | | s.executables = ['ferret-browser'] |
| 249 | | s.default_executable = 'ferret-browser' |
| 250 | | |
| 251 | | #### Author and project details. |
| 252 | | s.author = "David Balmain" |
| 253 | | s.email = "dbalmain@gmail.com" |
| 254 | | s.homepage = "http://ferret.davebalmain.com/trac" |
| 255 | | s.rubyforge_project = "ferret" |
| 256 | | |
| 257 | | s.has_rdoc = true |
| 258 | | s.extra_rdoc_files = $rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a |
| 259 | | s.rdoc_options << |
| 260 | | '--title' << 'Ferret -- Ruby Search Library' << |
| 261 | | '--main' << 'README' << '--line-numbers' << |
| 262 | | 'TUTORIAL' << 'TODO' |
| 263 | | |
| 264 | | key_file = File.expand_path('~/.gem/gem-private_key.pem') |
| 265 | | key_file = nil unless File.exists?(key_file) |
| 266 | | cert_file = File.expand_path('~/.gem/gem-public_cert.pem') |
| 267 | | cert_file = nil unless File.exists?(cert_file) |
| 268 | | if key_file and cert_file |
| 269 | | s.signing_key = key_file |
| 270 | | s.cert_chain = cert_file |
| 271 | |