#!/usr/local/bin/perl

# Copyright (c) 2012 Matthew Seaman. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
#    1.  Redistributions of source code must retain the above
#        copyright notice, this list of conditions and the following
#        disclaimer.
#
#    2.  Redistributions in binary form must reproduce the above
#        copyright notice, this list of conditions and the following
#        disclaimer in the documentation and/or other materials
#        provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.

# @(#) $Id$
#
# Process the cached 'make describe' output to produce a tree of
# README.html files.

use strict;
use warnings;

use FreeBSD::Portindex::Config qw(%Config read_config);
use FreeBSD::Portindex::Tree;

$0 =~ s@.*/@@;    # Script name for error messages

# Read three template files from $Config{ReadmeTemplatesDir} (
# ${PORTSDIR}/Templates by default) -- expect to find README.top,
# README.category, README.port
sub read_templates ($)
{
    my $templates_dir = shift;
    my $templates     = {};

    local $/ = undef;    # Slurp whole file mode

    for my $template (qw( top category port )) {
        my $template_file = "$templates_dir/README.$template";
        open( TEMPLATE, "<$template_file" )
          or die "$0: Unable to read \"$template_file\" -- $!\n";
        $templates->{$template} = <TEMPLATE>;
        close TEMPLATE;
    }
    return $templates;
}

MAIN:
{
    my $tree;
    my $templates;
    my $counter = 1;

    read_config('portindex');

    $tree = FreeBSD::Portindex::Tree->new(
        -Env           => { -Home => $Config{CacheDir}, },
        -CacheFilename => $Config{CacheFilename},
    );

    # Read the template files

    $templates = read_templates( $Config{ReadmeTemplatesDir} );

    # Unfreeze the cached ports data

    $tree->springtime();

    $tree->accumulate_dependencies();

    print STDERR "Generating README.html files: ";
    $tree->make_readmes( $Config{ReadmeDir}, '', $templates, 1, \$counter );
    print STDERR "<$counter>\n" if $Config{Verbose};
}

__END__

=head1 NAME

make-readmes -- generate README.html files from cached data

=head1 SYNOPSIS

B<make-readmes> [B<-hvqw>] [B<-c> F<dir>] [B<-t> F<directory>] [B<-d> F<directory>]

=head1 DESCRIPTION

B<make-readmes> processes the cached port description data into
F<README.html> files, populating a directory structure paralleling the
ports directory tree.  The cache contains a record of the one-line
description of all ports generated by C<make describe>, indexed by the
port origin directory.  It also contains a record of which Makefiles
are included by the port's Makefile, but that information is not used
by B<make-readmes>.

B<make-readmes> follows the C<SUBDIR> variable settings from the top
level F</usr/ports/Makefile> via the per-category makefiles to
individual ports, creating the corresponding directory heirarchy as it
goes, and editing data read from the cache into the F<README.html>
template files it outputs.

=head2 Configuration Files

B<make-readmes> shares configuration files with B<portindex>,
B<cache-init>, B<cache-update> and B<find-updated>.  Any configuration
settings are taken from the following locations, where the later items
on this list override the earlier:

=over 8

=item *

Built-in settings from the B<FreeBSD::Portindex::Config> perl module.

=item *

The system wide configuration file F</usr/local/etc/portindex.cfg>

=item *

The per-user configuration file F<${HOME}/.portindexrc> (ignored if
the program is being run by the superuser)

=item *

The local configuration file, found in the current working directory
of the B<cache-init> process F<./.portindexrc> (ignored if the program
is being run by the superuser)

=item *

The program command line.

=back

All of the configuration files are optional.  A summary of the
resultant configuration options including the effect of any command
line settings is printed as part of the help text when B<portindex> is
invoked with the C<-h> option.

=head1 OPTIONS

=over 8

=item B<-h>

=item B<--help>

Print a brief usage message and a summary of the configuration
settings after command line processing and then exit.

=item B<-v>

=item B<--verbose>

Turn on verbose output printed to C<STDERR>.  This is the default.

=item B<-w>

=item B<--warnings>

Turn on warning messages about duplicate ports and ports unreferenced
from their catergory F<Makefile>.  Default: off.

=item B<-nowarnings>

Turn off warning messages.  This is the default.

=item B<-q>

=item B<--quiet>

=item B<--noverbose>

Turn off verbose output to C<STDERR>.  Using both the B<-v> amd B<-q>
options together does not make any sense, but neither does it generate
an error.  The last mentioned of the two options will prevail.

=item B<-c> F<dir>

=item B<--cache-dir>=F<dir>

The location of the B<portindex> data cache, by default
F</var/db/portindex>.

=item B<-C> F<file>

=item B<--cache-file>=F<file>

Berkeley DB Btree file containing the cached and post-processed values
of a number of C<make> variables for all of the ports in the tree.
This file name will be relative to the cache directory (B<-c> option
above) unless an absolute path is given.  Defaults to
F<portindex-cache.db>.

=item B<-t> F<directory>

=item B<--template-dir>=F<directory>

Directory containing the templates for the F<README.html> files for
the top of the tree, for each category and for each different port.
Default: C<$PORTSDIR/Templates>

=item B<-d> F<directory>

=item B<--output-directory>=F<directory>

Top-level directory beneath which to create a copy of the ports
directory tree containing the generated F<README.html> files.  Will
create the top-level directory so long as the directory above that
already exists.  Any pre-existing F<README.html> files will be
overwritten.  Default: F<./ports> in the current working directory.

=back

=head1 FILES

=over 16

=item F</usr/ports>

The default ports directory.

=item F</var/db/portindex>

The location of the data cache.

=item F<portindex-cache.db>

Btree file containing cached C<make describe> output.

=item F<__db.001>, F<__db.002>, F<__db.003>

Files used as part of the internal workings of BerkeleyDB, for memory
pool management and DB locking.  Will be recreated automatically if
deleted.

=item F<portindex-timestamp>

This file contains the last time and date that the cache was updated
or modified.

=item F</usr/local/etc/portindex.cfg>

System-wide configuration file.

=item F<${HOME}/.portindexrc>

Per-user configuration file

=item F<./.portindexrc>

Local configuration file

=back

=head1 SEE ALSO

L<portindex>, L<cache-init(1)>, L<cache-update(1)>,
L<find-updated(1)>, L<cvsup(1)>, L<ports(7)>

=head1 BUGS

Unless the C<--crunch-whitespace> option is given, B<make-readmes>
extracts the C<COMMENT> lines from the C<make describe> output exactly
as shown.  C<make readmes> collapses multiple spaces to single.

=cut

#
# That's All Folks!
#
