From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- support/ctanify/README | 50 ++++ support/ctanify/ctanify | 716 ++++++++++++++++++++++++++++++++++++++++++++ support/ctanify/ctanify.1 | 398 ++++++++++++++++++++++++ support/ctanify/ctanify.pdf | Bin 0 -> 41083 bytes 4 files changed, 1164 insertions(+) create mode 100644 support/ctanify/README create mode 100755 support/ctanify/ctanify create mode 100644 support/ctanify/ctanify.1 create mode 100644 support/ctanify/ctanify.pdf (limited to 'support/ctanify') diff --git a/support/ctanify/README b/support/ctanify/README new file mode 100644 index 0000000000..284f18dfeb --- /dev/null +++ b/support/ctanify/README @@ -0,0 +1,50 @@ + +---------------------------------------+ + | CTANIFY | + | | + | Prepare a package for upload to CTAN | + | | + | By Scott Pakin, scott+ctify@pakin.org | + +---------------------------------------+ + + +Description +=========== + +ctanify is intended for developers of LaTeX packages who want to +distribute their packages via the Comprehensive TeX Archive Network +(CTAN). Given a list of filenames, ctanify creates a tarball (a +.tar.gz file) with the files laid out in CTAN's preferred structure. +The tarball additionally contains a ZIP (.zip) file with copies of all +files laid out in the standard TeX Directory Structure (TDS), which +facilitates inclusion of the package in the TeX Live distribution of +TeX. + +ctanify has been tested primarily on Linux but with reports from users +that it also works on OS X and can work on Windows under Cygwin. +Volunteers willing to help port ctanify to other platforms are +especially welcome. + + +File manifest +============= + +README This file +ctanify The ctanify Perl script itself +ctanify.1 ctanify documentation (Unix man-page format) +ctanify.pdf ctanify documentation (PDF format) + + +Copyright and License +===================== + +Copyright (C) 2017 Scott Pakin + +This work may be distributed and/or modified under the conditions of +the LaTeX Project Public License, either version 1.3c of this license +or (at your option) any later version. The latest version of this +license is in + + http://www.latex-project.org/lppl.txt + +and version 1.3c or later is part of all distributions of LaTeX version +2008/05/04 or later. diff --git a/support/ctanify/ctanify b/support/ctanify/ctanify new file mode 100755 index 0000000000..e168ed6ede --- /dev/null +++ b/support/ctanify/ctanify @@ -0,0 +1,716 @@ +#! /usr/bin/env perl + +################################################ +# Prepare a LaTeX package for upload to CTAN # +# By Scott Pakin # +################################################ + +use Cwd; +use File::Basename; +use File::Copy::Recursive qw(fcopy); +use File::Find; +use File::Path; +use File::Spec; +use File::stat; +use File::Temp qw(tempdir); +use Getopt::Long; +use Pod::Usage; +use warnings; +use strict; + +# Define some global variables. +our $VERSION = "1.9.1"; # ctanify version number +my $progname = basename $0; # Name of this program +my $pkgname; # Base name of the package to create +my $miscify = 0; # 1=replace singletons with misc; 0=don't +my $autoinclude = 1; # 1=automatically include files named in .ins +my $skipdroppings = 1; # 1=skip "dropping" files (e.g., "README~") +my $unixify = 1; # 1=make text files use Unix line endings +my $maketds = 1; # 1=embed a .tds.zip file; 0=don't +my @manifest; # List of files to include +my %file2tds; # Map from specific filenames to TDS directories +my @tdsdirlist; # Contents of the TDS tree +my @pkgdirlist; # Contents of the package tree +my @tdsonly; # Files to include only in the TDS tree +my $tdsdir = ""; # Absolute directory of the TDS tree +my $pkgdir = ""; # Absolute directory of the package directory +my $zipname; # Name of the TDS zip file +my $tarname; # Name of the package tar file +my $tdsoutdir; # Directory name where to output TDS tree +my $texmacros = "latex"; # TeX macro package + +# Associate file extensions with TDS directories. "%s" is replaced +# with the package name. +my %ext2tds = + ("README" => "doc/latex/%s", + "afm" => "fonts/afm/public/%s", + "bat" => "scripts/%s", + "bbx" => "tex/latex/%s", + "bib" => "bibtex/bib/%s", + "bst" => "bibtex/bst/%s", + "cbx" => "tex/latex/%s", + "cls" => "tex/latex/%s", + "dbx" => "tex/latex/%s", + "dtx" => "source/latex/%s", + "dvi" => "doc/latex/%s", + "fd" => "tex/latex/%s", + "ins" => "source/latex/%s", + "map" => "fonts/map/dvips/%s", + "md" => "doc/latex/%s", + "mf" => "fonts/source/public/%s", + "mp" => "metapost/%s", + "ofm" => "fonts/ofm/public/%s", + "ovf" => "fonts/ovf/public/%s", + "ovp" => "fonts/ovp/public/%s", + "pdf" => "doc/latex/%s", + "pfb" => "fonts/type1/public/%s", + "pfm" => "fonts/type1/public/%s", + "ps" => "doc/latex/%s", + "py" => "scripts/%s", + "sh" => "scripts/%s", + "sty" => "tex/latex/%s", + "tfm" => "fonts/tfm/public/%s", + "txt" => "doc/latex/%s", + "vf" => "fonts/vf/public/%s"); + +# Specify a list of filename regexps to ignore. +my @ignore_re = ('~$', '\bCVS\b', '\b\.svn\b'); + +# Specify a list of file extensions that are considered "text" files. +# This script will convert their line endings to Unix style (a single +# linefeed character). +my %text_ext = + map {($_ => 1)} qw(afm bib bst cls dtx fd ins ltx md mf mp sty tex txt); + +# Define a subroutine that returns the size in bytes of a file, +# aborting on error. +sub filesize ($) +{ + my $finfo = lstat($_[0]) || die "${progname}: Failed to stat $_ ($!)\n"; + return $finfo->size; +} + +# Define a subroutine that runs a command and aborts on error. +sub run_command ($;$) +{ + my $command = $_[0]; + my $ignore_errors = defined $_[1] ? $_[1] : 0; + my $retval = system $command; + if (!$ignore_errors && $retval>>8) { + die "${progname}: Command \"$command\" failed\n"; + } +} + +# Define a subroutine that Unix-ifies the line endings in text files. +# This subroutine is called from File::Find so it does not accept +# arguments via the @_ variable. +my %reported_line_endings; # Files we converted and told the user about +sub use_unix_line_endings +{ + # Determine if the file is a text file. + my $fname = $_; + return if !-f $fname; + my $fext = ($fname =~ m|([^./]+)$| && $1); + return if !defined $text_ext{$fext}; + + # Make it use Unix line endings. Note that we don't bother + # checking if we're already on a Unix (or Unix-like) system. + my $oldsize = filesize $fname; + open(TEXTFILE, "<$fname") || die "${progname}: Failed to open $File::Find::name ($!)\n"; + my @entirefile = map {s/[\n\r]+$/\n/; $_} ; + close TEXTFILE; + open(BINARYFILE, ">$fname") || die "${progname}: Failed to open $File::Find::name ($!)\n"; + binmode BINARYFILE; + print BINARYFILE @entirefile; + close BINARYFILE; + my $newsize = filesize $fname; + if ($newsize != $oldsize && !defined $reported_line_endings{$fname}) { + # Don't frighten the user when he sees a different file size + # in the tar file from the original in the filesystem + my $fullname = $File::Find::name; + $fullname =~ s,^$tdsdir/,,; + $fullname =~ s,^$pkgdir/,,; + warn "${progname}: Modified $fullname to use Unix line endings (use --no-unixify to prevent this)\n"; + $reported_line_endings{$fname} = 1; + } +} + +########################################################################### + +# Parse the command line. +my $wanthelp = 0; +my $wantversion = 0; +GetOptions("p|pkgname=s" => \$pkgname, + "m|misc!" => \$miscify, + "k|skip!" => \$skipdroppings, + "u|unixify!" => \$unixify, + "t|tdsonly=s" => \@tdsonly, + "a|auto!" => \$autoinclude, + "d|tdsdir=s" => \$tdsoutdir, + "T|tex=s" => \$texmacros, + "s|tds!" => \$maketds, + "V|version" => \$wantversion, + "h|help" => \$wanthelp) + || pod2usage(-verbose => 0, + -exitval => 1); +pod2usage(-verbose => 1, + -exitval => 0) if $wanthelp; +if ($wantversion) { + print "ctanify version $VERSION\n"; + exit 0; +} +pod2usage(-verbose => 0, + -exitval => 1) if !@ARGV; +foreach my $fname (@ARGV) { + # Let the user specify "=" to place files + # explicitly in the TDS tree. + if ($fname =~ /^(.*)=([^=]+)$/) { + foreach my $exp_fname (glob $1) { + $file2tds{$exp_fname} = $2; + push @manifest, $exp_fname; + } + } + else { + push @manifest, glob $fname; + } +} +@tdsonly = map {File::Spec->abs2rel($_)} map {glob} @tdsonly; + +# Replace "latex" with something else if --tex was specified. +if ($texmacros ne "latex") { + foreach my $ext (keys %ext2tds) { + $ext2tds{$ext} =~ s,\blatex\b,$texmacros,g; + } +} + +# Determine the package name if not explicitly specified. +if (!defined $pkgname) { + my @mainfiles = (grep(/\.ins$/, @manifest), grep(/\.sty$/, @manifest)); + if (!@mainfiles) { + die "${progname}: Please either list a .ins or .sty file or specify --pkgname\n"; + } + $pkgname = basename $mainfiles[0]; + $pkgname =~ s/\.[^.]+$//; +} + +# Parse each .ins file to find more files to include. +if ($autoinclude) { + foreach my $fname (grep /\.ins$/, @manifest) { + # Read the entire file. + local $/ = undef; + open(INSFILE, "<$fname") || die "${progname}: Failed to open $fname ($!)\n"; + my $insfile = ; + close INSFILE; + $insfile =~ s/\%.*?\n//g; + + # Add all source files (\from) to the manifest. + while ($insfile =~ /\\from\{([^\}]+)\}/g) { + my $fname_exp = $1; + $fname_exp =~ s/\\jobname\b/$pkgname/g; + push @manifest, $fname_exp; + } + + # Add all generated files (\file) to the manifest but also to + # the list of TDS-only inclusions. + while ($insfile =~ /\\file\{([^\}]+)\}/g) { + my $fname_exp = $1; + $fname_exp =~ s/\\jobname\b/$pkgname/g; + push @manifest, $fname_exp; + push @tdsonly, $fname_exp; + } + } +} + +# Skip "dropping" files and files beginning with ".". +if ($skipdroppings) { + my @newmanifest; + CHECK_DROPPING: + foreach my $fname (@manifest) { + if (substr($fname, 0, 1) eq ".") { + warn "${progname}: Excluding $fname (use --no-skip to force inclusion)\n"; + next CHECK_DROPPING; + } + foreach my $dropping_re (@ignore_re) { + if ($fname =~ $dropping_re) { + warn "${progname}: Excluding $fname (use --no-skip to force inclusion)\n"; + next CHECK_DROPPING; + } + } + push @newmanifest, $fname; + } + @manifest = @newmanifest; +} + +# Map each file to a TDS directory. +foreach my $fname (@manifest) { + next if defined $file2tds{$fname}; + my $fext = ($fname =~ m|([^./]+)$| && $1); + if ($fname =~ /\.tex$/ && $pkgname eq basename $fname, ".tex") { + # .tex -- treat as documentation. + $file2tds{$fname} = sprintf $ext2tds{"README"}, $pkgname; + } + elsif (defined $ext2tds{$fext}) { + # Most files -- determine the directory based on the file extension. + $file2tds{$fname} = sprintf $ext2tds{$fext}, $pkgname; + } + elsif ($fext =~ /^(\d+)[a-z]*$/i) { + # Man page (e.g., "ls.1" or "File::Temp.3pm"). + $file2tds{$fname} = "doc/man/man$1"; + } + else { + # Read the file to determine if it's a Unix script (starts with "#!"). + open(SCRIPT, "<", $fname) || die "${progname}: Failed to open $fname ($!)\n"; + my $shebang; + read(SCRIPT, $shebang, 2); + close SCRIPT; + if ($shebang eq "#!") { + $file2tds{$fname} = "scripts/$pkgname"; + } + else { + warn "${progname}: Not including $fname in the TDS tree (unknown extension)\n"; + } + } +} + +# Create a working directory and populate it with TDS files. +my $workdir = tempdir("$progname-XXXXXX", TMPDIR => 1, CLEANUP => 1); +$tdsdir = $tdsoutdir ? $tdsoutdir : "$workdir/texmf"; +mkdir $tdsdir || die "${progname}: Failed to create $tdsdir ($!)\n"; +foreach my $fname (@manifest) { + # Create a TDS subdirectory. + my $subdir = $file2tds{$fname}; + next if !defined $subdir; + mkpath "$tdsdir/$subdir"; + + # Copy the specified file into the subdirectory. + fcopy($fname, "$tdsdir/$subdir/" . basename $fname) || die "${progname}: Failed to copy $fname ($!)\n"; +} +if ($miscify) { + # Replace package directories containing a single file with "misc". + my %renamings; + find(sub { + return if $File::Find::name =~ m|\btexmf/fonts\b|; + if (-d) { + my @children = glob "$_/*"; + if ($#children == 0 && -f $children[0] && $_ eq $pkgname) { + $renamings{$File::Find::name} = $File::Find::dir . "/misc"; + } + } + }, $tdsdir); + while (my ($oldname, $newname) = each %renamings) { + rename $oldname, $newname; + } +} +if ($unixify) { + # Make all text files use Unix line endings. + find(\&use_unix_line_endings, $tdsdir); +} + +# Complain if the doc directory contains PostScript or DVI files. +my @bad_docs; +find(sub { + return if !-f; + push @bad_docs, $_ if $File::Find::name =~ m,\bdoc/[^/]+/$pkgname/.*\.(ps|dvi)$,; +}, $tdsdir); +if (@bad_docs) { + my $bad_docs = join ", ", @bad_docs; + warn "${progname}: CTAN prefers having only PDF documentation (re: $bad_docs)\n"; +} + +# We have no more work to do if we're simply creating a TDS directory. +exit 0 if $tdsoutdir; + +# Store a listing of the TDS directory. +my $prevdir = getcwd(); +chdir $tdsdir || die "${progname}: Failed to switch to $tdsdir ($!)\n"; +find(sub { + return if !-f; + my $fsize = filesize $_; + push @tdsdirlist, [substr($File::Find::name, 2), $fsize]; +}, "."); + +# Archive and remove the TDS directory. +$zipname = "$pkgname.tds.zip"; +my $zip_exclusions = $skipdroppings ? "-x __MACOSX -x .DS_Store" : ""; +run_command "zip -q -r -9 -y -m $workdir/$zipname . $zip_exclusions", 1; +my $zipsize; +if (-f "$workdir/$zipname") { + $zipsize = filesize "$workdir/$zipname"; +} +else { + $zipname = ""; +} +$zipname = "" if !$maketds; +chdir $prevdir || die "${progname}: Failed to switch to $prevdir ($!)\n"; +rmdir $tdsdir || die "${progname}: Failed to remove $tdsdir ($!)\n"; + +# Copy all files named in the file manifest to the package directory. +$pkgdir = "$workdir/$pkgname"; +mkdir $pkgdir || die "${progname}: Failed to create $pkgdir ($!)\n"; +my %tdsonly = map {($_ => 1)} @tdsonly; +foreach my $fname (@manifest) { + my $relname = File::Spec->abs2rel($fname); + next if defined $tdsonly{$relname}; + my ($namepart, $pathpart, $suffixpart) = fileparse($relname); + mkpath "$pkgdir/$pathpart"; + my $targetfile = "$pkgdir/$pathpart/$namepart$suffixpart"; + fcopy($fname, $targetfile) || die "${progname}: Failed to copy $fname ($!)\n"; +} +if ($unixify) { + # Make all text files use Unix line endings. + find(\&use_unix_line_endings, $pkgdir); +} + +# Store a listing of the package directory. +$prevdir = getcwd(); +chdir $pkgdir || die "${progname}: Failed to switch to $pkgdir ($!)\n"; +find(sub { + return if !-f; + my $fsize = filesize $_; + push @pkgdirlist, [substr($File::Find::name, 2), $fsize]; +}, "."); +chdir $prevdir || die "${progname}: Failed to switch to $prevdir ($!)\n"; + +# Tar up the package directory. +$tarname = "$pkgname.tar.gz"; +my $tar_exclusions = $skipdroppings ? "--exclude=__MACOSX --exclude=.DS_Store" : ""; +run_command "tar -czf $tarname -C $workdir $tar_exclusions $pkgname $zipname"; + +# Output a listing of what we tarred up. +printf "\n%8d %s\n\n", filesize($tarname), $tarname; +foreach my $fname_size (sort {$a->[0] cmp $b->[0]} @pkgdirlist) { + my ($fname, $fsize) = @$fname_size; + printf " %8d %s/%s\n", $fsize, $pkgname, $fname; +} +if ($zipname ne "") { + printf " %8d %s\n\n", $zipsize, $zipname; + foreach my $fname_size (sort {$a->[0] cmp $b->[0]} @tdsdirlist) { + my ($fname, $fsize) = @$fname_size; + printf " %8d %s\n", $fsize, $fname; + } +} +print "\n"; + +########################################################################### + +__END__ + +=head1 NAME + +ctanify - Prepare a package for upload to CTAN + + +=head1 SYNOPSIS + +ctanify +[B<--pkgname>=I] +[B<-->[B]B] +[B<--tdsonly>=I ...] +[B<-->[B]B] +[B<-->[B]B] +[B<--tdsdir>=I ...] +[B<--tex>=I] +[B<-->[B]B] +[B<-->[B]B] +I[=I] ... + +ctanify +[B<--help>] + +ctanify +[B<--version>] + + +=head1 DESCRIPTION + +B is intended for developers who have a LaTeX package that +they want to distribute via the Comprehensive TeX Archive Network +(CTAN). Given a list of filenames, B creates a tarball (a +F<.tar.gz> file) with the files laid out in CTAN's preferred +structure. The tarball additionally contains a ZIP (F<.zip>) file +with copies of all files laid out in the standard TeX Directory +Structure (TDS), which facilitates inclusion of the package in the TeX +Live distribution. + + +=head1 OPTIONS + +B accepts the following command-line options: + +=over 5 + +=item B<-h>, B<--help> + +Output basic usage information and exit. + +=item B<-V>, B<--version> + +Output B's version number and exit. + +=item B<-p> I, B<--pkgname>=I + +Specify explicitly a package name. Normally, B uses the base +name of the first F<.ins> or F<.sty> file listed as the package name. +The package name forms the base name of the tarball that B +produces. + +=item B<--noauto> + +Do not automatically add files to the tarball. Normally, B +automatically includes all files mentioned in a F<.ins> file. + +=item B<-t> I, B<--tdsonly>=I + +Specify a subset of the files named on the command line to include +only in the TDS ZIP file, not in the CTAN package directory. +Wildcards are allowed (quoted if necessary), and B<--tdsonly> can be +used multiple times on the same command line. + +=back + +At least one filename must be specified on the command line. +B automatically places files in the TDS tree based on their +extension, but this can be overridden by specifying explicitly a +target TDS directory using the form I=I. Wildcards +are allowed for the filespec (quoted if necessary). + + +=head1 ADDITIONAL OPTIONS + +The following options are unlikely to be necessary in ordinary usage. +They are provided for special circumstances that may arise. + +=over 5 + +=item B<-d> I, B<--tdsdir>=I + +Instead of creating a tarball for CTAN, merely create the package TDS +tree rooted in directory I. + +=item B<-T> I, B<--tex>=I + +Assert that the files being packaged for CTAN target a TeX macro +package other than LaTeX. Some common examples of I are +C, C, and C. + +=item B<-nou>, B<--no-unixify> + +Store text files unmodified instead of converting their end-of-line +character to Unix format (a single linefeed character with no +carriage-return character), even though CTAN prefers receiving all +files with Unix-format end-of-line characters. + +=item B<-nok>, B<--no-skip> + +Force B to include files such as Unix hidden files, Emacs +backup files, and version-control metadata files, all of which CTAN +dislikes receiving. + +=item B<-m>, B<--miscify> + +Rename directories containing a single file to C. (For example, +rename C to +C.) This was common practice in the +past but is now strongly discouraged. + +=item B<-nos>, B<--no-tds> + +Do not embed a .tds.zip file in the generated tarball. + +=back + + +=head1 DIAGNOSTICS + +=over 5 + +=item C (No such file or directory)> + +This message is typically caused by a F<.ins> file that generates +I but that has not already been run through F or +F to actually produce I. B does not +automatically run F or F; this needs to be done manually +by the user. See L for more information. + +=item C to use Unix line endings (use --no-unixify to prevent this)> + +For consistency, CTAN stores all text files with Unix-style line +endings (a single linefeed character with no carriage-return +character). To help in this effort, B automatically replaces +non-Unix-style line endings. The preceding merely message notifies +the user that he should not be alarmed to see a different size for +I in the tarball versus the original I on disk +(which B never modifies). If there's a good reason to +preserve the original line endings (and there rarely is), the +B<--no-unixify> option can be used to prevent B from altering +any files when storing them in the tarball. + +=item C (use --no-skip to force inclusion)> + +B normally ignores files--even when specified explicitly on +the command line--that CTAN prefers not receiving. These include +files whose names start with "F<.>" (Unix hidden files), end in "F<~>" +(Emacs automatic backups), or that come from a F or F<.svn> +directory (version-control metadata files). If there's a good reason +to submit such files to CTAN (and there rarely is), the B<--no-skip> +option can be used to prevent B from ignoring them. + +=item C)> + +Because of the popularity of the PDF format, CTAN wants to have as +much documentation as possible distributed in PDF. The preceding +message asks the user to replace any PostScript or DVI documentation +with PDF if possible. (B will still include PostScript and +DVI documentation in the tarball; the preceding message is merely a +polite request.) + +=item C in the TDS tree (unknown extension)> + +B places files in the TDS tree based on a table of file +extensions. For example, all F<.sty> files are placed in +F>. If B does not know where to +put a file it does not put it anywhere. See the last paragraph of +L for an explanation of how to specify explicitly a file's +target location in the TDS tree. For common file extensions that +happen to be absent from B's table, consider also notifying +B's author at the address shown below under L. + +=back + + +=head1 EXAMPLES + +=head2 The Common Case + +Normally, all that's needed is to tell B the name of the +F<.ins> file (or F<.sty> if the package does not use DocStrip) and the +prebuilt documentation, if any: + + $ ctanify mypackage.ins mypackage.pdf README + + 490347 mypackage.tar.gz + + 1771 mypackage/README + 15453 mypackage/mypackage.dtx + 1957 mypackage/mypackage.ins + 277683 mypackage/mypackage.pdf + 246935 mypackage.tds.zip + + 1771 doc/latex/mypackage/README + 277683 doc/latex/mypackage/mypackage.pdf + 15453 source/latex/mypackage/mypackage.dtx + 1957 source/latex/mypackage/mypackage.ins + 1725 tex/latex/mypackage/mypackage.sty + +B outputs the size in bytes of the resulting tarball, each +file within it, and each file within the contained ZIP file. In the +preceding example, notice how B automatically performed all +of the following operations: + +=over 5 + +=item * + +including F (found by parsing F) in both +the F directory and the ZIP file, + +=item * + +including F (found by parsing F) in the +ZIP file but, because it's a generated file, not in the F +directory, and + +=item * + +placing all files into appropriate TDS directories (documentation, +source, main package) within the ZIP file. + +=back + +Consider what it would take to manually produce an equivalent +F file. B is definitely a simpler, quicker +alternative. + + +=head2 Advanced Usage + +B assumes that PostScript files are documentation and +therefore stores them under F/> in the TDS +tree within the ZIP File. Suppose, however, that a LaTeX package uses +a set of PostScript files to control B's output. In this case, +B must be told to include those PostScript files in the +package directory, not the documentation directory. + + $ ctanify mypackage.ins "mypackage*.ps=tex/latex/mypackage" + + +=head1 FILES + +=over 5 + +=item F + +B is written in Perl and needs a Perl installation to run. + +=item F, F + +B requires the GNU F and F programs to create a +compressed tarball (F<.tar.gz>). + +=item F + +B uses a F program to archive the TDS tree within the +main tarball. + +=back + + +=head1 CAVEATS + +B does not invoke F or F on its own, S +process a F<.ins> file. The reason is that B does not know +in the general case how to produce all of a package's generated files. +It was deemed better to do nothing than to risk overwriting existing +F<.sty> (or other) files or to include outdated generated files in the +tarball. In short, before running B you should manually +process any F<.ins> files and otherwise generate any files that should +be sent to CTAN. + +B has been tested only on Linux. It may work on S. +I've been told that it works on Windows when run using Cygwin. +Volunteers willing to help port B to other platforms are +extremely welcome. + + +=head1 SEE ALSO + +tar(1), +zip(1), +latex(1), +Guidelines for uploading TDS-Packaged materials to CTAN +(L), +A Directory Structure for TeX Files (L), + + +=head1 AUTHOR + +Scott Pakin, I + + +=head1 COPYRIGHT AND LICENSE + +Copyright 2017 Scott Pakin + +This work may be distributed and/or modified under the conditions of +the LaTeX Project Public License, either S of this +license or (at your option) any later version. The latest version of +this license is in + +=over 4 + +L + +=back + +and S or later is part of all distributions of LaTeX +version 2008/05/04 or later. diff --git a/support/ctanify/ctanify.1 b/support/ctanify/ctanify.1 new file mode 100644 index 0000000000..62f7089f05 --- /dev/null +++ b/support/ctanify/ctanify.1 @@ -0,0 +1,398 @@ +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{ +. if \nF \{ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "CTANIFY 1" +.TH CTANIFY 1 "2017-04-22" "v1.9.1" "" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ctanify \- Prepare a package for upload to CTAN +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +ctanify +[\fB\-\-pkgname\fR=\fIstring\fR] +[\fB\-\-\fR[\fBno\fR]\fBauto\fR] +[\fB\-\-tdsonly\fR=\fIfilespec\fR ...] +[\fB\-\-\fR[\fBno\fR]\fBunixify\fR] +[\fB\-\-\fR[\fBno\fR]\fBskip\fR] +[\fB\-\-tdsdir\fR=\fIdirname\fR ...] +[\fB\-\-tex\fR=\fImacro_pkg\fR] +[\fB\-\-\fR[\fBno\fR]\fBmiscify\fR] +[\fB\-\-\fR[\fBno\fR]\fBtds\fR] +\&\fIfilespec\fR[=\fIdirname\fR] ... +.PP +ctanify +[\fB\-\-help\fR] +.PP +ctanify +[\fB\-\-version\fR] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBctanify\fR is intended for developers who have a LaTeX package that +they want to distribute via the Comprehensive TeX Archive Network +(\s-1CTAN\s0). Given a list of filenames, \fBctanify\fR creates a tarball (a +\&\fI.tar.gz\fR file) with the files laid out in \s-1CTAN\s0's preferred +structure. The tarball additionally contains a \s-1ZIP \s0(\fI.zip\fR) file +with copies of all files laid out in the standard TeX Directory +Structure (\s-1TDS\s0), which facilitates inclusion of the package in the TeX +Live distribution. +.SH "OPTIONS" +.IX Header "OPTIONS" +\&\fBctanify\fR accepts the following command-line options: +.IP "\fB\-h\fR, \fB\-\-help\fR" 5 +.IX Item "-h, --help" +Output basic usage information and exit. +.IP "\fB\-V\fR, \fB\-\-version\fR" 5 +.IX Item "-V, --version" +Output \fBctanify\fR's version number and exit. +.IP "\fB\-p\fR \fIstring\fR, \fB\-\-pkgname\fR=\fIstring\fR" 5 +.IX Item "-p string, --pkgname=string" +Specify explicitly a package name. Normally, \fBctanify\fR uses the base +name of the first \fI.ins\fR or \fI.sty\fR file listed as the package name. +The package name forms the base name of the tarball that \fBctanify\fR +produces. +.IP "\fB\-\-noauto\fR" 5 +.IX Item "--noauto" +Do not automatically add files to the tarball. Normally, \fBctanify\fR +automatically includes all files mentioned in a \fI.ins\fR file. +.IP "\fB\-t\fR \fIfilespec\fR, \fB\-\-tdsonly\fR=\fIfilespec\fR" 5 +.IX Item "-t filespec, --tdsonly=filespec" +Specify a subset of the files named on the command line to include +only in the \s-1TDS ZIP\s0 file, not in the \s-1CTAN\s0 package directory. +Wildcards are allowed (quoted if necessary), and \fB\-\-tdsonly\fR can be +used multiple times on the same command line. +.PP +At least one filename must be specified on the command line. +\&\fBctanify\fR automatically places files in the \s-1TDS\s0 tree based on their +extension, but this can be overridden by specifying explicitly a +target \s-1TDS\s0 directory using the form \fIfilespec\fR=\fIdirname\fR. Wildcards +are allowed for the filespec (quoted if necessary). +.SH "ADDITIONAL OPTIONS" +.IX Header "ADDITIONAL OPTIONS" +The following options are unlikely to be necessary in ordinary usage. +They are provided for special circumstances that may arise. +.IP "\fB\-d\fR \fIdirname\fR, \fB\-\-tdsdir\fR=\fIdirname\fR" 5 +.IX Item "-d dirname, --tdsdir=dirname" +Instead of creating a tarball for \s-1CTAN,\s0 merely create the package \s-1TDS\s0 +tree rooted in directory \fIdirname\fR. +.IP "\fB\-T\fR \fImacro_pkg\fR, \fB\-\-tex\fR=\fImacro_pkg\fR" 5 +.IX Item "-T macro_pkg, --tex=macro_pkg" +Assert that the files being packaged for \s-1CTAN\s0 target a TeX macro +package other than LaTeX. Some common examples of \fImacro_pkg\fR are +\&\f(CW\*(C`generic\*(C'\fR, \f(CW\*(C`plain\*(C'\fR, and \f(CW\*(C`context\*(C'\fR. +.IP "\fB\-nou\fR, \fB\-\-no\-unixify\fR" 5 +.IX Item "-nou, --no-unixify" +Store text files unmodified instead of converting their end-of-line +character to Unix format (a single linefeed character with no +carriage-return character), even though \s-1CTAN\s0 prefers receiving all +files with Unix-format end-of-line characters. +.IP "\fB\-nok\fR, \fB\-\-no\-skip\fR" 5 +.IX Item "-nok, --no-skip" +Force \fBctanify\fR to include files such as Unix hidden files, Emacs +backup files, and version-control metadata files, all of which \s-1CTAN\s0 +dislikes receiving. +.IP "\fB\-m\fR, \fB\-\-miscify\fR" 5 +.IX Item "-m, --miscify" +Rename directories containing a single file to \f(CW\*(C`misc\*(C'\fR. (For example, +rename \f(CW\*(C`tex/latex/mypackage/mypackage.sty\*(C'\fR to +\&\f(CW\*(C`tex/latex/misc/mypackage.sty\*(C'\fR.) This was common practice in the +past but is now strongly discouraged. +.IP "\fB\-nos\fR, \fB\-\-no\-tds\fR" 5 +.IX Item "-nos, --no-tds" +Do not embed a .tds.zip file in the generated tarball. +.SH "DIAGNOSTICS" +.IX Header "DIAGNOSTICS" +.ie n .IP """Failed to copy \f(CIfilename\f(CW (No such file or directory)""" 5 +.el .IP "\f(CWFailed to copy \f(CIfilename\f(CW (No such file or directory)\fR" 5 +.IX Item "Failed to copy filename (No such file or directory)" +This message is typically caused by a \fI.ins\fR file that generates +\&\fIfilename\fR but that has not already been run through \fItex\fR or +\&\fIlatex\fR to actually produce \fIfilename\fR. \fBctanify\fR does not +automatically run \fItex\fR or \fIlatex\fR; this needs to be done manually +by the user. See \*(L"\s-1CAVEATS\*(R"\s0 for more information. +.ie n .IP """Modified \f(CIfilename\f(CW to use Unix line endings (use \-\-no\-unixify to prevent this)""" 5 +.el .IP "\f(CWModified \f(CIfilename\f(CW to use Unix line endings (use \-\-no\-unixify to prevent this)\fR" 5 +.IX Item "Modified filename to use Unix line endings (use --no-unixify to prevent this)" +For consistency, \s-1CTAN\s0 stores all text files with Unix-style line +endings (a single linefeed character with no carriage-return +character). To help in this effort, \fBctanify\fR automatically replaces +non-Unix-style line endings. The preceding merely message notifies +the user that he should not be alarmed to see a different size for +\&\fIfilename\fR in the tarball versus the original \fIfilename\fR on disk +(which \fBctanify\fR never modifies). If there's a good reason to +preserve the original line endings (and there rarely is), the +\&\fB\-\-no\-unixify\fR option can be used to prevent \fBctanify\fR from altering +any files when storing them in the tarball. +.ie n .IP """Excluding \f(CIfilename\f(CW (use \-\-no\-skip to force inclusion)""" 5 +.el .IP "\f(CWExcluding \f(CIfilename\f(CW (use \-\-no\-skip to force inclusion)\fR" 5 +.IX Item "Excluding filename (use --no-skip to force inclusion)" +\&\fBctanify\fR normally ignores files\*(--even when specified explicitly on +the command line\*(--that \s-1CTAN\s0 prefers not receiving. These include +files whose names start with "\fI.\fR\*(L" (Unix hidden files), end in \*(R"\fI~\fR" +(Emacs automatic backups), or that come from a \fI\s-1CVS\s0\fR or \fI.svn\fR +directory (version-control metadata files). If there's a good reason +to submit such files to \s-1CTAN \s0(and there rarely is), the \fB\-\-no\-skip\fR +option can be used to prevent \fBctanify\fR from ignoring them. +.ie n .IP """CTAN prefers having only PDF documentation (re: \f(CIfilename\f(CW)""" 5 +.el .IP "\f(CWCTAN prefers having only PDF documentation (re: \f(CIfilename\f(CW)\fR" 5 +.IX Item "CTAN prefers having only PDF documentation (re: filename)" +Because of the popularity of the \s-1PDF\s0 format, \s-1CTAN\s0 wants to have as +much documentation as possible distributed in \s-1PDF. \s0 The preceding +message asks the user to replace any PostScript or \s-1DVI\s0 documentation +with \s-1PDF\s0 if possible. (\fBctanify\fR will still include PostScript and +\&\s-1DVI\s0 documentation in the tarball; the preceding message is merely a +polite request.) +.ie n .IP """Not including \f(CIfilename\f(CW in the TDS tree (unknown extension)""" 5 +.el .IP "\f(CWNot including \f(CIfilename\f(CW in the TDS tree (unknown extension)\fR" 5 +.IX Item "Not including filename in the TDS tree (unknown extension)" +\&\fBctanify\fR places files in the \s-1TDS\s0 tree based on a table of file +extensions. For example, all \fI.sty\fR files are placed in +\&\fItex/latex/\fIpackage-name\fI\fR. If \fBctanify\fR does not know where to +put a file it does not put it anywhere. See the last paragraph of +\&\*(L"\s-1OPTIONS\*(R"\s0 for an explanation of how to specify explicitly a file's +target location in the \s-1TDS\s0 tree. For common file extensions that +happen to be absent from \fBctanify\fR's table, consider also notifying +\&\fBctanify\fR's author at the address shown below under \*(L"\s-1AUTHOR\*(R"\s0. +.SH "EXAMPLES" +.IX Header "EXAMPLES" +.SS "The Common Case" +.IX Subsection "The Common Case" +Normally, all that's needed is to tell \fBctanify\fR the name of the +\&\fI.ins\fR file (or \fI.sty\fR if the package does not use DocStrip) and the +prebuilt documentation, if any: +.PP +.Vb 1 +\& $ ctanify mypackage.ins mypackage.pdf README +\& +\& 490347 mypackage.tar.gz +\& +\& 1771 mypackage/README +\& 15453 mypackage/mypackage.dtx +\& 1957 mypackage/mypackage.ins +\& 277683 mypackage/mypackage.pdf +\& 246935 mypackage.tds.zip +\& +\& 1771 doc/latex/mypackage/README +\& 277683 doc/latex/mypackage/mypackage.pdf +\& 15453 source/latex/mypackage/mypackage.dtx +\& 1957 source/latex/mypackage/mypackage.ins +\& 1725 tex/latex/mypackage/mypackage.sty +.Ve +.PP +\&\fBctanify\fR outputs the size in bytes of the resulting tarball, each +file within it, and each file within the contained \s-1ZIP\s0 file. In the +preceding example, notice how \fBctanify\fR automatically performed all +of the following operations: +.IP "\(bu" 5 +including \fImypackage.dtx\fR (found by parsing \fImypackage.ins\fR) in both +the \fImypackage\fR directory and the \s-1ZIP\s0 file, +.IP "\(bu" 5 +including \fImypackage.sty\fR (found by parsing \fImypackage.ins\fR) in the +\&\s-1ZIP\s0 file but, because it's a generated file, not in the \fImypackage\fR +directory, and +.IP "\(bu" 5 +placing all files into appropriate \s-1TDS\s0 directories (documentation, +source, main package) within the \s-1ZIP\s0 file. +.PP +Consider what it would take to manually produce an equivalent +\&\fImypackage.tar.gz\fR file. \fBctanify\fR is definitely a simpler, quicker +alternative. +.SS "Advanced Usage" +.IX Subsection "Advanced Usage" +\&\fBctanify\fR assumes that PostScript files are documentation and +therefore stores them under \fIdoc/latex/\fIpackage-name\fI/\fR in the \s-1TDS\s0 +tree within the \s-1ZIP\s0 File. Suppose, however, that a LaTeX package uses +a set of PostScript files to control \fBdvips\fR's output. In this case, +\&\fBctanify\fR must be told to include those PostScript files in the +package directory, not the documentation directory. +.PP +.Vb 1 +\& $ ctanify mypackage.ins "mypackage*.ps=tex/latex/mypackage" +.Ve +.SH "FILES" +.IX Header "FILES" +.IP "\fIperl\fR" 5 +.IX Item "perl" +\&\fBctanify\fR is written in Perl and needs a Perl installation to run. +.IP "\fItar\fR, \fIgzip\fR" 5 +.IX Item "tar, gzip" +\&\fBctanify\fR requires the \s-1GNU \s0\fItar\fR and \fIgzip\fR programs to create a +compressed tarball (\fI.tar.gz\fR). +.IP "\fIzip\fR" 5 +.IX Item "zip" +\&\fBctanify\fR uses a \fIzip\fR program to archive the \s-1TDS\s0 tree within the +main tarball. +.SH "CAVEATS" +.IX Header "CAVEATS" +\&\fBctanify\fR does not invoke \fItex\fR or \fIlatex\fR on its own, e.g.,\ to +process a \fI.ins\fR file. The reason is that \fBctanify\fR does not know +in the general case how to produce all of a package's generated files. +It was deemed better to do nothing than to risk overwriting existing +\&\fI.sty\fR (or other) files or to include outdated generated files in the +tarball. In short, before running \fBctanify\fR you should manually +process any \fI.ins\fR files and otherwise generate any files that should +be sent to \s-1CTAN.\s0 +.PP +\&\fBctanify\fR has been tested only on Linux. It may work on \s-1OS\s0\ X. +I've been told that it works on Windows when run using Cygwin. +Volunteers willing to help port \fBctanify\fR to other platforms are +extremely welcome. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +\&\fItar\fR\|(1), +\&\fIzip\fR\|(1), +\&\fIlatex\fR\|(1), +Guidelines for uploading TDS-Packaged materials to \s-1CTAN +\&\s0(), +A Directory Structure for TeX Files (), +.SH "AUTHOR" +.IX Header "AUTHOR" +Scott Pakin, \fIscott+ctify@pakin.org\fR +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright 2017 Scott Pakin +.PP +This work may be distributed and/or modified under the conditions of +the LaTeX Project Public License, either version\ 1.3c of this +license or (at your option) any later version. The latest version of +this license is in +.Sp +.RS 4 + +.RE +.PP +and version\ 1.3c or later is part of all distributions of LaTeX +version 2008/05/04 or later. diff --git a/support/ctanify/ctanify.pdf b/support/ctanify/ctanify.pdf new file mode 100644 index 0000000000..8c5d7b26bd Binary files /dev/null and b/support/ctanify/ctanify.pdf differ -- cgit v1.2.3