I saw someone who posted that they used the output of out-of-date to
automatically do updates.  I was looking at doing that, and found that
it would be easier to do correctly if I knew what depended on what.  

What I did was turn out-of-date into a "modulino"[1], then I wrote a
script that uses most of out-of-date, but instead of printing the
out-of-date ports, it runs make update.

This shouldn't change any of the current functionality of out-of-date,
but it does allow me to extend it.

I am sure there is probably a better way to write the "sort_by_depends"
sub, but I haven't spent enough time on the modules that are available
to know what it would be.  I did look at some of them, like
OpenBSD::Dependencies, but I didn't see how to get that to work with the
list of ports to give me a sorted SUBDIR list.

[1] http://www.perlmonks.org/?node_id=396759

l8rZ,
-- 
andrew - ICQ# 253198 - Jabber: [EMAIL PROTECTED]

BOFH excuse of the day: nesting roaches shorted out the ether cable
Index: out-of-date
===================================================================
RCS file: /cvs/ports/infrastructure/build/out-of-date,v
retrieving revision 1.16
diff -u -p -r1.16 out-of-date
--- out-of-date 1 Jun 2007 15:01:50 -0000       1.16
+++ out-of-date 2 May 2008 22:04:40 -0000
@@ -1,4 +1,5 @@
 #!/usr/bin/perl
+package OpenBSD::OutOfDate;
 
 # $OpenBSD: out-of-date,v 1.16 2007/06/01 15:01:50 espie Exp $
 #
@@ -27,15 +28,11 @@ use OpenBSD::ProgressMeter;
 use File::Temp;
 
 our $opt_q;
-set_usage('out-of-date [-q]');
-try {
-       getopts('q');
-} catchall {
-       Usage($_);
-};
+
 
 sub collect_installed
 {
+       my $class = shift;
        my $pkg = {};
        for my $name (installed_packages(1)) {
                my ($stem, $version) = OpenBSD::PackageName::splitname($name);
@@ -60,6 +57,7 @@ sub collect_installed
 
 sub fh_open
 {
+       my $class = shift;
        open(my $fh, shift);
        my $old = select $fh;
        $| = 1;
@@ -69,6 +67,7 @@ sub fh_open
 
 sub fh_close
 {
+       my $class = shift;
        my ($fh, $old) = @_;
        close($fh);
        select $old;
@@ -76,6 +75,7 @@ sub fh_close
 
 sub collect_port_versions
 {
+       my $class = shift;
        my ($pkg, $portsdir, $notfound) = @_;
 
        my @subdirs = ();
@@ -99,7 +99,7 @@ sub collect_port_versions
 
        my $progress = OpenBSD::ProgressMeter->new;
        $progress->set_header("Collecting port versions");
-       my ($fh, $old) = fh_open($cmd);
+       my ($fh, $old) = $class->fh_open($cmd);
        my $subdir     = "";
        while (<$fh>) {
                chomp;
@@ -122,7 +122,7 @@ sub collect_port_versions
                $port->{$subdir}->{stem}    = $stem;
                $port->{$subdir}->{version} = $version;
        }
-       fh_close($fh, $old);
+       $class->fh_close($fh, $old);
        $progress->next;
 
        return $port, $error;
@@ -130,10 +130,10 @@ sub collect_port_versions
 
 sub collect_port_signatures
 {
+       my $class    = shift;
        my $pkg      = shift;
        my $port     = shift;
        my $portsdir = shift;
-       my $output   = shift;
 
        my @subdirs = ();
        for my $dir (keys %$port) {
@@ -156,7 +156,7 @@ sub collect_port_signatures
        my $total = scalar @subdirs;
        my $progress = OpenBSD::ProgressMeter->new;
        $progress->set_header("Collecting port signatures");
-       my ($fh, $old) = fh_open($cmd);
+       my ($fh, $old) = $class->fh_open($cmd);
        my $subdir     = "";
        while (<$fh>) {
                chomp;
@@ -169,12 +169,13 @@ sub collect_port_signatures
                next unless $_ or $subdir;
                $port->{$subdir}->{signature} = $_;
        }
-       fh_close($fh, $old);
+       $class->fh_close($fh, $old);
        $progress->next;
 }
 
 sub split_sig
 {
+       my $class = shift;
        my $sig = shift;
        my $ret = {};
 
@@ -187,10 +188,11 @@ sub split_sig
 
 sub diff_sig
 {
+       my $class = shift;
        my ($dir, $pkg, $port) = @_;
 
-       my $old = split_sig($pkg->{$dir}->{signature});
-       my $new = split_sig($port->{$dir}->{signature});
+       my $old = $class->split_sig($pkg->{$dir}->{signature});
+       my $new = $class->split_sig($port->{$dir}->{signature});
 
        for my $key (keys %$old) {
                if (defined $new->{$key}) {
@@ -204,56 +206,75 @@ sub diff_sig
 
 sub find_outdated
 {
-       my ($pkg, $port, $output) = @_;
+       my $class = shift;
+       my ($pkg, $port, $outdated) = @_;
 
        for my $dir (keys %$pkg) {
                next unless $port->{$dir};
                if ($pkg->{$dir}->{name} ne $port->{$dir}->{name}) {
-                       push(@$output, sprintf("%-30s # %s -> %s\n", $dir,
-                           $pkg->{$dir}->{version}, $port->{$dir}->{version}));
+                       $outdated->{$dir} = sprintf("%s -> %s",
+                           $pkg->{$dir}->{version}, $port->{$dir}->{version});
                        next;
                }
                next if $opt_q;
                if ($pkg->{$dir}->{signature} ne $port->{$dir}->{signature}) {
-                       push(@$output, sprintf("%-30s # %s -> %s\n", $dir,
-                           diff_sig($dir, $pkg, $port)));
+                       $outdated->{$dir} = $class->diff_sig($dir, $pkg, $port);
+                       next;
                }
        }
 }
 
 my $portsdir = $ENV{PORTSDIR} || "/usr/ports";
+__PACKAGE__->run() unless caller();
 
-print STDERR "Collecting installed packages\n";
-my $pkg = collect_installed();
+sub run {
+       my $class = shift;
 
-my @output   = ();
-my @notfound = ();
-my ($port, $errors) = collect_port_versions($pkg, $portsdir, [EMAIL 
PROTECTED]);
-
-collect_port_signatures($pkg, $port, $portsdir, [EMAIL PROTECTED]) unless 
$opt_q;
-find_outdated($pkg, $port, [EMAIL PROTECTED]);
-
-print STDERR "Outdated ports:\n\n";
-print $_ for sort @output;
-
-if ($opt_q) {
-       print STDERR "\nWARNING: You've used the -q option. With this,\n"
-           . "out-of-date only looks for changed package names\nbut not "
-           . "for changed package signatures. If you\nwant to see ALL "
-           . "of your outdated packages,\ndon't use -q.\n";
-}
+       set_usage('out-of-date [-q]');
+       try {
+               getopts('q');
+       }
+       catchall {
+               Usage($_);
+       };
+
+       print STDERR "Collecting installed packages\n";
+       my $pkg = $class->collect_installed();
+
+       my %outdated = ();
+       my @notfound = ();
+       my ( $port, $errors ) =
+         $class->collect_port_versions( $pkg, $portsdir, [EMAIL PROTECTED] );
+
+       $class->collect_port_signatures( $pkg, $port, $portsdir ) unless $opt_q;
+       $class->find_outdated( $pkg, $port, \%outdated );
+
+       print STDERR "Outdated ports:\n\n";
+       foreach my $dir (sort keys %outdated) {
+               printf("%-30s # %s\n", $dir, $outdated{$dir});
+       }
 
-if (@notfound > 0) {
-       print STDERR "\nPorts that can't be found in the official "
-           . "ports tree:\n";
-       for (sort @notfound) {
-               print STDERR "  $_\n";
+       if ($opt_q) {
+               print STDERR "\nWARNING: You've used the -q option. With 
this,\n"
+                 . "out-of-date only looks for changed package names\nbut not "
+                 . "for changed package signatures. If you\nwant to see ALL "
+                 . "of your outdated packages,\ndon't use -q.\n";
        }
-}
-if ((keys %$errors) > 0) {
-       print STDERR "\nErrors:\n";
-       for (sort keys %$errors) {
-               print STDERR "  $_\n";
-               print STDERR "    $_\n" for @{$errors->{$_}};
+
+       if ( @notfound > 0 ) {
+               print STDERR "\nPorts that can't be found in the official "
+                 . "ports tree:\n";
+               for ( sort @notfound ) {
+                       print STDERR "  $_\n";
+               }
+       }
+       if ( ( keys %$errors ) > 0 ) {
+               print STDERR "\nErrors:\n";
+               for ( sort keys %$errors ) {
+                       print STDERR "  $_\n";
+                       print STDERR "    $_\n" for @{ $errors->{$_} };
+               }
        }
 }
+
+1;
#!/usr/bin/perl
package OpenBSD::OutOfDate::Update;

# $OpenBSD$
#
# Copyright (c) 2008 Andrew Fresh <[EMAIL PROTECTED]>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

my $portsdir = $ENV{PORTSDIR} || "/usr/ports";
do $portsdir . '/infrastructure/build/out-of-date';
use base qw{ OpenBSD::OutOfDate };

__PACKAGE__->run() unless caller();

sub run {
    my $class = shift;

    print STDERR "Collecting installed packages\n";
    my $pkg = $class->collect_installed();

    my @outdated = ();
    my @notfound = ();
    my ( $port, $errors ) =
      $class->collect_port_versions( $pkg, $portsdir, [EMAIL PROTECTED] );

    $class->collect_port_signatures( $pkg, $port, $portsdir ) unless $opt_q;
    $class->find_outdated( $pkg, $port, \%outdated );

    print STDERR "Updating ports:\n\n";
    my @subdirs = $class->sort_by_depends( $port, keys %outdated );
    my $cmd =
        "cd $portsdir && SUBDIR=\""
      . join( q{ }, @subdirs )
      . "\" REPORT_PROBLEM=true make update 2>&1 |";
    print $cmd, "\n";
    my ($fh, $old) = $class->fh_open($cmd);
    while (my $line = <$fh>) {
        print $line;
    }
    $class->fh_close($fh, $old);

    return 1;
}

sub sort_by_depends {
    my $class = shift;
    my ( $port, @keys ) = @_;
    @keys = sort @keys;

    my @sorted;
  KEY: while ( my $key = shift @keys ) {
        foreach my $subkey (@keys) {
            my $stem      = $port->{$key}->{stem};
            my $signature = $port->{$key}->{signature};
            my $substem   = $port->{$subkey}->{stem};
            $signature =~ s/^$stem//xms;

            if (   defined $substem
                && defined $signature
                && $signature =~ /$substem/xms )
            {
                push @keys, $key;
                next KEY;
            }
        }
        push @sorted, $key;
    }

    return @sorted;
}

1;

Reply via email to