]> git.donarmstrong.com Git - wannabuild.git/blobdiff - bin/wanna-build
wanna-build: ignore partial package overwrite with arch:all
[wannabuild.git] / bin / wanna-build
index 3ce374f68da2ea271193796f271ec10a1e83f1d6..6845901f17ad360e79e793d4df690732b9a20cc7 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
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #
+use strict;
+use warnings;
+use 5.010;
+
+die "wanna-build disabled" if -f "/org/wanna-build/NO-WANNA-BUILD";
 
 package conf;
 
 package conf;
+
+use vars qw< $basedir $dbbase $transactlog $mailprog $buildd_domain >;
 # defaults
 $basedir ||= "/var/lib/debbuild";
 $dbbase ||= "build-db";
 # defaults
 $basedir ||= "/var/lib/debbuild";
 $dbbase ||= "build-db";
@@ -32,15 +39,13 @@ die "dbbase is empty\n" if ! $dbbase;
 die "transactlog is empty\n" if ! $transactlog;
 die "mailprog binary $conf::mailprog does not exist or isn't executable\n"
        if !-x $conf::mailprog;
 die "transactlog is empty\n" if ! $transactlog;
 die "mailprog binary $conf::mailprog does not exist or isn't executable\n"
        if !-x $conf::mailprog;
-die "no distributions defined\n" if ! %distributions;
 package main;
 
 package main;
 
-use strict;
 use POSIX;
 use FileHandle;
 use File::Copy;
 use DBI;
 use POSIX;
 use FileHandle;
 use File::Copy;
 use DBI;
-use lib '/org/wanna-build/bin';
+use Getopt::Long qw ( :config gnu_getopt );
 use lib '/org/wanna-build/lib';
 #use lib 'lib';
 use WannaBuild;
 use lib '/org/wanna-build/lib';
 #use lib 'lib';
 use WannaBuild;
@@ -50,23 +55,31 @@ use Hash::Merge qw ( merge );
 use String::Format;
 use Date::Parse;
 use List::Util qw[max];
 use String::Format;
 use Date::Parse;
 use List::Util qw[max];
-use Dpkg::Version qw(vercmp); # TODO: change this for running with squeeze dpkg
+use Dpkg::Version (); # import nothing
+if ( defined $Dpkg::Version::VERSION ) {
+    *vercmp = \&Dpkg::Version::version_compare;
+} else {
+    *vercmp = \&Dpkg::Version::vercmp;
+}
+
 use Dpkg::Deps; # TODO: same
 
 our ($verbose, $mail_logs, $list_order, $list_state,
     $curr_date, $op_mode, $user, $real_user, $distribution,
 use Dpkg::Deps; # TODO: same
 
 our ($verbose, $mail_logs, $list_order, $list_state,
     $curr_date, $op_mode, $user, $real_user, $distribution,
-    $fail_reason, $opt_override, $import_from, $export_to, $opt_create_db,
+    $fail_reason, $opt_override, $import_from, $export_to,
     %prioval, %sectval,
     $info_all_dists, $arch,
     %prioval, %sectval,
     $info_all_dists, $arch,
-    $category, %catval, %short_category,
-    $short_date, $list_min_age, $dbbase, @curr_time,
+    $short_date, $list_min_age, $list_max_age, $dbbase, @curr_time,
     $build_priority, %new_vers, $binNMUver, %merge_srcvers, %merge_binsrc,
     $build_priority, %new_vers, $binNMUver, %merge_srcvers, %merge_binsrc,
-    $printformat, $ownprintformat, $privmode, $extra_depends, $extra_conflicts
+    $printformat, $ownprintformat, $privmode, $extra_depends, $extra_conflicts,
+    %distributions, %distribution_aliases, $actions,
+    $sshwrapper,
     );
 our $Pas = '/org/buildd.debian.org/etc/packages-arch-specific/Packages-arch-specific';
 our $simulate = 0;
 our $simulate_edos = 0;
 our $api = undef; # allow buildds to specify an different api
     );
 our $Pas = '/org/buildd.debian.org/etc/packages-arch-specific/Packages-arch-specific';
 our $simulate = 0;
 our $simulate_edos = 0;
 our $api = undef; # allow buildds to specify an different api
+our $recorduser = undef;
 
 # global vars
 $ENV{'PATH'} = "/bin:/usr/bin:/usr/local/bin:/org/wanna-build/bin/";
 
 # global vars
 $ENV{'PATH'} = "/bin:/usr/bin:/usr/local/bin:/org/wanna-build/bin/";
@@ -78,228 +91,197 @@ $curr_date = strftime("%Y %b %d %H:%M:%S",@curr_time);
 $short_date = strftime("%m/%d/%y",@curr_time);
 $| = 1;
 
 $short_date = strftime("%m/%d/%y",@curr_time);
 $| = 1;
 
-# map program invocation names to operation modes
-my %prognames = ( "uploaded-build"  => "set-uploaded",
-                                 "failed-build"    => "set-failed",
-                                 "no-build"            => "set-not-for-us",
-                                 "give-back-build" => "set-needs-build",
-                                 "dep-wait-build"  => "set-dep-wait",
-                                 "forget-build"        => "forget",
-                                 "build-info"          => "info" );
-
-%short_category = ( u => "uploaded-fixed-pkg",
-                                   f => "fix-expected",
-                                       r => "reminder-sent",
-                                       n => "nmu-offered",
-                                       e => "easy",
-                                       m => "medium",
-                                       h => "hard",
-                                       c => "compiler-error",
-                                       "" => "none" );
-
-my $progname;
-($progname = $0) =~ s,.*/,,;
-if ($prognames{$progname}) {
-       $op_mode = $prognames{$progname};
-}
-elsif ($progname =~ /^list-(.*)$/) {
-       $op_mode = "list";
-       $list_state = ($1 eq "all") ? "" : $1;
-}
-
-my %options =
-       (# flags
-        simulate       => { flag => \$simulate }, # this is not supported by all operations (yet)!
-        "simulate-edos"  => { flag => \$simulate_edos },
-        "simulate-all" => { code => sub { $simulate = 1; $simulate_edos = 1; } },
-        api            => { arg => \$api, code => sub {
-                            # official apis are numeric
-                            die "$api isn't numeric" unless int($api) eq $api;
-                            die "$api too large" unless $api <= 1;
-                            } },
-        verbose        => { short => "v", flag => \$verbose },
-        override               => { short => "o", flag => \$opt_override },
-        "create-db"    => { flag => \$opt_create_db },
-        "correct-compare" => { flag => \$WannaBuild::opt_correct_version_cmp },
-        # TODO: remove after buildds no longer pass to wanna-build
-        "no-propagation" => { short => "N" },
-        "no-down-propagation" => { short => "D" },
-        # normal actions
-        take                   => { mode => "set-building" },
-        failed                 => { short => "f", mode => "set-failed" },
-        uploaded               => { short => "u", mode => "set-uploaded" },
-        "no-build"             => { short => "n", mode => "set-not-for-us" },
-        built                  => { mode => "set-built" },
-        attempted              => { mode => "set-attempted" },
-        "give-back"            => { mode => "set-needs-build" },
-        "dep-wait"             => { mode => "set-dep-wait" },
-        forget                 => { mode => "forget" },
-        'forget-user' => { mode => 'forget-user' },
-        update                 => { mode => "set-update" },
-        #"merge-quinn"  => { mode => "merge-quinn" },
-        #"merge-partial-quinn" => { mode => "merge-partial-quinn" },
-        #"merge-packages" => { mode => "merge-packages" },
-        #"merge-sources" => { mode => "merge-sources" },
-        "pretend-avail" => { short => "p", mode => "pretend-avail" },
-        #"merge-all"     => { mode => "merge-all" },
-        #"merge-all-secondary" => { mode => "merge-all-secondary" },
-        "merge-v3"      => { mode => "merge-v3" },
-        info                   => { short => "i", mode => "info" },
-        'binNMU' => { mode => 'set-binary-nmu', arg => \$binNMUver, 
-                            code => sub { die "Invalid binNMU version: $binNMUver\n"
-                               if $binNMUver !~ /^([\d]*)$/ and $1 >= 0; } },
-        'perm-build-priority'    => { mode => "set-permanent-build-priority", arg => \$build_priority,
-                             code => sub { die "Invalid build priority: $build_priority\n"
-                               if $build_priority !~ /^-?[\d]+$/; } },
-        'build-priority'    => { mode => "set-build-priority", arg => \$build_priority,
-                             code => sub { die "Invalid build priority: $build_priority\n"
-                               if $build_priority !~ /^-?[\d]+$/; } },
-        list                   =>
-        { short => "l", mode => "list", arg => \$list_state,
-          code => sub {
-                  die "Unknown state to list: $list_state\n"
-                          if !isin( $list_state, qw(needs-build building uploaded
-                                                built build-attempted failed installed dep-wait
-                                                not-for-us all failed-removed
-                                                install-wait reupload-wait bd-uninstallable));} },
-        # options with args
-        dist           =>
-        { short => "d", arg => \$distribution,
-          code => sub {
-                  if ($distribution eq "a" || $distribution eq "all") {
-                          $info_all_dists = 1;
-                          $distribution = "";
-                  }
-                  else {
-                          $distribution = "oldstable"   if $distribution eq "o";
-                          $distribution = "stable"   if $distribution eq "s";
-                          $distribution = "testing"  if $distribution eq "t";
-                          $distribution = "unstable" if $distribution eq "u";
-                  }
-          } },
-        order          =>
-        { short => "O", arg => \$list_order,
-          code => sub {
-                  die "Bad ordering character\n"
-                          if $list_order !~ /^[PSpsncbCW]+$/;
-          } },
-        message        => { short => "m", arg => \$fail_reason },
-        # database is deprecated, use arch instead.
-        database       => { short => "b", arg => \$conf::dbbase },
-        arch           => { short => "A", arg => \$arch },
-        user           => { short => "U", arg => \$user },
-        category               => { short => "c", arg => \$category,
-                                                code => sub {
-                                                        $category = $short_category{$category}
-                                                                if exists $short_category{$category};
-                                                        die "Unknown category: $category\n"
-                                                                if !isin( $category, values %short_category );
-                                                } },
-        "min-age"      => { short => "a", arg => \$list_min_age,
-                                                code => sub {
-                                                        die "Argument of --min-age must be a non-zero number\n"
-                                                                if $list_min_age == 0;
-                                                } },
-        "max-age"      => { arg => \$list_min_age,
-                                                code => sub {
-                                                        die "Argument of --max-age must be a non-zero number\n"
-                                                                if $list_min_age == 0;
-                                                        $list_min_age *= -1;
-                                                } },
-         "format"       => { arg => \$printformat },
-         "own-format"       => { arg => \$ownprintformat },
-         "Pas"          => { arg => \$Pas },
-        "extra-depends"=> { arg => \$extra_depends },
-        "extra-conflicts"=> { arg => \$extra_conflicts },
-        # special actions
-        export         => { arg => \$export_to, mode => "export" },
-        import         => { arg => \$import_from, mode => "import" },
-        "manual-edit"  => { mode => "manual-edit" },
-        );
-
-while( @ARGV && $ARGV[0] =~ /^-/ ) {
-       $_ = shift @ARGV;
-       last if $_ eq "--";
-       my($opt, $optname, $arg);
-       if (/^--([^=]+)(=|$)/) {
-               $optname = $1;
-               $opt = $options{$optname};
-               $arg = $1 if /^--\Q$optname\E=((.|\n)*)$/;
-       }
-       else {
-               $optname = substr( $_, 1, 1 );
-               $opt = (grep { defined($_->{short}) ? $_->{short} eq $optname : 0} values %options)[0];
-               $arg = $1 if /^-$optname(.+)$/;
-       }
-       if (!$opt) {
-               warn "Unknown option: --$1\n";
-               usage();
-       }
-       if ($opt->{arg}) {
-               if (!defined $arg) {
-                       die "$optname option missing argument\n" if !@ARGV;
-                       $arg = shift @ARGV;
-               }
-               ${$opt->{arg}} = $arg;
-       }
-       elsif (defined $arg) {
-               die "Option $optname takes no argument\n";
-       }
-       
-       if ($opt->{mode}) {
-               die "Conflicting operation modes\n" if $op_mode;
-               $op_mode = $opt->{mode};
-       }
-       if ($opt->{flag}) {
-               ${$opt->{flag}}++;
-       }
-       if ($opt->{code}) {
-               &{$opt->{code}};
+# set mode of operation based on command line switch. Should be used
+# by GetOptions below.
+sub _set_mode_set { $op_mode = "set-$_[0]" }
+sub _set_mode { $op_mode = "$_[0]" }
+
+sub _option_deprecated { warn "Option $_[0] is deprecated" }
+
+my @wannabuildoptions = (
+    # this is not supported by all operations (yet)!
+    'simulate'      => \$simulate,
+    'simulate-edos' => \$simulate_edos,
+    'simulate-all'  => sub { $simulate = 1; $simulate_edos = 1; },
+    'api=i'         => sub {
+        $api = $_[1];
+        die "$api too large" unless $api <= 1;
+    },
+    'verbose|v'       => \$verbose,
+    'override|o'      => \$opt_override,
+    'correct-compare' => \$WannaBuild::opt_correct_version_cmp,
+
+    # TODO: remove after buildds no longer pass to wanna-build
+    'no-propagation|N'      => \&_option_deprecated,
+    'no-down-propagation|D' => \&_option_deprecated,
+
+    # normal actions
+    'building|take'         => \&_set_mode_set,
+    'failed|f'              => \&_set_mode_set,
+    'uploaded|u'            => \&_set_mode_set,
+    'not-for-us|no-build|n' => \&_set_mode_set,
+    'built'                 => \&_set_mode_set,
+    'attempted'             => \&_set_mode_set,
+    'needs-build|give-back' => \&_set_mode_set,
+    'dep-wait'              => \&_set_mode_set,
+    'update'                => \&_set_mode_set,
+    'forget'                => \&_set_mode,
+    'forget-user'           => \&_set_mode,
+    'merge-v3'              => \&_set_mode,
+    'info|i'                => \&_set_mode,
+    'binary-nmu|binNMU=i'   => sub {
+        _set_mode_set(@_);
+        $binNMUver = $_[1];
+    },
+    'permanent-build-priority|perm-build-priority=i' => sub {
+        _set_mode_set(@_);
+        $build_priority = $_[1];
+    },
+    'build-priority=i' => sub {
+        _set_mode_set(@_);
+        $build_priority = $_[1];
+    },
+    'list|l=s' => sub {
+        _set_mode(@_);
+        $list_state = $_[1];
+        die "Unknown state to list: $list_state\n"
+          if not $list_state ~~ [
+              qw( needs-build building uploaded built
+                  build-attempted failed installed
+                  dep-wait not-for-us auto-not-for-us
+                  all failed-removed install-wait
+                  reupload-wait bd-uninstallable ) ];
+    },
+    'dist|d=s' => sub {
+        $distribution = $_[1];
+        given ( $_[1] ) {
+            when ( [qw< a all >] ) {
+                $info_all_dists = 1;
+                $distribution   = '';
+            }
+            when ('o') { $distribution = 'oldstable'; }
+            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 {
+        $list_order = $_[1];
+        die "Bad ordering character\n"
+          if $list_order !~ /^[PSpsncbCWT]+$/;
+    },
+    '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";
+        $_[1] =~ m#^([^/]+)#;
+        $arch ||= $1;
+    },
+    'arch|A=s'     => \$arch,
+    'user|U=s'     => \$user,
+    'min-age|a=i'       => \$list_min_age,
+    'max-age=i'         => sub { $list_min_age = -1 * ($_[1]); },
+    'format=s'          => \$printformat,
+    'own-format=s'      => \$ownprintformat,
+    'Pas=s'             => \$Pas,
+    'extra-depends=s'   => \$extra_depends,
+    'extra-conflicts=s' => \$extra_conflicts,
+
+    # special actions
+    'export=s' => sub { _set_mode(@_); $export_to   = $_[1]; },
+    'import=s' => sub { _set_mode(@_); $import_from = $_[1]; },
+    'manual-edit'                => \&_set_mode,
+    'distribution-architectures' => \&_set_mode,
+    'distribution-aliases'       => \&_set_mode,
+
+    'ssh-wrapper'       => \$sshwrapper,
+    'recorduser'        => \$recorduser,
+    );
+
+GetOptions(@wannabuildoptions) or usage();
+
+my $dbh;
+
+END {
+       if (defined $dbh)
+       {
+               $dbh->disconnect or warn $dbh->errstr;
        }
 }
 
        }
 }
 
-$op_mode = $category ? "set-failed" : "set-building"
-       if !$op_mode; # default operation
-$distribution ||= "unstable";
-if ($distribution eq 'any-priv') {
-    $privmode = 'yes';
-    $distribution = 'any';
+my $schema_suffix = '';
+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';
+}
+else
+{
+       $dbh = DBI->connect("DBI:Pg:service=wanna-build-privileged") || 
+               die "FATAL: Cannot open database: $DBI::errstr\n";
+}
+
+# TODO: This shouldn't be needed, file a bug.
+$dbh->{pg_server_prepare} = 0;
+
+$dbh->begin_work or die $dbh->errstr;
+
+my $q = 'SELECT distribution, public, auto_dep_wait, build_dep_resolver, suppress_successful_logs, archive FROM distributions';
+my $rows = $dbh->selectall_hashref($q, 'distribution');
+foreach my $name (keys %$rows) {
+       $distributions{$name} = {};
+       $distributions{$name}->{'noadw'} = 1 if !($rows->{$name}->{'auto_dep_wait'});
+       $distributions{$name}->{'hidden'} = 1 if !($rows->{$name}->{'public'});
+       $distributions{$name}->{'build_dep_resolver'} = $rows->{$name}->{'build_dep_resolver'} if $rows->{$name}->{'build_dep_resolver'};
+       $distributions{$name}->{'suppress_successful_logs'} = $rows->{$name}->{'suppress_successful_logs'} if $rows->{$name}->{'suppress_successful_logs'};
+       $distributions{$name}->{'archive'} = $rows->{$name}->{'archive'} if $rows->{$name}->{'archive'};
 }
 }
-if ($distribution eq 'any-unpriv') {
-    $privmode = 'no';
-    $distribution = 'any';
+
+$q = 'SELECT alias, distribution FROM distribution_aliases';
+$rows = $dbh->selectall_hashref($q, 'alias');
+foreach my $name (keys %$rows) {
+       $distribution_aliases{$name} = $rows->{$name}->{'distribution'};
 }
 }
-undef $distribution if $distribution eq 'any';
+$distribution = $distribution_aliases{$distribution} if (isin($distribution, keys %distribution_aliases));
+
+$op_mode ||= "set-building";
 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 %conf::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
                                  merge-packages manual-edit
 }
 
 if (!@ARGV && !isin( $op_mode, qw(list merge-quinn merge-partial-quinn import export
                                  merge-packages manual-edit
-                                 merge-sources))) {
+                                 merge-sources distribution-architectures
+                                 distribution-aliases))) {
        warn "No packages given.\n";
        usage();
 }
        warn "No packages given.\n";
        usage();
 }
@@ -310,7 +292,7 @@ die "Can't determine your user name\n"
           !($user = $real_user);
 
 if (!$fail_reason) {
           !($user = $real_user);
 
 if (!$fail_reason) {
-       if ($op_mode eq "set-failed" && !$category) {
+       if ($op_mode eq "set-failed" ) {
                print "Enter reason for failing (end with '.' alone on ".
                      "its line):\n";
                my $line;
                print "Enter reason for failing (end with '.' alone on ".
                      "its line):\n";
                my $line;
@@ -343,7 +325,7 @@ my $yamlmap = ();
 my $yamldir = "/org/wanna-build/etc/yaml";
 my @files = ('wanna-build.yaml');
 if ((getpwuid($>))[7]) { push (@files, ((getpwuid($>))[7])."/.wanna-build.yaml"); }
 my $yamldir = "/org/wanna-build/etc/yaml";
 my @files = ('wanna-build.yaml');
 if ((getpwuid($>))[7]) { push (@files, ((getpwuid($>))[7])."/.wanna-build.yaml"); }
-if ($user =~ /(buildd.*)-/) { push (@files, "$1.yaml") };
+if ($user && $user =~ /(buildd.*)-/) { push (@files, "$1.yaml") };
 if ($user) { push ( @files, "$user.yaml"); }
 foreach my $file (@files) {
         my $cfile = File::Spec->rel2abs( $file, $yamldir );
 if ($user) { push ( @files, "$user.yaml"); }
 foreach my $file (@files) {
         my $cfile = File::Spec->rel2abs( $file, $yamldir );
@@ -361,48 +343,20 @@ $list_order ||= $yamlmap->{"list-order"}{'default'};
 $api //= $yamlmap->{"api"};
 $api //= 0;
 
 $api //= $yamlmap->{"api"};
 $api //= 0;
 
-my $dbh;
-
-END {
-       if (defined $dbh)
-       {
-               $dbh->disconnect or warn $dbh->errstr;
-       }
+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";
 }
 }
-
-my $schema_suffix = '';
-if (isin( $op_mode, qw(list info)) && $distribution !~ /security/ && !(not -t and $user =~ /buildd-/) && !($privmode eq 'yes')) {
-       $dbh = DBI->connect("DBI:Pg:service=wanna-build") || 
-               die "FATAL: Cannot open database: $DBI::errstr\n";
-       $schema_suffix = '_public';
-}
-else
-{
-       $dbh = DBI->connect("DBI:Pg:service=wanna-build-privileged") || 
-               die "FATAL: Cannot open database: $DBI::errstr\n";
-}
-
-# TODO: This shouldn't be needed, file a bug.
-$dbh->{pg_server_prepare} = 0;
-
-$dbh->begin_work or die $dbh->errstr;
-
-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<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 {
@@ -418,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;
                };
@@ -428,95 +379,22 @@ sub process {
                        forget_packages( @ARGV );
                        last SWITCH;
                };
                        forget_packages( @ARGV );
                        last SWITCH;
                };
-               /^merge-partial-quinn/ && do {
-                       die "This operation is restricted to admin users\n"
-                               if (defined @conf::admin_users and
-                                   !isin( $real_user, @conf::admin_users));
-                       lock_table();
-                       parse_quinn_diff(1);
-                       last SWITCH;
-               };
-               /^merge-quinn/ && do {
-                       die "This operation is restricted to admin users\n"
-                               if (defined @conf::admin_users and
-                                   !isin( $real_user, @conf::admin_users));
-                       lock_table();
-                       parse_quinn_diff(0);
-                       last SWITCH;
-               };
-               /^merge-packages/ && do {
-                       die "This operation is restricted to admin users\n"
-                               if (defined @conf::admin_users and
-                                   !isin( $real_user, @conf::admin_users));
-                       lock_table();
-                       parse_packages(0);
-                       last SWITCH;
-               };
-               /^merge-sources/ && do {
-                       die "This operation is restricted to admin users\n"
-                               if (defined @conf::admin_users and
-                                   !isin( $real_user, @conf::admin_users));
-                       lock_table();
-                       parse_sources(0);
-                       last SWITCH;
-               };
-               /^pretend-avail/ && do {
-                       pretend_avail( @ARGV );
-                       last SWITCH;
-               };
-               /^merge-all$/ && do {
-                       die "This operation is restricted to admin users\n"
-                               if (defined @conf::admin_users and
-                                   !isin( $real_user, @conf::admin_users));
-                       lock_table();
-                       my @ARGS = @ARGV;
-                       @ARGV = ( $ARGS[0] );
-                       my $pkgs = parse_packages(0);
-                       @ARGV = ( $ARGS[1] );
-                       parse_quinn_diff(0);
-                       @ARGV = ( $ARGS[2] );
-                       my $srcs = parse_sources(1);
-                       call_edos_depcheck( {'arch' => $arch, 'pkgs' => ($ARGS[0]), 'srcs' => $srcs });
-                       last SWITCH;
-               };
-               /^merge-all-secondary/ && do {
-                       die "This operation is restricted to admin users\n"
-                               if (defined @conf::admin_users and
-                                   !isin( $real_user, @conf::admin_users));
-                       # This is in case the chroot has multiple unrelated
-                       # dist, for instance unstable and experimental.
-                       # This is not for stable and proposed-updates.
-                       # The second packages file contains a combination
-                       # of all Packages files known to the buildd, the
-                       # first only for the current dist.
-                       lock_table();
-                       my @ARGS = @ARGV;
-                       @ARGV = ( $ARGS[0] );
-                       my $pkgs = parse_packages(0);
-                       @ARGV = ( $ARGS[3] );
-                       my $pkgs = parse_packages(1);
-                       @ARGV = ( $ARGS[1] );
-                       parse_quinn_diff(0);
-                       @ARGV = ( $ARGS[2] );
-                       my $srcs = parse_sources(1);
-                       call_edos_depcheck( {'arch' => $arch, 'pkgs' => ($ARGS[3]), 'srcs' => $srcs });
-                       last SWITCH;
-               };
                /^merge-v3/ && do {
                /^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};
@@ -526,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 );
@@ -546,10 +421,18 @@ sub process {
                        export_db( $export_to );
                        last SWITCH;
                };
                        export_db( $export_to );
                        last SWITCH;
                };
+               /^distribution-architectures/ && do {
+                       show_distribution_architectures({'suite' => $suite});
+                       last SWITCH;
+               };
+               /^distribution-aliases/ && do {
+                       show_distribution_aliases();
+                       last SWITCH;
+               };
 
                die "Unexpected operation mode $op_mode\n";
        }
 
                die "Unexpected operation mode $op_mode\n";
        }
-       if (not -t and $user =~ /buildd-/) {
+       if ($recorduser) {
                my $userinfo = get_user_info($user);
                if (!defined $userinfo)
                {
                my $userinfo = get_user_info($user);
                if (!defined $userinfo)
                {
@@ -560,62 +443,166 @@ 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" );
 }
 
 }
 
-sub add_packages {
-       my $newstate = shift;
-       my( $package, $name, $version, $ok, $reason );
-       
-       foreach $package (@_) {
-               $package =~ s,^.*/,,; # strip path
-               $package =~ s/\.(dsc|diff\.gz|tar\.gz|deb)$//; # strip extension
-               $package =~ s/_[a-zA-Z\d-]+\.changes$//; # strip extension
-               if ($package =~ /^([\w\d.+-]+)_([\w\d:.+~-]+)/) {
-                       ($name,$version) = ($1,$2);
-               }
-               else {
-                       warn "$package: can't extract package name and version ".
-                                "(bad format)\n";
-                       next;
-               }
+exit 0;
 
 
-               if ($op_mode eq "set-building") {
-                       add_one_building( $name, $version );
-               }
-               elsif ($op_mode eq "set-built") {
-                       add_one_built( $name, $version );
-               }
-               elsif ($op_mode eq "set-attempted") {
-                       add_one_attempted( $name, $version );
-               }
-               elsif ($op_mode eq "set-uploaded") {
-                       add_one_uploaded( $name, $version );
-               }
-               elsif ($op_mode eq "set-failed") {
-                       add_one_failed( $name, $version );
-               }
-               elsif ($op_mode eq "set-not-for-us") {
-                       add_one_notforus( $name, $version );
-               }
-               elsif ($op_mode eq "set-needs-build") {
-                       add_one_needsbuild( $name, $version );
-               }
-               elsif ($op_mode eq "set-dep-wait") {
-                       add_one_depwait( $name, $version );
-               }
-               elsif ($op_mode eq "set-build-priority") {
-                       set_one_buildpri( $name, $version, 'buildpri' );
-               }
-               elsif ($op_mode eq "set-permanent-build-priority") {
-                       set_one_buildpri( $name, $version, 'permbuildpri' );
-               }
-               elsif ($op_mode eq "set-binary-nmu") {
-                       set_one_binnmu( $name, $version );
-               }
-               elsif ($op_mode eq "set-update") {
-                       set_one_update( $name, $version );
-               }
+
+BEGIN {
+    $actions = {
+        'set-building'  => { 'noversion' => 1, 'nopkgdef' => 1, },
+        'set-built'     => { 'builder' => 1, to => 'Built', action => 'built', 'from' => [qw<Building Build-Attempted>]},
+        'set-attempted' => { 'builder' => 1, to => 'Build-Attempted', action => 'attempted', 'from' => [qw<Building Build-Attempted>]},
+        'set-uploaded'  => { 'builder' => 1, to => 'Uploaded', action => 'uploaded', 'from' => [qw<Building Built Build-Attempted>], binversion => 1, },
+        'set-failed'    => { 'builder' => 1, to => 'Failed', action => 'failed', from => [qw<Building Built Build-Attempted Dep-Wait Failed>], warnfrom => [qw<Needs-Build Uploaded Dep-Wait BD-Uninstallable>], },
+        'set-dep-wait'  => { 'builder' => 1, warnfrom => [qw<Needs-Build Failed BD-Uninstallable>], },
+        'set-update'    => { 'noversion' => 1, },
+        'set-needs-build' => { builder => 1, to => 'BD-Uninstallable', action => 'give-back'},
+    };
+}
+
+sub add_packages {
+    my $newstate = shift;
+    my( $package, $name, $version, $ok, $reason );
+
+    foreach $package (@_) {
+        $package =~ s,^.*/,,; # strip path
+        $package =~ s/\.(dsc|diff\.gz|tar\.gz|deb)$//; # strip extension
+        $package =~ s/_[a-zA-Z\d-]+\.changes$//; # strip extension
+        if ($package =~ /^([\w\d.+-]+)_([\w\d:.+~-]+)/) {
+            ($name,$version) = ($1,$2);
+        } else {
+           warn "$package: can't extract package name and version (bad format)\n";
+           next;
        }
        }
+
+       my $pkg = get_source_info($name);
+        if (!($actions->{$op_mode}) || !($actions->{$op_mode}->{'nopkgdef'})) {
+            if (!defined($pkg)) {
+                print "$name: not registered yet.\n";
+                next;
+            }
+        }
+        if ($actions->{$op_mode} && $actions->{$op_mode}->{'builder'}) {
+            if (($pkg->{'builder'} && $user ne $pkg->{'builder'}) &&
+               !($pkg->{'builder'} =~ /^(\w+)-\w+/ && $1 eq $user) &&
+               !$opt_override) {
+                print "$pkg->{'package'}: not taken by you, but by $pkg->{'builder'}. Skipping.\n";
+                next;
+            }
+        }
+        if (!($actions->{$op_mode}) || !($actions->{$op_mode}->{'noversion'})) {
+            my $nmuver = binNMU_version($pkg->{version}, $pkg->{'binary_nmu_version'});
+            if ((!pkg_version_eq($pkg,$version) || $actions->{$op_mode}->{'binversion'}) && !version_eq( $nmuver, $version )) {
+                print "$pkg->{package}: version mismatch ($nmuver";
+                print " by $pkg->{'builder'}" if $pkg->{'builder'};
+                print ")\n";
+                next;
+            }
+        }
+
+        if ($actions->{$op_mode} && $actions->{$op_mode}->{'from'}) {
+            if (!isin($pkg->{'state'}, @{$actions->{$op_mode}->{'from'}}, @{$actions->{$op_mode}->{'warnfrom'}})) {
+                print "$name: skiping: state is $pkg->{'state'}, not in ".join(", ",@{$actions->{$op_mode}->{'from'}}, @{$actions->{$op_mode}->{'warnfrom'}})."\n";
+                next;
+            }
+        }
+        if ($actions->{$op_mode} && $actions->{$op_mode}->{'warnfrom'}) {
+            if (isin($pkg->{'state'}, @{$actions->{$op_mode}->{'warnfrom'}})) {
+                print "$name: warning: state is $pkg->{'state'}, processing anyways.\n";
+            }
+        }
+
+        if ($op_mode eq "set-building") {
+            add_one_building( $name, $version, $pkg );
+        }
+        elsif ($op_mode eq "set-failed") {
+           print "$pkg->{'package'}: already registered as failed; will append new message\n" if $pkg->{'state'} eq "Failed";
+           $pkg->{'builder'} = $user;
+           $pkg->{'failed'} .= "\n" if $pkg->{'failed'};
+           $pkg->{'failed'} .= $fail_reason;
+        }
+        elsif ($op_mode eq "set-not-for-us") {
+            add_one_notforus( $pkg );
+        }
+        elsif ($op_mode eq "set-needs-build") {
+           my $state = $pkg->{'state'};
+
+           if ($state eq "BD-Uninstallable") {
+               if ($opt_override) {
+                       print "$name: Forcing uninstallability mark to be removed. This is not permanent and might be reset with the next trigger run\n";
+
+                       change_state( \$pkg, 'Needs-Build' );
+                       delete $pkg->{'builder'};
+                       delete $pkg->{'depends'};
+                       log_ta( $pkg, "--give-back" );
+                       update_source_info($pkg);
+                       print "$name: given back\n" if $verbose;
+                       next;
+               }
+               else {
+                       print "$name: has uninstallable build-dependencies. Skipping\n  (use --override to clear dependency list and give back anyway)\n";
+                       next;
+               }
+            }
+            elsif ($state eq "Dep-Wait") {
+               if ($opt_override) {
+                       print "$name: Forcing source dependency list to be cleared\n";
+               }
+               else {
+                       print "$name: waiting for source dependencies. Skipping\n  (use --override to clear dependency list and give back anyway)\n";
+                       next;
+               }
+            }
+            elsif (!isin( $state, qw(Building Built Build-Attempted))) {
+               print "$name: not taken for building (state is $state).";
+               if ($opt_override) {
+                       print "\n$name: Forcing give-back\n";
+               }
+               else {
+                       print " Skipping.\n";
+                       next;
+               }
+            }
+            $pkg->{'builder'} = undef;
+            $pkg->{'depends'} = undef;
+        }
+        elsif ($op_mode eq "set-dep-wait") {
+            add_one_depwait( $pkg );
+        }
+        elsif ($op_mode eq "set-build-priority") {
+            set_one_buildpri( 'buildpri', $pkg );
+        }
+        elsif ($op_mode eq "set-permanent-build-priority") {
+            set_one_buildpri( 'permbuildpri', $pkg );
+        }
+        elsif ($op_mode eq "set-binary-nmu") {
+            set_one_binnmu( $name, $version, $pkg );
+        }
+        elsif ($op_mode eq "set-update") {
+            $pkg->{'version'} =~ s/\+b[0-9]+$//;
+
+           log_ta( $pkg, "--update" );
+           update_source_info($pkg);
+        }
+
+        if ($actions->{$op_mode} && $actions->{$op_mode}->{'action'} && $actions->{$op_mode}->{'to'}) {
+           change_state( \$pkg, $actions->{$op_mode}->{'to'} );
+           log_ta( $pkg, "--".$actions->{$op_mode}->{'action'} );
+           update_source_info($pkg);
+           print "$name: registered as ".$actions->{$op_mode}->{'action'}."\n" if $verbose;
+        }
+    }
 }
 
 sub add_one_building {
 }
 
 sub add_one_building {
@@ -624,19 +611,16 @@ sub add_one_building {
        my( $ok, $reason );
 
        $ok = 1;
        my( $ok, $reason );
 
        $ok = 1;
-       my $pkg = get_source_info($name);
+       my $pkg = shift;
        if (defined($pkg)) {
        if (defined($pkg)) {
-               if ($pkg->{'state'} eq "Not-For-Us") {
-                       $ok = 0;
-                       $reason = "not suitable for this architecture";
-               }
-               elsif ($pkg->{'state'} =~ /^Dep-Wait/) {
+            my $pkgnack = {
+                'Not-For-Us' => 'not suitable for this architecture',
+                'Dep-Wait' => 'not all source dependencies available yet',
+                'BD-Uninstallable' => 'source dependencies are not installable',
+            };
+               if ($pkgnack->{$pkg->{'state'}}) {
                        $ok = 0;
                        $ok = 0;
-                       $reason = "not all source dependencies available yet";
-               }
-               elsif ($pkg->{'state'} =~ /^BD-Uninstallable/) {
-                       $ok = 0;
-                       $reason = "source dependencies are not installable";
+                       $reason = $pkgnack->{$pkg->{'state'}};
                }
                elsif ($pkg->{'state'} eq "Uploaded" &&
                           (version_lesseq($version, $pkg->{'version'}))) {
                }
                elsif ($pkg->{'state'} eq "Uploaded" &&
                           (version_lesseq($version, $pkg->{'version'}))) {
@@ -757,6 +741,10 @@ sub add_one_building {
                 print  "    - extra-changelog: $pkg->{'binary_nmu_changelog'}\n" if $pkg->{'binary_nmu_changelog'} && $pkg->{'binary_nmu_version'};
                 print  "    - extra-depends: $pkg->{'extra_depends'}\n" if $pkg->{'extra_depends'};
                 print  "    - extra-conflicts: $pkg->{'extra_conflicts'}\n" if $pkg->{'extra_conflicts'};
                 print  "    - extra-changelog: $pkg->{'binary_nmu_changelog'}\n" if $pkg->{'binary_nmu_changelog'} && $pkg->{'binary_nmu_version'};
                 print  "    - extra-depends: $pkg->{'extra_depends'}\n" if $pkg->{'extra_depends'};
                 print  "    - extra-conflicts: $pkg->{'extra_conflicts'}\n" if $pkg->{'extra_conflicts'};
+                print  "    - archive: $distributions{$distribution}->{'archive'}\n" if $distributions{$distribution}->{'archive'};
+                print  "    - build_dep_resolver: $distributions{$distribution}->{'build_dep_resolver'}\n" if $distributions{$distribution}->{'build_dep_resolver'};
+                print  "    - arch_all: $pkg->{'build_arch_all'}\n" if $pkg->{'build_arch_all'};
+                print  "    - suppress_successful_logs: $distributions{$distribution}->{'suppress_successful_logs'}\n" if $distributions{$distribution}->{'suppress_successful_logs'};
             }
                change_state( \$pkg, 'Building' );
                $pkg->{'package'} = $name;
             }
                change_state( \$pkg, 'Building' );
                $pkg->{'package'} = $name;
@@ -767,222 +755,18 @@ sub add_one_building {
        }
        else {
             if ($api < 1) {
        }
        else {
             if ($api < 1) {
-               print "$name: NOT OK!\n  $reason\n";
-            } else {
-               print "- $name:\n    - status: not ok\n    - reason: \"$reason\"\n";
-            }
-       }
-}
-
-sub add_one_attempted {
-       my $name = shift;
-       my $version = shift;
-       my $pkg = get_source_info($name);
-
-       if (!defined($pkg)) {
-               print "$name: not registered yet.\n";
-               return;
-       }
-
-       if (($pkg->{'state'} ne "Building") && ($pkg->{'state'} ne "Build-Attempted")) {
-               print "$name: not taken for building (state is $pkg->{'state'}). ",
-                         "Skipping.\n";
-               return;
-       }
-       if ($pkg->{'builder'} ne $user) {
-               print "$name: not taken by you, but by $pkg->{'builder'}. Skipping.\n";
-               return;
-       }
-       elsif ( !pkg_version_eq($pkg, $version) ) {
-               print "$name: version mismatch ".
-                         "$(pkg->{'version'} ".
-                         "by $pkg->{'builder'})\n";
-               return;
-       }
-
-       change_state( \$pkg, 'Build-Attempted' );
-       log_ta( $pkg, "--attempted" );
-       update_source_info($pkg);
-       print "$name: registered as uploaded\n" if $verbose;
-}
-
-sub add_one_built {
-       my $name = shift;
-       my $version = shift;
-       my $pkg = get_source_info($name);
-
-       if (!defined($pkg)) {
-               print "$name: not registered yet.\n";
-               return;
-       }
-
-        if (($pkg->{'state'} ne "Building") && ($pkg->{'state'} ne "Build-Attempted")) {
-               print "$name: not taken for building (state is $pkg->{'state'}). ",
-                         "Skipping.\n";
-               return;
-       }
-       if ($pkg->{'builder'} ne $user) {
-               print "$name: not taken by you, but by $pkg->{'builder'}. Skipping.\n";
-               return;
-       }
-       elsif ( !pkg_version_eq($pkg, $version) ) {
-               print "$name: version mismatch ".
-                         "$(pkg->{'version'} ".
-                         "by $pkg->{'builder'})\n";
-               return;
-       }
-       change_state( \$pkg, 'Built' );
-       log_ta( $pkg, "--built" );
-       update_source_info($pkg);
-       print "$name: registered as built\n" if $verbose;
-}
-
-sub add_one_uploaded {
-       my $name = shift;
-       my $version = shift;
-       my $pkg = get_source_info($name);
-
-       if (!defined($pkg)) {
-               print "$name: not registered yet.\n";
-               return;
-       }
-
-       if ($pkg->{'state'} eq "Uploaded" &&
-               pkg_version_eq($pkg,$version)) {
-               print "$name: already uploaded\n";
-               return;
-       }
-       if (!isin( $pkg->{'state'}, qw(Building Built Build-Attempted))) {
-               print "$name: not taken for building (state is $pkg->{'state'}). ",
-                         "Skipping.\n";
-               return;
-       }
-       if ($pkg->{'builder'} ne $user) {
-               print "$name: not taken by you, but by $pkg->{'builder'}. Skipping.\n";
-               return;
-       }
-       # strip epoch -- buildd-uploader used to go based on the filename.
-       # (to remove at some point)
-       my $pkgver;
-       ($pkgver = $pkg->{'version'}) =~ s/^\d+://;
-       $version =~ s/^\d+://; # for command line use
-       if ($pkg->{'binary_nmu_version'} ) {
-               my $nmuver = binNMU_version($pkgver, $pkg->{'binary_nmu_version'});
-               if (!version_eq( $nmuver, $version )) {
-                       print "$name: version mismatch ($nmuver registered). ",
-                                 "Skipping.\n";
-                       return;
-               }
-       } elsif (!version_eq($pkgver, $version)) {
-               print "$name: version mismatch ($pkg->{'version'} registered). ",
-                         "Skipping.\n";
-               return;
-       }
-
-       change_state( \$pkg, 'Uploaded' );
-       log_ta( $pkg, "--uploaded" );
-       update_source_info($pkg);
-       print "$name: registered as uploaded\n" if $verbose;
-}
-
-sub add_one_failed {
-       my $name = shift;
-       my $version = shift;
-       my ($state, $cat);
-       my $pkg = get_source_info($name);
-
-       if (!defined($pkg)) {
-               print "$name: not registered yet.\n";
-               return;
-       }
-       $state = $pkg->{'state'};
-
-       if ($state eq "Not-For-Us") {
-               print "$name: not suitable for this architecture anyway. Skipping.\n";
-               return;
-       }
-       elsif ($state eq "Failed-Removed") {
-               print "$name: failed previously and doesn't need building. Skipping.\n";
-               return;
-       }
-       elsif ($state eq "Installed") {
-               print "$name: Is already installed in archive. Skipping.\n";
-               return;
-       }
-       elsif ($pkg->{'builder'} &&
-                  (($user ne $pkg->{'builder'}) &&
-                   !($pkg->{'builder'} =~ /^(\w+)-\w+/ && $1 eq $user))) {
-               print "$name: not taken by you, but by ".
-                         "$pkg->{'builder'}. Skipping.\n";
-               return;
-       }
-       elsif ( !pkg_version_eq($pkg, $version) ) {
-               print "$name: version mismatch ".
-                         "$(pkg->{'version'} ".
-                         "by $pkg->{'builder'})\n";
-               return;
-       }
-
-       $cat = $category;
-       if (!$cat && $fail_reason =~ /^\[([^\]]+)\]/) {
-               $cat = $1;
-               $cat = $short_category{$cat} if exists $short_category{$cat};
-               if (!isin( $cat, values %short_category )) {
-                       print "$name: Warning: unknown category $cat; discarded\n";
-                       $cat = "";
-               }
-               $fail_reason =~ s/^\[[^\]]+\][ \t]*\n*//;
-       }
-
-       if ($state eq "Needs-Build") {
-               print "$name: Warning: not registered for building previously, ".
-                         "but processing anyway.\n";
-       }
-       elsif ($state eq "Uploaded") {
-               print "$name: Warning: marked as uploaded previously, ".
-                         "but processing anyway.\n";
-       }
-       elsif ($state eq "Dep-Wait") {
-               print "$name: Warning: marked as waiting for dependencies, ".
-                         "but processing anyway.\n";
-       }
-       elsif ($state eq "BD-Uninstallable") {
-               print "$name: Warning: marked as having uninstallable build-dependencies, ".
-                         "but processing anyway.\n";
-       }
-       elsif ($state eq "Failed") {
-               print "$name: already registered as failed; will append new message\n"
-                       if $fail_reason;
-               print "$name: already registered as failed; changing category\n"
-                       if $cat;
-       }
-
-       if (($cat eq "reminder-sent" || $cat eq "nmu-offered") &&
-               defined $pkg->{'failed_category'} &&
-               $pkg->{'failed_category'} ne $cat) {
-               (my $action = $cat) =~ s/-/ /;
-               $fail_reason .= "\n$short_date: $action";
-       }
-
-       change_state( \$pkg, 'Failed' );
-       $pkg->{'builder'} = $user;
-       $pkg->{'failed'} .= "\n" if $pkg->{'failed'};
-       $pkg->{'failed'} .= $fail_reason;
-       $pkg->{'failed_category'} = $cat if $cat;
-       if (defined $pkg->{'permbuildpri'}) {
-               $pkg->{'buildpri'} = $pkg->{'permbuildpri'};
-       } else {
-               delete $pkg->{'buildpri'};
+               print "$name: NOT OK!\n  $reason\n";
+            } else {
+               print "- $name:\n    - status: not ok\n    - reason: \"$reason\"\n";
+            }
        }
        }
-       log_ta( $pkg, "--failed" );
-       update_source_info($pkg);
-       print "$name: registered as failed\n" if $verbose;
 }
 
 }
 
+
 sub add_one_notforus {
 sub add_one_notforus {
-       my $name = shift;
-       my $version = shift;
-       my $pkg = get_source_info($name);
+       my $pkg = shift;
+       my $state = $pkg->{'state'};
+        my $name = $pkg->{'package'};
 
        if ($pkg->{'state'} eq 'Not-For-Us') {
                # reset Not-For-Us state in case it's called twice; this is
 
        if ($pkg->{'state'} eq 'Not-For-Us') {
                # reset Not-For-Us state in case it's called twice; this is
@@ -1011,7 +795,6 @@ sub add_one_notforus {
                $pkg->{'package'} = $name;
                delete $pkg->{'builder'};
                delete $pkg->{'depends'};
                $pkg->{'package'} = $name;
                delete $pkg->{'builder'};
                delete $pkg->{'depends'};
-               delete $pkg->{'buildpri'};
                delete $pkg->{'binary_nmu_version'};
                delete $pkg->{'binary_nmu_changelog'};
                log_ta( $pkg, "--no-build" );
                delete $pkg->{'binary_nmu_version'};
                delete $pkg->{'binary_nmu_changelog'};
                log_ta( $pkg, "--no-build" );
@@ -1029,101 +812,11 @@ sub add_one_notforus {
        update_source_info($pkg);
 }
 
        update_source_info($pkg);
 }
 
-sub add_one_needsbuild {
-       my $name = shift;
-       my $version = shift;
-       my $state;
-       my $pkg = get_source_info($name);
-
-       if (!defined($pkg)) {
-               print "$name: not registered; can't give back.\n";
-               return;
-       }
-       $state = $pkg->{'state'};
-
-       if ($state eq "BD-Uninstallable") {
-               if ($opt_override) {
-                       print "$name: Forcing uninstallability mark to be removed. This is not permanent and might be reset with the next trigger run\n";
-
-                       change_state( \$pkg, 'Needs-Build' );
-                       delete $pkg->{'builder'};
-                       delete $pkg->{'depends'};
-                       log_ta( $pkg, "--give-back" );
-                       update_source_info($pkg);
-                       print "$name: given back\n" if $verbose;
-                       return;
-               }
-               else {
-                       print "$name: has uninstallable build-dependencies. Skipping\n",
-                                 "  (use --override to clear dependency list and ",
-                                 "give back anyway)\n";
-                       return;
-               }
-       }
-       elsif ($state eq "Dep-Wait") {
-               if ($opt_override) {
-                       print "$name: Forcing source dependency list to be cleared\n";
-               }
-               else {
-                       print "$name: waiting for source dependencies. Skipping\n",
-                                 "  (use --override to clear dependency list and ",
-                                 "give back anyway)\n";
-                       return;
-               }
-       }
-       elsif (!isin( $state, qw(Building Built Build-Attempted))) {
-               print "$name: not taken for building (state is $state).";
-               if ($opt_override) {
-                       print "\n$name: Forcing give-back\n";
-               }
-               else {
-                       print " Skipping.\n";
-                       return;
-               }
-       }
-       if (defined ($pkg->{'builder'}) && $user ne $pkg->{'builder'} &&
-               !($pkg->{'builder'} =~ /^(\w+)-\w+/ && $1 eq $user) &&
-               !$opt_override) {
-               print "$name: not taken by you, but by ".
-                         "$pkg->{'builder'}. Skipping.\n";
-               return;
-       }
-       if (!pkg_version_eq($pkg, $version)) {
-               print "$name: version mismatch ($pkg->{'version'} registered). ",
-                         "Skipping.\n";
-               return;
-       }
-       if ($distribution eq "unstable") {
-               change_state( \$pkg, 'BD-Uninstallable' );
-               $pkg->{'bd_problem'} = "Installability of build dependencies not tested yet";
-       } else {
-               change_state( \$pkg, 'Needs-Build' );
-       }
-       $pkg->{'builder'} = undef;
-       $pkg->{'depends'} = undef;
-       log_ta( $pkg, "--give-back" );
-       update_source_info($pkg);
-       print "$name: given back\n" if $verbose;
-}
-
 sub set_one_binnmu {
        my $name = shift;
        my $version = shift;
 sub set_one_binnmu {
        my $name = shift;
        my $version = shift;
-       my $pkg = get_source_info($name);
-       my $state;
-
-       if (!defined($pkg)) {
-               print "$name: not registered; can't register for binNMU.\n";
-               return;
-       }
-       my $db_ver = $pkg->{'version'};
-
-       if (!version_eq($db_ver, $version)) {
-               print "$name: version mismatch ($db_ver registered). ",
-                         "Skipping.\n";
-               return;
-       }
-       $state = $pkg->{'state'};
+       my $pkg = shift;
+       my $state = $pkg->{'state'};
 
        if (defined $pkg->{'binary_nmu_version'}) {
                if ($binNMUver == 0) {
 
        if (defined $pkg->{'binary_nmu_version'}) {
                if ($binNMUver == 0) {
@@ -1132,6 +825,7 @@ sub set_one_binnmu {
                        delete $pkg->{'depends'};
                        delete $pkg->{'binary_nmu_version'};
                        delete $pkg->{'binary_nmu_changelog'};
                        delete $pkg->{'depends'};
                        delete $pkg->{'binary_nmu_version'};
                        delete $pkg->{'binary_nmu_changelog'};
+                        delete $pkg->{'buildpri'};
                } elsif ($binNMUver <= $pkg->{'binary_nmu_version'}) {
                        print "$name: already building binNMU $pkg->{'binary_nmu_version'}\n";
                        return;
                } elsif ($binNMUver <= $pkg->{'binary_nmu_version'}) {
                        print "$name: already building binNMU $pkg->{'binary_nmu_version'}\n";
                        return;
@@ -1139,8 +833,8 @@ sub set_one_binnmu {
                        $pkg->{'binary_nmu_version'} = $binNMUver;
                        $pkg->{'binary_nmu_changelog'} = $fail_reason;
                        $pkg->{'notes'} = 'out-of-date';
                        $pkg->{'binary_nmu_version'} = $binNMUver;
                        $pkg->{'binary_nmu_changelog'} = $fail_reason;
                        $pkg->{'notes'} = 'out-of-date';
-                       $pkg->{'buildpri'} = $pkg->{'permbuildpri'}
-                               if (defined $pkg->{'permbuildpri'});
+                        delete $pkg->{'buildpri'};
+                       change_state( \$pkg, 'BD-Uninstallable' );
                }
                log_ta( $pkg, "--binNMU" );
                update_source_info($pkg);
                }
                log_ta( $pkg, "--binNMU" );
                update_source_info($pkg);
@@ -1162,123 +856,53 @@ sub set_one_binnmu {
                return;
        }
 
                return;
        }
 
-       if ($distribution eq "unstable") {
-               change_state( \$pkg, 'BD-Uninstallable' );
-               $pkg->{'bd_problem'} = "Installability of build dependencies not tested yet";
-       }
-       else
-       {
-               change_state( \$pkg, 'Needs-Build' );
-       }
+       change_state( \$pkg, 'BD-Uninstallable' );
        delete $pkg->{'builder'};
        delete $pkg->{'depends'};
        $pkg->{'binary_nmu_version'} = $binNMUver;
        $pkg->{'binary_nmu_changelog'} = $fail_reason;
        $pkg->{'notes'} = 'out-of-date';
        delete $pkg->{'builder'};
        delete $pkg->{'depends'};
        $pkg->{'binary_nmu_version'} = $binNMUver;
        $pkg->{'binary_nmu_changelog'} = $fail_reason;
        $pkg->{'notes'} = 'out-of-date';
+        delete $pkg->{'buildpri'};
        log_ta( $pkg, "--binNMU" );
        update_source_info($pkg);
        print "${name}: registered for binNMU $fullver\n" if $verbose;
 }
 
 sub set_one_buildpri {
        log_ta( $pkg, "--binNMU" );
        update_source_info($pkg);
        print "${name}: registered for binNMU $fullver\n" if $verbose;
 }
 
 sub set_one_buildpri {
-       my $name = shift;
-       my $version = shift;
        my $key = shift;
        my $key = shift;
-       my $pkg = get_source_info($name);
-       my $state;
-
-       if (!defined($pkg)) {
-               print "$name: not registered; can't set priority.\n";
-               return;
-       }
-       $state = $pkg->{'state'};
+       my $pkg = shift;
+        my $name = $pkg->{'package'};
 
 
-       if ($state eq "Not-For-Us") {
-               print "$name: not suitable for this architecture. Skipping.\n";
-               return;
-       } elsif ($state eq "Failed-Removed") {
-               print "$name: failed previously and doesn't need building. Skipping.\n";
-               return;
-        }
-       if (!pkg_version_eq($pkg, $version)) {
-               print "$name: version mismatch ($pkg->{'version'} registered). ",
-                         "Skipping.\n";
-               return;
-       }
-       if ( $build_priority == 0 ) {
-               delete $pkg->{'buildpri'}
-                       if $key eq 'permbuildpri' and defined $pkg->{'buildpri'}
-                       and $pkg->{'buildpri'} == $pkg->{$key};
-               delete $pkg->{$key};
-       } else {
-               $pkg->{'buildpri'} = $build_priority
-                       if $key eq 'permbuildpri';
+       if ( $build_priority ) {
                $pkg->{$key} = $build_priority;
                $pkg->{$key} = $build_priority;
+       } else {
+               delete $pkg->{$key};
        }
        update_source_info($pkg);
        print "$name: set to build priority $build_priority\n" if $verbose;
 }
 
 sub add_one_depwait {
        }
        update_source_info($pkg);
        print "$name: set to build priority $build_priority\n" if $verbose;
 }
 
 sub add_one_depwait {
-       my $name = shift;
-       my $version = shift;
-       my $state;
-       my $pkg = get_source_info($name);
-
-       if (!defined($pkg)) {
-               print "$name: not registered yet.\n";
-               return;
-       }
-       $state = $pkg->{'state'};
+       my $pkg = shift;
+       my $state = $pkg->{'state'};
+        my $name = $pkg->{'package'};
 
        if ($state eq "Dep-Wait") {
                print "$name: merging with previously registered dependencies\n";
        }
        
 
        if ($state eq "Dep-Wait") {
                print "$name: merging with previously registered dependencies\n";
        }
        
-       if (isin( $state, qw(Needs-Build Failed BD-Uninstallable))) {
-               print "$name: Warning: not registered for building previously, ".
-                         "but processing anyway.\n";
-       }
-       elsif ($state eq "Not-For-Us") {
-               print "$name: not suitable for this architecture anyway. Skipping.\n";
-               return;
-       }
-       elsif ($state eq "Failed-Removed") {
-               print "$name: failed previously and doesn't need building. Skipping.\n";
-               return;
-       }
-       elsif ($state eq "Installed") {
-               print "$name: Is already installed in archive. Skipping.\n";
-               return;
-       }
-       elsif ($state eq "Uploaded") {
-               print "$name: Is already uploaded. Skipping.\n";
-               return;
-       }
-       elsif ($pkg->{'builder'} &&
-                  $user ne $pkg->{'builder'}) {
-               print "$name: not taken by you, but by ".
-                         "$pkg->{'builder'}. Skipping.\n";
-               return;
-       }
-       elsif ( !pkg_version_eq($pkg,$version)) {
-               print "$name: version mismatch ".
-                         "($pkg->{'version'} ".
-                         "by $pkg->{'builder'})\n";
-               return;
-       }
-       elsif ($fail_reason =~ /^\s*$/ ||
+       if (isin( $state, qw<Installed Not-For-Us>)) {
+            print "add_one_depwait: $name: skiping in state $state\n";
+            return;
+        }
+        
+       if ($fail_reason =~ /^\s*$/ ||
                   !parse_deplist( $fail_reason, 1 )) {
                print "$name: Bad dependency list\n";
                return;
        }
        change_state( \$pkg, 'Dep-Wait' );
        $pkg->{'builder'} = $user;
                   !parse_deplist( $fail_reason, 1 )) {
                print "$name: Bad dependency list\n";
                return;
        }
        change_state( \$pkg, 'Dep-Wait' );
        $pkg->{'builder'} = $user;
-       if (defined $pkg->{'permbuildpri'}) {
-               $pkg->{'buildpri'} = $pkg->{'permbuildpri'};
-       } else {
-               delete $pkg->{'buildpri'};
-       }
        my $deplist = parse_deplist( $pkg->{'depends'} );
        my $new_deplist = parse_deplist( $fail_reason );
        # add new dependencies, maybe overwriting old entries
        my $deplist = parse_deplist( $pkg->{'depends'} );
        my $new_deplist = parse_deplist( $fail_reason );
        # add new dependencies, maybe overwriting old entries
@@ -1286,503 +910,9 @@ sub add_one_depwait {
                $deplist->{$_} = $new_deplist->{$_};
        }
        $pkg->{'depends'} = build_deplist($deplist);
                $deplist->{$_} = $new_deplist->{$_};
        }
        $pkg->{'depends'} = build_deplist($deplist);
-       log_ta( $pkg, "--dep-wait" );
-       update_source_info($pkg);
-       print "$name: registered as waiting for dependencies\n" if $verbose;
-}
-
-sub set_one_update {
-       my $name = shift;
-       my $version = shift;
-       my $pkg = get_source_info($name);
-
-       if (!defined($pkg)) {
-               print "$name: not registered yet.\n";
-               return;
-       }
-        $pkg->{'version'} =~ s/\+b[0-9]+$//;
-
-       log_ta( $pkg, "--update" );
-       update_source_info($pkg);
-}
-
-
-sub parse_sources {
-       my %pkgs;
-       my %srcver;
-       my $name;
-       my $full = shift;
-
-       my $db = get_all_source_info();
-
-       local($/) = ""; # read in paragraph mode
-       while( <> ) {
-               my( $version, $arch, $section, $priority, $builddep, $buildconf, $binaries );
-               s/\s*$//m;
-               /^Package:\s*(\S+)$/mi and $name = $1;
-               /^Version:\s*(\S+)$/mi and $version = $1;
-               /^Architecture:\s*(\S+)$/mi and $arch = $1;
-               /^Section:\s*(\S+)$/mi and $section = $1;
-               /^Priority:\s*(\S+)$/mi and $priority = $1;
-               /^Build-Depends:\s*(.*)$/mi and $builddep = $1;
-               /^Build-Conflicts:\s*(.*)$/mi and $buildconf = $1;
-                /^Binary:\s*(.*)$/mi and $binaries = $1;
-
-               next if (defined $srcver{$name} and version_less( $version, $srcver{$name} ));
-               $srcver{$name} = $version;
-
-               $pkgs{$name}{'ver'} = $version;
-               $pkgs{$name}{'bin'} = $binaries;
-               $pkgs{$name}{'dep'} = $builddep;
-               $pkgs{$name}{'conf'} = $buildconf;
-               my $pkg = $db->{$name};
-
-               if (defined $pkg) {
-                       my $change = 0;
-
-                       if ($arch eq "all" && !version_less( $version, $pkg->{'version'} )) {
-                               # package is now Arch: all, delete it from db
-                               change_state( \$pkg, 'deleted' );
-                               log_ta( $pkg, "--merge-sources" );
-                               print "$name ($pkg->{'version'}): deleted ".
-                                         "from database, because now Arch: all\n"
-                                                 if $verbose;
-                               del_source_info($name);
-                               delete $db->{$name};
-                               next;
-                       }
-
-                       # The "Version" should always be the source version --
-                       # not a possible binNMU version number.
-                       $pkg->{'version'} = $version, $change++
-                               if ($pkg->{'state'} eq 'Installed' and
-                               !version_eq( $pkg->{'version'}, $version));
-                       # Always update priority and section, if available
-                       $pkg->{'priority'} = $priority, $change++
-                               if defined $priority and (not defined($pkg->{'priority'}) or $pkg->{'priority'} ne $priority);
-
-                       $pkg->{'section'} = $section, $change++
-                               if defined $section and (not defined($pkg->{'section'}) or $pkg->{'section'} ne $section);
-
-                       update_source_info($pkg) if $change;
-               }
-       }
-        # Now that we only have the latest source version, build the list
-        # of binary packages from the Sources point of view
-        foreach $name (keys %pkgs) {
-            foreach my $bin (split( /\s*,\s*/, $pkgs{$name}{'bin'} ) ) {
-                $merge_binsrc{$bin} = $name;
-            }
-        }
-       # remove installed packages that no longer have source available
-       # or binaries installed
-        foreach $name (keys %$db) {
-               next if $name =~ /^_/;
-               my $pkg = $db->{$name};
-               if (not defined($pkgs{$name})) {
-                       change_state( \$pkg, 'deleted' );
-                       log_ta( $pkg, "--merge-sources" );
-                       print "$name ($pkg->{'version'}): ".
-                                 "deleted from database, because ".
-                                 "not in Sources anymore\n"
-                                         if $verbose;
-                       del_source_info($name);
-                       delete $db->{$name};
-               } else {
-                       next if !isin( $pkg->{'state'}, qw(Installed) );
-                       if ($full && not defined $merge_srcvers{$name}) {
-                            change_state( \$pkg, 'deleted' );
-                            log_ta( $pkg, "--merge-sources" );
-                            print "$name ($pkg->{'version'}): ".
-                                      "deleted from database, because ".
-                                      "binaries don't exist anymore\n"
-                                              if $verbose;
-                           del_source_info($name);
-                           delete $db->{$name};
-                        } elsif ($full && version_less( $merge_srcvers{$name}, $pkg->{'version'})) {
-                            print "$name ($pkg->{'version'}): ".
-                                      "package is Installed but binaries are from ".
-                                      $merge_srcvers{$name}. "\n"
-                                              if $verbose;
-                        }
-                }
-       }
-       return \%pkgs;
-}
-
-# This function looks through a Packages file and sets the state of
-# packages to 'Installed'
-sub parse_packages {
-       my $depwait_only = shift;
-       my $installed;
-
-       my $pkgs = get_all_source_info();
-       local($/) = ""; # read in paragraph mode
-       while( <> ) {
-               my( $name, $version, $depends, $source, $sourcev, $architecture, $provides, $binaryv, $binnmu );
-               s/\s*$//m;
-               /^Package:\s*(\S+)$/mi and $name = $1;
-               /^Version:\s*(\S+)$/mi and $version = $1;
-               /^Depends:\s*(.*)$/mi and $depends = $1;
-               /^Source:\s*(\S+)(\s*\((\S+)\))?$/mi and ($source,$sourcev) = ($1, $3);
-               /^Architecture:\s*(\S+)$/mi and $architecture = $1;
-               /^Provides:\s*(.*)$/mi and $provides = $1;
-               next if !$name || !$version;
-               next if ($arch ne $architecture and $architecture ne "all");
-               next if (defined ($installed->{$name}) and $installed->{$name}{'version'} ne "" and
-                       version_lesseq( $version, $installed->{$name}{'version'} ));
-               $installed->{$name}{'version'} = $version;
-               next if $depwait_only;
-               $installed->{$name}{'depends'} = $depends;
-               $installed->{$name}{'all'} = 1 if $architecture eq "all";
-               undef $installed->{$name}{'Provider'};
-               $installed->{$name}{'Source'} = $source ? $source : $name;
-               if ($provides) {
-                    foreach (split( /\s*,\s*/, $provides )) {
-                        if (not defined ($installed->{$_})) {
-                            $installed->{$_}{'version'} = "";
-                            $installed->{$_}{'Provider'} = $name;
-                        }
-                    }
-               }
-               if ( $version =~ /\+b(\d+)$/ ) {
-                    $binnmu = $1;
-               }
-               $version = $sourcev if $sourcev;
-               $binaryv = $version;
-               $binaryv =~ s/\+b\d+$//;
-               $installed->{$name}{'Sourcev'} = $sourcev ? $sourcev : $binaryv;
-               $binaryv .= "+b$binnmu" if defined($binnmu);
-
-               next if $architecture ne $arch;
-               $name = $source if $source;
-               next if defined($merge_srcvers{$name}) and $merge_srcvers{$name} eq $version;
-               $merge_srcvers{$name} = $version;
-
-               my $pkg = $pkgs->{$name};
-
-               if (defined $pkg) {
-                       if (isin( $pkg->{'state'}, qw(Not-For-Us)) ||
-                               (isin($pkg->{'state'}, qw(Installed)) &&
-                                version_lesseq($binaryv, $pkg->{'installed_version'}))) {
-                               print "Skipping $name because State == $pkg->{'state'}\n"
-                                       if $verbose >= 2;
-                               next;
-                       }
-                       if ($pkg->{'binary_nmu_version'} ) {
-                               my $nmuver = binNMU_version($pkg->{'version'}, $pkg->{'binary_nmu_version'});
-                               if (version_less( $binaryv, $nmuver )) {
-                                       print "Skipping $name ($version) because have newer ".
-                                               "version ($nmuver) in db.\n"
-                                                       if $verbose >= 2;
-                                       next;
-                               }
-                       } elsif (version_less($version, $pkg->{'version'})) {
-                               print "Skipping $name ($version) because have newer ".
-                                       "version ($pkg->{'version'}) in db.\n"
-                                               if $verbose >= 2;
-                               next;
-                       }
-
-                       if (!pkg_version_eq($pkg, $version) &&
-                          $pkg->{'state'} ne "Installed") {
-                               warn "Warning: $name: newer version than expected appeared ".
-                                        "in archive ($version vs. $pkg->{'version'})\n";
-                               delete $pkg->{'builder'};
-                       }
-
-                       if (!isin( $pkg->{'state'}, qw(Uploaded) )) {
-                               warn "Warning: Package $name was not in uploaded state ".
-                                        "before (but in '$pkg->{'state'}').\n";
-                               delete $pkg->{'builder'};
-                               delete $pkg->{'depends'};
-                       }
-               } else {
-                       $pkg = {};
-                       $pkg->{'version'} = $version;
-               }
-               
-               change_state( \$pkg, 'Installed' );
-               $pkg->{'package'} = $name;
-               $pkg->{'installed_version'} = $binaryv;
-               if (defined $pkg->{'permbuildpri'}) {
-                       $pkg->{'buildpri'} = $pkg->{'permbuildpri'};
-               } else {
-                       delete $pkg->{'buildpri'};
-               }
-               $pkg->{'version'} = $version
-                       if version_less( $pkg->{'version'}, $version);
-               delete $pkg->{'binary_nmu_version'};
-               delete $pkg->{'binary_nmu_changelog'};
-               log_ta( $pkg, "--merge-packages" );
-               update_source_info($pkg);
-               print "$name ($version) is up-to-date now.\n" if $verbose;
-       }
-
-       check_dep_wait( "--merge-packages", $installed );
-       return $installed;
-}
-
-sub pretend_avail {
-       my ($package, $name, $version, $installed);
-       
-       foreach $package (@_) {
-               $package =~ s,^.*/,,; # strip path
-               $package =~ s/\.(dsc|diff\.gz|tar\.gz|deb)$//; # strip extension
-               $package =~ s/_[\w\d]+\.changes$//; # strip extension
-               if ($package =~ /^([\w\d.+-]+)_([\w\d:.+~-]+)/) {
-                       ($name,$version) = ($1,$2);
-               }
-               else {
-                       warn "$package: can't extract package name and version ".
-                                "(bad format)\n";
-                       next;
-               }
-               $installed->{$name}{'version'} = $version;
-       }
-
-       check_dep_wait( "--pretend-avail", $installed );
-}
-
-sub check_dep_wait {
-       my $action = shift;
-       my $installed = shift;
-       
-       # check all packages in state Dep-Wait if dependencies are all
-       # available now
-       my $name;
-       my $db = get_all_source_info();
-        foreach $name (keys %$db) {
-               next if $name =~ /^_/;
-               my $pkg = $db->{$name};
-               next if $pkg->{'state'} ne "Dep-Wait";
-               my $deps = $pkg->{'depends'};
-               if (!$deps) {
-                       print "$name: was in state Dep-Wait, but with empty ",
-                                 "dependencies!\n";
-                       goto make_needs_build;
-               }
-               my $deplist = parse_deplist($deps);
-               my $new_deplist;
-               my $allok = 1;
-               my @removed_deps;
-               foreach (keys %$deplist) {
-                       if (!exists $installed->{$_} ||
-                               ($deplist->{$_}->{'rel'} && $deplist->{$_}->{'version'} &&
-                                !version_compare( $installed->{$_}{'version'},
-                                                                  $deplist->{$_}->{'rel'},
-                                                                  $deplist->{$_}->{'version'}))) {
-                               $allok = 0;
-                               $new_deplist->{$_} = $deplist->{$_};
-                       }
-                       else {
-                               push( @removed_deps, $_ );
-                       }
-               }
-               if ($allok) {
-                 make_needs_build:
-                       change_state( \$pkg, 'Needs-Build' );
-                       log_ta( $pkg, $action );
-                       delete $pkg->{'builder'};
-                       delete $pkg->{'depends'};
-                       print "$name ($pkg->{'version'}) has all ",
-                                 "dependencies available now\n" if $verbose;
-                       $new_vers{$name}++;
-                       update_source_info($pkg);
-               }
-               elsif (@removed_deps) {
-                       $pkg->{'depends'} = build_deplist( $new_deplist );
-                       print "$name ($pkg->{'version'}): some dependencies ",
-                                 "(@removed_deps) available now, but not all yet\n"
-                               if $verbose;
-                       update_source_info($pkg);
-               }
-       }
-}
-
-# This function accepts quinn-diff output (either from a file named on
-# the command line, or on stdin) and sets the packages named there to
-# state 'Needs-Build'.
-sub parse_quinn_diff {
-       my $partial = shift;
-       my %quinn_pkgs;
-       my $dubious = "";
-       
-       my $pkgs = get_all_source_info();
-
-       while( <> ) {
-               my $change = 0;
-               next if !m,^([-\w\d/]*)/                        # section
-                              ([-\w\d.+]+)_                    # package name
-                                  ([\w\d:.~+-]+)\.dsc\s*       # version
-                                  \[([^:]*):                           # priority
-                                  ([^]]+)\]\s*$,x;                     # rest of notes
-               my($section,$name,$version,$priority,$notes) = ($1, $2, $3, $4, $5);
-               $quinn_pkgs{$name}++;
-               $section ||= "unknown";
-               $priority ||= "unknown";
-               $priority = "unknown" if $priority eq "-";
-               $priority = "standard" if ($name eq "debian-installer");
-
-               my $pkg = $pkgs->{$name};
-
-               # Always update section and priority.
-               if (defined($pkg)) {
-
-                       $pkg->{'section'}  = $section, $change++ if not defined
-                               $pkg->{'section'} or $section ne "unknown";
-                       $pkg->{'priority'} = $priority, $change++ if not defined
-                               $pkg->{'priority'} or $priority ne "unknown";
-               }
-
-               if (defined($pkg) &&
-                       $pkg->{'state'} =~ /^Dep-Wait/ &&
-                       version_less( $pkg->{'version'}, $version )) {
-                       change_state( \$pkg, 'Dep-Wait' );
-                       $pkg->{'version'}  = $version;
-                       delete $pkg->{'binary_nmu_version'};
-                       delete $pkg->{'binary_nmu_changelog'};
-                       log_ta( $pkg, "--merge-quinn" );
-                       $change++;
-                       print "$name ($version) still waiting for dependencies.\n"
-                               if $verbose;
-               }
-               elsif (defined($pkg) &&
-                          $pkg->{'state'} =~ /-Removed$/ &&
-                          version_eq($pkg->{'version'}, $version)) {
-                       # reinstantiate a package that has been removed earlier
-                       # (probably due to a quinn-diff malfunction...)
-                       my $newstate = $pkg->{'state'};
-                       $newstate =~ s/-Removed$//;
-                       change_state( \$pkg, $newstate );
-                       $pkg->{'version'}  = $version;
-                       $pkg->{'notes'}    = $notes;
-                       log_ta( $pkg, "--merge-quinn" );
-                       $change++;
-                       print "$name ($version) reinstantiated to $newstate.\n"
-                               if $verbose;
-               }
-               elsif (defined($pkg) &&
-                          $pkg->{'state'} eq "Not-For-Us" &&
-                          version_less( $pkg->{'version'}, $version )) {
-                       # for Not-For-Us packages just update the version etc., but
-                       # keep the state
-                       change_state( \$pkg, "Not-For-Us" );
-                       $pkg->{'package'}  = $name;
-                       $pkg->{'version'}  = $version;
-                       $pkg->{'notes'}    = $notes;
-                       delete $pkg->{'builder'};
-                       log_ta( $pkg, "--merge-quinn" );
-                       $change++;
-                       print "$name ($version) still Not-For-Us.\n" if $verbose;
-               }
-               elsif (!defined($pkg) ||
-                          $pkg->{'state'} ne "Not-For-Us" &&
-                          (version_less( $pkg->{'version'}, $version ) ||
-                          ($pkg->{'state'} eq "Installed" && version_less($pkg->{'installed_version'}, $version)))) {
-
-                       if (defined( $pkg->{'state'} ) && isin( $pkg->{'state'}, qw(Building Built Build-Attempted))) {
-                               send_mail( $pkg->{'builder'},
-                                                  "new version of $name (dist=$distribution)",
-                                                  "As far as I'm informed, you're currently ".
-                                                  "building the package $name\n".
-                                                  "in version $pkg->{'version'}.\n\n".
-                                                  "Now there's a new source version $version. ".
-                                                  "If you haven't finished\n".
-                                                  "compiling $name yet, you can stop it to ".
-                                                  "save some work.\n".
-                                                  "Just to inform you...\n".
-                                                  "(This is an automated message)\n" );
-                               print "$name: new version ($version) while building ".
-                                         "$pkg->{'version'} -- sending mail ".
-                                         "to builder ($pkg->{'builder'})\n"
-                                 if $verbose;
-                       }
-                       change_state( \$pkg, 'Needs-Build' );
-                       $pkg->{'package'}  = $name;
-                       $pkg->{'version'}  = $version;
-                       $pkg->{'section'}  = $section;
-                       $pkg->{'priority'} = $priority;
-                       $pkg->{'notes'}    = $notes;
-                       delete $pkg->{'builder'};
-                       delete $pkg->{'binary_nmu_version'};
-                       delete $pkg->{'binary_nmu_changelog'};
-                       log_ta( $pkg, "--merge-quinn" );
-                       $new_vers{$name}++;
-                       $change++;
-                       print "$name ($version) needs rebuilding now.\n" if $verbose;
-               }
-               elsif (defined($pkg) &&
-                          !version_eq( $pkg->{'version'}, $version ) &&
-                          isin( $pkg->{'state'}, qw(Installed Not-For-Us) )) {
-                       print "$name: skipping because version in db ".
-                                 "($pkg->{'version'}) is >> than ".
-                                 "what quinn-diff says ($version) ".
-                                 "(state is $pkg->{'state'})\n"
-                                         if $verbose;
-                       $dubious .= "$pkg->{'state'}: ".
-                                               "db ${name}_$pkg->{'version'} >> ".
-                                               "quinn $version\n" if !$partial;
-               }
-               elsif ($verbose >= 2) {
-                       if ($pkg->{'state'} eq "Not-For-Us") {
-                               print "Skipping $name because State == ".
-                                         "$pkg->{'state'}\n";
-                       }
-                       elsif (!version_less($pkg->{'version'}, $version)) {
-                               print "Skipping $name because version in db ".
-                                         "($pkg->{'version'}) is >= than ".
-                                         "what quinn-diff says ($version)\n";
-                       }
-               }
-               update_source_info($pkg) if $change;
-       }
-
-       if ($dubious) {
-               send_mail( $conf::db_maint,
-                                  "Dubious versions in " . table_name() . " "
-                                  . $distribution . " table",
-                                  "The following packages have a newer version in the ".
-                                  "wanna-build database\n".
-                                  "than what quinn-diff says, and this is strange for ".
-                                  "their state\n".
-                                  "It could be caused by a lame mirror, or the version ".
-                                  "in the database\n".
-                                  "is wrong.\n\n".
-                                  $dubious );
-       }
-
-       # Now re-check the DB for packages in states Needs-Build, Failed,
-       # Dep-Wait or BD-Uninstallable and remove them if they're not listed
-       # anymore by quinn-diff.
-       if ( !$partial ) {
-               my $name;
-               my $db = get_all_source_info();
-               foreach $name (keys %$db) {
-                       next if $name =~ /^_/;
-                       my $pkg = $db->{$name};
-                       next if defined $pkg->{'binary_nmu_version'};
-                       next if !isin( $pkg->{'state'},
-                                                  qw(Needs-Build Building Built Build-Attempted Uploaded Failed Dep-Wait BD-Uninstallable) );
-                       my $virtual_delete = $pkg->{'state'} eq 'Failed';
-                                                                
-                       if (!$quinn_pkgs{$name}) {
-                               change_state( \$pkg, $virtual_delete ?
-                                                         $pkg->{'state'}."-Removed" :
-                                                         'deleted' );
-                               log_ta( $pkg, "--merge-quinn" );
-                               print "$name ($pkg->{'version'}): ".
-                                         ($virtual_delete ? "(virtually) " : "") . "deleted ".
-                                         "from database, because not in quinn-diff anymore\n"
-                                                 if $verbose;
-                               if ($virtual_delete) {
-                                   update_source_info($pkg);
-                               } else {
-                                   del_source_info($name);
-                               }
-                       }
-               }
-       }
+       log_ta( $pkg, "--dep-wait" ) unless $simulate;
+       update_source_info($pkg) unless $simulate;
+       print "$name: registered as waiting for dependencies\n" if $verbose || $simulate;
 }
 
 
 }
 
 
@@ -1855,35 +985,27 @@ BEGIN {
        }
        $sectval{'unknown'}     = -165;
 
        }
        $sectval{'unknown'}     = -165;
 
-       %catval =  ( "none"                           => -20,
-                                "uploaded-fixed-pkg" => -19,
-                                "fix-expected"       => -18,
-                                "reminder-sent"      => -17,
-                                "nmu-offered"        => -16,
-                                "easy"               => -15,
-                                "medium"                     => -14,
-                                "hard"                   => -13,
-                                "compiler-error"     => -12 );
 }
 
 sub sort_list_func {
     my $map_funcs = {
 }
 
 sub sort_list_func {
     my $map_funcs = {
-        'C' => ['<=>', sub { return (-1) * $_[0]->{'calprio'}; }],
-        'W' => ['<=>', sub { return (-1) * $_[0]->{'state_days'}; }],
-        'P' => ['<=>', sub { return (-1) * $_[0]->{'buildpri'}; }],
-        'p' => ['<=>', sub { return $prioval{$_[0]->{'priority'}}; }],
-        's' => ['<=>', sub { return $sectval{$_[0]->{'section'}}; }],
+        'C' => ['<->', sub { return $_[0]->{'calprio'}; }],
+        'W' => ['<->', sub { return $_[0]->{'state_days'}; }],
+        'P' => ['<->', sub { return ($_[0]->{'buildpri'}//0) + ($_[0]->{'permbuildpri'}//0); }],
+        'p' => ['<=>', sub { return $prioval{$_[0]->{'priority'}//""}//0; }],
+        's' => ['<=>', sub { return $sectval{$_[0]->{'section'}//""}//0; }],
         'n' => ['cmp', sub { return $_[0]->{'package'}; }],
         'b' => ['cmp', sub { return $_[0]->{'builder'}; }],
         'n' => ['cmp', sub { return $_[0]->{'package'}; }],
         'b' => ['cmp', sub { return $_[0]->{'builder'}; }],
-        'c' => ['<=>', sub { return ($_[0]->{'notes'} =~ /^(out-of-date|partial)/) ? 0: ($_[0]->{'notes'} =~ /^uncompiled/) ? 2 : 1; }],
-        'f' => ['<=>', sub { return $catval{ $_[0]->{'failed_category'} ? $_[0]->{'failed_category'}: "none" }; }],
-        'S' => ['<=>', sub { return $prioval{$_[0]->{'priority'}} > $prioval{'standard'}; }],
+        'c' => ['<=>', sub { return ($_[0]->{'notes'}//"" =~ /^(out-of-date|partial)/) ? 0: ($_[0]->{'notes'}//"" =~ /^uncompiled/) ? 2 : 1; }],
+        'S' => ['<->', sub { return isin($_[0]->{'priority'}, qw(required important standard)); }],
+        'T' => ['<->', sub { return $_[0]->{'state_time'} % 86400;} ], # Fractions of a day
     };
 
        foreach my $letter (split( //, $list_order )) {
             my $r;
     };
 
        foreach my $letter (split( //, $list_order )) {
             my $r;
-            $r = &{$map_funcs->{$letter}[1]}($a) <=> &{$map_funcs->{$letter}[1]}($b) if $map_funcs->{$letter}[0] eq '<=>';
-            $r = &{$map_funcs->{$letter}[1]}($a) cmp &{$map_funcs->{$letter}[1]}($b) if $map_funcs->{$letter}[0] eq 'cmp';
+            $r = (&{$map_funcs->{$letter}[1]}($b)//0 ) <=> (&{$map_funcs->{$letter}[1]}($a)//0 ) if $map_funcs->{$letter}[0] eq '<->';
+            $r = (&{$map_funcs->{$letter}[1]}($a)//0 ) <=> (&{$map_funcs->{$letter}[1]}($b)//0 ) if $map_funcs->{$letter}[0] eq '<=>';
+            $r = (&{$map_funcs->{$letter}[1]}($a)//"") cmp (&{$map_funcs->{$letter}[1]}($b)//"") if $map_funcs->{$letter}[0] eq 'cmp';
             return $r if $r != 0;
        }
        return 0;
             return $r if $r != 0;
        }
        return 0;
@@ -1892,7 +1014,7 @@ sub sort_list_func {
 sub calculate_prio {
        my $priomap = $yamlmap->{priority};
        my $pkg = shift;
 sub calculate_prio {
        my $priomap = $yamlmap->{priority};
        my $pkg = shift;
-        my @s=split("/", $pkg->{'section'});
+        my @s=split("/", $pkg->{'section'}//"");
         $pkg->{'component'} = $s[0] if $s[1];
         $pkg->{'component'} ||= 'main';
        $pkg->{'calprio'} = 0;
         $pkg->{'component'} = $s[0] if $s[1];
         $pkg->{'component'} ||= 'main';
        $pkg->{'calprio'} = 0;
@@ -1906,6 +1028,13 @@ sub calculate_prio {
        my $scale = $priomap->{'waitingdays'}->{'scale'} || 1;
        $pkg->{'calprio'} += $days * $scale;
 
        my $scale = $priomap->{'waitingdays'}->{'scale'} || 1;
        $pkg->{'calprio'} += $days * $scale;
 
+        my $btime = max($pkg->{'anytime'}//0, $pkg->{'successtime'}//0);
+        my $bhours = $btime ? int($btime/3600) : ($priomap->{'buildhours'}->{'default'} || 2);
+       $bhours = $priomap->{'buildhours'}->{'min'} if $priomap->{'buildhours'}->{'min'} and $bhours < $priomap->{'buildhours'}->{'min'};
+       $bhours = $priomap->{'buildhours'}->{'max'} if $priomap->{'buildhours'}->{'max'} and $bhours > $priomap->{'buildhours'}->{'max'};
+       $scale = $priomap->{'buildhours'}->{'scale'} || 1;
+        $pkg->{'calprio'} -= $bhours * $scale;
+
        $pkg->{'calprio'} += $pkg->{'permbuildpri'} if  $pkg->{'permbuildpri'};
        $pkg->{'calprio'} += $pkg->{'buildpri'} if  $pkg->{'buildpri'};
 
        $pkg->{'calprio'} += $pkg->{'permbuildpri'} if  $pkg->{'permbuildpri'};
        $pkg->{'calprio'} += $pkg->{'buildpri'} if  $pkg->{'buildpri'};
 
@@ -1958,7 +1087,9 @@ sub print_format {
     my $printfmt = shift;
     my $pkg = shift;
     my $var = shift;
     my $printfmt = shift;
     my $pkg = shift;
     my $var = shift;
+
 =pod
 =pod
+
 Within an format string, the following values are allowed (need to be preceded by %).
 This can be combined to e.g.
 wanna-build --format='wanna-build -A %a --give-back %p_%v' -A mipsel --list=failed
 Within an format string, the following values are allowed (need to be preceded by %).
 This can be combined to e.g.
 wanna-build --format='wanna-build -A %a --give-back %p_%v' -A mipsel --list=failed
@@ -1992,6 +1123,7 @@ X the string normally between [], e.g. optional:out-of-date:calprio{61}:days{25}
 Text could contain further %. To start with !, use %!
 
 =cut
 Text could contain further %. To start with !, use %!
 
 =cut
+
     return stringf($printfmt, (
         'p' => make_fmt( $pkg->{'package'}, $pkg, $var),
         'a' => make_fmt( $arch, $pkg, $var),
     return stringf($printfmt, (
         'p' => make_fmt( $pkg->{'package'}, $pkg, $var),
         'a' => make_fmt( $arch, $pkg, $var),
@@ -2001,9 +1133,10 @@ Text could contain further %. To start with !, use %!
         'S' => make_fmt( $pkg->{'state'}, $pkg, $var),
         'u' => make_fmt( $pkg->{'builder'}, $pkg, $var),
         'X' => make_fmt( sub {
         'S' => make_fmt( $pkg->{'state'}, $pkg, $var),
         'u' => make_fmt( $pkg->{'builder'}, $pkg, $var),
         'X' => make_fmt( sub {
+            no warnings;
             my $c = "$pkg->{'priority'}:$pkg->{'notes'}";
             my $c = "$pkg->{'priority'}:$pkg->{'notes'}";
-            $c .= ":PREV-FAILED" if $pkg->{'previous_state'} =~ /^Failed/;
-            $c .= ":bp{" . $pkg->{'buildpri'} . "}" if defined $pkg->{'buildpri'};
+            $c .= ":PREV-FAILED" if $pkg->{'previous_state'} && $pkg->{'previous_state'} =~ /^Failed/;
+            $c .= ":bp{" . (($pkg->{'buildpri'}//0)+($pkg->{'permbuildpri'}//0)) . "}" if (($pkg->{'buildpri'}//0)+($pkg->{'permbuildpri'}//0));
             $c .= ":binNMU{" . $pkg->{'binary_nmu_version'} . "}" if defined $pkg->{'binary_nmu_version'};
             $c .= ":calprio{". $pkg->{'calprio'}."}";
             $c .= ":days{". $pkg->{'state_days'}."}";
             $c .= ":binNMU{" . $pkg->{'binary_nmu_version'} . "}" if defined $pkg->{'binary_nmu_version'};
             $c .= ":calprio{". $pkg->{'calprio'}."}";
             $c .= ":days{". $pkg->{'state_days'}."}";
@@ -2030,36 +1163,43 @@ Text could contain further %. To start with !, use %!
         'O' => make_fmt( sub { return seconds2time ( $pkg->{'successtime'}); }, $pkg, $var),
         'q' => make_fmt( $pkg->{'anytime'}, $pkg, $var),
         'Q' => make_fmt( sub { return seconds2time ( $pkg->{'anytime'}); }, $pkg, $var),
         'O' => make_fmt( sub { return seconds2time ( $pkg->{'successtime'}); }, $pkg, $var),
         'q' => make_fmt( $pkg->{'anytime'}, $pkg, $var),
         'Q' => make_fmt( sub { return seconds2time ( $pkg->{'anytime'}); }, $pkg, $var),
-        'r' => make_fmt( sub { return max($pkg->{'successtime'}, $pkg->{'anytime'}); }, $pkg, $var),
-        'R' => make_fmt( sub { return seconds2time ( max($pkg->{'successtime'}, $pkg->{'anytime'})); }, $pkg, $var),
+        'r' => make_fmt( sub { my $c = max($pkg->{'successtime'}//0, $pkg->{'anytime'}//0); return $c if $c; return; }, $pkg, $var),
+        'R' => make_fmt( sub { return seconds2time ( max($pkg->{'successtime'}//0, $pkg->{'anytime'}//0)); }, $pkg, $var),
     ));
 }
 
 sub list_packages {
        my $state = shift;
     ));
 }
 
 sub list_packages {
        my $state = shift;
-       my( $name, $pkg, @list );
+       my @list;
        my $cnt = 0;
        my %scnt;
        my $ctime = time;
 
        my $cnt = 0;
        my %scnt;
        my $ctime = time;
 
-       my $db = get_all_source_info(state => $state, user => $user, category => $category, list_min_age => $list_min_age);
-       foreach $name (keys %$db) {
-               next if $name =~ /^_/;
-               push @list, calculate_prio($db->{$name});
+       my $db = get_all_source_info(state => $state, user => $user, list_min_age => $list_min_age, multisuite => 1);
+       foreach my $key (keys %$db) {
+               next if $key =~ /^_/;
+               push @list, calculate_prio($db->{$key});
        }
 
         # filter components
         @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 components
         @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
 
         # first adjust ownprintformat, then set printformat accordingly
-        $printformat ||= $yamlmap->{"format"}{$ownprintformat};
+        $printformat ||= $yamlmap->{"format"}{$ownprintformat} if $ownprintformat;
         $printformat ||= $yamlmap->{"format"}{"default"}{$state};
         $printformat ||= $yamlmap->{"format"}{"default"}{"default"};
         $printformat ||= $yamlmap->{"format"}{"default"}{$state};
         $printformat ||= $yamlmap->{"format"}{"default"}{"default"};
-        undef $printformat if ($ownprintformat eq 'none');
+        undef $printformat if ($ownprintformat && $ownprintformat eq 'none');
 
 
-       foreach $pkg (sort sort_list_func @list) {
+       foreach my $pkg (sort sort_list_func @list) {
+                no warnings;
                 if ($printformat) {
                     print print_format($printformat, $pkg, {'cnt' => $cnt, 'scnt' => \%scnt})."\n";
                    ++$cnt;
                 if ($printformat) {
                     print print_format($printformat, $pkg, {'cnt' => $cnt, 'scnt' => \%scnt})."\n";
                    ++$cnt;
@@ -2073,9 +1213,6 @@ sub list_packages {
                        if $pkg->{'state'} ne "Needs-Build";
                print print_format(" [%X]\n", $pkg, {});
                print "  Reasons for failing:\n",
                        if $pkg->{'state'} ne "Needs-Build";
                print print_format(" [%X]\n", $pkg, {});
                print "  Reasons for failing:\n",
-                         "    [Category: ",
-                         defined $pkg->{'failed_category'} ? $pkg->{'failed_category'} : "none",
-                         "]\n    ",
                          join("\n    ",split("\n",$pkg->{'failed'})), "\n"
                        if $pkg->{'state'} =~ /^Failed/;
                print "  Dependencies: $pkg->{'depends'}\n"
                          join("\n    ",split("\n",$pkg->{'failed'})), "\n"
                        if $pkg->{'state'} =~ /^Failed/;
                print "  Dependencies: $pkg->{'depends'}\n"
@@ -2110,7 +1247,7 @@ sub info_packages {
        my( $name, $pkg, $key, $dist );
        my @firstkeys = qw(package version builder state section priority
                                           installed_version previous_state state_change);
        my( $name, $pkg, $key, $dist );
        my @firstkeys = qw(package version builder state section priority
                                           installed_version previous_state state_change);
-       my @dists = $info_all_dists ? keys %conf::distributions : ($distribution);
+       my @dists = $info_all_dists ? keys %distributions : ($distribution);
        my %beautykeys = ( 'package' => 'Package', 'version' => 'Version', 'builder' => 'Builder',
                'state' => 'State', 'section' => 'Section', 'priority' => 'Priority',
                'installed_version' => 'Installed-Version', 'previous_state' => 'Previous-State',
        my %beautykeys = ( 'package' => 'Package', 'version' => 'Version', 'builder' => 'Builder',
                'state' => 'State', 'section' => 'Section', 'priority' => 'Priority',
                'installed_version' => 'Installed-Version', 'previous_state' => 'Previous-State',
@@ -2118,14 +1255,15 @@ sub info_packages {
                'bd_problem' => 'BD-Problem', 
                'binary_nmu_changelog' => 'Binary-NMU-Changelog', 'binary_nmu_version' => 'Binary-NMU-Version',
                'buildpri' => 'BuildPri', 'depends' => 'Depends', 'failed' => 'Failed',
                'bd_problem' => 'BD-Problem', 
                'binary_nmu_changelog' => 'Binary-NMU-Changelog', 'binary_nmu_version' => 'Binary-NMU-Version',
                'buildpri' => 'BuildPri', 'depends' => 'Depends', 'failed' => 'Failed',
-               'failed_category' => 'Failed-Category', 'notes' => 'Notes',
+               'notes' => 'Notes',
                'distribution' => 'Distribution', 'old_failed' => 'Old-Failed',
                'permbuildpri' => 'PermBuildPri', 'rel' => 'Rel',
                'distribution' => 'Distribution', 'old_failed' => 'Old-Failed',
                'permbuildpri' => 'PermBuildPri', 'rel' => 'Rel',
-               'calprio' => 'CalculatedPri', 'state_days' => 'State-Days',
+               'calprio' => 'CalculatedPri', 'state_days' => 'State-Days', 'state_time' => 'State-Time',
                 'successtime' => 'Success-build-time',
                 'anytime' => 'Build-time',
                 'extra_depends' => 'Extra-Dependencies',
                 'extra_conflicts' => 'Extra-Conflicts',
                 'successtime' => 'Success-build-time',
                 'anytime' => 'Build-time',
                 'extra_depends' => 'Extra-Dependencies',
                 'extra_conflicts' => 'Extra-Conflicts',
+                'build_arch_all' => 'Build-Arch-All',
                         );
        
        foreach $name (@_) {
                         );
        
        foreach $name (@_) {
@@ -2167,6 +1305,7 @@ sub info_packages {
 }
 
 sub forget_packages {
 }
 
 sub forget_packages {
+        no warnings;
        my( $name, $pkg, $key, $data );
        
        foreach $name (@_) {
        my( $name, $pkg, $key, $data );
        
        foreach $name (@_) {
@@ -2206,11 +1345,11 @@ sub read_db {
        my $file = shift;
 
        print "Reading ASCII database from $file..." if $verbose >= 1;
        my $file = shift;
 
        print "Reading ASCII database from $file..." if $verbose >= 1;
-       open( F, "<$file" ) or
+       open( my $fh, '<', $file ) or
                die "Can't open database $file: $!\n";
 
        local($/) = ""; # read in paragraph mode
                die "Can't open database $file: $!\n";
 
        local($/) = ""; # read in paragraph mode
-       while( <F> ) {
+       while( <$fh> ) {
                my( %thispkg, $name );
                s/[\s\n]+$//;
                s/\n[ \t]+/\376\377/g;  # fix continuation lines
                my( %thispkg, $name );
                s/[\s\n]+$//;
                s/\n[ \t]+/\376\377/g;  # fix continuation lines
@@ -2238,7 +1377,7 @@ sub read_db {
                                or die $dbh->errstr;
                 }
        }
                                or die $dbh->errstr;
                 }
        }
-       close( F );
+       close( $fh );
        print "done\n" if $verbose >= 1;
 }
 
        print "done\n" if $verbose >= 1;
 }
 
@@ -2269,7 +1408,7 @@ sub check_entry {
        die "Bad state $pkg->{'state'} of package $pkg->{Package}\n"
                if !isin( $pkg->{'state'},
                                  qw(Needs-Build Building Built Build-Attempted Uploaded Installed Dep-Wait Dep-Wait-Removed
        die "Bad state $pkg->{'state'} of package $pkg->{Package}\n"
                if !isin( $pkg->{'state'},
                                  qw(Needs-Build Building Built Build-Attempted Uploaded Installed Dep-Wait Dep-Wait-Removed
-                                        Failed Failed-Removed Not-For-Us BD-Uninstallable
+                                        Failed Failed-Removed Not-For-Us BD-Uninstallable Auto-Not-For-Us
                                         ) );
 }
 
                                         ) );
 }
 
@@ -2278,7 +1417,7 @@ sub export_db {
        my($name,$pkg,$key);
 
        print "Writing ASCII database to $file..." if $verbose >= 1;
        my($name,$pkg,$key);
 
        print "Writing ASCII database to $file..." if $verbose >= 1;
-       open( F, ">$file" ) or
+       open( my $fh, '>', $file ) or
                die "Can't open export $file: $!\n";
 
         my $db = get_all_source_info();
                die "Can't open export $file: $!\n";
 
         my $db = get_all_source_info();
@@ -2291,11 +1430,11 @@ sub export_db {
                        $val =~ s/\n*$//;
                        $val =~ s/^/ /mg;
                        $val =~ s/^ +$/ ./mg;
                        $val =~ s/\n*$//;
                        $val =~ s/^/ /mg;
                        $val =~ s/^ +$/ ./mg;
-                       print F "$key: $val\n";
+                       print $fh "$key: $val\n";
                }
                }
-               print F "\n";
+               print $fh "\n";
        }
        }
-       close( F );
+       close( $fh );
        print "done\n" if $verbose >= 1;
 }
 
        print "done\n" if $verbose >= 1;
 }
 
@@ -2305,6 +1444,7 @@ sub change_state {
        my $newstate = shift;
        my $state = \$pkg->{'state'};
        
        my $newstate = shift;
        my $state = \$pkg->{'state'};
        
+        $newstate = 'Needs-Build' if $newstate eq 'BD-Uninstallable' && $distributions{$distribution}{noadw};
        return if defined($$state) and $$state eq $newstate;
         $pkg->{'previous_state'} = $$state if defined($$state);
        $pkg->{'state_change'} = $curr_date;
        return if defined($$state) and $$state eq $newstate;
         $pkg->{'previous_state'} = $$state if defined($$state);
        $pkg->{'state_change'} = $curr_date;
@@ -2313,14 +1453,12 @@ sub change_state {
        if (defined($$state) and $$state eq 'Failed') {
                $pkg->{'old_failed'} =
                        "-"x20 . " $pkg->{'version'} " . "-"x20 . "\n" .
        if (defined($$state) and $$state eq 'Failed') {
                $pkg->{'old_failed'} =
                        "-"x20 . " $pkg->{'version'} " . "-"x20 . "\n" .
-                       $pkg->{'failed'} . "\n" .
-                       $pkg->{'old_failed'};
+                       ($pkg->{'failed'} // ""). "\n" .
+                       ($pkg->{'old_failed'} // "");
                delete $pkg->{'failed'};
                delete $pkg->{'failed'};
-               delete $pkg->{'failed_category'};
-       }
-       if (defined($$state) and $$state eq 'BD-Uninstallable') {
-               delete $pkg->{'bd_problem'};
        }
        }
+       delete $pkg->{'bd_problem'} if ($$state//"") eq 'BD-Uninstallable';
+        $pkg->{'bd_problem'} = "Installability of build dependencies not tested yet" if $newstate eq 'BD-Uninstallable';
        $$state = $newstate;
 }
 
        $$state = $newstate;
 }
 
@@ -2372,13 +1510,13 @@ sub send_mail {
        $to .= '@' . $domain if $to !~ /\@/;
        $text =~ s/^\.$/../mg;
        local $SIG{'PIPE'} = 'IGNORE';
        $to .= '@' . $domain if $to !~ /\@/;
        $text =~ s/^\.$/../mg;
        local $SIG{'PIPE'} = 'IGNORE';
-       open( PIPE,  "| $conf::mailprog -oem $to" )
+       open( my $pipe,  '|-', "$conf::mailprog -oem $to" )
                or die "Can't open pipe to $conf::mailprog: $!\n";
        chomp $text;
                or die "Can't open pipe to $conf::mailprog: $!\n";
        chomp $text;
-       print PIPE "From: $from\n";
-       print PIPE "Subject: $subject\n\n";
-       print PIPE "$text\n";
-       close( PIPE );
+       print $pipe "From: $from\n";
+       print $pipe "Subject: $subject\n\n";
+       print $pipe "$text\n";
+       close( $pipe );
 }
 
 # for parsing input to dep-wait
 }
 
 # for parsing input to dep-wait
@@ -2387,6 +1525,7 @@ sub parse_deplist {
     my $verify = shift;
     my %result;
     
     my $verify = shift;
     my %result;
     
+    return $verify ? 0 : \%result unless $deps;
     foreach (split( /\s*,\s*/, $deps )) {
         if ($verify) {
             # verification requires > starting prompts, no | crap
     foreach (split( /\s*,\s*/, $deps )) {
         if ($verify) {
             # verification requires > starting prompts, no | crap
@@ -2433,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 {
@@ -2452,8 +1591,8 @@ sub wb_edos_builddebcheck {
 
     my $packagearch="";
     foreach my $packagefile (@$packagefiles) {
 
     my $packagearch="";
     foreach my $packagefile (@$packagefiles) {
-        open(P,$packagefile);
-        while (<P>) {
+        open(my $fh,'<', $packagefile);
+        while (<$fh>) {
             next unless /^Architecture/;
             next if /^Architecture:\s*all/;
             /Architecture:\s*([^\s]*)/;
             next unless /^Architecture/;
             next if /^Architecture:\s*all/;
             /Architecture:\s*([^\s]*)/;
@@ -2463,7 +1602,7 @@ sub wb_edos_builddebcheck {
                return "Package file contains different architectures: $packagearch, $1";
             }
         }
                return "Package file contains different architectures: $packagearch, $1";
             }
         }
-        close P;
+        close $fh;
     }
 
     if ( $architecture eq "" ) {
     }
 
     if ( $architecture eq "" ) {
@@ -2480,15 +1619,15 @@ sub wb_edos_builddebcheck {
         }   
     }
 
         }   
     }
 
-    print "calling: edos-debcheck $edosoptions < $sourcesfile ".join('', map {" '-base FILE' ".$_ } @$packagefiles)."\n";
-    open(RESULT, '-|',
-        "edos-debcheck $edosoptions < $sourcesfile ".join('', map {" '-base FILE' ".$_ } @$packagefiles));
+    print "calling: edos-debcheck $edosoptions < $sourcesfile ".join('', map {" -I ".$_ } @$packagefiles)."\n";
+    open(my $result_cmd, '-|',
+        "edos-debcheck $edosoptions < $sourcesfile ".join('', map {" -I ".$_ } @$packagefiles));
 
     my $explanation="";
     my $result={};
     my $binpkg="";
 
 
     my $explanation="";
     my $result={};
     my $binpkg="";
 
-    while (<RESULT>) {
+    while (<$result_cmd>) {
 # source---pulseaudio (= 0.9.15-4.1~bpo50+1): FAILED
 #   source---pulseaudio (= 0.9.15-4.1~bpo50+1) depends on missing:
 #   - libltdl-dev (>= 2.2.6a-2)
 # source---pulseaudio (= 0.9.15-4.1~bpo50+1): FAILED
 #   source---pulseaudio (= 0.9.15-4.1~bpo50+1) depends on missing:
 #   - libltdl-dev (>= 2.2.6a-2)
@@ -2517,7 +1656,7 @@ sub wb_edos_builddebcheck {
         }
     }
 
         }
     }
 
-    close RESULT;
+    close $result_cmd;
     $result->{$binpkg} = $explanation if $binpkg;
     return $result;
 
     $result->{$binpkg} = $explanation if $binpkg;
     return $result;
 
@@ -2529,24 +1668,27 @@ sub call_edos_depcheck {
     my $args = shift;
     my $srcs = $args->{'srcs'};
     my $key;
     my $args = shift;
     my $srcs = $args->{'srcs'};
     my $key;
-    
-    return if defined ($conf::distributions{$distribution}{noadw}) && not defined $args->{'depwait'};
+   
+    # 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
     # something in needs-build have uninstallable deps
     # We also check everything in bd-uninstallable, as any new upload could
     # make that work again
     my (%interesting_packages, %interesting_packages_depwait);
 
     # We need to check all of needs-build, as any new upload could make
     # something in needs-build have uninstallable deps
     # 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};
     foreach $key (keys %$db) {
        my $pkg = $db->{$key};
-        if (defined $pkg and isin($pkg->{'state'}, qw/Needs-Build BD-Uninstallable/) and not defined ($conf::distributions{$distribution}{noadw})) {
-               $interesting_packages{$key} = undef;
+        if (defined $pkg and isin($pkg->{'state'}, qw/Needs-Build BD-Uninstallable/) and not defined ($distributions{$distribution}{noadw})) {
+               $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_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 ($conf::distributions{$distribution}{noadw});
+               $interesting_packages{$key} = undef unless defined ($distributions{$distribution}{noadw});
        }
     }
     
        }
     }
     
@@ -2564,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";
@@ -2616,10 +1758,11 @@ 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');
-       my $problemchange = $interesting_packages{$key} ne $pkg->{'bd_problem'};
+       my $problemchange = ($interesting_packages{$key}//"") ne ($pkg->{'bd_problem'}//"");
        if ($change) {
            if (defined $interesting_packages{$key}) {
                    change_state( \$pkg, 'BD-Uninstallable' );
        if ($change) {
            if (defined $interesting_packages{$key}) {
                    change_state( \$pkg, 'BD-Uninstallable' );
@@ -2648,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;
@@ -2667,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
@@ -2687,14 +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.
-    --merge-quinn: Merge quinn-diff output into database.
-    --merge-packages: Merge Packages files into database.
-    --pretend-avail: Pretend that given packages are available now and give
-        free packages waiting for them
+    --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)
@@ -2706,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;
 }
@@ -2747,10 +1903,10 @@ sub pkg_history_table_name {
 sub get_readonly_source_info {
        my $name = shift;
        # SELECT FLOOR(EXTRACT('epoch' FROM age(localtimestamp, '2010-01-22  23:45')) / 86400) -- change to that?
 sub get_readonly_source_info {
        my $name = shift;
        # SELECT FLOOR(EXTRACT('epoch' FROM age(localtimestamp, '2010-01-22  23:45')) / 86400) -- change to that?
-        my $q = "SELECT rel, priority, state_change, permbuildpri, section, buildpri, failed, state, binary_nmu_changelog, bd_problem, version, package, distribution, installed_version, notes, failed_category, builder, old_failed, previous_state, binary_nmu_version, depends, extract(days from date_trunc('days', now() - state_change)) as state_days"
+        my $q = "SELECT rel, priority, state_change, permbuildpri, section, buildpri, failed, state, binary_nmu_changelog, bd_problem, version, package, distribution, installed_version, notes, builder, old_failed, previous_state, binary_nmu_version, depends, extract(days from date_trunc('days', now() - state_change)) as state_days, floor(extract(epoch from now()) - extract(epoch from state_change)) as state_time"
             . ", (SELECT max(build_time) FROM ".pkg_history_table_name()." WHERE pkg_history.package = packages.package AND pkg_history.distribution = packages.distribution AND result = 'successful') AS successtime"
             . ", (SELECT max(build_time) FROM ".pkg_history_table_name()." WHERE pkg_history.package = packages.package AND pkg_history.distribution = packages.distribution ) AS anytime"
             . ", (SELECT max(build_time) FROM ".pkg_history_table_name()." WHERE pkg_history.package = packages.package AND pkg_history.distribution = packages.distribution AND result = 'successful') AS successtime"
             . ", (SELECT max(build_time) FROM ".pkg_history_table_name()." WHERE pkg_history.package = packages.package AND pkg_history.distribution = packages.distribution ) AS anytime"
-            . ", extra_depends, extra_conflicts"
+            . ", extra_depends, extra_conflicts, build_arch_all"
             . " FROM " .  table_name()
             . ' WHERE package = ? AND distribution = ?';
        my $pkg = $dbh->selectrow_hashref( $q,
             . " FROM " .  table_name()
             . ' WHERE package = ? AND distribution = ?';
        my $pkg = $dbh->selectrow_hashref( $q,
@@ -2761,9 +1917,9 @@ sub get_readonly_source_info {
 sub get_source_info {
        my $name = shift;
         return get_readonly_source_info($name) if $simulate;
 sub get_source_info {
        my $name = shift;
         return get_readonly_source_info($name) if $simulate;
-       my $pkg = $dbh->selectrow_hashref('SELECT *, extract(days from date_trunc(\'days\', now() - state_change)) as state_days FROM ' . 
-               table_name() . ' WHERE package = ? AND distribution = ?' .
-               ' FOR UPDATE',
+       lock_table();
+       my $pkg = $dbh->selectrow_hashref('SELECT *, extract(days from date_trunc(\'days\', now() - state_change)) as state_days, floor(extract(epoch from now()) - extract(epoch from state_change)) as state_time FROM ' . 
+               table_name() . ' WHERE package = ? AND distribution = ?',
                undef, $name, $distribution);
        return $pkg;
 }
                undef, $name, $distribution);
        return $pkg;
 }
@@ -2771,7 +1927,7 @@ sub get_source_info {
 sub get_all_source_info {
        my %options = @_;
 
 sub get_all_source_info {
        my %options = @_;
 
-        my $q = "SELECT rel, priority, state_change, permbuildpri, section, buildpri, failed, state, binary_nmu_changelog, bd_problem, version, package, distribution, installed_version, notes, failed_category, builder, old_failed, previous_state, binary_nmu_version, depends, extract(days from date_trunc('days', now() - state_change)) as state_days"
+        my $q = "SELECT rel, priority, state_change, permbuildpri, section, buildpri, failed, state, binary_nmu_changelog, bd_problem, version, package, distribution, installed_version, notes, builder, old_failed, previous_state, binary_nmu_version, depends, extract(days from date_trunc('days', now() - state_change)) as state_days, floor(extract(epoch from now()) - extract(epoch from state_change)) as state_time"
 #            . ", (SELECT max(build_time) FROM ".pkg_history_table_name()." WHERE pkg_history.package = packages.package AND pkg_history.distribution = packages.distribution AND result = 'successful') AS successtime"
 #            . ", (SELECT max(build_time) FROM ".pkg_history_table_name()." WHERE pkg_history.package = packages.package AND pkg_history.distribution = packages.distribution ) AS anytime"
             . ", successtime.build_time as successtime, anytime.build_time as anytime, extra_depends, extra_conflicts"
 #            . ", (SELECT max(build_time) FROM ".pkg_history_table_name()." WHERE pkg_history.package = packages.package AND pkg_history.distribution = packages.distribution AND result = 'successful') AS successtime"
 #            . ", (SELECT max(build_time) FROM ".pkg_history_table_name()." WHERE pkg_history.package = packages.package AND pkg_history.distribution = packages.distribution ) AS anytime"
             . ", successtime.build_time as successtime, anytime.build_time as anytime, extra_depends, extra_conflicts"
@@ -2802,26 +1958,54 @@ sub get_all_source_info {
                push @args, $options{user};
        }
 
                push @args, $options{user};
        }
 
-       if ($options{category}) {
-               $q .= ' AND failed_category <> ? AND upper(state) = ? ';
-               push @args, $options{category};
-               push @args, "FAILED";
-       }
-
-       if ($options{list_min_age} > 0) {
+       if ($options{list_min_age} && $options{list_min_age} > 0) {
                $q .= ' AND age(state_change) > ? ';
                push @args, $options{list_min_age} . " days";
        }
 
                $q .= ' AND age(state_change) > ? ';
                push @args, $options{list_min_age} . " days";
        }
 
-       if ($options{list_min_age} < 0) {
+       if ($options{list_min_age} && $options{list_min_age} < 0) {
                $q .= ' AND age(state_change) < ? ';
                push @args, -$options{list_min_age} . " days";
        }
 
                $q .= ' AND age(state_change) < ? ';
                push @args, -$options{list_min_age} . " days";
        }
 
-       my $db = $dbh->selectall_hashref($q, 'package', undef, @args);
+       my $db;
+        if (($options{multisuite}) && (!$distribution || $distribution =~ / /)) {
+            # return packages in multiple suites - only for those functions marked as clean for that api change
+            $db = $dbh->selectall_hashref($q, [qw<package distribution>], undef, @args);
+            my $dbk = {};
+            foreach my $p ( keys %$db ) {
+                foreach my $d (keys %{$db->{$p}}) {
+                    $dbk->{"$p/$d"} = $db->{$p}->{$d};
+                }
+            }
+            $db = $dbk;
+        } else {
+            $db = $dbh->selectall_hashref($q, [qw<package>], undef, @args);
+        }
        return $db;
 }
 
        return $db;
 }
 
+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');
+        if ($args->{suite}) {
+            print $rows->{$args->{'suite'}}->{'architectures'}."\n";
+        } else {
+           foreach my $name (keys %$rows) {
+               print $name.': '.$rows->{$name}->{'architectures'}."\n";
+           }
+        }
+}
+
+sub show_distribution_aliases {
+       foreach my $alias (keys %distribution_aliases) {
+               print $alias.': '.$distribution_aliases{$alias}."\n";
+       }
+}
+
 sub update_source_info {
        my $pkg = shift;
         $pkg->{'extra_depends'} = $extra_depends if defined $extra_depends;
 sub update_source_info {
        my $pkg = shift;
         $pkg->{'extra_depends'} = $extra_depends if defined $extra_depends;
@@ -2851,7 +2035,6 @@ sub update_source_info {
                        'old_failed = ?, ' .
                        'binary_nmu_version = ?, ' .
                        'binary_nmu_changelog = ?, ' .
                        'old_failed = ?, ' .
                        'binary_nmu_version = ?, ' .
                        'binary_nmu_changelog = ?, ' .
-                       'failed_category = ?, ' .
                        'permbuildpri = ?, ' .
                        'buildpri = ?, ' .
                        'depends = ?, ' .
                        'permbuildpri = ?, ' .
                        'buildpri = ?, ' .
                        'depends = ?, ' .
@@ -2873,7 +2056,6 @@ sub update_source_info {
                $pkg->{'old_failed'},
                $pkg->{'binary_nmu_version'},
                $pkg->{'binary_nmu_changelog'},
                $pkg->{'old_failed'},
                $pkg->{'binary_nmu_version'},
                $pkg->{'binary_nmu_changelog'},
-               $pkg->{'failed_category'},
                $pkg->{'permbuildpri'},
                $pkg->{'buildpri'},
                $pkg->{'depends'},
                $pkg->{'permbuildpri'},
                $pkg->{'buildpri'},
                $pkg->{'depends'},
@@ -2930,14 +2112,15 @@ sub add_user_info {
                or die $dbh->errstr;
 }
 
                or die $dbh->errstr;
 }
 
-sub lock_table()
-{
+sub lock_table {
         return if $simulate;
         return if $simulate;
-       $dbh->do('LOCK TABLE ' . table_name() .
-               ' IN EXCLUSIVE MODE', undef) or die $dbh->errstr;
+       $q = 'SELECT 1 AS result FROM public.locks' .
+            ' WHERE architecture = ? AND distribution = ? FOR UPDATE';
+       my $result = $dbh->selectrow_hashref($q, undef, $arch, $distribution) or die $dbh->errstr;
+       die unless $result->{'result'} == 1;
 }
 
 }
 
-sub parse_argv() {
+sub parse_argv {
 # parts the array $_[0] and $_[1] and returns the sub-array (modifies the original one)
     my @ret = ();
     my $args = shift;
 # parts the array $_[0] and $_[1] and returns the sub-array (modifies the original one)
     my @ret = ();
     my $args = shift;
@@ -2949,7 +2132,7 @@ sub parse_argv() {
     return @ret;
 }
 
     return @ret;
 }
 
-sub parse_all_v3() {
+sub parse_all_v3 {
     my $srcs = shift;
     my $vars = shift;
     my $db = get_all_source_info();
     my $srcs = shift;
     my $vars = shift;
     my $db = get_all_source_info();
@@ -2959,81 +2142,82 @@ sub parse_all_v3() {
     foreach my $name (keys %$srcs) {
         next if $name eq '_binary';
 
     foreach my $name (keys %$srcs) {
         next if $name eq '_binary';
 
-        # state = installed, out-of-date, uncompiled, not-for-us
+        # state = installed, out-of-date, uncompiled, packages-arch-specific, overwritten-by-arch-all, arch-not-in-arch-list, arch-all-only
         my $pkgs = $srcs->{$name};
         my $pkgs = $srcs->{$name};
+        next if isin($pkgs->{'status'}, qw <arch-all-only>);
         my $pkg = $db->{$name};
 
         unless ($pkg) {
         my $pkg = $db->{$name};
 
         unless ($pkg) {
-            next SRCS if $pkgs->{'status'} eq 'not-for-us';
-            my $logstr = "merge-v3 $vars->{'time'} ".$name."_$pkgs->{'version'} ($vars->{'arch'}, $vars->{'suite'}):";
+            next SRCS if $pkgs->{'status'} eq 'packages-arch-specific';
+            my $logstr = sprintf("merge-v3 %s %s_%s (%s, %s):", $vars->{'time'}, $name, $pkgs->{'version'}, $vars->{'arch'}, $vars->{'suite'});
 
             # does at least one binary exist in the database and is more recent - if so, we're probably just outdated, ignore the source package
             for my $bin (@{$pkgs->{'binary'}}) {
 
             # does at least one binary exist in the database and is more recent - if so, we're probably just outdated, ignore the source package
             for my $bin (@{$pkgs->{'binary'}}) {
-                if ($binary->{$bin} and vercmp($pkgs->{'version'}, $binary->{$bin}->{'version'}) < 0) {
-                    print "$logstr skipped because binaries (assumed to be) overwritten\n" if $verbose || $simulate;
+                if ($binary->{$bin} and $binary->{$bin}->{'arch'} ne 'all' and vercmp($pkgs->{'version'}, $binary->{$bin}->{'version'}) < 0) {
+                   print Dumper($binary->{$bin}) . "\n";
+                    print "$logstr skipped because binaries (assumed to be) overwritten (" .
+                       $bin . ", " . $pkgs->{'version'} . " vs. " . $binary->{$bin}->{'version'} . ")\n" if $verbose || $simulate;
                     next SRCS;
                 }
             }
             $pkg->{'package'}  = $name;
         }
                     next SRCS;
                 }
             }
             $pkg->{'package'}  = $name;
         }
-        my $logstr = "merge-v3 $vars->{'time'} ".$name."_$pkgs->{'version'}".
+        $pkg->{'version'} ||= "";
+        $pkg->{'state'} ||= "";
+        my $logstr = sprintf("merge-v3 %s %s_%s", $vars->{'time'}, $name, $pkgs->{'version'}).
             ($pkgs->{'binnmu'} ? ";b".$pkgs->{'binnmu'} : "").
             ($pkgs->{'binnmu'} ? ";b".$pkgs->{'binnmu'} : "").
-            "($vars->{'arch'}, $vars->{'suite'}, previous: $pkg->{'version'}".
+            sprintf(" (%s, %s, previous: %s", $vars->{'arch'}, $vars->{'suite'}, $pkg->{'version'}//"").
             ($pkg->{'binary_nmu_version'} ? ";b".$pkg->{'binary_nmu_version'} : "").
             ($pkg->{'binary_nmu_version'} ? ";b".$pkg->{'binary_nmu_version'} : "").
-            ", $pkg->{'state'}):";
+            ", $pkg->{'state'}".($pkg->{'notes'} ? "/".$pkg->{'notes'} : "")."):";
 
 
-        if (isin($pkgs->{'status'}, qw (installed related)) && $pkg->{'binary_nmu_version'} && $pkgs->{'binnmu'} < int($pkg->{'binary_nmu_version'})) {
+        if (isin($pkgs->{'status'}, qw (installed related)) && $pkgs->{'version'} eq $pkg->{'version'} && ($pkgs->{'binnmu'}//0) < int($pkg->{'binary_nmu_version'}//0)) {
                 $pkgs->{'status'} = 'out-of-date';
         }
                 $pkgs->{'status'} = 'out-of-date';
         }
-        if (isin($pkgs->{'status'}, qw (installed related))) {
+        if (isin($pkgs->{'status'}, qw <installed related arch-not-in-arch-list packages-arch-specific overwritten-by-arch-all arch-all-only>)) {
             my $change = 0;
             my $change = 0;
-            if ($pkg->{'state'} ne 'Installed') {
-                change_state( \$pkg, 'Installed');
-                delete $pkg->{'depends'};
-                delete $pkg->{'extra_depends'};
-                delete $pkg->{'extra_conflicts'};
+            my $tstate = {'installed' => 'Installed', 'related' => 'Installed', 
+                'arch-not-in-arch-list' => 'Auto-Not-For-Us', 'packages-arch-specific' => 'Auto-Not-For-Us', 'overwritten-by-arch-all' => 'Auto-Not-For-Us', 'arch-all-only' => 'Auto-Not-For-Us',
+                }->{$pkgs->{'status'}};
+            next if isin( $pkg->{'state'}, qw<Not-For-Us Failed Failed-Removed Dep-Wait Dep-Wait-Removed>) && isin( $tstate, qw<Auto-Not-For-Us>);
+            # if the package is currently current, the status is Installed, not not-for-us
+            if ($pkg->{'state'} ne $tstate) {
+                change_state( \$pkg, $tstate);
+                if (isin( $tstate, qw<Installed>)) {
+                    delete $pkg->{'depends'};
+                    delete $pkg->{'extra_depends'};
+                    delete $pkg->{'extra_conflicts'};
+                }
                 $change++;
             }
             my $attrs = { 'version' => 'version', 'installed_version' => 'version', 'binary_nmu_version' => 'binnmu', 'section' => 'section', 'priority' => 'priority' };
             foreach my $k (keys %$attrs) {
                 $change++;
             }
             my $attrs = { 'version' => 'version', 'installed_version' => 'version', 'binary_nmu_version' => 'binnmu', 'section' => 'section', 'priority' => 'priority' };
             foreach my $k (keys %$attrs) {
-                if ($pkg->{$k} ne $pkgs->{$attrs->{$k}}) {
+                next if isin( $tstate, qw<Auto-Not-For-Us>) && isin( $k, qw<installed_version binary_nmu_version>);
+                if (($pkg->{$k}//"") ne ($pkgs->{$attrs->{$k}}//"")) {
                     $pkg->{$k} = $pkgs->{$attrs->{$k}};
                     $change++;
                 }
             }
                     $pkg->{$k} = $pkgs->{$attrs->{$k}};
                     $change++;
                 }
             }
-            if (isin($pkgs->{'status'}, qw (related)) and $pkg->{'notes'} ne "related") {
-                $pkg->{'notes'} = "related";
-                $change++;
+            if (isin($pkgs->{'status'}, qw <related packages-arch-specific overwritten-by-arch-all arch-not-in-arch-list arch-all-only>)) {
+                my $tnotes = $pkgs->{'status'};
+                if (($pkg->{'notes'}//"") ne $tnotes) {
+                    $pkg->{'notes'} = $tnotes;
+                    $change++;
+                }
             }
             if ($change) {
             }
             if ($change) {
-                print "$logstr set to installed/".$pkg->{'notes'}."\n" if $verbose || $simulate;
-                log_ta( $pkg, "--merge-v3: installed" ) unless $simulate;
+                print "$logstr set to $tstate/".($pkg->{'notes'}//"")."\n" if $verbose || $simulate;
+                log_ta( $pkg, "--merge-v3: $tstate" ) unless $simulate;
                 update_source_info($pkg) unless $simulate;
             }
             next;
         }
 
                 update_source_info($pkg) unless $simulate;
             }
             next;
         }
 
-        if ($pkgs->{'status'} eq 'not-for-us') {
-            next if isin( $pkg->{'state'}, qw(Not-For-Us Installed Failed-Removed));
-
-            if (isin( $pkg->{'state'}, qw(Failed Build-Attempted Built))) {
-                change_state( \$pkg, "Failed-Removed" );
-               log_ta( $pkg, "--merge-v3: Failed-Removed" ) unless $simulate;
-               update_source_info($pkg) unless $simulate;
-                print "$logstr (virtually) deleted from database\n" if $verbose || $simulate;
-                next;
-            }
-
-            print "$logstr should delete (not-for-us according to P-a-s)\n" if $verbose || $simulate || 1; # not implemented yet on purpose
-            next;
-        }
-
         # only uncompiled / out-of-date are left, so check if anything new
         if (!(isin($pkgs->{'status'}, qw (uncompiled out-of-date)))) {
             print "$logstr package in unknown state: $pkgs->{'status'}\n";
             next SRCS;
         }
         # only uncompiled / out-of-date are left, so check if anything new
         if (!(isin($pkgs->{'status'}, qw (uncompiled out-of-date)))) {
             print "$logstr package in unknown state: $pkgs->{'status'}\n";
             next SRCS;
         }
-        next if $pkgs->{'version'} eq $pkg->{'version'} and $pkgs->{'binnmu'} >= int($pkg->{'binary_nmu_version'});
+        next if $pkgs->{'version'} eq $pkg->{'version'} and $pkgs->{'binnmu'}//0 >= int($pkg->{'binary_nmu_version'}//0);
         next if $pkgs->{'version'} eq $pkg->{'version'} and !isin( $pkg->{'state'}, qw(Installed));
         next if isin( $pkg->{'state'}, qw(Not-For-Us Failed-Removed));
 
         next if $pkgs->{'version'} eq $pkg->{'version'} and !isin( $pkg->{'state'}, qw(Installed));
         next if isin( $pkg->{'state'}, qw(Not-For-Us Failed-Removed));
 
@@ -3059,6 +2243,7 @@ sub parse_all_v3() {
         delete $pkg->{'builder'};
         delete $pkg->{'binary_nmu_version'} unless $pkgs->{'binnmu'};
         delete $pkg->{'binary_nmu_changelog'} unless $pkgs->{'binnmu'};
         delete $pkg->{'builder'};
         delete $pkg->{'binary_nmu_version'} unless $pkgs->{'binnmu'};
         delete $pkg->{'binary_nmu_changelog'} unless $pkgs->{'binnmu'};
+        delete $pkg->{'buildpri'};
         log_ta( $pkg, "--merge-v3: needs-build" ) unless $simulate;
         update_source_info($pkg) unless $simulate;
         print "$logstr set to needs-builds\n" if $simulate || $verbose;
         log_ta( $pkg, "--merge-v3: needs-build" ) unless $simulate;
         update_source_info($pkg) unless $simulate;
         print "$logstr set to needs-builds\n" if $simulate || $verbose;