utils.rb: fix handling of require return value
[rbot] / Rakefile
1 require 'rubygems'
2 require 'rake'
3 require 'rake/gempackagetask'
4
5 task :default => [:buildext]
6
7 spec = Gem::Specification.new do |s|
8   s.name = 'rbot'
9   s.version = '0.9.15'
10   s.summary = <<-EOF
11     A modular ruby IRC bot.
12   EOF
13   s.description = <<-EOF
14     A modular ruby IRC bot specifically designed for ease of extension via plugins.
15   EOF
16   s.requirements << 'Ruby, version 1.8.0 (or newer)'
17
18   #  s.files = Dir.glob("**/*").delete_if { |item| item.include?(".svn") }
19   s.files = FileList['lib/**/*.rb', 'bin/*', 'data/rbot/**/*', 'AUTHORS', 'COPYING', 'README', 'REQUIREMENTS', 'TODO', 'ChangeLog', 'INSTALL',  'Usage_en.txt', 'setup.rb', 'po/*.pot', 'po/**/*.po'].to_a.delete_if {|item| item == ".svn"}
20   s.bindir = 'bin'
21   s.executables = ['rbot', 'rbot-remote']
22   s.default_executable = 'rbot'
23   s.extensions = 'Rakefile'
24
25 #  s.autorequire = 'rbot/ircbot'
26   s.has_rdoc = true
27   s.rdoc_options = ['--exclude', 'post-install.rb',
28   '--title', 'rbot API Documentation', '--main', 'README', 'README']
29
30   s.author = 'Tom Gilbert'
31   s.email = 'tom@linuxbrit.co.uk'
32   s.homepage = 'http://ruby-rbot.org'
33   s.rubyforge_project = 'rbot'
34 end
35
36 Rake::GemPackageTask.new(spec) do |pkg|
37   pkg.need_zip = true
38   pkg.need_tar = true
39 end
40
41 # normalize a po/pot file
42 def normalize_po(fn)
43   content = File.read(fn)
44
45   # sort the messages by file location
46   if MSGCAT
47     sorted = `#{MSGCAT} --width=79 --sort-by-file #{fn}`
48     if sorted != content
49       content = sorted
50       modified = true
51     end
52   end
53
54   # replace project-id-version placholder
55   modified |= content.sub!(/^("Project-Id-Version: )PACKAGE VERSION(\\n")$/) {
56     "#{$1}rbot#{$2}"
57   }
58
59   if modified
60     File.open(fn, 'w') {|f| f.write content}
61   end
62 end
63
64 PLUGIN_FILES = FileList['data/rbot/plugins/**/*.rb']
65 NON_PLUGIN_FILES = FileList["{lib,bin,data}/**/*.{rb,rhtml}"] - PLUGIN_FILES
66
67 # this task defines how po files and pot files are made. those rules are not defined
68 # normally because po and pot files should be only updated in the updatepo task,
69 # but po files are also prereqs for makemo
70 task :define_po_rules do
71   # generate pot file from rb files
72   rgettext_proc = proc do |t|
73     require 'gettext/utils'
74     source_files, pot_file = t.prerequisites, t.name
75     new_pot_file = "#{pot_file}.new"
76     puts "#{source_files.join(', ')} => #{pot_file}"
77     GetText.rgettext(source_files, new_pot_file)
78
79     # only use the new pot file if it contains unique messages
80     if File.exists?(pot_file) && MSGCOMM && `#{MSGCOMM} --unique #{pot_file} #{new_pot_file}`.empty?
81       rm new_pot_file
82     else
83       mv new_pot_file, pot_file
84     end
85
86     normalize_po(pot_file)
87     
88     # save all this work until rb files are updated again
89     touch pot_file
90   end
91
92   # generate pot file for non-plugin files
93   file('po/rbot.pot' => NON_PLUGIN_FILES, &rgettext_proc)
94
95   # generate pot files for plugin files
96   rule(%r'^po/.+\.pot$' => proc {|fn|
97     PLUGIN_FILES.select {|f| f.pathmap('rbot-%n') == fn.pathmap('%n')}
98   }, &rgettext_proc)
99
100   # map the po file to its source pot file
101   pot_for_po = proc {|fn| fn.pathmap '%{^po/.+/,po/}X.pot'}
102
103   # update po file from pot file
104   msgmerge_proc = proc do |t|
105     require 'gettext/utils'
106     po_file, pot_file = t.name, t.source
107     puts "#{pot_file} => #{po_file}"
108     if File.exists? po_file
109       sh "#{MSGMERGE} --backup=off --update #{po_file} #{pot_file}"
110     elsif MSGINIT
111       locale = po_file[%r'^po/(.+)/.+\.po$', 1]
112       sh "#{MSGINIT} --locale=#{locale} --no-translator --input=#{pot_file} --output-file=#{po_file}"
113     else
114       warn "#{po_file} is missing and cannot be generated without msginit"
115       next
116     end
117     normalize_po(po_file)
118     touch po_file
119   end
120
121   # generate English po files
122   file(%r'^po/en_US/.+\.po$' => pot_for_po) do |t|
123     po_file, pot_file = t.name, t.source
124     if MSGEN
125       sh "#{MSGEN} --output-file=#{po_file} #{pot_file}"
126       normalize_po(po_file)
127       touch po_file
128     else
129       msgmerge_proc.call t
130     end
131   end
132
133   # update po files
134   rule(%r'^po/.+/.+\.po$' => pot_for_po, &msgmerge_proc)
135 end
136
137 # generate mo files
138 rule(%r'^data/locale/.+/LC_MESSAGES/.+\.mo$' => proc {|fn|
139   [ fn.pathmap('%{^data/locale,po;LC_MESSAGES/,}X.po'), 
140     # the directory is created if not existing
141     fn.pathmap('%d') ]
142 }) do |t|
143   po_file, mo_file = t.source, t.name
144   puts "#{po_file} => #{mo_file}"
145   require 'gettext/utils'
146   GetText.rmsgfmt po_file, mo_file
147 end
148
149 task :check_po_tools do
150   have = {}
151
152   po_tools = {
153     'msgmerge' => {
154       :options => %w[--backup= --update],
155       :message => 'Cannot update po files' },
156     'msginit' => {
157       :options => %w[--locale= --no-translator --input= --output-file=],
158       :message => 'Cannot generate missing po files' },
159     'msgcomm' => {
160       :options => %w[--unique],
161       :message => 'Pot files may be modified even without message change' },
162     'msgen' => {
163       :options => %w[--output-file],
164       :message => 'English po files will not be generated' },
165     'msgcat' => {
166       :options => %w[--width= --sort-by-file],
167       :message => 'Pot files will not be normalized' }
168   }
169
170   po_tools.each_pair do |command, value|
171     path = ENV["#{command.upcase}_PATH"] || command
172     have_it = have[command] = value[:options].all? do |option|
173       `#{path} --help`.include? option
174     end
175     Object.const_set(command.upcase, have_it ? path : false)
176     warn "#{command} not found. #{value[:message]}" unless have_it
177   end
178   abort unless MSGMERGE
179 end
180
181 PLUGIN_BASENAMES = PLUGIN_FILES.map {|f| f.pathmap('%n')}
182 LOCALES = FileList['po/*/'].map {|d| d.pathmap('%n')}
183
184 LOCALES.each do |l|
185   directory "data/locale/#{l}/LC_MESSAGES"
186 end
187
188 desc 'Update po files'
189 task :updatepo => [:define_po_rules, :check_po_tools] + LOCALES.map {|l|
190   ["po/#{l}/rbot.po"] +
191   PLUGIN_BASENAMES.map {|n| "po/#{l}/rbot-#{n}.po"}
192 }.flatten
193
194 desc 'Normalize po files'
195 task :normalizepo => :check_po_tools do
196   FileList['po/*/*.po'].each {|fn| normalize_po(fn)}
197 end
198
199 # this task invokes makemo if ruby-gettext is available, but otherwise succeeds
200 # with a warning instead of failing. it is to be used by Gem's extension builder
201 # to make installation not fail because of lack of ruby-gettext
202 task :buildext do
203   begin
204     require 'gettext/utils'
205     Rake::Task[:makemo].invoke
206   rescue LoadError
207     warn 'Ruby-gettext cannot be located, so mo files cannot be built and installed' 
208   end
209 end
210
211 desc 'Generate mo files'
212 task :makemo =>
213   FileList['po/*/*.po'].pathmap('%{^po,data/locale}d/LC_MESSAGES/%n.mo')
214
215