summaryrefslogtreecommitdiff
path: root/app-portage
diff options
context:
space:
mode:
authorMarcin Deranek <marcin.deranek@booking.com>2020-02-20 20:49:44 +0100
committerMarcin Deranek <marcin.deranek@booking.com>2020-02-20 20:49:44 +0100
commit334f72c87ce8a048074cb0664e1997a62663825c (patch)
treee1caf36cb7242c6327718957e6ef15db56897193 /app-portage
parent1e8fac87077ff08bea267a1af94e33eb5fc39e96 (diff)
downloadportage-334f72c87ce8a048074cb0664e1997a62663825c.tar.gz
portage-334f72c87ce8a048074cb0664e1997a62663825c.tar.bz2
portage-334f72c87ce8a048074cb0664e1997a62663825c.zip
Provide local copy as package is not maintained anymore
Diffstat (limited to 'app-portage')
-rw-r--r--app-portage/epm/Manifest7
-rw-r--r--app-portage/epm/epm-1.40.ebuild8
-rw-r--r--app-portage/epm/files/epm984
3 files changed, 995 insertions, 4 deletions
diff --git a/app-portage/epm/Manifest b/app-portage/epm/Manifest
index 99526a3..6a55b7d 100644
--- a/app-portage/epm/Manifest
+++ b/app-portage/epm/Manifest
@@ -1,3 +1,4 @@
-AUX epm-1.40-prefix.patch 1293 SHA256 11a6411c14ac807f75191d5281795aa61fdbdc0e91207afde55f84a62d487f7e SHA512 877204c75356b36df74ace94fe26a09f598448cbf502b7d65fec9d4b142368c4734e16807e5e4706671d8a59bc7db09811166f422d43d74a40fae5ff65e8c256 WHIRLPOOL 009f33ba08c34ba709ddf08f57209b4d707c5652dd8f46a9abe77e0984eda7b2ec3d4a5c3c698aae603a1d5cfcbf9e8f597586a0280790075b040d19e7dba4c4
-DIST epm-1.40.tar.gz 10980 BLAKE2B 3d05968038157b650bcb553c7cadba467604ae8e8318c20d3a1973146925c4daad796ec61aea2ed541e7ec1b2dc59da690c1cd073b2f63f20bd4976ebb152cf6 SHA512 745c7f902fb35672058b05763a308322fb891b5dcc4f37a0444fdc22f1802ec5e8479445537c299e23dcf3882259751a163e356a633e270a2386a1456b541103
-EBUILD epm-1.40.ebuild 722 SHA256 5684efa3e5606f4f8337c7c498927b10bdf1782567155c8ba1a8f7eec2c9700d SHA512 8b417529834667b2d86a3ac92818211b2110c83e77268b5d2ce387af662cea627f5a3f31124970937bcb524c07e627e52c683278c8b137b2cf61a5c839a55678 WHIRLPOOL 9310a6bf8822ae053bb985e7ff8bb0a49fb624669fc733ff4206ab7b46a3ed04b4a0fb9a1c10f26e6595d283bce0a7028f673a710133ef838bf1497337792e5e
+AUX epm 30664 BLAKE2B 72988b0b08616761367b98dc3c698e0d352e2c442d0bcc1c77b2bfcd0009cb06bd27572e93d727babeca5bc353a3e7db43a8d7997e316a9e3b41b434e1d93a11 SHA512 75ae3fb03be9508f357f020310fba1e2d89513782ea57cb39f5a524b8cf5ded95c45bc4fbe0bfd195902c25f286119cf54501de64a2f082a69ea0ca55968175a
+AUX epm-1.40-prefix.patch 1293 BLAKE2B 6d835610fce455f6089867b2fd7e959b5dffff07f72a96a9a8a2be3fb4033822967098e32f859b836c25cc8d463b9ae950a7337f65c261ceb538a0dac14a842c SHA512 877204c75356b36df74ace94fe26a09f598448cbf502b7d65fec9d4b142368c4734e16807e5e4706671d8a59bc7db09811166f422d43d74a40fae5ff65e8c256
+DIST epm 30664 BLAKE2B 72988b0b08616761367b98dc3c698e0d352e2c442d0bcc1c77b2bfcd0009cb06bd27572e93d727babeca5bc353a3e7db43a8d7997e316a9e3b41b434e1d93a11 SHA512 75ae3fb03be9508f357f020310fba1e2d89513782ea57cb39f5a524b8cf5ded95c45bc4fbe0bfd195902c25f286119cf54501de64a2f082a69ea0ca55968175a
+EBUILD epm-1.40.ebuild 740 BLAKE2B 79ef448a32b5d8484b3a33475304e47a297671b046c4542e91fd8a2a0caa3018d088b6189ad00779c3036002e1ab0bc1be8ed6418fa14be5e51493993517d50c SHA512 3acd58f62b9b191d4a8021d180125ac551396857e86ddbce368f37af11af5a1d613f0be2766acadf5b6fbfb77f1a69071dc98bdc904e4bd67563d8998ab098c4
diff --git a/app-portage/epm/epm-1.40.ebuild b/app-portage/epm/epm-1.40.ebuild
index 853bf26..7009253 100644
--- a/app-portage/epm/epm-1.40.ebuild
+++ b/app-portage/epm/epm-1.40.ebuild
@@ -8,7 +8,8 @@ inherit eutils prefix
DESCRIPTION="rpm workalike for Gentoo Linux"
HOMEPAGE="https://github.com/fuzzyray/epm"
-SRC_URI="http://dev.gentoo.org/~fuzzyray/distfiles/${P}.tar.gz"
+SRC_URI="epm"
+S="${WORKDIR}/"
LICENSE="GPL-2"
SLOT="0"
@@ -18,7 +19,12 @@ IUSE=""
DEPEND=">=dev-lang/perl-5"
RDEPEND="${DEPEND}"
+src_unpack() {
+ :
+}
+
src_prepare() {
+ cp "${FILESDIR}"/epm ${S}/epm
epatch "${FILESDIR}"/${P}-prefix.patch
eprefixify epm
}
diff --git a/app-portage/epm/files/epm b/app-portage/epm/files/epm
new file mode 100644
index 0000000..29d3d2f
--- /dev/null
+++ b/app-portage/epm/files/epm
@@ -0,0 +1,984 @@
+#!/usr/bin/perl -wI.
+
+use Getopt::Long;
+use Cwd qw(abs_path);
+
+# Global vars
+my $version = "EPM version 1.40";
+my $verbose = 0;
+my $dbpath = '/var/db/pkg';
+my $pkgregex =
+ '^.+?\/'. # group (ignored)
+ '(.+?)'. # name
+ '-(\d+(?:\.\d+)*\w*)'. # version, eg 1.23.4a
+ '((?:(?:_alpha|_beta|_pre|_rc)\d*)?)'. # special suffix
+ '((?:-r\d+)?)$'; # revision, eg r12
+my $root = '/';
+my %opt = (
+ 'dbpath' => \$dbpath,
+ 'root' => \$root,
+ 'v' => \$verbose,
+);
+my $exitcode = 0;
+
+##############################################
+#
+# UTILITY FUNCTIONS
+#
+##############################################
+sub verb
+{
+ print STDERR map "-- $_\n", @_ if $verbose;
+}
+
+sub vverb
+{
+ print STDERR map "-- $_\n", @_ if $verbose > 1;
+}
+
+##############################################
+#
+# DATABASE FUNCTIONS
+#
+# @dgrps contains a list of all the groups at dbpath
+# @dpkgs contains a list of all the packages at dbpath/@dgrps
+# %dnampkg contains a mapping of nam=>@pkg (libxml=>[libxml-1.8.13])
+# %dfilepkg is a mapping of filename=>@pkg
+#
+##############################################
+
+my (@dgrps, @dpkgs, %dnampkg);
+
+sub load_database()
+{
+ # Check if the database is already loaded
+ return if @dgrps;
+
+ # Read all groups in the db (except for virtual)
+ opendir D, $dbpath or
+ die "epm: Database not found at $dbpath\n";
+ @dgrps = grep {-d "$dbpath/$_" && !/^\./ && $_ ne 'virtual'} readdir D;
+ closedir D;
+ verb "read ".@dgrps." groups from $dbpath"; vverb @dgrps;
+
+ # Read all pkgs in the db (except for virtual)
+ for my $g (@dgrps) {
+ opendir D, "$dbpath/$g" or
+ die "epm: Error reading directory $dbpath/$g\n";
+ my @dp = grep { !/^\./ &&
+ -d "$dbpath/$g/$_" &&
+ !-f "$dbpath/$g/$_/VIRTUAL" } readdir D;
+ @dp = map $g."/".$_, @dp;
+ verb "read ".@dp." pkgs in group $g"; vverb @dp;
+ push @dpkgs, @dp;
+ }
+
+ # Create association of names => pkgs
+ for my $p (@dpkgs) {
+ $p =~ /$pkgregex/o || $p =~ /^virtual/ ||
+ die "epm: Could't parse name/version/suffix/rev from $p";
+ # $2, $3, $4 aren't used right now, but they're in the regex
+ # for the sake of completeness.
+ push @{$dnampkg{$1}}, $p;
+ }
+}
+
+sub cmppkg($$)
+{
+ my ($p1, $p2) = (shift, shift);
+ # Remove the group from the beginning
+ $p1 =~ s#.*/##;
+ $p2 =~ s#.*/##;
+ # Apply the regex
+ # [0] = name, [1] = version, [2] = special suffix, [3] = revision
+ my (@p1) = ($p1 =~ /$pkgregex/o);
+ die "epm: Couldn't parse name/version/suffix/rev from $p1" unless @p1;
+ my (@p2) = ($p2 =~ /$pkgregex/o);
+ die "epm: Couldn't parse name/version/suffix/rev from $p2" unless @p2;
+
+ #
+ # Compare VERSION (element 1)
+ #
+
+ # Split on .
+ my (@v1) = split /\./, $p1[1];
+ my (@v2) = split /\./, $p2[1];
+ # Make trailing letters their own element in the array
+ if ($v1[-1] =~ s/[a-z]+$//) { push @v1, $& }
+ if ($v2[-1] =~ s/[a-z]+$//) { push @v1, $& }
+ # Compare each element in turn
+ for (my $i = 0; $i < @v1 && $i < @v2; $i++) {
+ if ($v1[$i] =~ /^\d+$/) {
+ if ($v2[$i] =~ /^\d+$/) {
+ if ($v1[$i] != $v2[$i]) {
+ # 2 <=> 3
+ return $v1[$i] <=> $v2[$i];
+ } else {
+ # 2 == 2
+ next; # 2 == 2
+ }
+ } else {
+ # 1.2.1 is newer than 1.2a
+ return -1;
+ }
+ } elsif ($v2[$i] =~ /^\d+$/) {
+ # 1.2a is older than 1.2.1
+ return 1;
+ } elsif ($i != $#v1 || $i != $#v2) {
+ # 1.2a.3 is not a legal version
+ die "Error in comparing versions: $p1 vs. $p2";
+ } elsif ($v1[$i] ne $v2[$i]) {
+ # 1.2a <=> 1.2c
+ return $v1[$i] cmp $v2[$i];
+ }
+ # These elements are equal, just continue
+ }
+
+ #
+ # Compare SPECIAL SUFFIX (element 2)
+ #
+ #
+ if ($p1[2] eq '' && $p2[2] ne '') {
+ # 1.2 is newer than 1.2_pre1
+ return 1;
+ } elsif ($p1[2] ne '' && $p2[2] eq '') {
+ # 1.2_pre1 is older than 1.2
+ return -1;
+ } elsif ($p1[2] ne '' && $p2[2] ne '') {
+ my (%sufs) = qw/p 0 alpha 1 beta 2 pre 3 rc 4/;
+ die "Illegal suffix in $p1" unless defined $sufs{$p1[2]};
+ die "Illegal suffix in $p2" unless defined $sufs{$p2[2]};
+ }
+
+ # This isn't finished. What was I doing here?
+}
+
+##############################################
+#
+# QUERY MODE
+#
+##############################################
+
+# Utility function to sum the size of a package on the filesystem
+# in bytes
+sub pkg_bytes($)
+{
+ my ($p) = @_;
+ my $total = 0;
+ my $CONTENTS;
+
+ $CONTENTS = "$dbpath/$p/CONTENTS";
+
+ open F, "<$CONTENTS" or die "epm: Can't open $CONTENTS\n"
+ or die "epm: Can't open $CONTENTS: $!\n";
+ for my $f (grep /^obj/, <F>) {
+ $f =~ s/^obj (.+) \w+ \d+\s*$/$1/;
+ my ($size) = (stat($f))[7];
+ next unless $size;
+ verb "Adding $f ($size bytes)";
+ $total += $size;
+ }
+ close F;
+ return $total;
+}
+
+# Utility function to do -qi
+sub query_info($)
+{
+ my ($p) = @_;
+ my ($group, $ename) = $p =~ /^(.+?)\/(.+)$/;
+ my ($key, $value);
+ my %vals = map {$_, '(n/a)'} qw/CATEGORY HOSTNAME DESCRIPTION URL LICENSE NAME RELEASE VERSION SLOT PACKAGER/;
+ my $ldbpath = "$dbpath/$p";
+ my $fmt = <<EOT;
+Name : \%s
+Version : \%s
+Release : \%-28s Slot: \%s
+Install date: \%-28s Build Host: \%s
+Group : \%-28s License: \%s
+Size : \%s
+Packager : \%s
+URL : \%s
+Summary : \%s
+EOT
+ # Extract some information from files stored in the Portage pkgdb
+ open(F, "bzcat $ldbpath/environment.bz2|")
+ or die "epm: Can't open $ldbpath/environment.bz2: $!\n";
+ while (<F>) {
+ next unless (/^(?:declare\s+(?:-[x-]\s+)*)?(CATEGORY|HOSTNAME|DESCRIPTION|HOMEPAGE|LICENSE|PN|PR|PV|SLOT)=(.*)/);
+ ($key, $value) = ($1, $2);
+ if ($key eq 'PN') {
+ $key = 'NAME';
+ } elsif ($key eq 'PR') {
+ $key = 'RELEASE';
+ $value =~ s/^r0?//o;
+ } elsif ($key eq 'PV') {
+ $key = 'VERSION';
+ } elsif ($key eq 'HOMEPAGE') {
+ $key = 'URL';
+ $value = '(none)' unless $value;
+ }
+ # Clean up the double and single quotes
+ $value =~ s/^'(.*)'$/$1/o;
+ $value =~ s/^"(.*)"$/$1/o;
+ $value =~ s/'\\''/'/go;
+ $value =~ s/\\"/"/go;
+
+ $vals{$key} = $value;
+ }
+ close(F);
+
+ # When was this last built/installed?
+ $vals{'DATE'} = localtime((stat "$ldbpath/USE")[9]);
+
+ # Calculate the SIZE for the files it uses on the filesystem
+ $vals{'SIZE'} = $opt{'nosize'} ? '' : pkg_bytes($p);
+
+ # Extract the packager and description from the ebuild itself
+ open(F, "$ldbpath/$ename.ebuild")
+ or die "epm: Can't open $ldbpath/$p.ebuild: $!\n";
+ while (<F>) {
+ if (/Header:.*:\d\d (\w+)/o) {
+ $vals{'PACKAGER'} = $1;
+ last;
+ }
+ }
+ close(F);
+
+ printf $fmt, $vals{'NAME'}, $vals{'VERSION'}, $vals{'RELEASE'},
+ $vals{'SLOT'}, $vals{'DATE'}, $vals{'HOSTNAME'}, $group,
+ $vals{'LICENSE'}, $vals{'SIZE'}, $vals{'PACKAGER'}, $vals{'URL'},
+ $vals{'DESCRIPTION'};
+}
+
+# Utility function to do -ql
+sub query_list($)
+{
+ my ($p) = @_;
+ my ($CONTENTS) = "$dbpath/$p/CONTENTS";
+ my (@files);
+
+ open F, "<$CONTENTS" || die "epm: Can't open $CONTENTS\n";
+ @files = <F>;
+ close F;
+
+ # Look up CONFIG_PROTECT if -c
+ if ($opt{'c'}) {
+ # Read in CONFIG_PROTECT from /etc/make.{global,conf}
+ my (@CONFIG_PROTECT) = split ' ',
+ `. /etc/make.globals; . /etc/make.conf; echo \$CONFIG_PROTECT`;
+ die "CONFIG_PROTECT is empty" unless @CONFIG_PROTECT;
+ my ($confprotre) = join '|', @CONFIG_PROTECT;
+ @files = grep {
+ (split ' ', $_, 2)[1] =~ /^($confprotre)/o } @files;
+ }
+
+ # Trim @files if doc files requested
+ if ($opt{'d'}) {
+ # We don't have a variable like CONFIG_PROTECT to work
+ # with, so just fake it... :-)
+ @files = grep {
+ (split ' ', $_, 2)[1] =~ m/\/(?:doc|man|info)\//o } @files;
+ }
+
+ # If this is a dump query, then print the entire array
+ if ($opt{'dump'}) {
+ print @files;
+ } else {
+ print grep {
+ s{^obj (.+?)(?:/\.keep[^\s/]*)? \w+ \d+\s*?}{$1} ||
+ s{^sym (\S.*?) -> .*$}{$1} } @files;
+ }
+}
+
+# Utility function to do -qf
+sub query_file(@)
+{
+ my (@pkgs) = @_;
+ # Search through CONTENTS for elements in ARGV. Building an
+ # index would be bad because it would be HUGE.
+ for my $a (@ARGV) {
+ my $found = 0;
+ my $origa = $a;
+
+ # Try to get the absolute path before searching
+ $a = abs_path($a) || $a;
+
+ # TODO: stat the file here so that we can determine later
+ # what package the file currently belongs to
+ for my $p (@dpkgs) {
+ my $CONTENTS = "$dbpath/$p/CONTENTS";
+
+ unless (-s $CONTENTS) {
+ verb "skipping empty/nonexistent $CONTENTS";
+ next;
+ }
+ open F, "<$CONTENTS" or die "epm: Can't open $CONTENTS\n";
+ # Check this list of files for the current query
+ while (my $f = <F>) {
+ chomp($f);
+ $f =~ s/^dir // or
+ $f =~ s/^obj (.+) \w+ \d+\s*$/$1/ or
+ $f =~ s/^sym (\S.*?) -> .*$/$1/ or next;
+ next unless $f eq $a;
+ $found = 1;
+ push @pkgs, $p;
+ }
+ close F;
+ }
+ unless ($found) {
+ if (-e $a) { print "file $origa is not owned by any package\n"; }
+ else { print "file $origa: No such file or directory\n"; }
+ $exitcode = 1;
+ }
+ }
+ return @pkgs;
+}
+
+# Utility function to do -V
+sub verify($)
+{
+ my ($p) = @_;
+ my ($CONTENTS) = "$dbpath/$p/CONTENTS";
+ verb "verifying $p";
+
+ # CONTENTS consists of lines such as
+ # dir /usr/bin
+ # obj /usr/bin/qpkg e4a2da62aabb399c537ea9fa92b5af29 1034786384
+ open F, "<$CONTENTS" || die "epm: Can't open $CONTENTS\n";
+
+ # Verify directories and files
+ # XXX should label config files with 'c'
+ while ($f = <F>) {
+ chomp($f);
+ if ($f =~ /^obj (.+) (\w+) (\d+)\s*$/o) {
+ my ($Cname, $Cmd5, $Cmtime) = ($1, $2, $3);
+ my ($md5, $mtime);
+ vverb "$Cname: $Cmd5 $Cmtime";
+ if (! -f $Cname) {
+ print "missing $Cname\n" unless ($opt{'nofiles'});
+ next;
+ }
+ unless ($opt{'nomd5'}) {
+ if (-r _) {
+ ($md5 = `md5sum "$Cname"`) =~ s/\s.*//s;
+ } else {
+ $md5 = 'UNKNOWN';
+ }
+ # only report this if it's calculated.
+ vverb "Md5 is $md5 for $Cname";
+ }
+ $mtime = (stat _)[9];
+ vverb "Mtime is $mtime for $Cname";
+ # XXX size, device, user, group, and mode are not checked... :-(
+ next if (($opt{'nomd5'} or $md5 eq $Cmd5) and $mtime eq $Cmtime);
+ printf "..%s....%s %s\n",
+ ($md5 ne $Cmd5) ? ($md5 eq 'UNKNOWN') ? '?' : '5' : '.',
+ ($mtime ne $Cmtime) ? 'T' : '.', $Cname;
+ if ($md5 ne $Cmd5) { $exitcode = 1; }
+ next;
+ }
+ if ($f =~ /^dir (.+)/o) {
+ print "missing $1\n" unless (-d $1 or $opt{'nofiles'});
+ next;
+ }
+ if ($f =~/^sym (.+) -> (.+) (\d+)$/o) {
+ my ($Cname, $Clink, $Cmtime) = ($1, $2, $3);
+ my ($link, $mtime);
+ my ($modeok);
+
+ if (! -e $Cname) {
+ print "missing $Cname\n" unless ($opt{'nofiles'});
+ next;
+ }
+ vverb "$Cname -> $Clink $Cmtime";
+ $mtime = (stat $Cname)[9];
+ if (-l $Cname) {
+ $modeok = 1;
+ $link = readlink($Cname);
+ } else {
+ $modeok = 0;
+ $link = '';
+ }
+ next if ($modeok
+ and defined ($link)
+ and $Clink eq $link
+ and defined ($mtime)
+ and $Cmtime eq $mtime);
+ printf ".%s..%s..%s %s\n",
+ $modeok ? '.' : 'M',
+ defined($link) ? ($Clink ne $link) ? 'L' : '.' : '?',
+ defined($mtime) ? ($Cmtime ne $mtime) ? 'T' : '.' : '?',
+ $Cname;
+ next;
+ }
+ # XXX presently ignoring devices
+ }
+ close F;
+}
+
+sub query()
+{
+ verb "query mode";
+ verb "actually Verify mode" if $opt{'V'};
+
+ # Load the database which is needed for query mode
+ load_database();
+ my (@pkgs); # list of packages being queried
+
+ # Package-based query (how does this work with emerge?)
+ if ($opt{'p'}) {
+ die "epm: Sorry, package-based query not yet supported\n";
+ }
+
+ # Implied -l similar to rpm
+ $opt{'dump'} and $opt{'l'} = 1;
+ $opt{'d'} and $opt{'l'} = 1;
+ $opt{'c'} and $opt{'l'} = 1;
+
+ # File-based query
+ if ($opt{'f'}) {
+ @pkgs = query_file(@pkgs);
+ @ARGV = (); # Clear out ARGV so queries below don't get confused
+ }
+
+ # Group-based query
+ # Note that if -qfg specified, then rpm prioritizes -qf over -qg,
+ # so we do too.
+ elsif ($opt{'g'}) {
+ for my $a (@ARGV) {
+ verb "checking for packages in group $a";
+ my @l = grep /^$a\//, @dpkgs;
+ vverb "packages in group $a:";
+ vverb " ", join "\n ", @l;
+ unless (@l) {
+ print "group $a does not contain any packages\n";
+ $exitcode = 1;
+ }
+ push @pkgs, @l;
+ }
+ @ARGV = (); # Clear out ARGV so queries below don't get confused
+ }
+
+ # Query on all packages
+ if ($opt{'a'}) {
+ die "epm: extra arguments given for query of all packages\n" if @ARGV;
+ @pkgs = @dpkgs;
+ }
+ elsif (@pkgs) {
+ # must have been populated by, for instance, -qf
+ }
+ else {
+ USERARG: for my $a (@ARGV) {
+ if ($a =~ /$pkgregex/o) {
+ verb "$a matches pkgregex";
+ vverb "name=$1, version=$2, suffix=$3, revision=$4";
+ # user has asked for specific version, check if any
+ # installed version matches
+ for my $pver (@{$dnampkg{$1}}) {
+ vverb "found version: $pver";
+ if ($pver eq $a) {
+ push @pkgs, $a;
+ next USERARG;
+ }
+ }
+ }
+ if (defined $dnampkg{$a}) {
+ verb "$a found in dnampkg";
+ vverb @{$dnampkg{$a}};
+ push @pkgs, @{$dnampkg{$a}};
+ next;
+ }
+ print "package $a is not installed\n";
+ next;
+ }
+ }
+
+ # Sort package order, by reverse mtime
+ if ($opt{'last'}) {
+ my %mtimes;
+ @pkgs = sort {
+ # When was this last built/installed?
+ unless (exists $mtimes{$a}) {
+ $mtimes{$a} = (stat "$dbpath/$a")[9];
+ vverb "$a = $mtimes{$a}";
+ }
+ unless (exists $mtimes{$b}) {
+ $mtimes{$b} = (stat "$dbpath/$b")[9];
+ vverb "$b = $mtimes{$b}";
+ }
+ $mtimes{$b} <=> $mtimes{$a} or $a cmp $b;
+ } @pkgs;
+ }
+
+ for my $p (@pkgs) {
+ # Verify package
+ if ($opt{'V'}) { verify($p); next; }
+
+ # Information query
+ query_info($p) if $opt{'i'};
+
+ # File listing...
+ # We allow this to chain after query_info because rpm allows it.
+ query_list($p) if $opt{'l'};
+
+ # If not another type of listing, then simply list the packages
+ if (!$opt{'l'} && !$opt{'i'}) {
+ # If doing -qS, then include the size in kb, like ls -s
+ printf "%6d ", int(pkg_bytes($p)/1000) if $opt{'S'};
+ # If doing -qG, then include the group name
+ if ($opt{'G'}) {
+ print "$p\n";
+ } else {
+ ($nogrp) = $p =~ /^.+?\/(.+)$/;
+ print "$nogrp\n";
+ }
+ }
+ }
+}
+
+##############################################
+#
+# ERASE MODE
+#
+##############################################
+sub erase()
+{
+ my (@cmd);
+ verb "erase mode";
+ verb "(testing)" if $opt{'test'};
+
+ # Catch empty command-line
+ die "epm: no packages given for uninstall\n" unless @ARGV;
+
+ # Must be root to erase; rpm just lets permissions slide but I don't
+ if ($> != 0) {
+ print STDERR "Must be root to remove packages from the system\n";
+ $exitcode = 1;
+ return;
+ }
+
+ # There's no point implementing erase here. Might as well just
+ # use existing portage features. This means that we do
+ # --allmatches by default.
+ @cmd = qw(emerge --unmerge);
+ push @cmd, '--pretend' if $opt{'test'};
+ push @cmd, '--quiet' unless $opt{'verbose'};
+ push @cmd, @ARGV;
+ system(@cmd);
+ die "epm: Fatal error running emerge\n" if $?;
+}
+
+##############################################
+#
+# MAIN
+#
+##############################################
+
+# Syntax string for errors
+my $syntax = <<EOT;
+$version
+Copyright (C) 2001-2003 - Aron Griffis
+This program may be freely redistributed under the terms of the GNU GPL v2
+'*' leading an option indicates not-yet-implemented
+
+Usage:
+ --help - print this message
+ *--version - print the version of rpm being used
+
+ All modes support the following arguments:
+ -v - be a little more verbose
+ -vv - be incredibly verbose (for debugging)
+
+ -q, --query - query mode
+ --dbpath <dir> - use <dir> as the directory for the database
+ --root <dir> - use <dir> as the top level directory
+ --last - list package(s) by install time, most
+ recent first
+ Package specification options:
+ -a, --all - query all packages
+ -f <file>+ - query package owning <file>
+ *-p <packagefile>+ - query (uninstalled) package <packagefile>
+ *--triggeredby <pkg> - query packages triggered by <pkg>
+ *--whatprovides <cap> - query packages which provide <cap> capability
+ *--whatrequires <cap> - query packages which require <cap> capability
+ -g <group>+ --group <group>+ - query packages in group <group>
+ Information selection options:
+ -i, --info - display package information
+ --nosize - don't display size in info output (not in rpm)
+ -l - display package file list
+ -G, --showgroup - display group name in output (not in rpm)
+ -S, --size - display package size in output (not in rpm)
+ -d - list only documentation files (implies -l)
+ -c - list only configuration files (implies -l)
+ --dump - show all verifiable information for each file
+ (must be used with -l, -c, or -d)
+ *--provides - list capabilities package provides
+ *-R, --requires - list package dependencies
+ *--scripts - print the various [un]install scripts
+
+ --erase <package>
+ -e <package> - erase (uninstall) package
+ --allmatches - remove all packages which match <package>
+ (unlike rpm, this is the default)
+ --dbpath <dir> - use <dir> as the directory for the database
+ *--justdb - update the database, but do not modify the
+ filesystem
+ *--nodeps - do not verify package dependencies
+ *--noorder - do not reorder package installation to satisfy
+ dependencies
+ *--noscripts - do not execute any package specific scripts
+ *--notriggers - don't execute any scripts triggered by this
+ package
+ --root <dir> - use <dir> as the top level directory
+ --test - don't uninstall, but tell what would happen
+
+ -V, -y, --verify - verify a package installation using the same
+ package specification options as -q
+ --dbpath <dir> - use <dir> as the directory for the database
+ *--root <dir> - use <dir> as the top level directory
+ *--nodeps - do not verify package dependencies
+ *--nomd5 - do not verify file md5 checksums
+ *--nofiles - do not verify file attributes
+EOT
+
+# Allow bundling of options since rpm does
+Getopt::Long::Configure ("bundling");
+
+# Parse the options on the cmdline. Put the short versions first in
+# each optionstring so that the hash keys are created using the short
+# versions. For example, use 'q|query', not 'query|q'.
+my $result = GetOptions(
+ \%opt,
+ 'help', # help message
+ 'version', # version message
+ 'v+', # verbose, more v's for more verbosity
+
+ 'q|query', # query mode
+ 'dbpath=s', # use <dir> as the directory for the database
+ 'root=s', # use <dir> as the top level directory
+ 'last', # order package listing by most recent install first
+ # Package specification options:
+ 'a|all', # query all packages
+ 'f', # query package owning file(s)
+ 'p', # query (uninstalled) package
+ 'g|group', # query packages in group(s)
+ 'whatprovides', # query packages which provide capability
+ 'whatrequires', # query packages which require capability
+ # Information selection options:
+ 'i|info', # display package information
+ 'nosize', # don't display size in info output
+ 'l', # display package file list
+ 'd', # list documentation files (implies -l)
+ 'c', # list configuration files (implies -l)
+ 'dump', # show all verifiable information for each file
+ # (must be used with -l, -c, or -d)
+ 'R|requires', # list package dependencies
+ 'scripts', # print the various [un]install scripts
+ 'G|showgroup', # include group name in output
+ 'S|size', # display package size
+
+ 'e|erase', # erase mode
+ 'allmatches', # remove all packages which match <package>
+ 'test', # don't uninstall, but tell what would happen
+
+ 'V|y|verify', # verify a package installation using the same
+ # package specification options as -q
+ 'nodeps', # do not verify package dependencies
+ 'nomd5', # do not verify file md5 checksums
+ 'nofiles', # do not verify file attributes
+);
+
+# Handle help message
+if ($opt{'help'}) { print $syntax; exit 0 }
+if ($opt{'version'}) { print "$version\n"; exit 0 }
+
+# Determine which mode we're running in; make sure it's valid.
+# (q)uery
+# (V)erify
+# (U)pgrade
+# (e)rase
+# (b)uild
+# other
+if ((defined $opt{'q'} || 0) +
+ (defined $opt{'V'} || 0) +
+ (defined $opt{'U'} || 0) +
+ (defined $opt{'e'} || 0) +
+ (defined $opt{'b'} || 0) != 1) {
+ die "$syntax\nOne mode required, and only one mode allowed\n";
+}
+
+# Query mode
+if ($opt{'q'} || $opt{'V'}) { query(); exit $exitcode }
+if ($opt{'e'}) { erase(); exit $exitcode }
+
+# Other modes not implemented yet
+die "epm: Sorry, this mode isn't implemented yet. Check back later! :-)\n";
+
+# Revision 1.4.0 2013-01-23 p2w
+# Fix -qi (bug 310475).
+# New maintainer.
+# Revert the change of v1.33, fix others problems with -qf (Gentoo bugs 93843 and 153921)
+#
+# Revision 1.33 2006/09/13 15:09:19 agriffis
+# Treat dirs the same in -qf as in -ql
+#
+# Revision 1.32 2006/09/13 15:04:49 agriffis
+# Revert 1.30. Listing all intermediate dirs up to a file isn't useful, and doesn't match rpm. Only list dirs that contain .keep files
+#
+# Revision 1.31 2006/09/08 19:35:22 agriffis
+# Switch to cvs-based versioning. Add --version option. Add --last option, based on patch submitted by Tim Stotts #138679
+#
+# Revision 1.30 2006/04/04 21:07:07 mr_bones_
+# display directories as well as files and symlinks when doing query list (-ql)
+# This matches what rpm does. Reported by Steven Elling via Gentoo bugzilla:
+# http://bugs.gentoo.org/show_bug.cgi?id=128186
+#
+# Revision 1.29 2006/03/15 21:49:48 agriffis
+# Leave Size blank instead of n/a when --nosize given
+#
+# Revision 1.28 2006/03/15 21:43:23 agriffis
+# Add --nosize option
+#
+# Revision 1.27 2005/08/29 13:32:35 kanaka
+# Update version to 0.9.0
+#
+# Revision 1.26 2005/08/25 22:03:59 mr_bones_
+# -i is implemented so remove the * from the usage message. (reported by agriffis)
+#
+# Revision 1.25 2005/08/16 20:39:16 kanaka
+# Fix broken regex during file list query
+#
+# Revision 1.24 2005/08/15 20:37:14 kanaka
+# Fix situation where package group is different, but name and version are the same (i.e. crossdev)
+#
+# Revision 1.23 2005/07/05 20:01:36 mr_bones_
+# pass --quiet to emerge when performing -e (erase) to be more like rpm
+#
+# Revision 1.22 2005/06/22 05:28:24 mr_bones_
+# Print out usage if user didn't get the mode specified correctly.
+# Suggested by Tristan Cebulla in
+# http://bugs.gentoo.org/show_bug.cgi?id=96726
+#
+# Revision 1.21 2005/05/18 05:30:14 mr_bones_
+# fix silly check for empty HOMEPAGE
+#
+# Revision 1.20 2005/05/16 03:15:26 mr_bones_
+# Make all the regexs that match the obj lines from CONTENTS be the same.
+#
+# Revision 1.19 2005/05/14 23:50:33 mr_bones_
+# remove "use epm". guessing that was an idea that never materialized
+#
+# Revision 1.18 2005/05/14 23:48:48 mr_bones_
+# Added support for --nofiles in verify() - rpm man page claims it only
+# suppresses reports of missing files. epm suppresses all "missing" reporting
+# if --nofiles is given.
+#
+# Added support for --nomd5 in verify(); fixed up bare word in output.
+#
+# Added initial support for symlinks in verify().
+#
+# Revision 1.17 2005/05/14 22:24:12 mr_bones_
+# no reason to read CONTENTS into memory in query_file(). Modified to read
+# line at a time.
+#
+# Revision 1.16 2005/05/14 22:21:46 mr_bones_
+# Make output more similar to rpm by changing "Description" to "Summary"
+# in output. Maybe at some point the extended description from metadata.xml
+# will be stored in portage and can be extracted then by epm for Description.
+# Also changed "Build Host" from CHOST to HOSTNAME.
+#
+# Modified to read environment.bz2 instead of the ebuild for some values.
+# This is more reliable because environment.bz2 is the state after ebuild
+# and eclass processing. Epm was confused by ebuilds that have the HOMEPAGE
+# and DESCRIPTION in an eclass. (eg. xmms-mpg123)
+#
+# Fixed up display of values that contain double and single quotes
+# (eg. libmad)
+#
+# Added error checking for open()
+#
+# Revision 1.15 2005/05/14 21:55:25 mr_bones_
+# Pass long option (--unmerge) to emerge instead of short option (-C)
+# for better readability.
+#
+# Revision 1.14 2005/05/14 21:47:51 mr_bones_
+# fix bug in pkg_bytes() where files with whitespace in their name would
+# cause incorrect behavior.
+#
+# Revision 1.13 2005/05/14 21:38:10 mr_bones_
+# prototype functions
+#
+# Revision 1.12 2005/05/14 21:30:44 mr_bones_
+# Use correct variable in error message ($p -> $p1/$p2)
+#
+# Revision 1.11 2005/05/14 20:54:19 mr_bones_
+# Trim trailing whitespace
+#
+# Revision 1.10 2005/05/13 20:47:44 agriffis
+# epm-0.8.8
+#
+# Revision 1.20 2004/04/28 13:22:41 agriffis
+# - Fix printing of symlinks in -ql to exclude link target
+#
+# Revision 1.19 2004/04/05 04:37:46 agriffis
+# - Add patch from Michael Sterret in bug 45927 to handle whitespace
+# in filenames
+#
+# Revision 1.18 2004/03/29 16:47:34 agriffis
+# Fix bug 45927: Handle filenames with spaces correctly
+# Update version to 0.8.6
+#
+# Revision 1.17 2004/03/08 23:23:39 agriffis
+# - Update to 0.8.5
+#
+# Revision 1.16 2004/03/08 23:21:46 agriffis
+# - Added size option to -qi and -qS
+# - Thanks to Bram Dumolin (http://lanka-expats.net/) for the idea and
+# an initial effort at the code
+#
+# Revision 1.15 2003/05/27 01:36:01 agriffis
+# - Update to 0.8.4
+#
+# Revision 1.14 2003/05/27 01:33:41 agriffis
+# - Include patch from Michael Sterrett <msterret@gentoo.org> to display URL
+# in -qi output
+#
+# Revision 1.13 2003/05/02 02:00:22 agriffis
+# - Update to 0.8.3
+# - Check if file exists to choose error message for -qf
+#
+# Revision 1.12 2003/05/01 02:42:39 agriffis
+# - Add man-page in pod format inside epm
+#
+# Revision 1.11 2003/05/01 01:53:09 agriffis
+# - Update version to 0.8.2; forgot to checkin 0.8.1
+# - Fix bug 8832: Add code to determine full path for epm -qf.
+# Reported by Bill Gjestvang, patch provided by Wayne Davison.
+# - Fix bug 12798: Fix -V output for unreadable files
+# Reported and patched by Wayne Davison.
+# - Fix bug 19806: Need double-quotes to interpret \n on die message
+# Reported and patched by Scott Hunt
+# - Fix bug 19681: Check for requested version on epm -q.
+# Reported by Neil McCalden, patch provided by Wayne Davison.
+#
+# Revision 1.10 2002/10/22 13:55:00 agriffis
+# - Fix version reporting in help message
+# - Fix unmerging to use -C instead of non-existent --unmerge
+#
+# Revision 1.9 2002/10/22 13:48:47 agriffis
+# - Fixed erase -e to do something when not --test
+#
+# Revision 1.8 2002/10/22 13:44:08 agriffis
+# - Fix bug in -qa which listed too many packages
+#
+# Revision 1.7 2002/10/22 13:31:47 agriffis
+# - Split out query types into separate functions
+# - Add sub cmppkg which was for --update but might be abandoned
+# - Add information query -qi
+# - Add first-pass verification -V
+# - Change erase -e to use emerge (which maintains world)
+#
+
+=head1 NAME
+
+epm - rpm workalike for Gentoo
+
+=head1 SYNOPSIS
+
+epm { -eqVy | --erase | --help | --query | --verify } options...
+
+=head1 DESCRIPTION
+
+This tool provides a Gentoo query tool for users familiar with Red
+Hat's "rpm" package manager. In particular, it can query, verify, and
+erase packages from the system. I've tried to make it act as much
+like rpm as possible, but there are some differences made necessary by
+the differences in the distributions.
+
+Querying and verifying are the most powerful features of epm. Erase
+mode is really just a gate to "emerge -C", but force of habit makes it
+easier for me to type "epm -e".
+
+=head1 MODES
+
+=over
+
+=item B<-q --query>
+
+Query mode, for querying either the list of installed packages or the
+files owned by a package.
+
+=item B<-V -y --verify>
+
+Verify mode, for determining the integrity of an installed package
+using timestamps and md5 sums. Size, device, user, group, and mode
+are not presently checked.
+
+=item B<-e --erase>
+
+Erase mode, for removing packages from the system. Specify a package
+by version to remove a specific package. Specify a package by name to
+remove all versions (i.e. --allmatches is the default for epm, this is
+a difference from rpm).
+
+=item B<--help>
+
+This isn't really a mode, but it's the only thing you can do without
+otherwise specifying a mode. Run "epm --help" to see the
+comprehensive list of options available for each mode.
+
+=back
+
+=head1 EXAMPLES
+
+To find out if vim is installed:
+
+ $ epm -q vim
+ vim-6.2_pre2
+
+To include the group in the output:
+
+ $ epm -qG vim
+ app-editors/vim-6.2_pre2
+
+To see what binaries vim installs:
+
+ $ epm -ql vim | grep bin
+ /usr/bin/ex
+ /usr/bin/vim
+ /usr/bin/rvim
+ /usr/bin/view
+ /usr/bin/rview
+ /usr/bin/vimdiff
+
+To find what package owns /usr/bin/vim
+
+ $ epm -qf /usr/bin/vim
+ vim-6.2_pre2
+
+To verify your installation of vim:
+
+ $ epm -V vim
+
+No output indicates the installation is fine. If you get some other
+output when you verify a package installation, try the following link
+for an explanation. http://www.rpm.org/max-rpm/s1-rpm-verify-output.html
+
+To show all vim related packages on the system:
+
+ $ epm -qa | grep vim
+ vim-core-6.2_pre2
+ vim-6.2_pre2
+ gvim-6.2_pre2
+
+=head1 NOTES
+
+This tool was written by Aron Griffis. Currently, Peter Weilbacher
+<peter@weilbacher.org> tries to maintain it.
+It will probably blow up your computer, but it works well enough for
+me. If you report bugs at http://bugs.gentoo.org/, assigned to Peter,
+they might get fixed. Your chances increase a lot if you include a
+good patch.
+
+=cut