summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2011-09-07 23:36:27 +0000
committerKarl Berry <karl@freefriends.org>2011-09-07 23:36:27 +0000
commit24e336e14a82e9d1a0857014f6c7433129031a29 (patch)
treece54ff77f60ecf3e576181707403f99da1e3e803
parentf1cddb2ae051713a3d0b9efa1251d8f85d8131fc (diff)
new script ctanupload 1.1 (6sep11)
git-svn-id: svn://tug.org/texlive/trunk@23866 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Build/source/texk/texlive/linked_scripts/Makefile.am1
-rw-r--r--Build/source/texk/texlive/linked_scripts/Makefile.in1
-rw-r--r--Build/source/texk/texlive/linked_scripts/ctanupload/ctanupload.pl450
l---------Master/bin/alpha-linux/ctanupload1
l---------Master/bin/amd64-freebsd/ctanupload1
l---------Master/bin/amd64-kfreebsd/ctanupload1
l---------Master/bin/i386-cygwin/ctanupload1
l---------Master/bin/i386-freebsd/ctanupload1
l---------Master/bin/i386-kfreebsd/ctanupload1
l---------Master/bin/i386-linux/ctanupload1
l---------Master/bin/i386-netbsd/ctanupload1
l---------Master/bin/i386-solaris/ctanupload1
l---------Master/bin/mips-irix/ctanupload1
l---------Master/bin/powerpc-aix/ctanupload1
l---------Master/bin/powerpc-linux/ctanupload1
l---------Master/bin/sparc-linux/ctanupload1
l---------Master/bin/sparc-solaris/ctanupload1
l---------Master/bin/universal-darwin/ctanupload1
-rwxr-xr-xMaster/bin/win32/ctanupload.exebin0 -> 1536 bytes
l---------Master/bin/x86_64-darwin/ctanupload1
l---------Master/bin/x86_64-linux/ctanupload1
l---------Master/bin/x86_64-solaris/ctanupload1
-rw-r--r--Master/texmf-dist/doc/support/ctanupload/Makefile.example25
-rw-r--r--Master/texmf-dist/doc/support/ctanupload/README66
-rw-r--r--Master/texmf-dist/doc/support/ctanupload/ctanupload.pdfbin0 -> 140254 bytes
-rw-r--r--Master/texmf-dist/doc/support/ctanupload/ctanupload.tex192
-rw-r--r--Master/texmf-dist/scripts/ctanupload/ctanupload.pl450
-rwxr-xr-xMaster/tlpkg/bin/tlpkg-ctan-check2
-rw-r--r--Master/tlpkg/tlpsrc/collection-binextra.tlpsrc1
-rw-r--r--Master/tlpkg/tlpsrc/ctanupload.tlpsrc1
30 files changed, 1206 insertions, 1 deletions
diff --git a/Build/source/texk/texlive/linked_scripts/Makefile.am b/Build/source/texk/texlive/linked_scripts/Makefile.am
index 0891b7cd457..d33c711428e 100644
--- a/Build/source/texk/texlive/linked_scripts/Makefile.am
+++ b/Build/source/texk/texlive/linked_scripts/Makefile.am
@@ -72,6 +72,7 @@ texmf_dist_other_scripts = \
bundledoc/bundledoc \
cachepic/cachepic.tlu \
context/perl/mptopdf.pl \
+ ctanupload/ctanupload.pl \
de-macro/de-macro \
dviasm/dviasm.py \
ebong/ebong.py \
diff --git a/Build/source/texk/texlive/linked_scripts/Makefile.in b/Build/source/texk/texlive/linked_scripts/Makefile.in
index 7e8fb94fc84..d7752662b68 100644
--- a/Build/source/texk/texlive/linked_scripts/Makefile.in
+++ b/Build/source/texk/texlive/linked_scripts/Makefile.in
@@ -210,6 +210,7 @@ texmf_dist_other_scripts = \
bundledoc/bundledoc \
cachepic/cachepic.tlu \
context/perl/mptopdf.pl \
+ ctanupload/ctanupload.pl \
de-macro/de-macro \
dviasm/dviasm.py \
ebong/ebong.py \
diff --git a/Build/source/texk/texlive/linked_scripts/ctanupload/ctanupload.pl b/Build/source/texk/texlive/linked_scripts/ctanupload/ctanupload.pl
new file mode 100644
index 00000000000..70bb018217e
--- /dev/null
+++ b/Build/source/texk/texlive/linked_scripts/ctanupload/ctanupload.pl
@@ -0,0 +1,450 @@
+#!/usr/bin/perl
+################################################################################
+# Copyright (c) 2011 Martin Scharrer <martin@scharrer-online.de>
+# This is open source software under the GPL v3 or later.
+################################################################################
+use strict;
+use warnings;
+
+sub fromenv;
+sub load_data;
+sub save_data;
+
+my $VERSION = 'v1.1';
+my %CTAN_SERVERURLS = (
+ dante => 'http://dante.ctan.org/upload.html',
+ de => 'http://dante.ctan.org/upload.html',
+ uktug => 'http://www.tex.ac.uk/upload/',
+ 'uk-tug' => 'http://www.tex.ac.uk/upload/',
+ uk => 'http://www.tex.ac.uk/upload/',
+ cambridge => 'http://www.tex.ac.uk/upload/',
+);
+my $CTAN_URL = $CTAN_SERVERURLS{dante};
+
+my @FIELDS = qw(contribution version name email summary directory DoNotAnnounce announce notes license freeversion file);
+my @REQUIRED = qw(contribution version name email summary license file);
+my %FIELDS = map { $_ => fromenv($_) } @FIELDS;
+
+
+my %FIELDS_DESC = (
+ contribution => 'Name of your contribution',
+ version => 'Version number',
+ name => 'Your name',
+ email => 'Your email',
+ summary => 'Summary description',
+ directory => 'Suggested CTAN directory',
+ DoNotAnnounce => 'No need to announce this update',
+ announce => 'Short description for announcement',
+ notes => 'Optional notes to the CTAN maintainers',
+ license => 'License type',
+ freeversion => 'Which free license',
+ file => 'File to upload',
+);
+
+my @LICENSES = qw( free nocommercial nosell nosource shareware artistic other-nonfree);
+
+my %LICENSES = (
+ free => 'Free',
+ nocommercial => 'Nocommercial',
+ nosell => 'Nosell',
+ nosource => 'Nosource',
+ shareware => 'Shareware',
+ artistic => 'Perl Artistic (Clarified or later)',
+ 'other-nonfree' => 'Other nonfree License',
+);
+
+my @FREEVERSIONS = qw( apache2 artistic fdl gfl gpl lgpl lppl ofl pd other-free);
+
+my %FREEVERSIONS = (
+ apache2 => 'Apache License v2.0',
+ artistic => 'Perl Artistic License (version 2)',
+ fdl => 'GNU Free Documentation License',
+ gfl => 'GUST Font License',
+ gpl => 'GNU General Public License',
+ lgpl => 'Lesser GPL',
+ lppl => 'LaTeX Project',
+ ofl => 'Open Font License',
+ pd => 'Public Domain',
+ 'other-free' => 'Other Free',
+);
+
+my $QUIET = 0;
+my $ASK = 1;
+my $FORCE = 0;
+my $PROMPT = -t STDIN ? 1 : 0;
+
+sub usage {
+ my $warn = shift;
+ if ($warn) {
+ print STDERR "Unknown option '$warn'\n";
+ }
+ print STDERR <<"EOT";
+ctanupload script $VERSION
+Uploads a contribution to CTAN.
+
+Usage:
+ctanupload <options> --<name>=<value>
+
+Arguments can also be given using the CTANUPLOAD environment variable which are processed first, so that
+explicit arguments will overwrite them.
+
+Options:
+ -h Print this help and exit.
+ -y Do not ask for confirmation, but submit immediately.
+ -u <URL> CTAN URL to upload to.
+ -U <name> CTAN server to upload to, either 'dante' or 'uktug'.
+ -F <file> Read data from file
+ -f Force upload even if input seems incorrect (unknown license etc.).
+ -p Prompt for missing values. (default if run in terminal)
+ -P Do not prompt for missing values. (default if not run in terminal)
+ -v Verbose mode.
+ -q Quiet mode.
+ -V Print version number.
+
+The following fields exists and can be given as
+--<name>=<value>, --<name> <value>, --<name>-file=<file>, --<name>-file <file>
+or as environment variables: CTAN_<NAME>, CTAN_<name>, <NAME> or <name>.
+
+EOT
+
+ foreach my $field (@FIELDS) {
+ printf STDERR " %15s %s\n", $field, $FIELDS_DESC{$field};
+ }
+
+ printf STDERR "\nValid license types:\n";
+ for my $license (@LICENSES) {
+ printf STDERR " %15s %s\n", $license, $LICENSES{$license};
+ }
+
+ printf STDERR "\nValid free license:\n";
+ for my $license (@FREEVERSIONS) {
+ printf STDERR " %15s %s\n", $license, $FREEVERSIONS{$license};
+ }
+
+ exit ($warn ? 1 : 0);
+}
+
+if (exists $ENV{'CTANUPLOAD'}) {
+ unshift @ARGV, (split /\s+/, $ENV{'CTANUPLOAD'});
+}
+
+while (my $arg = shift @ARGV) {
+ if ($arg =~ /^--(.*?)(?:=(.*))?$/) {
+ my $name = $1;
+ my $value = defined $2 ? $2 : shift @ARGV;
+ my $file;
+ if ($name =~ /(.*)-file$/) {
+ $name = $1;
+ $file = $value;
+ }
+ if (exists $FIELDS{$name}) {
+ if ($file) {
+ if (open (my $valfile, '<', $file)) {
+ $value = join '', <$valfile>;
+ close ($valfile);
+ }
+ else {
+ warn "Couldn't read file '$file'!\n";
+ $value = '';
+ }
+ }
+ $FIELDS{$name} = $value;
+ }
+ else {
+ usage('--' . $name . ($file ? '-file' : ''));
+ }
+ }
+ elsif ($arg =~ /^-([a-z]+)$/i) {
+ for my $char (split //, $1) {
+ if ($char eq 'h') {
+ usage(0);
+ }
+ elsif ($char eq 'q') {
+ $QUIET = 1;
+ }
+ elsif ($char eq 'v') {
+ $QUIET = 0;
+ }
+ elsif ($char eq 'y') {
+ $ASK = 0;
+ }
+ elsif ($char eq 'F') {
+ my $file = shift @ARGV;
+ load_data ($file);
+ }
+ elsif ($char eq 'f') {
+ $FORCE = 1;
+ }
+ elsif ($char eq 'p') {
+ $PROMPT = 1;
+ }
+ elsif ($char eq 'P') {
+ $PROMPT = 0;
+ }
+ elsif ($char eq 'u') {
+ $CTAN_URL = shift @ARGV;
+ }
+ elsif ($char eq 'U') {
+ my $server = lc shift @ARGV;
+ if (not exists $CTAN_SERVERURLS{ $server }) {
+ die "Error: Unknown CTAN server '$server'.\n";
+ }
+ $CTAN_URL = $CTAN_SERVERURLS{ $server };
+ }
+ elsif ($char eq 'V') {
+ print STDERR "ctanupload script $VERSION.\n";
+ exit (0);
+ }
+ else {
+ usage('-' . $char);
+ }
+ }
+ }
+ else {
+ usage($arg);
+ }
+}
+
+PROMPT:
+
+if ($PROMPT) {
+ foreach my $field (@FIELDS) {
+ if (!defined $FIELDS{$field} || !length $FIELDS{$field}) {
+ my $input = '';
+ if ($field eq 'notes' || $field eq 'announce') {
+ next if $field eq 'announce' and $FIELDS{DoNotAnnounce};
+ print "\u$FIELDS_DESC{$field}: (press CTRL-Z (Windows) or CTRL-D (Linux) to stop)\n";
+ while (<STDIN>) {
+ $input .= $_;
+ }
+ }
+ elsif ($field eq 'DoNotAnnounce') {
+ print "\uNo need to announce upload? [y/N]: ";
+ $input = <STDIN>;
+ }
+ elsif ($field eq 'license') {
+ print "\u$FIELDS_DESC{$field}:\n";
+ my $num = 1;
+ foreach my $license (@LICENSES) {
+ printf " [%d] %s\n", $num++, $LICENSES{$license};
+ }
+ print "Selection: ";
+ $input = lc (<STDIN> || '');
+ if ($input =~ /^\s*(\d+)\s*$/) {
+ $input = $LICENSES[$1-1];
+ }
+ }
+ elsif ($field eq 'freeversion') {
+ next if $FIELDS{license} ne 'free';
+ print "\u$FIELDS_DESC{$field}:\n";
+ my $num = 1;
+ foreach my $license (@FREEVERSIONS) {
+ printf " [%d] %s\n", $num++, $FREEVERSIONS{$license};
+ }
+ print "Selection: ";
+ $input = lc (<STDIN> || '');
+ if ($input =~ /^\s*(\d+)\s*$/) {
+ $input = $FREEVERSIONS[$1-1];
+ }
+ }
+ else {
+ print "\u$FIELDS_DESC{$field}: ";
+ $input = <STDIN>;
+ }
+ $input = '' if not defined $input;
+ chomp $input;
+ $input =~ s/^\s+//;
+ $input =~ s/\s+$//;
+ $FIELDS{$field} = $input;
+ }
+ }
+}
+
+my $abort = 0;
+foreach my $required (@REQUIRED) {
+ if (!length $FIELDS{$required}) {
+ print "Required field '$required' is missing!\n";
+ $abort++;
+ }
+}
+if (not exists $LICENSES{ $FIELDS{license} }) {
+ print "Unknown license type '$FIELDS{license}'!\n";
+ $abort++ if not $FORCE;
+}
+if ($FIELDS{license} ne 'free') {
+ $FIELDS{freeversion} = '-not-selected-';
+} elsif (!$FIELDS{freeversion}) {
+ print "Required field 'freeversion' is missing!\n";
+ $abort++;
+} elsif (not exists $FREEVERSIONS{ $FIELDS{freeversion} }) {
+ print "Unknown free license '$FIELDS{freeversion}'!\n";
+ $abort++ if not $FORCE;
+}
+if ($FIELDS{file} && ! -f $FIELDS{file}) {
+ print "File '$FIELDS{file}' not found!\n";
+ $abort++;
+}
+if ($abort) {
+ print "Aborting!\n";
+ exit (2);
+}
+
+my $DoNotAnnounce;
+if ($FIELDS{DoNotAnnounce}) {
+ $FIELDS{DoNotAnnounce} = 'No';
+ $DoNotAnnounce = '[x]';
+}
+else {
+ $FIELDS{DoNotAnnounce} = undef;
+ $DoNotAnnounce = '[ ]';
+}
+
+if (!$FIELDS{directory}) {
+ $FIELDS{directory} = '/macros/latex/contrib/' . $FIELDS{contribution};
+}
+
+print "\nThe following data will be submitted to CTAN ($CTAN_URL):\n";
+
+foreach my $field (@FIELDS) {
+ if ($field eq 'DoNotAnnounce') {
+ print "$FIELDS_DESC{$field}: $DoNotAnnounce\n";
+ }
+ elsif ($field eq 'license') {
+ print "$FIELDS_DESC{$field}: $LICENSES{$FIELDS{$field}}\n";
+ }
+ elsif ($field eq 'freeversion') {
+ print "$FIELDS_DESC{$field}: $FREEVERSIONS{$FIELDS{$field}}\n";
+ }
+ else {
+ print "$FIELDS_DESC{$field}: $FIELDS{$field}\n";
+ }
+}
+
+if ($ASK) {
+ print "\nUpload? [(y/N/(e)dit/(s)ave] ";
+ my $response = lc <STDIN>;
+ chomp ($response);
+
+ unless ($response eq 'y' or $response eq 'yes') {
+ if ($response eq 'e' or $response eq 'edit') {
+ my $file = 'ctanupload.dat';
+ save_data($file);
+ if (not defined $ENV{EDITOR}) {
+ print "No EDITOR environment variable defined.\n";
+ print "Data was stored in file '$file'. Please edit manually and load with the -F option.\n";
+ exit (1);
+ }
+ else {
+ system($ENV{EDITOR}, $file);
+ load_data($file);
+ goto PROMPT;
+ }
+ }
+ elsif ($response eq 's' or $response eq 'save') {
+ my $file = 'ctanupload.dat';
+ save_data($file);
+ print "Data was stored in file '$file'.\n";
+ exit (2);
+ }
+ else {
+ print "\nUpload aborted!\n";
+ exit (1);
+ }
+ }
+}
+
+
+use WWW::Mechanize;
+my $mech = WWW::Mechanize->new(quiet => $QUIET, autocheck => 1);
+
+print "Accessing CTAN upload page ...\n";
+$mech->get( $CTAN_URL );
+print "Uploading ...\n";
+$mech->submit_form(
+ form_number => 1,
+ fields => \%FIELDS,
+);
+
+if ($mech->success()) {
+ print "Upload successfull!\n";
+}
+else {
+ print "Upload failed: ", $mech->response()->message(), "\n";
+}
+
+print "\nResponse:\n";
+eval {
+ use HTML::TreeBuilder;
+ use HTML::FormatText;
+ my $tree = HTML::TreeBuilder->new_from_content( $mech->content() );
+ my $formatter = HTML::FormatText->new(leftmargin => 0, rightmargin => 80);
+ my @response = split /\n/, $formatter->format($tree);
+ local $, = "\n";
+ print @response[3..$#response-3];
+} or do {
+ print "Can't display HTML response, storing reponse if log file 'ctanupload_response.html'\n";
+ open (LOG, '>', 'ctanupload_response.html');
+ print LOG $mech->content();
+ close (LOG);
+};
+
+exit (0);
+
+
+sub fromenv {
+ my $name = shift;
+ foreach my $var ('CTAN_' . uc $name, uc $name, 'CTAN_' . $name, $name) {
+ return $ENV{$var} if exists $ENV{$var};
+ }
+ return undef;
+}
+
+sub load_data {
+ my $file = shift;
+ open (my $load, '<', $file) or die "Couldn't open data file '$file'!\n";
+ LOAD_LOOP:
+ while (my $line = <$load>) {
+ if ($line =~ /^([a-z]+)\s*=\s*(.*)$/i) {
+ my ($name,$value) = ($1,$2);
+ if (!exists $FIELDS{$name}) {
+ print STDERR "Ignoring unknown variable '$name' from file '$file' (line $.)!\n";
+ next;
+ }
+ $FIELDS{$name} = $value;
+ if ($name eq 'announce' || $name eq 'notes') {
+ $FIELDS{$name} .= "\n";
+ while ($line = <$load>) {
+ last if ($line =~ /^[a-z]+\s*=/i);
+ $FIELDS{$name} .= $line;
+ }
+ $FIELDS{$name} =~ s/^[\s\n]+//;
+ $FIELDS{$name} =~ s/[\s\n]+$//;
+ redo LOAD_LOOP if not eof $load;
+ }
+ }
+ else {
+ print STDERR "Ignoring incorrect line '$line' from file '$file' (line $.)!\n";
+ }
+ }
+ close ($load);
+}
+
+sub save_data {
+ my $file = shift;
+ $file = 'ctanupload.dat' if not defined $file;
+ open (my $save, '>', $file) or do { warn "Couldn't save data to file '$file'!\n"; return; };
+ foreach my $field (@FIELDS) {
+ if ($field eq 'DoNotAnnounce') {
+ print {$save} "$field = ", $FIELDS{DoNotAnnounce} ? '1' : '0', "\n";
+ }
+ else {
+ print {$save} "$field = ", $FIELDS{$field} || '', "\n";
+ }
+ }
+ close ($save);
+ return;
+}
+
+
+
+__END__
diff --git a/Master/bin/alpha-linux/ctanupload b/Master/bin/alpha-linux/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/alpha-linux/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/amd64-freebsd/ctanupload b/Master/bin/amd64-freebsd/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/amd64-freebsd/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/amd64-kfreebsd/ctanupload b/Master/bin/amd64-kfreebsd/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/amd64-kfreebsd/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/i386-cygwin/ctanupload b/Master/bin/i386-cygwin/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/i386-cygwin/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/i386-freebsd/ctanupload b/Master/bin/i386-freebsd/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/i386-freebsd/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/i386-kfreebsd/ctanupload b/Master/bin/i386-kfreebsd/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/i386-kfreebsd/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/i386-linux/ctanupload b/Master/bin/i386-linux/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/i386-linux/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/i386-netbsd/ctanupload b/Master/bin/i386-netbsd/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/i386-netbsd/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/i386-solaris/ctanupload b/Master/bin/i386-solaris/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/i386-solaris/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/mips-irix/ctanupload b/Master/bin/mips-irix/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/mips-irix/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/powerpc-aix/ctanupload b/Master/bin/powerpc-aix/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/powerpc-aix/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/powerpc-linux/ctanupload b/Master/bin/powerpc-linux/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/powerpc-linux/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/sparc-linux/ctanupload b/Master/bin/sparc-linux/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/sparc-linux/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/sparc-solaris/ctanupload b/Master/bin/sparc-solaris/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/sparc-solaris/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/universal-darwin/ctanupload b/Master/bin/universal-darwin/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/universal-darwin/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/win32/ctanupload.exe b/Master/bin/win32/ctanupload.exe
new file mode 100755
index 00000000000..5777d90a17a
--- /dev/null
+++ b/Master/bin/win32/ctanupload.exe
Binary files differ
diff --git a/Master/bin/x86_64-darwin/ctanupload b/Master/bin/x86_64-darwin/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/x86_64-darwin/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/x86_64-linux/ctanupload b/Master/bin/x86_64-linux/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/x86_64-linux/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/bin/x86_64-solaris/ctanupload b/Master/bin/x86_64-solaris/ctanupload
new file mode 120000
index 00000000000..40bd522d6f0
--- /dev/null
+++ b/Master/bin/x86_64-solaris/ctanupload
@@ -0,0 +1 @@
+../../texmf-dist/scripts/ctanupload/ctanupload.pl \ No newline at end of file
diff --git a/Master/texmf-dist/doc/support/ctanupload/Makefile.example b/Master/texmf-dist/doc/support/ctanupload/Makefile.example
new file mode 100644
index 00000000000..ec35030541e
--- /dev/null
+++ b/Master/texmf-dist/doc/support/ctanupload/Makefile.example
@@ -0,0 +1,25 @@
+# Example Makefile which uses ctanify and ctanupload to pack and upload a LaTeX package
+# The required data is passed using environment variables.
+CONTRIBUTION = foobar
+NAME = John Doe
+EMAIL = john.doe@inter.net
+DIRECTORY = /macros/latex/contrib/${CONTRIBUTION}
+LICENSE = free
+FREEVERSION = lppl
+FILE = ${CONTRIBUTION}.tar.gz
+export CONTRIBUTION VERSION NAME EMAIL SUMMARY DIRECTORY DONOTANNOUNCE ANNOUNCE NOTES LICENSE FREEVERSION FILE
+
+ctanify: ${FILE}
+
+${CONTRIBUTION}.sty: ${CONTRIBUTION}.ins ${CONTRIBUTION}.dtx
+ yes | tex $<
+
+${CONTRIBUTION}.pdf: ${CONTRIBUTION}.dtx ${CONTRIBUTION}.sty
+ latexmk $<
+
+${FILE}: ${CONTRIBUTION}.dtx ${CONTRIBUTION}.ins ${CONTRIBUTION}.sty README ${CONTRIBUTION}.pdf
+ ctanify $^
+
+upload: ctanify
+ ctanupload -p
+
diff --git a/Master/texmf-dist/doc/support/ctanupload/README b/Master/texmf-dist/doc/support/ctanupload/README
new file mode 100644
index 00000000000..7a613440dee
--- /dev/null
+++ b/Master/texmf-dist/doc/support/ctanupload/README
@@ -0,0 +1,66 @@
+ctanupload script
+~~~~~~~~~~~~~~~~~
+This Perl script allows the uploads of a contribution to CTAN from the command line.
+It is intended to simplify the release process for LaTeX package authors.
+
+Copyright (C) by Martin Scharrer <martin@scharrer-online.de>
+Source code repository: https://bitbucket.org/martin_scharrer/ctanupload
+Please report bugs and feature requests at https://bitbucket.org/martin_scharrer/ctanupload/issues/
+
+Usage:
+ctanupload <options> --<name>=<value>
+
+Arguments can also be given using the CTANUPLOAD environment variable which are processed first, so that
+explicit arguments will overwrite them.
+
+Options:
+ -h Print this help and exit.
+ -y Do not ask for confirmation, but submit immediately.
+ -u <URL> CTAN URL to upload to.
+ -U <name> CTAN server to upload to, either 'dante' or 'uktug'.
+ -F <file> Read data from file
+ -f Force upload even if input seems incorrect (unknown license etc.).
+ -p Prompt for missing values. (default if run in terminal)
+ -P Do not prompt for missing values. (default if not run in terminal)
+ -v Verbose mode.
+ -q Quiet mode.
+ -V Print version number.
+
+The following fields exists and can be given as
+--<name>=<value>, --<name> <value>, --<name>-file=<file>, --<name>-file <file>
+or as environment variables: CTAN_<NAME>, CTAN_<name>, <NAME> or <name>.
+
+ contribution Name of your contribution
+ version Version number
+ name Your name
+ email Your email
+ summary Summary description
+ directory Suggested CTAN directory
+ DoNotAnnounce No need to announce this update
+ announce Short description for announcement
+ notes Optional notes to the CTAN maintainers
+ license License type
+ freeversion Which free license
+ file File to upload
+
+Valid license types:
+ free Free
+ nocommercial Nocommercial
+ nosell Nosell
+ nosource Nosource
+ shareware Shareware
+ artistic Perl Artistic (Clarified or later)
+ other-nonfree Other nonfree License
+
+Valid free license:
+ apache2 Apache License v2.0
+ artistic Perl Artistic License (version 2)
+ fdl GNU Free Documentation License
+ gfl GUST Font License
+ gpl GNU General Public License
+ lgpl Lesser GPL
+ lppl LaTeX Project
+ ofl Open Font License
+ pd Public Domain
+ other-free Other Free
+
diff --git a/Master/texmf-dist/doc/support/ctanupload/ctanupload.pdf b/Master/texmf-dist/doc/support/ctanupload/ctanupload.pdf
new file mode 100644
index 00000000000..7e4930d7fdc
--- /dev/null
+++ b/Master/texmf-dist/doc/support/ctanupload/ctanupload.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/support/ctanupload/ctanupload.tex b/Master/texmf-dist/doc/support/ctanupload/ctanupload.tex
new file mode 100644
index 00000000000..79d266062a8
--- /dev/null
+++ b/Master/texmf-dist/doc/support/ctanupload/ctanupload.tex
@@ -0,0 +1,192 @@
+\documentclass{ydoc}
+
+\title{The \textsf{ctanupload} script}
+\author{Martin Scharrer}
+\email{martin@scharrer.me}
+\date{Version v1.1 -- 2011/09/06}
+
+\providecommand\envvar{\texttt}
+
+\makeatletter
+\define@Macro@handler\DescribeScript{}
+\makeatother
+
+\begin{document}
+\maketitle
+\begin{abstract}
+ This Perl script allows the uploads of a contribution to CTAN from the command line.
+ It is intended to simplify the release process for LaTeX package authors.
+\end{abstract}
+
+\section{Introduction}
+The Comprehensive TeX Archive Network (CTAN) is the place to get materials related to the \TeX\ typesetting system.
+It provides an web form to upload contributions, like \LaTeX\ packages, to one of the main servers
+\url{http://dante.ctan.org/upload} (DANTE server, German TeX users group) or
+\url{http://www.tex.ac.uk/upload/} (UK-TUG server, UK TeX users group).
+The third main server \url{http://tug.ctan.org/} (TUG, US and International TeX users group) currently does not accept uploads.
+After uploading the contribution to one of these servers it will be distributed to the CTAN mirrors where it can be downloaded by other users.
+
+The \texttt{ctanupload} script allows to automate these uploads which is from benefit for \LaTeX\ package authors which
+write and maintain a larger number of packages. The script is designed to be used from the command line or from a Makefile or other script
+in a full or semi-automatic way. Constant data like the package and author names can be passed automatically to the script while the
+variable fields like the version number or announcement text can be entered manually.
+
+The script first collects the required data, applies some sanity checks before it is displayed again for confirmation.
+If the data is correct it is uploaded and the status and response from the CTAN upload server is printed.
+
+\section{Usage}
+\DescribeScript{ctanupload}<options>~'--'<name>'='<value>~!\ldots!
+\DescribeScript{ctanupload}<options>~'--'<name>~<value>~!\ldots!
+\DescribeScript{ctanupload}<options>~'--'<name>'-file='<file with value>~!\ldots!
+\DescribeScript{ctanupload}<options>~'--'<name>'-file'~<file with value>~!\ldots!
+
+The script accepts single letter options and awaits the upload form fields as double slash arguments.
+These fields can also be read from text files or given using environment variables in the form
+\MacroArgs'CTAN_'<NAME>, \MacroArgs'CTAN_'<name>, \MacroArgs<NAME> or \MacroArgs<name>\relax (in this order).
+The support of environment variable simplifies the usage inside Makefiles.
+
+All arguments can also be given using the \envvar{CTANUPLOAD} environment variable which are processed first, so that
+explicit arguments will overwrite them.
+
+\subsubsection*{Options}
+The following options control the behaviour of the script. They can also be grouped together, i.e.\ a single dash
+followed by multiple options.
+
+\par\medskip\par\noindent
+\begin{tabular}{>{\ttfamily}ll}
+\toprule
+ \normalfont Option & Description \\
+\midrule
+ -h & Print this help and exit.\\
+ -y & Do not ask for confirmation, but submit immediately.\\
+ -u <URL> & CTAN URL to upload to.\\
+ -U <name> & CTAN server to upload to, either 'dante' or 'uktug'.\\
+ -F <file> & Read all data from file. (See below)\\
+ -f & Force upload even if input seems incorrect (unknown license etc.).\\
+ -p & Prompt for missing values.\\
+ -P & Do not prompt for missing values. (default)\\
+ -v & Verbose mode. (Passed to the underlying WWW Perl module)\\
+ -q & Quiet mode. (Passed to the underlying WWW Perl module)\\
+ -V & Print version number.\\
+\bottomrule
+\end{tabular}
+
+\subsubsection*{Fields}
+The following fields exists in the CTAN upload form. At least the ones marked as mandatory must be provided.
+\par\medskip\par\noindent
+\begin{tabular}{>{\ttfamily}llc}
+\toprule
+ \normalfont Field & Description & Mandatory \\
+\midrule
+ contribution & Name of your contribution & * \\
+ version & Version number & *\\
+ name & Your name & *\\
+ email & Your email & *\\
+ summary & Summary description & *\\
+ directory & Suggested CTAN directory\\
+ DoNotAnnounce & No need to announce this update\\
+ announce & Short description for announcement\\
+ notes & Optional notes to the CTAN maintainers\\
+ license & License type (see below) & *\\
+ freeversion & Which free license (see below)\\
+ file & File to upload & *\\
+\bottomrule
+\end{tabular}
+
+\subsubsection*{Valid license types}
+The \texttt{license} field can have the following values to indicate the license type:
+\par\medskip\par\noindent
+\begin{tabular}{>{\ttfamily}ll}
+\toprule
+ \normalfont License Type & Description \\
+\midrule
+ free & Free\\
+ nocommercial & Nocommercial\\
+ nosell & Nosell\\
+ nosource & Nosource\\
+ shareware & Shareware\\
+ artistic & Perl Artistic (Clarified or later)\\
+ other-nonfree & Other nonfree License\\
+\bottomrule
+\end{tabular}
+
+\subsubsection*{Valid free licenses}
+If a free license was choosen using \texttt{license=free}
+the specific free license can be selected using the \texttt{freeversion} field which
+can have one of the following values:
+
+\par\medskip\par\noindent
+\begin{tabular}{>{\ttfamily}ll}
+\toprule
+ \normalfont License Type & Description \\
+\midrule
+ apache2 & Apache License v2.0\\
+ artistic & Perl Artistic License (version 2)\\
+ fdl & GNU Free Documentation License\\
+ gfl & GUST Font License\\
+ gpl & GNU General Public License\\
+ lgpl & Lesser GPL\\
+ lppl & LaTeX Project\\
+ ofl & Open Font License\\
+ pd & Public Domain\\
+ other-free & Other Free\\
+\bottomrule
+\end{tabular}
+
+\section{Examples}
+
+\def\example#1{\par\medskip\par\noindent\textbf{#1}\par}
+\lstset{numbers=none,basicstyle=\ttfamily\small}
+
+\example{Interactive mode (prompt for all values not read from environment variables):}
+\begin{lstlisting}
+ctanupload -p
+\end{lstlisting}
+
+\example{Fill complete form:}
+\begin{lstlisting}
+ctanupload --contribution=somepackage --version=v0.1 \
+ --name "John Doe" --email=john@doe.com \
+ --summary "New package to do something." \
+ --directory=/macros/latex/contrib/somepackage \
+ --DoNotAnnounce=0 \
+ --announce "This package allows to ..." \
+ --notes "Some note to the CTAN admins (if required)" \
+ --license=free --freeversion=lppl
+ --file=somepackage.tar.gz
+\end{lstlisting}
+
+\example{Use of environment variables:}
+\noindent
+The environment variables can be given in the command line or in a user specific configuration file
+which is read by the shell (e.g.\ \texttt{~/.bashrc} for the Bash shell).
+Shown here is the Bash shell syntax, which is the common shell for Linux.
+The static author data is given as environment variables and the contribution name as argument, while
+the script will prompt the user for the rest.
+
+\par\noindent
+\begin{lstlisting}
+export CTAN_NAME="John Doe"
+export CTAN_EMAIL="john@doe.com"
+ctanupload --contribution=somepackage -p
+\end{lstlisting}
+
+\example{Read date from file:}
+\noindent
+Here the announcement text is read from a file \texttt{announcement.txt} while the script will prompt the user
+for the rest of the fields.
+
+\par\noindent
+\begin{lstlisting}
+ctanupload --announce-file announcement.txt -p
+\end{lstlisting}
+
+
+\example{Example Makefile:}
+\noindent
+The following Makefile (see \url{http://www.gnu.org/software/make/manual/make.html}) uses the \texttt{ctanify} script (\url{http://www.ctan.org/pkg/ctanify})
+to create a compressed file for submission using \texttt{ctanupload}.
+
+\lstinputlisting{Makefile.example}
+
+\end{document}
diff --git a/Master/texmf-dist/scripts/ctanupload/ctanupload.pl b/Master/texmf-dist/scripts/ctanupload/ctanupload.pl
new file mode 100644
index 00000000000..70bb018217e
--- /dev/null
+++ b/Master/texmf-dist/scripts/ctanupload/ctanupload.pl
@@ -0,0 +1,450 @@
+#!/usr/bin/perl
+################################################################################
+# Copyright (c) 2011 Martin Scharrer <martin@scharrer-online.de>
+# This is open source software under the GPL v3 or later.
+################################################################################
+use strict;
+use warnings;
+
+sub fromenv;
+sub load_data;
+sub save_data;
+
+my $VERSION = 'v1.1';
+my %CTAN_SERVERURLS = (
+ dante => 'http://dante.ctan.org/upload.html',
+ de => 'http://dante.ctan.org/upload.html',
+ uktug => 'http://www.tex.ac.uk/upload/',
+ 'uk-tug' => 'http://www.tex.ac.uk/upload/',
+ uk => 'http://www.tex.ac.uk/upload/',
+ cambridge => 'http://www.tex.ac.uk/upload/',
+);
+my $CTAN_URL = $CTAN_SERVERURLS{dante};
+
+my @FIELDS = qw(contribution version name email summary directory DoNotAnnounce announce notes license freeversion file);
+my @REQUIRED = qw(contribution version name email summary license file);
+my %FIELDS = map { $_ => fromenv($_) } @FIELDS;
+
+
+my %FIELDS_DESC = (
+ contribution => 'Name of your contribution',
+ version => 'Version number',
+ name => 'Your name',
+ email => 'Your email',
+ summary => 'Summary description',
+ directory => 'Suggested CTAN directory',
+ DoNotAnnounce => 'No need to announce this update',
+ announce => 'Short description for announcement',
+ notes => 'Optional notes to the CTAN maintainers',
+ license => 'License type',
+ freeversion => 'Which free license',
+ file => 'File to upload',
+);
+
+my @LICENSES = qw( free nocommercial nosell nosource shareware artistic other-nonfree);
+
+my %LICENSES = (
+ free => 'Free',
+ nocommercial => 'Nocommercial',
+ nosell => 'Nosell',
+ nosource => 'Nosource',
+ shareware => 'Shareware',
+ artistic => 'Perl Artistic (Clarified or later)',
+ 'other-nonfree' => 'Other nonfree License',
+);
+
+my @FREEVERSIONS = qw( apache2 artistic fdl gfl gpl lgpl lppl ofl pd other-free);
+
+my %FREEVERSIONS = (
+ apache2 => 'Apache License v2.0',
+ artistic => 'Perl Artistic License (version 2)',
+ fdl => 'GNU Free Documentation License',
+ gfl => 'GUST Font License',
+ gpl => 'GNU General Public License',
+ lgpl => 'Lesser GPL',
+ lppl => 'LaTeX Project',
+ ofl => 'Open Font License',
+ pd => 'Public Domain',
+ 'other-free' => 'Other Free',
+);
+
+my $QUIET = 0;
+my $ASK = 1;
+my $FORCE = 0;
+my $PROMPT = -t STDIN ? 1 : 0;
+
+sub usage {
+ my $warn = shift;
+ if ($warn) {
+ print STDERR "Unknown option '$warn'\n";
+ }
+ print STDERR <<"EOT";
+ctanupload script $VERSION
+Uploads a contribution to CTAN.
+
+Usage:
+ctanupload <options> --<name>=<value>
+
+Arguments can also be given using the CTANUPLOAD environment variable which are processed first, so that
+explicit arguments will overwrite them.
+
+Options:
+ -h Print this help and exit.
+ -y Do not ask for confirmation, but submit immediately.
+ -u <URL> CTAN URL to upload to.
+ -U <name> CTAN server to upload to, either 'dante' or 'uktug'.
+ -F <file> Read data from file
+ -f Force upload even if input seems incorrect (unknown license etc.).
+ -p Prompt for missing values. (default if run in terminal)
+ -P Do not prompt for missing values. (default if not run in terminal)
+ -v Verbose mode.
+ -q Quiet mode.
+ -V Print version number.
+
+The following fields exists and can be given as
+--<name>=<value>, --<name> <value>, --<name>-file=<file>, --<name>-file <file>
+or as environment variables: CTAN_<NAME>, CTAN_<name>, <NAME> or <name>.
+
+EOT
+
+ foreach my $field (@FIELDS) {
+ printf STDERR " %15s %s\n", $field, $FIELDS_DESC{$field};
+ }
+
+ printf STDERR "\nValid license types:\n";
+ for my $license (@LICENSES) {
+ printf STDERR " %15s %s\n", $license, $LICENSES{$license};
+ }
+
+ printf STDERR "\nValid free license:\n";
+ for my $license (@FREEVERSIONS) {
+ printf STDERR " %15s %s\n", $license, $FREEVERSIONS{$license};
+ }
+
+ exit ($warn ? 1 : 0);
+}
+
+if (exists $ENV{'CTANUPLOAD'}) {
+ unshift @ARGV, (split /\s+/, $ENV{'CTANUPLOAD'});
+}
+
+while (my $arg = shift @ARGV) {
+ if ($arg =~ /^--(.*?)(?:=(.*))?$/) {
+ my $name = $1;
+ my $value = defined $2 ? $2 : shift @ARGV;
+ my $file;
+ if ($name =~ /(.*)-file$/) {
+ $name = $1;
+ $file = $value;
+ }
+ if (exists $FIELDS{$name}) {
+ if ($file) {
+ if (open (my $valfile, '<', $file)) {
+ $value = join '', <$valfile>;
+ close ($valfile);
+ }
+ else {
+ warn "Couldn't read file '$file'!\n";
+ $value = '';
+ }
+ }
+ $FIELDS{$name} = $value;
+ }
+ else {
+ usage('--' . $name . ($file ? '-file' : ''));
+ }
+ }
+ elsif ($arg =~ /^-([a-z]+)$/i) {
+ for my $char (split //, $1) {
+ if ($char eq 'h') {
+ usage(0);
+ }
+ elsif ($char eq 'q') {
+ $QUIET = 1;
+ }
+ elsif ($char eq 'v') {
+ $QUIET = 0;
+ }
+ elsif ($char eq 'y') {
+ $ASK = 0;
+ }
+ elsif ($char eq 'F') {
+ my $file = shift @ARGV;
+ load_data ($file);
+ }
+ elsif ($char eq 'f') {
+ $FORCE = 1;
+ }
+ elsif ($char eq 'p') {
+ $PROMPT = 1;
+ }
+ elsif ($char eq 'P') {
+ $PROMPT = 0;
+ }
+ elsif ($char eq 'u') {
+ $CTAN_URL = shift @ARGV;
+ }
+ elsif ($char eq 'U') {
+ my $server = lc shift @ARGV;
+ if (not exists $CTAN_SERVERURLS{ $server }) {
+ die "Error: Unknown CTAN server '$server'.\n";
+ }
+ $CTAN_URL = $CTAN_SERVERURLS{ $server };
+ }
+ elsif ($char eq 'V') {
+ print STDERR "ctanupload script $VERSION.\n";
+ exit (0);
+ }
+ else {
+ usage('-' . $char);
+ }
+ }
+ }
+ else {
+ usage($arg);
+ }
+}
+
+PROMPT:
+
+if ($PROMPT) {
+ foreach my $field (@FIELDS) {
+ if (!defined $FIELDS{$field} || !length $FIELDS{$field}) {
+ my $input = '';
+ if ($field eq 'notes' || $field eq 'announce') {
+ next if $field eq 'announce' and $FIELDS{DoNotAnnounce};
+ print "\u$FIELDS_DESC{$field}: (press CTRL-Z (Windows) or CTRL-D (Linux) to stop)\n";
+ while (<STDIN>) {
+ $input .= $_;
+ }
+ }
+ elsif ($field eq 'DoNotAnnounce') {
+ print "\uNo need to announce upload? [y/N]: ";
+ $input = <STDIN>;
+ }
+ elsif ($field eq 'license') {
+ print "\u$FIELDS_DESC{$field}:\n";
+ my $num = 1;
+ foreach my $license (@LICENSES) {
+ printf " [%d] %s\n", $num++, $LICENSES{$license};
+ }
+ print "Selection: ";
+ $input = lc (<STDIN> || '');
+ if ($input =~ /^\s*(\d+)\s*$/) {
+ $input = $LICENSES[$1-1];
+ }
+ }
+ elsif ($field eq 'freeversion') {
+ next if $FIELDS{license} ne 'free';
+ print "\u$FIELDS_DESC{$field}:\n";
+ my $num = 1;
+ foreach my $license (@FREEVERSIONS) {
+ printf " [%d] %s\n", $num++, $FREEVERSIONS{$license};
+ }
+ print "Selection: ";
+ $input = lc (<STDIN> || '');
+ if ($input =~ /^\s*(\d+)\s*$/) {
+ $input = $FREEVERSIONS[$1-1];
+ }
+ }
+ else {
+ print "\u$FIELDS_DESC{$field}: ";
+ $input = <STDIN>;
+ }
+ $input = '' if not defined $input;
+ chomp $input;
+ $input =~ s/^\s+//;
+ $input =~ s/\s+$//;
+ $FIELDS{$field} = $input;
+ }
+ }
+}
+
+my $abort = 0;
+foreach my $required (@REQUIRED) {
+ if (!length $FIELDS{$required}) {
+ print "Required field '$required' is missing!\n";
+ $abort++;
+ }
+}
+if (not exists $LICENSES{ $FIELDS{license} }) {
+ print "Unknown license type '$FIELDS{license}'!\n";
+ $abort++ if not $FORCE;
+}
+if ($FIELDS{license} ne 'free') {
+ $FIELDS{freeversion} = '-not-selected-';
+} elsif (!$FIELDS{freeversion}) {
+ print "Required field 'freeversion' is missing!\n";
+ $abort++;
+} elsif (not exists $FREEVERSIONS{ $FIELDS{freeversion} }) {
+ print "Unknown free license '$FIELDS{freeversion}'!\n";
+ $abort++ if not $FORCE;
+}
+if ($FIELDS{file} && ! -f $FIELDS{file}) {
+ print "File '$FIELDS{file}' not found!\n";
+ $abort++;
+}
+if ($abort) {
+ print "Aborting!\n";
+ exit (2);
+}
+
+my $DoNotAnnounce;
+if ($FIELDS{DoNotAnnounce}) {
+ $FIELDS{DoNotAnnounce} = 'No';
+ $DoNotAnnounce = '[x]';
+}
+else {
+ $FIELDS{DoNotAnnounce} = undef;
+ $DoNotAnnounce = '[ ]';
+}
+
+if (!$FIELDS{directory}) {
+ $FIELDS{directory} = '/macros/latex/contrib/' . $FIELDS{contribution};
+}
+
+print "\nThe following data will be submitted to CTAN ($CTAN_URL):\n";
+
+foreach my $field (@FIELDS) {
+ if ($field eq 'DoNotAnnounce') {
+ print "$FIELDS_DESC{$field}: $DoNotAnnounce\n";
+ }
+ elsif ($field eq 'license') {
+ print "$FIELDS_DESC{$field}: $LICENSES{$FIELDS{$field}}\n";
+ }
+ elsif ($field eq 'freeversion') {
+ print "$FIELDS_DESC{$field}: $FREEVERSIONS{$FIELDS{$field}}\n";
+ }
+ else {
+ print "$FIELDS_DESC{$field}: $FIELDS{$field}\n";
+ }
+}
+
+if ($ASK) {
+ print "\nUpload? [(y/N/(e)dit/(s)ave] ";
+ my $response = lc <STDIN>;
+ chomp ($response);
+
+ unless ($response eq 'y' or $response eq 'yes') {
+ if ($response eq 'e' or $response eq 'edit') {
+ my $file = 'ctanupload.dat';
+ save_data($file);
+ if (not defined $ENV{EDITOR}) {
+ print "No EDITOR environment variable defined.\n";
+ print "Data was stored in file '$file'. Please edit manually and load with the -F option.\n";
+ exit (1);
+ }
+ else {
+ system($ENV{EDITOR}, $file);
+ load_data($file);
+ goto PROMPT;
+ }
+ }
+ elsif ($response eq 's' or $response eq 'save') {
+ my $file = 'ctanupload.dat';
+ save_data($file);
+ print "Data was stored in file '$file'.\n";
+ exit (2);
+ }
+ else {
+ print "\nUpload aborted!\n";
+ exit (1);
+ }
+ }
+}
+
+
+use WWW::Mechanize;
+my $mech = WWW::Mechanize->new(quiet => $QUIET, autocheck => 1);
+
+print "Accessing CTAN upload page ...\n";
+$mech->get( $CTAN_URL );
+print "Uploading ...\n";
+$mech->submit_form(
+ form_number => 1,
+ fields => \%FIELDS,
+);
+
+if ($mech->success()) {
+ print "Upload successfull!\n";
+}
+else {
+ print "Upload failed: ", $mech->response()->message(), "\n";
+}
+
+print "\nResponse:\n";
+eval {
+ use HTML::TreeBuilder;
+ use HTML::FormatText;
+ my $tree = HTML::TreeBuilder->new_from_content( $mech->content() );
+ my $formatter = HTML::FormatText->new(leftmargin => 0, rightmargin => 80);
+ my @response = split /\n/, $formatter->format($tree);
+ local $, = "\n";
+ print @response[3..$#response-3];
+} or do {
+ print "Can't display HTML response, storing reponse if log file 'ctanupload_response.html'\n";
+ open (LOG, '>', 'ctanupload_response.html');
+ print LOG $mech->content();
+ close (LOG);
+};
+
+exit (0);
+
+
+sub fromenv {
+ my $name = shift;
+ foreach my $var ('CTAN_' . uc $name, uc $name, 'CTAN_' . $name, $name) {
+ return $ENV{$var} if exists $ENV{$var};
+ }
+ return undef;
+}
+
+sub load_data {
+ my $file = shift;
+ open (my $load, '<', $file) or die "Couldn't open data file '$file'!\n";
+ LOAD_LOOP:
+ while (my $line = <$load>) {
+ if ($line =~ /^([a-z]+)\s*=\s*(.*)$/i) {
+ my ($name,$value) = ($1,$2);
+ if (!exists $FIELDS{$name}) {
+ print STDERR "Ignoring unknown variable '$name' from file '$file' (line $.)!\n";
+ next;
+ }
+ $FIELDS{$name} = $value;
+ if ($name eq 'announce' || $name eq 'notes') {
+ $FIELDS{$name} .= "\n";
+ while ($line = <$load>) {
+ last if ($line =~ /^[a-z]+\s*=/i);
+ $FIELDS{$name} .= $line;
+ }
+ $FIELDS{$name} =~ s/^[\s\n]+//;
+ $FIELDS{$name} =~ s/[\s\n]+$//;
+ redo LOAD_LOOP if not eof $load;
+ }
+ }
+ else {
+ print STDERR "Ignoring incorrect line '$line' from file '$file' (line $.)!\n";
+ }
+ }
+ close ($load);
+}
+
+sub save_data {
+ my $file = shift;
+ $file = 'ctanupload.dat' if not defined $file;
+ open (my $save, '>', $file) or do { warn "Couldn't save data to file '$file'!\n"; return; };
+ foreach my $field (@FIELDS) {
+ if ($field eq 'DoNotAnnounce') {
+ print {$save} "$field = ", $FIELDS{DoNotAnnounce} ? '1' : '0', "\n";
+ }
+ else {
+ print {$save} "$field = ", $FIELDS{$field} || '', "\n";
+ }
+ }
+ close ($save);
+ return;
+}
+
+
+
+__END__
diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check
index 7e034926afb..959085401c4 100755
--- a/Master/tlpkg/bin/tlpkg-ctan-check
+++ b/Master/tlpkg/bin/tlpkg-ctan-check
@@ -110,7 +110,7 @@ my @TLP_working = qw(
courier-scaled courseoutline coursepaper coverpage covington
cprotect
crop crossreference crossword crosswrd cryst csbulletin
- csquotes csquotes-de csvsimple csvtools ctable ctex ctex-faq
+ csquotes csquotes-de csvsimple csvtools ctanupload ctable ctex ctex-faq
cursolatex cuisine
currfile currvita curve curve2e curves
custom-bib cutwin cv cweb-latex cyklop cyrillic
diff --git a/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc
index f39e8506e70..91fb59a5c27 100644
--- a/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc
+++ b/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc
@@ -11,6 +11,7 @@ depend bibtex8
depend bibtexu
depend bundledoc
depend chktex
+depend ctanupload
depend ctie
depend cweb
depend de-macro
diff --git a/Master/tlpkg/tlpsrc/ctanupload.tlpsrc b/Master/tlpkg/tlpsrc/ctanupload.tlpsrc
new file mode 100644
index 00000000000..56e0d45eb0b
--- /dev/null
+++ b/Master/tlpkg/tlpsrc/ctanupload.tlpsrc
@@ -0,0 +1 @@
+binpattern f bin/${ARCH}/ctanupload