#!/usr/bin/perl
use strict;
use warnings;
use Debian::Debhelper::Dh_Lib;
use Debian::Debhelper::Dh_components;
use Readonly;
use Cwd;
Readonly my $COMMA_RE => qr/,/;

Readonly my $CWD => getcwd;

init(options=>{
    "purge!"=>\$dh{PURGE},
    "components=s" => \$dh{COMPONENTS},
    "build_stages=s" => \$dh{BUILD_STAGES},
    "rules_locations=s" => \$dh{RULES_LOCATIONS},
});

# Work through the packages and components
foreach my $package (getpackages()) {

    my $dir = find_components_dir($package);
    next if !$dir;

    my %args = (dir=>$dir, package=>$package);
    if ($dh{BUILD_STAGES}) {
        $args{build_stages} = [split $COMMA_RE, $dh{BUILD_STAGES}];
    }
    if ($dh{COMPONENTS}) {
        $args{components} = [split $COMMA_RE, $dh{COMPONENTS}];
    }
    if ($dh{RULE_LOCATIONS}) {
        $args{rules_locations} = [split $COMMA_RE, $dh{RULES_LOCATIONS}];
    }

    my $component_data = Debian::Debhelper::Dh_components->new(%args);

    foreach my $c ($component_data->components) {

        foreach my $bs ($component_data->build_stages) {
            my $script = $component_data->script($c, $bs);
            my $command = "CURDIR=$CWD PACKAGE=$package DH_COMPONENT=$c $script";
            doit($command);
        }
    }

    my $copyright_file = "$CWD/debian/$package.copyright";
    if (not -f $copyright_file) {
        verbose_print("Building $copyright_file");
        $component_data->build_copyright($copyright_file);
    }

    foreach my $dependency ($component_data->substvars) {
        my $var = "$dependency->{component}:$dependency->{substvar}";
        my $verrel =
            $dependency->{rel} ? "($dependency->{rel} $dependency->{ver})" : "";
        my $deppackage = $dependency->{deppackage};
        addsubstvar($package, $var, $deppackage, $verrel);
    }

}

# Clean up the old components directory
if ($dh{PURGE} or not defined $dh{PURGE}) {
    doit("rm -rf COMPONENTS");
}

exit(0);

sub find_components_dir {
    my $package = shift;

    my $dir = "debian/$package.components";
    return $dir if -d $dir;

    $dir = "debian/components";
    return $dir if -d $dir && $package eq $dh{FIRSTPACKAGE};

    return;
}

=head1 NAME

dh_components - build additional components

=head1 SYNOPSIS

B<dh_components> [S<I<debhelper options>>] [B<--components> I<comp>[,I<comp>,...]]  [B<--build_stages> I<stage>[,I<stage>,...]]  [B<--rules_locations> I<dir>[,I<dir>,...]] 

=head1 DESCRIPTION

C<dh_components> is a debhelper program that is responsible for handling
additional components that come from separate upstream sources. The aim
is to turn each component into a "mini Debian package". It takes the
following actions:

=over 

=item Run through the various build stages for each package and component.

=item Optionally stitch together the Debian copyright files.

=item Generate the C<substvar> file from the component control files.

=item Purge the components working directory (unless the I<--no-purge> option
is set).

=back 

=head1 FILES

=over 4

=item debian/I<package>.components

=item debian/components

These directories contain all the component data for a given binary package.
The second form only works for the first binary in a source package and is
overridden by the equivalent first form.

=item debian/[I<package>.]components/I<component>

This is a directory that contains the files specific to that component.
In some ways it is like a cut-down version of the debian directory.

=item debian/[I<package>.]components/I<component>

=item debian/[I<package>.]components/

=item /usr/share/pkg-components/build_stages

These are the default locations of the build stage scripts in the order of 
precedence with highest first. These can be overridden using the
C<--rules_locations>.

=item debian/[I<package>.]components/copyright.in

This file provides the DEP-5 copyright stanzas for the package but without
any of the component stanzas. It forms the basis for the I<package>.copyright
file.

=item debian/[I<package>.]components/I<component>/copyright

This file provides a DEP-5 fragment of the Debian copyright for this component.
It will be merged into the main copyright file at I<package>.copyright. Any
duplicate C<License> clauses will be shown only once.

=item debian/[I<package>.]components/I<component>/control

If present this file should look like a Debian control file for the component.
The package name of the binary stanza should match the component name.
The C<Depends>, C<Recommends>, C<Suggests>, C<Enhances>, C<Replaces>,
C<Pre-Depends>, C<Conflicts>, C<Breaks> fields are read and turned into
substitution variables. So if you have a component C<X> which declares a
Depends on C<Y>, then a substvar variable C<X:Depends> will be created with
the value C<Y>.
The source package stanza is ignored but can be used to document which
build dependencies are due to the component.

=back

=head1 OPTIONS

=over 4

=item B<--build_stages b1,b2,...>

If this option is listed the sequence described will be used instead
of the normal one.

=item B<--components c1,c2,...>

If this option is listed only those components listed will be considered.

=item B<--rules_locations r1,r2,...>

If this option is listed the specified locations will be used instead
of the default ones. One can use C<%> to mean the component. Thus to
explicitly specify the default one would set:

    --rules_locations debian/components/%,debian/components,/usr/share/pkg-components/build_stages

=back

=head1 CONFIGURATION

To enable this functionality it is necessary to pass the argument
C<--with components> to the C<dh> programa in the C<debian/rules>
file.

=head1 SEE ALSO

L<debhelper(1)>

This program is used with debhelper. 

L<quilt(1)>

=head1 AUTHOR

Nicholas Bamber <nicholas@periapt.co.uk>

=cut
