diff --git a/scripts/prt-auf b/scripts/prt-auf index 042a1f3..e05fba9 100755 --- a/scripts/prt-auf +++ b/scripts/prt-auf @@ -671,38 +671,38 @@ sub port_diff { # find differences between the pkgdb and the repo } sub deporder { # returns a sorted list of packages required. - my $type=shift; my @seeds=@_; our @treewalk=(); our %missing; - our %level = map { $_ => 1 } @seeds; our $maxLevel=1; my @result; + my $type=shift; my @seeds=@_; our @treewalk=(); our %missing; our @result; + our %given = map { $_ => 1 } @seeds; our %imark=(); our %fmark=(); # determine the minimal set of targets needed to satisfy all dependencies - foreach my $t (@seeds) { recurse_deptree(0,1,$t); } + foreach my $t (@seeds) { recurse_deptree(0,$t); } sub recurse_deptree { - my $greedy=shift; my $thisLevel=shift; my $s=shift; my %curdeps; + my $greedy=shift; my $s=shift; my %curdeps=(); - # detect any dependencies that have been dropped from the repositories - if (! $V_REPO{$s}) { $missing{$s}=1; delete $level{$s}; return; } + # early return if this node has been visited already + if ($fmark{$s}) { return; } - # cycle detection - if (grep /^$s$/, @treewalk) { + # detect targets that have been dropped from the repositories + if (! $V_REPO{$s}) { $missing{$s}=1; $fmark{$s}=0; return; } + + # dependency cycle detection + if ($imark{$s}) { return if ($greedy == 1); print "Dependency cycle found: "; foreach (@treewalk) { print "$_ => "; } print "$s\n"; - } else { push(@treewalk, $s); } + } - # update the hash table and the height of the tree - if ( (! $level{$s}) or ($level{$s} < $thisLevel) ) { - $level{$s} = $thisLevel; - } - if ( $maxLevel < $thisLevel ) { $maxLevel = $thisLevel; } + push(@treewalk, $s); $imark{$s}=1; + # assemble the list of dependencies that must be visited next %curdeps = map { $_ => $greedy } split /[ ,]/, $DEPENDS{$s}; # if the user toggles --softdeps, consider the optional dependencies # that are already installed or are given on the command line if ($odepends{soft} == 1) { - foreach (grep { ($V_INST{$_}) or ($level{$_}) } + foreach (grep { ($V_INST{$_}) or ($given{$_}) } split /[ ,]/, $SOFTDEPS{$s}) { $curdeps{$_} = 1; } @@ -711,20 +711,15 @@ sub deporder { # returns a sorted list of packages required. foreach my $sd (keys %curdeps) { my $subit = who_aliased_to($sd); if ($subit) { - recurse_deptree($curdeps{$sd},$thisLevel+1,$subit); + recurse_deptree($curdeps{$sd},$subit); } else { - recurse_deptree($curdeps{$sd},$thisLevel+1,$sd); + recurse_deptree($curdeps{$sd},$sd); } } - pop (@treewalk); - - } # proceed with the topological sort - # gather up all the targets farthest from the root of the tree, - # then reduce by 1 the level at which to search. - while ($maxLevel >= 1) { - push(@result, grep { ($level{$_} == $maxLevel) } keys %level); - $maxLevel -= 1; - } + delete $imark{$s}; pop(@treewalk); + $fmark{$s} = 1; + push(@result, $s); + } if ((keys %missing > 0) and ($type ne "quickdep")) { push (@result, "MISSING", sort(keys %missing)); } return @result;