1# ex:ts=8 sw=4: 2# $OpenBSD: RequiredBy.pm,v 1.26 2014/03/18 18:53:29 espie Exp $ 3# 4# Copyright (c) 2003-2005 Marc Espie <espie@openbsd.org> 5# 6# Permission to use, copy, modify, and distribute this software for any 7# purpose with or without fee is hereby granted, provided that the above 8# copyright notice and this permission notice appear in all copies. 9# 10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 18use strict; 19use warnings; 20 21package OpenBSD::RequirementList; 22use OpenBSD::PackageInfo; 23use Carp; 24 25sub fill_entries 26{ 27 my $self = shift; 28 if (!exists $self->{entries}) { 29 my $l = $self->{entries} = {}; 30 31 if (-f $self->{filename}) { 32 open(my $fh, '<', $self->{filename}) or 33 croak ref($self), 34 ": reading $self->{filename}: $!"; 35 while(<$fh>) { 36 s/\s+$//o; 37 next if /^$/o; 38 chomp; 39 $l->{$_} = 1; 40 } 41 close($fh); 42 $self->{nonempty} = 1; 43 } else { 44 $self->{nonempty} = 0; 45 } 46 } 47} 48 49sub synch 50{ 51 my $self = shift; 52 return $self if $main::not; 53 54 if (!unlink $self->{filename}) { 55 if ($self->{nonempty}) { 56 croak ref($self), ": erasing $self->{filename}: $!"; 57 } 58 } 59 if (%{$self->{entries}}) { 60 open(my $fh, '>', $self->{filename}) or 61 croak ref($self), ": writing $self->{filename}: $!"; 62 while (my ($k, $v) = each %{$self->{entries}}) { 63 print $fh "$k\n"; 64 } 65 close($fh) or 66 croak ref($self), ": closing $self->{filename}: $!"; 67 $self->{nonempty} = 1; 68 } else { 69 $self->{nonempty} = 0; 70 } 71 return $self; 72} 73 74sub list 75{ 76 my $self = shift; 77 78 if (wantarray) { 79 $self->fill_entries; 80 return keys %{$self->{entries}}; 81 } else { 82 if (exists $self->{entries}) { 83 return %{$self->{entries}} ? 1 : 0; 84 } elsif (!exists $self->{nonempty}) { 85 $self->{nonempty} = -f $self->{filename} ? 1 : 0; 86 } 87 return $self->{nonempty}; 88 } 89} 90 91sub erase 92{ 93 my $self = shift; 94 $self->{entries} = {}; 95 $self->synch; 96} 97 98sub delete 99{ 100 my ($self, @pkgnames) = @_; 101 $self->fill_entries($self); 102 for my $pkg (@pkgnames) { 103 delete $self->{entries}->{$pkg}; 104 } 105 $self->synch; 106} 107 108sub add 109{ 110 my ($self, @pkgnames) = @_; 111 $self->fill_entries($self); 112 for my $pkg (@pkgnames) { 113 $self->{entries}->{$pkg} = 1; 114 } 115 $self->synch; 116} 117 118my $cache = {}; 119 120sub new 121{ 122 my ($class, $pkgname) = @_; 123 my $f = installed_info($pkgname).$class->filename; 124 if (!exists $cache->{$f}) { 125 return $cache->{$f} = bless { filename => $f }, $class; 126 } 127 return $cache->{$f}; 128} 129 130sub forget 131{ 132 my ($class, $dir) = @_; 133 my $f = $dir.$class->filename; 134 if (exists $cache->{$f}) { 135 $cache->{$f}->{entries} = {}; 136 $cache->{$f}->{nonempty} = 0; 137 } 138} 139 140sub compute_closure 141{ 142 my ($class, @seed) = @_; 143 144 my @todo = @seed; 145 my %done = (); 146 147 while (my $pkgname = pop @todo) { 148 next if $done{$pkgname}; 149 $done{$pkgname} = 1; 150 for my $dep ($class->new($pkgname)->list) { 151 next if defined $done{$dep}; 152 push(@todo, $dep); 153 } 154 } 155 return keys %done; 156} 157 158package OpenBSD::RequiredBy; 159our @ISA=qw(OpenBSD::RequirementList); 160use OpenBSD::PackageInfo; 161 162sub filename() { REQUIRED_BY }; 163 164package OpenBSD::Requiring; 165our @ISA=qw(OpenBSD::RequirementList); 166use OpenBSD::PackageInfo; 167 168sub filename() { REQUIRING }; 169 1701; 171