1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
#!/usr/bin/env perl
#
# Originally written by T.M.Trzeciak in 2010
#
# Purpose: create/update a local package repository
# How to use: place it tlpkg/installer and run
#
our $Master;
our $location;
BEGIN {
$^W = 1;
$Master = __FILE__;
$Master =~ s;\\;/;g if ($^O =~ /^MSWin/i);
$Master =~ s;[^/]*$;../..; unless ($Master =~ s;(/[^/]*){3,3}$;;);
unshift (@INC, "$Master/tlpkg");
$::installerdir = $Master;
$::localrepo = $Master;
# $::localrepo = '.';
# $Master = $ENV{"TLINSTALLERDIR"};
# print "$Master\n";
}
use TeXLive::TLPDB;
use TeXLive::TLPOBJ;
use TeXLive::TLConfig;
use TeXLive::TLUtils;
use TeXLive::TLDownload;
use Getopt::Long;
use Pod::Usage;
use File::Path;
use Cwd;
TeXLive::TLUtils::process_logging_options();
my $opt_location;
my $opt_destination;
my $opt_persistent_downloads = 1;
my $opt_help = 0;
GetOptions(
"location|url|repository|repo=s" => \$opt_location,
# "destination=s" => \$opt_destination,
"persistent-downloads!" => \$opt_persistent_downloads,
"h|help|?" => \$opt_help) or pod2usage(1);
if ($opt_help) {
my @noperldoc = ("-noperldoc", "1") if ($^O =~ /^MSWin/i);
pod2usage(-exitstatus => 0, -verbose => 2, @noperldoc);
}
exit(&main());
sub main {
if ( !setup_programs( "$::installerdir/$InfraLocation/installer",
TeXLive::TLUtils::platform() ) ) {
die "$0: failed to set up necessary programs.\n";
}
if ($opt_persistent_downloads) {
TeXLive::TLUtils::setup_persistent_downloads() ;
}
$location = defined($opt_location) ? $opt_location :
TeXLive::TLUtils::give_ctan_mirror();
if (!defined($location)) {
die("$0: failed to obtain repository location.\n");
}
$::localrepo = $opt_destination if defined($opt_destination);
if ( $location eq $::localrepo ) {
die "destination and remote repository cannot be the same: $location";
}
info("Cloning package repository from $location\n");
$::archivedir = "__ARCHIVE__";
if (-d "$::localrepo/$Archive") {
rename("$::localrepo/$Archive", "$::localrepo/$::archivedir") ||
die "unable to rename $::localrepo/$Archive to $::archivedir: $!";
}
if (!-d "$::localrepo/$::archivedir") {
mkdir("$::localrepo/$::archivedir") ||
die "$0: could not create directory $::localrepo/$::archivedir: $!";
}
if (!-d "$::localrepo/$InfraLocation" ) {
mkdir("$::localrepo/$InfraLocation") ||
die "$0: cannot create directory $::localrepo/$InfraLocation: $!";
}
my $tlpdbfile = "$InfraLocation/$DatabaseName";
my $tlpdbpacked = "$tlpdbfile.$DefaultContainerFormat";
my $md5there;
download_file("$location/$tlpdbfile.md5", "$::localrepo/$tlpdbfile.md5");
open MD5FILE, "$::localrepo/$tlpdbfile.md5" or
die "cannot open $::localrepo/$tlpdbfile.md5: $!";
if (read (MD5FILE, $md5there, 32) != 32) {
die "cannot download remote TeX Live database from $location.\n";
}
close MD5FILE;
my $md5here = (!-r "$::localrepo/$tlpdbfile") ? "" :
TeXLive::TLUtils::tlmd5("$::localrepo/$tlpdbfile");
# debug("md5 hash mismatch\n") if ($md5there ne $md5here);
if ($md5there ne $md5here) {
download_file("$location/$tlpdbpacked", "$::localrepo/$tlpdbpacked");
if ( system("$::progs{'xzdec'} <\"$::localrepo/$tlpdbpacked\" >\"$::localrepo/$tlpdbfile\"") ) {
die "cannot decompress $::localrepo/$tlpdbpacked\n";
}
}
my $tlpdb = TeXLive::TLPDB->new ("root" => $::localrepo);
if ( !defined($tlpdb) ) {
die "unusable repository database at $location\n";
}
my $error_count = 0;
for my $pkgname ($tlpdb->list_packages) {
next if $pkgname =~ /^00texlive/;
my $tlp = $tlpdb->get_package($pkgname);
$error_count += get_container("$pkgname", $tlp->containermd5() );
$error_count += get_container("$pkgname.doc", $tlp->doccontainermd5() )
if ($tlp->docfiles());
$error_count += get_container("$pkgname.source", $tlp->srccontainermd5() )
if ($tlp->srcfiles());
}
if ($error_count == 0) {
rename("$::localrepo/$::archivedir", "$::localrepo/$Archive") ||
die "unable to rename $::localrepo/$::archivedir to $Archive: $!";
print("Pacakge repository cloning finished successfully.\n");
return 0;
} else {
print("Pacakge repository cloning finished with errors.\n");
print("Rerunning again might fix the problems.\n");
return 1;
}
sub get_container {
my ($pkgname, $md5there) = @_;
my $pkgcontainerfile = "$pkgname.$DefaultContainerExtension";
my $localfile = "$::localrepo/$::archivedir/$pkgcontainerfile";
my $remotefile = "$location/$Archive/$pkgcontainerfile";
if (!-r "$localfile" ||
TeXLive::TLUtils::tlmd5("$localfile") ne $md5there ) {
print("downloading $pkgname\n");
download_file("$remotefile", "$localfile");
# check downloaded file
my $md5here = TeXLive::TLUtils::tlmd5("$localfile");
if ($md5here ne $md5there) {
warn("md5 sum mismatch for package $pkgname:
database: $md5there
dowloaded: $md5here\n");
return 1;
}
return 0;
}
# info("package container up to date: $pkgcontainerfile\n");
print("skipping $pkgname\n");
return 0;
}
}
__END__
=head1 NAME
download-package-repository - creates a local package repository
=head1 SYNOPSIS
download-package-repository [OPTION]...
=head1 OPTIONS
=item B<-repository> I<url|path>
=item B<-persistent-downloads>
=item B<-no-persistent-downloads>
See the tlmgr documentation (L<http://tug.org/texlive/tlmgr.html>) for
information.
The standard options B<-help> and B<-q>, B<-v>, and
B<-logfile>=I<file> are accepted too; see the C<process_logging_options>
function in L<TeXLive::TLUtils> for details.
=head1 DESCRIPTION
This script is useful particularly on unstable Internet connections to
pre-download all packages before doing an installation.
In general,it creates or updates a local package repository (within the
TL installer directories). The resulting local repository will be
picked up automatically by the installer as a default one. The new
repository is not enabled untill all packages have been downloaded and
verified.
If the download is interrupted for any reason, just rerun this script
again to complete it. It will pick upwhere it left off.
=head1 AUTHORS AND COPYRIGHT
This script and its documentation were written for the TeX Live
distribution (L<http://tug.org/texlive>) and both are licensed under the
GNU General Public License Version 2 or later.
=cut
|