]> git.donarmstrong.com Git - wannabuild.git/blobdiff - bin/wanna-build
filter out noautobuild: use proper perl
[wannabuild.git] / bin / wanna-build
index 5d3f4b7d6577c0ee9bd08874279b5121389ebc8e..78e80ba119b75fe8c2837c00db31dc105eddd0a3 100755 (executable)
@@ -3,7 +3,7 @@
 # wanna-build: coordination script for Debian buildds
 # Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
 # Copyright (C) 2005-2008 Ryan Murray <rmurray@debian.org>
 # wanna-build: coordination script for Debian buildds
 # Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
 # Copyright (C) 2005-2008 Ryan Murray <rmurray@debian.org>
-# Copyright (C) 2010      Andreas Barth <aba@not.so.argh.org>
+# Copyright (C) 2010,2011 Andreas Barth <aba@not.so.argh.org>
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License as
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License as
@@ -23,6 +23,8 @@ use strict;
 use warnings;
 use 5.010;
 
 use warnings;
 use 5.010;
 
+die "wanna-build disabled" if -f "/org/wanna-build/NO-WANNA-BUILD";
+
 package conf;
 
 use vars qw< $basedir $dbbase $transactlog $mailprog $buildd_domain >;
 package conf;
 
 use vars qw< $basedir $dbbase $transactlog $mailprog $buildd_domain >;
@@ -70,7 +72,8 @@ our ($verbose, $mail_logs, $list_order, $list_state,
     $short_date, $list_min_age, $list_max_age, $dbbase, @curr_time,
     $build_priority, %new_vers, $binNMUver, %merge_srcvers, %merge_binsrc,
     $printformat, $ownprintformat, $privmode, $extra_depends, $extra_conflicts,
     $short_date, $list_min_age, $list_max_age, $dbbase, @curr_time,
     $build_priority, %new_vers, $binNMUver, %merge_srcvers, %merge_binsrc,
     $printformat, $ownprintformat, $privmode, $extra_depends, $extra_conflicts,
-    %distributions, %distribution_aliases, $actions
+    %distributions, %distribution_aliases, $actions,
+    $sshwrapper,
     );
 our $Pas = '/org/buildd.debian.org/etc/packages-arch-specific/Packages-arch-specific';
 our $simulate = 0;
     );
 our $Pas = '/org/buildd.debian.org/etc/packages-arch-specific/Packages-arch-specific';
 our $simulate = 0;
@@ -95,7 +98,7 @@ sub _set_mode { $op_mode = "$_[0]" }
 
 sub _option_deprecated { warn "Option $_[0] is deprecated" }
 
 
 sub _option_deprecated { warn "Option $_[0] is deprecated" }
 
-GetOptions(
+my @wannabuildoptions = (
     # this is not supported by all operations (yet)!
     'simulate'      => \$simulate,
     'simulate-edos' => \$simulate_edos,
     # this is not supported by all operations (yet)!
     'simulate'      => \$simulate,
     'simulate-edos' => \$simulate_edos,
@@ -160,6 +163,16 @@ GetOptions(
             when ('s') { $distribution = 'stable'; }
             when ('t') { $distribution = 'testing'; }
             when ('u') { $distribution = 'unstable'; }
             when ('s') { $distribution = 'stable'; }
             when ('t') { $distribution = 'testing'; }
             when ('u') { $distribution = 'unstable'; }
+
+            if ($distribution eq 'any-priv') {
+                $privmode = 1;
+                $distribution = 'any';
+            }
+            if ($distribution eq 'any-unpriv') {
+                $privmode = 0;
+                $distribution = 'any';
+            }
+            $privmode = 1 if $distribution =~ /security/;
         }
     },
     'order|O=s' => sub {
         }
     },
     'order|O=s' => sub {
@@ -169,13 +182,18 @@ GetOptions(
     },
     'message|m=s'  => \$fail_reason,
     'database|b=s' => sub {
     },
     'message|m=s'  => \$fail_reason,
     'database|b=s' => sub {
+        # If they didn't specify an arch, try to get it from database name which
+        # is in the form of $arch/build-db
+        # This is for backwards compatibity with older versions that didn't
+        # specify the arch yet.
         warn "database is deprecated, please use 'arch' instead.\n";
         warn "database is deprecated, please use 'arch' instead.\n";
-        $conf::dbbase = $_[1];
+        $_[1] =~ m#^([^/]+)#;
+        $arch ||= $1;
     },
     'arch|A=s'     => \$arch,
     'user|U=s'     => \$user,
     'min-age|a=i'       => \$list_min_age,
     },
     'arch|A=s'     => \$arch,
     'user|U=s'     => \$user,
     'min-age|a=i'       => \$list_min_age,
-    'max-age=i'         => \$list_max_age,
+    'max-age=i'         => sub { $list_min_age = -1 * ($_[1]); },
     'format=s'          => \$printformat,
     'own-format=s'      => \$ownprintformat,
     'Pas=s'             => \$Pas,
     'format=s'          => \$printformat,
     'own-format=s'      => \$ownprintformat,
     'Pas=s'             => \$Pas,
@@ -188,8 +206,12 @@ GetOptions(
     'manual-edit'                => \&_set_mode,
     'distribution-architectures' => \&_set_mode,
     'distribution-aliases'       => \&_set_mode,
     'manual-edit'                => \&_set_mode,
     'distribution-architectures' => \&_set_mode,
     'distribution-aliases'       => \&_set_mode,
-) or usage();
-$list_min_age = -1 * $list_max_age if $list_max_age;
+
+    'ssh-wrapper'       => \$sshwrapper,
+    'recorduser'        => \$recorduser,
+    );
+
+GetOptions(@wannabuildoptions) or usage();
 
 my $dbh;
 
 
 my $dbh;
 
@@ -200,19 +222,8 @@ END {
        }
 }
 
        }
 }
 
-$distribution ||= "sid";
-if ($distribution eq 'any-priv') {
-    $privmode = 1;
-    $distribution = 'any';
-}
-if ($distribution eq 'any-unpriv') {
-    $privmode = 0;
-    $distribution = 'any';
-}
-
 my $schema_suffix = '';
 my $schema_suffix = '';
-$recorduser //= (not -t and $user//"" =~ /^buildd_/);
-if ((isin( $op_mode, qw(list info distribution-architectures distribution-aliases)) && $distribution !~ /security/ && !$recorduser && !($privmode)) || $simulate) {
+if ((isin( $op_mode, qw(list info distribution-architectures distribution-aliases)) && !$recorduser && !$privmode) || $simulate) {
        $dbh = DBI->connect("DBI:Pg:service=wanna-build") || 
                die "FATAL: Cannot open database: $DBI::errstr\n";
        $schema_suffix = '_public';
        $dbh = DBI->connect("DBI:Pg:service=wanna-build") || 
                die "FATAL: Cannot open database: $DBI::errstr\n";
        $schema_suffix = '_public';
@@ -247,32 +258,24 @@ foreach my $name (keys %$rows) {
 $distribution = $distribution_aliases{$distribution} if (isin($distribution, keys %distribution_aliases));
 
 $op_mode ||= "set-building";
 $distribution = $distribution_aliases{$distribution} if (isin($distribution, keys %distribution_aliases));
 
 $op_mode ||= "set-building";
-undef $distribution if $distribution eq 'any';
 if ($distribution) {
     my @dists = split(/[, ]+/, $distribution);
     foreach my $dist (@dists) {
         die "Bad distribution '$distribution'\n"
 if ($distribution) {
     my @dists = split(/[, ]+/, $distribution);
     foreach my $dist (@dists) {
         die "Bad distribution '$distribution'\n"
-           if !isin($dist, keys %distributions);
+           if !isin($dist, keys %distributions, "any");
     }
 }
     }
 }
-if (!isin ( $op_mode, qw(list) ) && ( !$distribution || $distribution =~ /[ ,]/)) {
+if (!isin ( $op_mode, qw(list) ) && ( ($distribution//"") =~ /[ ,]/)) {
     die "multiple distributions are only allowed for list";
 }
 
     die "multiple distributions are only allowed for list";
 }
 
-# If they didn't specify an arch, try to get it from database name which
-# is in the form of $arch/build-db
-# This is for backwards compatibity with older versions that didn't
-# specify the arch yet.
-$conf::dbbase =~ m#^([^/]+)#;
-$arch ||= $1;
-
 # TODO: Check that it's an known arch (for that dist), and give
 # a proper error.
 
 if ($verbose) {
 # TODO: Check that it's an known arch (for that dist), and give
 # a proper error.
 
 if ($verbose) {
-       my $version = '$Revision: db181a534e9d $ $Date: 2008/03/26 06:20:22 $ $Author: rmurray $';
-       $version =~ s/(^\$| \$ .*$)//g;
-       print "wanna-build $version for $distribution on $arch\n";
+       my $version = '$Id$';
+       $version =~ s/^.* ([a-f0-9]+) .*$/$1/g;
+       print "wanna-build $version for ".($distribution//"sid")." on $arch\n";
 }
 
 if (!@ARGV && !isin( $op_mode, qw(list merge-quinn merge-partial-quinn import export
 }
 
 if (!@ARGV && !isin( $op_mode, qw(list merge-quinn merge-partial-quinn import export
@@ -340,22 +343,20 @@ $list_order ||= $yamlmap->{"list-order"}{'default'};
 $api //= $yamlmap->{"api"};
 $api //= 0;
 
 $api //= $yamlmap->{"api"};
 $api //= 0;
 
-process();
-
-$dbh->commit;
-$dbh->disconnect;
-
-if ($mail_logs && $conf::log_mail) {
-       send_mail( $conf::log_mail,
-                          "wanna-build $distribution state changes $curr_date",
-                          "State changes at $curr_date for distribution ".
-                          "$distribution:\n\n$mail_logs\n" );
+if (isin($op_mode, qw<forget-user merge-v3 import>) && defined @conf::admin_users && !isin( $real_user, @conf::admin_users) && !$simulate ) {
+    die "This operation is restricted to admin users";
+}
+if (!isin($op_mode, qw<distribution-architectures distribution-aliases>)) {
+    die "need an architecture" unless $arch;
+    my $rows = $dbh->selectall_hashref('SELECT distribution as d from distribution_architectures where architecture=? and distribution=?', [qw<d>], undef, ($arch, $distribution//"sid")) if ($distribution//"") ne 'any';
+    $rows = $dbh->selectall_hashref('SELECT distribution as d from distribution_architectures where architecture=?', [qw<d>], undef, ($arch,)) unless $rows;
+    die "architecture ($arch) does not exist (at least not for ".($distribution//"sid").")" if !keys %$rows and $distribution//"sid" ne 'any';
+    die "architecture ($arch) does not exist" if !keys %$rows;
 }
 
 }
 
-exit 0;
-
-
-sub process {
+my $suite = $distribution;
+$distribution ||='sid';
+undef $distribution if $distribution eq 'any';
 
        SWITCH: foreach ($op_mode) {
                /^set-(.+)/ && do {
 
        SWITCH: foreach ($op_mode) {
                /^set-(.+)/ && do {
@@ -371,9 +372,6 @@ sub process {
                        last SWITCH;
                };
                /^forget-user/ && do {
                        last SWITCH;
                };
                /^forget-user/ && do {
-                       die "This operation is restricted to admin users\n"
-                               if (defined @conf::admin_users and
-                                   !isin( $real_user, @conf::admin_users));
                        forget_users( @ARGV );
                        last SWITCH;
                };
                        forget_users( @ARGV );
                        last SWITCH;
                };
@@ -382,20 +380,21 @@ sub process {
                        last SWITCH;
                };
                /^merge-v3/ && do {
                        last SWITCH;
                };
                /^merge-v3/ && do {
-                        die "This operation is restricted to admin users\n"
-                           if (defined @conf::admin_users and !isin( $real_user, @conf::admin_users) and !$simulate);
                         # call with installed-packages+ . installed-sources+ [ . available-for-build-packages* [ . consider-as-installed-source* ]  ]
                         # in case available-for-build-packages is not specified, installed-packages are used
                         lock_table() unless $simulate;
                         my $replacemap = { '%ARCH%' => $arch, '%SUITE%' => $distribution };
                         map { my $k = $_; grep { $k =~ s,$_,$replacemap->{$_}, } keys %{$replacemap}; $_ = $k; } @ARGV;
                         # call with installed-packages+ . installed-sources+ [ . available-for-build-packages* [ . consider-as-installed-source* ]  ]
                         # in case available-for-build-packages is not specified, installed-packages are used
                         lock_table() unless $simulate;
                         my $replacemap = { '%ARCH%' => $arch, '%SUITE%' => $distribution };
                         map { my $k = $_; grep { $k =~ s,$_,$replacemap->{$_}, } keys %{$replacemap}; $_ = $k; } @ARGV;
-                        my @ipkgs = &parse_argv( \@ARGV, '.');
-                        my @isrcs = &parse_argv( \@ARGV, '.');
-                        my @bpkgs = &parse_argv( \@ARGV, '.');
-                        my @psrcs = &parse_argv( \@ARGV, '.');
+                        my @ipkgs = &parse_argv( \@ARGV, '.'); # installed packages
+                        my @isrcs = &parse_argv( \@ARGV, '.'); # installed sources
+                        my @bpkgs = &parse_argv( \@ARGV, '.'); # packages available for building (edos-debcheck)
+                        my @psrcs = &parse_argv( \@ARGV, '.'); # consider as installed sources
                         use WB::QD;
                         my $srcs = WB::QD::readsourcebins($arch, $Pas, \@isrcs, \@ipkgs);
                         if (@psrcs) {
                         use WB::QD;
                         my $srcs = WB::QD::readsourcebins($arch, $Pas, \@isrcs, \@ipkgs);
                         if (@psrcs) {
+                            # Installed sources of the base suite: only add them as related, not
+                            # installed; skip the entries if we got something in installed
+                            # sources already.
                             my $psrcs = WB::QD::readsourcebins($arch, $Pas, \@psrcs, []);
                             foreach my $k (keys %$$psrcs) {
                                 next if $$srcs->{$k};
                             my $psrcs = WB::QD::readsourcebins($arch, $Pas, \@psrcs, []);
                             foreach my $k (keys %$$psrcs) {
                                 next if $$srcs->{$k};
@@ -405,17 +404,14 @@ sub process {
                             }
                         }
                         parse_all_v3($$srcs, {'arch' => $arch, 'suite' => $distribution, 'time' => $curr_date});
                             }
                         }
                         parse_all_v3($$srcs, {'arch' => $arch, 'suite' => $distribution, 'time' => $curr_date});
+                        # The packages passed to edos-debcheck are normally the binaries available,
+                        # unless you've also a base suite the builder will take packages from.
                         @bpkgs = @ipkgs unless @bpkgs;
                         call_edos_depcheck( {'arch' => $arch, 'pkgs' => \@bpkgs, 'srcs' => $$srcs, 'depwait' => 1 });
                         last SWITCH;
                };
                /^import/ && do {
                         @bpkgs = @ipkgs unless @bpkgs;
                         call_edos_depcheck( {'arch' => $arch, 'pkgs' => \@bpkgs, 'srcs' => $$srcs, 'depwait' => 1 });
                         last SWITCH;
                };
                /^import/ && do {
-                       die "This operation is restricted to admin users\n"
-                               if (defined @conf::admin_users and
-                                   !isin( $real_user, @conf::admin_users));
-                       $dbh->do("DELETE from " . table_name() . 
-                               " WHERE distribution = ?", undef,
-                               $distribution)
+                       $dbh->do("DELETE from ".table_name()." WHERE distribution = ?", undef, $distribution)
                                or die $dbh->errstr;
                        forget_users();
                        read_db( $import_from );
                                or die $dbh->errstr;
                        forget_users();
                        read_db( $import_from );
@@ -426,7 +422,7 @@ sub process {
                        last SWITCH;
                };
                /^distribution-architectures/ && do {
                        last SWITCH;
                };
                /^distribution-architectures/ && do {
-                       show_distribution_architectures();
+                       show_distribution_architectures({'suite' => $suite});
                        last SWITCH;
                };
                /^distribution-aliases/ && do {
                        last SWITCH;
                };
                /^distribution-aliases/ && do {
@@ -447,8 +443,20 @@ sub process {
                        update_user_info($user);
                }
        }
                        update_user_info($user);
                }
        }
+
+
+$dbh->commit unless $simulate;
+$dbh->disconnect;
+
+if ($mail_logs && $conf::log_mail) {
+       send_mail( $conf::log_mail,
+                          "wanna-build $distribution state changes $curr_date",
+                          "State changes at $curr_date for distribution ".
+                          "$distribution:\n\n$mail_logs\n" );
 }
 
 }
 
+exit 0;
+
 
 BEGIN {
     $actions = {
 
 BEGIN {
     $actions = {
@@ -1177,6 +1185,12 @@ sub list_packages {
         @list = grep { my $i = $_->{'component'}; grep { $i eq $_ } split /[, ]+/, $yamlmap->{"restrict"}{'component'} } @list;
         # extra depends / conflicts only from api 1 on
         @list = grep { !$_->{'extra_depends'} and !$_->{'extra_conflicts'} } @list if $api < 1 ;
         @list = grep { my $i = $_->{'component'}; grep { $i eq $_ } split /[, ]+/, $yamlmap->{"restrict"}{'component'} } @list;
         # extra depends / conflicts only from api 1 on
         @list = grep { !$_->{'extra_depends'} and !$_->{'extra_conflicts'} } @list if $api < 1 ;
+        # filter out packages for needs-build in noautobuild state - same could exist for weaknoautobuild if buildds would tell us what they do
+        if (($state eq 'needs-build') && ($yamlmap->{"restrict"}) && ($yamlmap->{"restrict"}{"noautobuild"})) {
+            foreach my $key (map {keys %$_} @{$yamlmap->{"restrict"}{"noautobuild"}}) {
+                @list = grep { $_->{'package'} ne $key } @list;
+            }
+        }
 
         # first adjust ownprintformat, then set printformat accordingly
         $printformat ||= $yamlmap->{"format"}{$ownprintformat} if $ownprintformat;
 
         # first adjust ownprintformat, then set printformat accordingly
         $printformat ||= $yamlmap->{"format"}{$ownprintformat} if $ownprintformat;
@@ -1558,7 +1572,7 @@ sub build_deplist {
 
 sub filterarch {
     return "" unless $_[0];
 
 sub filterarch {
     return "" unless $_[0];
-    return Dpkg::Deps::parse($_[0], ("reduce_arch" => 1, "host_arch" => $_[1]))->dump();
+    return Dpkg::Deps::deps_parse($_[0], ("reduce_arch" => 1, "host_arch" => $_[1]))->output();
 }
 
 sub wb_edos_builddebcheck {
 }
 
 sub wb_edos_builddebcheck {
@@ -1605,9 +1619,9 @@ sub wb_edos_builddebcheck {
         }   
     }
 
         }   
     }
 
-    print "calling: edos-debcheck $edosoptions < $sourcesfile ".join('', map {" '-base FILE' ".$_ } @$packagefiles)."\n";
+    print "calling: edos-debcheck $edosoptions < $sourcesfile ".join('', map {" -I ".$_ } @$packagefiles)."\n";
     open(my $result_cmd, '-|',
     open(my $result_cmd, '-|',
-        "edos-debcheck $edosoptions < $sourcesfile ".join('', map {" '-base FILE' ".$_ } @$packagefiles));
+        "edos-debcheck $edosoptions < $sourcesfile ".join('', map {" -I ".$_ } @$packagefiles));
 
     my $explanation="";
     my $result={};
 
     my $explanation="";
     my $result={};
@@ -1654,7 +1668,9 @@ sub call_edos_depcheck {
     my $args = shift;
     my $srcs = $args->{'srcs'};
     my $key;
     my $args = shift;
     my $srcs = $args->{'srcs'};
     my $key;
-    
+   
+    # Do not dispatch edos-debcheck if BD-Uninstallable is deactivated for the target.
+    # ("noadw")  Depwait will always be 1 in normal use.
     return if defined ($distributions{$distribution}{noadw}) && not defined $args->{'depwait'};
 
     # We need to check all of needs-build, as any new upload could make
     return if defined ($distributions{$distribution}{noadw}) && not defined $args->{'depwait'};
 
     # We need to check all of needs-build, as any new upload could make
@@ -1662,13 +1678,14 @@ sub call_edos_depcheck {
     # We also check everything in bd-uninstallable, as any new upload could
     # make that work again
     my (%interesting_packages, %interesting_packages_depwait);
     # We also check everything in bd-uninstallable, as any new upload could
     # make that work again
     my (%interesting_packages, %interesting_packages_depwait);
-    my $db = get_all_source_info();
+    my $db = get_all_source_info(); # TODO: Filter for needs-build bd-uninst dep-wait, that's all we need.
     foreach $key (keys %$db) {
        my $pkg = $db->{$key};
         if (defined $pkg and isin($pkg->{'state'}, qw/Needs-Build BD-Uninstallable/) and not defined ($distributions{$distribution}{noadw})) {
     foreach $key (keys %$db) {
        my $pkg = $db->{$key};
         if (defined $pkg and isin($pkg->{'state'}, qw/Needs-Build BD-Uninstallable/) and not defined ($distributions{$distribution}{noadw})) {
-               $interesting_packages{$key} = undef;
+               $interesting_packages{$key} = undef; # add key to interesting packages
        }
         if (defined $pkg and isin($pkg->{'state'}, qw/Dep-Wait/) and defined $args->{'depwait'}) {
        }
         if (defined $pkg and isin($pkg->{'state'}, qw/Dep-Wait/) and defined $args->{'depwait'}) {
+                # Depwaits are checked by creating pseudo binaries for edos-debcheck, so collect them.
                $interesting_packages_depwait{$key} = undef;
                 # we always check for BD-Uninstallability in depwait - could be that depwait is satisfied but package is uninstallable
                $interesting_packages{$key} = undef unless defined ($distributions{$distribution}{noadw});
                $interesting_packages_depwait{$key} = undef;
                 # we always check for BD-Uninstallability in depwait - could be that depwait is satisfied but package is uninstallable
                $interesting_packages{$key} = undef unless defined ($distributions{$distribution}{noadw});
@@ -1689,12 +1706,12 @@ sub call_edos_depcheck {
         # If such a "binary" package is installable, the corresponding source package is buildable.
        print $SOURCES "Package: source---$key\n";
        print $SOURCES "Version: $pkg->{'version'}\n";
         # If such a "binary" package is installable, the corresponding source package is buildable.
        print $SOURCES "Package: source---$key\n";
        print $SOURCES "Version: $pkg->{'version'}\n";
-        my $t = &filterarch($srcs->{$key}{'dep'} || $srcs->{$key}{'depends'}, $arch);
-        my $tt = &filterarch($pkg->{'extra_depends'}, $arch);
+        my $t = &filterarch($srcs->{$key}{'dep'} || $srcs->{$key}{'depends'}, $args->{'arch'});
+        my $tt = &filterarch($pkg->{'extra_depends'}, $args->{'arch'});
         $t = $t ? ($tt ? "$t, $tt" : $t) : $tt;
        print $SOURCES "Depends: $t\n" if $t;
         $t = $t ? ($tt ? "$t, $tt" : $t) : $tt;
        print $SOURCES "Depends: $t\n" if $t;
-        my $u = &filterarch($srcs->{$key}{'conf'} || $srcs->{$key}{'conflicts'}, $arch);
-        my $uu = &filterarch($pkg->{'extra_conflicts'}, $arch);
+        my $u = &filterarch($srcs->{$key}{'conf'} || $srcs->{$key}{'conflicts'}, $args->{'arch'});
+        my $uu = &filterarch($pkg->{'extra_conflicts'}, $args->{'arch'});
         $u = $u ? ($uu ? "$u, $uu" : $u) : $uu;
        print $SOURCES "Conflicts: $u\n" if $u;
        print $SOURCES "Architecture: all\n";
         $u = $u ? ($uu ? "$u, $uu" : $u) : $uu;
        print $SOURCES "Conflicts: $u\n" if $u;
        print $SOURCES "Architecture: all\n";
@@ -1741,6 +1758,7 @@ sub call_edos_depcheck {
     for my $key (keys %interesting_packages) {
         next if defined $interesting_packages_depwait{$key};
        my $pkg = $db->{$key};
     for my $key (keys %interesting_packages) {
         next if defined $interesting_packages_depwait{$key};
        my $pkg = $db->{$key};
+        # (defined $interesting_packages{$key}) => edos found an uninstallability
        my $change = 
            (defined $interesting_packages{$key} and $pkg->{'state'} eq 'Needs-Build') ||
            (not defined $interesting_packages{$key} and $pkg->{'state'} eq 'BD-Uninstallable');
        my $change = 
            (defined $interesting_packages{$key} and $pkg->{'state'} eq 'Needs-Build') ||
            (not defined $interesting_packages{$key} and $pkg->{'state'} eq 'BD-Uninstallable');
@@ -1773,12 +1791,13 @@ sub call_edos_depcheck {
             next;
         }
        my $pkg = $db->{$key};
             next;
         }
        my $pkg = $db->{$key};
-           if (defined $interesting_packages{$key}) {
-                   change_state( \$pkg, 'BD-Uninstallable' );
-                   $pkg->{'bd_problem'} = $interesting_packages{$key};
-           } else {
-                   change_state( \$pkg, 'Needs-Build' );
-           }
+        # The depwait could be cleared with the result still being uninstallable.
+        if (defined $interesting_packages{$key}) {
+           change_state( \$pkg, 'BD-Uninstallable' );
+           $pkg->{'bd_problem'} = $interesting_packages{$key};
+        } else {
+           change_state( \$pkg, 'Needs-Build' );
+        }
        log_ta( $pkg, "edos_depcheck: depwait" ) unless $simulate;
        update_source_info($pkg) unless $simulate;
        print "edos-builddebchange changed state of ${key}_$pkg->{'version'} ($args->{'arch'}) from dep-wait to $pkg->{'state'}\n" if $verbose || $simulate;
        log_ta( $pkg, "edos_depcheck: depwait" ) unless $simulate;
        update_source_info($pkg) unless $simulate;
        print "edos-builddebchange changed state of ${key}_$pkg->{'version'} ($args->{'arch'}) from dep-wait to $pkg->{'state'}\n" if $verbose || $simulate;
@@ -1792,7 +1811,10 @@ sub usage {
 Usage: $prgname <options...> <package_version...>
 Options:
     -v, --verbose: Verbose execution.
 Usage: $prgname <options...> <package_version...>
 Options:
     -v, --verbose: Verbose execution.
-    -A arch: Architecture this operation is for.
+    --simulate: Do not actually execute the action.
+        (Not yet implemented for all operations.  Check the source.)
+    -A arch: Architecture this operation is for.  (REQUIRED)
+    -d dist: Distribution/suite this operation is for. Defaults to unstable.
     --take: Take package for building [default operation]
     -f, --failed: Record in database that a build failed due to
         deficiencies in the package (that aren't fixable without a new
     --take: Take package for building [default operation]
     -f, --failed: Record in database that a build failed due to
         deficiencies in the package (that aren't fixable without a new
@@ -1812,10 +1834,20 @@ Options:
         BD-Uninstallable, until the installability of its Build-Dependencies
         were verified. This happens at each call of --merge-all, usually
         every 15 minutes.
         BD-Uninstallable, until the installability of its Build-Dependencies
         were verified. This happens at each call of --merge-all, usually
         every 15 minutes.
+    --build-priority=VALUE: Adjust the build priority of the currently
+        queued build.
+    --permanent-build-priority=VALUE: Adjust the permanent build
+        priority of a source package in a given distribution.
+    --extra-depends=BUILD-DEPENDS: Specify additional build-dependencies
+        used for the build.
+    --extra-conflicts=BUILD-DEPENDS: Specify additional build-conflicts
+        used for the build.
     -i SRC_PKG, --info SRC_PKG: Show information for source package
     -l STATE, --list=STATE: List all packages in state STATE; can be
         combined with -U to restrict to a specific user; STATE can
         also be 'all'
     -i SRC_PKG, --info SRC_PKG: Show information for source package
     -l STATE, --list=STATE: List all packages in state STATE; can be
         combined with -U to restrict to a specific user; STATE can
         also be 'all'
+    --min-age=VALUE, --max-age=VALUE: Filter the output of --list
+        by the age of the builds.
     -m MESSAGE, --message=MESSAGE: Give reason why package failed or
         source dependency list
         (used with -f, --dep-wait, and --binNMU)
     -m MESSAGE, --message=MESSAGE: Give reason why package failed or
         source dependency list
         (used with -f, --dep-wait, and --binNMU)
@@ -1827,13 +1859,16 @@ Options:
         automatically choosen
     --import FILE: Import database from a ASCII file FILE
     --export FILE: Export database to a ASCII file FILE
         automatically choosen
     --import FILE: Import database from a ASCII file FILE
     --export FILE: Export database to a ASCII file FILE
+    --format string, --own-format name: specify how the listing of packages
+        should look like. Please check the source for details. Own-Format
+        definitions are in ~/.wanna-build.yaml within the format section.
+
+There are more options not relevant for normal usage - please check source
+if you need them.
 
 The remaining arguments (depending on operation) usually start with
 "name_version", the trailer is ignored. This allows to pass the names
 of .dsc files, for which file name completion can be used.
 
 The remaining arguments (depending on operation) usually start with
 "name_version", the trailer is ignored. This allows to pass the names
 of .dsc files, for which file name completion can be used.
---merge-packages and --merge-quinn take Package/quin--diff file names
-on the command line or read stdin. --list needs nothing more on the
-command line. --info takes source package names (without version).
 EOF
        exit 1;
 }
 EOF
        exit 1;
 }
@@ -1951,13 +1986,18 @@ sub get_all_source_info {
 }
 
 sub show_distribution_architectures {
 }
 
 sub show_distribution_architectures {
+        my $args = shift;
        my $q = 'SELECT distribution, spacecat_all(architecture) AS architectures '.
                'FROM distribution_architectures '.
                'GROUP BY distribution';
        my $rows = $dbh->selectall_hashref($q, 'distribution');
        my $q = 'SELECT distribution, spacecat_all(architecture) AS architectures '.
                'FROM distribution_architectures '.
                'GROUP BY distribution';
        my $rows = $dbh->selectall_hashref($q, 'distribution');
-       foreach my $name (keys %$rows) {
+        if ($args->{suite}) {
+            print $rows->{$args->{'suite'}}->{'architectures'}."\n";
+        } else {
+           foreach my $name (keys %$rows) {
                print $name.': '.$rows->{$name}->{'architectures'}."\n";
                print $name.': '.$rows->{$name}->{'architectures'}."\n";
-       }
+           }
+        }
 }
 
 sub show_distribution_aliases {
 }
 
 sub show_distribution_aliases {
@@ -2074,8 +2114,8 @@ sub add_user_info {
 
 sub lock_table {
         return if $simulate;
 
 sub lock_table {
         return if $simulate;
-       $dbh->do('LOCK TABLE ' . table_name() .
-               ' IN EXCLUSIVE MODE', undef) or die $dbh->errstr;
+       $dbh->do('SELECT 1 FROM ' . table_name() .
+               ' WHERE distribution = ? FOR UPDATE', undef, $distribution) or die $dbh->errstr;
 }
 
 sub parse_argv {
 }
 
 sub parse_argv {