#!/usr/bin/perl
#
# Auther:	Jun Kuwamura(juk@rccm.co.jp)
# Creation Date:	02/02/1998
#
# Description:
#  Slackware の pkgtool によるインストールにより /var/adm/packages/ ディレ
# クトリに作成されるようなパッケージの内容リストを PostgreSQL データベース
# に登録します。 pkglis(パッケージに含まれるファイルのリスト) と pkgtab 
# (それ以外の情報)というテーブルを作り、pkglis のカラムに索引を付けます。
#
#  使い方は、
#	pkg2db.pl [-i] <filename>...
#
#	-i:		指定するとテーブルを作り直します。
#	<filename>...:	パッケージファイル名(複数可能です)
#
#  なお、package という名前のデータベースをあらかじめ作るか、あるいは、この
# スクリプトの中の $DBNAME の値を既存のデータベース名にする必要があります。
# package データベースを作る場合はコマンドラインにて、
#
#	% createdb package
#
# あるいは、SQL を使う場合は、  
#
#	% psql
#	postgres=> create database package;
#	postgres=> \q
#
# を実行します。
#
#  インストールされた Plagiaware のパッケージリストをすべて登録するには、
#
#	% pkg2db.pl -i /var/adm/packages/*
#
# を実行するとできますが、Pentium100 のマシンで約2時間くらいかかりますので
# ご注意下さい。
#
# History:
#  1998-02-19(Thu) JuK Add comment
#  1998-02-20(Fri) JuK Add -i option
#  1998-02-28(Sat) JuK Mod 日本語の見出しに対応
#

use Pg;
$DBNAME = 'package';
#$DBNAME = 'postgres';
$SIG{PIPE} = sub { print "broken pipe\n" };
$DEBUG  = 0;			# set this to 1 for traces

if ($#ARGV < 0) {
	print "Usage:\n";
	print "\tpkg2db.pl [-i] <filename> [<filename1> ...]\n";
	print "\t\t-i:\tinitialize tables\n";
	print "\t\t<filename>:\tpackage contents list file name\n";
	exit;
}

&_db_conn;

if ($ARGV[0] eq "-i") {
	&_db_init_pkg unless ($DEBUG);
	shift(@ARGV);
}

if ($#ARGV > -1) {		# if input files are specified on command line
  FILE: while ($filename = shift(@ARGV)) {
      if ( ! -r  $filename ) {
	  print "Error! file: $filename is not exist!\n";
	  next FILE;
      }
      &_mklist($filename);
  }
}


sub _mklist
{
   $filepath = shift;		#   local($filepath) = @_;

   @filepath = split('/', $filepath);
   $filename = $filepath[$#filepath];

   $mode_lis = 0;
   $mode_dsc = 0;

   $pkg_name = "";
   $tar_size = 0;
   $tgz_size = 0;
   $pkg_loca = "";
   $pkg_desc = "";

   open ( INP, "< $filepath" );
   while (<INP>) {
      chop;
      if ($mode_lis) {				# FILE LIST
         if ( !/\/$/ ) {
            print "$filename\t$_\n" if (!/\/$/);

	    &_db_insert_lis unless ($DEBUG);

	 }
      } elsif ($mode_dsc) {		# パッケージの内容
         if ( /^ファイルリスト:/ || /^FILE LIST:/ ) {  # (内容記述の次は FILE LIST)
	    $mode_lis = 1;
	    $mode_dsc = 0;
	    print "$pkg_name, $tar_size, $tgz_size, $pkg_loca\n";
	    print "$pkg_desc\n";
	 } else {			# (内容記述を登録する書式にする)
            $desc = $_;
	    $desc =~ s/^\S+:\s*//;	# 字下げを除く
	    $desc =~ s/\'/\\\'/g;	# シングルクォートをエスケイプ
	    $desc =~ s/\"/\\\"/g;	# ダブルクォートをエスケイプ
	    $pkg_desc .= "$desc\n";
	 }
      } else {
         $fld = $_;
         $fld =~ s/^\D+:\s*//;		# フィールド名と区切りを除く
         if ( /^パッケージ名:/ || /^PACKAGE NAME:/ ) {$pkg_name = $fld;}
         if ( /^圧縮時のパッケージのサイズ:/ || /^COMPRESSED PACKAGE SIZE:/ ) {
	    $fld =~ s/\D//g;		# 数字だけ取り出す
	    $tgz_size = $fld;
	 }
         if ( /^非圧縮時のパッケージのサイズ:/ || /^UNCOMPRESSED PACKAGE SIZE:/ ) {
	    $fld =~ s/\D//g;		# 数字だけ取り出す
	    $tar_size = $fld;
	 }
         if ( /^パッケージの所在:/ || /^PACKAGE LOCATION:/ ) {$pkg_loca = $fld;}
         if ( /^パッケージの内容:/ || /^PACKAGE DESCRIPTION:/ ) {
	    $mode_dsc = 1;
	    $pkg_desc = "";
	 }
         if ( /^ファイルリスト:/ || /^FILE LIST:/ ) { $mode_lis = 1; }	# (パッケージの内容が無いとき)
      }
   }
   close INP;

   &_db_insert_tab unless ($DEBUG);

}

sub _db_conn {
  $conn = Pg::connectdb("dbname=$DBNAME");
  if ($conn->status ne PGRES_CONNECTION_OK) {
     print "_db_conn: ". $conn->errorMessage . " \n";
     &_db_cre_pkg;
     &_db_conn;
     &_db_init_pkg;
  }
}

#
# create database package;
#
sub _db_cre_pkg {
  $conn = Pg::connectdb("dbname=template1");
  if ($conn->status ne PGRES_CONNECTION_OK) {
     print "_db_cre_pkg: ". $conn->errorMessage . " \n";
     exit;
  }
  $result = $conn->exec( "CREATE DATABASE $DBNAME" );
  if ( $result->resultStatus ne PGRES_COMMAND_OK) {
     print "CREATE DATABASE pkgtab:". $conn->errorMessage . "\n";
     print "$cmd\n" if $DEBUG;
     exit
  }

}

#
# -i オプションで、以下の SQL を実行する。
#
# create table pkgtab (
# 	pkgname	text,
# 	pkgsize	int4,
# 	pressize	int4,
# 	location	text,
# 	description	text
# );
# create table pkglis (
# 	pkgname	text,
# 	fpath	text
# );
# create index pkglis_pkgname_idx on pkglis using btree ( pkgname );
# create index pkglis_fpath_idx on pkglis using btree ( fpath );
#
sub _db_init_pkg {

  $result = $conn->exec( "DROP TABLE pkgtab" );
  $cmd = "CREATE TABLE pkgtab ("
 	."pkgname	text,"
 	."pkgsize	int4,"
 	."pressize	int4,"
 	."location	text,"
 	."description	text)";
  $result = $conn->exec( $cmd );
  if ( $result->resultStatus ne PGRES_COMMAND_OK) {
     print "CREATE TABLE pkgtab:". $conn->errorMessage . "\n";
     print "$cmd\n" if $DEBUG;
     exit
  }


  $result = $conn->exec( "DROP TABLE pkglis" );
  $cmd = "CREATE TABLE pkglis ("
	."pkgname	text,"
	."fpath	text)";
  $result = $conn->exec( $cmd );
  if ( $result->resultStatus ne PGRES_COMMAND_OK) {
     print "CREATE TABLE pkglis:". $conn->errorMessage . "\n";
     print "$cmd\n" if $DEBUG;
     exit
  }


  $cmd = "CREATE INDEX pkglis_pkgname_ind ON pkglis USING btree ( pkgname )";
  $result = $conn->exec( $cmd );
  if ( $result->resultStatus ne PGRES_COMMAND_OK) {
     print "CREATE INDEX pkglis_pkgname_ind:". $conn->errorMessage . "\n";
     print "$cmd\n" if $DEBUG;
     exit
  }

  $cmd = "CREATE INDEX pkglis_fpath_ind ON pkglis USING btree ( fpath )";
  $result = $conn->exec( $cmd );
  if ( $result->resultStatus ne PGRES_COMMAND_OK) {
     print "CREATE INDEX pkglis_fpath_ind:". $conn->errorMessage . "\n";
     print "$cmd\n" if $DEBUG;
     exit
  }
}


sub _db_insert_lis {
	    $cmd = "INSERT INTO pkglis VALUES "
      	         ."('$filename', '$_')";
	    $result = $conn->exec($cmd);
	    if ( $result->resultStatus ne PGRES_COMMAND_OK) {
	       print "INSERT INTO pkglis:".$conn->errorMessage."\n";
	       print "$cmd\n" if $DEBUG;
	       exit;
	    }
}


sub _db_insert_tab {
   $cmd = "INSERT INTO pkgtab VALUES "
        ."('$pkg_name', $tar_size, $tgz_size, '$pkg_loca', '$pkg_desc')";
   $result = $conn->exec($cmd);
   if ( $result->resultStatus ne PGRES_COMMAND_OK) {
      print "INSERT INTO pkgtab:".$conn->errorMessage."\n";
      print "$cmd\n" if $DEBUG;
      exit;
   }
}
