# encoding: utf-8 # require 'kde-build/vcs/git-svn' require 'kde-build/command/build' require 'kde-build/command/compile' require 'kde-build/command/configure' require 'kde-build/command/ctags' require 'kde-build/command/fetch' require 'kde-build/command/help' require 'kde-build/command/install' require 'kde-build/command/info' require 'kde-build/command/rebase' require 'kde-build/command/version' require 'kde-build/configuration' require 'kde-build/tools/ctags.rb' require 'kde-build/tools/logging.rb' require 'kde-build/moduleregistry' require 'kde-build/module_configuration' require 'cmdparse' require 'erb' require 'singleton' require 'yaml' require 'fileutils' # log4r produces nasty warnings # (eval):1: warning: redefine off? # (eval):2: warning: redefine debug # (eval):2: warning: redefine info with_warnings_suppressed do require 'log4r' include Log4r Log4r.define_levels('DEBUG','CMDOUT', 'CMD', 'INFO', 'WARN', 'ERROR', 'FATAL') $log = Logger.new('default') $log.outputters = StdoutOutputter.new( "log_stdout", :level => INFO ) Outputter["log_stdout"].formatter = BuildTool::PlainFormatter.new end module BuildTool class Application include Singleton include MJ::Configuration::Configurable # This is where the script is installed. attr_accessor :root_directory option( "workdir", "Working directory" ). required.on_write{ |val| File.expand_path( val ) } def initialize $noop = false $verbose = false with_warnings_suppressed do @outputter = Outputter["log_stdout"] end @command = CmdParse::CommandParser.new( false, # handle exceptions true # Allow partial command matching ) @command.program_name = "kde4svn-build" @command.program_version = KdeBuild::VERSION @command.options = CmdParse::OptionParserWrapper.new do |opt| opt.separator "Global Options" opt.on( "--verbose", "Verbose output" ) { |t| $verbose = true with_warnings_suppressed do @outputter.level = DEBUG end } opt.on( "--dry-run", "Verbose output" ) { |t| $noop = true } end YAML.add_domain_type( "michael-jansen.biz,2009", "ApplicationConfiguration" ) { |type, val| mc = Application::instance MJ::Configuration::flatten_values val do |k, v| mc.set( k, v ) end mc } @command.add_command( BuildCommand.new ) @command.add_command( CompileCommand.new ) @command.add_command( ConfigureCommand.new ) @command.add_command( CTagsCommand.new ) @command.add_command( FetchCommand.new ) @command.add_command( InfoCommand.new ) @command.add_command( InstallCommand.new ) @command.add_command( RebaseCommand.new ) @command.add_command( HelpCommand.new ) @command.add_command( VersionCommand.new ) end # Read the configuration file. If we can't find a configuration file # provide a template file def read_configuration( name ) configdir = Pathname.new("~").expand_path.join('.build_tool') # Make sure out configuration directory exists if !configdir.exist? # Create it FileUtils.mkdir_p( configdir ) else # It's there. Make sure it's a directory if !configdir.directory? puts "Failed to create configuration directory #{configdir}. There is a file with this name!" return false end end # Check if the configuration file exists configfile = configdir.join( name ) if !configfile.exist? # Copy our template file (if we find it) templatefile = root_directory.join( 'test.yaml.tmpl' ) if !templatefile.exist? $log.error( "Could not find our template file at #{templatefile}!" ) return false end FileUtils.copy( templatefile, configfile ) $log.info( "I copied a template configuration file to '#{configfile}'. Please review it and adapt it to your needs." ) return false end # The config file exists. Go on and read it config_string = File.read(configfile) config = ERB.new( config_string ) @configuration = YAML.load( config.result ) return true end def cli require 'readline' require 'shellwords' Readline.completion_proc = method(:completion) Readline.completer_word_break_characters = "\x00" begin while line = Readline.readline('> ', true) return nil if line.nil? # Remove duplicate or empty lines from history if line =~ /^\s*$/ or Readline::HISTORY.to_a[-2] == line Readline::HISTORY.pop end # Split the line like bash would do it execute Shellwords.shellwords( line ) end rescue Interrupt => e exit end end def completion( string ) args = Shellwords.shellwords(string) # Check if we are able to resolve to a command cmd = @command.main_command.commands[args[0]] if cmd # We are still on the first shellword if args.length == 1 and args[0] != cmd.name return [ cmd.name ] else return cmd.complete args[1..-1] end else # No command. Try to give some possible expansions args[0] = "" if args[0] === nil cmds = [] @command.main_command.commands.each do |name, cmd| if name.start_with? args[0] cmds.push cmd.name end end cmds end end def execute(args) begin @command.parse( args ) rescue CmdParse::InvalidCommandError => e puts e.message @command.main_command.commands.sort.each do |name, cmd| print name.ljust( 15 ) + cmd.short_desc.to_s print " (=default command)" if name == cmd.default_command print "\n" end rescue CmdParse::InvalidOptionError => e puts e.message cmd = @command.main_command.commands[args[0]] cmd.show_help rescue Exception => e puts e.message puts e.backtrace if $verbose end end def log_directory @log_directory end def initialize_logging # Ensure the base log directory exists if !File.exist? "#{workdir}/log" FileUtils.mkdir_p "#{workdir}/log" end i = -1 begin @log_directory = "#{workdir}/log/#{Date.today.to_s}-%02d" % i+=1 end until !File.exist?( @log_directory ) FileUtils.mkdir_p( @log_directory ) with_warnings_suppressed do $log.add( FileOutputter.new( "status", :filename => "#{@log_directory}/build-status", :level => INFO ) ) end end def main(args) if args.length > 0 initialize_logging execute(args) else cli end end end end