X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=bin%2Fwanna-build;h=18822532e8eaa04c00bd1de047147924cecf7af5;hb=c44876928c07326581b0b4588c4a5e62e892750c;hp=893b96a85543f2dfcc25b61e89b5aea4f9939148;hpb=aaf62bbb2d408fbd9a92e9f767c55752b5b9cb5d;p=wannabuild.git diff --git a/bin/wanna-build b/bin/wanna-build index 893b96a..1882253 100755 --- a/bin/wanna-build +++ b/bin/wanna-build @@ -3,6 +3,7 @@ # wanna-build: coordination script for Debian buildds # Copyright (C) 1998 Roman Hodek # Copyright (C) 2005-2008 Ryan Murray +# Copyright (C) 2010 Andreas Barth # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -40,6 +41,8 @@ use FileHandle; use File::Copy; use DBI; use lib '/org/wanna-build/bin'; +use lib '/org/wanna-build/lib'; +#use lib 'lib'; use WannaBuild; use YAML::Tiny; use Data::Dumper; @@ -47,6 +50,7 @@ use Hash::Merge qw ( merge ); use String::Format; use Date::Parse; use List::Util qw[max]; +use Dpkg::Version qw(vercmp); # TODO: change this for running with squeeze dpkg our ($verbose, $mail_logs, $list_order, $list_state, $curr_date, $op_mode, $user, $real_user, $distribution, @@ -58,6 +62,10 @@ our ($verbose, $mail_logs, $list_order, $list_state, $build_priority, %new_vers, $binNMUver, %merge_srcvers, %merge_binsrc, $printformat, $ownprintformat, $privmode ); +our $Pas = '/org/buildd.debian.org/etc/packages-arch-specific/Packages-arch-specific'; +our $simulate = 0; +our $simulate_edos = 0; +our $api = 0; # allow buildds to specify an different api # global vars $ENV{'PATH'} = "/bin:/usr/bin:/usr/local/bin:/org/wanna-build/bin/"; @@ -76,9 +84,6 @@ my %prognames = ( "uploaded-build" => "set-uploaded", "give-back-build" => "set-needs-build", "dep-wait-build" => "set-dep-wait", "forget-build" => "forget", - "merge-quinn" => "merge-quinn", - "merge-packages" => "merge-packages", - "merge-sources" => "merge-sources", "build-info" => "info" ); %short_category = ( u => "uploaded-fixed-pkg", @@ -103,6 +108,14 @@ elsif ($progname =~ /^list-(.*)$/) { 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 }, @@ -121,13 +134,14 @@ my %options = "dep-wait" => { mode => "set-dep-wait" }, forget => { mode => "forget" }, 'forget-user' => { mode => 'forget-user' }, - "merge-quinn" => { mode => "merge-quinn" }, - "merge-partial-quinn" => { mode => "merge-partial-quinn" }, - "merge-packages" => { mode => "merge-packages" }, - "merge-sources" => { mode => "merge-sources" }, + #"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-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" @@ -192,6 +206,7 @@ my %options = } }, "format" => { arg => \$printformat }, "own-format" => { arg => \$ownprintformat }, + "Pas" => { arg => \$Pas }, # special actions export => { arg => \$export_to, mode => "export" }, import => { arg => \$import_from, mode => "import" }, @@ -350,7 +365,7 @@ END { } my $schema_suffix = ''; -if (isin( $op_mode, qw(list info)) && $distribution !~ /security/ && !(not -t and $user =~ /-/) && !($privmode eq 'yes')) { +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'; @@ -455,7 +470,7 @@ sub process { parse_quinn_diff(0); @ARGV = ( $ARGS[2] ); my $srcs = parse_sources(1); - call_edos_depcheck( $ARGS[0], $srcs ); + call_edos_depcheck( {'arch' => $arch, 'pkgs' => ($ARGS[0]), 'srcs' => $srcs }); last SWITCH; }; /^merge-all-secondary/ && do { @@ -478,9 +493,37 @@ sub process { parse_quinn_diff(0); @ARGV = ( $ARGS[2] ); my $srcs = parse_sources(1); - call_edos_depcheck( $ARGS[3], $srcs ); + call_edos_depcheck( {'arch' => $arch, 'pkgs' => ($ARGS[3]), 'srcs' => $srcs }); last SWITCH; }; + /^merge-v3/ && do { + die "This operation is restricted to admin users\n" + if (defined @conf::admin_users and !isin( $real_user, @conf::admin_users) and !$simulate); + # call with installed-packages+ . installed-sources+ [ . available-for-build-packages* [ . consider-as-installed-source* ] ] + # in case available-for-build-packages is not specified, installed-packages are used + lock_table() unless $simulate; + my $replacemap = { '%ARCH%' => $arch, '%SUITE%' => $distribution }; + map { my $k = $_; grep { $k =~ s,$_,$replacemap->{$_}, } keys %{$replacemap}; $_ = $k; } @ARGV; + my @ipkgs = &parse_argv( \@ARGV, '.'); + my @isrcs = &parse_argv( \@ARGV, '.'); + my @bpkgs = &parse_argv( \@ARGV, '.'); + my @psrcs = &parse_argv( \@ARGV, '.'); + use WB::QD; + my $srcs = WB::QD::readsourcebins($arch, $Pas, \@isrcs, \@ipkgs); + if (@psrcs) { + my $psrcs = WB::QD::readsourcebins($arch, $Pas, \@psrcs, []); + foreach my $k (keys %$$psrcs) { + next if $$srcs->{$k}; + my $pkg = $$psrcs->{$k}; + $pkg->{'status'} = 'related'; + $$srcs->{$k} = $pkg; + } + } + parse_all_v3($$srcs, {'arch' => $arch, 'suite' => $distribution, 'time' => $curr_date}); + @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 @@ -500,7 +543,7 @@ sub process { die "Unexpected operation mode $op_mode\n"; } - if (not -t and $user =~ /-/) { + if (not -t and $user =~ /buildd-/) { my $userinfo = get_user_info($user); if (!defined $userinfo) { @@ -573,6 +616,7 @@ sub add_one_building { $ok = 1; my $pkg = get_source_info($name); + $pkg->{'version'} =~ s/\+b[0-9]+$//; if (defined($pkg)) { if ($pkg->{'state'} eq "Not-For-Us") { $ok = 0; @@ -685,6 +729,7 @@ sub add_one_building { } } if ($ok) { + if ($api < 1) { my $ok = 'ok'; if ($pkg->{'binary_nmu_version'}) { print "$name: Warning: needs binary NMU $pkg->{'binary_nmu_version'}\n" . @@ -695,16 +740,29 @@ sub add_one_building { if $pkg->{'previous_state'} =~ /^Failed/ || $pkg->{'state'} =~ /^Failed/; } + print "$name: $ok\n" if $verbose; + } else { + print "- $name:\n"; + print " - status: ok\n"; + if ($pkg->{'binary_nmu_version'}) { + print " - binNMU:\n"; + print " - version: $pkg->{'binary_nmu_version'}\n"; + print " - changelog: $pkg->{'binary_nmu_changelog'}\n"; + } + } change_state( \$pkg, 'Building' ); $pkg->{'package'} = $name; $pkg->{'version'} = $version; $pkg->{'builder'} = $user; log_ta( $pkg, "--take" ); update_source_info($pkg); - print "$name: $ok\n" if $verbose; } else { + if ($api < 1) { print "$name: NOT OK!\n $reason\n"; + } else { + print "- $name:\n - status: not ok\n - reason: \"$reason\"\n"; + } } } @@ -717,6 +775,7 @@ sub add_one_attempted { print "$name: not registered yet.\n"; return; } + $pkg->{'version'} =~ s/\+b[0-9]+$//; if (($pkg->{'state'} ne "Building") && ($pkg->{'state'} ne "Build-Attempted")) { print "$name: not taken for building (state is $pkg->{'state'}). ", @@ -749,6 +808,7 @@ sub add_one_built { print "$name: not registered yet.\n"; return; } + $pkg->{'version'} =~ s/\+b[0-9]+$//; if (($pkg->{'state'} ne "Building") && ($pkg->{'state'} ne "Build-Attempted")) { print "$name: not taken for building (state is $pkg->{'state'}). ", @@ -780,6 +840,7 @@ sub add_one_uploaded { print "$name: not registered yet.\n"; return; } + $pkg->{'version'} =~ s/\+b[0-9]+$//; if ($pkg->{'state'} eq "Uploaded" && pkg_version_eq($pkg,$version)) { @@ -829,6 +890,7 @@ sub add_one_failed { print "$name: not registered yet.\n"; return; } + $pkg->{'version'} =~ s/\+b[0-9]+$//; $state = $pkg->{'state'}; if ($state eq "Not-For-Us") { @@ -917,6 +979,7 @@ sub add_one_notforus { my $name = shift; my $version = shift; my $pkg = get_source_info($name); + $pkg->{'version'} =~ s/\+b[0-9]+$//; if ($pkg->{'state'} eq 'Not-For-Us') { # reset Not-For-Us state in case it's called twice; this is @@ -973,6 +1036,7 @@ sub add_one_needsbuild { print "$name: not registered; can't give back.\n"; return; } + $pkg->{'version'} =~ s/\+b[0-9]+$//; $state = $pkg->{'state'}; if ($state eq "BD-Uninstallable") { @@ -1050,6 +1114,7 @@ sub set_one_binnmu { print "$name: not registered; can't register for binNMU.\n"; return; } + $pkg->{'version'} =~ s/\+b[0-9]+$//; my $db_ver = $pkg->{'version'}; if (!version_eq($db_ver, $version)) { @@ -1125,6 +1190,7 @@ sub set_one_buildpri { print "$name: not registered; can't set priority.\n"; return; } + $pkg->{'version'} =~ s/\+b[0-9]+$//; $state = $pkg->{'state'}; if ($state eq "Not-For-Us") { @@ -1163,6 +1229,7 @@ sub add_one_depwait { print "$name: not registered yet.\n"; return; } + $pkg->{'version'} =~ s/\+b[0-9]+$//; $state = $pkg->{'state'}; if ($state eq "Dep-Wait") { @@ -1964,6 +2031,7 @@ sub list_packages { 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 =~ /^_/; + $db->{$name}->{'version'} =~ s/\+b[0-9]+$//; push @list, calculate_prio($db->{$name}); } @@ -2251,6 +2319,13 @@ sub log_ta { "changed from $prevstate to $pkg->{'state'} ". "by $real_user as $user"; + if ($simulate) { + printf "update transactions: %s %s %s %s %s %s %s %s\n", + $pkg->{'package'}, $distribution, + $pkg->{'version'}, $action, $prevstate, $pkg->{'state'}, + $real_user, $user; + return; + } $dbh->do('INSERT INTO ' . transactions_table_name() . ' (package, distribution, version, action, ' . ' prevstate, state, real_user, set_user, time) ' . @@ -2370,11 +2445,11 @@ sub wb_edos_builddebcheck { my $sourceprefix="source---"; my $architecture=$args->{'arch'}; my $edosoptions = "-failures -explain -quiet"; - my @packagefiles = $args->{'pkgs'}; + my $packagefiles = $args->{'pkgs'}; my $sourcesfile = $args->{'src'}; my $packagearch=""; - foreach my $packagefile (@packagefiles) { + foreach my $packagefile (@$packagefiles) { open(P,$packagefile); while (

) { next unless /^Architecture/; @@ -2403,9 +2478,9 @@ sub wb_edos_builddebcheck { } } - print "calling: edos-debcheck $edosoptions < $sourcesfile ".join('', map {" '-base FILE' ".$_ } @packagefiles); + print "calling: edos-debcheck $edosoptions < $sourcesfile ".join('', map {" '-base FILE' ".$_ } @$packagefiles)."\n"; open(RESULT, '-|', - "edos-debcheck $edosoptions < $sourcesfile ".join('', map {" '-base FILE' ".$_ } @packagefiles)); + "edos-debcheck $edosoptions < $sourcesfile ".join('', map {" '-base FILE' ".$_ } @$packagefiles)); my $explanation=""; my $result={}; @@ -2429,7 +2504,14 @@ sub wb_edos_builddebcheck { $result->{$binpkg} = $explanation if $binpkg; $explanation = ""; $binpkg = $1; - } # else something broken is happening + } elsif (/^(depwait---.*) \(.*\): FAILED/o) { + $result->{$binpkg} = $explanation if $binpkg; + $explanation = ""; + $binpkg = $1; + } else { # else something broken is happening + #print "ignoring $_\n"; + 1; + } } } @@ -2441,28 +2523,34 @@ sub wb_edos_builddebcheck { sub call_edos_depcheck { - my $packagesfile = shift; - my $srcs = shift; + return if $simulate_edos; + my $args = shift; + my $srcs = $args->{'srcs'}; my $key; - return if defined ($conf::distributions{$distribution}{noadw}); + return if defined ($conf::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; + my (%interesting_packages, %interesting_packages_depwait); my $db = get_all_source_info(); foreach $key (keys %$db) { my $pkg = $db->{$key}; - if (defined $pkg and isin($pkg->{'state'}, qw/Needs-Build BD-Uninstallable/)) { + 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/Dep-Wait/) and defined $args->{'depwait'}) { + $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}); + } } #print "I would look at these sources with edos-depcheck:\n"; #print join " ", keys %interesting_packages,"\n"; - return unless %interesting_packages; + return unless %interesting_packages || %interesting_packages_depwait; my $tmpfile_pattern = "/tmp/wanna-build-interesting-sources-$distribution.$$-XXXXX"; use File::Temp qw/ tempfile /; @@ -2474,24 +2562,43 @@ 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"; - my $t = &filterarch($srcs->{$key}{'dep'}, $arch); + my $t = &filterarch($srcs->{$key}{'dep'} || $srcs->{$key}{'depends'}, $arch); print $SOURCES "Depends: $t\n" if $t; - my $u = &filterarch($srcs->{$key}{'conf'}, $arch); + my $u = &filterarch($srcs->{$key}{'conf'} || $srcs->{$key}{'conflicts'}, $arch); print $SOURCES "Conflicts: $u\n" if $u; print $SOURCES "Architecture: all\n"; print $SOURCES "\n"; } + for my $key (keys %interesting_packages_depwait) { + my $pkg = $db->{$key}; + # we print the source files as binary ones (with "depwait---"-prefixed), + # so we can try if these "binary" packages are installable. + # If such a "binary" package is installable, the corresponding source package goes out of depwait + print $SOURCES "Package: depwait---$key\n"; + print $SOURCES "Version: $pkg->{'version'}\n"; + print $SOURCES "Depends: $pkg->{'depends'}\n"; + print $SOURCES "Architecture: all\n"; + print $SOURCES "\n"; + } close $SOURCES; - my $edosresults = wb_edos_builddebcheck({'arch' => $arch, 'pkgs' => [$packagesfile], 'src' => $tmpfile) + my $edosresults = wb_edos_builddebcheck({'arch' => $args->{'arch'}, 'pkgs' => $args->{'pkgs'}, 'src' => $tmpfile}); if (ref($edosresults) eq 'HASH') { - foreach my $key (keys %$edosresults) { + foreach my $key (grep { $_ !~ /^depwait---/ } keys %$edosresults) { if (exists $interesting_packages{$key}) { $interesting_packages{$key} = $edosresults->{$key}; } else { #print "TODO: edos reported a package we do not care about now\n" if $verbose; } } + foreach my $key (grep { $_ =~ /^depwait---/ } keys %$edosresults) { + $key =~ /^depwait---(.*)/ and $key = $1; + if (exists $interesting_packages_depwait{$key}) { + $interesting_packages_depwait{$key} = $edosresults->{"depwait---".$key}; + } else { + #print "TODO: edos reported a package we do not care about now\n" if $verbose; + } + } } else { # if $edosresults isn't an hash, then something went wrong and the string is the error message print "ERROR: Could not run wb-edos-builddebcheck. I am continuing, assuming\n" . @@ -2501,6 +2608,7 @@ sub call_edos_depcheck { unlink( $tmpfile ); for my $key (keys %interesting_packages) { + next if defined $interesting_packages_depwait{$key}; my $pkg = $db->{$key}; my $change = (defined $interesting_packages{$key} and $pkg->{'state'} eq 'Needs-Build') || @@ -2520,13 +2628,30 @@ sub call_edos_depcheck { } } if ($change) { - log_ta( $pkg, "--merge-all" ); - print "edos-builddebchange changed state of ${key}_$pkg->{'version'} to $pkg->{'state'}\n" if $verbose; + log_ta( $pkg, "--merge-all (edos)" ) unless $simulate; + print "edos-builddebchange changed state of ${key}_$pkg->{'version'} ($args->{'arch'}) to $pkg->{'state'}\n" if $verbose || $simulate; } if ($change || $problemchange) { - update_source_info($pkg); + update_source_info($pkg) unless $simulate; } } + + for my $key (keys %interesting_packages_depwait) { + if ($interesting_packages_depwait{$key}) { + print "dep-wait for $key ($args->{'arch'}) not fullfiled yet\n" if $verbose || $simulate; + 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' ); + } + 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; + } } sub usage { @@ -2628,6 +2753,7 @@ sub get_readonly_source_info { 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', @@ -2691,6 +2817,8 @@ sub get_all_source_info { sub update_source_info { my $pkg = shift; + print Dumper $pkg if $verbose and $simulate; + return if $simulate; my $pkg2 = get_source_info($pkg->{'package'}); if (! defined $pkg2) @@ -2743,6 +2871,7 @@ sub update_source_info { } sub add_source_info { + return if $simulate; my $pkg = shift; $dbh->do('INSERT INTO ' . table_name() . ' (package, distribution) values (?, ?)', @@ -2750,6 +2879,7 @@ sub add_source_info { } sub del_source_info { + return if $simulate; my $name = shift; $dbh->do('DELETE FROM ' . table_name() . ' WHERE package = ? AND distribution = ?', @@ -2765,6 +2895,7 @@ sub get_user_info { } sub update_user_info { + return if $simulate; my $user = shift; $dbh->do('UPDATE ' . user_table_name() . ' SET last_seen = now() WHERE username = ?' . @@ -2775,6 +2906,7 @@ sub update_user_info { sub add_user_info { + return if $simulate; my $user = shift; $dbh->do('INSERT INTO ' . user_table_name() . ' (username, distribution, last_seen)' . @@ -2785,7 +2917,149 @@ sub add_user_info { sub lock_table() { + return if $simulate; $dbh->do('LOCK TABLE ' . table_name() . ' IN EXCLUSIVE MODE', undef) or die $dbh->errstr; } +sub parse_argv() { +# parts the array $_[0] and $_[1] and returns the sub-array (modifies the original one) + my @ret = (); + my $args = shift; + my $separator = shift; + while($args->[0] && $args->[0] ne $separator) { + push @ret, shift @$args; + } + shift @$args if @$args; + return @ret; +} + +sub parse_all_v3() { + my $srcs = shift; + my $vars = shift; + my $db = get_all_source_info(); + my $binary = $srcs->{'_binary'}; + + SRCS: + foreach my $name (keys %$srcs) { + next if $name eq '_binary'; + + # state = installed, out-of-date, uncompiled, not-for-us + my $pkgs = $srcs->{$name}; + 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'}):"; + + # 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; + next SRCS; + } + } + $pkg->{'package'} = $name; + } + my $logstr = "merge-v3 $vars->{'time'} ".$name."_$pkgs->{'version'}". + " ($vars->{'arch'}, $vars->{'suite'}, previous: $pkg->{'version'}". + ", $pkg->{'state'}):"; + + if (isin($pkgs->{'status'}, qw (installed related)) && $pkg->{'binary_nmu_version'} && $pkgs->{'binnmu'} < int($pkg->{'binary_nmu_version'})) { + $pkgs->{'status'} = 'out-of-date'; + } + if (isin($pkgs->{'status'}, qw (installed related))) { + my $change = 0; + if ($pkg->{'state'} ne 'Installed') { + change_state( \$pkg, 'Installed'); + delete $pkg->{'depends'}; + delete $pkg->{'binary_nmu_version'}; + # delete $pkg->{'binary_nmu_changelog'}; - we keep the changelog for now in case there are bugs; activate in August 2010 or later + $change++; + } + my $attrs = { 'version' => 'version', 'installed_version' => 'version', 'section' => 'section', 'priority' => 'priority' }; + foreach my $k (keys %$attrs) { + if ($pkg->{$k} ne $pkgs->{$attrs->{$k}}) { + $pkg->{$k} = $pkgs->{$attrs->{$k}}; + $change++; + } + } + if ($pkg->{'binary_nmu_version'}) { # cleanup only + delete $pkg->{'binary_nmu_version'}; + $change++; + } + if (isin($pkgs->{'status'}, qw (related)) and $pkg->{'notes'} ne "related") { + $pkg->{'notes'} = "related"; + $change++; + } + if ($change) { + print "$logstr set to installed/".$pkg->{'notes'}."\n" if $verbose || $simulate; + log_ta( $pkg, "--merge-v3: installed" ) unless $simulate; + 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; + } + next if $pkgs->{'version'} eq $pkg->{'version'} and $pkgs->{'binnmu'} >= int($pkg->{'binary_nmu_version'}); + next if $pkgs->{'version'} eq $pkg->{'version'} and !isin( $pkg->{'state'}, qw(Installed)); + next if isin( $pkg->{'state'}, qw(Not-For-Us Failed-Removed)); + + 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 $pkgs->{'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" ) unless $simulate; + print "$logstr new version while building $pkg->{'version'} -- sending mail to builder ($pkg->{'builder'})\n" + if $verbose || $simulate; + } + change_state( \$pkg, 'Needs-Build'); + $pkg->{'notes'} = $pkgs->{'status'}; + $pkg->{'version'} = $pkgs->{'version'}; + $pkg->{'section'} = $pkgs->{'section'}; + $pkg->{'priority'} = $pkgs->{'priority'}; + $pkg->{'dep'} = $pkgs->{'depends'}; + $pkg->{'conf'} = $pkgs->{'conflicts'}; + delete $pkg->{'builder'}; + delete $pkg->{'binary_nmu_version'} unless $pkgs->{'binnmu'}; + delete $pkg->{'binary_nmu_changelog'} unless $pkgs->{'binnmu'}; + 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; + } + + foreach my $name (keys %$db) { + next if $srcs->{$name}; + my $pkg = $db->{$name}; + my $logstr = "merge-v3 $vars->{'time'} ".$name."_$pkg->{'version'} ($vars->{'arch'}, $vars->{'suite'}, previous: $pkg->{'state'}):"; + # package disappeared - delete + change_state( \$pkg, 'deleted' ); + log_ta( $pkg, "--merge-v3: deleted" ) unless $simulate; + print "$logstr deleted from database\n" if $verbose || $simulate; + del_source_info($name) unless $simulate; + delete $db->{$name}; + } +}