#!/usr/bin/env perl # $Id$ # License: public domain. Originally written by Sebastian Rahtz. # # Process a tree in the Build/cdbuild/cooked directory (probably created # by ctan2tds.pl) and integrate into the main texmf trees. # # Basic usage: place PKG # to process Build/cdbuild/cooked/PKG. BEGIN { chomp ($mydir = `dirname $0`); unshift (@INC, "$mydir/../../Master/tlpkg"); } use File::Basename; use File::Find; use Cwd; use TeXLive::TLPSRC; use TeXLive::TLPOBJ; use TeXLive::TLPDB; use TeXLive::TLTREE; if ($ARGV[0] eq "-n") { $chicken = 1; shift; } else { $chicken = 0; } print "place: chicken mode = $chicken\n"; die "usage: $0 PKGNAME\n" unless @ARGV == 1; $package = $ARGV[0]; $newpackage = 0; %dirs = (); # dirs we make changes in $TMP = $ENV{"TMPDIR"} || "/tmp"; xchdir (dirname($0) . "/cooked"); $mydir = getcwd(); -d "$mydir/$package" || die "$0: No such package in $mydir: $package\n"; xchdir ("../../../Master"); $M = getcwd(); xchdir ("$mydir/$package"); if (-d "texmf-dist") {$Root="texmf-dist"; } elsif (-d "texmf-doc") {$Root="texmf-doc"; } elsif (-d "texmf") {$Root="texmf"; } # I moved this test BEFORE any action. For now I want this script ONLY to # work with Documentation/Package and NOT with anything else!!! [np] if ($Root eq 'texmf-doc') { $Type = 'Documentation'; } elsif ($Root eq 'texmf-dist') { $Type = 'Package'; } else { die "cannot handle Root=$Root"; } # initialize TLPDB my $tlpdb = new TeXLive::TLPDB ( location => "$M/texlive.tlpdb" ); # create TLTREE from stuff in cooked/$pkg my $tltree = TeXLive::TLTREE->new( 'svnroot' => "$mydir/$package" ); $tltree->init_from_files; # get package from TLPDB; my $tlpold = $tlpdb->get_package("$package"); if (defined($tlpold)) { # what to do with binfiles, but they are not place-ed!!! foreach ($tlpold->srcfiles, $tlpold->runfiles, $tlpold->docfiles) { $Old{$_} = 1; } } else { $newpackage = 1; } # create new tlpsrc and tlpobj my $tlpsrc = TeXLive::TLPSRC; if (! -r "$M/tlpkg/tlpsrc/$package.tlpsrc") { $tlpsrc->name("$package"); $tlpsrc->category($Type); if (!$chicken) { open TMP, ">$M/tlpkg/tlpsrc/$package.tlpsrc" or die "Cannot open tlpsrc file!"; $tlpsrc->writeout(\*TMP); close TMP } } else { $tlpsrc->from_file("$M/tlpkg/tlpsrc/$package.tlpsrc"); } my $tlpnew = $tlpsrc->make_tlpobj($tltree); # we took over the comparison of files from the ctan2tl script since # we are here in perl world, which makes it easier ... print "\n\f "; if (!defined($tlpold)) { print "place: $package not present in $M/texlive.tlpdb\n\n"; } else { print "new vs. present $package\n"; my @oldfiles; push @oldfiles, $tlpold->srcfiles; push @oldfiles, $tlpold->runfiles; push @oldfiles, $tlpold->docfiles; `rm -f $TMP/tlplace.old`; foreach (sort @oldfiles) { `echo $_ >> $TMP/tlplace.old`; } my @newfiles; push @newfiles, $tlpnew->srcfiles; push @newfiles, $tlpnew->runfiles; push @newfiles, $tlpnew->docfiles; `rm -f $TMP/tlplace.new`; foreach (sort @newfiles) { `echo $_ >> $TMP/tlplace.new`; } print `comm -3 $TMP/tlplace.new $TMP/tlplace.old`; my @difffiles = `comm -12 $TMP/tlplace.new $TMP/tlplace.old`; chomp (@difffiles); my $sum = 0; unlink ("$TMP/tlplace.diff"); my $diff_cmd = "diff --ignore-all-space -U 0"; foreach (@difffiles) { my @foo = `$diff_cmd $M/$_ $mydir/$package/$_ | tee -a $TMP/tlplace.diff`; $sum += ($#foo + 1); } my $nrcommfiles = $#difffiles + 1; print "$nrcommfiles common files, ~$sum lines different\n\n\f\n"; #`rm -f $TMP/tlplace.new $TMP/tlplace.old $TMP/tlplace.diff`; } &xchdir ("$mydir/$package"); find (\&files,"."); foreach $file (sort keys %Old) { print "* $file: [retained=$New{$file}]\n"; # and if the file does not exist, don't try to remove it -- we # probably did so by hand and didn't bother to update the tpm. next unless -f "$M/$file"; # don't remove tpm or lists file, they won't be in the new package. if (! $New{$file} && $file !~ /\.tpm$/ && $file !~ m,/lists/[^/]+$,) { &my_system ("svn remove $M/$file"); } $dirs{dirname ("$M/$file")}++; } # copy files my $Job = "tar cf - . | (cd $M && tar xf - )"; &my_system ($Job); # sort so dirs will be added before subdirs. foreach $file (sort keys %New) { if (! $Old{$file}) { &add_file ("$M/$file"); } } xchdir ($mydir); &my_system ("mv $package $package.done"); chomp (my $tools = `cd $mydir/../../tools && pwd`); if ($newpackage) { &add_file ("$M/tlpkg/tlpsrc/$package.tlpsrc"); } # these two dirs will essentially always change, so just list them. $dirs{"$M/tlpkg/tlpsrc/$package.tlpsrc"}++; # print dirs with changed files, for svn commit purposes. # if other files have been modified in those same dirs, though, this # won't detect it. It would be better to list exactly the *files* which # should be committed, but ... lazy. # # also write dir list to a separate file, for easy passing to a commit. # $DIRLIST = ">$TMP/tlplace.dirs"; open (DIRLIST) || die "open($DIRLIST) failed: $!"; # for my $dir (sort keys %dirs) { print "$dir\n"; print DIRLIST "$dir\n"; } # close (DIRLIST) || warn "close($DIRLIST) failed: $!"; #xx warn "WARNING WARNING Things we SHOULD/COULD do here:\n - Update the texlive.tlpdb\n - Compare the files ACTUALLY present in cooked/package with those included via tlpsrc/tltree generation!!!\n - Create list file\n - Update the list of available packages for web update\n - Create zip file(s)\n\n\n"; exit (0); #-------------------------------------- sub dirs { local @filenames; if (-d) { @filenames=&buildfilelist($File::Find::name); if (!@filenames) { rmdir $File::Find::name;} }} sub buildfilelist { my($me) = @_; my @files; opendir(DIR,$me) || cleanup ("cannot open directory $me"); @files =grep(!/^\.\.?/,readdir(DIR)); closedir(DIR); return @files; } sub files { if (-f) { $This=$File::Find::name; $This =~ s/^\.\///; $New{$This}=1; } } # add a file to the repository. for svn, we also have to add the # containing dir, and the parent of that dir, if they are new. # (Should really just traverse ) # sub add_file { my ($newfile) = @_; my $newdir = dirname ($newfile); # when it's needed, parent must come first, else have svn "not working copy". my $parentdir = dirname ($newdir); unless (-d "$parentdir/.svn") { &my_system ("svn add -N $parentdir"); $dirs{$parentdir}++; } unless (-d "$newdir/.svn") { &my_system ("svn add -N $newdir"); } &my_system ("svn add $newfile"); # remember that we changed this directory. $dirs{$newdir}++; } sub xchdir { my ($dir) = @_; chdir ($dir) || die "chdir($dir) failed: $!"; print "place: chdir($dir)\n"; } sub my_system { my ($cmd) = @_; print "place: SYSTEM $cmd\n"; unless ($chicken) { my $ret = system ($cmd); die "`$cmd' failed, status=$ret, goodbye\n" if $ret != 0; } }