diff --git a/vendor/plugins/rcon/bin/rcontool b/vendor/plugins/rcon/bin/rcontool deleted file mode 100644 index 8734dba..0000000 --- a/vendor/plugins/rcon/bin/rcontool +++ /dev/null @@ -1,296 +0,0 @@ -#!/usr/bin/env ruby -################################################################ -# -# rcontool - shell interface to rcon commands -# -# (C) 2006 Erik Hollensbe, License details below -# -# Use 'rcontool -h' for usage instructions. -# -# The compilation of software known as rcontool is distributed under the -# following terms: -# Copyright (C) 2005-2006 Erik Hollensbe. All rights reserved. -# -# Redistribution and use in source form, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -# -# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# -################################################################ - -# -# rubygems hack -# - -begin - require 'rubygems' -rescue LoadError => e -end -begin - require 'rcon' - require 'ip' -rescue LoadError => e - $stderr.puts "rcontool requires the rcon and ip libraries be installed." - $stderr.puts "You can find them both via rubygems or at http://rubyforge.org." - exit -1 -end - -RCONTOOL_VERSION = '0.1.0' - -require 'optparse' -require 'ostruct' - -# -# Manages our options -# - -def get_options - options = OpenStruct.new - # ip address (IP::Address object) - options.ip_address = nil - # port (integer) - options.port = nil - # password - options.password = nil - # protocol type (one of :hlds, :source, :oldquake, :newquake) - options.protocol_type = nil - # verbose, spit out extra information - options.verbose = false - # command to execute on the server - options.command = nil - - optparse = OptionParser.new do |opts| - opts.banner = "Usage: #{File.basename $0} [options]" - opts.separator "" - opts.separator "Options:" - - opts.on("--ip-address [ADDRESS]", - "Provide an IP address to connect to. Does not take a port.") do |ip_address| - if ! options.ip_address.nil? - $stderr.puts "Error: you have already provided an IP Address." - $stderr.puts opts - exit -1 - end - - options.ip_address = IP::Address.new(ip_address) - end - - opts.on("-r", "--port [PORT]", - "Port to connect to.") do |port| - if ! options.port.nil? - $stderr.puts "Error: you have already provided a port." - $stderr.puts opts - exit -1 - end - - options.port = port.to_i - end - - opts.on("-c", "--command [COMMAND]", - "Command to run on the server.") do |command| - if ! options.command.nil? - $stderr.puts "Error: you have already provided a command." - $stderr.puts opts - exit -1 - end - - options.command = command - end - - opts.on("-p", "--password [PASSWORD]", - "Provide a password on the command line.") do |password| - options.password = password - end - - opts.on("-f", "--password-from [FILENAME]", - "Get the password from a file (use '/dev/fd/0' or '/dev/stdin' to read from Standard Input).") do |filename| - if !filename.nil? - f = File.open(filename) - options.password = f.gets.chomp - f.close - else - $stderr.puts "Error: filename (from -f) is not valid." - $stderr.puts opts - exit -1 - end - end - - opts.on("-t", "--protocol-type [TYPE]", [:hlds, :source, :oldquake, :newquake], - "Type of rcon connection to make: (hlds, source, oldquake, newquake).", - " Note: oldquake is quake1/quakeworld, newquake is quake2/3.") do |protocol_type| - options.protocol_type = protocol_type - end - - opts.on("-v", "--[no-]verbose", - "Run verbosely, print information about each packet recieved and turnaround times.") do |verbose| - options.verbose = verbose - end - - opts.on("-h", "--help", - "This help message.") do - $stderr.puts opts - exit -1 - end - - opts.on("--version", "Print the version information.") do - $stderr.puts "This is rcontool version #{RCONTOOL_VERSION}," - $stderr.puts "it is located at #{File.expand_path $0}." - exit -1 - end - - opts.separator "" - opts.separator "Note: IP, port, protocol type, password and command are required to function." - opts.separator "" - opts.separator "Examples (all are equivalent):" - opts.separator "\t#{File.basename($0)} 10.0.0.11 status -t hlds -r 27015 -p foobar" - opts.separator "\techo 'foobar' | #{File.basename($0)} 10.0.0.11:27015 status -t hlds -f /dev/stdin" - opts.separator "\t#{File.basename($0)} --ip-address 10.0.0.11 --port 27015 -c status -t hlds -f file_with_password" - opts.separator "" - - end - - ################################################################ - # - # This hackery is to help facilitate the bareword options if - # they exist, while still allowing for the option parser - # to work properly. - # - ################################################################ - - s1 = ARGV.shift - s2 = ARGV.shift - - begin - options.ip_address = IP::Address::IPv4.new(s1) - options.command = s2 - rescue IP::AddressException => e - # attempt to split it first... not sure how to best handle this situation - begin - ip,port = s1.split(/:/, 2) - options.ip_address = IP::Address::IPv4.new(ip) - options.port = port.to_i - options.command = s2 - rescue Exception => e - end - - if [options.ip_address, options.port].include? nil - ARGV.unshift(s2) - ARGV.unshift(s1) - end - end - - optparse.parse! - - if [options.ip_address, options.protocol_type, options.port, options.password, options.command].include? nil - $stderr.puts optparse - exit -1 - end - - return options -end - -def verbose(string) - $stderr.puts string if $options.verbose -end - -def dump_source_packet(packet) - if $options.verbose - verbose "Request ID: #{packet.request_id}" - verbose "Packet Size: #{packet.packet_size}" - verbose "Response Type: #{packet.command_type}" - end -end - -################################################################ -# -# start main block -# -################################################################ - -$options = get_options - -################################################################ -# -# Source query -# -################################################################ - -if $options.protocol_type == :source - verbose "Protocol type 'SOURCE' selected." - - rcon = RCon::Query::Source.new($options.ip_address.ip_address, $options.port) - - # if we have a verbose request, give all the information we can about - # the query, including the packet information. - rcon.return_packets = $options.verbose - - verbose "Attempting authentication to #{$options.ip_address.ip_address}:#{$options.port} with password '#{$options.password}'" - - value = rcon.auth $options.password - - dump_source_packet value - - if ($options.verbose && value.command_type == RCon::Packet::Source::RESPONSE_AUTH) || value - verbose "Authentication succeeded. Sending command: '#{$options.command}'" - - value = rcon.command $options.command - - dump_source_packet value - verbose "" - - if $options.verbose - puts value.string1 - else - puts value - end - - exit 0 - else - $stderr.puts "Authentication failed." - exit 1 - end - -################################################################ -# -# Original Query -# -################################################################ - -else - rcon = nil - case $options.protocol_type - when :hlds - verbose "Protocol type 'HLDS' selected" - rcon = RCon::Query::Original.new($options.ip_address.ip_address, $options.port, $options.password, - RCon::Query::Original::HLDS) - when :oldquake - verbose "Protocol type 'OLDQUAKE' selected" - rcon = RCon::Query::Original.new($options.ip_address.ip_address, $options.port, $options.password, - RCon::Query::Original::QUAKEWORLD) - when :newquake - verbose "Protocol type 'NEWQUAKE' selected" - rcon = RCon::Query::Original.new($options.ip_address.ip_address, $options.port, $options.password, - RCon::Query::Original::NEWQUAKE) - end - verbose "Attempting transmission to #{$options.ip_address.ip_address}:#{$options.port}" - verbose "Using password: '#{$options.password}' and sending command: '#{$options.command}'" - verbose "" - string = rcon.command($options.command) - - puts string - exit 0 -end - diff --git a/vendor/plugins/rcon/lib/rcon.rb b/vendor/plugins/rcon/lib/rcon.rb deleted file mode 100644 index 9977135..0000000 --- a/vendor/plugins/rcon/lib/rcon.rb +++ /dev/null @@ -1,499 +0,0 @@ -# encoding: US-ASCII - -require 'socket' - -# -# RCon is a module to work with Quake 1/2/3, Half-Life, and Half-Life -# 2 (Source Engine) RCon (Remote Console) protocols. -# -# Version:: 0.2.0 -# Author:: Erik Hollensbe -# License:: BSD -# Contact:: erik@hollensbe.org -# Copyright:: Copyright (c) 2005-2006 Erik Hollensbe -# -# The relevant modules to query RCon are in the RCon::Query namespace, -# under RCon::Query::Original (for Quake 1/2/3 and Half-Life), and -# RCon::Query::Source (for HL2 and CS: Source, and other Source Engine -# games). The RCon::Packet namespace is used to manage complex packet -# structures if required. The Original protocol does not require -# this, but Source does. -# -# Usage is fairly simple: -# -# # Note: Other classes have different constructors -# -# rcon = RCon::Query::Source.new("10.0.0.1", 27015) -# -# rcon.auth("foobar") # source only -# -# rcon.command("mp_friendlyfire") => "mp_friendlyfire = 1" -# -# rcon.cvar("mp_friendlyfire") => 1 -# -#-- -# -# The compilation of software known as rcon.rb is distributed under the -# following terms: -# Copyright (C) 2005-2006 Erik Hollensbe. All rights reserved. -# -# Redistribution and use in source form, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -# -# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -#++ - - -class RCon - class Packet - # placeholder so ruby doesn't bitch - end - class Query - - # - # Convenience method to scrape input from cvar output and return that data. - # Returns integers as a numeric type if possible. - # - # ex: rcon.cvar("mp_friendlyfire") => 1 - # - - def cvar(cvar_name) - response = command(cvar_name) - match = /^.+?\s(?:is|=)\s"([^"]+)".*$/.match response - match = match[1] - if /\D/.match match - return match - else - return match.to_i - end - end - end -end - -# -# RCon::Packet::Source generates a packet structure useful for -# RCon::Query::Source protocol queries. -# -# This class is primarily used internally, but is available if you -# want to do something more advanced with the Source RCon -# protocol. -# -# Use at your own risk. -# - -class RCon::Packet::Source - # execution command - COMMAND_EXEC = 2 - # auth command - COMMAND_AUTH = 3 - # auth response - RESPONSE_AUTH = 2 - # normal response - RESPONSE_NORM = 0 - # packet trailer - TRAILER = "\x00\x00" - - # size of the packet (10 bytes for header + string1 length) - attr_accessor :packet_size - # Request Identifier, used in managing multiple requests at once - attr_accessor :request_id - # Type of command, normally COMMAND_AUTH or COMMAND_EXEC. In response packets, RESPONSE_AUTH or RESPONSE_NORM - attr_accessor :command_type - # First string, the only used one in the protocol, contains - # commands and responses. Null terminated. - attr_accessor :string1 - # Second string, unused by the protocol. Null terminated. - attr_accessor :string2 - - # - # Generate a command packet to be sent to an already - # authenticated RCon connection. Takes the command as an - # argument. - # - def command(string) - @request_id = rand(1000) - @string1 = string - @string2 = TRAILER - @command_type = COMMAND_EXEC - - @packet_size = build_packet.length - - return self - end - - # - # Generate an authentication packet to be sent to a newly - # started RCon connection. Takes the RCon password as an - # argument. - # - def auth(string) - @request_id = rand(1000) - @string1 = string - @string2 = TRAILER - @command_type = COMMAND_AUTH - - @packet_size = build_packet.length - - return self - end - - # - # Builds a packet ready to deliver, without the size prepended. - # Used to calculate the packet size, use #to_s to get the packet - # that srcds actually needs. - # - def build_packet - return [@request_id, @command_type, @string1, @string2].pack("VVa#{@string1.length}a2") - end - - # Returns a string representation of the packet, useful for - # sending and debugging. This include the packet size. - def to_s - packet = build_packet - @packet_size = packet.length - return [@packet_size].pack("V") + packet - end - -end - -# -# RCon::Query::Original queries Quake 1/2/3 and Half-Life servers -# with the rcon protocol. This protocol travels over UDP to the -# game server port, and requires an initial authentication step, -# the information of which is provided at construction time. -# -# Some of the work here (namely the RCon packet structure) was taken -# from the KKRcon code, which is written in perl. -# -# One query per authentication is allowed. -# - -class RCon::Query::Original < RCon::Query - # HLDS-Based Servers - HLDS = "l" - # QuakeWorld/Quake 1 Servers - QUAKEWORLD = "n" - # Quake 2/3 Servers - NEWQUAKE = "" - - # Request to be sent to server - attr_reader :request - # Response from server - attr_reader :response - # Challenge ID (served by server-side of connection) - attr_reader :challenge_id - # UDPSocket object - attr_reader :socket - # Host of connection - attr_reader :host - # Port of connection - attr_reader :port - # RCon password - attr_reader :password - # type of server - attr_reader :server_type - - # - # Creates a RCon::Query::Original object for use. - # - # The type (the default of which is HLDS), has multiple possible - # values: - # - # HLDS - Half Life 1 (will not work with older versions of HLDS) - # - # QUAKEWORLD - QuakeWorld/Quake 1 - # - # NEWQUAKE - Quake 2/3 (and many derivatives) - # - - def initialize(host, port, password, type=HLDS) - @host = host - @port = port - @password = password - @server_type = type - end - - # - # Sends a request given as the argument, and returns the - # response as a string. - # - def command(request) - @request = request - @challenge_id = nil - - establish_connection - - @socket.print "\xFF" * 4 + "challenge rcon\n\x00" - - tmp = retrieve_socket_data - challenge_id = /challenge rcon (\d+)/.match tmp - if challenge_id - @challenge_id = challenge_id[1] - end - - if @challenge_id.nil? - raise RCon::NetworkException.new("RCon challenge ID never returned: wrong rcon password?") - end - - @socket.print "\xFF" * 4 + "rcon #{@challenge_id} \"#{@password}\" #{@request}\n\x00" - @response = retrieve_socket_data - - @response.sub!(/^\xFF\xFF\xFF\xFF#{@server_type}/, "") - @response.sub!(/\x00+$/, "") - - return @response - end - - # - # Disconnects the RCon connection. - # - def disconnect - if @socket - @socket.close - @socket = nil - end - end - - protected - - # - # Establishes the connection. - # - def establish_connection - if @socket.nil? - @socket = UDPSocket.new - @socket.connect(@host, @port) - end - end - - # - # Generic method to pull data from the socket. - # - - def retrieve_socket_data - return "" if @socket.nil? - - retval = "" - loop do - break unless IO.select([@socket], nil, nil, 10) - packet = @socket.recv(8192) - retval << packet - break if packet.length < 8192 - end - - return retval - end - -end - -# -# RCon::Query::Source sends queries to a "Source" Engine server, -# such as Half-Life 2: Deathmatch, Counter-Strike: Source, or Day -# of Defeat: Source. -# -# Note that one authentication packet needs to be sent to send -# multiple commands. Sending multiple authentication packets may -# damage the current connection and require it to be reset. -# -# Note: If the attribute 'return_packets' is set to true, the full -# RCon::Packet::Source object is returned, instead of just a string -# with the headers stripped. Useful for debugging. -# - -class RCon::Query::Source < RCon::Query - # RCon::Packet::Source object that was sent as a result of the last query - attr_reader :packet - # TCPSocket object - attr_reader :socket - # Host of connection - attr_reader :host - # Port of connection - attr_reader :port - # Authentication Status - attr_reader :authed - # return full packet, or just data? - attr_accessor :return_packets - - # - # Given a host and a port (dotted-quad or hostname OK), creates - # a RCon::Query::Source object. Note that this will still - # require an authentication packet (see the auth() method) - # before commands can be sent. - # - - def initialize(host, port) - @host = host - @port = port - @socket = nil - @packet = nil - @authed = false - @return_packets = false - end - - # - # See RCon::Query#cvar. - # - - def cvar(cvar_name) - return_packets = @return_packets - @return_packets = false - response = super - @return_packets = return_packets - return response - end - - # - # Sends a RCon command to the server. May be used multiple times - # after an authentication is successful. - # - # See the class-level documentation on the 'return_packet' attribute - # for return values. The default is to return a string containing - # the response. - # - - def command(command) - - if ! @authed - raise RCon::NetworkException.new("You must authenticate the connection successfully before sending commands.") - end - - @packet = RCon::Packet::Source.new - @packet.command(command) - - @socket.print @packet.to_s - rpacket = build_response_packet - - if rpacket.command_type != RCon::Packet::Source::RESPONSE_NORM - raise RCon::NetworkException.new("error sending command: #{rpacket.command_type}") - end - - if @return_packets - return rpacket - else - return rpacket.string1 - end - end - - # - # Requests authentication from the RCon server, given a - # password. Is only expected to be used once. - # - # See the class-level documentation on the 'return_packet' attribute - # for return values. The default is to return a true value if auth - # succeeded. - # - - def auth(password) - establish_connection - - @packet = RCon::Packet::Source.new - @packet.auth(password) - - @socket.print @packet.to_s - # on auth, one junk packet is sent - rpacket = nil - 2.times { rpacket = build_response_packet } - - if rpacket.command_type != RCon::Packet::Source::RESPONSE_AUTH - raise RCon::NetworkException.new("error authenticating: #{rpacket.command_type}") - end - - @authed = true - if @return_packets - return rpacket - else - return true - end - end - - alias_method :authenticate, :auth - - # - # Disconnects from the Source server. - # - - def disconnect - if @socket - @socket.close - @socket = nil - @authed = false - end - end - - protected - - # - # Builds a RCon::Packet::Source packet based on the response - # given by the server. - # - def build_response_packet - rpacket = RCon::Packet::Source.new - total_size = 0 - request_id = 0 - type = 0 - response = "" - message = "" - - - loop do - break unless IO.select([@socket], nil, nil, 10) - - # - # TODO: clean this up - read everything and then unpack. - # - - tmp = @socket.recv(14) - if tmp.nil? - return nil - end - size, request_id, type, message = tmp.unpack("VVVa*") - total_size += size - - # special case for authentication - break if message.sub!(/\x00\x00$/, "") - - response << message - - # the 'size - 10' here accounts for the fact that we've snarfed 14 bytes, - # the size (which is 4 bytes) is not counted, yet represents the rest - # of the packet (which we have already taken 10 bytes from) - - tmp = @socket.recv(size - 10) - response << tmp - response.sub!(/\x00\x00$/, "") - end - - rpacket.packet_size = total_size - rpacket.request_id = request_id - rpacket.command_type = type - - # strip nulls (this is actually the end of string1 and string2) - rpacket.string1 = response.sub(/\x00\x00$/, "") - return rpacket - end - - # establishes a connection to the server. - def establish_connection - if @socket.nil? - @socket = TCPSocket.new(@host, @port) - end - end - -end - -# Exception class for network errors -class RCon::NetworkException < Exception -end diff --git a/vendor/plugins/rcon/rcon.gemspec b/vendor/plugins/rcon/rcon.gemspec deleted file mode 100644 index 03527ca..0000000 --- a/vendor/plugins/rcon/rcon.gemspec +++ /dev/null @@ -1,13 +0,0 @@ -spec = Gem::Specification.new -spec.name = "rcon" -spec.version = "0.2.1" -spec.author = "Erik Hollensbe" -spec.email = "erik@hollensbe.org" -spec.summary = "Ruby class to work with Quake 1/2/3, Half-Life and Source Engine rcon (remote console)" -spec.has_rdoc = true -spec.autorequire = "rcon" -spec.bindir = 'bin' -spec.executables << 'rcontool' -spec.add_dependency('ip', '>= 0.2.1') -spec.files = Dir['lib/rcon.rb'] + Dir['bin/rcontool'] -spec.rubyforge_project = 'rcon' diff --git a/vendor/plugins/rcon/setup.rb b/vendor/plugins/rcon/setup.rb deleted file mode 100644 index 0807023..0000000 --- a/vendor/plugins/rcon/setup.rb +++ /dev/null @@ -1,1360 +0,0 @@ -# -# setup.rb -# -# Copyright (c) 2000-2004 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# - -unless Enumerable.method_defined?(:map) # Ruby 1.4.6 - module Enumerable - alias map collect - end -end - -unless File.respond_to?(:read) # Ruby 1.6 - def File.read(fname) - open(fname) {|f| - return f.read - } - end -end - -def File.binread(fname) - open(fname, 'rb') {|f| - return f.read - } -end - -# for corrupted windows stat(2) -def File.dir?(path) - File.directory?((path[-1,1] == '/') ? path : path + '/') -end - - -class SetupError < StandardError; end - -def setup_rb_error(msg) - raise SetupError, msg -end - -# -# Config -# - -if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } - ARGV.delete(arg) - require arg.split(/=/, 2)[1] - $".push 'rbconfig.rb' -else - require 'rbconfig' -end - -def multipackage_install? - FileTest.directory?(File.dirname($0) + '/packages') -end - - -class ConfigItem - def initialize(name, template, default, desc) - @name = name.freeze - @template = template - @value = default - @default = default.dup.freeze - @description = desc - end - - attr_reader :name - attr_reader :description - - attr_accessor :default - alias help_default default - - def help_opt - "--#{@name}=#{@template}" - end - - def value - @value - end - - def eval(table) - @value.gsub(%r<\$([^/]+)>) { table[$1] } - end - - def set(val) - @value = check(val) - end - - private - - def check(val) - setup_rb_error "config: --#{name} requires argument" unless val - val - end -end - -class BoolItem < ConfigItem - def config_type - 'bool' - end - - def help_opt - "--#{@name}" - end - - private - - def check(val) - return 'yes' unless val - unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ val - setup_rb_error "config: --#{@name} accepts only yes/no for argument" - end - (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no' - end -end - -class PathItem < ConfigItem - def config_type - 'path' - end - - private - - def check(path) - setup_rb_error "config: --#{@name} requires argument" unless path - path[0,1] == '$' ? path : File.expand_path(path) - end -end - -class ProgramItem < ConfigItem - def config_type - 'program' - end -end - -class SelectItem < ConfigItem - def initialize(name, template, default, desc) - super - @ok = template.split('/') - end - - def config_type - 'select' - end - - private - - def check(val) - unless @ok.include?(val.strip) - setup_rb_error "config: use --#{@name}=#{@template} (#{val})" - end - val.strip - end -end - -class PackageSelectionItem < ConfigItem - def initialize(name, template, default, help_default, desc) - super name, template, default, desc - @help_default = help_default - end - - attr_reader :help_default - - def config_type - 'package' - end - - private - - def check(val) - unless File.dir?("packages/#{val}") - setup_rb_error "config: no such package: #{val}" - end - val - end -end - -class ConfigTable_class - - def initialize(items) - @items = items - @table = {} - items.each do |i| - @table[i.name] = i - end - ALIASES.each do |ali, name| - @table[ali] = @table[name] - end - end - - include Enumerable - - def each(&block) - @items.each(&block) - end - - def key?(name) - @table.key?(name) - end - - def lookup(name) - @table[name] or raise ArgumentError, "no such config item: #{name}" - end - - def add(item) - @items.push item - @table[item.name] = item - end - - def remove(name) - item = lookup(name) - @items.delete_if {|i| i.name == name } - @table.delete_if {|name, i| i.name == name } - item - end - - def new - dup() - end - - def savefile - '.config' - end - - def load - begin - t = dup() - File.foreach(savefile()) do |line| - k, v = *line.split(/=/, 2) - t[k] = v.strip - end - t - rescue Errno::ENOENT - setup_rb_error $!.message + "#{File.basename($0)} config first" - end - end - - def save - @items.each {|i| i.value } - File.open(savefile(), 'w') {|f| - @items.each do |i| - f.printf "%s=%s\n", i.name, i.value if i.value - end - } - end - - def [](key) - lookup(key).eval(self) - end - - def []=(key, val) - lookup(key).set val - end - -end - -c = ::Config::CONFIG - -rubypath = c['bindir'] + '/' + c['ruby_install_name'] - -major = c['MAJOR'].to_i -minor = c['MINOR'].to_i -teeny = c['TEENY'].to_i -version = "#{major}.#{minor}" - -# ruby ver. >= 1.4.4? -newpath_p = ((major >= 2) or - ((major == 1) and - ((minor >= 5) or - ((minor == 4) and (teeny >= 4))))) - -if c['rubylibdir'] - # V < 1.6.3 - _stdruby = c['rubylibdir'] - _siteruby = c['sitedir'] - _siterubyver = c['sitelibdir'] - _siterubyverarch = c['sitearchdir'] -elsif newpath_p - # 1.4.4 <= V <= 1.6.3 - _stdruby = "$prefix/lib/ruby/#{version}" - _siteruby = c['sitedir'] - _siterubyver = "$siteruby/#{version}" - _siterubyverarch = "$siterubyver/#{c['arch']}" -else - # V < 1.4.4 - _stdruby = "$prefix/lib/ruby/#{version}" - _siteruby = "$prefix/lib/ruby/#{version}/site_ruby" - _siterubyver = _siteruby - _siterubyverarch = "$siterubyver/#{c['arch']}" -end -libdir = '-* dummy libdir *-' -stdruby = '-* dummy rubylibdir *-' -siteruby = '-* dummy site_ruby *-' -siterubyver = '-* dummy site_ruby version *-' -parameterize = lambda {|path| - path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')\ - .sub(/\A#{Regexp.quote(libdir)}/, '$libdir')\ - .sub(/\A#{Regexp.quote(stdruby)}/, '$stdruby')\ - .sub(/\A#{Regexp.quote(siteruby)}/, '$siteruby')\ - .sub(/\A#{Regexp.quote(siterubyver)}/, '$siterubyver') -} -libdir = parameterize.call(c['libdir']) -stdruby = parameterize.call(_stdruby) -siteruby = parameterize.call(_siteruby) -siterubyver = parameterize.call(_siterubyver) -siterubyverarch = parameterize.call(_siterubyverarch) - -if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } - makeprog = arg.sub(/'/, '').split(/=/, 2)[1] -else - makeprog = 'make' -end - -common_conf = [ - PathItem.new('prefix', 'path', c['prefix'], - 'path prefix of target environment'), - PathItem.new('bindir', 'path', parameterize.call(c['bindir']), - 'the directory for commands'), - PathItem.new('libdir', 'path', libdir, - 'the directory for libraries'), - PathItem.new('datadir', 'path', parameterize.call(c['datadir']), - 'the directory for shared data'), - PathItem.new('mandir', 'path', parameterize.call(c['mandir']), - 'the directory for man pages'), - PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), - 'the directory for man pages'), - PathItem.new('stdruby', 'path', stdruby, - 'the directory for standard ruby libraries'), - PathItem.new('siteruby', 'path', siteruby, - 'the directory for version-independent aux ruby libraries'), - PathItem.new('siterubyver', 'path', siterubyver, - 'the directory for aux ruby libraries'), - PathItem.new('siterubyverarch', 'path', siterubyverarch, - 'the directory for aux ruby binaries'), - PathItem.new('rbdir', 'path', '$siterubyver', - 'the directory for ruby scripts'), - PathItem.new('sodir', 'path', '$siterubyverarch', - 'the directory for ruby extentions'), - PathItem.new('rubypath', 'path', rubypath, - 'the path to set to #! line'), - ProgramItem.new('rubyprog', 'name', rubypath, - 'the ruby program using for installation'), - ProgramItem.new('makeprog', 'name', makeprog, - 'the make program to compile ruby extentions'), - SelectItem.new('shebang', 'all/ruby/never', 'ruby', - 'shebang line (#!) editing mode'), - BoolItem.new('without-ext', 'yes/no', 'no', - 'does not compile/install ruby extentions') -] -class ConfigTable_class # open again - ALIASES = { - 'std-ruby' => 'stdruby', - 'site-ruby-common' => 'siteruby', # For backward compatibility - 'site-ruby' => 'siterubyver', # For backward compatibility - 'bin-dir' => 'bindir', - 'bin-dir' => 'bindir', - 'rb-dir' => 'rbdir', - 'so-dir' => 'sodir', - 'data-dir' => 'datadir', - 'ruby-path' => 'rubypath', - 'ruby-prog' => 'rubyprog', - 'ruby' => 'rubyprog', - 'make-prog' => 'makeprog', - 'make' => 'makeprog' - } -end -multipackage_conf = [ - PackageSelectionItem.new('with', 'name,name...', '', 'ALL', - 'package names that you want to install'), - PackageSelectionItem.new('without', 'name,name...', '', 'NONE', - 'package names that you do not want to install') -] -if multipackage_install? - ConfigTable = ConfigTable_class.new(common_conf + multipackage_conf) -else - ConfigTable = ConfigTable_class.new(common_conf) -end - - -module MetaConfigAPI - - def eval_file_ifexist(fname) - instance_eval File.read(fname), fname, 1 if File.file?(fname) - end - - def config_names - ConfigTable.map {|i| i.name } - end - - def config?(name) - ConfigTable.key?(name) - end - - def bool_config?(name) - ConfigTable.lookup(name).config_type == 'bool' - end - - def path_config?(name) - ConfigTable.lookup(name).config_type == 'path' - end - - def value_config?(name) - case ConfigTable.lookup(name).config_type - when 'bool', 'path' - true - else - false - end - end - - def add_config(item) - ConfigTable.add item - end - - def add_bool_config(name, default, desc) - ConfigTable.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) - end - - def add_path_config(name, default, desc) - ConfigTable.add PathItem.new(name, 'path', default, desc) - end - - def set_config_default(name, default) - ConfigTable.lookup(name).default = default - end - - def remove_config(name) - ConfigTable.remove(name) - end - -end - - -# -# File Operations -# - -module FileOperations - - def mkdir_p(dirname, prefix = nil) - dirname = prefix + File.expand_path(dirname) if prefix - $stderr.puts "mkdir -p #{dirname}" if verbose? - return if no_harm? - - # does not check '/'... it's too abnormal case - dirs = File.expand_path(dirname).split(%r<(?=/)>) - if /\A[a-z]:\z/i =~ dirs[0] - disk = dirs.shift - dirs[0] = disk + dirs[0] - end - dirs.each_index do |idx| - path = dirs[0..idx].join('') - Dir.mkdir path unless File.dir?(path) - end - end - - def rm_f(fname) - $stderr.puts "rm -f #{fname}" if verbose? - return if no_harm? - - if File.exist?(fname) or File.symlink?(fname) - File.chmod 0777, fname - File.unlink fname - end - end - - def rm_rf(dn) - $stderr.puts "rm -rf #{dn}" if verbose? - return if no_harm? - - Dir.chdir dn - Dir.foreach('.') do |fn| - next if fn == '.' - next if fn == '..' - if File.dir?(fn) - verbose_off { - rm_rf fn - } - else - verbose_off { - rm_f fn - } - end - end - Dir.chdir '..' - Dir.rmdir dn - end - - def move_file(src, dest) - File.unlink dest if File.exist?(dest) - begin - File.rename src, dest - rescue - File.open(dest, 'wb') {|f| f.write File.binread(src) } - File.chmod File.stat(src).mode, dest - File.unlink src - end - end - - def install(from, dest, mode, prefix = nil) - $stderr.puts "install #{from} #{dest}" if verbose? - return if no_harm? - - realdest = prefix ? prefix + File.expand_path(dest) : dest - realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) - str = File.binread(from) - if diff?(str, realdest) - verbose_off { - rm_f realdest if File.exist?(realdest) - } - File.open(realdest, 'wb') {|f| - f.write str - } - File.chmod mode, realdest - - File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| - if prefix - f.puts realdest.sub(prefix, '') - else - f.puts realdest - end - } - end - end - - def diff?(new_content, path) - return true unless File.exist?(path) - new_content != File.binread(path) - end - - def command(str) - $stderr.puts str if verbose? - system str or raise RuntimeError, "'system #{str}' failed" - end - - def ruby(str) - command config('rubyprog') + ' ' + str - end - - def make(task = '') - command config('makeprog') + ' ' + task - end - - def extdir?(dir) - File.exist?(dir + '/MANIFEST') - end - - def all_files_in(dirname) - Dir.open(dirname) {|d| - return d.select {|ent| File.file?("#{dirname}/#{ent}") } - } - end - - REJECT_DIRS = %w( - CVS SCCS RCS CVS.adm .svn - ) - - def all_dirs_in(dirname) - Dir.open(dirname) {|d| - return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS - } - end - -end - - -# -# Main Installer -# - -module HookUtils - - def run_hook(name) - try_run_hook "#{curr_srcdir()}/#{name}" or - try_run_hook "#{curr_srcdir()}/#{name}.rb" - end - - def try_run_hook(fname) - return false unless File.file?(fname) - begin - instance_eval File.read(fname), fname, 1 - rescue - setup_rb_error "hook #{fname} failed:\n" + $!.message - end - true - end - -end - - -module HookScriptAPI - - def get_config(key) - @config[key] - end - - alias config get_config - - def set_config(key, val) - @config[key] = val - end - - # - # srcdir/objdir (works only in the package directory) - # - - #abstract srcdir_root - #abstract objdir_root - #abstract relpath - - def curr_srcdir - "#{srcdir_root()}/#{relpath()}" - end - - def curr_objdir - "#{objdir_root()}/#{relpath()}" - end - - def srcfile(path) - "#{curr_srcdir()}/#{path}" - end - - def srcexist?(path) - File.exist?(srcfile(path)) - end - - def srcdirectory?(path) - File.dir?(srcfile(path)) - end - - def srcfile?(path) - File.file? srcfile(path) - end - - def srcentries(path = '.') - Dir.open("#{curr_srcdir()}/#{path}") {|d| - return d.to_a - %w(. ..) - } - end - - def srcfiles(path = '.') - srcentries(path).select {|fname| - File.file?(File.join(curr_srcdir(), path, fname)) - } - end - - def srcdirectories(path = '.') - srcentries(path).select {|fname| - File.dir?(File.join(curr_srcdir(), path, fname)) - } - end - -end - - -class ToplevelInstaller - - Version = '3.3.1' - Copyright = 'Copyright (c) 2000-2004 Minero Aoki' - - TASKS = [ - [ 'all', 'do config, setup, then install' ], - [ 'config', 'saves your configurations' ], - [ 'show', 'shows current configuration' ], - [ 'setup', 'compiles ruby extentions and others' ], - [ 'install', 'installs files' ], - [ 'clean', "does `make clean' for each extention" ], - [ 'distclean',"does `make distclean' for each extention" ] - ] - - def ToplevelInstaller.invoke - instance().invoke - end - - @singleton = nil - - def ToplevelInstaller.instance - @singleton ||= new(File.dirname($0)) - @singleton - end - - include MetaConfigAPI - - def initialize(ardir_root) - @config = nil - @options = { 'verbose' => true } - @ardir = File.expand_path(ardir_root) - end - - def inspect - "#<#{self.class} #{__id__()}>" - end - - def invoke - run_metaconfigs - case task = parsearg_global() - when nil, 'all' - @config = load_config('config') - parsearg_config - init_installers - exec_config - exec_setup - exec_install - else - @config = load_config(task) - __send__ "parsearg_#{task}" - init_installers - __send__ "exec_#{task}" - end - end - - def run_metaconfigs - eval_file_ifexist "#{@ardir}/metaconfig" - end - - def load_config(task) - case task - when 'config' - ConfigTable.new - when 'clean', 'distclean' - if File.exist?(ConfigTable.savefile) - then ConfigTable.load - else ConfigTable.new - end - else - ConfigTable.load - end - end - - def init_installers - @installer = Installer.new(@config, @options, @ardir, File.expand_path('.')) - end - - # - # Hook Script API bases - # - - def srcdir_root - @ardir - end - - def objdir_root - '.' - end - - def relpath - '.' - end - - # - # Option Parsing - # - - def parsearg_global - valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/ - - while arg = ARGV.shift - case arg - when /\A\w+\z/ - setup_rb_error "invalid task: #{arg}" unless valid_task =~ arg - return arg - - when '-q', '--quiet' - @options['verbose'] = false - - when '--verbose' - @options['verbose'] = true - - when '-h', '--help' - print_usage $stdout - exit 0 - - when '-v', '--version' - puts "#{File.basename($0)} version #{Version}" - exit 0 - - when '--copyright' - puts Copyright - exit 0 - - else - setup_rb_error "unknown global option '#{arg}'" - end - end - - nil - end - - - def parsearg_no_options - unless ARGV.empty? - setup_rb_error "#{task}: unknown options: #{ARGV.join ' '}" - end - end - - alias parsearg_show parsearg_no_options - alias parsearg_setup parsearg_no_options - alias parsearg_clean parsearg_no_options - alias parsearg_distclean parsearg_no_options - - def parsearg_config - re = /\A--(#{ConfigTable.map {|i| i.name }.join('|')})(?:=(.*))?\z/ - @options['config-opt'] = [] - - while i = ARGV.shift - if /\A--?\z/ =~ i - @options['config-opt'] = ARGV.dup - break - end - m = re.match(i) or setup_rb_error "config: unknown option #{i}" - name, value = *m.to_a[1,2] - @config[name] = value - end - end - - def parsearg_install - @options['no-harm'] = false - @options['install-prefix'] = '' - while a = ARGV.shift - case a - when /\A--no-harm\z/ - @options['no-harm'] = true - when /\A--prefix=(.*)\z/ - path = $1 - path = File.expand_path(path) unless path[0,1] == '/' - @options['install-prefix'] = path - else - setup_rb_error "install: unknown option #{a}" - end - end - end - - def print_usage(out) - out.puts 'Typical Installation Procedure:' - out.puts " $ ruby #{File.basename $0} config" - out.puts " $ ruby #{File.basename $0} setup" - out.puts " # ruby #{File.basename $0} install (may require root privilege)" - out.puts - out.puts 'Detailed Usage:' - out.puts " ruby #{File.basename $0} " - out.puts " ruby #{File.basename $0} [] []" - - fmt = " %-24s %s\n" - out.puts - out.puts 'Global options:' - out.printf fmt, '-q,--quiet', 'suppress message outputs' - out.printf fmt, ' --verbose', 'output messages verbosely' - out.printf fmt, '-h,--help', 'print this message' - out.printf fmt, '-v,--version', 'print version and quit' - out.printf fmt, ' --copyright', 'print copyright and quit' - out.puts - out.puts 'Tasks:' - TASKS.each do |name, desc| - out.printf fmt, name, desc - end - - fmt = " %-24s %s [%s]\n" - out.puts - out.puts 'Options for CONFIG or ALL:' - ConfigTable.each do |item| - out.printf fmt, item.help_opt, item.description, item.help_default - end - out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" - out.puts - out.puts 'Options for INSTALL:' - out.printf fmt, '--no-harm', 'only display what to do if given', 'off' - out.printf fmt, '--prefix=path', 'install path prefix', '$prefix' - out.puts - end - - # - # Task Handlers - # - - def exec_config - @installer.exec_config - @config.save # must be final - end - - def exec_setup - @installer.exec_setup - end - - def exec_install - @installer.exec_install - end - - def exec_show - ConfigTable.each do |i| - printf "%-20s %s\n", i.name, i.value - end - end - - def exec_clean - @installer.exec_clean - end - - def exec_distclean - @installer.exec_distclean - end - -end - - -class ToplevelInstallerMulti < ToplevelInstaller - - include HookUtils - include HookScriptAPI - include FileOperations - - def initialize(ardir) - super - @packages = all_dirs_in("#{@ardir}/packages") - raise 'no package exists' if @packages.empty? - end - - def run_metaconfigs - eval_file_ifexist "#{@ardir}/metaconfig" - @packages.each do |name| - eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig" - end - end - - def init_installers - @installers = {} - @packages.each do |pack| - @installers[pack] = Installer.new(@config, @options, - "#{@ardir}/packages/#{pack}", - "packages/#{pack}") - end - - with = extract_selection(config('with')) - without = extract_selection(config('without')) - @selected = @installers.keys.select {|name| - (with.empty? or with.include?(name)) \ - and not without.include?(name) - } - end - - def extract_selection(list) - a = list.split(/,/) - a.each do |name| - setup_rb_error "no such package: #{name}" unless @installers.key?(name) - end - a - end - - def print_usage(f) - super - f.puts 'Inluded packages:' - f.puts ' ' + @packages.sort.join(' ') - f.puts - end - - # - # multi-package metaconfig API - # - - attr_reader :packages - - def declare_packages(list) - raise 'package list is empty' if list.empty? - list.each do |name| - raise "directory packages/#{name} does not exist"\ - unless File.dir?("#{@ardir}/packages/#{name}") - end - @packages = list - end - - # - # Task Handlers - # - - def exec_config - run_hook 'pre-config' - each_selected_installers {|inst| inst.exec_config } - run_hook 'post-config' - @config.save # must be final - end - - def exec_setup - run_hook 'pre-setup' - each_selected_installers {|inst| inst.exec_setup } - run_hook 'post-setup' - end - - def exec_install - run_hook 'pre-install' - each_selected_installers {|inst| inst.exec_install } - run_hook 'post-install' - end - - def exec_clean - rm_f ConfigTable.savefile - run_hook 'pre-clean' - each_selected_installers {|inst| inst.exec_clean } - run_hook 'post-clean' - end - - def exec_distclean - rm_f ConfigTable.savefile - run_hook 'pre-distclean' - each_selected_installers {|inst| inst.exec_distclean } - run_hook 'post-distclean' - end - - # - # lib - # - - def each_selected_installers - Dir.mkdir 'packages' unless File.dir?('packages') - @selected.each do |pack| - $stderr.puts "Processing the package `#{pack}' ..." if @options['verbose'] - Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") - Dir.chdir "packages/#{pack}" - yield @installers[pack] - Dir.chdir '../..' - end - end - - def verbose? - @options['verbose'] - end - - def no_harm? - @options['no-harm'] - end - -end - - -class Installer - - FILETYPES = %w( bin lib ext data ) - - include HookScriptAPI - include HookUtils - include FileOperations - - def initialize(config, opt, srcroot, objroot) - @config = config - @options = opt - @srcdir = File.expand_path(srcroot) - @objdir = File.expand_path(objroot) - @currdir = '.' - end - - def inspect - "#<#{self.class} #{File.basename(@srcdir)}>" - end - - # - # Hook Script API base methods - # - - def srcdir_root - @srcdir - end - - def objdir_root - @objdir - end - - def relpath - @currdir - end - - # - # configs/options - # - - def no_harm? - @options['no-harm'] - end - - def verbose? - @options['verbose'] - end - - def verbose_off - begin - save, @options['verbose'] = @options['verbose'], false - yield - ensure - @options['verbose'] = save - end - end - - # - # TASK config - # - - def exec_config - exec_task_traverse 'config' - end - - def config_dir_bin(rel) - end - - def config_dir_lib(rel) - end - - def config_dir_ext(rel) - extconf if extdir?(curr_srcdir()) - end - - def extconf - opt = @options['config-opt'].join(' ') - command "#{config('rubyprog')} #{curr_srcdir()}/extconf.rb #{opt}" - end - - def config_dir_data(rel) - end - - # - # TASK setup - # - - def exec_setup - exec_task_traverse 'setup' - end - - def setup_dir_bin(rel) - all_files_in(curr_srcdir()).each do |fname| - adjust_shebang "#{curr_srcdir()}/#{fname}" - end - end - - def adjust_shebang(path) - return if no_harm? - tmpfile = File.basename(path) + '.tmp' - begin - File.open(path, 'rb') {|r| - first = r.gets - return unless File.basename(config('rubypath')) == 'ruby' - return unless File.basename(first.sub(/\A\#!/, '').split[0]) == 'ruby' - $stderr.puts "adjusting shebang: #{File.basename(path)}" if verbose? - File.open(tmpfile, 'wb') {|w| - w.print first.sub(/\A\#!\s*\S+/, '#! ' + config('rubypath')) - w.write r.read - } - move_file tmpfile, File.basename(path) - } - ensure - File.unlink tmpfile if File.exist?(tmpfile) - end - end - - def setup_dir_lib(rel) - end - - def setup_dir_ext(rel) - make if extdir?(curr_srcdir()) - end - - def setup_dir_data(rel) - end - - # - # TASK install - # - - def exec_install - rm_f 'InstalledFiles' - exec_task_traverse 'install' - end - - def install_dir_bin(rel) - install_files collect_filenames_auto(), "#{config('bindir')}/#{rel}", 0755 - end - - def install_dir_lib(rel) - install_files ruby_scripts(), "#{config('rbdir')}/#{rel}", 0644 - end - - def install_dir_ext(rel) - return unless extdir?(curr_srcdir()) - install_files ruby_extentions('.'), - "#{config('sodir')}/#{File.dirname(rel)}", - 0555 - end - - def install_dir_data(rel) - install_files collect_filenames_auto(), "#{config('datadir')}/#{rel}", 0644 - end - - def install_files(list, dest, mode) - mkdir_p dest, @options['install-prefix'] - list.each do |fname| - install fname, dest, mode, @options['install-prefix'] - end - end - - def ruby_scripts - collect_filenames_auto().select {|n| /\.rb\z/ =~ n } - end - - # picked up many entries from cvs-1.11.1/src/ignore.c - reject_patterns = %w( - core RCSLOG tags TAGS .make.state - .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb - *~ *.old *.bak *.BAK *.orig *.rej _$* *$ - - *.org *.in .* - ) - mapping = { - '.' => '\.', - '$' => '\$', - '#' => '\#', - '*' => '.*' - } - REJECT_PATTERNS = Regexp.new('\A(?:' + - reject_patterns.map {|pat| - pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] } - }.join('|') + - ')\z') - - def collect_filenames_auto - mapdir((existfiles() - hookfiles()).reject {|fname| - REJECT_PATTERNS =~ fname - }) - end - - def existfiles - all_files_in(curr_srcdir()) | all_files_in('.') - end - - def hookfiles - %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| - %w( config setup install clean ).map {|t| sprintf(fmt, t) } - }.flatten - end - - def mapdir(filelist) - filelist.map {|fname| - if File.exist?(fname) # objdir - fname - else # srcdir - File.join(curr_srcdir(), fname) - end - } - end - - def ruby_extentions(dir) - Dir.open(dir) {|d| - ents = d.select {|fname| /\.#{::Config::CONFIG['DLEXT']}\z/ =~ fname } - if ents.empty? - setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" - end - return ents - } - end - - # - # TASK clean - # - - def exec_clean - exec_task_traverse 'clean' - rm_f ConfigTable.savefile - rm_f 'InstalledFiles' - end - - def clean_dir_bin(rel) - end - - def clean_dir_lib(rel) - end - - def clean_dir_ext(rel) - return unless extdir?(curr_srcdir()) - make 'clean' if File.file?('Makefile') - end - - def clean_dir_data(rel) - end - - # - # TASK distclean - # - - def exec_distclean - exec_task_traverse 'distclean' - rm_f ConfigTable.savefile - rm_f 'InstalledFiles' - end - - def distclean_dir_bin(rel) - end - - def distclean_dir_lib(rel) - end - - def distclean_dir_ext(rel) - return unless extdir?(curr_srcdir()) - make 'distclean' if File.file?('Makefile') - end - - # - # lib - # - - def exec_task_traverse(task) - run_hook "pre-#{task}" - FILETYPES.each do |type| - if config('without-ext') == 'yes' and type == 'ext' - $stderr.puts 'skipping ext/* by user option' if verbose? - next - end - traverse task, type, "#{task}_dir_#{type}" - end - run_hook "post-#{task}" - end - - def traverse(task, rel, mid) - dive_into(rel) { - run_hook "pre-#{task}" - __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') - all_dirs_in(curr_srcdir()).each do |d| - traverse task, "#{rel}/#{d}", mid - end - run_hook "post-#{task}" - } - end - - def dive_into(rel) - return unless File.dir?("#{@srcdir}/#{rel}") - - dir = File.basename(rel) - Dir.mkdir dir unless File.dir?(dir) - prevdir = Dir.pwd - Dir.chdir dir - $stderr.puts '---> ' + rel if verbose? - @currdir = rel - yield - Dir.chdir prevdir - $stderr.puts '<--- ' + rel if verbose? - @currdir = File.dirname(rel) - end - -end - - -if $0 == __FILE__ - begin - if multipackage_install? - ToplevelInstallerMulti.invoke - else - ToplevelInstaller.invoke - end - rescue SetupError - raise if $DEBUG - $stderr.puts $!.message - $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." - exit 1 - end -end