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
|
#!/usr/bin/perl
#
# $FreeBSD$
#
# Written to speed-up INDEX file generation. The new scheme
# basically visits each port once and writes out each port's
# build-depends and run-depends as a list of directories. This
# script goes back in and maps the directories back to pkgnames,
# fixes up the build-depends and run-depends list, and writes
# out the new INDEX file.
require 5.002;
# Helper function to map a directory to a pkgname.
sub by_path {
my $name = shift;
# If a direct mapping exists, then use it.
return $by_path{$name} if (defined $by_path{$name});
# Make sure we have /usr/ports at the beginning.
$name =~ s!^$pwd!/usr/ports!o;
return $by_path{$name} if (defined $by_path{$name});
# Collapse all the '..' sequences.
my @f = split('/', $name), @p = ();
foreach (@f) { (/\.\./) ? pop(@p) : push(@p, $_); }
return $by_path{join('/', @p)};
}
# This routine replaces what used to be the time-consuming
# recursive 'depends-list' and 'package-depends' targets.
sub recurse {
my $pkg = shift(@_);
return if $pkg->{checked};
# build-depends = build-depends + recursive list of run-depends
# for each build-depends
my @deps = ();
foreach $name (@{$pkg->{bdep}}) {
recurse($index{$name});
push(@deps, @{$index{$name}->{rdep}});
}
$pkg->{bdep} = uniqify(@{$pkg->{bdep}}, @deps);
# same as above except for run-depends this time
@deps = ();
foreach $name (@{$pkg->{rdep}}) {
recurse($index{$name});
push(@deps, @{$index{$name}->{rdep}});
}
$pkg->{rdep} = uniqify(@{$pkg->{rdep}}, @deps);
$pkg->{checked} = 1;
}
# Given one or more lists as arguments return the set
# of unique elements among them.
sub uniqify {
my %seen = ();
my @unique = grep {! $seen{$_}++} (@_);
return \@unique;
}
# Save where we are so that we can map all directories formed
# from ${PORTSDIR} to their canonical location '/usr/ports/...'.
chomp($pwd = `pwd`);
# Read each line of output generated by the 'index' target.
while (<>) {
chomp;
my @f = split(/\|/);
# Force to canonical form.
$f[1] =~ s!^$pwd!/usr/ports!o;
$f[4] =~ s!^$pwd!/usr/ports!o;
# Save directory -> pkgname relationship.
# Note: $f[0] gets clobbered by the splice below so we'll save
# it to a new $name first.
$by_path{$f[1]} = $name = $f[0];
# Create a hash table of the infomation we need about this port.
my $pkg = {
'bdep' => [split(/ /, $f[7])],
'rdep' => [split(/ /, $f[8])],
'rest' => join('|', splice(@f, 9)),
'text' => join('|', splice(@f, 0, 7))
};
$index{$name} = $pkg;
# This is a cheap way of preserving the order of the entries.
push(@names, $name);
}
# For each port perform the mapping between directory and pkgnames.
foreach $name (keys %index) {
my $pkg = $index{$name};
# first the build dependencies
if (@{$pkg->{bdep}}) {
my @bdep = map { by_path($_) } @{$pkg->{bdep}};
$pkg->{bdep} = \@bdep;
}
# and now the run dependencies
if (@{$pkg->{rdep}}) {
my @rdep = map { by_path($_) } @{$pkg->{rdep}};
$pkg->{rdep} = \@rdep;
}
}
# With all that done we're finally ready to write out the new
# INDEX file one port at a time.
foreach $name (@names) {
my $pkg = $index{$name};
recurse($pkg);
print "$pkg->{text}|";
print join(' ', sort(@{$pkg->{bdep}})) if @{$pkg->{bdep}};
print "|";
print join(' ', sort(@{$pkg->{rdep}})) if @{$pkg->{rdep}};
print "|$pkg->{rest}\n";
}
|