#!/usr/bin/perl -w

#
# update_modules
# $Id$
#
# Copyright (C) 2007 by John Heidemann <johnh@isi.edu>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
# 
# 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.
#


=head1 NAME

update_modules - update the list of fsdb modules in the three places they're kept

=head1 SYNOPSIS

update_modules

=head1 DESCRIPTION

The list of fsdb modules needs to be kept in several places.
This program updates all of those from the master list in
C<Makefile.PL>.

This program is only needed to be run by developers of
new modules.  It updates source files that are hopefully
distributed with complete information.

=cut

use strict;
use Pod::Usage;
use Getopt::Long;

Getopt::Long::Configure ("bundling");
pod2usage(2) if ($#ARGV >= 0 && $ARGV[0] eq '-?');
#my(@orig_argv) = @ARGV;
my($prog) = $0;
my $debug = undef;
my $verbose = undef;
&GetOptions(
 	'help|?' => sub { pod2usage(1); },
	'man' => sub { pod2usage(-verbose => 2); },
	'd|debug+' => \$debug,   
        'v|verbose+' => \$verbose) or pod2usage(2);

#
# get the info
#
my $code = '';
my $in_code = undef;
open(MFPL, "< Makefile.PL") or die "cannot open Makefile.PL\n";
while (<MFPL>) {
    if (!$in_code) {
	if (/BEGIN MODULE LIST/) {
	    $in_code = 1;
	};
    } else {
	if ($in_code && /END MODULE LIST/) {
	    $in_code = undef;
	} else {
	    s/^my //;   # we declare the my's below so -w works
	    $code .= $_;
	};
    };
};
close MFPL;

# get the definitions
# pick up these in code:
my @modularized_db_programs;
my @modularized_db_converters;
my @modularized_db_non_programs;
my @helper_db_programs;
my @standalone_db_programs;
my @converters;
my @backwards_db_programs;
eval $code;
$@ && die "internal eval error: $@.\n";

#
# transaction support
#
my $active_pn = undef;
sub prepare_transaction {
    my($pn) = @_;
    die "ongoing transaction on $active_pn, cannot start $pn\n"
	if (defined($active_pn));
    open(OLD, "<$pn") or die "cannot read $pn\n";
    open(NEW, ">$pn+") or die "cannot write $pn\n";
    $active_pn = $pn;
}
sub commit_transaction {
    close NEW;
    close OLD;
    my $pn = $active_pn;
    $pn or die "no active transaction\n";
    rename $pn, "$pn~" or die "cannot rename $pn to $pn~\n";
    if (!rename ("$pn+", $pn)) {
	# abort
	rename "$pn~", $pn;
	die "cannot rename $pn+ to $pn\n";
    };
    $active_pn = undef;
}

#
# now go update things
#

#
# bin/.gitignore
#
prepare_transaction("bin/.gitignore");
print NEW "# This file is managed by update_modules; DO NOT EDIT DIRECTLY.\n";
print NEW "*-\n";
foreach (sort (@modularized_db_programs, @modularized_db_converters)) {
    print NEW "$_\n";
};
commit_transaction;

#
# MANIFEST.SKIP
#
prepare_transaction("MANIFEST.SKIP");
my $in_ms_section = undef;
while (<OLD>) {
    if ($in_ms_section) {
	$in_ms_section = undef if (/END AUTOGENERATED SECTION/);
	# fall through to print this line in next if
    };
    if (!$in_ms_section) {
	print NEW $_;
	if (/BEGIN AUTOGENERATED SECTION/) {
	    $in_ms_section = 1;
	    print NEW "# This next section is managed by update_modules.  DO NOT EDIT DIRECTLY.\n";
	    foreach (sort(@modularized_db_programs, @modularized_db_converters)) {
		print NEW "bin/$_\$\n";
	    };
	};
    };
};
commit_transaction;

#
# dbpipeline.pm
#
prepare_transaction("lib/Fsdb/Filter/dbpipeline.pm");
my $in_dbp_section = undef;
while (<OLD>) {
    if ($in_dbp_section) {
	$in_dbp_section = undef if (/END AUTOGENERATED \S+ SECTION/);
	# fall through to print this line in next if
    };
    if (!$in_dbp_section) {
	print NEW $_;
	if (/BEGIN AUTOGENERATED VARIABLE SECTION/) {
	    $in_dbp_section = 1;
	    print NEW "# This next section is managed by update_modules.  DO NOT EDIT DIRECTLY.\n";
	    print NEW "our \@modularized_db_programs = qw(" .
		join ("\n\t", '', @modularized_db_programs) .
		"\n);\n";
	    print NEW "our \@modularized_db_converters = qw(" .
		join ("\n\t", '', @modularized_db_converters) .
		"\n);\n";
	    print NEW "our \@modularized_db_non_programs = qw(" .
		join ("\n\t", '', @modularized_db_non_programs) .
		"\n);\n";
	};
	if (/BEGIN AUTOGENERATED DOCUMENTATION SECTION/) {
	    $in_dbp_section = 1;
	    print NEW "\n=over\n\n";
	    foreach (sort(@modularized_db_programs, @modularized_db_converters)) {
		print NEW "=item L<$_(1)>\n\n";
	    };
	    print NEW "=back\n\n=for comment\n";
	};
    };
};
commit_transaction;

exit 0;


