#!/usr/bin/perl $realsrc=$src=shift; if ($src eq '--desc') { $usedesc=1; $src=shift; $realsrc=shift; } if ($src eq '' || $src eq '--help' || $src eq '-h') { print "\n Usage: dtree [--desc ] [ ...] Creates list of packages in such that dependent packages are listed after their prerequisites. When using cached descriptions, only pacakges actually present as sources in are listed. Options: --desc look for cached *.DESCRIPTION in Note that additional directories are used for dependence detection but their content is not printed. "; exit 1; } # base packages @repkg=('base','boot','class','cluster','datasets','foreign','graphics','grDevices','grid','KernSmooth','lattice','MASS', 'methods','mgcv','nlme','nnet','rpart','spatial','splines','stats','stats4','survival','tcltk','tools','utils'); foreach(@repkg) { $sx{$_}=1; }; if ($usedesc>0) { @f=<$src/*.DESCRIPTION>; } else { @f=<$src/*.tar.gz>; } $mkmk=1 if ($ENV{MKF} ne ''); foreach(@f) { undef $pkg; undef $dep; undef $sug; undef $ver; undef $bdl; undef $cts; undef $lnk; undef $imp; $tar=$_; $fn=$_; $fn=~s/.*\///; if ($usedesc > 0) { open IN, $tar; } else { $pn = $fn; $pn =~ s/_.*//; open IN, "tar fxzO $_ $pn/DESCRIPTION|"; } $lines = 0; $lk=''; undef %hh; while () { $lines++; $ignore = 0; s/[\r\n]+//g; if (/^\s+(.*)/) { $_="$lk:$1" } elsif (/^(.*?):/) { $hn = lc $1; $on = $1; if ($hh{$hn} > 0) { $ignore = 1; $ad=''; if ($hn eq 'package') { $ad = " (old $pkg, new $_)"; } print STDERR "WARNING: $fn: duplicate entry '$on'$ad, ignoring\n"; } $hh{$hn}++; } if ($ignore == 0) { $pkg.=$1 if (/^Package:(.*)/i); $bdl.=$1 if (/^Bundle:(.*)/i); $ver.=$1 if (/^Version:(.*)/i); $dep.=$1 if (/^Depends:(.*)/i); $cts.=$1 if (/^Contains:(.*)/i); $sug.=$1 if (/^Suggests:(.*)/i); $imp.=$1 if (/^Imports:(.*)/i); $lnk.=$1 if (/^LinkingTo:(.*)/i); } $lk=(/^([A-Za-z0-9]+):/)?$1:''; } close IN; if ($lines == 0) { print STDERR "WARNING: $_ does not contain DESCRIPTION"; } $ad="$dep,$sug,$imp,$lnk"; $ad=~s/\([^,]+\)//g; $ad=~s/[ \t]+//g; $ad=~s/,,/,/g; $ad=~s/^,//; $ad=~s/,$//; $ad='' if ($ad eq ','); $pkg=~s/[ \t]+//g; $bdl=~s/[ \t]+//g; $pkg=$bdl if ($pkg eq ''); if ($bdl ne '') { $cts=~s/,/ /g; $cts=~s/\s+/ /g; @cc=split ' ',$cts; foreach(@cc) { $sx{$_}=1; $pdep{$_}=$ad; } } $pdep{$pkg}=$ad; $sx{$pkg}=1; if ($mkmk > 0) { $pd=$ad; $pd=~s/,/ /g; print "$pkg: $pd\n"; } #print "$pkg: \"$ad\"\n"; } # load additional directories while ($more=shift) { next if ($more eq $src || $more eq $realsrc); print STDERR "Loading extra repository $more ...\n"; $usedesc=1; @g=<$more/*.DESCRIPTION>; if ($g[0] eq '') { @g=<$more/*.tar.gz>; $usedesc=0; } foreach(@g) { undef $pkg; undef $dep; undef $sug; undef $ver; undef $bdl; undef $cts; if ($usedesc>0) { open IN, $_; } else { open IN, "tar fxzO $_ \*/DESCRIPTION|"; } undef $pkg; undef $cts; while () { s/[\r\n]+//g; $pkg=$1 if (/^Package:(.*)/); $cts=$1 if (/^Contains:(.*)/); } $pkg=~s/[ \t]+//g; if ($cts ne '') { $cts=~s/,/ /g; $cts=~s/\s+/ /g; @cc=split ' ',$cts; foreach(@cc) { $sx{$_}=1; } } $sx{$pkg}=1 if($pkg ne ''); #print STDERR "$pkg "; } } sub addPKG { my ($pkg); $pkg=$_[0]; return if ($pkg eq ''); #print "Add: $pkg\n"; if ($sx{$pkg}!=1) { print STDERR "NOTE: there is no source for package $pkg [",join(',',@cda),"], installed CRAN version will be used.\n"; print "$pkg:\n\t\@echo \"No source for package $pkg, skipping\"\n\n" if ($mkmk > 0); } if ($done{$pkg}==0) { my ($dl,@da,$pn); #print " - new $pkg\n"; $indep{$pkg}=1; $dl=$pdep{$pkg}; if ($dl ne '') { #print " dep list: \"$dl\"\n"; @da=split /,/,$dl; foreach $pn (@da) { if ($pn ne '' && $pn ne 'R') { #print " - depends on $pn\n"; if ($done{$pn}==0 && $indep{$pn}>0) { print STDERR "ERROR: circular dependency on $pn [",join(',',@cda),"]\n"; } else { push @cda, $pn; addPKG($pn); pop @cda; } } }; } push @plist, $pkg; $done{$pkg}=1; } } print "all: ",join(' ',sort(keys(%pdep))),"\n\t\@echo All packages have been built.\n\nclean:\n\trm -f *.log ",join(' ',sort(keys(%pdep))),"\n\n" if ($mkmk > 0); foreach(sort(keys(%pdep))) { addPKG($_); } exit 0 if ($mkmk > 0); foreach(@plist) { @fl=<$realsrc/$_*.tar.gz>; if ($fl[0] eq '') { #print "### $_\n"; } else { print "$_\n"; } #print join("\n",@plist),"\n"; }