#!/usr/bin/env ruby
raise 'Please, use ruby1.8.4 or later.' if RUBY_VERSION < '1.8.4'
=begin
 Rantfile mapping setup.rb directory structure

 SiSU Simple information Structuring Universe, Serialised information, Structured Units
 * SiSU at present is for the Linux/Unix platform
 * See homepage at: <<  http://www.jus.uio.no/sisu/SiSU  >>
 * &  <<  http://www.jus.uio.no/sisu/download  >>

 Rant is a Ruby 'ant' by Stefan Lang

 For Setup/Installation SiSU uses either:
 * Minero Aoki's setup.rb, provided along with SiSU, or 
 * Rant which may be downloaded and installed from: 
     http://make.rubyforge.org/

 * Name: Rant install/setup file for SiSU - Simple information Structuring Universe, Serialised information Structured Units
 *
 * Author: Ralph@Amissah.com
 * Description: Rant install/setup file which maps directory structure used by setup.rb
   * arch-tag: Rant install/setup file which maps directory structure used by setup.rb
   * $Id$

 Copyright (C) 2005 Ralph Amissah (first release edition)
 Copyright (C) 1997 Ralph Amissah (first edition)

 * License: GPL 2 or later

  Summary of GPL 2

  This program is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the Free
  Software Foundation; either version 2 of the License, or (at your option)
  any later version.

  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  more details.

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

  If you have Internet connection, the latest version of the GPL should be
  available at these locations:
    http://www.fsf.org/licenses/gpl.html
    http://www.gnu.org/copyleft/gpl.html
    http://www.jus.uio.no/sisu/gpl2.fsf

  SiSU was first released to the public on January 4th 2005

  SiSU uses:
  
  *  Standard SiSU markup syntax,
  *  Standard SiSU meta-markup syntax, and the
  *  Standard SiSU object citation numbering and system
  
  © Ralph Amissah 1997, current 2005.
  All Rights Reserved.

 * Ralph Amissah mailto:ralph@amissah.com
   Ralph Amissah mailto:amissah@gmail.com

 * NOTE reminder to create independent setup file called install:
     rant-import --auto install
   then you can, as root (for default action):
     ruby install
   or for help on alternative actions:
     ruby install help
     ruby install -T

=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
PKG_VERSION=Version
@dir[:version]=Version
@host=Config::CONFIG['host']
@dir[:arch]=Config::CONFIG['archdir']
@dir[:sitearch]=Config::CONFIG['sitearchdir']
@dir[:bin]=Config::CONFIG['bindir']
#@dir_lib=Config::CONFIG['rubylibdir']
@dir[:lib]=Config::CONFIG['sitelibdir']
#@dir_lib='/usr/local/lib/site_ruby/1.9' #Config::CONFIG['sitelibdir']
@dir[:data]=Config::CONFIG['datadir']
@dir[:share]="#{Config::CONFIG['datadir']}/sisu"
@dir[:conf]=Config::CONFIG['sysconfdir']                     #etc
@dir[:man]=Config::CONFIG['mandir']
@dir[:vim]="#{Config::CONFIG['datadir']}/sisu/vim"
@dir[:out]="#{Config::CONFIG['localstatedir']}/#{@dir[:proj]}"
@rubylib=Config::CONFIG['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
                                                           #%% using a single filelist
#filelist broken in switch to rant from rake
#filelist=Rant::FileList.new('bin/*','lib/**/*','conf/**/*','data/**/*','man/**/*')
#filelist=Rant::FileList.new('bin/*','lib/**/*','conf/**/*','data/**/*','data/man/**/*')
def dest(f)                                                #filelist mapping - note currently does not get 'data/man'
  stub=f.scan(/^\S+?\/(\S+)/).join
  place=case f
  when /^bin/;        "#{@dir[:bin]}/#{stub}"
  when /^lib/;        "#{@dir[:lib]}/#{stub}"
  when /^conf/;       "#{@dir[:conf]}/#{stub}"
  when /^data/;       "#{@dir[:data]}/#{stub}" unless f =~/^data\/sisu/
  when /^share/;      "#{@dir[:share]}"
  when /^man/;        "#{@dir[:man]}/#{stub}"
  when /^vim/;        "#{@dir[:conf]}/#{stub}/vim"
  else 'ERROR' #change
  end
end
def setup_filelist_cp_r(filelist)                          #secondary, using recursive copy
  filelist.sort.each do |f|
    place=dest(f)
    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 setup_filelist_create(filelist)                        #secondary
  filelist.sort.each do |f|
    place=dest(f)
    action=case
    when File.file?(f)
      cp(f,place)
      chmod_file(place)
      "->  #{place}"
    when File.directory?(f)
      p place
      File.mkpath(place) unless FileTest.directory?(place)
      ".#{place}/"
    else '?'
    end
    puts action
  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]
#:install uses filelist which was broken in switch to rant from rake, look at later
#task :install => [:install]
task :install_a => [:rant_default1]
task :install_b => [:rant_default2]
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_default1 do                                     #secondary
  setup_filelist_cp_r(filelist)
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 :install do                                           #secondary
  setup_filelist_create(filelist)
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
  Config::CONFIG.each {|c| p c }
end
task :project_help do                                       #%% help
  rant_project_help
end
task :rant_tasks do                                       #%% help
  rant_tasks
end