#!/usr/bin/env perl
# $Id$
# Public domain. Originally written 2026, Karl Berry.
# Dump the TeX Catalogue in tlpdb format. Run nightly via tl-update-auto.

our ($vc_id, $Master);

BEGIN {
  $vc_id = '$Id$';
  $^W = 1;
  chomp ($mydir = `dirname $0`);
  unshift (@INC, "$mydir/..");
  chomp ($Master = `cd $::mydir/../.. && pwd`);
}

use strict; use warnings;

use TeXLive::TLPDB;
use TeXLive::TLPOBJ;
use TeXLive::TLUtils;
use TeXLive::TeXCatalogue;
use Getopt::Long;
use Pod::Usage;

my $opt_catalogue = "/home/texlive/catalogue";
my $opt_catalogue_dump = "";
my $opt_output = 0;
my $opt_version = 0;
my $opt_help = 0;

TeXLive::TLUtils::process_logging_options();
GetOptions(
  "catalogue=s"      => \$opt_catalogue,
  "catalogue-dump=s" => \$opt_catalogue_dump,
  "output=s"         => \$opt_output,
  "version"	     => \$opt_version,
  "help|?"           => \$opt_help,
) or pod2usage(1);

pod2usage(-exitstatus => 0, -verbose => 2) if $opt_help;
if ($opt_version) { print "$vc_id\n"; exit 0; } 

my $prg = TeXLive::TLUtils::basename ($0);

exit (&main ());

sub main {
  my $texcat = &read_catalogue ($opt_catalogue);
  my $tlpdb = TeXLive::TLPDB->new ("root" => $Master);
  for my $pkgname ($tlpdb->list_packages) {
    my $tlpobj = $tlpdb->get_package ($pkgname);
    $tlpobj->update_from_catalogue ($texcat);
    $tlpobj->writeout (*STDOUT, 1); # the 1 means write only catalogue fields
    print "\n";
  }
  return 0;
}

# Read the TeX Catalogue under CATDIR, or from $opt_catalogue_dir
# if that exists.
#
sub read_catalogue {
  my ($catdir) = @_;
  my $texcat = undef;
  if (-s $opt_catalogue_dump) { # if dump file exists, use it.
    &info ("$prg: reading TeX Catalogue dump $opt_catalogue_dump ...\n");
    require $opt_catalogue_dump;
    $::texcat = $::texcat; # avoid "used only once" warning
    $texcat = $::texcat;
    
  } else {
    &info ("$prg: reading TeX Catalogue $catdir ...\n");
    $texcat = TeXLive::TeXCatalogue->new ("location" => $catdir);
    if ($opt_catalogue_dump) {
      # Way to dump the catalogue and then use it instead of reparsing,
      # to save time when developing/debugging.
      # Maybe someday have the energy to merge this with the same dumping
      # code in TLUtils as a common function.
      require Data::Dumper;
      $Data::Dumper::Indent = 1;
      $Data::Dumper::Sortkeys = 1;  # stable output
      $Data::Dumper::Purity = 1; # recursive structures must be safe
      &info ("$prg: dumping TeX Catalogue to $opt_catalogue_dump ...\n");
      my $catdump = ">$opt_catalogue_dump";
      open (my $fh, $catdump) || die "open($catdump) failed: $!\n";
      print $fh Data::Dumper->Dump ([$texcat], [qw(::texcat)]);
      close ($fh) || die "close($catdump) failed: $!\n";
    }
  }
  return $texcat;
}
__END__

=head1 NAME

tl-dump-catalogue-as-tlpdb - dump a TeX Live database with TeX Catalogue info

=head1 SYNOPSIS

tl-dump-catalogue-as-tlpdb [OPTION]...

=head1 OPTIONS

=over 4

=item B<--catalogue> I<Catalogue_dir>

The I<Catalogue_file> must point to a valid TeX Catalogue checkout, with
subdirectory C</entries>; the default is C</home/texlive/catalogue>. If
the directory is readable, the generated tlpobj files will contain
information gathered from the TeX Catalogue. To disable this, specify a
nonexistent filename, e.g., C<--catalogue=/nonesuch>.

=item B<--catalogue-dump> I<file>

This is for debugging and development. If specified, and I<file> is
nonempty, it is <C>require</C>d, instead of reading the XML files from
I<Catalogue_dir> from C<--catalogue>. If I<file> is empty or does not
exist, the XML tree is read, and then dumped (with L<Data::Dumper>) to
I<file>.

The idea is to specify this, the dump gets written, and then subsequent
runs will use it, which is much faster than reading the XML. However,
you must not forget to delete the file when done, since there is no
check for staleness.

Also, don't use this if you are working on the Catalogue reading
routines (L<TeXLive::TeXCatalogue>), since they won't get invoked at all
if the dump is read.

=item B<--help>

Display this documentation and exit.

=item B<--version>

Display version information and exit.

=back

The standard options C<-q>, C<-v>, and C<-logfile>=I<file> are also
accepted; see the C<process_logging_options> function in
L<TeXLive::TLUtils> for details.

=head1 DESCRIPTION

C<tl-dump-catalogue-as-tlpdb> converts a TeX Live directory hierarchy,
along with a TeX Catalogue tree, into a TeX Live package database
(tlpdb) containing only the Catalogue information, which is ultimately
maintained by CTAN.

The idea is to separate the Catalogue information from the main tlpdb,
so that when the Catalogue information changes, the TL package does not
need to be updated, that is, re-downloaded in its entirety.  CTAN should
be free to make mass updates of the Catalogue information, notably
the topic lists, without that causing mass downloads in TL installations.

So this is run from cron (via the C<tl-update-auto> script) to create a
Catalogue-only tlpdb that is distributed as part of the
C<texlive-scripts> package. Then C<tlmgr> can read this Catalogue tlpdb
when the info is actually needed (C<tlmgr info> and C<tlmgr search>),
but Catalogue changes won't affect the TL package revision numbers and updates.

=head1 SEE ALSO

The modules in C<Master/tlpkg/TeXLive/>, especially
L<TeXLive::TeXCatalogue>, and the other scripts in C<Master/tlpg/bin/>
(especially C<tl-update-tlpdb>), the documentation in
C<Master/tlpkg/doc/>, etc.

=head1 AUTHORS AND COPYRIGHT

This script and its documentation were written for the TeX Live
distribution (L<https://tug.org/texlive>), originally in July 2026, and
both are public domain.

=cut

### Local Variables:
### perl-indent-level: 2
### tab-width: 2
### indent-tabs-mode: nil
### End:
# vim:set tabstop=2 expandtab: #
