/[gentoo-src]/epm/epm
Gentoo

Contents of /epm/epm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.33 - (show annotations) (download)
Wed Sep 13 15:09:19 2006 UTC (8 years ago) by agriffis
Branch: MAIN
CVS Tags: HEAD
Changes since 1.32: +7 -5 lines
Treat dirs the same in -qf as in -ql

1 #!/usr/bin/perl -wI.
2 # $Id: epm,v 1.32 2006/09/13 15:04:49 agriffis Exp $
3
4 use Getopt::Long;
5 use Cwd qw(abs_path);
6
7 # Global vars
8 (my $version = '$Revision: 1.32 $') =~ s/.*?(\d.*\d).*/EPM version $1/;
9 my $verbose = 0;
10 my $dbpath = '/var/db/pkg';
11 my $pkgregex =
12 '^.+?\/'. # group (ignored)
13 '(.+?)'. # name
14 '-(\d+(?:\.\d+)*\w*)'. # version, eg 1.23.4a
15 '((?:(?:_alpha|_beta|_pre|_rc)\d*)?)'. # special suffix
16 '((?:-r\d+)?)$'; # revision, eg r12
17 my $root = '/';
18 my %opt = (
19 'dbpath' => \$dbpath,
20 'root' => \$root,
21 'v' => \$verbose,
22 );
23 my $exitcode = 0;
24
25 ##############################################
26 #
27 # UTILITY FUNCTIONS
28 #
29 ##############################################
30 sub verb
31 {
32 print STDERR map "-- $_\n", @_ if $verbose;
33 }
34
35 sub vverb
36 {
37 print STDERR map "-- $_\n", @_ if $verbose > 1;
38 }
39
40 ##############################################
41 #
42 # DATABASE FUNCTIONS
43 #
44 # @dgrps contains a list of all the groups at dbpath
45 # @dpkgs contains a list of all the packages at dbpath/@dgrps
46 # %dnampkg contains a mapping of nam=>@pkg (libxml=>[libxml-1.8.13])
47 # %dfilepkg is a mapping of filename=>@pkg
48 #
49 ##############################################
50
51 my (@dgrps, @dpkgs, %dnampkg);
52
53 sub load_database()
54 {
55 # Check if the database is already loaded
56 return if @dgrps;
57
58 # Read all groups in the db (except for virtual)
59 opendir D, $dbpath or
60 die "epm: Database not found at $dbpath\n";
61 @dgrps = grep {-d "$dbpath/$_" && !/^\./ && $_ ne 'virtual'} readdir D;
62 closedir D;
63 verb "read ".@dgrps." groups from $dbpath"; vverb @dgrps;
64
65 # Read all pkgs in the db (except for virtual)
66 for my $g (@dgrps) {
67 opendir D, "$dbpath/$g" or
68 die "epm: Error reading directory $dbpath/$g\n";
69 my @dp = grep { !/^\./ &&
70 -d "$dbpath/$g/$_" &&
71 !-f "$dbpath/$g/$_/VIRTUAL" } readdir D;
72 @dp = map $g."/".$_, @dp;
73 verb "read ".@dp." pkgs in group $g"; vverb @dp;
74 push @dpkgs, @dp;
75 }
76
77 # Create association of names => pkgs
78 for my $p (@dpkgs) {
79 $p =~ /$pkgregex/o || $p =~ /^virtual/ ||
80 die "epm: Could't parse name/version/suffix/rev from $p";
81 # $2, $3, $4 aren't used right now, but they're in the regex
82 # for the sake of completeness.
83 push @{$dnampkg{$1}}, $p;
84 }
85 }
86
87 sub cmppkg($$)
88 {
89 my ($p1, $p2) = (shift, shift);
90 # Remove the group from the beginning
91 $p1 =~ s#.*/##;
92 $p2 =~ s#.*/##;
93 # Apply the regex
94 # [0] = name, [1] = version, [2] = special suffix, [3] = revision
95 my (@p1) = ($p1 =~ /$pkgregex/o);
96 die "epm: Couldn't parse name/version/suffix/rev from $p1" unless @p1;
97 my (@p2) = ($p2 =~ /$pkgregex/o);
98 die "epm: Couldn't parse name/version/suffix/rev from $p2" unless @p2;
99
100 #
101 # Compare VERSION (element 1)
102 #
103
104 # Split on .
105 my (@v1) = split /\./, $p1[1];
106 my (@v2) = split /\./, $p2[1];
107 # Make trailing letters their own element in the array
108 if ($v1[-1] =~ s/[a-z]+$//) { push @v1, $& }
109 if ($v2[-1] =~ s/[a-z]+$//) { push @v1, $& }
110 # Compare each element in turn
111 for (my $i = 0; $i < @v1 && $i < @v2; $i++) {
112 if ($v1[$i] =~ /^\d+$/) {
113 if ($v2[$i] =~ /^\d+$/) {
114 if ($v1[$i] != $v2[$i]) {
115 # 2 <=> 3
116 return $v1[$i] <=> $v2[$i];
117 } else {
118 # 2 == 2
119 next; # 2 == 2
120 }
121 } else {
122 # 1.2.1 is newer than 1.2a
123 return -1;
124 }
125 } elsif ($v2[$i] =~ /^\d+$/) {
126 # 1.2a is older than 1.2.1
127 return 1;
128 } elsif ($i != $#v1 || $i != $#v2) {
129 # 1.2a.3 is not a legal version
130 die "Error in comparing versions: $p1 vs. $p2";
131 } elsif ($v1[$i] ne $v2[$i]) {
132 # 1.2a <=> 1.2c
133 return $v1[$i] cmp $v2[$i];
134 }
135 # These elements are equal, just continue
136 }
137
138 #
139 # Compare SPECIAL SUFFIX (element 2)
140 #
141 #
142 if ($p1[2] eq '' && $p2[2] ne '') {
143 # 1.2 is newer than 1.2_pre1
144 return 1;
145 } elsif ($p1[2] ne '' && $p2[2] eq '') {
146 # 1.2_pre1 is older than 1.2
147 return -1;
148 } elsif ($p1[2] ne '' && $p2[2] ne '') {
149 my (%sufs) = qw/p 0 alpha 1 beta 2 pre 3 rc 4/;
150 die "Illegal suffix in $p1" unless defined $sufs{$p1[2]};
151 die "Illegal suffix in $p2" unless defined $sufs{$p2[2]};
152 }
153
154 # This isn't finished. What was I doing here?
155 }
156
157 ##############################################
158 #
159 # QUERY MODE
160 #
161 ##############################################
162
163 # Utility function to sum the size of a package on the filesystem
164 # in bytes
165 sub pkg_bytes($)
166 {
167 my ($p) = @_;
168 my $total = 0;
169 my $CONTENTS;
170
171 $CONTENTS = "$dbpath/$p/CONTENTS";
172
173 open F, "<$CONTENTS" or die "epm: Can't open $CONTENTS\n"
174 or die "epm: Can't open $CONTENTS: $!\n";
175 for my $f (grep /^obj/, <F>) {
176 $f =~ s/^obj (.+) \w+ \d+\s*$/$1/;
177 my ($size) = (stat($f))[7];
178 next unless $size;
179 verb "Adding $f ($size bytes)";
180 $total += $size;
181 }
182 close F;
183 return $total;
184 }
185
186 # Utility function to do -qi
187 sub query_info($)
188 {
189 my ($p) = @_;
190 my ($group, $ename) = $p =~ /^(.+?)\/(.+)$/;
191 my ($key, $value);
192 my %vals;
193 my $ldbpath = "$dbpath/$p";
194 my $fmt = <<EOT;
195 Name : \%s
196 Version : \%s
197 Release : \%-28s Slot: \%s
198 Install date: \%-28s Build Host: \%s
199 Group : \%-28s License: \%s
200 Size : \%s
201 Packager : \%s
202 URL : \%s
203 Summary : \%s
204 EOT
205 # Extract some information from files stored in the Portage pkgdb
206 open(F, "bzcat $ldbpath/environment.bz2|")
207 or die "epm: Can't open $ldbpath/environment.bz2: $!\n";
208 while (<F>) {
209 next unless (/^(CATEGORY|HOSTNAME|DESCRIPTION|HOMEPAGE|LICENSE|PN|PR|PV|SLOT)=(.*)/);
210 ($key, $value) = ($1, $2);
211 if ($key eq 'PN') {
212 $key = 'NAME';
213 } elsif ($key eq 'PR') {
214 $key = 'RELEASE';
215 $value =~ s/^r0?//o;
216 } elsif ($key eq 'PV') {
217 $key = 'VERSION';
218 } elsif ($key eq 'HOMEPAGE') {
219 $key = 'URL';
220 $value = '(none)' unless $value;
221 }
222 # Clean up the double and single quotes
223 $value =~ s/^'(.*)'$/$1/o;
224 $value =~ s/'\\''/'/go;
225 $value =~ s/\\"/"/go;
226
227 $vals{$key} = $value;
228 }
229 close(F);
230
231 # When was this last built/installed?
232 $vals{'DATE'} = localtime((stat "$ldbpath/USE")[9]);
233
234 # Calculate the SIZE for the files it uses on the filesystem
235 $vals{'SIZE'} = $opt{'nosize'} ? '' : pkg_bytes($p);
236
237 # Extract the packager and description from the ebuild itself
238 open(F, "$ldbpath/$ename.ebuild")
239 or die "epm: Can't open $ldbpath/$p.ebuild: $!\n";
240 while (<F>) {
241 if (/Header:.*:\d\d (\w+)/o) {
242 $vals{'PACKAGER'} = $1;
243 last;
244 }
245 }
246 close(F);
247
248 printf $fmt, $vals{'NAME'}, $vals{'VERSION'}, $vals{'RELEASE'},
249 $vals{'SLOT'}, $vals{'DATE'}, $vals{'HOSTNAME'}, $group,
250 $vals{'LICENSE'}, $vals{'SIZE'}, $vals{'PACKAGER'}, $vals{'URL'},
251 $vals{'DESCRIPTION'};
252 }
253
254 # Utility function to do -ql
255 sub query_list($)
256 {
257 my ($p) = @_;
258 my ($CONTENTS) = "$dbpath/$p/CONTENTS";
259 my (@files);
260
261 open F, "<$CONTENTS" || die "epm: Can't open $CONTENTS\n";
262 @files = <F>;
263 close F;
264
265 # Look up CONFIG_PROTECT if -c
266 if ($opt{'c'}) {
267 # Read in CONFIG_PROTECT from /etc/make.{global,conf}
268 my (@CONFIG_PROTECT) = split ' ',
269 `. /etc/make.globals; . /etc/make.conf; echo \$CONFIG_PROTECT`;
270 die "CONFIG_PROTECT is empty" unless @CONFIG_PROTECT;
271 my ($confprotre) = join '|', @CONFIG_PROTECT;
272 @files = grep {
273 (split ' ', $_, 2)[1] =~ /^($confprotre)/o } @files;
274 }
275
276 # Trim @files if doc files requested
277 if ($opt{'d'}) {
278 # We don't have a variable like CONFIG_PROTECT to work
279 # with, so just fake it... :-)
280 @files = grep {
281 (split ' ', $_, 2)[1] =~ m/\/(?:doc|man|info)\//o } @files;
282 }
283
284 # If this is a dump query, then print the entire array
285 if ($opt{'dump'}) {
286 print @files;
287 } else {
288 print grep {
289 s{^obj (.+?)(?:/\.keep[^\s/]*)? \w+ \d+\s*?}{$1} ||
290 s{^sym (\S.*?) -> .*$}{$1} } @files;
291 }
292 }
293
294 # Utility function to do -qf
295 sub query_file(@)
296 {
297 my (@pkgs) = @_;
298 # Search through CONTENTS for elements in ARGV. Building an
299 # index would be bad because it would be HUGE.
300 for my $a (@ARGV) {
301 my $found = 0;
302 my $origa = $a;
303
304 # Trim trailing slashes from directories
305 $a =~ s#/*$##;
306
307 # If it's a relative pathname, then figure out the full pathname
308 if ($a !~ m#^/# || $a =~ m#/\.\./#) {
309 # Make the pathname absolute
310 if ($a =~ s#/([^/]+)$##) {
311 my $name = $1;
312 $a = abs_path($a) . '/' . $name;
313 }
314 else {
315 $a = abs_path('.') . '/' . $a;
316 }
317 }
318 # TODO: stat the file here so that we can determine later
319 # what package the file currently belongs to
320 for my $p (@dpkgs) {
321 my $CONTENTS = "$dbpath/$p/CONTENTS";
322
323 unless (-s $CONTENTS) {
324 verb "skipping empty/nonexistent $CONTENTS";
325 next;
326 }
327 open F, "<$CONTENTS" or die "epm: Can't open $CONTENTS\n";
328 # Check this list of files for the current query
329 while (my $f = <F>) {
330 chomp($f);
331 $f =~ s{^obj (.+?)(?:/\.keep[^\s/]*)? \w+ \d+\s*?}{$1} or
332 $f =~ s{^sym (\S.*?) -> .*$}{$1} or next;
333 next unless $f eq $a;
334 $found = 1;
335 push @pkgs, $p;
336 }
337 close F;
338 }
339 unless ($found) {
340 if (-e $a) { print "file $origa is not owned by any package\n"; }
341 else { print "file $origa: No such file or directory\n"; }
342 $exitcode = 1;
343 }
344 }
345 return @pkgs;
346 }
347
348 # Utility function to do -V
349 sub verify($)
350 {
351 my ($p) = @_;
352 my ($CONTENTS) = "$dbpath/$p/CONTENTS";
353 verb "verifying $p";
354
355 # CONTENTS consists of lines such as
356 # dir /usr/bin
357 # obj /usr/bin/qpkg e4a2da62aabb399c537ea9fa92b5af29 1034786384
358 open F, "<$CONTENTS" || die "epm: Can't open $CONTENTS\n";
359
360 # Verify directories and files
361 # XXX should label config files with 'c'
362 while ($f = <F>) {
363 chomp($f);
364 if ($f =~ /^obj (.+) (\w+) (\d+)\s*$/o) {
365 my ($Cname, $Cmd5, $Cmtime) = ($1, $2, $3);
366 my ($md5, $mtime);
367 vverb "$Cname: $Cmd5 $Cmtime";
368 if (! -f $Cname) {
369 print "missing $Cname\n" unless ($opt{'nofiles'});
370 next;
371 }
372 unless ($opt{'nomd5'}) {
373 if (-r _) {
374 ($md5 = `md5sum "$Cname"`) =~ s/\s.*//s;
375 } else {
376 $md5 = 'UNKNOWN';
377 }
378 # only report this if it's calculated.
379 vverb "Md5 is $md5 for $Cname";
380 }
381 $mtime = (stat _)[9];
382 vverb "Mtime is $mtime for $Cname";
383 # XXX size, device, user, group, and mode are not checked... :-(
384 next if (($opt{'nomd5'} or $md5 eq $Cmd5) and $mtime eq $Cmtime);
385 printf "..%s....%s %s\n",
386 ($md5 ne $Cmd5) ? ($md5 eq 'UNKNOWN') ? '?' : '5' : '.',
387 ($mtime ne $Cmtime) ? 'T' : '.', $Cname;
388 if ($md5 ne $Cmd5) { $exitcode = 1; }
389 next;
390 }
391 if ($f =~ /^dir (.+)/o) {
392 print "missing $1\n" unless (-d $1 or $opt{'nofiles'});
393 next;
394 }
395 if ($f =~/^sym (.+) -> (.+) (\d+)$/o) {
396 my ($Cname, $Clink, $Cmtime) = ($1, $2, $3);
397 my ($link, $mtime);
398 my ($modeok);
399
400 if (! -e $Cname) {
401 print "missing $Cname\n" unless ($opt{'nofiles'});
402 next;
403 }
404 vverb "$Cname -> $Clink $Cmtime";
405 $mtime = (stat $Cname)[9];
406 if (-l $Cname) {
407 $modeok = 1;
408 $link = readlink($Cname);
409 } else {
410 $modeok = 0;
411 $link = '';
412 }
413 next if ($modeok
414 and defined ($link)
415 and $Clink eq $link
416 and defined ($mtime)
417 and $Cmtime eq $mtime);
418 printf ".%s..%s..%s %s\n",
419 $modeok ? '.' : 'M',
420 defined($link) ? ($Clink ne $link) ? 'L' : '.' : '?',
421 defined($mtime) ? ($Cmtime ne $mtime) ? 'T' : '.' : '?',
422 $Cname;
423 next;
424 }
425 # XXX presently ignoring devices
426 }
427 close F;
428 }
429
430 sub query()
431 {
432 verb "query mode";
433 verb "actually Verify mode" if $opt{'V'};
434
435 # Load the database which is needed for query mode
436 load_database();
437 my (@pkgs); # list of packages being queried
438
439 # Package-based query (how does this work with emerge?)
440 if ($opt{'p'}) {
441 die "epm: Sorry, package-based query not yet supported\n";
442 }
443
444 # Implied -l similar to rpm
445 $opt{'dump'} and $opt{'l'} = 1;
446 $opt{'d'} and $opt{'l'} = 1;
447 $opt{'c'} and $opt{'l'} = 1;
448
449 # File-based query
450 if ($opt{'f'}) {
451 @pkgs = query_file(@pkgs);
452 @ARGV = (); # Clear out ARGV so queries below don't get confused
453 }
454
455 # Group-based query
456 # Note that if -qfg specified, then rpm prioritizes -qf over -qg,
457 # so we do too.
458 elsif ($opt{'g'}) {
459 for my $a (@ARGV) {
460 verb "checking for packages in group $a";
461 my @l = grep /^$a\//, @dpkgs;
462 vverb "packages in group $a:";
463 vverb " ", join "\n ", @l;
464 unless (@l) {
465 print "group $a does not contain any packages\n";
466 $exitcode = 1;
467 }
468 push @pkgs, @l;
469 }
470 @ARGV = (); # Clear out ARGV so queries below don't get confused
471 }
472
473 # Query on all packages
474 if ($opt{'a'}) {
475 die "epm: extra arguments given for query of all packages\n" if @ARGV;
476 @pkgs = @dpkgs;
477 }
478 elsif (@pkgs) {
479 # must have been populated by, for instance, -qf
480 }
481 else {
482 USERARG: for my $a (@ARGV) {
483 if ($a =~ /$pkgregex/o) {
484 verb "$a matches pkgregex";
485 vverb "name=$1, version=$2, suffix=$3, revision=$4";
486 # user has asked for specific version, check if any
487 # installed version matches
488 for my $pver (@{$dnampkg{$1}}) {
489 vverb "found version: $pver";
490 if ($pver eq $a) {
491 push @pkgs, $a;
492 next USERARG;
493 }
494 }
495 }
496 if (defined $dnampkg{$a}) {
497 verb "$a found in dnampkg";
498 vverb @{$dnampkg{$a}};
499 push @pkgs, @{$dnampkg{$a}};
500 next;
501 }
502 print "package $a is not installed\n";
503 next;
504 }
505 }
506
507 # Sort package order, by reverse mtime
508 if ($opt{'last'}) {
509 my %mtimes;
510 @pkgs = sort {
511 # When was this last built/installed?
512 unless (exists $mtimes{$a}) {
513 $mtimes{$a} = (stat "$dbpath/$a")[9];
514 vverb "$a = $mtimes{$a}";
515 }
516 unless (exists $mtimes{$b}) {
517 $mtimes{$b} = (stat "$dbpath/$b")[9];
518 vverb "$b = $mtimes{$b}";
519 }
520 $mtimes{$b} <=> $mtimes{$a} or $a cmp $b;
521 } @pkgs;
522 }
523
524 for my $p (@pkgs) {
525 # Verify package
526 if ($opt{'V'}) { verify($p); next; }
527
528 # Information query
529 query_info($p) if $opt{'i'};
530
531 # File listing...
532 # We allow this to chain after query_info because rpm allows it.
533 query_list($p) if $opt{'l'};
534
535 # If not another type of listing, then simply list the packages
536 if (!$opt{'l'} && !$opt{'i'}) {
537 # If doing -qS, then include the size in kb, like ls -s
538 printf "%6d ", int(pkg_bytes($p)/1000) if $opt{'S'};
539 # If doing -qG, then include the group name
540 if ($opt{'G'}) {
541 print "$p\n";
542 } else {
543 ($nogrp) = $p =~ /^.+?\/(.+)$/;
544 print "$nogrp\n";
545 }
546 }
547 }
548 }
549
550 ##############################################
551 #
552 # ERASE MODE
553 #
554 ##############################################
555 sub erase()
556 {
557 my (@cmd);
558 verb "erase mode";
559 verb "(testing)" if $opt{'test'};
560
561 # Catch empty command-line
562 die "epm: no packages given for uninstall\n" unless @ARGV;
563
564 # Must be root to erase; rpm just lets permissions slide but I don't
565 if ($> != 0) {
566 print STDERR "Must be root to remove packages from the system\n";
567 $exitcode = 1;
568 return;
569 }
570
571 # There's no point implementing erase here. Might as well just
572 # use existing portage features. This means that we do
573 # --allmatches by default.
574 @cmd = qw(emerge --unmerge);
575 push @cmd, '--pretend' if $opt{'test'};
576 push @cmd, '--quiet' unless $opt{'verbose'};
577 push @cmd, @ARGV;
578 system(@cmd);
579 die "epm: Fatal error running emerge\n" if $?;
580 }
581
582 ##############################################
583 #
584 # MAIN
585 #
586 ##############################################
587
588 # Syntax string for errors
589 my $syntax = <<EOT;
590 $version
591 Copyright (C) 2001-2003 - Aron Griffis
592 This program may be freely redistributed under the terms of the GNU GPL v2
593 '*' leading an option indicates not-yet-implemented
594
595 Usage:
596 --help - print this message
597 *--version - print the version of rpm being used
598
599 All modes support the following arguments:
600 -v - be a little more verbose
601 -vv - be incredibly verbose (for debugging)
602
603 -q, --query - query mode
604 --dbpath <dir> - use <dir> as the directory for the database
605 --root <dir> - use <dir> as the top level directory
606 --last - list package(s) by install time, most
607 recent first
608 Package specification options:
609 -a, --all - query all packages
610 -f <file>+ - query package owning <file>
611 *-p <packagefile>+ - query (uninstalled) package <packagefile>
612 *--triggeredby <pkg> - query packages triggered by <pkg>
613 *--whatprovides <cap> - query packages which provide <cap> capability
614 *--whatrequires <cap> - query packages which require <cap> capability
615 -g <group>+ --group <group>+ - query packages in group <group>
616 Information selection options:
617 -i, --info - display package information
618 --nosize - don't display size in info output (not in rpm)
619 -l - display package file list
620 -G, --showgroup - display group name in output (not in rpm)
621 -S, --size - display package size in output (not in rpm)
622 -d - list only documentation files (implies -l)
623 -c - list only configuration files (implies -l)
624 --dump - show all verifiable information for each file
625 (must be used with -l, -c, or -d)
626 *--provides - list capabilities package provides
627 *-R, --requires - list package dependencies
628 *--scripts - print the various [un]install scripts
629
630 --erase <package>
631 -e <package> - erase (uninstall) package
632 --allmatches - remove all packages which match <package>
633 (unlike rpm, this is the default)
634 --dbpath <dir> - use <dir> as the directory for the database
635 *--justdb - update the database, but do not modify the
636 filesystem
637 *--nodeps - do not verify package dependencies
638 *--noorder - do not reorder package installation to satisfy
639 dependencies
640 *--noscripts - do not execute any package specific scripts
641 *--notriggers - don't execute any scripts triggered by this
642 package
643 --root <dir> - use <dir> as the top level directory
644 --test - don't uninstall, but tell what would happen
645
646 -V, -y, --verify - verify a package installation using the same
647 package specification options as -q
648 --dbpath <dir> - use <dir> as the directory for the database
649 *--root <dir> - use <dir> as the top level directory
650 *--nodeps - do not verify package dependencies
651 *--nomd5 - do not verify file md5 checksums
652 *--nofiles - do not verify file attributes
653 EOT
654
655 # Allow bundling of options since rpm does
656 Getopt::Long::Configure ("bundling");
657
658 # Parse the options on the cmdline. Put the short versions first in
659 # each optionstring so that the hash keys are created using the short
660 # versions. For example, use 'q|query', not 'query|q'.
661 my $result = GetOptions(
662 \%opt,
663 'help', # help message
664 'version', # version message
665 'v+', # verbose, more v's for more verbosity
666
667 'q|query', # query mode
668 'dbpath=s', # use <dir> as the directory for the database
669 'root=s', # use <dir> as the top level directory
670 'last', # order package listing by most recent install first
671 # Package specification options:
672 'a|all', # query all packages
673 'f', # query package owning file(s)
674 'p', # query (uninstalled) package
675 'g|group', # query packages in group(s)
676 'whatprovides', # query packages which provide capability
677 'whatrequires', # query packages which require capability
678 # Information selection options:
679 'i|info', # display package information
680 'nosize', # don't display size in info output
681 'l', # display package file list
682 'd', # list documentation files (implies -l)
683 'c', # list configuration files (implies -l)
684 'dump', # show all verifiable information for each file
685 # (must be used with -l, -c, or -d)
686 'R|requires', # list package dependencies
687 'scripts', # print the various [un]install scripts
688 'G|showgroup', # include group name in output
689 'S|size', # display package size
690
691 'e|erase', # erase mode
692 'allmatches', # remove all packages which match <package>
693 'test', # don't uninstall, but tell what would happen
694
695 'V|y|verify', # verify a package installation using the same
696 # package specification options as -q
697 'nodeps', # do not verify package dependencies
698 'nomd5', # do not verify file md5 checksums
699 'nofiles', # do not verify file attributes
700 );
701
702 # Handle help message
703 if ($opt{'help'}) { print $syntax; exit 0 }
704 if ($opt{'version'}) { print "$version\n"; exit 0 }
705
706 # Determine which mode we're running in; make sure it's valid.
707 # (q)uery
708 # (V)erify
709 # (U)pgrade
710 # (e)rase
711 # (b)uild
712 # other
713 if ((defined $opt{'q'} || 0) +
714 (defined $opt{'V'} || 0) +
715 (defined $opt{'U'} || 0) +
716 (defined $opt{'e'} || 0) +
717 (defined $opt{'b'} || 0) != 1) {
718 die "$syntax\nOne mode required, and only one mode allowed\n";
719 }
720
721 # Query mode
722 if ($opt{'q'} || $opt{'V'}) { query(); exit $exitcode }
723 if ($opt{'e'}) { erase(); exit $exitcode }
724
725 # Other modes not implemented yet
726 die "epm: Sorry, this mode isn't implemented yet. Check back later! :-)\n";
727
728 # $Log: epm,v $
729 # Revision 1.32 2006/09/13 15:04:49 agriffis
730 # 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
731 #
732 # Revision 1.31 2006/09/08 19:35:22 agriffis
733 # Switch to cvs-based versioning. Add --version option. Add --last option, based on patch submitted by Tim Stotts #138679
734 #
735 # Revision 1.30 2006/04/04 21:07:07 mr_bones_
736 # display directories as well as files and symlinks when doing query list (-ql)
737 # This matches what rpm does. Reported by Steven Elling via Gentoo bugzilla:
738 # http://bugs.gentoo.org/show_bug.cgi?id=128186
739 #
740 # Revision 1.29 2006/03/15 21:49:48 agriffis
741 # Leave Size blank instead of n/a when --nosize given
742 #
743 # Revision 1.28 2006/03/15 21:43:23 agriffis
744 # Add --nosize option
745 #
746 # Revision 1.27 2005/08/29 13:32:35 kanaka
747 # Update version to 0.9.0
748 #
749 # Revision 1.26 2005/08/25 22:03:59 mr_bones_
750 # -i is implemented so remove the * from the usage message. (reported by agriffis)
751 #
752 # Revision 1.25 2005/08/16 20:39:16 kanaka
753 # Fix broken regex during file list query
754 #
755 # Revision 1.24 2005/08/15 20:37:14 kanaka
756 # Fix situation where package group is different, but name and version are the same (i.e. crossdev)
757 #
758 # Revision 1.23 2005/07/05 20:01:36 mr_bones_
759 # pass --quiet to emerge when performing -e (erase) to be more like rpm
760 #
761 # Revision 1.22 2005/06/22 05:28:24 mr_bones_
762 # Print out usage if user didn't get the mode specified correctly.
763 # Suggested by Tristan Cebulla in
764 # http://bugs.gentoo.org/show_bug.cgi?id=96726
765 #
766 # Revision 1.21 2005/05/18 05:30:14 mr_bones_
767 # fix silly check for empty HOMEPAGE
768 #
769 # Revision 1.20 2005/05/16 03:15:26 mr_bones_
770 # Make all the regexs that match the obj lines from CONTENTS be the same.
771 #
772 # Revision 1.19 2005/05/14 23:50:33 mr_bones_
773 # remove "use epm". guessing that was an idea that never materialized
774 #
775 # Revision 1.18 2005/05/14 23:48:48 mr_bones_
776 # Added support for --nofiles in verify() - rpm man page claims it only
777 # suppresses reports of missing files. epm suppresses all "missing" reporting
778 # if --nofiles is given.
779 #
780 # Added support for --nomd5 in verify(); fixed up bare word in output.
781 #
782 # Added initial support for symlinks in verify().
783 #
784 # Revision 1.17 2005/05/14 22:24:12 mr_bones_
785 # no reason to read CONTENTS into memory in query_file(). Modified to read
786 # line at a time.
787 #
788 # Revision 1.16 2005/05/14 22:21:46 mr_bones_
789 # Make output more similar to rpm by changing "Description" to "Summary"
790 # in output. Maybe at some point the extended description from metadata.xml
791 # will be stored in portage and can be extracted then by epm for Description.
792 # Also changed "Build Host" from CHOST to HOSTNAME.
793 #
794 # Modified to read environment.bz2 instead of the ebuild for some values.
795 # This is more reliable because environment.bz2 is the state after ebuild
796 # and eclass processing. Epm was confused by ebuilds that have the HOMEPAGE
797 # and DESCRIPTION in an eclass. (eg. xmms-mpg123)
798 #
799 # Fixed up display of values that contain double and single quotes
800 # (eg. libmad)
801 #
802 # Added error checking for open()
803 #
804 # Revision 1.15 2005/05/14 21:55:25 mr_bones_
805 # Pass long option (--unmerge) to emerge instead of short option (-C)
806 # for better readability.
807 #
808 # Revision 1.14 2005/05/14 21:47:51 mr_bones_
809 # fix bug in pkg_bytes() where files with whitespace in their name would
810 # cause incorrect behavior.
811 #
812 # Revision 1.13 2005/05/14 21:38:10 mr_bones_
813 # prototype functions
814 #
815 # Revision 1.12 2005/05/14 21:30:44 mr_bones_
816 # Use correct variable in error message ($p -> $p1/$p2)
817 #
818 # Revision 1.11 2005/05/14 20:54:19 mr_bones_
819 # Trim trailing whitespace
820 #
821 # Revision 1.10 2005/05/13 20:47:44 agriffis
822 # epm-0.8.8
823 #
824 # Revision 1.20 2004/04/28 13:22:41 agriffis
825 # - Fix printing of symlinks in -ql to exclude link target
826 #
827 # Revision 1.19 2004/04/05 04:37:46 agriffis
828 # - Add patch from Michael Sterret in bug 45927 to handle whitespace
829 # in filenames
830 #
831 # Revision 1.18 2004/03/29 16:47:34 agriffis
832 # Fix bug 45927: Handle filenames with spaces correctly
833 # Update version to 0.8.6
834 #
835 # Revision 1.17 2004/03/08 23:23:39 agriffis
836 # - Update to 0.8.5
837 #
838 # Revision 1.16 2004/03/08 23:21:46 agriffis
839 # - Added size option to -qi and -qS
840 # - Thanks to Bram Dumolin (http://lanka-expats.net/) for the idea and
841 # an initial effort at the code
842 #
843 # Revision 1.15 2003/05/27 01:36:01 agriffis
844 # - Update to 0.8.4
845 #
846 # Revision 1.14 2003/05/27 01:33:41 agriffis
847 # - Include patch from Michael Sterrett <msterret@gentoo.org> to display URL
848 # in -qi output
849 #
850 # Revision 1.13 2003/05/02 02:00:22 agriffis
851 # - Update to 0.8.3
852 # - Check if file exists to choose error message for -qf
853 #
854 # Revision 1.12 2003/05/01 02:42:39 agriffis
855 # - Add man-page in pod format inside epm
856 #
857 # Revision 1.11 2003/05/01 01:53:09 agriffis
858 # - Update version to 0.8.2; forgot to checkin 0.8.1
859 # - Fix bug 8832: Add code to determine full path for epm -qf.
860 # Reported by Bill Gjestvang, patch provided by Wayne Davison.
861 # - Fix bug 12798: Fix -V output for unreadable files
862 # Reported and patched by Wayne Davison.
863 # - Fix bug 19806: Need double-quotes to interpret \n on die message
864 # Reported and patched by Scott Hunt
865 # - Fix bug 19681: Check for requested version on epm -q.
866 # Reported by Neil McCalden, patch provided by Wayne Davison.
867 #
868 # Revision 1.10 2002/10/22 13:55:00 agriffis
869 # - Fix version reporting in help message
870 # - Fix unmerging to use -C instead of non-existent --unmerge
871 #
872 # Revision 1.9 2002/10/22 13:48:47 agriffis
873 # - Fixed erase -e to do something when not --test
874 #
875 # Revision 1.8 2002/10/22 13:44:08 agriffis
876 # - Fix bug in -qa which listed too many packages
877 #
878 # Revision 1.7 2002/10/22 13:31:47 agriffis
879 # - Split out query types into separate functions
880 # - Add sub cmppkg which was for --update but might be abandoned
881 # - Add information query -qi
882 # - Add first-pass verification -V
883 # - Change erase -e to use emerge (which maintains world)
884 #
885
886 =head1 NAME
887
888 epm - rpm workalike for Gentoo
889
890 =head1 SYNOPSIS
891
892 epm { -eqVy | --erase | --help | --query | --verify } options...
893
894 =head1 DESCRIPTION
895
896 This tool provides a Gentoo query tool for users familiar with Red
897 Hat's "rpm" package manager. In particular, it can query, verify, and
898 erase packages from the system. I've tried to make it act as much
899 like rpm as possible, but there are some differences made necessary by
900 the differences in the distributions.
901
902 Querying and verifying are the most powerful features of epm. Erase
903 mode is really just a gate to "emerge -C", but force of habit makes it
904 easier for me to type "epm -e".
905
906 =head1 MODES
907
908 =over
909
910 =item B<-q --query>
911
912 Query mode, for querying either the list of installed packages or the
913 files owned by a package.
914
915 =item B<-V -y --verify>
916
917 Verify mode, for determining the integrity of an installed package
918 using timestamps and md5 sums. Size, device, user, group, and mode
919 are not presently checked.
920
921 =item B<-e --erase>
922
923 Erase mode, for removing packages from the system. Specify a package
924 by version to remove a specific package. Specify a package by name to
925 remove all versions (i.e. --allmatches is the default for epm, this is
926 a difference from rpm).
927
928 =item B<--help>
929
930 This isn't really a mode, but it's the only thing you can do without
931 otherwise specifying a mode. Run "epm --help" to see the
932 comprehensive list of options available for each mode.
933
934 =head1 EXAMPLES
935
936 To find out if vim is installed:
937
938 $ epm -q vim
939 vim-6.2_pre2
940
941 To include the group in the output:
942
943 $ epm -qG vim
944 app-editors/vim-6.2_pre2
945
946 To see what binaries vim installs:
947
948 $ epm -ql vim | grep bin
949 /usr/bin/ex
950 /usr/bin/vim
951 /usr/bin/rvim
952 /usr/bin/view
953 /usr/bin/rview
954 /usr/bin/vimdiff
955
956 To find what package owns /usr/bin/vim
957
958 $ epm -qf /usr/bin/vim
959 vim-6.2_pre2
960
961 To verify your installation of vim:
962
963 $ epm -V vim
964
965 No output indicates the installation is fine. If you get some other
966 output when you verify a package installation, try the following link
967 for an explanation. http://www.rpm.org/max-rpm/s1-rpm-verify-output.html
968
969 To show all vim related packages on the system:
970
971 $ epm -qa | grep vim
972 vim-core-6.2_pre2
973 vim-6.2_pre2
974 gvim-6.2_pre2
975
976 =back
977
978 =head1 NOTES
979
980 This tool was written by Aron Griffis <agriffis@gentoo.org>. It will
981 probably blow up your computer, but it works well enough for me. If
982 you report bugs at http://bugs.gentoo.org/, assigned to me, I might
983 fix them eventually. Your chances skyrocket if you include a good
984 patch, like Wayne Davison always does.
985
986 =end

  ViewVC Help
Powered by ViewVC 1.1.20