#!/usr/bin/perl -w

=head1 NAME

dh_installzopeinstance - install a zope instance into package build directories

=cut

use strict;
use Debian::Debhelper::Dh_Lib;

=head1 SYNOPSIS

B<dh_installzopeinstance> [S<I<debhelper options>>] [B<-n>] [S<I<instance name>>]

=head1 DESCRIPTION

dh_installzopeinstance is a debhelper program that is responsible for installing
zope instances into package build directories.

The argument is interpreted as zope instance and will be created within the 
first package dh_installzopeinstance is told to act on. By default, this is
the first binary package in debian/control, but if you use B<-p>, B<-i>,
or B<-a> flags, it will be the first package specified by those flags.

dh_installzopeinstance automatically install debian/dzinstance if it exists. 
If dh_installzopeinstance is acting on multiple packages, debian/dzinstance file will 
be installed into the first package. Use debian/package.dzinstance for 
different binary packages.

The substitution variable zope:Depends is replaced by a list of the available
zope versions.

=head1 OPTIONS

=over 4

=item B<-n>, B<--noscripts>

Do not modify postinst/prerm scripts.

=item I<instance name>

This parameter will be considered as an instance name which will 
be installed into the first package acted on.

=back

=head1 EXAMPLES

This is an example of a debian/package.dzinstance file:

  Package: plone-site
  ZopeVersion: 2.9
  Name: plone-site
  Addon-Mode: manual
  Addon-Technique: tree-linked
  Restart-Policy: end
  Products: CMFPlone
  Skeleton: /usr/lib/zope2.9/skel-with-magic

The Products field specify a list of comma separated products that will
be automatically installed into the instance. Obviously, it has no sense
if the Addon-Mode field contains 'all'.
The optional Skeleton field specifies a path which is used as skeleton for
the new zope instance.

=head1 NOTES

Note that this command is not idempotent. "dh_clean B<-k>" should be called
between invocations of this command. Otherwise, it may cause multiple
instances of the same text to be added to maintainer scripts.

=cut

init();

sub read_dzfile {
	my $fn = shift;
	my %fields=();
	open (DZ, "debian/$fn") || error("cannot read debian/$fn: $!\n");
	while (<DZ>) {
		chomp;
		s/\s+$//;
		if (/^([^:]+):\s*(.*)/) {
			$fields{$1} = $2;
		}
	}
	close DZ;
	return %fields;
}

sub write_dzfile {
	my ($fn, %fields) = @_;
	my ($out) = "";
	open (DZ, ">$fn") || error("cannot write $fn: $!\n");
	foreach (sort keys %fields) {
		$out = "$_: $fields{$_}\n" . $out;
	}
	print DZ $out;
	close DZ;
}

sub addzopesubstvars {
	my ($package, %fields) = @_;
	addsubstvar($package, "zope:Depends", "zope-common (>= 0.5.49), zope" . $fields{'ZopeVersion'});
}

my @autoscripts = ('config', 'preinst', 'postinst', 'prerm', 'postrm');

foreach my $package (@{$dh{DOPACKAGES}}) {
	next if is_udeb($package);
	
	my $tmp=tmpdir($package);

	my $dzinstancefile=pkgfile($package,"dzinstance");
	my $archdir=package_arch($package) eq 'all' ? 'share' : 'lib';

	# needed to get $dh{VERSION}
	my $isnative = isnative($package);

	my $addon_version;

	my @instances;

	if ($package eq $dh{FIRSTPACKAGE} && @ARGV) {
		push @instances, @ARGV;
	}

	if ($dh{V_FLAG}) {
		$addon_version = $dh{V_FLAG};
	}

	# Handle dzinstance files. There are two filename formats,
	# the usual plus an extended format (debian/package.*).
	my @dzin_files;
	
	opendir(DEB,"debian/") || error("can't read debian directory: $!");
	# If this is the main package, we need to handle unprefixed filenames.
	# For all packages, we must support both the usual filename format plus
	# that format with a period an something appended.
	my $regexp="\Q$package\E\.";
	if ($package eq $dh{MAINPACKAGE}) {
		$regexp="(|$regexp)";
	}
	foreach my $fn (grep {/^${regexp}dzinstance(\..*)?$/} readdir(DEB)) {
		# .EX are example files, generated by eg, dh-make
		next if $fn=~/\.EX$/;
		push @dzin_files, $fn;
	}
	closedir(DEB);

	if (@instances == 0 || @dzin_files == 0) {
		error("missing instance name or dzinstance files");
	}
	if (@instances > 1) {
		error("unable to handle multiple instances");
	}

	if (@instances) {
		my %dzinstance;
		if (@dzin_files) {
			%dzinstance = read_dzfile(shift @dzin_files);
		}
		else {
			$dzinstance{'Package'} = $package;
		}

		$dzinstance{'Version'} = $dh{VERSION};
		foreach my $instance (@instances) {
			if (!$dzinstance{'Name'}) {
				error("you have to specify the instance name in the dzinstance file");
			}
			elsif (!$dzinstance{'ZopeVersion'}) {
				error("you have to specify the zope version in the dzinstance file");
			}

			$dzinstance{'Addon-Mode'} = 'manual' if (!$dzinstance{'Addon-Mode'});
			$dzinstance{'Addon-Technique'} = 'tree-linked' if (!$dzinstance{'Addon-Technique'});
			$dzinstance{'RestartPolicy'} = 'end' if (!$dzinstance{'RestartPolicy'});
			if ($dzinstance{'Products'}) {
				$dzinstance{'Products'} =~ s/,//g;
			} else {
				$dzinstance{'Products'} = '';
			}
			$dzinstance{'Port'} = '9673' if (!$dzinstance{'Port'});
			if ($dzinstance{'Skeleton'}) {
				$dzinstance{'Skeleton'} = '--skelsrc ' . $dzinstance{'Skeleton'};
			} else {
				$dzinstance{'Skeleton'} = '';
			}
			
			if (!$dzinstance{'Zope-Database'}) {
				$dzinstance{'Zope-Database'} = 'ZODB';
			}
			if (!$dzinstance{'Zope-User'}) {
				$dzinstance{'Zope-User'} = 'zope:zope';
			}

			if (!$dh{NOSCRIPTS}) {
				foreach my $script (@autoscripts) {
					autoscript($package,$script,"$script-dzinstance",
						   "s,#DZ-PKG#,$package,;" .
						   "s,#DZ-PORT#,$dzinstance{'Port'},;" .
						   "s,#DZ-ZVER#,$dzinstance{'ZopeVersion'},;" .
						   "s,#DZ-INSTANCE#,$dzinstance{'Name'},;" .
						   "s,#DZ-ADDON-MODE#,$dzinstance{'Addon-Mode'},;" .
						   "s,#DZ-ADDON-TECHNIQUE#,$dzinstance{'Addon-Technique'},;" .
						   "s,#DZ-RESTARTPOLICY#,$dzinstance{'RestartPolicy'},;" .
						   "s,#DZ-PRODUCTS#,$dzinstance{'Products'},;" .
						   "s,#DZ-SKELETON#,$dzinstance{'Skeleton'},;".
						   "s,#DZ-DATABASE#,$dzinstance{'Zope-Database'},;".
						   "s,#DZ-USER#,$dzinstance{'Zope-User'},;",
						  );
				}
			}
			addzopesubstvars($package, %dzinstance);
		}
	}
}

=head1 SEE ALSO

L<debhelper(7)>

This program is a part of zope-debhelper.

=head1 AUTHOR

Fabio Tranchitella <kobold@debian.org>
Bernd Zeimetz <bernd@bzed.de>

=cut
