# $Id: manifest.rb,v 1.8 1999/08/27 02:23:00 akira Exp $
require 'ftools'

module Manifest
  IGNORE_DIR_REGEXP = 
    /^(ext|lib|missing|win32|x68|src)$/i
  EXAMPLE_DIR_REGEXP = 
    /^(example|samples?|demo)$/i
  EXAMPLE_DIR_EXCLUDE_REGEXP = 
    /^$/o unless defined?(EXAMPLE_DIR_EXCLUDE_REGEXP)
  DOCUMENT_DIR_REGEXP = 
    /^(manual|doc|html).*$/i
  DOCUMENT_DIR_EXCLUDE_REGEXP = 
    /^$/o unless defined?(DOCUMENT_DIR_EXCLUDE_REGEXP)

  IGNORE_REGEXP = 
    /^lib|^extconf\.rb|^Makefile\.rb|^depend$|^instruby\.rb$|^mkconfig\.rb$|^rubytest\.rb$/
  EXAMPLE_REGEXP = 
    /^(.+\.rb)$/
  EXAMPLE_EXCLUDE_REGEXP = 
    /^$/o unless defined?(EXAMPLE_EXCLUDE_REGEXP)
  DOCUMENT_REGEXP = 
    /^ChangeLog|^MANUAL|^README|^HISTORY|^ToDo|\.(txt|doc|html)(\...)?$/i
  DOCUMENT_EXCLUDE_REGEXP = 
    /^$/o unless defined?(DOCUMENT_EXCLUDE_REGEXP)

  Manifest_info = Struct.new('MANIFEST_INFO', 
			     :document_dir_files, 
			     :document_files,
			     :example_dir_files,
			     :example_files)

  def read_manifest(manifest, prefix = '')
    info = Manifest_info.new([], [], [], [])

    IO.foreach(manifest) {|l|
      l.chomp!
      l.sub!(%r!^\./!o, '')

      dir  = l.split(%r!/!)
      file = dir.pop

      f = false
      doc = nil
      exp = nil
      dir.each {|d|
	if IGNORE_DIR_REGEXP =~ d
	  f = true
	  doc = nil
	  exp = nil
	  break

	elsif DOCUMENT_DIR_EXCLUDE_REGEXP =~ d
	  f = true
	  doc = nil
	  break

	elsif DOCUMENT_DIR_REGEXP =~ d &&
	    DOCUMENT_EXCLUDE_REGEXP !~ file
	  f = true
	  doc = prefix + l

	elsif EXAMPLE_DIR_EXCLUDE_REGEXP =~ d
	  f = true
	  exp = nil
	  break

	elsif EXAMPLE_DIR_REGEXP =~ d &&
	    EXAMPLE_EXCLUDE_REGEXP !~ file
	  f = true
	  exp = prefix + l
	end
      }
      info.document_dir_files << doc if doc
      info.example_dir_files  << exp if exp
      next if f


      if IGNORE_REGEXP =~ file
	next
      elsif DOCUMENT_REGEXP =~ file &&
	  DOCUMENT_EXCLUDE_REGEXP !~ file
	info.document_files << prefix + l
      elsif EXAMPLE_REGEXP =~ file &&
	  EXAMPLE_EXCLUDE_REGEXP !~ file
	info.example_files  << prefix + l
      end
    }

    return info
  end
  module_function :read_manifest

  def compact_path(paths)
    return paths if paths.size == 0

    dir = paths[0].split(%r!/!)
    dir.pop

    dup_part = nil
    while dir.size > 0
      d = dir.join('/') + '/'
      i = 0
      paths.each {|x|
	f = x.index(d)
	if !f || f != 0
	  break
	end
	i += 1
      }
      if i == paths.size
	dup_part = d
	break
      end

      dir.pop
    end

    if dup_part
      beg = dup_part.length
      paths = paths.collect {|x|
	x[beg..-1]
      }
    end

    return paths
  end
  module_function :compact_path

  def get_install_list(info, base_dir)
    base_dir = base_dir.sub(%r!/$!o, '')
    list = []

    if info.document_dir_files.size > 0
      list += get_install_list2(info.document_dir_files, base_dir)
    end
    if info.document_files.size > 0
      list += get_install_list2(info.document_files, base_dir)
    end

    base_example_dir = base_dir + '/examples'
    if info.example_dir_files.size > 0
      list += get_install_list2(info.example_dir_files, 
				base_example_dir)
    end
    if info.example_files.size > 0
      list += get_install_list2(info.example_files, 
				base_example_dir)
    end

    return list
  end
  module_function :get_install_list

  def get_install_list2(files, base_dir)
    src = files.dup
    dst = compact_path(files)

    list = []
    src.each_index{|i|
      if %r!^changelog!i =~ src[i]
	# print "#{src[i]} -> #{base_dir}/changelog#{$'}\n"
	# File.install(src[i], base_dir + "/changelog#{$'}"", mode, verbose)
	list << [src[i], base_dir + "/changelog#{$'}"]
      else
	# print "#{src[i]} -> #{base_dir}/#{dst[i]}\n"
	# File.install(src[i], base_dir + '/' + dst[i], mode, verbose)
	list << [src[i], base_dir + '/' + dst[i]]
      end
    }

    return list
  end
  module_function :get_install_list2
end

if $0 == __FILE__
  t = Manifest::read_manifest("MANIFEST")

  # p t
  # p Manifest::compact_path(t.document_dir_files)
  # p Manifest::compact_path(t.document_files)
  # p Manifest::compact_path(t.example_dir_files)
  # p Manifest::compact_path(t.example_files)

  Manifest::get_install_list(t, "tmp/usr/doc/ruby-foo-mod").each {|x|
    print "#{x[0]} -> #{x[1]}\n"
  }
end
