#!/usr/bin/env ruby
raise 'Please, use ruby1.8.4 or later.' if RUBY_VERSION < '1.8.4'
=begin
 Rantfile installer for SiSU
 * Homepage: <http://www.jus.uio.no/sisu/SiSU> <http://www.sisudoc.org>
 * Download:  <http://www.jus.uio.no/sisu/download>


 Copyright (C) 2007 Ralph Amissah

 * License: LGPL - GNU Lesser General Public License
     [same license as Rant provided within the Rant package]

 * Ralph Amissah <ralph@amissah.com>
   Ralph Amissah <ralph.amissah@gmail.com>

 Rant is a Ruby 'ant' by Stefan Lang
 * Rant may be downloaded and installed from:
     http://make.rubyforge.org/

 Notes on use:

     rant -T

 SiSU can also be Setup/Installation using:
 * Minero Aoki's setup.rb, provided along with SiSU, or

=end
#%% produce a makefile suitable for the target platform
#require 'mkmf'
#create_makefile("sisu")
require 'find'
require 'fileutils'
require 'rbconfig.rb'
include FileUtils
@dir=Hash.new
@proj=Hash.new
                                                           #%% project specific variables
@proj[:name]='SiSU'
@proj[:rant]="Rantfile for the installation/setup of #{@proj[:name]}"
@proj[:platform_notice]="[#{@proj[:name]} is for the Linux/Unix Platforms]"
@dir[:proj]='sisu'
Version=` pwd | grep -o "[0-9]+\.[0-9]+\.[0-9]+$" | grep -o "^[0-9]+\.[0-9]+"`                                             #%% NOTE placing version number permits fine grained removal of version directories if used in lib and conf / etc
                                                           #%% system configuration
@env=Config::CONFIG
PKG_VERSION=Version
@dir[:version]=Version
@host=@env['host']
@dir[:arch]=@env['archdir']
@dir[:sitearch]=@env['sitearchdir']
@dir[:bin]=@env['bindir']
#@dir_lib=@env['rubylibdir']
@dir[:lib]=@env['sitelibdir']
#@dir_lib='/usr/local/lib/site_ruby/1.9' #@env['sitelibdir']
@dir[:data]=@env['datadir']
@dir[:share]="#{@env['datadir']}/sisu"
@dir[:conf]=@env['sysconfdir']                     #etc
@dir[:man]=@env['mandir']
@dir[:vim]="#{@env['datadir']}/sisu/vim"
@dir[:out]="#{@env['localstatedir']}/#{@dir[:proj]}"
@rubylib=@env['LIBRUBYARG_SHARED']
@pwd=Dir.pwd
def answer?(ask)
  resp='redo'
  print ask + " ['yes', 'no' or 'quit']: "
  resp=File.new('/dev/tty').gets.strip
  #resp=gets.strip
  ans=if resp == 'yes'; true
  elsif resp == 'no'; false
  elsif resp =~/^quit|exit$/; exit
  else puts "[please type: 'yes', 'no' or 'quit']"
    answer?(ask)
  end
end
def default_notice
    ans= %{#{@proj[:rant]}
  Information on alternative actions is available using:
    "rant help" or "rant -T"
  Default action selected - "install and to setup #{@proj[:name]}" proceed? }
    resp=answer?(ans)
    exit unless resp
end
def get_username
  gets.strip
end
def chmod_file(place)
  if place =~/\/bin/; File.chmod(0755,place)
  else                File.chmod(0644,place)
  end
end
def chmod_util(place)
  if place =~/\/bin/; chmod(0755,place)
  else                chmod(0644,place)
  end
end
                                                           #%% using a directory and its mapping
def setup_find_create(dir_get,dir_put)                     #primary,
  Find.find("#@pwd/#{dir_get}") do |f|
    stub=f.scan(/#@pwd\/#{dir_get}\/(\S+)/).join
    place="#{dir_put}/#{stub}"
    action=case
    when File.file?(f)
      cp(f,place)
      chmod_file(place)
      "->  #{dir_put}/"
    when File.directory?(f)
      FileUtils.mkpath(place) unless FileTest.directory?(place)
      "./#{dir_get}/"
    else '?'
    end
    puts "#{action}#{stub}"
  end
end
def setup_find_cp_r(dir_get,dir_put)                       #secondary, using recursive copy
  Find.find("#@pwd/#{dir_get}") do |f|
    stub=f.scan(/#@pwd\/#{dir_get}\/(\S+)/).join
    place="#{dir_put}/#{stub}"
    case
    when File.file?(f)
      cp_r(f,place)
      chmod_util(place)
    when File.directory?(f)
      mkdir(place) unless FileTest.directory?(place)
    end
  end
end
def rant_system_info
  puts <<WOK
  #{@proj[:platform_notice]}

  Host
    host:             #@host
    arch:             #{@dir[:arch]}
    sitearch:         #{@dir[:sitearch]}

  Directories for installation
    bin:                                          #{@dir[:bin]}
    lib (site-ruby):                              #{@dir[:lib]}/#{@dir[:proj]}/#{Version}
    conf [etc]:                                   #{@dir[:conf]}/#{@dir[:proj]}
    data (odf, shared images):                    #{@dir[:share]}
    vim  (vim syntax, highlighting, ftplugin):    #{@dir[:data]}/sisu/vim
    data (README, version_manifest):              #{@dir[:data]}/doc/#{@dir[:proj]}
    man (manual pages):                           #{@dir[:man]}
    output:                                       #{@dir[:out]}
      processing:                                 #{@dir[:out]}/processing
      www:                                        #{@dir[:out]}/www

    rubylib:          #@rubylib

WOK
end
def rant_project_help
  puts <<WOK

#{@proj[:name]}
  #{@proj[:rant]}
  #{@proj[:platform_notice]}

Commands quick start list

  #{@proj[:name]} Rant Help:          (This Rantfile uses the same directory structure as setup.rb)
    rant -T                # a task list, (generated by Rant) for more complete and up to date help
    rant system            # system info used

  Quick start install and remove project #{@proj[:name]}
   as root:
    rant                   # install #{@proj[:name]}

    rant setup             # install #{@proj[:name]} (without additonal configuration and generating of test file)

    rant reinstall         # reinstall #{@proj[:name]}

    rant remove            # clobber/remove #{@proj[:name]}, current version: #{Version}
    rant remove_package    # clobber/remove #{@proj[:name]}, all versions

For a more detailed and up to date list of command options use

  rant -T

WOK
end
def rant_tasks
  sys('rant -T')
end
                                                           #%% tasks
desc "rant (as root type 'rant' for default action)"
task :default => [:default_notice,:project]
#task :default => [:help,:notice,:project]
desc "Setup/Install #{@proj[:name]} and try generate a file"
task :project=> [:setup_bin,:setup_lib,:setup_conf,:setup_share,:setup_data,:setup_man,:setup_vim,:post_install_note]
desc "Setup/Install #{@proj[:name]}"
task :setup=> [:setup_bin, :setup_lib,:setup_conf,:setup_share,:setup_data,:post_install] #, :help]
desc "Setup/Install #{@proj[:name]}: bin, lib and conf (no data)"
task :setup_base=> [:setup_bin,:setup_lib,:setup_conf,:setup_share,:setup_man,:setup_vim]
desc "Setup/Install #{@proj[:name]} bin, lib and conf (no data and no attempt to do postinstall setup)"
task :base=> [:setup_base]
if File.directory?('bin')                                       #bin
  desc "Setup #{@proj[:name]} bin only, synonym :bin"
  task :setup_bin => [:setup_bin]
  task :bin => [:setup_bin]
end
if File.directory?('lib')                                       #lib
  desc "Setup #{@proj[:name]} lib only, synonym :lib"
  task :setup_lib => [:setup_lib]
  task :lib => [:setup_lib]
end
if File.directory?('conf')                                      #conf or etc
  desc "Setup #{@proj[:name]} conf only, synonyms :conf & :etc"
  task :setup_conf => [:setup_conf]
  task :conf => [:setup_conf]
  task :setup_etc => [:setup_conf]
  task :etc => [:setup_conf]
end
if File.directory?('data')                                      #data
  desc "Setup #{@proj[:name]} data only, synonyms :data & :examples"
  task :setup_data => [:setup_data]
  task :data => [:setup_data]
  task :setup_examples => [:setup_data]
  task :examples => [:setup_data]
end
if File.directory?('data/sisu')                                      #share (odf shared-images)
  desc "Setup #{@proj[:name]} shared data only (odf & shared images)"
  task :setup_share => [:setup_share]
  task :share => [:setup_share]
end
if File.directory?('man')                                  #man pages
  desc "Setup #{@proj[:name]} man pages only, synonyms :man"
  task :setup_man => [:setup_man]
  task :man => [:setup_man]
end
if File.directory?('data/vim')                                  #man pages
  desc "Setup #{@proj[:name]} vim config files only, synonyms :vim"
  task :setup_vim => [:setup_vim]
  task :vim => [:setup_vim]
end
desc "Setup/Install #{@proj[:name]}: bin, lib, conf and data (no attempt to do postinstall setup)"
task :setup_only=> [:setup_bin,:setup_lib,:setup_conf,:setup_share,:setup_data,:help]
#desc "Remove #{@proj[:name]} version: #{Version}"
#task :remove => [:remove_version]
desc "Remove #{@proj[:name]} (all versions)"                   #remove project
task :remove_package => [:remove_bin, :remove_lib, :remove_conf]
if File.directory?('bin')                                       #bin
  desc "Remove #{@proj[:name]} bin only"                       #remove bin
  task :remove_bin => [:remove_bin]
end
if File.directory?('lib')                                       #lib
  desc "Remove #{@proj[:name]} lib only"                       #remove lib
  task :remove_lib => [:remove_lib]
end
if File.directory?('conf')                                      #conf
  desc "Remove #{@proj[:name]} conf only"                      #remove conf
  task :remove_conf => [:remove_conf]
end
#if File.directory?('data')                                      #data
#  desc "Remove #{@proj[:name]} data only"                      #remove data
#  task :remove_data => [:remove_data]
#end
desc "Re-setup #{@proj[:name]}, synonym :reinstall"            #resetup reinstall
task :resetup => [:remove, :setup]
task :reinstall => [:remove, :setup]
desc "Re-setup #{@proj[:name]}: bin, lib, conf (ignore data), synonym :reinstall"  #partial reinstall
task :resetup_base => [:remove, :setup_base]
task :reinstall_base => [:remove, :setup_base]
if File.directory?('bin')                                       #bin
  desc "Re-setup #{@proj[:name]} bin, synonym :reinstall"
  task :resetup_bin => [:remove_bin, :setup_bin]
  task :reinstall_bin => [:remove_bin, :setup_bin]
end
if File.directory?('lib')                                       #lib
  desc "Re-setup #{@proj[:name]} lib, synonym :reinstall_lib"
  task :resetup_lib => [:remove_lib, :setup_lib]
  task :reinstall_lib => [:remove_lib, :setup_lib]
end
if File.directory?('conf')                                       #conf
  desc "Re-setup #{@proj[:name]} conf, synonyms :reinstall_conf & :resetup_etc"
  task :resetup_conf => [:remove_conf, :setup_conf]
  task :reinstall_conf => [:remove_conf, :setup_conf]
  task :resetup_etc => [:remove_conf, :setup_conf]
  task :reinstall_etc => [:remove_conf, :setup_conf]
end
if File.directory?('data/sisu')                                       #share
  desc "Re-setup #{@proj[:name]} shared data, (odf & images)"
  task :resetup_share => [:remove_share, :setup_share]
  task :reinstall_share => [:remove_share, :setup_share]
end
if File.directory?('man')                                    #man
  desc "Re-setup #{@proj[:name]} man, synonym :reinstall_man"
  task :resetup_man => [:remove_man, :setup_man]
  task :reinstall_man => [:remove_man, :setup_man]
end
desc "Setup Note"
task :setup_note => [:help]
desc "Note on post installation"                      #remove conf
task :post_install_note => [:post_install_note]
desc "System information used by #{@proj[:name]}"
task :system => [:system_info,:project_help,:post_install_note]
desc "show all system info available - parameters found"
task :system_param => [:system_param]
desc "Help"
task :help => [:project_help,:system_info,:rant_tasks,:pi?]
#desc "Setup/Install #{@proj[:name]} (uses filelist)"
task :install => [:default_notice,:project]
task :install_bin => [:setup_bin]
desc "[make rant install file]"
task :create_rant_independent_task_file => [:rant_independence]
                                                           #%% setup/install tasks
task :rant_independence do                                 #notice
  resp=''
  while resp.length < 4
    resp='install'                                     #default name install
    print %{#{@proj[:rant]}
  Create a rant dependency independent file
  provide filename default name is "install"
    [Warning, will overwrite file of name provided
      provide name or "quit" to exit]: }
    #res=File.new('/dev/tty').gets.strip
    #resp=res if res =~/\S{4,30}/
    exit if resp =~/^(?:n|quit|exit)$/
  end
  remove='y' #remove='n'
  #remove=if FileTest.file?(resp)
  #  print "a file of the same name #{resp} exists, [y] to replace: "
  #  File.new('/dev/tty').gets.strip
  #else 'y'
  #end
 if remove =~/y/; system("rant-import --force --auto #{resp}\n")
   #puts "#{resp} updated"
 else #puts "#{resp} not replaced"
 end
end

task :default_notice do                                    #notice
  default_notice
end
task :rant_default2 do                                     #secondary
  setup_find_cp_r('bin',@dir[:bin]) if File.directory?('bin')
  setup_find_cp_r('lib',@dir[:lib]) if File.directory?('lib')
  setup_find_cp_r('conf',@dir[:conf]) if File.directory?('conf')
  setup_find_cp_r('data/sisu',"#{@dir[:share]}") if File.directory?('data/sisu') #
  setup_find_cp_r('data',@dir[:data]) if File.directory?('data')
  setup_find_cp_r('data/vim',"#{@dir[:data]}/vim") if File.directory?('data/vim')
  setup_find_cp_r('man',@dir[:man]) if File.directory?('man')
end
task :setup_bin do                                         #bin
  setup_find_create('bin',@dir[:bin]) if File.directory?('bin')
end
task :setup_lib do                                         #lib
  setup_find_create('lib',@dir[:lib]) if File.directory?('lib')
end
task :setup_conf do                                        #conf
  setup_find_create('conf',@dir[:conf]) if File.directory?('conf')
end
task :setup_share do                                        #share
  setup_find_create('data/sisu',@dir[:share]) if File.directory?('data/sisu')
end
task :setup_data do                                        #data
  setup_find_create('data',@dir[:data]) if File.directory?('data')
end
task :setup_man do                                         #man
  setup_find_create('man',@dir[:man]) if File.directory?('man') #man pages
  setup_find_create('man.deb/man',@dir[:man]) if File.directory?('man.deb/man') #man pages
end
task :setup_vim do                                         #man
  setup_find_create('data/vim',@dir[:vim]) if File.directory?('data/vim') #man pages
end
                                                           #%% post install
                                                           #%% clobber/remove tasks
task :remove_bin do
  rm_r "#{@dir[:bin]}/#{@dir[:proj]}" if FileTest.file?("#{@dir[:bin]}/#{@dir[:proj]}")
end
task :remove_lib do
  rm_r "#{@dir[:lib]}/#{@dir[:proj]}" if FileTest.directory?("#{@dir[:lib]}/#{@dir[:proj]}")
end
task :remove_conf do
  rm_r "#{@dir[:conf]}/#{@dir[:proj]}" if FileTest.directory?("#{@dir[:conf]}/#{@dir[:proj]}")
end
#task :remove_data do
#  rm_r "#{@dir[:data]}/#{@dir[:proj_eg]}" if FileTest.directory?("#{@dir[:data]}/#{@dir[:proj_eg]}")
#end
task :remove_man do
  rm_r "#{@dir[:man]}/**/#{@dir[:proj]}" if FileTest.directory?("#{@dir[:man]}/man1/#{@dir[:proj]}")
end
task :remove_version do
  rm_r "#{@dir[:bin]}/#{@dir[:proj]}" if FileTest.file?("#{@dir[:bin]}/#{@dir[:proj]}")
  rm_r "#{@dir[:lib]}/#{@dir[:proj]}/#{Version}" if FileTest.directory?("#{@dir[:lib]}/#{@dir[:proj]}/#{Version}")
  rm_r "#{@dir[:conf]}/#{@dir[:proj]} if FileTest.directory?("#{@dir[:conf]}/#{@dir[:proj]}")
  #rm_r "#@dir_data/#{@dir[:proj]}"
end
task :remove_package do
  rm_r "#{@dir[:bin]}/#{@dir[:proj]}" if FileTest.file?("#{@dir[:bin]}/#{@dir[:proj]}")
  rm_r "#{@dir[:lib]}/#{@dir[:proj]}" if FileTest.directory?("#{@dir[:lib]}/#{@dir[:proj]}")
  rm_r "#{@dir[:conf]}/#{@dir[:proj]}" if FileTest.directory?("#{@dir[:conf]}/#{@dir[:proj]}")
end
task :post_install_note do
  puts <<WOK

  sisu markup samples are now packaged separately in sisu-markup-samples
    visit:
      http://www.jus.uio.no/sisu
    and:
      http://www.jus.uio.no/sisu/SiSU/download

WOK
end
task :system_info do                                       #%% system info
  rant_system_info
end
task :system_param do
  @env.each {|c| puts c.inspect }
end
task :project_help do                                       #%% help
  rant_project_help
end
task :rant_tasks do                                       #%% help
  rant_tasks
end