1#!/usr/bin/env perl 2# 3# 4# INDEX builds visit each port once and write out each port's 5# *-depends as a list of directories, using 'make describe'. This 6# script goes back in and maps the directories back to pkgnames, 7# fixes up the *-depends list, and writes out the new INDEX file. 8 9require 5.002; 10 11# Helper function to map a directory to a pkgname. 12sub by_path { 13 my ($name, $port) = @_; 14 15 # If a direct mapping exists, then use it. 16 return $by_path{$name} if (defined $by_path{$name}); 17 18 # Make sure we have /usr/mports at the beginning. 19 $name =~ s!^$pwd!/usr/mports!o; 20 return $by_path{$name} if (defined $by_path{$name}); 21 22 # Collapse all the '..' sequences. 23 my @f = split('/', $name), @p = (); 24 foreach (@f) { (/\.\./) ? pop(@p) : push(@p, $_); } 25 $name = join('/', @p); 26 return $by_path{$name} if (defined $by_path{$name}); 27 28 print STDERR "make_index: $port: no entry for $name\n"; 29 return undef; 30} 31 32# This routine replaces what used to be the time-consuming 33# recursive 'depends-list' and 'package-depends' targets. 34sub recurse { 35 my $pkg = shift(@_); 36 return if $pkg->{checked}; 37 38 # extract-depends = extract-depends + recursive list of run-depends 39 # for each extract-depends 40 my @deps = (); 41 foreach $name (@{$pkg->{edep}}) { 42 recurse($index{$name}); 43 push(@deps, @{$index{$name}->{rdep}}); 44 } 45 $pkg->{edep} = uniqify(@{$pkg->{edep}}, @deps); 46 47 # same as above except for patch-depends this time 48 @deps = (); 49 foreach $name (@{$pkg->{pdep}}) { 50 recurse($index{$name}); 51 push(@deps, @{$index{$name}->{rdep}}); 52 } 53 $pkg->{pdep} = uniqify(@{$pkg->{pdep}}, @deps); 54 55 # same as above except for fetch-depends this time 56 @deps = (); 57 foreach $name (@{$pkg->{fdep}}) { 58 recurse($index{$name}); 59 push(@deps, @{$index{$name}->{rdep}}); 60 } 61 $pkg->{fdep} = uniqify(@{$pkg->{fdep}}, @deps); 62 $pkg->{checked} = 1; 63 64 # same as above except for build-depends this time 65 @deps = (); 66 foreach $name (@{$pkg->{bdep}}) { 67 recurse($index{$name}); 68 push(@deps, @{$index{$name}->{rdep}}); 69 } 70 $pkg->{bdep} = uniqify(@{$pkg->{bdep}}, @deps); 71 $pkg->{checked} = 1; 72 73 # same as above except for run-depends this time 74 @deps = (); 75 foreach $name (@{$pkg->{rdep}}) { 76 recurse($index{$name}); 77 push(@deps, @{$index{$name}->{rdep}}); 78 } 79 $pkg->{rdep} = uniqify(@{$pkg->{rdep}}, @deps); 80 $pkg->{checked} = 1; 81 82} 83 84# Given one or more lists as arguments return the set 85# of unique elements among them. 86sub uniqify { 87 my %seen = (); 88 my @unique = grep {! $seen{$_}++} (@_); 89 return \@unique; 90} 91 92# Save where we are so that we can map all directories formed 93# from ${PORTSDIR} to their canonical location '/usr/mports/...'. 94chomp($pwd = `pwd`); 95 96# Read each line of output generated by the 'index' target. 97while (<>) { 98 chomp; 99 s/\015$//; 100 101 my @f = split(/\|/); 102 103 # Force to canonical form. 104 $f[1] =~ s!^$pwd!/usr/mports!o; 105 $f[4] =~ s!^$pwd!/usr/mports!o; 106 107 # Save directory -> pkgname relationship. 108 # Note: $f[0] gets clobbered by the splice below so we'll save 109 # it to a new $name first. 110 $by_path{$f[1]} = $name = $f[0]; 111 112 # Create a hash table of the infomation we need about this port. 113 my $pkg = { 114 'edep' => [split(/ /, $f[7])], 115 'pdep' => [split(/ /, $f[8])], 116 'fdep' => [split(/ /, $f[9])], 117 'bdep' => [split(/ /, $f[10])], 118 'rdep' => [split(/ /, $f[11])], 119 'rest' => join('|', splice(@f, 12)), 120 'text' => join('|', splice(@f, 0, 7)) 121 }; 122 $index{$name} = $pkg; 123 124 # This is a cheap way of preserving the order of the entries. 125 push(@names, $name); 126} 127 128# For each port perform the mapping between directory and pkgnames. 129foreach $name (keys %index) { 130 my $pkg = $index{$name}; 131 # first the extract dependencies 132 if (@{$pkg->{edep}}) { 133 my @edep = map { by_path($_, $name) } @{$pkg->{edep}}; 134 $pkg->{edep} = \@edep; 135 } 136 # then the patch dependencies 137 if (@{$pkg->{pdep}}) { 138 my @pdep = map { by_path($_, $name) } @{$pkg->{pdep}}; 139 $pkg->{pdep} = \@pdep; 140 } 141 # then the fetch dependencies 142 if (@{$pkg->{fdep}}) { 143 my @fdep = map { by_path($_, $name) } @{$pkg->{fdep}}; 144 $pkg->{fdep} = \@fdep; 145 } 146 # then the build dependencies 147 if (@{$pkg->{bdep}}) { 148 my @bdep = map { by_path($_, $name) } @{$pkg->{bdep}}; 149 $pkg->{bdep} = \@bdep; 150 } 151 # then the run dependencies 152 if (@{$pkg->{rdep}}) { 153 my @rdep = map { by_path($_, $name) } @{$pkg->{rdep}}; 154 $pkg->{rdep} = \@rdep; 155 } 156} 157 158# With all that done we're finally ready to write out the new 159# INDEX file one port at a time. 160foreach $name (@names) { 161 my $pkg = $index{$name}; 162 if (exists $pkg->{'PRINTED'}) { 163 print STDERR "Warning: Duplicate INDEX entry: $name\n"; 164 } else { 165 recurse($pkg); 166 print "$pkg->{text}|"; 167 print join(' ', sort(@{$pkg->{bdep}})) if @{$pkg->{bdep}}; 168 print "|"; 169 print join(' ', sort(@{$pkg->{rdep}})) if @{$pkg->{rdep}}; 170 print "|$pkg->{rest}|"; 171 print join(' ', sort(@{$pkg->{edep}})) if @{$pkg->{edep}}; 172 print "|"; 173 print join(' ', sort(@{$pkg->{pdep}})) if @{$pkg->{pdep}}; 174 print "|"; 175 print join(' ', sort(@{$pkg->{fdep}})) if @{$pkg->{fdep}}; 176 print "\n"; 177 ++$pkg->{'PRINTED'}; 178 } 179} 180