#
# futils.rb
#
#   Copyright (c) 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
#

require 'amstd/fileutils'


module FileUtils

  include FileTest
  extend FileTest


  module_function


  @verbose = false
  @futils_output = $stderr

  def futilsmsg( msg )
    @futils_output ||= $stderr
    @futils_output.puts 'futils: ' + msg
  end
  private_class_method :futilsmsg


  FU = FileUtilities

  def cd( dn )
    if iterator? then
      pre = Dir.pwd
      Dir.chdir dn
      yield
      Dir.chdir pre
    else
      Dir.chdir dn
    end
  end
  alias chdir cd

  def indir( dir, *args )
    args.flatten!
    args.collect do |fn|
      %r(\A[/\\]) === fn ? fn : FU.join(dir, fn)
    end
  end

  def isdir( *args )
    args.flatten!
    dn = FU.join( *args )
    mkdir_p dn
    dn
  end

  def mustdir( dn )
    full = File.expand_path( dn )
    unless directory? full then
      raise ArgumentError, "#{dn} is not directory"
    end
    full
  end

  def pwd
    Dir.pwd
  end


  def expand( fn )
    File.expand_path fn
  end

  def dirname( fn )
    File.dirname fn
  end

  def basename( fn )
    File.basename fn
  end

  def fjoin( *args )
    FU.join( args )
  end
  alias sepjoin fjoin

  def is_newer?( new, *old )
    old.flatten!
    old.each do |fn|
      return false unless FU.is_newer? new, fn
    end
    true
  end
  alias uptodate? is_newer?

  def is_older?( old, *new )
    new.flatten!
    new.each do |fn|
      return false unless FU.is_older? old, fn
    end
    true
  end


  def mkdir( *args )
    args.flatten!
    futilsmsg "mkdir #{args.join ' '}" if @verbose
    args.each do |i|
      Dir.mkdir File.expand_path(i)
    end
  end

  def mkdir_p( *args )
    args.flatten!
    futilsmsg "mkdir -p #{args.join ' '}" if @verbose
    args.each do |i|
      FU.mkdir_p File.expand_path(i)
    end
  end
  alias mkpath mkdir_p

  def rmdir( *args )
    args.flatten!
    futilsmsg "rmdir -p #{args.join ' '}" if @verbose
    args.each do |i|
      Dir.rmdir File.expand_path(i)
    end
  end


  def ln( old, new )
    futilsmsg "ln #{old} #{new}" if @verbose
    FU.ln File.expand_path(old), File.expand_path(new)
  end

  def ln_s( old, new )
    futilsmsg "ln -s #{old} #{new}" if @verbose
    FU.ln_s File.expand_path(old), File.expand_path(new)
  end


  BSIZE = FU::BSIZE

  def cp( *args )
    args.flatten!
    to = args.pop
    futilsmsg "cp #{args.join ' '} #{to}" if @verbose
    to = File.expand_path( to )
    args.each do |i|
      FU.cp File.expand_path(i), to
    end
  end

  def cp_r( from, to )
    futilsmsg "cp -r #{from} #{to}" if @verbose
    FU.cp_r File.expand_path(from), File.expand_path(to)
  end


  def mv( *args )
    args.flatten!
    to = args.pop
    futilsmsg "mv #{args.join ' '} #{to}" if @verbose
    to = File.expand_path( to )
    args.each do |i|
      FU.mv File.expand_path(i), to
    end
  end


  def rm( *args )
    args.flatten!
    futilsmsg "rm #{args.join ' '}" if @verbose
    args.each do |i|
      FU.rm File.expand_path(i)
    end
  end

  def rm_f( *args )
    args.flatten!
    futilsmsg "rm -f #{args.join ' '}" if @verbose
    args.each do |i|
      FU.rm_f File.expand_path(i)
    end
  end

  def rm_rf( *args )
    args.flatten!
    futilsmsg "rm -rf #{args.join ' '}" if @verbose
    args.each do |i|
      FU.rm_rf File.expand_path(i)
    end
  end


  def cmp( a, b )
    futilsmsg "cmp #{a} #{b}" if @verbose
    FU.cmp a, b
  end
  alias identical? cmp


  def install( from, to, mode = nil )
    futilsmsg "install #{mode ? '%o ' % mode : ''}#{from} #{to}" if @verbose
    FU.install from, to, mode
  end


  def foreach_fullpath( dn )
    d = Dir.open( dn )
    dirs = d.to_a
    d.close
    dirs.each do |fn|
      next if fn == '.' or fn == '..'
      yield FU.join(dn, fn)
    end
  end

  def chmod( mode, *args )
    args.flatten!
    futilsmsg "chmod #{mode ? '%o ' % mode : ''}#{args.join ' '}" if @verbose
    File.chmod mode, *args
  end

  Separator = FU::Separator


  def command( line )
    unless ret = system( line ) then
      raise ArgumentError, "'system #{line}' failed"
    end
    ret
  end

end
