1 #!/usr/bin/env perl
2 #
3 # pkg-get - A binary package management utility for CRUX Linux
4 # Copyright (C) 2004-06 Simone Rota <sip@varlock.com>
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10
11 use warnings;
12 use strict;
13 use Getopt::Long;
14
15 my $VERSION = "0.4.5";
16 my $CFGFILE = "/etc/pkg-get.conf";
17 my $LOCKFILE = "/var/lib/pkg/pkg-get.locker";
18 my $PKGDB = "/var/lib/pkg/db" ;
19
20 $SIG{HUP} = \&trap; $SIG{INT} = \&trap; $SIG{QUIT} = \&trap; $SIG{TERM} = \&trap;
21
22 # Global vars
23 my @repos = (); # package repositories
24 my @donetasks; my @failtasks; my @prevtasks; my %pptasks; my %readmetasks;
25 my $curraction = ""; my %installed; my %deps; my @dependencies; my %missingdeps;
26
27 # CL Options
28 my $download_only; my $pre_install; my $post_install;
29 my $install_scripts; my $filter = ""; my $all; my $unused;
30 my $aargs=""; my $ignore_md5sum; my $force; my $root;
31 GetOptions("do"=>\$download_only,
32 "pre-install"=>\$pre_install, "post-install"=>\$post_install,
33 "install-scripts"=>\$install_scripts, "all"=>\$all,
34 "filter=s"=>\$filter, "config=s"=>\$CFGFILE, "aargs=s"=>\$aargs,
35 "f"=>\$force, "im"=>\$ignore_md5sum, "margs=s"=>\$unused,
36 "rargs=s"=>\$unused, "r=s"=>\$root);
37
38 # use compression-mode defined in pkgmk.conf
39 our $compress = "gz";
40 open CONFIG, "/etc/pkgmk.conf" or die "Could not open /etc/pkgmk.conf";
41 while (<CONFIG>) {
42 $compress = $1 if m/^PKGMK_COMPRESSION_MODE="(.*)"\n/;
43 }
44 close CONFIG;
45
46 if ($root) {
47 $LOCKFILE = $root.$LOCKFILE ;
48 $PKGDB = $root.$PKGDB;
49 }
50
51 # Get command, verify it's valid
52 my $command = getcommand(@ARGV);
53 if (index($command,"Error: ") eq 0 ) {
54 $command =~ s/Error\: //;
55 exiterr($command);
56 }
57 readconfig();
58
59 SWITCH: {
60 if ($command eq "version") { version(); last SWITCH; }
61 if ($command eq "sync") { sync(); last SWITCH; }
62 if ($command eq "info") { info(); last SWITCH; }
63 if ($command eq "help") { help(); last SWITCH; }
64 if ($command eq "readme") { readme(); last SWITCH; }
65 if ($command eq "search") { search(); last SWITCH; }
66 if ($command eq "dsearch") { dsearch(); last SWITCH; }
67 if ($command eq "list") { list(); last SWITCH; }
68 if ($command eq "path") { path(); last SWITCH; }
69 if ($command eq "remove") { remove(); last SWITCH; }
70 if ($command eq "listinst") { listinst(); last SWITCH; }
71 if ($command eq "lock") { dolock(); last SWITCH; }
72 if ($command eq "unlock") { unlock(); last SWITCH; }
73 if ($command eq "listlocked") { listlocked(); last SWITCH; }
74 if ($command eq "printf") { doprintf(); last SWITCH; }
75 if ($command eq "isinst") { isinst(); last SWITCH; }
76 if ($command eq "diff") { diff(); last SWITCH; }
77 if ($command eq "quickdiff") { quickdiff(); last SWITCH; }
78 if ($command eq "dup") { dup(); last SWITCH; }
79 if ($command eq "depends") { depends(); last SWITCH; }
80 if ($command eq "quickdep") { quickdep(); last SWITCH; }
81 if ($command eq "install") { install(@ARGV); last SWITCH; }
82 if ($command eq "update") { update(@ARGV); last SWITCH; }
83 if ($command eq "sysup") { sysup(); last SWITCH; }
84 if ($command eq "dependent") { dependent(); last SWITCH; }
85 if ($command eq "depinst") { depinst(); last SWITCH; }
86 if ($command eq "current") { current(); last SWITCH; }
87 }
88
89
90 ############################################################################
91 # Support functions
92 ############################################################################
93
94 # Exit with error
95 sub exiterr {
96 my ($msg) = @_;
97 print "pkg-get: $msg\n";
98 exit 1;
99 }
100
101 sub trap {
102 printresults(1);
103 die("\npkg-get: interrupted\n");
104 }
105
106 # Get command, return an error if not in the list of allowed commands
107 sub getcommand {
108 my @args = @_;
109 my $givencmd = $args[0];
110 my $givenarg = $args[1];
111 if (not $givenarg){$givenarg = ""};
112 if (not $givencmd){$givencmd = ""};
113 my @allowed = ("depinst:", "install:", "sysup", "diff", "update:", "depends:", "info:", "sync",
114 "version", "help", "quickdep:", "dependent:", "list", "listinst", "isinst:",
115 "search:", "dsearch:", "lock:", "unlock:", "listlocked", "quickdiff", "printf:",
116 "remove:", "readme:", "dup", "path:", "current:");
117
118 foreach my $valid(@allowed) {
119 if ($givencmd eq ""){
120 return "Error: no command given. try pkg-get help for more information";
121 }
122 if ($givencmd eq $valid) {
123 return $givencmd;
124 } elsif ($givencmd.":" eq $valid) {
125 if ($givenarg ne "") {
126 return $givencmd;
127 } else {
128 return "Error: '$givencmd' requires an argument";
129 }
130 }
131 }
132 return "Error: unknown command '$givencmd'. try pkg-get help for more information";
133 }
134
135 # Parses the configuration file
136 sub readconfig {
137 open(CFG, $CFGFILE)
138 or exiterr("could not open $CFGFILE");
139 while (<CFG>) {
140 chomp;
141 if ( /^pkgdir\s+/ ) {
142 my $repo = $_;
143 $repo =~ s/^pkgdir\s+//;
144 $repo =~ s/#(.*)$//;
145 $repo =~ s/\s+$//;
146 push @repos, $repo;
147 } elsif (/^runscripts\s+/) {
148 my $rs = $_;
149 $rs =~ s/^runscripts\s+//;
150 $rs =~ s/#(.*)$//;
151 $rs =~ s/\s+$//;
152 if ($rs eq "yes") {$install_scripts = 1};
153 }
154 }
155 close(CFG);
156 }
157
158 # Parse a line describing a package
159 sub parsepackage {
160 my @p = split(/\:/, $_[0]);
161 if ($#p != 6) {exiterr("$_[1]/PKGREPO appears to be in wrong format!\nAborting.")};
162 my %pkg;
163 my $name = $p[0];
164 $name =~ s/\#.*$//;
165 my $version = $p[0];
166 $version =~ s/^.*\#//;
167 $version =~ s/-\w*\.pkg\.tar\.[gbx]z*//;
168 my $release = $p[0];
169 $release =~ s/^.*-//;
170 $release =~ s/\.pkg\.tar\.[gbx]z*//;
171 if (not $_[2]) {$_[2] = $_[1]};
172 $pkg{'name'} = $name;
173 $pkg{'version'} = $version;
174 $pkg{'release'} = $release;
175 $pkg{'path'} = $_[1];
176 $pkg{'url'} = $_[2] . "/$p[0]";
177 $pkg{'size'} = $p[1];
178 $pkg{'md5sum'} = $p[2];
179 $pkg{'description'} = $p[3];
180 $pkg{'pre_install'} = $p[4];
181 $pkg{'post_install'} = $p[5];
182 $pkg{'readme'} = $p[6];
183 if ($_[3] == 1) {
184 getinstalled();
185 $pkg{'instversion'} = $installed{$name};
186 }
187 return %pkg;
188 }
189
190 # Parse a line describing a package (just the name)
191 sub parsepackagelight {
192 my @p = split(/\:/, $_[0]);
193 if ($#p != 6) {exiterr("$_[1]/PKGREPO appears to be in wrong format!\nAborting.")};
194 my %pkg;
195 my $name = $p[0];
196 $name =~ s/\#.*$//;
197 $pkg{'name'} = $name;
198 return %pkg;
199 }
200
201 # Print info about the given package
202 sub printinfo {
203 my %pkg = @_;
204 print "Name : " . $pkg{'name'} . "\n";
205 print "Version : " . $pkg{'version'} . "\n";
206 print "Release : " . $pkg{'release'} . "\n";
207 print "Description : " . $pkg{'description'} . "\n";
208 print "URL : " . $pkg{'url'} . "\n";
209 print "Md5sum : " . $pkg{'md5sum'} . "\n";
210 print "Size : " . $pkg{'size'} . "\n";
211 my $deps = getdirectdeps($pkg{'name'}, $pkg{'path'});
212 if ($deps ne "") { print "Depends on : $deps\n";};
213 my $files = "";
214 if ($pkg{'readme'} eq "yes") {$files .= "README,"};
215 if ($pkg{'pre_install'} eq "yes") {$files .= "pre-install,"};
216 if ($pkg{'post_install'} eq "yes") {$files .= "post-install,"};
217 $files =~ s/\,$//;
218 if ($files ne "") { print "Files : $files\n";};
219 }
220
221 # Get direct dependencies for package
222 sub getdirectdeps {
223 my $pkgname = $_[0];
224 my $dir = $_[1];
225 open(DEPS, "$dir/PKGDEPS")
226 or exiterr("could not open $dir/PKGDEPS");
227 while (<DEPS>) {
228 chomp;
229 if ( /^\Q$pkgname\E\s+/ ) {
230 my $dep = $_;
231 $dep =~ s/^.*\: //;
232 close(DEPS);
233 return $dep;
234 }
235 }
236 close(DEPS);
237 return "";
238 }
239
240 # Prints the README file to stdout
241 sub printreadme {
242 my %pkg = @_;
243 my $dir = $pkg{'path'};
244 my $pkgname = $pkg{'name'};
245 my $found = 0;
246 my $finished = 0;
247 open(READ, "$dir/PKGREAD")
248 or exiterr("could not open $dir/PKGREAD");
249 while (<READ>) {
250 if ($finished eq 1) {return;};
251 chomp;
252 if ($found eq 1) {
253 if ( /PKGREADME\:/ ) {
254 $finished = 1;
255 close(READ);
256 return;
257 } else {
258 print "$_\n";
259 }
260 }
261 if ($finished eq 0) {
262 if ( /PKGREADME: $pkgname$/ ) {
263 $found = 1;
264 }
265 }
266 }
267 close(READ);
268 }
269
270 # Print results for multiple package operations
271 sub printresults {
272 my $okaction = $curraction;
273 my $curr = "";
274 my $action;
275 my $pkg;
276 my @t;
277 my @readme;
278 my $goterror = 0;
279 if (@donetasks) {
280 print "\n-- Packages $okaction\n";
281 foreach my $task(@donetasks) {
282 if ($readmetasks{$task}) {push(@readme, $task)}
283 print "$task" . $pptasks{$task}."\n";
284 }
285 }
286 if (@prevtasks) {
287 if ($okaction eq "installed") {
288 print "\n-- Packages installed before this run (ignored)\n";
289 } else {
290 print "\n-- Packages not previously installed (ignored)\n";
291 }
292 foreach my $task(@prevtasks) {
293 print "$task\n";
294 }
295 }
296 if (@failtasks) {
297 @failtasks = sort(@failtasks);
298 foreach my $task(@failtasks) {
299 @t = split(/,/,$task);
300 $action = $t[0];
301 $pkg = $t[1];
302 if ($curr ne $action) {
303 print "\n-- Packages $action\n";
304 $curr = $action;
305 }
306 print "$pkg\n";
307 }
308 }
309 if (@readme) {
310 print "\n-- $okaction packgages with README file\n";
311 foreach my $task(@readme) {
312 print "$task" . $pptasks{$task}."\n";
313 }
314 }
315 if(@donetasks and not @failtasks and not $_[0]) {
316 print "\npkg-get: $okaction successfully\n"
317 }
318 }
319
320 # Get the list of installed packages
321 sub getinstalled {
322 if (%installed) {
323 return;
324 }
325 my $name;
326 my $version;
327 my $sec = 0;
328 open(DB, $PKGDB)
329 or exiterr("could not open ".$PKGDB);
330 while (<DB>) {
331 chomp;
332 if ($_ ne "") {
333 if ($sec == 0) {
334 $name = $_;
335 $sec = 1;
336 } elsif ($sec == 1) {
337 $version = $_;
338 $sec = 3;
339 }
340 }
341 if ($sec == 3) {
342 if ($_ eq "") {
343 $sec = 0;
344 $installed{$name} = $version;
345 }
346 }
347 }
348 close(DB);
349 }
350
351 # Lock the given pkgname
352 sub lockadd {
353 my $pkg = $_[0];
354 my @locked = ();
355 if (not -e $LOCKFILE) {
356 open(LCK, "+>> $LOCKFILE") or exiterr("could not write to lock file");
357 close(LCK);
358 }
359 open(LCK, $LOCKFILE);
360 while (<LCK>) {
361 chomp;
362 if ($_ eq $pkg) {
363 print "Already locked: $pkg\n";
364 close(LCK);
365 return;
366 } else {
367 push (@locked, $_);
368 }
369 }
370 close(LCK);
371 push(@locked, $pkg);
372 @locked = sort(@locked);
373 open(LCK, "> $LOCKFILE") or exiterr("could not write to lock file");
374 foreach my $lock(@locked) {
375 print LCK "$lock\n";
376 }
377 close(LCK);
378 }
379
380 # Rrint formatted info for given package
381 sub formattedprint {
382 my %pkg = @_;
383 my $fmt = $ARGV[1];
384 $fmt =~ s|%n|$pkg{'name'}|;
385 $fmt =~ s|%p|$pkg{'path'}|;
386 $fmt =~ s|%v|$pkg{'version'}|;
387 $fmt =~ s|%r|$pkg{'release'}|;
388 $fmt =~ s|%d|$pkg{'description'}|;
389 $fmt =~ s|%u|$pkg{'url'}|;
390 $fmt =~ s|%R|$pkg{'readme'}|;
391 $fmt =~ s|%E|$pkg{'pre_install'}|;
392 $fmt =~ s|%O|$pkg{'post_install'}|;
393 $fmt =~ s|%M|Nobody|; # for prt-get compatibility
394 $fmt =~ s|%P|Nobody|; # for prt-get compatibility
395 $fmt =~ s|\\n|\n|;
396 $fmt =~ s|\\t|\t|;
397 if (index($fmt,"%e") >=0) {
398 my $deps = getdirectdeps($pkg{'name'}, $pkg{'path'});
399 $fmt =~ s|%e|$deps|;
400 }
401 if (index($fmt,"%l") >=0) {
402 my $locked = islocked($pkg{'name'});
403 $fmt =~ s|%l|$locked|;
404 }
405 if (index($fmt,"%i") >=0) {
406 my $inst = "no";
407 if ($pkg{'instversion'}) {
408 if ($pkg{'instversion'} eq $pkg{'version'}."-".$pkg{'release'}) {
409 $inst = "yes";
410 } else {
411 $inst = "diff";
412 }
413 }
414 $fmt =~ s|%i|$inst|;
415 }
416 print "$fmt";
417 }
418
419 # See if package is currently locked
420 sub islocked {
421 my $pkg = $_[0];
422 open(LCK, $LOCKFILE) or return "no";
423 while (<LCK>) {
424 chomp;
425 if ($_ eq $pkg) {
426 close(LCK);
427 return "yes";
428 }
429 }
430 close(LCK);
431 return "no";
432 }
433
434 # Get package from the repo(s)
435 sub getpackage {
436 my $pkgname = $_[0];
437 my $checkver = $_[1];
438 my %found;
439 my %res;
440 foreach my $repo(@repos) {
441 my @r = split(/\|/, $repo);
442 my $dir = $r[0];
443 my $url = $r[1];
444 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
445 while (<REPO>) {
446 chomp;
447 my %pkg = parsepackage($_, $dir, $url, $checkver);
448 if ($pkg{'name'} eq $pkgname) {
449 close (REPO);
450 return %pkg;
451 }
452 }
453 close (REPO);
454 }
455 return %res;
456 }
457
458 # Get short status for package, ie [i]
459 sub getshortstatus {
460 my %pkg = @_;
461 if ($pkg{'instversion'}) {
462 if ($pkg{'instversion'} eq $pkg{'version'}."-".$pkg{'release'}) {
463 return "[i]";
464 } else {
465 return "[u]";
466 }
467 }
468 return "[ ]";
469 }
470
471 # Get (recursive) dependencies for pkgname
472 sub getdependencies {
473 my $pkgname = $_[0];
474 my $checkver = $_[1];
475 my $pkgparent = $_[2];
476 my $depstring = "";
477 if ($pkgparent eq "") {
478 #%deps = ();
479 };
480 if (not $deps{$pkgname}) {
481 my %pkg = getpackage($pkgname, 1);
482 if (%pkg) {
483 my $ddeps = getdirectdeps($pkg{'name'}, $pkg{'path'});
484 my @d = split(/,/, $ddeps);
485 foreach my $dep(@d) {
486 getdependencies($dep, $checkver, $pkgname);
487 }
488 if ($checkver) {
489 $depstring = getshortstatus(%pkg) . " $pkgname";
490 } else {
491 $depstring = $pkgname;
492 }
493 $deps{$pkgname} = $depstring;
494 push(@dependencies, $depstring);
495 } else {
496 if ($pkgparent eq "") {
497 return 0;
498 } else {
499 $missingdeps{$pkgname} = $pkgparent;
500 }
501 }
502 }
503 }
504
505 # Download given package (if needed), check md5sum
506 sub downloadpkg {
507 my %pkg = @_;
508 my $fullpath = $pkg{'path'}."/".$pkg{'name'}."#".$pkg{'version'}."-".$pkg{'release'}.".pkg.tar.$compress";
509 if (-f $fullpath) {
510 my $md5 = `md5sum $fullpath`; chomp;
511 $md5 =~ s/\s+.*$//;
512 $md5 =~ chop($md5);
513 if ($md5 ne $pkg{'md5sum'} and not $ignore_md5sum) {
514 print STDERR "=======> ERROR: md5sum mismatch for $pkg{'name'}:\n";
515 print STDERR "required : $pkg{'md5sum'}\n";
516 print STDERR "found : $md5\n";
517 return 0;
518 }
519 return 1;
520 } else {
521 if ($pkg{'url'} eq "") {return 1}; # repo is local and pkg does not exist.
522 my $url = $pkg{'url'};
523 $url =~ s/\#/\%23/;
524 system ("wget --no-directories --tries=3 --waitretry=3 --directory-prefix=$pkg{'path'} $url") == 0 or return 0;
525 my $md5 = `md5sum $fullpath`; chomp;
526 $md5 =~ s/\s+.*$//;
527 $md5 =~ chop($md5);
528 if ($md5 ne $pkg{'md5sum'} and not $ignore_md5sum) {
529 print STDERR "=======> ERROR: md5sum mismatch for $pkg{'name'}:\n";
530 print STDERR "required : $pkg{'md5sum'}\n";
531 print STDERR "found : $md5\n";
532 return 0;
533 }
534 }
535 return 1;
536 }
537
538 # Install given package
539 sub installpkg {
540 my $upgrade = shift(@_);
541 my %pkg = @_;
542 my $aa = $aargs." ";
543 if ($pkg{'readme'} eq "yes") {$readmetasks{$pkg{'name'}} = 1};
544 $pptasks{$pkg{'name'}} = "";
545 if ($download_only) {return 1};
546 if ($force){$aa = $aa."-f "};
547 if ($root) {$aa = $aa."-r ".$root." "};
548 if ($pkg{'pre_install'} eq "yes" and ($install_scripts or $pre_install)) {dopre(%pkg)};
549 my $fullpath = $pkg{'path'}."/".$pkg{'name'}."#".$pkg{'version'}."-".$pkg{'release'}.".pkg.tar.$compress";
550 print "pkg-get: /usr/bin/pkgadd $upgrade$aa$fullpath\n";
551 system ("/usr/bin/pkgadd $upgrade$aa$fullpath") == 0 or return 0;
552 if ($pkg{'post_install'} eq "yes" and ($install_scripts or $post_install)) {dopost(%pkg)};
553 return 1;
554 }
555
556 # Execute pre-install script
557 sub dopre {
558 my %pkg = @_;
559 my $cmd = "/bin/bash $pkg{'path'}/PKGINST $pkg{name}_pre_install";
560 if (system($cmd) == 0){
561 $pptasks{$pkg{'name'}} .= " [pre: ok]";
562 } else {
563 $pptasks{$pkg{'name'}} .= " [pre: failed]";
564 }
565 }
566
567 # Execute post-install script
568 sub dopost {
569 my %pkg = @_;
570 my $cmd = "/bin/bash $pkg{'path'}/PKGINST $pkg{name}_post_install";
571 if (system($cmd) == 0){
572 $pptasks{$pkg{'name'}} .= " [post: ok]";
573 } else {
574 $pptasks{$pkg{'name'}} .= " [post: failed]";
575 }
576 }
577
578 ############################################################################
579 # Main functions (commands)
580 ############################################################################
581
582 # No pun intended ##########################################################
583 sub version {
584 print "pkg-get $VERSION ";
585 print "by Simone Rota <sip\@varlock.com>\n";
586 }
587
588 # Show brief help ##########################################################
589 sub help {
590 print "Usage: pkg-get command <package1> [package2 ... packageN] [options]
591
592 Some command:
593 sync synchronize with the repository
594 depinst install package and its dependencies;
595 info info about package
596 sysup updates all outdated packages
597 diff list all outdated packages
598
599 Some option:
600 -do download only
601 --install-scripts use install scripts
602 -r <root> use <root> for pkgadd
603
604 Example:
605 pkg-get install sqlite pysqlite
606
607 For other commands and samples, see the pkg-get(8) man page\n";
608 }
609
610 # Sync with the remote server(s) ###########################################
611 sub sync {
612 my @r;
613 my $dir;
614 my $url;
615 my $dlerror = 0;
616 foreach my $repo(@repos) {
617 @r = split(/\|/, $repo);
618 $dir = $r[0];
619 $url = $r[1];
620 if (not $url){$url = ""};
621 print "Updating collection $dir\n";
622 if (not -d $dir) {
623 mkdir($dir) or exiterr("cannot create $dir");
624 }
625 if ($url ne "") {
626 for my $f ("PKGREPO", "PKGDEPS", "PKGREAD", "PKGINST") {
627 if (-f "$dir/$f") {rename("$dir/$f", "$dir/$f.old") or exiterr("cannot write to $dir")};
628 if (system("wget -q -P $dir $url/$f") != 0) {
629 print " cannot retrieve $f\n";
630 $dlerror=1;
631 }
632 }
633 if ($dlerror) { # restore backup repo
634 for my $f ("PKGREPO", "PKGDEPS", "PKGREAD", "PKGINST") {
635 if (-f "$dir/$f.old") {rename("$dir/$f.old", "$dir/$f") or exiterr("cannot write to $dir")};};
636 } else { # remove backup repo
637 for my $f ("PKGREPO", "PKGDEPS", "PKGREAD", "PKGINST") {
638 if (-f "$dir/$f.old") {unlink("$dir/$f.old") or exiterr("cannot write to $dir")};};
639 }
640 }
641 }
642 }
643
644 # Show info about the package ##############################################
645 sub info {
646 my $arg = $ARGV[1];
647 foreach my $repo(@repos) {
648 my @r = split(/\|/, $repo);
649 my $dir = $r[0];
650 my $url = $r[1];
651 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
652 while (<REPO>) {
653 chomp;
654 my %pkg = parsepackage($_, $dir, $url, 0);
655 if ($pkg{'name'} eq $arg) {
656 printinfo(%pkg);
657 close(REPO);
658 return;
659 }
660 }
661 close(REPO);
662 }
663 print "Package '$arg' not found\n";
664 }
665
666 # List packages containing given string in their name ######################
667 sub search {
668 my $arg = $ARGV[1];
669 my %found;
670 foreach my $repo(@repos) {
671 my @r = split(/\|/, $repo);
672 my $dir = $r[0];
673 my $url = $r[1];
674 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
675 while (<REPO>) {
676 chomp;
677 my %pkg = parsepackage($_, $dir, $url, 0);
678 if (index($pkg{'name'}, $arg) > -1 and not $found{$pkg{'name'}}) {
679 $found{$pkg{'name'}} = 1;
680 }
681 }
682 close(REPO);
683 }
684 foreach my $key (sort keys %found) {
685 print "$key\n";
686 }
687 if (not %found) {print "No matching packages found\n"};
688 }
689
690 # List packages containing given string (name / description) ###############
691 sub dsearch {
692 my $arg = $ARGV[1];
693 my %found;
694 foreach my $repo(@repos) {
695 my @r = split(/\|/, $repo);
696 my $dir = $r[0];
697 my $url = $r[1];
698 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
699 while (<REPO>) {
700 chomp;
701 my %pkg = parsepackage($_, $dir, $url, 0);
702 if ((index($pkg{'name'}, $arg) > -1 or index($pkg{'description'}, $arg) > -1)
703 and not $found{$pkg{'name'}}) {
704 $found{$pkg{'name'}} = 1;
705 }
706 }
707 close(REPO);
708 }
709 foreach my $key (sort keys %found) {
710 print "$key\n";
711 }
712 if (not %found) {print "No matching packages found\n";};
713 }
714
715 # List all available packages ##############################################
716 sub list {
717 my $arg = $ARGV[1];
718 my %found;
719 foreach my $repo(@repos) {
720 my @r = split(/\|/, $repo);
721 my $dir = $r[0];
722 my $url = $r[1];
723 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
724 while (<REPO>) {
725 chomp;
726 my %pkg = parsepackage($_, $dir, $url, 0);
727 $found{$pkg{'name'}} = 1;
728 }
729 close(REPO);
730 }
731 foreach my $key (sort keys %found) {
732 print "$key\n";
733 }
734 }
735
736 # Show path for a package ##################################################
737 sub path {
738 my $arg = $ARGV[1];
739 foreach my $repo(@repos) {
740 my @r = split(/\|/, $repo);
741 my $dir = $r[0];
742 my $url = $r[1];
743 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
744 while (<REPO>) {
745 chomp;
746 my %pkg = parsepackage($_, $dir, $url, 0);
747 if ($pkg{'name'} eq $arg) {
748 print $pkg{'path'} . "\n";
749 close(REPO);
750 return;
751 }
752 }
753 close(REPO);
754 }
755 print "Package '$arg' not found\n";
756 }
757
758 # Show current installed version of a package ##############################
759 sub current {
760 my $pkgname = $ARGV[1];
761 getinstalled();
762 if ($installed{$pkgname}) {
763 print "$installed{$pkgname}\n";
764 } else {
765 print "Package $pkgname not installed\n";
766 }
767 }
768
769 # Print the README file for a package ######################################
770 sub readme {
771 my $arg = $ARGV[1];
772 foreach my $repo(@repos) {
773 my @r = split(/\|/, $repo);
774 my $dir = $r[0];
775 my $url = $r[1];
776 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
777 while (<REPO>) {
778 chomp;
779 my %pkg = parsepackage($_, $dir, $url, 0);
780 if ($pkg{'name'} eq $arg) {
781 printreadme(%pkg);
782 close(REPO);
783 return;
784 }
785 }
786 close(REPO);
787 }
788 print "Package '$arg' not found\n";
789 }
790
791 # Remove given packages ####################################################
792 sub remove {
793 $curraction = "removed";
794 shift(@ARGV);
795 foreach my $pkg(@ARGV) {
796 $pptasks{$pkg} = "";
797 if (system("/usr/bin/pkgrm $pkg") ==0) {
798 push(@donetasks, $pkg);
799 } else {
800 push(@failtasks, "where removal failed,$pkg");
801 }
802 }
803 printresults();
804 }
805
806 # List installed packages ##################################################
807 sub listinst {
808 getinstalled();
809 foreach my $key (sort keys %installed) {
810 print "$key\n";
811 }
812 }
813
814 # Print if package is installed ###########################################
815 sub isinst {
816 getinstalled();
817 shift(@ARGV);
818 foreach my $pkg(@ARGV) {
819 if ($installed{$pkg}) {
820 print "package $pkg is installed\n";
821 } else {
822 print "package $pkg is not installed\n";
823 }
824 }
825 }
826
827
828 # Lock given packages ######################################################
829 sub dolock {
830 shift(@ARGV);
831 foreach my $arg(@ARGV) {
832 my $found = 0;
833 foreach my $repo(@repos) {
834 if ($found == 0) {
835 my @r = split(/\|/, $repo);
836 my $dir = $r[0];
837 my $url = $r[1];
838 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
839 while (<REPO>) {
840 chomp;
841 my %pkg = parsepackagelight($_);
842 if ($pkg{'name'} eq $arg) {
843 $found = 1;
844 lockadd($arg);
845 }
846 }
847 close(REPO);
848 }
849 }
850 if ($found == 0) {print "Package '$arg' not found\n"};
851 }
852 }
853
854 # Unlock given packages ####################################################
855 sub unlock {
856 shift(@ARGV);
857 my @locked;
858 my $found;
859 foreach my $arg(@ARGV) {
860 $found = 0;
861 @locked = ();
862 open(LCK, $LOCKFILE) or exiterr("could not open lock file");
863 while (<LCK>) {
864 chomp;
865 if ($_ eq $arg) {
866 push (@locked, "-");
867 $found = 1;
868 } else {
869 push (@locked, $_);
870 }
871 }
872 close(LCK);
873 if ($found == 1) {
874 @locked = sort(@locked);
875 open(LCK, ">$LOCKFILE") or exiterr("could not write to lock file");
876 foreach my $lock(@locked) {
877 if ($lock ne "-") {print LCK "$lock\n"};
878 }
879 close(LCK);
880 } else {
881 print "Not locked previously: $arg\n";
882 }
883 }
884 }
885
886 # List locked packages #####################################################
887 sub listlocked {
888 open(LCK, $LOCKFILE)
889 or exit;
890 while (<LCK>) {
891 chomp;
892 print "$_\n";
893 }
894 close(LCK);
895 }
896
897 # Print formatted info #####################################################
898 sub doprintf {
899 my %found;
900 foreach my $repo(@repos) {
901 my @r = split(/\|/, $repo);
902 my $dir = $r[0];
903 my $url = $r[1];
904 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
905 while (<REPO>) {
906 chomp;
907 my %pkg;
908 if (index($ARGV[1], "%i") >=0 ) {
909 %pkg = parsepackage($_, $dir, $url, 1);
910 } else {
911 %pkg = parsepackage($_, $dir, $url, 0);
912 }
913 if (not $found{$pkg{'name'}}) {
914 if ($filter ne "") {
915 my $match = $pkg{'name'};
916 my $cfilter = $filter;
917 $cfilter =~ s/\*/\.\*/;
918 if ($match =~ /^$cfilter$/) {
919 formattedprint(%pkg);
920 $found{$pkg{'name'}} = 1;
921 }
922 } else {
923 formattedprint(%pkg);
924 $found{$pkg{'name'}} = 1;
925 }
926 }
927 }
928 close(REPO);
929 }
930 }
931
932 # Show differences between installed and available packages ################
933 sub diff {
934 my %found;
935 my $gotdiff = 0;
936 foreach my $repo(@repos) {
937 my @r = split(/\|/, $repo);
938 my $dir = $r[0];
939 my $url = $r[1];
940 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
941 while (<REPO>) {
942 chomp;
943 my %pkg;
944 %pkg = parsepackage($_, $dir, $url, 1);
945 if (not $found{$pkg{'name'}}) {
946 if ($pkg{'instversion'}) {
947 if ($pkg{'instversion'} ne $pkg{'version'}."-".$pkg{'release'}) {
948 if (islocked($pkg{'name'}) eq "no") {
949 if ($gotdiff == 0){
950 print "Differences between installed packages and packages repo:\n\n";
951 printf("%-19s %-19s %-19s\n\n","Package","Installed","Available in the repositories");
952 $gotdiff = 1;
953 }
954 printf("%-19s %-19s %-19s\n", $pkg{'name'}, $pkg{'instversion'}, $pkg{'version'}."-".$pkg{'release'});
955 } elsif ($all) { # yeah, it blows, at least avoid to read the locked state twice.
956 if ($gotdiff == 0){
957 print "Differences between installed packages and packages repo:\n\n";
958 printf("%-19s %-19s %-19s\n\n","Package","Installed","Available in the repositories");
959 $gotdiff = 1;
960 }
961 printf("%-19s %-19s %-19s %-19s\n", $pkg{'name'}, $pkg{'instversion'}, $pkg{'version'}."-".$pkg{'release'}, "locked");
962 }
963 }
964 }
965 $found{$pkg{'name'}} = 1;
966 }
967 }
968 close(REPO);
969 }
970 if ($gotdiff ==0) {print "No differences found\n"};
971 }
972
973 # Show differences between installed and available packages ################
974 sub quickdiff {
975 my %found;
976 my $gotdiff = 0;
977 foreach my $repo(@repos) {
978 my @r = split(/\|/, $repo);
979 my $dir = $r[0];
980 my $url = $r[1];
981 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
982 while (<REPO>) {
983 chomp;
984 my %pkg;
985 %pkg = parsepackage($_, $dir, $url, 1);
986 if (not $found{$pkg{'name'}}) {
987 if ($pkg{'instversion'}) {
988 if ($pkg{'instversion'} ne $pkg{'version'}."-".$pkg{'release'} and islocked($pkg{'name'}) eq "no") {
989 if ($gotdiff == 0){
990 print $pkg{'name'};
991 $gotdiff = 1;
992 } else {
993 print " " . $pkg{'name'};
994 }
995 }
996 }
997 $found{$pkg{'name'}} = 1;
998 }
999 }
1000 close(REPO);
1001 }
1002 if ($gotdiff != 0) {print "\n"};
1003 }
1004
1005 # Display duplicate packages (found in more than one repo) #################
1006 sub dup {
1007 my %found;
1008 foreach my $repo(@repos) {
1009 my @r = split(/\|/, $repo);
1010 my $dir = $r[0];
1011 my $url = $r[1];
1012 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
1013 while (<REPO>) {
1014 chomp;
1015 my %pkg;
1016 %pkg = parsepackage($_, $dir, $url, 0);
1017 $found{$pkg{'name'}} .= "###" . $pkg{'path'}."/". $pkg{'name'}.$pkg{'version'}."-".$pkg{'release'};
1018 }
1019 close(REPO);
1020 }
1021 my $curr = "";
1022 foreach my $key (sort keys %found) {
1023 my $value = $found{$key};
1024 $value =~ s/^\#\#\#//;
1025 if (rindex($value, "###") >=0){
1026 print "* $key\n";
1027 my @d = split(/\#\#\#/, $value);
1028 foreach my $dup(@d){
1029 print " $dup\n";
1030 }
1031 }
1032 }
1033 }
1034
1035 # Show list of dependencies for package ####################################
1036 sub depends {
1037 getdependencies($ARGV[1], 1, "") or exiterr("package '$ARGV[1]' not found");
1038 if (@dependencies) {print "-- dependencies ([i] = installed, [u] = updatable)\n"}
1039 foreach my $dep(@dependencies) {
1040 print "$dep\n";
1041 }
1042 if (%missingdeps) {
1043 print "\n-- missing packages\n";
1044 foreach my $dep(sort keys %missingdeps) {
1045 print "$dep from $missingdeps{$dep}\n";
1046 }
1047 }
1048 }
1049
1050 # Show compact list of dependencies for package ############################
1051 sub quickdep {
1052 getdependencies($ARGV[1], 0, "") or exiterr("package '$ARGV[1]' not found");
1053 foreach my $dep(@dependencies) {
1054 print "$dep ";
1055 }
1056 print "\n";
1057 }
1058
1059 # Show packages directly depending from given package ######################
1060 sub dependent {
1061 my $arg = $ARGV[1];
1062 my %dp;
1063 if (not $all) { getinstalled(); }
1064 foreach my $repo(@repos) {
1065 my @r = split(/\|/, $repo);
1066 my $dir = $r[0];
1067 my $url = $r[1];
1068 open(DEPS, "$dir/PKGDEPS")
1069 or exiterr("could not open $dir/PKGDEPS");
1070 while (<DEPS>) {
1071 chomp;
1072 my $dep = $_;
1073 $dep =~ s/\s+\:.*$//;
1074 s/^.*\: /\,/;
1075 s/$/\,\$/;
1076 if ( /\,\Q$arg\E\,/ ) {
1077 if (not $all) {
1078 if ($installed{$dep}) {
1079 $dp{$dep} = 1;
1080 }
1081 } else {
1082 $dp{$dep} = 1;
1083 }
1084 }
1085 }
1086 close(DEPS);
1087 }
1088 foreach my $res(keys %dp) {
1089 print "$res\n";
1090 }
1091 }
1092
1093 # Install given package ####################################################
1094 sub install {
1095 $curraction = "installed";
1096 my @args = @_; shift(@args);
1097 getinstalled();
1098 foreach my $pkgname(@args) {
1099 my %pkg = getpackage($pkgname, 1);
1100 if (not %pkg) {
1101 push(@failtasks, "not found,$pkgname");
1102 } elsif (getshortstatus(%pkg) ne "[ ]") {
1103 push(@prevtasks, "$pkgname");
1104 } elsif (downloadpkg(%pkg) and installpkg("", %pkg)) {
1105 push(@donetasks, $pkgname);
1106 } else {
1107 push(@failtasks, "where install failed,$pkgname");
1108 }
1109 }
1110 printresults();
1111 }
1112
1113 # Update given package #####################################################
1114 sub update {
1115 $curraction = "updated";
1116 my @args = @_; shift(@args);
1117 getinstalled();
1118 foreach my $pkgname(@args) {
1119 my %pkg = getpackage($pkgname, 1);
1120 if (not %pkg) {
1121 push(@failtasks, "not found,$pkgname");
1122 } elsif (getshortstatus(%pkg) eq "[ ]") {
1123 push(@prevtasks, "$pkgname");
1124 } elsif (downloadpkg(%pkg) and installpkg("-u ", %pkg)) {
1125 push(@donetasks, $pkgname);
1126 } else {
1127 push(@failtasks, "where update failed,$pkgname");
1128 }
1129 }
1130 printresults();
1131 }
1132
1133 # Update out of date packages ##############################################
1134 sub sysup {
1135 my %found;
1136 my @diff;
1137 foreach my $repo(@repos) {
1138 my @r = split(/\|/, $repo);
1139 my $dir = $r[0];
1140 my $url = $r[1];
1141 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
1142 while (<REPO>) {
1143 chomp;
1144 my %pkg;
1145 %pkg = parsepackage($_, $dir, $url, 1);
1146 if (not $found{$pkg{'name'}}) {
1147 if ($pkg{'instversion'}) {
1148 if ($pkg{'instversion'} ne $pkg{'version'}."-".$pkg{'release'} and islocked($pkg{'name'}) eq "no") {
1149 push(@diff, $pkg{'name'});
1150 }
1151 }
1152 $found{$pkg{'name'}} = 1;
1153 }
1154 }
1155 close(REPO);
1156 }
1157 if (@diff) {
1158 unshift(@diff, "dummy"); # is shifted later in update sub;
1159 update(@diff);
1160 }
1161 }
1162
1163 sub depinst {
1164 my @toinst; my %seen;
1165 $curraction = "installed";
1166 my @args = @ARGV; shift(@args);
1167 getinstalled();
1168 foreach my $pkgname(@args) {
1169 getdependencies($pkgname, 0, "");
1170 foreach my $dep(@dependencies) {
1171 if (not $seen{$dep}) {
1172 my %pkg = getpackage($dep, 1);
1173 if (%pkg) {
1174 if (getshortstatus(%pkg) eq "[ ]"){
1175 push(@toinst, $pkg{'name'});
1176 }
1177 }
1178 $seen{$dep} = 1;
1179 }
1180 }
1181 }
1182 if (@toinst) {
1183 unshift(@toinst, "dummy"); # is shifted later in install sub;
1184 install(@toinst);
1185 }
1186 }
|