require "highline" require "highline/import" # &:symbol goodness. require "facet/symbol/to_proc" # blank? on string and nil require "facet/string/blank" require "facet/nilclass/blank" # x.in?(y) is better than y.include?(x) require "facet/kernel/in" # Allows binding[] require "facet/binding" # What it says. require "facet/kernel/__DIR__" require "facet/kernel/instance_exec" require "facet/module/alias_method_chain" require "facet/module/memoize" require "facet/array/head" require "facet/string/starts_with" require "facet/openobject" require "facets/core/kernel/tap" # A different kind of buildr, one we use to create XML. require "builder" module Buildr VERSION = "1.2.1".freeze end # When running from +rake+, we already have an Application setup and must plug into it, # since the top-level tasks come from there. When running from +buildr+, we get to load # Rake and set everything up, and we use our own Application full of cool Buildr features. unless defined?(Rake) require "rake" module Buildr class Application < Rake::Application #:nodoc: DEFAULT_BUILDFILES = ["buildfile", "Buildfile"] + DEFAULT_RAKEFILES OPTIONS = [ # :nodoc: ['--help', '-H', GetoptLong::NO_ARGUMENT, "Display this help message."], ['--nosearch', '-N', GetoptLong::NO_ARGUMENT, "Do not search parent directories for the buildfile."], ['--quiet', '-q', GetoptLong::NO_ARGUMENT, "Do not log messages to standard output."], ['--buildfile', '-f', GetoptLong::OPTIONAL_ARGUMENT, "Use FILE as the buildfile."], ['--require', '-r', GetoptLong::REQUIRED_ARGUMENT, "Require MODULE before executing buildfile."], ['--trace', '-t', GetoptLong::NO_ARGUMENT, "Turn on invoke/execute tracing, enable full backtrace."], ['--verbose', '-v', GetoptLong::NO_ARGUMENT, "Log message to standard output (default)."], ['--version', '-V', GetoptLong::NO_ARGUMENT, "Display the program version."], ['--freeze', "-F", GetoptLong::NO_ARGUMENT, "Freezes the Buildfile so it always uses Buildr version #{Buildr::VERSION}"], ['--unfreeze', "-U", GetoptLong::NO_ARGUMENT, "Unfreezes the Buildfile to use the latest version of Buildr"] ] def initialize() super @rakefiles = DEFAULT_BUILDFILES @name = "Buildr" opts = GetoptLong.new(*command_line_options) opts.each { |opt, value| do_option(opt, value) } collect_tasks end def run() standard_exception_handling do load_buildfile top_level end end def do_option(opt, value) case opt when '--help' help exit when "--buildfile" @rakefiles.clear @rakefiles << value when '--version' puts "Buildr, version #{Buildr::VERSION}" exit when "--freeze" find_buildfile puts "Freezing the Buildfile so it always uses Buildr version #{Buildr::VERSION}" gem = original = File.read(rakefile) if original =~ /gem\s*(["'])buildr\1/ modified = original.sub(/gem\s*(["'])buildr\1\s*,\s*(["']).*\2/, %{gem "buildr", "#{Buildr::VERSION}"}) else modified = %{gem "buildr", "#{Buildr::VERSION}"\n} + original end File.open(rakefile, "w") { |file| file.write modified } exit when "--unfreeze" find_buildfile puts "Unfreezing the Buildfile to use the latest version of Buildr from your Gems repository." modified = File.read(rakefile).sub(/^\s*gem\s*(["'])buildr\1.*\n/, "") File.open(rakefile, "w") { |file| file.write modified } exit when '--require', "--nosearch", "--quiet", "--trace", "--verbose" super end end def find_buildfile() here = Dir.pwd while ! have_rakefile Dir.chdir("..") if Dir.pwd == here || options.nosearch error = "No Buildfile found (looking for: #{@rakefiles.join(', ')})" if STDIN.isatty if $terminal.agree("To use Buildr you need a buildfile. Do you want me to create one? (yes/no)") chdir(original_dir) { task("generate").invoke } end exit 1 else raise error end end here = Dir.pwd end end def load_buildfile() find_buildfile puts "(in #{Dir.pwd})" load File.expand_path(@rakefile) if @rakefile != '' load_imports end def usage() puts "Buildr #{Buildr::VERSION}" puts puts "Usage:" puts " buildr [-f buildfile] {options} targets..." end def help() usage puts puts "Options:" OPTIONS.sort.each do |long, short, mode, desc| if mode == GetoptLong::REQUIRED_ARGUMENT if desc =~ /\b([A-Z]{2,})\b/ long = long + "=#{$1}" end end printf " %-20s (%s)\n", long, short printf " %s\n", desc end puts puts "For help with your buildfile:" puts " buildr help" end def command_line_options OPTIONS.collect { |lst| lst[0..-2] } end end Rake.application = Application.new end end # Now it's safe to load Buildr, after we set up the Rake Application. $LOAD_PATH.unshift __DIR__ ["core", "tasks", "java"].each do |dir| Dir[File.join(__DIR__, dir, "*.rb")].map { |file| File.basename(file) }.each { |file| require "#{dir}/#{file}" } end # Methods defined in Buildr are both instance methods (e.g. when included in Project) # and class methods when invoked like Buildr.artifacts(). module Buildr ; extend self ; end # The Buildfile object (self) has access to all the Buildr methods and constants. class << self ; include Buildr ; end class Object #:nodoc: Buildr.constants.each { |c| const_set c, Buildr.const_get(c) unless const_defined?(c) } end # Project has visibility to everything in the Buildr namespace. (See above for constants) class Project ; include Buildr ; end module Buildr @loaded_features_to_ignore = $LOADED_FEATURES end # Load the settings files. [ File.expand_path("buildr.rb", Gem::user_home), "buildr.rb" ].each { |file| load file if File.exist?(file) } [ File.expand_path("buildr.rake", Gem::user_home), File.expand_path("buildr.rake") ].each do |file| if File.exist?(file) warn "Please use '#{file.ext('rb')}' instead of '#{file}'" load file end end #Load local tasks that can be used in the Buildfile. Dir["#{Dir.pwd}/tasks/*.rake"].each do |file| unless $LOADED_FEATURES.include?(file) load file $LOADED_FEATURES << file end end