aboutsummaryrefslogtreecommitdiffhomepage
path: root/sisu-install
diff options
context:
space:
mode:
authorRalph Amissah <ralph@amissah.com>2013-11-08 20:52:43 -0500
committerRalph Amissah <ralph@amissah.com>2013-11-08 21:02:50 -0500
commitcf8ff1a3ec40f321e9ecf7afdbc4f1b8254597a4 (patch)
tree9761cfba7c6f58df6076e7a91d92787bbe4d518f /sisu-install
parentv4 v5: sisu_manual, minor info addition (diff)
v4 v5: rake (& rant) sisu installer
* do less by default * remove rant generated sisu-install
Diffstat (limited to 'sisu-install')
-rwxr-xr-xsisu-install3088
1 files changed, 0 insertions, 3088 deletions
diff --git a/sisu-install b/sisu-install
deleted file mode 100755
index 206867fd..00000000
--- a/sisu-install
+++ /dev/null
@@ -1,3088 +0,0 @@
-#!/usr/bin/env ruby
-
-# sisu-install - Monolithic rant script, autogenerated by rant-import 0.5.8.
-#
-# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
-#
-# 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.
-
-
-require 'getoptlong'
-
-
-require 'rbconfig'
-
-unless Process::Status.method_defined?(:success?) # new in 1.8.2
- class Process::Status
- def success?; exitstatus == 0; end
- end
-end
-unless Regexp.respond_to? :union # new in 1.8.1
- def Regexp.union(*patterns)
- return /(?!)/ if patterns.empty?
- Regexp.new(patterns.join("|"))
- end
-end
-if RUBY_VERSION < "1.8.2"
- class Array
- undef_method :flatten, :flatten!
- def flatten
- cp = self.dup
- cp.flatten!
- cp
- end
- def flatten!
- res = []
- flattened = false
- self.each { |e|
- if e.respond_to? :to_ary
- res.concat(e.to_ary)
- flattened = true
- else
- res << e
- end
- }
- if flattened
- replace(res)
- flatten!
- self
- end
- end
- end
-end
-
-class String
- def _rant_sub_ext(ext, new_ext = nil)
- if new_ext
- self.sub(/#{Regexp.escape ext}$/, new_ext)
- else
- self.sub(/(\.[^.]*$)|$/, ".#{ext}")
- end
- end
-end
-
-module Rant
- VERSION = '0.5.8'
-
- @__rant_no_value__ = Object.new.freeze
- def self.__rant_no_value__
- @__rant_no_value__
- end
-
- module Env
- OS = ::Config::CONFIG['target']
- RUBY = ::Config::CONFIG['ruby_install_name']
- RUBY_BINDIR = ::Config::CONFIG['bindir']
- RUBY_EXE = File.join(RUBY_BINDIR, RUBY + ::Config::CONFIG["EXEEXT"])
-
- @@zip_bin = false
- @@tar_bin = false
-
- if OS =~ /mswin/i
- def on_windows?; true; end
- else
- def on_windows?; false; end
- end
-
- def have_zip?
- if @@zip_bin == false
- @@zip_bin = find_bin "zip"
- end
- !@@zip_bin.nil?
- end
- def have_tar?
- if @@tar_bin == false
- @@tar_bin = find_bin "tar"
- end
- !@@tar_bin.nil?
- end
- def pathes
- path = ENV[on_windows? ? "Path" : "PATH"]
- return [] unless path
- path.split(on_windows? ? ";" : ":")
- end
- def find_bin bin_name
- if on_windows?
- bin_name_exe = nil
- if bin_name !~ /\.[^\.]{1,3}$/i
- bin_name_exe = bin_name + ".exe"
- end
- pathes.each { |dir|
- file = File.join(dir, bin_name)
- return file if test(?f, file)
- if bin_name_exe
- file = File.join(dir, bin_name_exe)
- return file if test(?f, file)
- end
- }
- else
- pathes.each { |dir|
- file = File.join(dir, bin_name)
- return file if test(?x, file)
- }
- end
- nil
- end
- def shell_path path
- if on_windows?
- path = path.tr("/", "\\")
- if path.include? ' '
- '"' + path + '"'
- else
- path
- end
- else
- if path.include? ' '
- "'" + path + "'"
- else
- path
- end
- end
- end
- extend self
- end # module Env
-
- module Sys
- def sp(arg)
- if arg.respond_to? :to_ary
- arg.to_ary.map{ |e| sp e }.join(' ')
- else
- _escaped_path arg
- end
- end
- def escape(arg)
- if arg.respond_to? :to_ary
- arg.to_ary.map{ |e| escape e }.join(' ')
- else
- _escaped arg
- end
- end
- if Env.on_windows?
- def _escaped_path(path)
- _escaped(path.to_s.tr("/", "\\"))
- end
- def _escaped(arg)
- sarg = arg.to_s
- return sarg unless sarg.include?(" ")
- sarg << "\\" if sarg[-1].chr == "\\"
- "\"#{sarg}\""
- end
- def regular_filename(fn)
- fn.to_str.tr("\\", "/").gsub(%r{/{2,}}, "/")
- end
- else
- def _escaped_path(path)
- path.to_s.gsub(/(?=\s)/, "\\")
- end
- alias _escaped _escaped_path
- def regular_filename(fn)
- fn.to_str.gsub(%r{/{2,}}, "/")
- end
- end
- private :_escaped_path
- private :_escaped
- def split_all(path)
- names = regular_filename(path).split(%r{/})
- names[0] = "/" if names[0] && names[0].empty?
- names
- end
- extend self
- end # module Sys
-
-
- ROOT_RANTFILE = "root.rant"
- SUB_RANTFILE = "sub.rant"
- RANTFILES = [ "Rantfile", "rantfile", ROOT_RANTFILE ]
-
- CODE_IMPORTS = []
-
- class RantAbortException < StandardError
- end
-
- class RantDoneException < StandardError
- end
-
- class Error < StandardError
- end
-
- module Generators
- end
-
- module RantVar
-
- class Error < Rant::Error
- end
-
- class ConstraintError < Error
-
- attr_reader :constraint, :val
-
- def initialize(constraint, val, msg = nil)
- @msg = msg
- @constraint = constraint
- @val = val
- end
-
- def message
- val_desc = @val.inspect
- val_desc[7..-1] = "..." if val_desc.length > 10
- "#{val_desc} doesn't match constraint: #@constraint"
- end
- end
-
- class NotAConstraintFactoryError < Error
- attr_reader :obj
- def initialize(obj, msg = nil)
- @msg = msg
- @obj = obj
- end
- def message
- obj_desc = @obj.inspect
- obj_desc[7..-1] = "..." if obj_desc.length > 10
- "#{obj_desc} is not a valid constraint factory"
- end
- end
-
- class InvalidVidError < Error
- def initialize(vid, msg = nil)
- @msg = msg
- @vid = vid
- end
- def message
- vid_desc = @vid.inspect
- vid_desc[7..-1] = "..." if vid_desc.length > 10
- "#{vid_desc} is not a valid var identifier"
- end
- end
-
- class InvalidConstraintError < Error
- end
-
- class QueryError < Error
- end
-
- class Space
-
- @@env_ref = Object.new
-
- def initialize
- @store = {}
- @constraints = {}
- end
-
- def query(*args, &block)
- case args.size
- when 0
- raise QueryError, "no arguments", caller
- when 1
- arg = args.first
- if Hash === arg
- if arg.size == 1
- arg.each { |k,v|
- self[k] = v if self[k].nil?
- }
- self
- else
- init_all arg
- end
- else
- self[arg]
- end
- when 2, 3
- vid, cf, val = *args
- constrain vid,
- get_factory(cf).rant_constraint
- self[vid] = val if val
- else
- raise QueryError, "too many arguments"
- end
- end
-
- def restrict vid, ct, *ct_args
- if vid.respond_to? :to_ary
- vid.to_ary.each { |v| restrict(v, ct, *ct_args) }
- else
- constrain vid,
- get_factory(ct).rant_constraint(*ct_args)
- end
- self
- end
-
- def get_factory id
- if String === id || Symbol === id
- id = Constraints.const_get(id) rescue nil
- end
- unless id.respond_to? :rant_constraint
- raise NotAConstraintFactoryError.new(id), caller
- end
- id
- end
- private :get_factory
-
- def [](vid)
- vid = RantVar.valid_vid vid
- val = @store[vid]
- val.equal?(@@env_ref) ? ENV[vid] : val
- end
-
- def []=(vid, val)
- vid = RantVar.valid_vid(vid)
- c = @constraints[vid]
- if @store[vid] == @@env_ref
- ENV[vid] = c ? c.filter(val) : val
- else
- @store[vid] = c ? c.filter(val) : val
- end
- end
-
- def env(*vars)
- vars.flatten.each { |var|
- vid = RantVar.valid_vid(var)
- cur_val = @store[vid]
- next if cur_val == @@env_ref
- ENV[vid] = cur_val unless cur_val.nil?
- @store[vid] = @@env_ref
- }
- nil
- end
-
- def set_all hash
- unless Hash === hash
- raise QueryError,
- "set_all argument has to be a hash"
- end
- hash.each_pair { |k, v|
- self[k] = v
- }
- end
-
- def init_all hash
- unless Hash === hash
- raise QueryError,
- "init_all argument has to be a hash"
- end
- hash.each_pair { |k, v|
- self[k] = v if self[k].nil?
- }
- end
-
- def constrain vid, constraint
- vid = RantVar.valid_vid(vid)
- unless RantVar.valid_constraint? constraint
- raise InvalidConstraintError, constraint
- end
- @constraints[vid] = constraint
- if @store.member? vid
- begin
- val = @store[vid]
- @store[vid] = constraint.filter(@store[vid])
- rescue
- @store[vid] = constraint.default
- raise ConstraintError.new(constraint, val)
- end
- else
- @store[vid] = constraint.default
- end
- end
-
- def has_var?(vid)
- !self[vid].nil?
- end
-
- def _set(vid, val) #:nodoc:
- @store[vid] = val
- end
-
- def _get(vid) #:nodoc:
- @store[vid]
- end
-
- def _init(vid, val) #:nodoc:
- @store[vid] ||= val
- end
-
- end # class Space
-
- module Constraint
- def matches? val
- filter val
- true
- rescue
- return false
- end
- end
-
- def valid_vid(obj)
- case obj
- when String; obj
- when Symbol; obj.to_s
- else
- if obj.respond_to? :to_str
- obj.to_str
- else
- raise InvalidVidError.new(obj)
- end
- end
- end
-
- def valid_constraint?(obj)
- obj.respond_to?(:filter) &&
- obj.respond_to?(:matches?) &&
- obj.respond_to?(:default)
- end
-
- module_function :valid_constraint?, :valid_vid
-
- module Constraints
- class AutoList
- include Constraint
- class << self
- alias rant_constraint new
- end
- def filter(val)
- if val.respond_to? :to_ary
- val.to_ary
- elsif val.nil?
- raise ConstraintError.new(self, val)
- else
- [val]
- end
- end
- def default
- []
- end
- def to_s
- "list or single, non-nil value"
- end
- end
- end # module Constraints
- end # module RantVar
-end # module Rant
-
-
-require 'fileutils'
-
-
-module Rant
- def FileList(arg)
- if arg.respond_to?(:to_rant_filelist)
- arg.to_rant_filelist
- elsif arg.respond_to?(:to_ary)
- FileList.new(arg.to_ary)
- else
- raise TypeError,
- "cannot convert #{arg.class} into Rant::FileList"
- end
- end
- module_function :FileList
- class FileList
- include Enumerable
-
- ESC_SEPARATOR = Regexp.escape(File::SEPARATOR)
- ESC_ALT_SEPARATOR = File::ALT_SEPARATOR ?
- Regexp.escape(File::ALT_SEPARATOR) : nil
-
- class << self
- def [](*patterns)
- new.hide_dotfiles.include(*patterns)
- end
- def glob(*patterns)
- fl = new.hide_dotfiles.ignore(".", "..").include(*patterns)
- if block_given? then yield fl else fl end
- end
- def glob_all(*patterns)
- fl = new.ignore(".", "..").include(*patterns)
- if block_given? then yield fl else fl end
- end
- end
-
- def initialize(store = [])
- @pending = false
- @def_glob_dotfiles = true
- @items = store
- @ignore_rx = nil
- @keep = {}
- @actions = []
- end
- alias _object_dup dup
- private :_object_dup
- def dup
- c = _object_dup
- c.items = @items.dup
- c.actions = @actions.dup
- c.ignore_rx = @ignore_rx.dup if @ignore_rx
- c.instance_variable_set(:@keep, @keep.dup)
- c
- end
- def copy
- c = _object_dup
- c.items = @items.map { |entry| entry.dup }
- c.actions = @actions.dup
- c.ignore_rx = @ignore_rx.dup if @ignore_rx
- h_keep = {}
- @keep.each_key { |entry| h_keep[entry] = true }
- c.instance_variable_set(:@keep, h_keep)
- c
- end
- def glob_dotfiles?
- @def_glob_dotfiles
- end
- def glob_dotfiles=(flag)
- @def_glob_dotfiles = flag ? true : false
- end
- def hide_dotfiles
- @def_glob_dotfiles = false
- self
- end
- def glob_dotfiles
- @def_glob_dotfiles = true
- self
- end
-
- protected
- attr_accessor :actions, :items
- attr_accessor :pending
- attr_accessor :ignore_rx
-
- public
- def each(&block)
- resolve if @pending
- @items.each(&block)
- self
- end
- def to_ary
- resolve if @pending
- @items
- end
- alias to_a to_ary
- alias entries to_ary # entries: defined in Enumerable
- def to_rant_filelist
- self
- end
- def +(other)
- if other.respond_to? :to_rant_filelist
- c = other.to_rant_filelist.dup
- c.actions.concat(@actions)
- c.items.concat(@items)
- c.pending = !c.actions.empty?
- c
- elsif other.respond_to? :to_ary
- c = dup
- c.actions <<
- [:apply_ary_method_1, :concat, other.to_ary.dup]
- c.pending = true
- c
- else
- raise TypeError,
- "cannot add #{other.class} to Rant::FileList"
- end
- end
- def <<(file)
- @actions << [:apply_ary_method_1, :push, file]
- @keep[file] = true
- @pending = true
- self
- end
- def keep(entry)
- @keep[entry] = true
- @items << entry
- self
- end
- def concat(ary)
- if @pending
- ary = ary.to_ary.dup
- @actions << [:apply_ary_method_1, :concat, ary]
- else
- ix = ignore_rx and ary = ary.to_ary.reject { |f| f =~ ix }
- @items.concat(ary)
- end
- self
- end
- def size
- resolve if @pending
- @items.size
- end
- alias length size
- def empty?
- resolve if @pending
- @items.empty?
- end
- def join(sep = ' ')
- resolve if @pending
- @items.join(sep)
- end
- def pop
- resolve if @pending
- @items.pop
- end
- def push(entry)
- resolve if @pending
- @items.push(entry) if entry !~ ignore_rx
- self
- end
- def shift
- resolve if @pending
- @items.shift
- end
- def unshift(entry)
- resolve if @pending
- @items.unshift(entry) if entry !~ ignore_rx
- self
- end
- if Object.method_defined?(:fcall) || Object.method_defined?(:funcall) # in Ruby 1.9 like __send__
- @@__send_private__ = Object.method_defined?(:fcall) ? :fcall : :funcall
- def resolve
- @pending = false
- @actions.each{ |action| self.__send__(@@__send_private__, *action) }.clear
- ix = ignore_rx
- if ix
- @items.reject! { |f| f =~ ix && !@keep[f] }
- end
- self
- end
- else
- def resolve
- @pending = false
- @actions.each{ |action| self.__send__(*action) }.clear
- ix = ignore_rx
- if ix
- @items.reject! { |f| f =~ ix && !@keep[f] }
- end
- self
- end
- end
- def include(*pats)
- @def_glob_dotfiles ? glob_all(*pats) : glob_unix(*pats)
- end
- alias glob include
- def glob_unix(*patterns)
- patterns.flatten.each { |pat|
- @actions << [:apply_glob_unix, pat]
- }
- @pending = true
- self
- end
- def glob_all(*patterns)
- patterns.flatten.each { |pat|
- @actions << [:apply_glob_all, pat]
- }
- @pending = true
- self
- end
- if RUBY_VERSION < "1.8.2"
- FN_DOTFILE_RX_ = ESC_ALT_SEPARATOR ?
- /(^|(#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+)\..*
- ((#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+|$)/x :
- /(^|#{ESC_SEPARATOR}+)\..* (#{ESC_SEPARATOR}+|$)/x
- def apply_glob_unix(pattern)
- inc_files = Dir.glob(pattern)
- unless pattern =~ /(^|\/)\./
- inc_files.reject! { |fn| fn =~ FN_DOTFILE_RX_ }
- end
- @items.concat(inc_files)
- end
- else
- def apply_glob_unix(pattern)
- @items.concat(Dir.glob(pattern))
- end
- end
- private :apply_glob_unix
- def apply_glob_all(pattern)
- @items.concat(Dir.glob(pattern, File::FNM_DOTMATCH))
- end
- private :apply_glob_all
- def exclude(*patterns)
- patterns.each { |pat|
- if Regexp === pat
- @actions << [:apply_exclude_rx, pat]
- else
- @actions << [:apply_exclude, pat]
- end
- }
- @pending = true
- self
- end
- def ignore(*patterns)
- patterns.each { |pat|
- add_ignore_rx(Regexp === pat ? pat : mk_all_rx(pat))
- }
- @pending = true
- self
- end
- def add_ignore_rx(rx)
- @ignore_rx =
- if @ignore_rx
- Regexp.union(@ignore_rx, rx)
- else
- rx
- end
- end
- private :add_ignore_rx
- def apply_exclude(pattern)
- @items.reject! { |elem|
- File.fnmatch?(pattern, elem, File::FNM_DOTMATCH) && !@keep[elem]
- }
- end
- private :apply_exclude
- def apply_exclude_rx(rx)
- @items.reject! { |elem|
- elem =~ rx && !@keep[elem]
- }
- end
- private :apply_exclude_rx
- def exclude_name(*names)
- names.each { |name|
- @actions << [:apply_exclude_rx, mk_all_rx(name)]
- }
- @pending = true
- self
- end
- alias shun exclude_name
- if File::ALT_SEPARATOR
- def mk_all_rx(file)
- /(^|(#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+)#{Regexp.escape(file)}
- ((#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+|$)/x
- end
- else
- def mk_all_rx(file)
- /(^|#{ESC_SEPARATOR}+)#{Regexp.escape(file)}
- (#{ESC_SEPARATOR}+|$)/x
- end
- end
- private :mk_all_rx
- def exclude_path(*patterns)
- patterns.each { |pat|
- @actions << [:apply_exclude_path, pat]
- }
- @pending = true
- self
- end
- def apply_exclude_path(pattern)
- flags = File::FNM_DOTMATCH|File::FNM_PATHNAME
- @items.reject! { |elem|
- File.fnmatch?(pattern, elem, flags) && !@keep[elem]
- }
- end
- private :apply_exclude
- def select(&block)
- d = dup
- d.actions << [:apply_select, block]
- d.pending = true
- d
- end
- alias find_all select
- def apply_select blk
- @items = @items.select(&blk)
- end
- private :apply_select
- def map(&block)
- d = dup
- d.actions << [:apply_ary_method, :map!, block]
- d.pending = true
- d
- end
- alias collect map
- def sub_ext(ext, new_ext=nil)
- map { |f| f._rant_sub_ext ext, new_ext }
- end
- def ext(ext_str)
- sub_ext(ext_str)
- end
- def arglist
- Rant::Sys.sp to_ary
- end
- alias to_s arglist
- alias object_inspect inspect
- def uniq!
- @actions << [:apply_ary_method, :uniq!]
- @pending = true
- self
- end
- def sort!
- @actions << [:apply_ary_method, :sort!]
- @pending = true
- self
- end
- def map!(&block)
- @actions << [:apply_ary_method, :map!, block]
- @pending = true
- self
- end
- def reject!(&block)
- @actions << [:apply_ary_method, :reject!, block]
- @pending = true
- self
- end
- private
- def apply_ary_method(meth, block=nil)
- @items.send meth, &block
- end
- def apply_ary_method_1(meth, arg1, block=nil)
- @items.send meth, arg1, &block
- end
- end # class FileList
-end # module Rant
-
-if RUBY_VERSION == "1.8.3"
- module FileUtils
- METHODS = singleton_methods - %w(private_module_function
- commands options have_option? options_of collect_method)
- module Verbose
- class << self
- public(*::FileUtils::METHODS)
- end
- public(*::FileUtils::METHODS)
- end
- end
-end
-
-if RUBY_VERSION < "1.8.1"
- module FileUtils
- undef_method :fu_list
- def fu_list(arg)
- arg.respond_to?(:to_ary) ? arg.to_ary : [arg]
- end
- end
-end
-
-module Rant
- class RacFileList < FileList
-
- attr_reader :subdir
- attr_reader :basedir
-
- def initialize(rac, store = [])
- super(store)
- @rac = rac
- @subdir = @rac.current_subdir
- @basedir = Dir.pwd
- @ignore_hash = nil
- @add_ignore_args = []
- update_ignore_rx
- end
- def dup
- c = super
- c.instance_variable_set(
- :@add_ignore_args, @add_ignore_args.dup)
- c
- end
- def copy
- c = super
- c.instance_variable_set(
- :@add_ignore_args, @add_ignore_args.map { |e| e.dup })
- c
- end
- alias filelist_ignore ignore
- def ignore(*patterns)
- @add_ignore_args.concat patterns
- self
- end
- def ignore_rx
- update_ignore_rx
- @ignore_rx
- end
- alias filelist_resolve resolve
- def resolve
- Sys.cd(@basedir) { filelist_resolve }
- end
- def each_cd(&block)
- old_pwd = Dir.pwd
- Sys.cd(@basedir)
- filelist_resolve if @pending
- @items.each(&block)
- ensure
- Sys.cd(old_pwd)
- end
- private
- def update_ignore_rx
- ri = @rac.var[:ignore]
- ri = ri ? (ri + @add_ignore_args) : @add_ignore_args
- rh = ri.hash
- unless rh == @ignore_hash
- @ignore_rx = nil
- filelist_ignore(*ri)
- @ignore_hash = rh
- end
- end
- end # class RacFileList
-
- class MultiFileList
-
- attr_reader :cur_list
-
- def initialize(rac)
- @rac = rac
- @cur_list = RacFileList.new(@rac)
- @lists = [@cur_list]
- end
-
- def each_entry(&block)
- @lists.each { |list|
- list.each_cd(&block)
- }
- end
-
- def add(filelist)
- @cur_list = filelist
- @lists << filelist
- self
- end
-
- def method_missing(sym, *args, &block)
- if @cur_list && @cur_list.respond_to?(sym)
- if @cur_list.subdir == @rac.current_subdir
- @cur_list.send(sym, *args, &block)
- else
- add(RacFileList.new(@rac))
- @cur_list.send(sym, *args, &block)
- end
- else
- super
- end
- end
- end # class MultiFileList
-
- class CommandError < StandardError
- attr_reader :cmd
- attr_reader :status
- def initialize(cmd, status=nil, msg=nil)
- @msg = msg
- @cmd = cmd
- @status = status
- end
- def message
- if !@msg && cmd
- if status
- "Command failed with status #{status.exitstatus}:\n" +
- "[#{cmd}]"
- else
- "Command failed:\n[#{cmd}]"
- end
- else
- @msg
- end
- end
- end
-
- module Sys
- include ::FileUtils::Verbose
-
- @symlink_supported = true
- class << self
- attr_accessor :symlink_supported
- end
-
- def fu_output_message(msg) #:nodoc:
- end
- private :fu_output_message
-
- def fu_each_src_dest(src, *rest)
- src = src.to_ary if src.respond_to? :to_ary
- super(src, *rest)
- end
- private :fu_each_src_dest
-
- def sh(*cmd_args, &block)
- cmd_args.flatten!
- cmd = cmd_args.join(" ")
- fu_output_message cmd
- success = system(*cmd_args)
- if block_given?
- block[$?]
- elsif !success
- raise CommandError.new(cmd, $?)
- end
- end
-
- def ruby(*args, &block)
- if args.empty?
- sh(Env::RUBY_EXE, '', &block)
- else
- sh(args.unshift(Env::RUBY_EXE), &block)
- end
- end
- def cd(dir, &block)
- fu_output_message "cd #{dir}"
- orig_pwd = Dir.pwd
- Dir.chdir dir
- if block
- begin
- block.arity == 0 ? block.call : block.call(Dir.pwd)
- ensure
- fu_output_message "cd -"
- Dir.chdir orig_pwd
- end
- else
- self
- end
- end
-
- def safe_ln(src, dest)
- dest = dest.to_str
- src = src.respond_to?(:to_ary) ? src.to_ary : src.to_str
- unless Sys.symlink_supported
- cp(src, dest)
- else
- begin
- ln(src, dest)
- rescue Exception # SystemCallError # Errno::EOPNOTSUPP
- Sys.symlink_supported = false
- cp(src, dest)
- end
- end
- end
-
- def ln_f(src, dest)
- ln(src, dest, :force => true)
- end
-
- def split_path(str)
- str.split(Env.on_windows? ? ";" : ":")
- end
-
- if Env.on_windows?
- def root_dir?(path)
- path == "/" || path == "\\" ||
- path =~ %r{\A[a-zA-Z]+:(\\|/)\Z}
- end
- def absolute_path?(path)
- path =~ %r{\A([a-zA-Z]+:)?(/|\\)}
- end
- else
- def root_dir?(path)
- path == "/"
- end
- def absolute_path?(path)
- path =~ %r{\A/}
- end
- end
-
- extend self
-
- if RUBY_VERSION >= "1.8.4" # needed by 1.9.0, too
- class << self
- public(*::FileUtils::METHODS)
- end
- public(*::FileUtils::METHODS)
- end
-
- end # module Sys
-
- class SysObject
- include Sys
- def initialize(rant)
- @rant = rant or
- raise ArgumentError, "rant application required"
- end
- def ignore(*patterns)
- @rant.var[:ignore].concat(patterns)
- nil
- end
- def filelist(arg = Rant.__rant_no_value__)
- if Rant.__rant_no_value__.equal?(arg)
- RacFileList.new(@rant)
- elsif arg.respond_to?(:to_rant_filelist)
- arg.to_rant_filelist
- elsif arg.respond_to?(:to_ary)
- RacFileList.new(@rant, arg.to_ary)
- else
- raise TypeError,
- "cannot convert #{arg.class} into Rant::FileList"
- end
- end
- def [](*patterns)
- RacFileList.new(@rant).hide_dotfiles.include(*patterns)
- end
- def glob(*patterns, &block)
- fl = RacFileList.new(@rant).hide_dotfiles.include(*patterns)
- fl.ignore(".", "..")
- if block_given? then yield fl else fl end
- end
- def glob_all(*patterns, &block)
- fl = RacFileList.new(@rant).include(*patterns)
- fl.ignore(".", "..") # use case: "*.*" as pattern
- if block_given? then yield fl else fl end
- end
- def expand_path(path)
- File.expand_path(@rant.project_to_fs_path(path))
- end
- private
- def fu_output_message(cmd)
- @rant.cmd_msg cmd
- end
- end
-
-
- class TaskFail < StandardError
- def initialize(task, orig, msg)
- @task = task
- @orig = orig
- @msg = msg
- end
- def exception
- self
- end
- def task
- @task
- end
- def tname
- @task ? @task.name : nil
- end
- def orig
- @orig
- end
- def msg
- @msg
- end
- end
-
- class Rantfile
- attr_reader :tasks, :path
- attr_accessor :project_subdir
- def initialize(path)
- @path = path or raise ArgumentError, "path required"
- @tasks = []
- @project_subdir = nil
- end
- alias to_s path
- alias to_str path
- end # class Rantfile
-
- module Node
-
- INVOKE_OPT = {}.freeze
-
- T0 = Time.at(0).freeze
-
- attr_reader :name
- attr_reader :rac
- attr_accessor :description
- attr_accessor :rantfile
- attr_accessor :line_number
- attr_accessor :project_subdir
-
- def initialize
- @description = nil
- @rantfile = nil
- @line_number = nil
- @run = false
- @project_subdir = ""
- @success = nil
- end
-
- def reference_name
- sd = rac.current_subdir
- case sd
- when ""; full_name
- when project_subdir; name
- else "@#{full_name}".sub(/^@#{Regexp.escape sd}\//, '')
- end
- end
-
- alias to_s reference_name
- alias to_rant_target name
-
- def full_name
- sd = project_subdir
- sd.empty? ? name : File.join(sd, name)
- end
-
- def ch
- {:file => rantfile.to_str, :ln => line_number}
- end
-
- def goto_task_home
- @rac.goto_project_dir project_subdir
- end
-
- def file_target?
- false
- end
-
- def done?
- @success
- end
-
- def needed?
- invoke(:needed? => true)
- end
-
- def run?
- @run
- end
-
- def invoke(opt = INVOKE_OPT)
- return circular_dep if run?
- @run = true
- begin
- return !done? if opt[:needed?]
- self.run if !done?
- @success = true
- ensure
- @run = false
- end
- end
-
- def fail msg = nil, orig = nil
- raise TaskFail.new(self, orig, msg)
- end
-
- def each_target
- end
-
- def has_actions?
- defined? @block and @block
- end
-
- def dry_run
- text = "Executing #{name.dump}"
- text << " [NOOP]" unless has_actions?
- @rac.cmd_msg text
- action_descs.each { |ad|
- @rac.cmd_print " - "
- @rac.cmd_msg ad.sub(/\n$/, '').gsub(/\n/, "\n ")
- }
- end
-
- private
- def run
- goto_task_home
- return if @rac.running_task(self)
- return unless has_actions?
- @receiver.pre_run(self) if defined? @receiver and @receiver
- @block.arity == 0 ? @block.call : @block[self] if @block
- end
-
- def action_descs
- descs = []
- if defined? @receiver and @receiver
- descs.concat(@receiver.pre_action_descs)
- end
- @block ? descs << action_block_desc : descs
- end
-
- def action_block_desc
- @block.inspect =~ /^#<Proc:[\da-z]+@(.+):(\d+)>$/i
- fn, ln = $1, $2
- "Ruby Proc at #{fn.sub(/^#{Regexp.escape @rac.rootdir}\//, '')}:#{ln}"
- end
-
- def circular_dep
- rac.warn_msg "Circular dependency on task `#{full_name}'."
- false
- end
- end # module Node
-
-
- def self.init_import_nodes__default(rac, *rest)
- rac.node_factory = DefaultNodeFactory.new
- end
-
- class DefaultNodeFactory
- def new_task(rac, name, pre, blk)
- Task.new(rac, name, pre, &blk)
- end
- def new_file(rac, name, pre, blk)
- FileTask.new(rac, name, pre, &blk)
- end
- def new_dir(rac, name, pre, blk)
- DirTask.new(rac, name, pre, &blk)
- end
- def new_source(rac, name, pre, blk)
- SourceNode.new(rac, name, pre, &blk)
- end
- def new_custom(rac, name, pre, blk)
- UserTask.new(rac, name, pre, &blk)
- end
- def new_auto_subfile(rac, name, pre, blk)
- AutoSubFileTask.new(rac, name, pre, &blk)
- end
- end
-
- class Task
- include Node
-
- attr_accessor :receiver
-
- def initialize(rac, name, prerequisites = [], &block)
- super()
- @rac = rac or raise ArgumentError, "rac not given"
- @name = name or raise ArgumentError, "name not given"
- @pre = prerequisites || []
- @pre_resolved = false
- @block = block
- @run = false
- @receiver = nil
- end
-
- def prerequisites
- @pre.collect { |pre| pre.to_s }
- end
- alias deps prerequisites
-
- def source
- @pre.first.to_s
- end
-
- def has_actions?
- @block or @receiver && @receiver.has_pre_action?
- end
-
- def <<(pre)
- @pre_resolved = false
- @pre << pre
- end
-
- def invoked?
- !@success.nil?
- end
-
- def fail?
- @success == false
- end
-
- def enhance(deps = nil, &blk)
- if deps
- @pre_resolved = false
- @pre.concat deps
- end
- if @block
- if blk
- first_block = @block
- @block = lambda { |t|
- first_block[t]
- blk[t]
- }
- end
- else
- @block = blk
- end
- end
-
- def invoke(opt = INVOKE_OPT)
- return circular_dep if @run
- @run = true
- begin
- return if done?
- internal_invoke opt
- ensure
- @run = false
- end
- end
-
- def internal_invoke(opt, ud_init = true)
- goto_task_home
- update = ud_init || opt[:force]
- dep = nil
- uf = false
- each_dep { |dep|
- if dep.respond_to? :timestamp
- handle_timestamped(dep, opt) && update = true
- elsif Node === dep
- handle_node(dep, opt) && update = true
- else
- dep, uf = handle_non_node(dep, opt)
- uf && update = true
- dep
- end
- }
- if @receiver
- goto_task_home
- update = true if @receiver.update?(self)
- end
- return update if opt[:needed?]
- run if update
- @success = true
- update
- rescue StandardError => e
- @success = false
- self.fail(nil, e)
- end
- private :internal_invoke
-
- def handle_node(dep, opt)
- dep.invoke opt
- end
-
- def handle_timestamped(dep, opt)
- dep.invoke opt
- end
-
- def handle_non_node(dep, opt)
- @rac.err_msg "Unknown task `#{dep}',",
- "referenced in `#{rantfile.path}', line #{@line_number}!"
- self.fail
- end
-
- def each_dep
- t = nil
- if @pre_resolved
- return @pre.each { |t| yield(t) }
- end
- my_full_name = full_name
- my_project_subdir = project_subdir
- @pre.map! { |t|
- if Node === t
- if t.full_name == my_full_name
- nil
- else
- yield(t)
- t
- end
- else
- t = t.to_s if Symbol === t
- if t == my_full_name #TODO
- nil
- else
- selection = @rac.resolve t,
- my_project_subdir
- if selection.empty?
- yield(t)
- else
- selection.each { |st| yield(st) }
- selection
- end
- end
- end
- }
- if @pre.kind_of? Rant::FileList
- @pre.resolve
- else
- @pre.flatten!
- @pre.compact!
- end
- @pre_resolved = true
- end
- end # class Task
-
- class UserTask < Task
-
- def initialize(*args)
- super
- @block = nil
- @needed = nil
- @target_files = nil
- yield self if block_given?
- end
-
- def act(&block)
- @block = block
- end
-
- def needed(&block)
- @needed = block
- end
-
- def file_target?
- @target_files and @target_files.include? @name
- end
-
- def each_target(&block)
- goto_task_home
- @target_files.each(&block) if @target_files
- end
-
- def file_target(*args)
- args.flatten!
- args << @name if args.empty?
- if @target_files
- @target_files.concat(args)
- else
- @target_files = args
- end
- end
-
- def invoke(opt = INVOKE_OPT)
- return circular_dep if @run
- @run = true
- begin
- return if done?
- internal_invoke(opt, ud_init_by_needed)
- ensure
- @run = false
- end
- end
-
- private
- def ud_init_by_needed
- if @needed
- goto_task_home
- @needed.arity == 0 ? @needed.call : @needed[self]
- end
- end
- end # class UserTask
-
- class FileTask < Task
-
- def initialize(*args)
- super
- @ts = T0
- end
-
- def file_target?
- true
- end
-
- def invoke(opt = INVOKE_OPT)
- return circular_dep if @run
- @run = true
- begin
- return if done?
- goto_task_home
- if File.exist? @name
- @ts = File.mtime @name
- internal_invoke opt, false
- else
- @ts = T0
- internal_invoke opt, true
- end
- ensure
- @run = false
- end
- end
-
- def timestamp(opt = INVOKE_OPT)
- File.exist?(@name) ? File.mtime(@name) : T0
- end
-
- def handle_node(dep, opt)
- return true if dep.file_target? && dep.invoke(opt)
- if File.exist? dep.name
- File.mtime(dep.name) > @ts
- elsif !dep.file_target?
- @rac.err_msg @rac.pos_text(rantfile.path, line_number),
- "in prerequisites: no such file: `#{dep.full_name}'"
- self.fail
- end
- end
-
- def handle_timestamped(dep, opt)
- return true if dep.invoke opt
- dep.timestamp(opt) > @ts
- end
-
- def handle_non_node(dep, opt)
- goto_task_home # !!??
- unless File.exist? dep
- @rac.err_msg @rac.pos_text(rantfile.path, line_number),
- "in prerequisites: no such file or task: `#{dep}'"
- self.fail
- end
- [dep, File.mtime(dep) > @ts]
- end
-
- def each_target
- goto_task_home
- yield name
- end
- end # class FileTask
-
- module AutoInvokeDirNode
- private
- def run
- goto_task_home
- return if @rac.running_task(self)
- dir = File.dirname(name)
- @rac.build dir unless dir == "." || dir == "/"
- return unless @block
- @block.arity == 0 ? @block.call : @block[self]
- end
- end
-
- class AutoSubFileTask < FileTask
- include AutoInvokeDirNode
- end
-
- class DirTask < Task
-
- def initialize(*args)
- super
- @ts = T0
- @isdir = nil
- end
-
- def invoke(opt = INVOKE_OPT)
- return circular_dep if @run
- @run = true
- begin
- return if done?
- goto_task_home
- @isdir = test(?d, @name)
- if @isdir
- @ts = @block ? test(?M, @name) : Time.now
- internal_invoke opt, false
- else
- @ts = T0
- internal_invoke opt, true
- end
- ensure
- @run = false
- end
- end
-
- def file_target?
- true
- end
-
- def handle_node(dep, opt)
- return true if dep.file_target? && dep.invoke(opt)
- if File.exist? dep.name
- File.mtime(dep.name) > @ts
- elsif !dep.file_target?
- @rac.err_msg @rac.pos_text(rantfile.path, line_number),
- "in prerequisites: no such file: `#{dep.full_name}'"
- self.fail
- end
- end
-
- def handle_timestamped(dep, opt)
- return @block if dep.invoke opt
- @block && dep.timestamp(opt) > @ts
- end
-
- def handle_non_node(dep, opt)
- goto_task_home
- unless File.exist? dep
- @rac.err_msg @rac.pos_text(rantfile.path, line_number),
- "in prerequisites: no such file or task: `#{dep}'"
- self.fail
- end
- [dep, @block && File.mtime(dep) > @ts]
- end
-
- def run
- return if @rac.running_task(self)
- @rac.sys.mkdir @name unless @isdir
- if @block
- @block.arity == 0 ? @block.call : @block[self]
- goto_task_home
- @rac.sys.touch @name
- end
- end
-
- def each_target
- goto_task_home
- yield name
- end
- end # class DirTask
-
- class SourceNode
- include Node
- def initialize(rac, name, prerequisites = [])
- super()
- @rac = rac
- @name = name or raise ArgumentError, "name not given"
- @pre = prerequisites
- @run = false
- @ts = nil
- end
- def prerequisites
- @pre
- end
- def timestamp(opt = INVOKE_OPT)
- return @ts if @ts
- goto_task_home
- if File.exist?(@name)
- @ts = File.mtime @name
- else
- rac.abort_at(ch, "SourceNode: no such file -- #@name")
- end
- sd = project_subdir
- @pre.each { |f|
- nodes = rac.resolve f, sd
- if nodes.empty?
- if File.exist? f
- mtime = File.mtime f
- @ts = mtime if mtime > @ts
- else
- rac.abort_at(ch,
- "SourceNode: no such file -- #{f}")
- end
- else
- nodes.each { |node|
- node.invoke(opt)
- if node.respond_to? :timestamp
- node_ts = node.timestamp(opt)
- goto_task_home
- @ts = node_ts if node_ts > @ts
- else
- rac.abort_at(ch,
- "SourceNode can't depend on #{node.name}")
- end
- }
- end
- }
- @ts
- end
- def invoke(opt = INVOKE_OPT)
- false
- end
- def related_sources
- @pre
- end
- end # class SourceNode
-
- module Generators
- class Task
- def self.rant_gen(rac, ch, args, &block)
- unless args.size == 1
- rac.abort("Task takes only one argument " +
- "which has to be like one given to the " +
- "`task' function")
- end
- rac.prepare_task(args.first, nil, ch) { |name,pre,blk|
- rac.node_factory.new_custom(rac, name, pre, block)
- }
- end
- end
- class Directory
- def self.rant_gen(rac, ch, args, &block)
- case args.size
- when 1
- name, pre = rac.normalize_task_arg(args.first, ch)
- self.task(rac, ch, name, pre, &block)
- when 2
- basedir = args.shift
- if basedir.respond_to? :to_str
- basedir = basedir.to_str
- else
- rac.abort_at(ch,
- "Directory: basedir argument has to be a string.")
- end
- name, pre = rac.normalize_task_arg(args.first, ch)
- self.task(rac, ch, name, pre, basedir, &block)
- else
- rac.abort_at(ch, "Directory takes one argument, " +
- "which should be like one given to the `task' command.")
- end
- end
-
- def self.task(rac, ch, name, prerequisites=[], basedir=nil, &block)
- dirs = ::Rant::Sys.split_all(name)
- if dirs.empty?
- rac.abort_at(ch,
- "Not a valid directory name: `#{name}'")
- end
- path = basedir
- last_task = nil
- task_block = nil
- desc_for_last = rac.pop_desc
- dirs.each { |dir|
- pre = [path]
- pre.compact!
- if dir.equal?(dirs.last)
- rac.cx.desc desc_for_last
-
- dp = prerequisites.dup
- pre.each { |elem| dp << elem }
- pre = dp
-
- task_block = block
- end
- path = path.nil? ? dir : File.join(path, dir)
- last_task = rac.prepare_task({:__caller__ => ch,
- path => pre}, task_block) { |name,pre,blk|
- rac.node_factory.new_dir(rac, name, pre, blk)
- }
- }
- last_task
- end
- end # class Directory
- class SourceNode
- def self.rant_gen(rac, ch, args)
- unless args.size == 1
- rac.abort_at(ch, "SourceNode takes one argument.")
- end
- if block_given?
- rac.abort_at(ch, "SourceNode doesn't take a block.")
- end
- rac.prepare_task(args.first, nil, ch) { |name, pre, blk|
- rac.node_factory.new_source(rac, name, pre, blk)
- }
- end
- end
- class Rule
- def self.rant_gen(rac, ch, args, &block)
- unless args.size == 1
- rac.abort_at(ch, "Rule takes only one argument.")
- end
- rac.abort_at(ch, "Rule: block required.") unless block
- arg = args.first
- target = nil
- src_arg = nil
- if Symbol === arg
- target = ".#{arg}"
- elsif arg.respond_to? :to_str
- target = arg.to_str
- elsif Regexp === arg
- target = arg
- elsif Hash === arg && arg.size == 1
- arg.each_pair { |target, src_arg| }
- src_arg = src_arg.to_str if src_arg.respond_to? :to_str
- target = target.to_str if target.respond_to? :to_str
- src_arg = ".#{src_arg}" if Symbol === src_arg
- target = ".#{target}" if Symbol === target
- else
- rac.abort_at(ch, "Rule argument " +
- "has to be a hash with one key-value pair.")
- end
- esc_target = nil
- target_rx = case target
- when String
- esc_target = Regexp.escape(target)
- /#{esc_target}$/
- when Regexp
- target
- else
- rac.abort_at(ch, "rule target has " +
- "to be a string or regular expression")
- end
- src_proc = case src_arg
- when String, Array
- unless String === target
- rac.abort(ch, "rule target has to be " +
- "a string if source is a string")
- end
- if src_arg.kind_of? String
- lambda { |name|
- name.sub(/#{esc_target}$/, src_arg)
- }
- else
- lambda { |name|
- src_arg.collect { |s_src|
- s_src = ".#{s_src}" if Symbol === s_src
- name.sub(/#{esc_target}$/, s_src)
- }
- }
- end
- when Proc; src_arg
- when nil; lambda { |name| [] }
- else
- rac.abort_at(ch, "rule source has to be a " +
- "String, Array or Proc")
- end
- rac.resolve_hooks <<
- (block.arity == 2 ? Hook : FileHook).new(
- rac, ch, target_rx, src_proc, block)
- nil
- end
- class Hook
- attr_accessor :target_rx
- def initialize(rant, ch, target_rx, src_proc, block)
- @rant = rant
- @ch = ch
- @target_rx = target_rx
- @src_proc = src_proc
- @block = block
- end
- def call(target, rel_project_dir)
- if @target_rx =~ target
- have_src = true
- src = @src_proc[target]
- if src.respond_to? :to_ary
- have_src = src.to_ary.all? { |s|
- have_src?(rel_project_dir, s)
- }
- else
- have_src = have_src?(rel_project_dir, src)
- end
- if have_src
- create_nodes(rel_project_dir, target, src)
- end
- end
- end
- alias [] call
- private
- def have_src?(rel_project_dir, name)
- return true unless
- @rant.rec_save_resolve(name, self, rel_project_dir).empty?
- test(?e, @rant.abs_path(rel_project_dir, name))
- end
- def create_nodes(rel_project_dir, target, deps)
- @rant.goto_project_dir rel_project_dir
- case nodes = @block[target, deps]
- when Array; nodes
- when Node; [nodes]
- else
- @rant.abort_at(@ch, "Block has to " +
- "return Node or array of Nodes.")
- end
- end
- end
- class FileHook < Hook
- private
- def have_src?(rel_project_dir, name)
- test(?e, @rant.abs_path(rel_project_dir, name)) or
- @rant.rec_save_resolve(name, self, rel_project_dir
- ).any? { |t| t.file_target? }
- end
- def create_nodes(rel_project_dir, target, deps)
- @rant.goto_project_dir rel_project_dir
- t = @rant.file(:__caller__ => @ch,
- target => deps, &@block)
- [t]
- end
- end
- end # class Rule
- class Action
- def self.rant_gen(rac, ch, args, &block)
- case args.size
- when 0
- unless (rac[:tasks] || rac[:stop_after_load])
- yield
- end
- when 1
- rx = args.first
- unless rx.kind_of? Regexp
- rac.abort_at(ch, "Action: argument has " +
- "to be a regular expression.")
- end
- rac.resolve_hooks << self.new(rac, block, rx)
- nil
- else
- rac.abort_at(ch, "Action: too many arguments.")
- end
- end
- def initialize(rant, block, rx)
- @rant = rant
- @subdir = @rant.current_subdir
- @block = block
- @rx = rx
- end
- def call(target, rel_project_dir)
- if target =~ @rx
- @rant.resolve_hooks.delete(self)
- @rant.goto_project_dir @subdir
- @block.call
- @rant.resolve(target, rel_project_dir)
- end
- end
- alias [] call
- end
- end # module Generators
-end # module Rant
-
-Rant::MAIN_OBJECT = self
-
-class String
- alias sub_ext _rant_sub_ext
- def to_rant_target
- self
- end
-end
-
-module Rant::Lib
- def parse_caller_elem(elem)
- return { :file => "", :ln => 0 } unless elem
- if elem =~ /^(.+):(\d+)(?::|$)/
- { :file => $1, :ln => $2.to_i }
- else
- $stderr.puts "parse_caller_elem: #{elem.inspect}"
- { :file => elem, :ln => 0 }
- end
-
- end
- module_function :parse_caller_elem
-end # module Lib
-
-module Rant::Console
- RANT_PREFIX = "rant: "
- ERROR_PREFIX = "[ERROR] "
- WARN_PREFIX = "[WARNING] "
- def msg_prefix
- if defined? @msg_prefix and @msg_prefix
- @msg_prefix
- else
- RANT_PREFIX
- end
- end
- def msg(*text)
- pre = msg_prefix
- $stderr.puts "#{pre}#{text.join("\n" + ' ' * pre.length)}"
- end
- def vmsg(importance, *text)
- msg(*text) if verbose >= importance
- end
- def err_msg(*text)
- pre = msg_prefix + ERROR_PREFIX
- $stderr.puts "#{pre}#{text.join("\n" + ' ' * pre.length)}"
- end
- def warn_msg(*text)
- pre = msg_prefix + WARN_PREFIX
- $stderr.puts "#{pre}#{text.join("\n" + ' ' * pre.length)}"
- end
- def ask_yes_no text
- $stderr.print msg_prefix + text + " [y|n] "
- case $stdin.readline
- when /y|yes/i; true
- when /n|no/i; false
- else
- $stderr.puts(' ' * msg_prefix.length +
- "Please answer with `yes' or `no'")
- ask_yes_no text
- end
- end
- def prompt text
- $stderr.print msg_prefix + text
- input = $stdin.readline
- input ? input.chomp : input
- end
- def option_listing opts
- rs = ""
- opts.each { |lopt, *opt_a|
- if opt_a.size == 2
- mode, desc = opt_a
- else
- sopt, mode, desc = opt_a
- end
- next unless desc # "private" option
- optstr = ""
- arg = nil
- if mode != GetoptLong::NO_ARGUMENT
- if desc =~ /(\b[A-Z_]{2,}\b)/
- arg = $1
- end
- end
- if lopt
- optstr << lopt
- if arg
- optstr << " " << arg
- end
- optstr = optstr.ljust(30)
- end
- if sopt
- optstr << " " unless optstr.empty?
- optstr << sopt
- if arg
- optstr << " " << arg
- end
- end
- rs << " #{optstr}\n"
- rs << " #{desc.split("\n").join("\n ")}\n"
- }
- rs
- end
- extend self
-end # module Rant::Console
-
-module RantContext
- include Rant::Generators
-
- Env = Rant::Env
- FileList = Rant::FileList
-
- def task(targ, &block)
- rant.task(targ, &block)
- end
-
- def file(targ, &block)
- rant.file(targ, &block)
- end
-
- def enhance(targ, &block)
- rant.enhance(targ, &block)
- end
-
- def desc(*args)
- rant.desc(*args)
- end
-
- def gen(*args, &block)
- rant.gen(*args, &block)
- end
-
- def import(*args, &block)
- rant.import(*args, &block)
- end
-
- def plugin(*args, &block)
- rant.plugin(*args, &block)
- end
-
- def subdirs(*args)
- rant.subdirs(*args)
- end
-
- def source(opt, rantfile = nil)
- rant.source(opt, rantfile)
- end
-
- def sys(*args, &block)
- rant.sys(*args, &block)
- end
-
- def var(*args, &block)
- rant.var(*args, &block)
- end
-
- def make(*args, &block)
- rant.make(*args, &block)
- end
-
-end # module RantContext
-
-class RantAppContext
- include RantContext
-
- def initialize(app)
- @__rant__ = app
- end
-
- def rant
- @__rant__
- end
-
- def method_missing(sym, *args)
- Rant::MAIN_OBJECT.send(sym, *args)
- rescue NoMethodError
- raise NameError, "NameError: undefined local " +
- "variable or method `#{sym}' for main:Object", caller
- end
-end
-
-module Rant
-
- @__rant__ = nil
- class << self
-
- def run(first_arg=nil, *other_args)
- other_args = other_args.flatten
- args = first_arg.nil? ? ARGV.dup : ([first_arg] + other_args)
- if rant && !rant.run?
- rant.run(args.flatten)
- else
- @__rant__ = Rant::RantApp.new
- rant.run(args)
- end
- end
-
- def rant
- @__rant__
- end
- end
-
-end # module Rant
-
-class Rant::RantApp
- include Rant::Console
-
- class AutoLoadNodeFactory
- def initialize(rant)
- @rant = rant
- end
- def method_missing(sym, *args, &block)
- @rant.import "nodes/default"
- @rant.node_factory.send(sym, *args, &block)
- end
- end
-
-
-
- OPTIONS = [
- [ "--help", "-h", GetoptLong::NO_ARGUMENT,
- "Print this help and exit." ],
- [ "--version", "-V", GetoptLong::NO_ARGUMENT,
- "Print version of Rant and exit." ],
- [ "--verbose", "-v", GetoptLong::NO_ARGUMENT,
- "Print more messages to stderr." ],
- [ "--quiet", "-q", GetoptLong::NO_ARGUMENT,
- "Don't print commands." ],
- [ "--err-commands", GetoptLong::NO_ARGUMENT,
- "Print failed commands and their exit status." ],
- [ "--directory","-C", GetoptLong::REQUIRED_ARGUMENT,
- "Run rant in DIRECTORY." ],
- [ "--cd-parent","-c", GetoptLong::NO_ARGUMENT,
- "Run rant in parent directory with Rantfile." ],
- [ "--look-up", "-u", GetoptLong::NO_ARGUMENT,
- "Look in parent directories for root Rantfile." ],
- [ "--rantfile", "-f", GetoptLong::REQUIRED_ARGUMENT,
- "Process RANTFILE instead of standard rantfiles.\n" +
- "Multiple files may be specified with this option." ],
- [ "--force-run","-a", GetoptLong::REQUIRED_ARGUMENT,
- "Force rebuild of TARGET and all dependencies." ],
- [ "--dry-run", "-n", GetoptLong::NO_ARGUMENT,
- "Print info instead of actually executing actions." ],
- [ "--tasks", "-T", GetoptLong::NO_ARGUMENT,
- "Show a list of all described tasks and exit." ],
-
-
- [ "--import", "-i", GetoptLong::REQUIRED_ARGUMENT, nil ],
- [ "--stop-after-load", GetoptLong::NO_ARGUMENT, nil ],
- [ "--trace-abort", GetoptLong::NO_ARGUMENT, nil ],
- ]
-
- ROOT_DIR_ID = "@"
- ESCAPE_ID = "\\"
-
- attr_reader :args
- attr_reader :rantfiles
- attr_reader :force_targets
- attr_reader :plugins
- attr_reader :context
- alias cx context
- attr_reader :tasks
- attr_reader :imports
- attr_reader :current_subdir
- attr_reader :resolve_hooks
- attr_reader :rootdir
-
- attr_accessor :node_factory
-
- def initialize
- @args = []
- @context = RantAppContext.new(self)
- @sys = ::Rant::SysObject.new(self)
- @rantfiles = []
- @tasks = {}
- @opts = {
- :verbose => 0,
- :quiet => false,
- }
- @rootdir = Dir.pwd # root directory of project
- @arg_rantfiles = [] # rantfiles given in args
- @arg_targets = [] # targets given in args
- @force_targets = [] # targets given with -a option
- @run = false # run method was called at least once
- @done = false # run method was successful
- @plugins = []
- @var = Rant::RantVar::Space.new
- @var.query :ignore, :AutoList, []
- @imports = []
-
- @task_desc = nil
- @last_build_subdir = ""
-
- @current_subdir = ""
- @resolve_hooks = []
-
- @node_factory = AutoLoadNodeFactory.new(self)
- end
-
- def [](opt)
- @opts[opt]
- end
-
- def []=(opt, val)
- @opts[opt] = val
- end
-
- def expand_path(subdir, path)
- case path
- when nil; subdir.dup
- when ""; subdir.dup
- when /^@/; path.sub(/^@/, '')
- else
- path = path.sub(/^\\(?=@)/, '')
- if subdir.empty?
- path
- else
- File.join(subdir, path)
- end
- end
- end
- def resolve_root_ref(path)
- return File.join(@rootdir, path[1..-1]) if path =~ /^@/
- path.sub(/^\\(?=@)/, '')
- end
- def project_to_fs_path(path)
- sub = expand_path(@current_subdir, path)
- sub.empty? ? @rootdir : File.join(@rootdir, sub)
- end
- def abs_path(subdir, fn)
- return fn if Rant::Sys.absolute_path?(fn)
- path = File.join(@rootdir, subdir, fn)
- path.gsub!(%r{/+}, "/")
- path.sub!(%r{/$}, "") if path.length > 1
- path
- end
- def goto(dir)
- goto_project_dir(expand_path(@current_subdir, dir))
- end
- def goto_project_dir(dir='')
- @current_subdir = dir
- abs_path = @current_subdir.empty? ?
- @rootdir : File.join(@rootdir, @current_subdir)
- unless Dir.pwd == abs_path
- Dir.chdir abs_path
- vmsg 1, "in #{abs_path}"
- end
- end
-
- def run?
- @run
- end
-
- def done?
- @done
- end
-
- def run(*args)
- @run = true
- @args.concat(args.flatten)
- orig_pwd = @rootdir = Dir.pwd
- process_args
- Dir.chdir(@rootdir) rescue abort $!.message
- load_rantfiles
-
- raise Rant::RantDoneException if @opts[:stop_after_load]
-
- @plugins.each { |plugin| plugin.rant_start }
- if @opts[:tasks]
- show_descriptions
- raise Rant::RantDoneException
- end
- run_tasks
- raise Rant::RantDoneException
- rescue Rant::RantDoneException
- @done = true
- @plugins.each { |plugin| plugin.rant_done }
- return 0
- rescue Rant::RantAbortException
- $stderr.puts "rant aborted!"
- return 1
- rescue Exception => e
- ch = get_ch_from_backtrace(e.backtrace)
- if ch && !@opts[:trace_abort]
- err_msg(pos_text(ch[:file], ch[:ln]), e.message)
- else
- err_msg e.message, e.backtrace[0..4]
- end
- $stderr.puts "rant aborted!"
- return 1
- ensure
- Dir.chdir @rootdir if test ?d, @rootdir
- hooks = var._get("__at_return__")
- hooks.each { |hook| hook.call } if hooks
- @plugins.each { |plugin| plugin.rant_plugin_stop }
- @plugins.each { |plugin| plugin.rant_quit }
- Dir.chdir orig_pwd
- end
-
-
- def desc(*args)
- if args.empty? || (args.size == 1 && args.first.nil?)
- @task_desc = nil
- else
- @task_desc = args.join("\n")
- end
- end
-
- def task(targ, &block)
- prepare_task(targ, block) { |name,pre,blk|
- @node_factory.new_task(self, name, pre, blk)
- }
- end
-
- def file(targ, &block)
- prepare_task(targ, block) { |name,pre,blk|
- @node_factory.new_file(self, name, pre, blk)
- }
- end
-
- def gen(*args, &block)
- ch = Rant::Lib::parse_caller_elem(caller[1])
- generator = args.shift
- unless generator.respond_to? :rant_gen
- abort_at(ch,
- "gen: First argument has to be a task-generator.")
- end
- generator.rant_gen(self, ch, args, &block)
- end
-
- def import(*args, &block)
- ch = Rant::Lib::parse_caller_elem(caller[1])
- if block
- warn_msg pos_text(ch[:file], ch[:ln]),
- "import: ignoring block"
- end
- args.flatten.each { |arg|
- unless String === arg
- abort_at(ch, "import: only strings allowed as arguments")
- end
- unless @imports.include? arg
- unless Rant::CODE_IMPORTS.include? arg
- begin
- vmsg 2, "import #{arg}"
- require "rant/import/#{arg}"
- rescue LoadError => e
- abort_at(ch, "No such import - #{arg}")
- end
- Rant::CODE_IMPORTS << arg.dup
- end
- init_msg = "init_import_#{arg.gsub(/[^\w]/, '__')}"
- Rant.send init_msg, self if Rant.respond_to? init_msg
- @imports << arg.dup
- end
- }
- end
-
- def plugin(*args, &block)
- clr = caller[1]
- ch = Rant::Lib::parse_caller_elem(clr)
- name = nil
- pre = []
- ln = ch[:ln] || 0
- file = ch[:file]
-
- pl_name = args.shift
- pl_name = pl_name.to_str if pl_name.respond_to? :to_str
- pl_name = pl_name.to_s if pl_name.is_a? Symbol
- unless pl_name.is_a? String
- abort(pos_text(file, ln),
- "Plugin name has to be a string or symbol.")
- end
- lc_pl_name = pl_name.downcase
- import_name = "plugin/#{lc_pl_name}"
- unless Rant::CODE_IMPORTS.include? import_name
- begin
- require "rant/plugin/#{lc_pl_name}"
- Rant::CODE_IMPORTS << import_name
- rescue LoadError
- abort(pos_text(file, ln),
- "no such plugin library -- #{lc_pl_name}")
- end
- end
- pl_class = nil
- begin
- pl_class = ::Rant::Plugin.const_get(pl_name)
- rescue NameError, ArgumentError
- abort(pos_text(file, ln),
- "no such plugin -- #{pl_name}")
- end
-
- plugin = pl_class.rant_plugin_new(self, ch, *args, &block)
- @plugins << plugin
- vmsg 2, "Plugin `#{plugin.rant_plugin_name}' registered."
- plugin.rant_plugin_init
- plugin
- end
-
- def enhance(targ, &block)
- prepare_task(targ, block) { |name,pre,blk|
- t = resolve(name).last
- if t
- unless t.respond_to? :enhance
- abort("Can't enhance task `#{name}'")
- end
- t.enhance(pre, &blk)
- return t
- end
- warn_msg "enhance \"#{name}\": no such task",
- "Generating a new file task with the given name."
- @node_factory.new_file(self, name, pre, blk)
- }
- end
-
- def source(opt, rantfile = nil)
- unless rantfile
- rantfile = opt
- opt = nil
- end
- make_rf = opt != :n && opt != :now
- rf, is_new = rantfile_for_path(rantfile)
- return false unless is_new
- make rantfile if make_rf
- unless File.exist? rf.path
- abort("source: No such file -- #{rantfile}")
- end
-
- load_file rf
- end
-
- def subdirs(*args)
- args.flatten!
- ch = Rant::Lib::parse_caller_elem(caller[1])
- args.each { |arg|
- if arg.respond_to? :to_str
- arg = arg.to_str
- else
- abort_at(ch, "subdirs: arguments must be strings")
- end
- loaded = false
- prev_subdir = @current_subdir
- begin
- goto arg
- if test(?f, Rant::SUB_RANTFILE)
- path = Rant::SUB_RANTFILE
- else
- path = rantfile_in_dir
- end
- if path
- if defined? @initial_subdir and
- @initial_subdir == @current_subdir
- rf, is_new = rantfile_for_path(path, false)
- @rantfiles.unshift rf if is_new
- else
- rf, is_new = rantfile_for_path(path)
- end
- load_file rf if is_new
- elsif !@opts[:no_warn_subdir]
- warn_msg(pos_text(ch[:file], ch[:ln]),
- "subdirs: No Rantfile in subdir `#{arg}'.")
- end
- ensure
- goto_project_dir prev_subdir
- end
- }
- rescue SystemCallError => e
- abort_at(ch, "subdirs: " + e.message)
- end
-
- def sys(*args, &block)
- args.empty? ? @sys : @sys.sh(*args, &block)
- end
-
- def var(*args, &block)
- args.empty? ? @var : @var.query(*args, &block)
- end
-
- def pop_desc
- td = @task_desc
- @task_desc = nil
- td
- end
-
- def abort(*msg)
- err_msg(msg) unless msg.empty?
- $stderr.puts caller if @opts[:trace_abort]
- raise Rant::RantAbortException
- end
-
- def abort_at(ch, *msg)
- err_msg(pos_text(ch[:file], ch[:ln]), msg)
- $stderr.puts caller if @opts[:trace_abort]
- raise Rant::RantAbortException
- end
-
- def show_help
- puts "rant [-f Rantfile] [Options] [targets]"
- puts
- puts "Options are:"
- print option_listing(OPTIONS)
- end
-
- def show_descriptions
- tlist = select_tasks { |t| t.description }
- def_target = target_list.first
- if tlist.empty?
- puts "rant # => " + list_task_names(
- resolve(def_target)).join(', ')
- msg "No described tasks."
- return
- end
- prefix = "rant "
- infix = " # "
- name_length = (tlist.map{ |t| t.to_s.length } << 7).max
- cmd_length = prefix.length + name_length
- unless tlist.first.to_s == def_target
- defaults = list_task_names(
- resolve(def_target)).join(', ')
- puts "#{prefix}#{' ' * name_length}#{infix}=> #{defaults}"
- end
- tlist.each { |t|
- print(prefix + t.to_s.ljust(name_length) + infix)
- dt = t.description.sub(/\s+$/, "")
- puts dt.gsub(/\n/, "\n" + ' ' * cmd_length + infix + " ")
- }
- true
- end
-
- def list_task_names(*tasks)
- rsl = []
- tasks.flatten.each { |t|
- if t.respond_to?(:has_actions?) && t.has_actions?
- rsl << t
- elsif t.respond_to? :prerequisites
- if t.prerequisites.empty?
- rsl << t
- else
- t.prerequisites.each { |pre|
- rsl.concat(list_task_names(
- resolve(pre, t.project_subdir)))
- }
- end
- else
- rsl << t
- end
- }
- rsl
- end
- private :list_task_names
-
- def verbose
- @opts[:verbose]
- end
-
- def quiet?
- @opts[:quiet]
- end
-
- def pos_text(file, ln)
- t = "in file `#{file}'"
- t << ", line #{ln}" if ln && ln > 0
- t << ": "
- end
-
- def cmd_msg(cmd)
- puts cmd unless quiet?
- end
-
- def cmd_print(text)
- print text unless quiet?
- $stdout.flush
- end
-
- def cmd_targets
- @force_targets + @arg_targets
- end
-
- def running_task(task)
- if @current_subdir != @last_build_subdir
- cmd_msg "(in #{@current_subdir.empty? ?
- @rootdir : @current_subdir})"
- @last_build_subdir = @current_subdir
- end
- if @opts[:dry_run]
- task.dry_run
- true
- end
- end
-
- private
- def have_any_task?
- !@tasks.empty?
- end
-
- def target_list
- if !have_any_task? && @resolve_hooks.empty?
- abort("No tasks defined for this rant application!")
- end
-
- target_list = @force_targets + @arg_targets
- if target_list.empty?
- def_tasks = resolve "default"
- unless def_tasks.empty?
- target_list << "default"
- else
- @rantfiles.each { |f|
- first = f.tasks.first
- if first
- target_list << first.reference_name
- break
- end
- }
- end
- end
- target_list
- end
-
- def run_tasks
- target_list.each { |target|
- if build(target) == 0
- abort("Don't know how to make `#{target}'.")
- end
- }
- end
-
- def make(target, *args, &block)
- ch = nil
- if target.respond_to? :to_hash
- targ = target.to_hash
- ch = Rant::Lib.parse_caller_elem(caller[1])
- abort_at(ch, "make: too many arguments") unless args.empty?
- tn = nil
- prepare_task(targ, block, ch) { |name,pre,blk|
- tn = name
- @node_factory.new_file(self, name, pre, blk)
- }
- build(tn)
- elsif target.respond_to? :to_rant_target
- rt = target.to_rant_target
- opt = args.shift
- unless args.empty?
- ch ||= Rant::Lib.parse_caller_elem(caller[1])
- abort_at(ch, "make: too many arguments")
- end
- if block
- ch ||= Rant::Lib.parse_caller_elem(caller[1])
- prepare_task(rt, block, ch) { |name,pre,blk|
- @node_factory.new_file(self, name, pre, blk)
- }
- build(rt)
- else
- build(rt, opt||{})
- end
- elsif target.respond_to? :rant_gen
- ch = Rant::Lib.parse_caller_elem(caller[1])
- rv = target.rant_gen(self, ch, args, &block)
- unless rv.respond_to? :to_rant_target
- abort_at(ch, "make: invalid generator return value")
- end
- build(rv.to_rant_target)
- rv
- else
- ch = Rant::Lib.parse_caller_elem(caller[1])
- abort_at(ch,
- "make: generator or target as first argument required.")
- end
- end
- public :make
-
- def build(target, opt = {})
- opt[:force] = true if @force_targets.delete(target)
- opt[:dry_run] = @opts[:dry_run]
- matching_tasks = 0
- old_subdir = @current_subdir
- old_pwd = Dir.pwd
- resolve(target).each { |t|
- unless opt[:type] == :file && !t.file_target?
- matching_tasks += 1
- begin
- t.invoke(opt)
- rescue Rant::TaskFail => e
- err_task_fail(e)
- abort
- end
- end
- }
- @current_subdir = old_subdir
- Dir.chdir old_pwd
- matching_tasks
- end
- public :build
-
- def resolve(task_name, rel_project_dir = @current_subdir)
- s = @tasks[expand_path(rel_project_dir, task_name)]
- case s
- when nil
- @resolve_hooks.each { |s|
- s = s[task_name, rel_project_dir]
- return s if s
- }
- []
- when Rant::Node; [s]
- else # assuming list of tasks
- s
- end
- end
- public :resolve
-
- def rec_save_resolve(task_name, excl_hook, rel_project_dir = @current_subdir)
- s = @tasks[expand_path(rel_project_dir, task_name)]
- case s
- when nil
- @resolve_hooks.each { |s|
- next if s == excl_hook
- s = s[task_name, rel_project_dir]
- return s if s
- }
- []
- when Rant::Node; [s]
- else
- s
- end
- end
- public :rec_save_resolve
-
- def at_resolve(&block)
- @resolve_hooks << block if block
- end
- public :at_resolve
-
- def at_return(&block)
- hooks = var._get("__at_return__")
- if hooks
- hooks << block
- else
- var._set("__at_return__", [block])
- end
- end
- public :at_return
-
- def select_tasks
- selection = []
- @rantfiles.each { |rf|
- rf.tasks.each { |t|
- selection << t if yield t
- }
- }
- selection
- end
- public :select_tasks
-
- def load_rantfiles
- unless @arg_rantfiles.empty?
- @arg_rantfiles.each { |fn|
- if test(?f, fn)
- rf, is_new = rantfile_for_path(fn)
- load_file rf if is_new
- else
- abort "No such file -- #{fn}"
- end
- }
- return
- end
- return if have_any_task?
- fn = rantfile_in_dir
- if @opts[:cd_parent]
- old_root = @rootdir
- until fn or @rootdir == "/"
- @rootdir = File.dirname(@rootdir)
- fn = rantfile_in_dir(@rootdir)
- end
- if @rootdir != old_root and fn
- Dir.chdir @rootdir
- cmd_msg "(in #@rootdir)"
- end
- end
- if fn
- rf, is_new = rantfile_for_path(fn)
- load_file rf if is_new
- return
- end
- have_sub_rantfile = test(?f, Rant::SUB_RANTFILE)
- if have_sub_rantfile || @opts[:look_up]
- cur_dir = Dir.pwd
- until cur_dir == "/"
- cur_dir = File.dirname(cur_dir)
- Dir.chdir cur_dir
- fn = rantfile_in_dir
- if fn
- @initial_subdir = @rootdir.sub(
- /^#{Regexp.escape cur_dir}\//, '')
- @rootdir = cur_dir
- cmd_msg "(root is #@rootdir, in #@initial_subdir)"
- @last_build_subdir = @initial_subdir
- rf, is_new = rantfile_for_path(fn)
- load_file rf if is_new
- goto_project_dir @initial_subdir
- if have_sub_rantfile
- rf, is_new = rantfile_for_path(
- Rant::SUB_RANTFILE, false)
- if is_new
- @rantfiles.unshift rf
- load_file rf
- end
- end
- break
- end
- end
- end
- if @rantfiles.empty?
- abort("No Rantfile found, looking for:",
- Rant::RANTFILES.join(", "))
- end
- end
-
- def load_file(rantfile)
- vmsg 1, "source #{rantfile}"
- @context.instance_eval(File.read(rantfile), rantfile)
- end
- private :load_file
-
- def rantfile_in_dir(dir=nil)
- ::Rant::RANTFILES.each { |rfn|
- path = dir ? File.join(dir, rfn) : rfn
- return path if test ?f, path
- }
- nil
- end
-
- def process_args
- old_argv = ARGV.dup
- ARGV.replace(@args.dup)
- cmd_opts = GetoptLong.new(*OPTIONS.collect { |lst| lst[0..-2] })
- cmd_opts.quiet = true
- cmd_opts.each { |opt, value|
- case opt
- when "--verbose"; @opts[:verbose] += 1
- when "--version"
- puts "rant #{Rant::VERSION}"
- raise Rant::RantDoneException
- when "--help"
- show_help
- raise Rant::RantDoneException
- when "--directory"
- @rootdir = File.expand_path(value)
- when "--rantfile"
- @arg_rantfiles << value
- when "--force-run"
- @force_targets << value
- when "--import"
- import value
- else
- @opts[opt.sub(/^--/, '').tr('-', "_").to_sym] = true
- end
- }
- rescue GetoptLong::Error => e
- abort(e.message)
- ensure
- rem_args = ARGV.dup
- ARGV.replace(old_argv)
- rem_args.each { |ra|
- if ra =~ /(^[^=]+)=([^=]+)$/
- vmsg 2, "var: #$1=#$2"
- @var[$1] = $2
- else
- @arg_targets << ra
- end
- }
- end
-
- def prepare_task(targ, block, clr = caller[2])
-
- if targ.is_a? Hash
- targ.reject! { |k, v| clr = v if k == :__caller__ }
- end
- ch = Hash === clr ? clr : Rant::Lib::parse_caller_elem(clr)
-
- name, pre = normalize_task_arg(targ, ch)
-
- file, is_new = rantfile_for_path(ch[:file])
- nt = yield(name, pre, block)
- nt.rantfile = file
- nt.project_subdir = @current_subdir
- nt.line_number = ch[:ln]
- nt.description = @task_desc
- @task_desc = nil
- file.tasks << nt
- hash_task nt
- nt
- end
- public :prepare_task
-
- def hash_task(task)
- n = task.full_name
- et = @tasks[n]
- case et
- when nil
- @tasks[n] = task
- when Rant::Node
- mt = [et, task]
- @tasks[n] = mt
- else # assuming list of tasks
- et << task
- end
- end
-
- def normalize_task_arg(targ, ch)
- name = nil
- pre = []
-
- if targ.is_a? Hash
- if targ.empty?
- abort_at(ch, "Empty hash as task argument, " +
- "task name required.")
- end
- if targ.size > 1
- abort_at(ch, "Too many hash elements, " +
- "should only be one.")
- end
- targ.each_pair { |k,v|
- name = normalize_task_name(k, ch)
- pre = v
- }
- unless ::Rant::FileList === pre
- if pre.respond_to? :to_ary
- pre = pre.to_ary.dup
- pre.map! { |elem|
- normalize_task_name(elem, ch)
- }
- else
- pre = [normalize_task_name(pre, ch)]
- end
- end
- else
- name = normalize_task_name(targ, ch)
- end
-
- [name, pre]
- end
- public :normalize_task_arg
-
- def normalize_task_name(arg, ch)
- return arg if arg.is_a? String
- if Symbol === arg
- arg.to_s
- elsif arg.respond_to? :to_str
- arg.to_str
- else
- abort_at(ch, "Task name has to be a string or symbol.")
- end
- end
-
- def rantfile_for_path(path, register=true)
- abs_path = File.expand_path(path)
- file = @rantfiles.find { |rf| rf.path == abs_path }
- if file
- [file, false]
- else
- file = Rant::Rantfile.new abs_path
- file.project_subdir = @current_subdir
- @rantfiles << file if register
- [file, true]
- end
- end
-
- def get_ch_from_backtrace(backtrace)
- backtrace.each { |clr|
- ch = ::Rant::Lib.parse_caller_elem(clr)
- if ::Rant::Env.on_windows?
- return ch if @rantfiles.any? { |rf|
- rf.path.tr("\\", "/").sub(/^\w\:/, '') ==
- ch[:file].tr("\\", "/").sub(/^\w\:/, '')
- }
- else
- return ch if @rantfiles.any? { |rf|
- rf.path == ch[:file]
- }
- end
- }
- nil
- end
-
- def err_task_fail(e)
- msg = []
- t_msg = ["Task `#{e.tname}' fail."]
- orig = e
- loop { orig = orig.orig; break unless Rant::TaskFail === orig }
- if orig && orig != e && !(Rant::RantAbortException === orig)
- ch = get_ch_from_backtrace(orig.backtrace)
- msg << pos_text(ch[:file], ch[:ln]) if ch
- unless Rant::CommandError === orig && !@opts[:err_commands]
- msg << orig.message
- msg << orig.backtrace[0..4] unless ch
- end
- end
- if e.msg && !e.msg.empty?
- ch = get_ch_from_backtrace(e.backtrace)
- t_msg.unshift(e.msg)
- t_msg.unshift(pos_text(ch[:file], ch[:ln])) if ch
- end
- err_msg msg unless msg.empty?
- err_msg t_msg
- end
-end # class Rant::RantApp
-
-$".concat(['rant/rantlib.rb', 'rant/init.rb', 'rant/rantvar.rb', 'rant/rantsys.rb', 'rant/import/filelist/core.rb', 'rant/node.rb', 'rant/import/nodes/default.rb', 'rant/coregen.rb'])
-Rant::CODE_IMPORTS.concat %w(nodes/default
- )
-
-# Catch a `require "rant"', sad...
-alias require_backup_by_rant require
-def require libf
- if libf == "rant"
- # TODO: needs rework! look at lib/rant.rb
- self.class.instance_eval { include Rant }
- else
- begin
- require_backup_by_rant libf
- rescue
- raise $!, caller
- end
- end
-end
-
-exit Rant.run