Blame docs/doc-install.pl

Packit 908522
package main;
Packit 908522
Packit 908522
# Copyright (c) 2009  Openismus GmbH  <http://www.openismus.com/>
Packit 908522
#
Packit 908522
# This file is part of mm-common.
Packit 908522
#
Packit 908522
# mm-common is free software: you can redistribute it and/or modify
Packit 908522
# it under the terms of the GNU General Public License as published
Packit 908522
# by the Free Software Foundation, either version 2 of the License,
Packit 908522
# or (at your option) any later version.
Packit 908522
#
Packit 908522
# mm-common is distributed in the hope that it will be useful,
Packit 908522
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 908522
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 908522
# GNU General Public License for more details.
Packit 908522
#
Packit 908522
# You should have received a copy of the GNU General Public License
Packit 908522
# along with mm-common.  If not, see <http://www.gnu.org/licenses/>.
Packit 908522
Packit 908522
use strict;
Packit 908522
use warnings;
Packit 908522
use bytes;
Packit 908522
use File::Glob qw(:glob);
Packit 908522
use File::Spec;
Packit 908522
use Getopt::Long qw(:config no_getopt_compat no_ignore_case require_order bundling);
Packit 908522
Packit 908522
# Globals
Packit 908522
my $message_prefix;
Packit 908522
my %tags_hash;
Packit 908522
my $book_base;
Packit 908522
my $perm_mode;
Packit 908522
my $target_dir;
Packit 908522
my $target_nodir = '';
Packit 908522
my $expand_glob  = '';
Packit 908522
my $verbose      = '';
Packit 908522
Packit 908522
sub path_basename ($)
Packit 908522
{
Packit 908522
  my ($path) = @_;
Packit 908522
  my $basename = File::Spec->splitpath($path);
Packit 908522
Packit 908522
  return $basename;
Packit 908522
}
Packit 908522
Packit 908522
sub exit_help ()
Packit 908522
{
Packit 908522
  my $script_name = path_basename($0) || 'doc-install.pl';
Packit 908522
Packit 908522
  print <<"EOF";
Packit 908522
Usage: perl $script_name [OPTION]... [-T] SOURCE DEST
Packit 908522
  or:  perl $script_name [OPTION]... SOURCE... DIRECTORY
Packit 908522
  or:  perl $script_name [OPTION]... -t DIRECTORY SOURCE...
Packit 908522
Packit 908522
Copy SOURCE to DEST or multiple SOURCE files to the existing DIRECTORY,
Packit 908522
while setting permission modes.  For HTML files, translate references to
Packit 908522
external documentation.
Packit 908522
Packit 908522
Mandatory arguments to long options are mandatory for short options, too.
Packit 908522
      --book-base=BASEPATH          use reference BASEPATH for Devhelp book
Packit 908522
  -l, --tag-base=TAGFILE\@BASEPATH   use BASEPATH for references from TAGFILE
Packit 908522
  -m, --mode=MODE                   override file permission MODE (octal)
Packit 908522
  -t, --target-directory=DIRECTORY  copy all SOURCE arguments into DIRECTORY
Packit 908522
  -T, --no-target-directory         treat DEST as normal file
Packit 908522
      --glob                        expand SOURCE as filename glob pattern
Packit 908522
  -v, --verbose                     enable informational messages
Packit 908522
  -?, --help                        display this help and exit
Packit 908522
EOF
Packit 908522
  exit;
Packit 908522
}
Packit 908522
Packit 908522
sub notice (@)
Packit 908522
{
Packit 908522
  print($message_prefix, @_, "\n") if ($verbose);
Packit 908522
}
Packit 908522
Packit 908522
sub warning (@)
Packit 908522
{
Packit 908522
  print STDERR ($message_prefix, @_, "\n");
Packit 908522
}
Packit 908522
Packit 908522
sub error (@)
Packit 908522
{
Packit 908522
  warning(@_);
Packit 908522
  exit 1;
Packit 908522
}
Packit 908522
Packit 908522
# Copy file to destination while translating references on the fly.
Packit 908522
# Sniff the content for the file type, as it is always read in anyway.
Packit 908522
sub install_file ($$$)
Packit 908522
{
Packit 908522
  my ($in_name, $out_name, $basename) = @_;
Packit 908522
  my ($in, $out, $buf);
Packit 908522
  {
Packit 908522
    local $/; # slurp mode: read entire file into buffer
Packit 908522
Packit 908522
    open($in, '<', $in_name) and binmode($in) and defined($buf = <$in>) and close($in)
Packit 908522
      or error('Failed to read ', $basename, ': ', $!);
Packit 908522
  }
Packit 908522
Packit 908522
  if (%tags_hash and $buf =~ m/\A(?> \s*)(?> (?> <[?!][^<]+ )* )<html[>\s]/sx)
Packit 908522
  {
Packit 908522
    my $count = 0;
Packit 908522
    my $total = $buf =~
Packit 908522
      s!(?<= \s) doxygen="((?> [^:"]+)):((?> [^"]*))" # doxygen="(TAGFILE):(BASEPATH)"
Packit 908522
        (?> \s+) ((?> href|src) =") \2 ((?> [^"]*)")  # (href|src=")BASEPATH(RELPATH")
Packit 908522
       ! $3 . ((exists $tags_hash{$1}) ? (++$count, $tags_hash{$1}) : $2) . $4
Packit 908522
       !egsx;
Packit 908522
    my $change = $total ? "rewrote $count of $total"
Packit 908522
                        : 'no';
Packit 908522
    notice('Translating ', $basename, ' (', $change, ' references)');
Packit 908522
  }
Packit 908522
  elsif (defined($book_base) and $buf =~ m/\A(?> \s*)(?> (?> <[?!][^<]+ )* )
Packit 908522
  {
Packit 908522
    # Substitute new value for attribute "base" of element <book>
Packit 908522
    my $change = $buf =~ s/(<book \s [^<>]*? \b base=") (?> [^"]*) (?= ")/$1$book_base/sx
Packit 908522
                 ? 'rewrote base path'
Packit 908522
                 : 'base path not set';
Packit 908522
    notice('Translating ', $basename, ' (', $change, ')');
Packit 908522
  }
Packit 908522
  else
Packit 908522
  {
Packit 908522
    notice('Copying ', $basename);
Packit 908522
  }
Packit 908522
Packit 908522
  # Avoid inheriting permissions of existing file
Packit 908522
  unlink($out_name);
Packit 908522
Packit 908522
  open($out, '>', $out_name) and binmode($out) and print $out ($buf) and close($out)
Packit 908522
    or error('Failed to write ', $basename, ': ', $!);
Packit 908522
Packit 908522
  chmod($perm_mode, $out_name)
Packit 908522
    or warning('Failed to set ', $basename, ' permissions: ', $!);
Packit 908522
}
Packit 908522
Packit 908522
# Split TAGFILE@BASEPATH argument into key/value pair
Packit 908522
sub split_key_value ($)
Packit 908522
{
Packit 908522
  my ($mapping) = @_;
Packit 908522
  my ($name, $path) = split(m'@', $mapping, 2);
Packit 908522
Packit 908522
  error('Invalid base path mapping: ', $mapping) unless (defined($name) and $name ne '');
Packit 908522
Packit 908522
  if (defined $path)
Packit 908522
  {
Packit 908522
    notice('Using base path ', $path, ' for tag file ', $name);
Packit 908522
    return ($name, $path);
Packit 908522
  }
Packit 908522
  notice('Not changing base path for tag file ', $name);
Packit 908522
  return ();
Packit 908522
}
Packit 908522
Packit 908522
# Define line leader of log messages
Packit 908522
$message_prefix = path_basename($0);
Packit 908522
$message_prefix =~ s/\.[^.]*$//s if (defined $message_prefix);
Packit 908522
$message_prefix = ($message_prefix || 'doc-install') . ': ';
Packit 908522
Packit 908522
# Process command-line options
Packit 908522
{
Packit 908522
  my @tags = ();
Packit 908522
  my $mode = '0644';
Packit 908522
Packit 908522
  GetOptions('book-base=s'           => \$book_base,
Packit 908522
             'tag-base|l=s'          => \@tags,
Packit 908522
             'mode|m=s'              => \$mode,
Packit 908522
             'target-directory|t=s'  => \$target_dir,
Packit 908522
             'no-target-directory|T' => \$target_nodir,
Packit 908522
             'glob'                  => \$expand_glob,
Packit 908522
             'verbose|v'             => \$verbose,
Packit 908522
             'help|?'                => \&exit_help)
Packit 908522
    or exit 2;
Packit 908522
Packit 908522
  error('Invalid permission mode: ', $mode) unless ($mode =~ m/^[0-7]+$/s);
Packit 908522
Packit 908522
  $perm_mode = oct($mode);
Packit 908522
  %tags_hash = map(split_key_value($_), @tags);
Packit 908522
}
Packit 908522
notice('Using base path ', $book_base, ' for Devhelp book') if (defined $book_base);
Packit 908522
Packit 908522
if ($target_nodir)
Packit 908522
{
Packit 908522
  error('Conflicting target directory options') if (defined $target_dir);
Packit 908522
  error('Source and destination filenames expected') unless ($#ARGV == 1);
Packit 908522
  error('Filename globbing requires target directory') if ($expand_glob);
Packit 908522
Packit 908522
  install_file($ARGV[0], $ARGV[1], path_basename($ARGV[1]));
Packit 908522
  exit;
Packit 908522
}
Packit 908522
Packit 908522
unless (defined $target_dir)
Packit 908522
{
Packit 908522
  if (!$expand_glob and $#ARGV == 1)
Packit 908522
  {
Packit 908522
    my $basename = path_basename($ARGV[1]);
Packit 908522
Packit 908522
    if (defined($basename) and $basename ne '')
Packit 908522
    {
Packit 908522
      install_file($ARGV[0], $ARGV[1], $basename);
Packit 908522
      exit;
Packit 908522
    }
Packit 908522
  }
Packit 908522
  $target_dir = pop(@ARGV);
Packit 908522
}
Packit 908522
error('No target directory specified') unless (defined($target_dir) and $target_dir ne '');
Packit 908522
Packit 908522
@ARGV = map(bsd_glob($_, GLOB_NOSORT), @ARGV) if ($expand_glob);
Packit 908522
my %basename_hash = ();
Packit 908522
Packit 908522
foreach my $in_name (@ARGV)
Packit 908522
{
Packit 908522
  my $basename = path_basename($in_name);
Packit 908522
Packit 908522
  # If there are multiple files with the same base name in the list, only
Packit 908522
  # the first one will be installed.  This behavior makes it very easy to
Packit 908522
  # implement a VPATH search for each individual file.
Packit 908522
  unless (exists $basename_hash{$basename})
Packit 908522
  {
Packit 908522
    $basename_hash{$basename} = undef;
Packit 908522
    my $out_name = File::Spec->catfile($target_dir, $basename);
Packit 908522
    install_file($in_name, $out_name, $basename);
Packit 908522
  }
Packit 908522
}
Packit 908522
exit;