C0 code coverage information
Generated on Wed Oct 07 08:33:59 -0700 2009 with rcov 0.8.2.1
Code reported as executed by Ruby looks like this...
and this: this line is also marked as covered.
Lines considered as run by rcov, but not reported by Ruby, look like this,
and this: these lines were inferred by rcov (using simple heuristics).
Finally, here's a line marked as not executed.
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with this
3 # work for additional information regarding copyright ownership. The ASF
4 # licenses this file to you under the Apache License, Version 2.0 (the
5 # "License"); you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations under
14 # the License.
15
16
17 require 'rbconfig'
18 require 'pathname'
19 autoload :Tempfile, 'tempfile'
20 autoload :YAML, 'yaml'
21 autoload :REXML, 'rexml/document'
22 gem 'xml-simple' ; autoload :XmlSimple, 'xmlsimple'
23 gem 'builder' ; autoload :Builder, 'builder' # A different kind of buildr, one we use to create XML.
24 require 'highline/import'
25
26
27 module Buildr
28
29 module Util
30 extend self
31
32 def java_platform?
33 RUBY_PLATFORM =~ /java/
34 end
35
36 # In order to determine if we are running on a windows OS,
37 # prefer this function instead of using Gem.win_platform?.
38 #
39 # Gem.win_platform? only checks these RUBY_PLATFORM global,
40 # that in some cases like when running on JRuby is not
41 # succifient for our purpose:
42 #
43 # For JRuby, the value for RUBY_PLATFORM will always be 'java'
44 # That's why this function checks on Config::CONFIG['host_os']
45 def win_os?
46 Config::CONFIG['host_os'] =~ /windows|cygwin|bccwin|cygwin|djgpp|mingw|mswin|wince/i
47 end
48
49 # Runs Ruby with these command line arguments. The last argument may be a hash,
50 # supporting the following keys:
51 # :command -- Runs the specified script (e.g., :command=>'gem')
52 # :sudo -- Run as sudo on operating systems that require it.
53 # :verbose -- Override Rake's verbose flag.
54 def ruby(*args)
55 options = Hash === args.last ? args.pop : {}
56 cmd = []
57 ruby_bin = File.expand_path(Config::CONFIG['ruby_install_name'], Config::CONFIG['bindir'])
58 if options.delete(:sudo) && !(win_os? || Process.uid == File.stat(ruby_bin).uid)
59 cmd << 'sudo' << '-u' << "##{File.stat(ruby_bin).uid}"
60 end
61 cmd << ruby_bin
62 cmd << '-S' << options.delete(:command) if options[:command]
63 cmd.concat args.flatten
64 cmd.push options
65 sh *cmd do |ok, status|
66 ok or fail "Command ruby failed with status (#{status ? status.exitstatus : 'unknown'}): [#{cmd.join(" ")}]"
67 end
68 end
69
70 # Just like File.expand_path, but for windows systems it
71 # capitalizes the drive name and ensures backslashes are used
72 def normalize_path(path, *dirs)
73 path = File.expand_path(path, *dirs)
74 if win_os?
75 path.gsub!('/', '\\').gsub!(/^[a-zA-Z]+:/) { |s| s.upcase }
76 else
77 path
78 end
79 end
80
81 # Return the timestamp of file, without having to create a file task
82 def timestamp(file)
83 if File.exist?(file)
84 File.mtime(file)
85 else
86 Rake::EARLY
87 end
88 end
89
90 # Return the path to the first argument, starting from the path provided by the
91 # second argument.
92 #
93 # For example:
94 # relative_path('foo/bar', 'foo')
95 # => 'bar'
96 # relative_path('foo/bar', 'baz')
97 # => '../foo/bar'
98 # relative_path('foo/bar')
99 # => 'foo/bar'
100 # relative_path('/foo/bar', 'baz')
101 # => '/foo/bar'
102 def relative_path(to, from = '.')
103 to = Pathname.new(to).cleanpath
104 return to.to_s if from.nil?
105 to_path = Pathname.new(File.expand_path(to.to_s, "/"))
106 from_path = Pathname.new(File.expand_path(from.to_s, "/"))
107 to_path.relative_path_from(from_path).to_s
108 end
109
110 # Generally speaking, it's not a good idea to operate on dot files (files starting with dot).
111 # These are considered invisible files (.svn, .hg, .irbrc, etc). Dir.glob/FileList ignore them
112 # on purpose. There are few cases where we do have to work with them (filter, zip), a better
113 # solution is welcome, maybe being more explicit with include. For now, this will do.
114 def recursive_with_dot_files(*dirs)
115 FileList[dirs.map { |dir| File.join(dir, '/**/{*,.*}') }].reject { |file| File.basename(file) =~ /^[.]{1,2}$/ }
116 end
117
118 # Utility methods for running gem commands
119 module Gems #:nodoc:
120 extend self
121
122 # Install gems specified by each Gem::Dependency if they are missing. This method prompts the user
123 # for permission before installing anything.
124 #
125 # Returns the installed Gem::Dependency objects or fails if permission not granted or when buildr
126 # is not running interactively (on a tty)
127 def install(*dependencies)
128 raise ArgumentError, "Expected at least one argument" if dependencies.empty?
129 remote = dependencies.map { |dep| Gem::SourceInfoCache.search(dep).last || dep }
130 not_found_deps, to_install = remote.partition { |gem| gem.is_a?(Gem::Dependency) }
131 fail Gem::LoadError, "Build requires the gems #{not_found_deps.join(', ')}, which cannot be found in local or remote repository." unless not_found_deps.empty?
132 uses = "This build requires the gems #{to_install.map(&:full_name).join(', ')}:"
133 fail Gem::LoadError, "#{uses} to install, run Buildr interactively." unless $stdout.isatty
134 unless agree("#{uses} do you want me to install them? [Y/n]", true)
135 fail Gem::LoadError, 'Cannot build without these gems.'
136 end
137 to_install.each do |spec|
138 say "Installing #{spec.full_name} ... " if verbose
139 command 'install', spec.name, '-v', spec.version.to_s, :verbose => false
140 Gem.source_index.load_gems_in Gem::SourceIndex.installed_spec_directories
141 end
142 to_install
143 end
144
145 # Execute a GemRunner command
146 def command(cmd, *args)
147 options = Hash === args.last ? args.pop : {}
148 gem_home = ENV['GEM_HOME'] || Gem.path.find { |f| File.writable?(f) }
149 options[:sudo] = :root unless Util.win_os? || gem_home
150 options[:command] = 'gem'
151 args << options
152 args.unshift '-i', gem_home if cmd == 'install' && gem_home && !args.any?{ |a| a[/-i|--install-dir/] }
153 Util.ruby cmd, *args
154 end
155
156 end # Gems
157
158 end # Util
159 end
160
161
162 class Object #:nodoc:
163 unless defined? instance_exec # 1.9
164 module InstanceExecMethods #:nodoc:
165 end
166 include InstanceExecMethods
167
168 # Evaluate the block with the given arguments within the context of
169 # this object, so self is set to the method receiver.
170 #
171 # From Mauricio's http://eigenclass.org/hiki/bounded+space+instance_exec
172 def instance_exec(*args, &block)
173 begin
174 old_critical, Thread.critical = Thread.critical, true
175 n = 0
176 n += 1 while respond_to?(method_name = "__instance_exec#{n}")
177 InstanceExecMethods.module_eval { define_method(method_name, &block) }
178 ensure
179 Thread.critical = old_critical
180 end
181
182 begin
183 send(method_name, *args)
184 ensure
185 InstanceExecMethods.module_eval { remove_method(method_name) } rescue nil
186 end
187 end
188 end
189 end
190
191 module Kernel #:nodoc:
192 unless defined? tap # 1.9
193 def tap
194 yield self if block_given?
195 self
196 end
197 end
198 end
199
200 class Symbol #:nodoc:
201 unless defined? to_proc # 1.9
202 # Borrowed from Ruby 1.9.
203 def to_proc
204 Proc.new{|*args| args.shift.__send__(self, *args)}
205 end
206 end
207 end
208
209 unless defined? BasicObject # 1.9
210 class BasicObject #:nodoc:
211 (instance_methods - ['__send__', '__id__', '==', 'send', 'send!', 'respond_to?', 'equal?', 'object_id']).
212 each do |method|
213 undef_method method
214 end
215
216 def self.ancestors
217 [Kernel]
218 end
219 end
220 end
221
222
223 class OpenObject < Hash
224
225 def initialize(source=nil, &block)
226 super &block
227 update source if source
228 end
229
230 def method_missing(symbol, *args)
231 if symbol.to_s =~ /=$/
232 self[symbol.to_s[0..-2].to_sym] = args.first
233 else
234 self[symbol]
235 end
236 end
237 end
238
239
240 class Hash
241
242 class << self
243
244 # :call-seq:
245 # Hash.from_java_properties(string)
246 #
247 # Returns a hash from a string in the Java properties file format. For example:
248 # str = 'foo=bar\nbaz=fab'
249 # Hash.from_properties(str)
250 # => { 'foo'=>'bar', 'baz'=>'fab' }.to_properties
251 def from_java_properties(string)
252 hash = {}
253 input_stream = Java.java.io.StringBufferInputStream.new(string)
254 java_properties = Java.java.util.Properties.new
255 java_properties.load input_stream
256 keys = java_properties.keySet.iterator
257 while keys.hasNext
258 # Calling key.next in JRuby returns a java.lang.String, behaving as a Ruby string and life is good.
259 # MRI, unfortunately, treats next() like the interface says returning an object that's not a String,
260 # and the Hash doesn't work the way we need it to. Unfortunately, we can call toString on MRI's object,
261 # but not on the JRuby one; calling to_s on the JRuby object returns what we need, but ... you guessed it.
262 # So this seems like the one hack to unite them both.
263 #key = Java.java.lang.String.valueOf(keys.next.to_s)
264 key = keys.next
265 key = key.toString unless String === key
266 hash[key] = java_properties.getProperty(key)
267 end
268 hash
269 end
270
271 end
272
273 # :call-seq:
274 # only(keys*) => hash
275 #
276 # Returns a new hash with only the specified keys.
277 #
278 # For example:
279 # { :a=>1, :b=>2, :c=>3, :d=>4 }.only(:a, :c)
280 # => { :a=>1, :c=>3 }
281 def only(*keys)
282 keys.inject({}) { |hash, key| has_key?(key) ? hash.merge(key=>self[key]) : hash }
283 end
284
285
286 # :call-seq:
287 # except(keys*) => hash
288 #
289 # Returns a new hash without the specified keys.
290 #
291 # For example:
292 # { :a=>1, :b=>2, :c=>3, :d=>4 }.except(:a, :c)
293 # => { :b=>2, :d=>4 }
294 def except(*keys)
295 (self.keys - keys).inject({}) { |hash, key| hash.merge(key=>self[key]) }
296 end
297
298 # :call-seq:
299 # to_java_properties => string
300 #
301 # Convert hash to string format used for Java properties file. For example:
302 # { 'foo'=>'bar', 'baz'=>'fab' }.to_properties
303 # => foo=bar
304 # baz=fab
305 def to_java_properties
306 keys.sort.map { |key|
307 value = self[key].gsub(/[\t\r\n\f\\]/) { |escape| "\\" + {"\t"=>"t", "\r"=>"r", "\n"=>"n", "\f"=>"f", "\\"=>"\\"}[escape] }
308 "#{key}=#{value}"
309 }.join("\n")
310 end
311
312 end
313
314 if Buildr::Util.java_platform?
315 require 'ffi'
316
317 # Fix for BUILDR-292.
318 # JRuby fails to rename a file on different devices
319 # this monkey-patch wont be needed when JRUBY-3381 gets resolved.
320 module FileUtils #:nodoc:
321 alias_method :__mv_native, :mv
322
323 def mv(from, to, options = nil)
324 dir_to = File.directory?(to) ? to : File.dirname(to)
325 Array(from).each do |from|
326 dir_from = File.dirname(from)
327 if File.stat(dir_from).dev != File.stat(dir_to).dev
328 cp from, to, options
329 rm from, options
330 else
331 __mv_native from, to, options
332 end
333 end
334 end
335 private :mv
336 end
337
338 module RakeFileUtils #:nodoc:
339 def rake_merge_option(args, defaults)
340 defaults[:verbose] = false if defaults[:verbose] == :default
341
342 if Hash === args.last
343 defaults.update(args.last)
344 args.pop
345 end
346 args.push defaults
347 args
348 end
349 private :rake_merge_option
350 end
351
352 module Buildr
353 class ProcessStatus
354 attr_reader :pid, :termsig, :stopsig, :exitstatus
355
356 def initialize(pid, success, exitstatus)
357 @pid = pid
358 @success = success
359 @exitstatus = exitstatus
360
361 @termsig = nil
362 @stopsig = nil
363 end
364
365 def &(num)
366 pid & num
367 end
368
369 def ==(other)
370 pid == other.pid
371 end
372
373 def >>(num)
374 pid >> num
375 end
376
377 def coredump?
378 false
379 end
380
381 def exited?
382 true
383 end
384
385 def stopped?
386 false
387 end
388
389 def success?
390 @success
391 end
392
393 def to_i
394 pid
395 end
396
397 def to_int
398 pid
399 end
400
401 def to_s
402 pid.to_s
403 end
404 end
405 end
406
407 module FileUtils
408 extend FFI::Library
409 alias_method :__jruby_system__, :system
410 attach_function :system, [:string], :int
411 alias_method :__native_system__, :system
412 alias_method :system, :__jruby_system__
413
414 # code "borrowed" directly from Rake
415 def sh(*cmd, &block)
416 options = (Hash === cmd.last) ? cmd.pop : {}
417 unless block_given?
418 show_command = cmd.join(" ")
419 show_command = show_command[0,42] + "..."
420
421 block = lambda { |ok, status|
422 ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
423 }
424 end
425 if RakeFileUtils.verbose_flag == :default
426 options[:verbose] = false
427 else
428 options[:verbose] ||= RakeFileUtils.verbose_flag
429 end
430 options[:noop] ||= RakeFileUtils.nowrite_flag
431 rake_check_options options, :noop, :verbose
432 rake_output_message cmd.join(" ") if options[:verbose]
433 unless options[:noop]
434 cd = "cd '#{Dir.pwd}' && "
435 args = if cmd.size > 1 then cmd[1..cmd.size] else [] end
436
437 res = if Buildr::Util.win_os? && cmd.size == 1
438 __native_system__("#{cd} call #{cmd.first}")
439 else
440 arg_str = args.map { |a| "'#{a}'" }
441 __native_system__(cd + cmd.first + ' ' + arg_str.join(' '))
442 end
443 $? = Buildr::ProcessStatus.new(0, res == 0, res) # KLUDGE
444 block.call(res == 0, $?)
445 end
446 end
447
448 end
449 end
Generated using the rcov code coverage analysis tool for Ruby
version 0.8.2.1.