From 2559ab32acfcf160257c8a7c85c968e7dd58b589 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Thu, 12 Jul 2007 09:38:09 +0000 Subject: the road to new texdoc handling: - allow tags "details" and "language" for docfiles - allow catalogue-* keys in a TLPOBJ file - TLPOBJ.pm: add update_from_catalogue which updates some information - adapt the tlpsrc2tlpdb script to take another argument -catalogue in which case the database is build with catalogue information included git-svn-id: svn://tug.org/texlive/trunk@4568 c570f23f-e606-0410-a88d-b1316a301751 --- Master/tlpkg/TeXLive/TLPDB.pm | 20 ++-- Master/tlpkg/TeXLive/TLPOBJ.pm | 185 +++++++++++++++++++++++++++++------ Master/tlpkg/TeXLive/TLPSRC.pm | 2 +- Master/tlpkg/TeXLive/TLTREE.pm | 12 +-- Master/tlpkg/TeXLive/TLUtils.pm | 2 +- Master/tlpkg/TeXLive/TeXCatalogue.pm | 177 +++++++++++++++++++++++++++++++-- 6 files changed, 342 insertions(+), 56 deletions(-) (limited to 'Master/tlpkg/TeXLive') diff --git a/Master/tlpkg/TeXLive/TLPDB.pm b/Master/tlpkg/TeXLive/TLPDB.pm index 5d4d146957b..cc426df6dcb 100644 --- a/Master/tlpkg/TeXLive/TLPDB.pm +++ b/Master/tlpkg/TeXLive/TLPDB.pm @@ -245,11 +245,11 @@ sub _generate_listfile { } elsif ($tlp->category eq "Scheme") { print TMP "*Title: ", $tlp->shortdesc, "\n"; my $s = 0; - # schemes size includes ONLY those packages which are directly - # included and direclty included files, not the size of the - # included collections. But if a package is included in one of - # the called for collections AND listed directly, we don't want - # to count its size two times + # schemes size includes ONLY those packages which are directly + # included and direclty included files, not the size of the + # included collections. But if a package is included in one of + # the called for collections AND listed directly, we don't want + # to count its size two times my (@inccol,@incpkg,@collpkg); # first we add all the packages tlps that are directly included @incpkg = @lop; @@ -265,11 +265,11 @@ sub _generate_listfile { } # finally go through all packages and add the ->total_size foreach my $p (@incpkg) { - if (!TeXLive::TLUtils::member($p,@collpkg)) { - $s += $self->get_package($p)->total_size; - } + if (!TeXLive::TLUtils::member($p,@collpkg)) { + $s += $self->get_package($p)->total_size; + } } - $s += $tlp->runsize + $tlp->srcsize + $tlp->docsize; + $s += $tlp->runsize + $tlp->srcsize + $tlp->docsize; print TMP "*Size: $s\n"; } # dependencies and inclusion of packages @@ -346,4 +346,4 @@ GNU General Public License Version 2 or later. ### tab-width: 2 ### indent-tabs-mode: nil ### End: -# vim:set tabstop=2: # +# vim:set tabstop=2 expandtab: # diff --git a/Master/tlpkg/TeXLive/TLPOBJ.pm b/Master/tlpkg/TeXLive/TLPOBJ.pm index 814c2d7d314..425bdcd480f 100644 --- a/Master/tlpkg/TeXLive/TLPOBJ.pm +++ b/Master/tlpkg/TeXLive/TLPOBJ.pm @@ -8,10 +8,13 @@ package TeXLive::TLPOBJ; use TeXLive::TLUtils; +use TeXLive::TeXCatalogue; use File::Path; use Cwd; use TeXLive::TLTREE; use FileHandle; +use Text::ParseWords; +use File::Basename; my $_tmp; my $_zipdir; @@ -37,6 +40,7 @@ sub new { binsize => defined($params{'binsize'}) ? $params{'binsize'} : {}, depends => defined($params{'depends'}) ? $params{'depends'} : [], revision => $params{'revision'}, + cataloguedata => defined($params{'cataloguedata'}) ? $params{'cataloguedata'} : {}, }; $_zipdir = $params{'zipdir'} if defined($params{'zipdir'}); bless $self, $class; @@ -61,7 +65,6 @@ sub from_fh { while (my $line = $fh->getline) { &TeXLive::TLUtils::debug("reading line: >>>$line<<<\n"); - &TeXLive::TLUtils::debug("multi=...$multi...\n"); $line =~ /^\s*#/ && next; # skip comment lines if ($line =~ /^\s*$/) { if (!$started) { next; } @@ -135,7 +138,24 @@ sub from_fh { $self->{"${type}size"} = $size; } next; - } elsif ($line =~ /^(doc|src|run)filescontinued\s+(.*)$/) { + } elsif ($line =~ /^docfilescontinued\s+(.*)$/) { + # docfiles can have tags + my @words = "ewords('\s+', 0, "$1"); + # the first entry is the file + my $f = shift @words; + push @{$self->{'docfiles'}}, $f; + while (@words) { + $_ = shift @words; + if (/^details=(.*)$/) { + $self->{'docfiledata'}{$f}{'details'} = "$1"; + } elsif (/^language=(.*)$/) { + $self->{'docfiledata'}{$f}{'href'} = "$1"; + } else { + die "Unknown docfile tag: $line"; + } + } + next; + } elsif ($line =~ /^(src|run)filescontinued\s+(.*)$/) { push @{$self->{$1."files"}}, "$2"; next; } elsif ($line =~ /^binfiles\s+/) { @@ -168,6 +188,8 @@ sub from_fh { push @{$self->{'depends'}}, "$2" unless "$2" eq ""; $lastcmd = "depend"; next; + } elsif ($line =~ /^catalogue-([^\s]+)\s+(.*)$/) { + $self->{'cataloguedata'}{$1} = "$2"; } else { die("Unknown directive ...$line... , please fix it!"); } @@ -237,6 +259,7 @@ sub writeout { defined($self->{'revision'}) && print $fd "revision $self->{'revision'}\n"; defined($self->{'catalogue'}) && print $fd "catalogue $self->{'catalogue'}\n"; defined($self->{'shortdesc'}) && print $fd "shortdesc $self->{'shortdesc'}\n"; + defined($self->{'license'}) && print $fd "license $self->{'license'}\n"; if (defined($self->{'longdesc'})) { $_tmp = "$self->{'longdesc'}"; write $fd; @@ -253,8 +276,15 @@ sub writeout { } if (defined($self->{'docfiles'}) && (@{$self->{'docfiles'}})) { print $fd "docfiles size=$self->{'docsize'}\n"; - foreach (sort @{$self->{'docfiles'}}) { - print $fd " $_\n"; + foreach my $f (sort @{$self->{'docfiles'}}) { + print $fd " $f"; + if (defined($self->{'docfiledata'}{$f}{'details'})) { + print $fd ' details="', $self->{'docfiledata'}{$f}{'details'}, '"'; + } + if (defined($self->{'docfiledata'}{$f}{'language'})) { + print $fd ' language="', $self->{'docfiledata'}{$f}{'language'}, '"'; + } + print $fd "\n"; } } if (defined($self->{'srcfiles'}) && (@{$self->{'srcfiles'}})) { @@ -277,6 +307,10 @@ sub writeout { } } } + # writeout all the catalogue keys + foreach my $k (keys %{$self->cataloguedata}) { + print $fd "catalogue-$k ", $self->cataloguedata->{$k}, "\n"; + } } sub writeout_simple { @@ -381,24 +415,24 @@ sub _make_zip { return; } my $cwd = &getcwd; - if ("$destdir" !~ m@^/@) { - # we have an relative zipdir, so we have to make it absolute - $destdir = "$cwd/$destdir"; - } + if ("$destdir" !~ m@^/@) { + # we have an relative zipdir, so we have to make it absolute + $destdir = "$cwd/$destdir"; + } &mkpath("$destdir") if (! -d "$destdir"); chdir($tltree->svnroot); - if ($arch eq "all") { - # we add the .tlpobj into the .tlpobj directory - my $removetlpobjdir = 0; - if (! -d ".tlpobj") { - &mkpath(".tlpobj"); - $removetlpobjdir = 1; - } - open(TMP,">.tlpobj/$self->{'name'}.tlpobj") or die "Cannot create .tlpobj/$self->{'name'}.tlpobj"; - $self->writeout(\*TMP); - close(TMP); - push @files, ".tlpobj/$self->{'name'}.tlpobj"; - } + if ($arch eq "all") { + # we add the .tlpobj into the .tlpobj directory + my $removetlpobjdir = 0; + if (! -d ".tlpobj") { + &mkpath(".tlpobj"); + $removetlpobjdir = 1; + } + open(TMP,">.tlpobj/$self->{'name'}.tlpobj") or die "Cannot create .tlpobj/$self->{'name'}.tlpobj"; + $self->writeout(\*TMP); + close(TMP); + push @files, ".tlpobj/$self->{'name'}.tlpobj"; + } unlink($zipname); print $zipcmd . "$destdir/$zipname" . " > $nul\n" if ($::opt_debug); open ZIP, $zipcmd . "$destdir/$zipname" . " > $nul"; @@ -410,11 +444,11 @@ sub _make_zip { } } @files; close ZIP; - if ($arch eq "all") { - # cleaning up - unlink(".tlpobj/$self->{'name'}.tlpobj"); - rmdir(".tlpobj") if $removetlpobjdir; - } + if ($arch eq "all") { + # cleaning up + unlink(".tlpobj/$self->{'name'}.tlpobj"); + rmdir(".tlpobj") if $removetlpobjdir; + } print "Done $zipname\n" if ($::opt_debug); } @@ -444,6 +478,57 @@ sub total_size { return($ret); } +sub update_from_catalogue { + my ($self, $tlc) = @_; + my $tlcname = defined($self->catalogue) ? $self->catalogue : $self->name; + if (defined($tlc->entries->{$tlcname})) { + my $entry = $tlc->entries->{$tlcname}; + if (defined($entry->license)) { + $self->cataloguedata->{'license'} = $entry->license; + } + if (defined($entry->version)) { + $self->cataloguedata->{'version'} = $entry->version; + } + if (defined($entry->url)) { + $self->cataloguedata->{'url'} = $entry->url; + } + # + # we need to do the following: + # - take the href entry for a documentation file entry in the TC + # - remove the 'ctan:' prefix + # - remove the part + # - match the rest against all docfiles in an intelligent way + # + # Example: + # juramisc.xml contains: + # + # + my @tcdocfiles = keys %{$entry->docs}; + my @tlpdocfiles = $self->docfiles; + foreach my $tcdocfile (@tcdocfiles) { + # basename also kills the ctan: prefix! + my $tcdocfilebasename = $tcdocfile; + # remove the ctan: prefix + $tcdocfilebasename =~ s/^ctan://; + # remove the ctan path if present + my $tcctanpath = $entry->ctan; + $tcdocfilebasename =~ s/^$tcctanpath//; + foreach my $tlpdocfile (@tlpdocfiles) { + if ($tlpdocfile =~ m/$tcdocfilebasename$/) { + # update the language/detail tags if present! + if (defined($entry->docs->{$tcdocfile}{'details'})) { + $self->{'docfiledata'}{$tlpdocfile}{'details'} = $entry->docs->{$tcdocfile}{'details'}; + } + if (defined($entry->docs->{$tcdocfile}{'language'})) { + $self->{'docfiledata'}{$tlpdocfile}{'language'} = $entry->docs->{$tcdocfile}{'language'}; + } + } + } + } + } +} + # # member access functions # @@ -589,6 +674,12 @@ sub zipdir { if (@_) { $_zipdir = $_[0] } return $_zipdir; } +sub cataloguedata { + my $self = shift; + my %ct = @_; + if (@_) { $self->{'cataloguedata'} = \%ct } + return $self->{'cataloguedata'}; +} 1; @@ -623,8 +714,10 @@ files describing a self-contained package. Please see L documentation for the specification. The only differences are that the various C<*pattern> keys are invalid, and instead there are the respective C<*files> keys described below. Furthermore -one more I is allowed, C which specifies the maximum of -all last changed revision of files contained in the package. +some more I is allowed: C which specifies the maximum of +all last changed revision of files contained in the package, and anything +starting with C specifying information coming from the +TeX Catalogue. All these keys have in common that the are followed by a list of files B by one space. They differ only in the first line itself @@ -632,15 +725,32 @@ B by one space. They differ only in the first line itself =over -=item C, C, C +=item C, C each of these three items contains in addition the sum of sizes of the single files (currently in byte, but this may change). srcfiles size=NNNNNN - docfiles size=NNNNNN runfiles size=NNNNNN +=item C + +The docfiles line itself is similar to the C and C lines +above: + + docfiles size=NNNNNN + +But the lines listing the files are allowed to have additional tags: + + /------- excerpt from achemso.tlpobj + |... + |docfiles size=1702468 + | texmf-dist/doc/latex/aeguill/README details="Package Readme" + | texmf-dist/doc/latex/achemso/achemso.pdf details="Package documentation" language="en" + |... + +Currently only the tags C
and C are allowed. + =item C Since C are different for the different architectures one C @@ -685,7 +795,12 @@ For any of the I a function $tlpobj->key is available, which returns the current value when called without an argument, -and sets the respective value when called with an argument. +and sets the respective value when called with an argument. For the +TeX Catalogue Data the function + + $tlpobj->cataloguedata + +returns and takes as argument a hash. Arguments and return values for C, C, C, C, C, C are single scalars. @@ -771,6 +886,12 @@ recomputes the sizes based on the information present in C<$tltree>. recomputes the revision based on the information present in C<$tltree>. +=item C + +adds information from a C object +(currently license, version, url, and updates docfiles with details and +languages tags if present in the Catalogue) + =item C returns 1 if there are C, otherwise 0. @@ -799,7 +920,7 @@ adds or removes files for the given type (only for C, C, C). =head1 SEE ALSO The modules L, L, -L, L. +L, L, L. =head1 AUTHORS AND COPYRIGHT @@ -814,4 +935,4 @@ GNU General Public License Version 2 or later. ### tab-width: 2 ### indent-tabs-mode: nil ### End: -# vim:set tabstop=2: # +# vim:set tabstop=2 expandtab: # diff --git a/Master/tlpkg/TeXLive/TLPSRC.pm b/Master/tlpkg/TeXLive/TLPSRC.pm index 7fdf16a3657..cf03fe819f0 100644 --- a/Master/tlpkg/TeXLive/TLPSRC.pm +++ b/Master/tlpkg/TeXLive/TLPSRC.pm @@ -664,4 +664,4 @@ GNU General Public License Version 2 or later. ### tab-width: 2 ### indent-tabs-mode: nil ### End: -# vim:set tabstop=2: # +# vim:set tabstop=2 expandtab: # diff --git a/Master/tlpkg/TeXLive/TLTREE.pm b/Master/tlpkg/TeXLive/TLTREE.pm index 47202a9fcd0..bf007b9cfb2 100644 --- a/Master/tlpkg/TeXLive/TLTREE.pm +++ b/Master/tlpkg/TeXLive/TLTREE.pm @@ -45,11 +45,11 @@ sub init_from_statusfile { $self->_initialize_lines(@lines); } sub init_from_files { - my $self = shift; - my $svnroot = $self->{'svnroot'}; - my @lines = `find $svnroot ! -wholename '*/.svn*'`; - @lines = map { s@^$svnroot@@; s@^/@@; " 1 1 dummy $_" } @lines; - $self->_initialize_lines(@lines); + my $self = shift; + my $svnroot = $self->{'svnroot'}; + my @lines = `find $svnroot ! -wholename '*/.svn*'`; + @lines = map { s@^$svnroot@@; s@^/@@; " 1 1 dummy $_" } @lines; + $self->_initialize_lines(@lines); } sub _initialize_lines { @@ -73,7 +73,7 @@ sub _initialize_lines { add_path_to_tree($self->{'_dirtree'}, split("[/\\\\]", $dn)); push @{$self->{'_filesofdir'}{$dn}}, $fn; } else { - warn("Ignoring svn status output line:\n $l\n"); + warn("Ignoring svn status output line:\n $l\n"); #die("Cannot read svn status output line:\n $l\n"); } } diff --git a/Master/tlpkg/TeXLive/TLUtils.pm b/Master/tlpkg/TeXLive/TLUtils.pm index 86f98e2de03..2a939443b81 100644 --- a/Master/tlpkg/TeXLive/TLUtils.pm +++ b/Master/tlpkg/TeXLive/TLUtils.pm @@ -133,4 +133,4 @@ GNU General Public License Version 2 or later. ### tab-width: 2 ### indent-tabs-mode: nil ### End: -# vim:set tabstop=2: # +# vim:set tabstop=2 expandtab: # diff --git a/Master/tlpkg/TeXLive/TeXCatalogue.pm b/Master/tlpkg/TeXLive/TeXCatalogue.pm index 25aae3074d9..33ef33e6a7d 100644 --- a/Master/tlpkg/TeXLive/TeXCatalogue.pm +++ b/Master/tlpkg/TeXLive/TeXCatalogue.pm @@ -1,21 +1,168 @@ # $Id$ # TeXLive::TeXCatalogue - module for accessing the TeX Catalogue +# # Copyright 2007 Norbert Preining # +# Loads of code is taken from the catalogue checking script of Robin Fairbairns +# # This file is licensed under the GNU General Public Licence version 2 # or any later version. -die "THIS MODULE IS NOT EVEN CLOSE TO BE FINISHED\n"; +use XML::DOM; -package TeXLive::TeXCatalogue; +package TeXLive::TeXCatalogue::Entry; -use XML::Parser; +sub new { + my $class = shift; + my %params = @_; + my $self = { + xmlfile => $params{'xmlfile'}, + entry => defined($params{'entry'}) ? $params{'entry'} : {}, + docs => defined($params{'docs'}) ? $params{'docs'} : {}, + name => $params{'name'}, + caption => $params{'caption'}, + ctan => $params{'ctan'}, + texlive => $params{'texlive'}, + version => $params{'version'}, + url => $params{'url'}, + }; + bless $self, $class; + if (defined($self->{'xmlfile'})) { + $self->initialize(); + } + return $self; +} + +sub initialize { + my $self = shift; + my $parser = new XML::DOM::Parser; + # parse all the files + my $cat = $parser->parsefile ($self->{'xmlfile'}) || + die "Failed to parse ", $self->{'xmlfile'}; + # there's almost always only one, but... + my $entryset = $cat -> getElementsByTagName ("entry"); + my $entry = $entryset->item(0); + # entry attributes + my $entryid = $entry->getAttributeNode("id"); + $self->{'entry'}{'id'} = $entryid->getValue; + my $entrydate = $entry->getAttributeNode("datestamp"); + if ($entrydate) { + $self->{'entry'}{'date'} = $entrydate->getValue; + } + my $entrymodder = $entry->getAttributeNode("modifier"); + if ($entrymodder) { + $self->{'entry'}{'modder'} = $entrymodder->getValue; + } + # parse the rest of the entries + # only the first name and caption is allowed + # description CANNOT be parsed like this since it contains more childs!! + # ( etc elements + foreach my $k qw/name caption/ { + $self->{$k} = $cat->getElementsByTagName($k)->item(0)->getFirstChild->toString; + } + $self->{'license'} = $cat->getElementsByTagName("license")->item(0)->getAttributeNode("type")->getValue; + my $versnode = $cat->getElementsByTagName("version")->item(0); + if ($versnode) { + my $numnode = $versnode->getAttributeNode("number"); + if ($numnode) { + $self->{'version'} = $numnode->getValue; + } + } + my $urlnode = $cat->getElementsByTagName("home")->item(0); + if ($urlnode) { + $self->{'url'} = $urlnode->getAttributeNode("href")->getValue; + } + $ctannode = $cat->getElementsByTagName("ctan")->item(0); + if ($ctannode) { + $self->{'ctan'} = $ctannode->getAttributeNode("path")->getValue; + } + my $tlnode = $cat->getElementsByTagName("texlive")->item(0); + if ($tlnode) { + $self->{'texlive'} = $tlnode->getAttributeNode("location")->getValue; + } + # parse the documentation entries + my $doc = $cat->getElementsByTagName ("documentation"); + for (my $i=0; $i < $doc->getLength; $i++ ) { + my $node = $doc->item($i); + my $docfile = $node->getAttributeNode("href")->getValue; + my $detailsnode = $node->getAttributeNode("details"); + if ($detailsnode) { $details = $detailsnode->getValue; } + my $languagenode = $node->getAttributeNode("language"); + if ($languagenode) { $language = $languagenode->getValue; } + $self->{'docs'}{$docfile}{'available'} = 1; + if ($details) { $self->{'docs'}{$docfile}{'details'} = $details; } + if ($language) { $self->{'docs'}{$docfile}{'language'} = $language; } + } + $cat->dispose; +} + +sub xmlfile { + my $self = shift; + if (@_) { $self->{'xmlfile'} = shift } + return $self->{'xmlfile'}; +} +sub name { + my $self = shift; + if (@_) { $self->{'name'} = shift } + return $self->{'name'}; +} +sub license { + my $self = shift; + if (@_) { $self->{'license'} = shift } + return $self->{'license'}; +} +sub version { + my $self = shift; + if (@_) { $self->{'version'} = shift } + return $self->{'version'}; +} +sub caption { + my $self = shift; + if (@_) { $self->{'caption'} = shift } + return $self->{'caption'}; +} +sub url { + my $self = shift; + if (@_) { $self->{'url'} = shift } + return $self->{'url'}; +} +sub ctan { + my $self = shift; + if (@_) { $self->{'ctan'} = shift } + return $self->{'ctan'}; +} +sub texlive { + my $self = shift; + if (@_) { $self->{'texlive'} = shift } + return $self->{'texlive'}; +} +sub docs { + my $self = shift; + my %newdocs = @_; + if (@_) { $self->{'docs'} = \%newdocs } + return $self->{'docs'}; +} +sub entry { + my $self = shift; + my %newentry = @_; + if (@_) { $self->{'entry'} = \%newentry } + return $self->{'entry'}; +} + + +################################################################ +# +# TeXLive::TeXCatalogue +# +################################################################ +package TeXLive::TeXCatalogue; sub new { my $class = shift; my %params = @_; my $self = { location => $params{'location'}, + entries => defined($params{'entries'}) ? $params{'entries'} : {}, }; bless $self, $class; if (defined($self->{'location'})) { @@ -25,10 +172,26 @@ sub new { } sub initialize { - my $class = shift; - die "Not done yet ...\n"; + my $self = shift; + my $parser = new XML::DOM::Parser; + # parse all the files + foreach (glob($self->{'location'} . "/entries/?/*.xml")) { + my $tce = TeXLive::TeXCatalogue::Entry->new( 'xmlfile' => "$_" ); + $self->{'entries'}{$tce->name} = $tce; + } } +sub location { + my $self = shift; + if (@_) { $self->{'location'} = shift } + return $self->{'location'}; +} +sub entries { + my $self = shift; + my %newentries = @_; + if (@_) { $self->{'entries'} = \%newentries } + return $self->{'entries'}; +} 1; @@ -48,6 +211,8 @@ missing The L module provides access to the data stored in the TeX Catalogue. +DOCUMENTATION MISSING, SORRY!!! + =head1 AUTHORS AND COPYRIGHT This script and its documentation were written for the TeX Live @@ -61,4 +226,4 @@ GNU General Public License Version 2 or later. ### tab-width: 2 ### indent-tabs-mode: nil ### End: -# vim:set tabstop=2: # +# vim:set tabstop=2 expandtab: # -- cgit v1.2.3