source: soft/build_system/build_system/mkcd/tags/Corpo_2_1_1/pm/Mkcd/List.pm @ 1

Last change on this file since 1 was 1, checked in by fasma, 12 years ago

Initial Import from Mandriva's soft revision 224062 and package revision 45733

File size: 72.1 KB
Line 
1package Mkcd::List;
2
3my $VERSION = '2.4.2';
4
5use strict;
6use File::NCopy qw(copy);       
7use File::Path;
8use URPM qw(ranges_overlap);
9use Mkcd::Package qw(rpmVersionCompare);
10use Mkcd::Tools qw(log_);
11use Mkcd::Optimize qw(optimize_space get_pkgs_deps);
12use MDK::Common qw(any);
13
14=head1 NAME
15
16List - mkcd module
17
18=head1 SYNOPSYS
19
20    require Mkcd::List;
21
22=head1 DESCRIPTION
23
24C<mkcd::List> include the mkcd packages list functions.
25
26=head1 SEE ALSO
27
28mkcd
29
30=head1 COPYRIGHT
31
32Copyright (C) 2000 MandrakeSoft <warly@mandrakesoft.com>
33
34This program is free software; you can redistribute it and/or modify
35it under the terms of the GNU General Public License as published by
36the Free Software Foundation; either version 2, or (at your option)
37any later version.
38
39This program is distributed in the hope that it will be useful,
40but WITHOUT ANY WARRANTY; without even the implied warranty of
41MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
42GNU General Public License for more details.
43
44You should have received a copy of the GNU General Public License
45along with this program; if not, write to the Free Software
46Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
47
48=cut
49
50my $config;
51
52sub new {
53    my ($class, $conf) = @_;
54    $config = $conf;
55    bless {
56           config       => $config,
57          }, $class;
58}
59
60sub processDiff {
61    my ($class, $groups, $diff, $discsFiles) = @_;
62    my (@cd, @action);
63    my %new;
64    my $prev = $diff->{previous_idx} || {};
65    foreach (@{$diff->{idx}}) {
66        push @{$action[1]}, $_ if !$prev->{$_};
67        $new{$_} = 1
68    }
69    foreach (keys %$prev) {
70        push @{$action[2]}, $_ if !$new{$_}
71    }
72    foreach my $op (2,1) {
73        foreach my $idx (@{$action[$op]}) {
74            my $d = $diff->{data}[$idx];
75            if (!$d) { log_("ERROR processDiff: THIS MUST NOT HAPPEN action is null ($d) op $op idx $idx\n", $config->{verbose}, $config->{LOG}); next }
76            my ($curdir, $grp, $list, undef, undef, $data) = @$d;
77            my $cd = $curdir->[0];
78            foreach my $ent (@$data) {
79                my $rpm = $ent->[0];
80                log_("LOG disc $cd group $grp: ($op) $rpm ($groups->[$grp]{size}{$rpm}{$list}[1])\n", $config->{verbose}, $config->{LOG},3);
81                if (!$rpm) {
82                    foreach (@$ent) {
83                        if (ref $_) { log_("ERROR processDiff: @$_\n", $config->{verbose}, $config->{LOG},2) }
84                        else { log_("ERROR processDiff: $_\n", $config->{verbose}, $config->{LOG},2) }
85                    }
86                }
87                $rpm or next;
88                my $source = $groups->[$grp]{size}{$rpm}{$list}[1];
89                push @{$cd[$cd]{$curdir->[1]}{$list}{$source}}, [$op, "$groups->[$grp]{urpm}{rpmkey}{rpm}{$rpm}.rpm"];
90                if ($op == 1) { $discsFiles->[$cd]{$curdir->[1]}{$list}{$groups->[$grp]{urpm}{rpmkey}{rpm}{$rpm}} = $source }
91                elsif ($op == 2) { delete $discsFiles->[$cd]{$curdir->[1]}{$list}{$groups->[$grp]{urpm}{rpmkey}{rpm}{$rpm}} }
92            }
93        }
94    }
95    my %new_diff;
96    # clear diff
97    foreach my $idx (@{$diff->{idx}}) {
98        my $nidx = push @{$new_diff{data}}, $diff->{data}[$idx];
99        push @{$new_diff{idx}}, $nidx - 1;
100        $new_diff{previous_idx}{$nidx - 1} = 1
101    }
102    return \@cd, \%new_diff
103}
104
105sub getDoneList {
106    my ($config, $group, $listnumber, $discsFiles) = @_;
107
108    my $topdir = "$config->{topdir}/build/$config->{name}";
109    my $add_rpm = sub {
110            my ($d, $rpm, $cd, $rep, $type) = @_;
111            #$rpm =~ /($test)\.rpm$/ or return;
112            $rpm =~ /(.*)\.rpm$/ or return;
113            #$rpm =~ /src\.rpm$/ and return;
114            my $rpm = $group->{urpm}{rpmkey}{key}{$1};
115            $group->{done}{rep}{$rpm} = $group->{orderedrep}{$type}{"$cd/$rep"};
116            $group->{done}{list}{$rpm} = $listnumber;
117            $discsFiles->[$cd]{$rep}{$listnumber}{$1} = $d
118    };
119    my $read_dir = sub {
120        my ($dir, $cd, $rep, $type) = @_;
121        my $RPMS;
122        if (!opendir $RPMS, $dir) { 
123            log_("WARNING getGroupReps: cannot open $dir\n",1, $config->{LOG},0);
124            return
125        }
126        foreach (readdir $RPMS) {
127            if (-d "$dir/$_") {
128                opendir my $D, "$dir/$_";
129                foreach my $r (readdir $D) {
130                    $add_rpm->("$dir/$_", $r, $cd, $rep, $type)
131                }
132            } else {
133                $add_rpm->($dir, $_, $cd, $rep, $type)
134            }
135        }
136    };
137    foreach my $type ('rpm', 'srpm') {
138        foreach my $curdir (@{$group->{list}{$listnumber}{$type}}) {
139            my ($cd, $rep) = @$curdir;
140            my $path = $config->{disc}[$cd]{function}{data}{dir}{$rep}[1]{reploc};
141            my $dir = "$topdir/$cd/$path";
142            log_("getDoneList: $listnumber disc $cd rep $rep\n", $config->{verbose}, $config->{LOG},2);
143            if ($config->{nolive}) {
144                if ($config->{list}[$listnumber]{packages}) {
145                    foreach my $ent (@{$config->{list}[$listnumber]{packages}}) {
146                        foreach my $type (keys %$ent) {
147                            my $rpm_tab = $ent->{$type};
148                            log_("getDoneList: @$rpm_tab\n",1, $config->{LOG},3);
149                            foreach my $dir (@$rpm_tab) {
150                                $read_dir->($dir, $cd, $rep, $type) 
151                            }
152                        }
153                    }
154                } else {
155                    log_("ERROR getDoneList: could not find data for $listnumber disc $cd rep $rep\n", $config->{verbose}, $config->{LOG},0);
156                }
157            } elsif (-d $dir) {
158                $read_dir->($dir, $cd, $rep, $type);
159            } else {
160                log_("ERROR getDoneList: could not find data for $listnumber disc $cd rep $rep\n", $config->{verbose}, $config->{LOG},0);
161                next
162            }
163            $config->{list}[$listnumber]{disc}{$cd}{$rep}{done} = 1
164        }
165    }
166
167    foreach my $d (@{$config->{list}[$listnumber]{virtual}}) {
168        my $cd = $d->{disc};
169        my $path = $d->{path};
170        my $rep = $d->{repname};
171        my $dir = "$topdir/$cd/$path";
172        log_("getDoneList: virtual disc $cd path $path in $dir\n",1, $config->{LOG},2);
173        foreach my $list_rep (@{$group->{rep}{$listnumber}}) {
174            $list_rep->{rpm}{$dir} or next;
175            foreach (@{$list_rep->{rpm}{$dir}}) {
176                my $rpm = $group->{urpm}{rpmkey}{key}{$_};
177                $group->{done}{rep}{$rpm} = $group->{orderedrep}{rpm}{"$cd/$rep"};
178                $group->{done}{list}{$rpm} = $listnumber;
179                $discsFiles->[$cd]{$rep}{$listnumber}{$_} = $dir
180            }
181        }
182        $config->{list}[$listnumber]{disc}{$cd}{$rep}{done} = 1;
183    }
184}
185
186sub getList {
187    my ($class, $group, $discsFiles) = @_;
188    my $config = $class->{config};
189    my %filelist;
190    my @norpmsrate;
191    log_("getList: group list " . join(' ', (keys %{$group->{list}})) . "\n", $config->{verbose}, $config->{LOG},1);
192    foreach my $listnumber (keys %{$group->{list}}) {
193        my $done = $config->{list}[$listnumber]{done};
194        $done and getDoneList($config, $group, $listnumber, $discsFiles);
195        log_("getList: FILE LIST listnumber $listnumber ($config->{list}[$listnumber]{filelist}) or ($config->{list}[$listnumber]{prelist})\n", $config->{verbose}, $config->{LOG},2);
196        if ($config->{list}[$listnumber]{filelist} || $config->{list}[$listnumber]{prelist}) {
197            foreach (@{$config->{list}[$listnumber]{filelist}}) {
198                log_("getList: FILE LIST listnumber $listnumber ($_)\n", $config->{verbose}, $config->{LOG},2);
199                my $A;
200                if (! open $A, $_) { log_("ERROR: cannot open $_, ignoring\n",1, $config->{LOG}); next }
201                local $_;
202                while (<$A>) {
203                    s/#.*//;
204                    next if !$_ || /^\s*$/;
205                    my ($name, $options) = /\s*(\S+)\s*(.*)/;
206                    my @options = split ',', $options;
207                    log_("FILESLIST: $_ -> $name options @options\n", $config->{verbose}, $config->{LOG},3);
208                    my %opt;
209                    foreach (@options) {
210                        s/^\s*//;
211                        /norpmsrate/ and push @norpmsrate, $name and next;
212                        if (!/^(?:(?:nosrc|section|noalternatives|regexp|ignore|nodeps|force|limit|exclude)|(rate|notondisc|rpmsrate|needed|section) (\d+))$/) {
213                            log_("WARNING: getList: $_: unknown option\n",1, $config->{LOG}); next
214                        }
215                        $_ = $1 || $_; 
216                        $opt{$_} = $2 || 1;
217                    }
218                    log_("Adding $name -- " . join(' ', keys %opt) . "\n", $config->{verbose}, $config->{LOG},4);
219                    push @{$filelist{$listnumber}}, [ $name, \%opt ];   
220                }
221                close $A
222            }
223            foreach my $p (@{$config->{list}[$listnumber]{prelist}}) {
224                log_("Prelist Adding $p->[0] -- " . join(' ', keys %{$p->[1]}) . "\n", $config->{verbose}, $config->{LOG},3);
225                $p->[1]{norpmsrate} and push @norpmsrate, $_->[0] and next;
226                push @{$filelist{$listnumber}}, $p
227            }
228        } else {
229            if (!$done && $config->{list}[$listnumber]{auto}) {
230                push @{$filelist{$listnumber}}, [ "INSTALL", { section =>1, force => 1 } ];
231                push @{$filelist{$listnumber}}, [ "SYSTEM", { section =>1, force => 1 } ];
232                push @{$filelist{$listnumber}}, [ "kernel-(smp-|)[0-9].*", { regexp => 1, force => 1 } ];
233                push @{$filelist{$listnumber}}, [ "kernel.*linus", { regexp => 1, noalternatives => 1 } ];
234                push @{$filelist{$listnumber}}, [ ".*", { regexp => 1 } ]
235            } else {
236                log_("getList: FILE LIST listnumber $listnumber defaulting to .* regexp\n", $config->{verbose}, $config->{LOG},2);
237                push @{$filelist{$listnumber}}, [ ".*" , { regexp => 1 } ]
238            }
239        }
240        my $listdone = 1;
241        foreach my $r (@{$group->{list}{$listnumber}{rpm}}) {
242            my ($cd, $rep, $repopt, $opt) = @$r;
243            log_("getList: searching for done rep ($cd/$rep)\n", $config->{verbose}, $config->{LOG},2);
244            if ($config->{list}[$listnumber]{disc}{$cd}{$rep}{done}) {
245                if (!$opt->{dup}) {
246                    foreach my $rpmkey (keys %{$discsFiles->[$cd]{$rep}{$listnumber}}) {
247                        my $rpm = $group->{urpm}{rpmkey}{key}{$rpmkey};
248                        $group->{done}{rep}{$rpm} = $group->{orderedrep}{rpm}{"$cd/$rep"};
249                        $group->{done}{list}{$rpm} = $listnumber;
250                        log_("getList: $rpm in $cd/$rep -> $group->{done}{rep}{$rpm} (noprovide $r->[3]{noprovide} update $r->[3]{update})\n", $config->{verbose}, $config->{LOG},3);
251                        push @{$filelist{$listnumber}}, [ $rpm, { done => $group->{done}{rep}{$rpm}, 
252                                                                  regexp => 1, 
253                                                                  udpate => $r->[3]{update}, 
254                                                                  noprovide => $r->[3]{noprovide} } ];
255                    }
256                }
257            } else { $listdone = 0 }
258        }
259        if ($listdone) {
260            log_("getList: setting list $listnumber as done\n", $config->{verbose}, $config->{LOG},2);
261            $config->{list}[$listnumber]{done} = 1 }
262    }
263    (\%filelist, \@norpmsrate)
264}
265
266#
267# compute individual scoring (max_size*(rpmsrate+1)*rpmsrate_factor/(size*size_factor))
268# then add dependencies sons score ( score + deps_factor*(sons_score)
269#
270# special rpmsrate groups score could be added in the rpmsrate value
271#
272# FIXME current scoring rules make size only significant for equaly dependent packages,
273# dependencies get far more importance for packages a lot of packages depend on.
274#
275# Size scoring could be added afterwards, but this will break the autodeps created with
276# this scheme.
277#
278# TODO
279# add scoring rules to include srpm size in score.
280#
281#
282sub scoreList {
283    my ($class, $group) = @_;
284    my $scoreweight = $group->{score};
285    my $urpm = $group->{urpm};
286    my $rpmsrate = $group->{rpmsrate};
287    my $maxsize = $group->{maxsize} || 1;
288    $scoreweight ||= [1,1,1];
289    log_("scoreList: SCORE for group: @$scoreweight\n", $config->{verbose}, $config->{LOG},2);
290    log_("scoreList: Individual scoring\n", $config->{verbose}, $config->{LOG},2);
291    my ($sf, $i, $total);
292    my (@min, @max);
293    if ($scoreweight->[1]) {
294        (@min,@max) = (($maxsize*$scoreweight->[0]*6/($scoreweight->[1]*1),0), (0,0))
295    } else {
296        (@min,@max) = (($maxsize*$scoreweight->[0]*6,0), (0,0))
297    }
298    my @specialdeps;
299    foreach (keys %{$urpm->{rpm}}) {
300        # print "INFO KEYS $_\n";
301        my ($ratekey) = /(.*)-[^-]+-[^-]+\.[^.]+$/;
302        # FIXME take the bigger size when package appears in multiple lists
303        my $size;
304        foreach my $list (keys %{$group->{size}{$_}}) { $size = $group->{size}{$_}{$list}[0] if $size < $group->{size}{$_}{$list}[0] }
305        $size or log_("WARNING scoreList: $_ has zero size\n",1, $config->{LOG});
306        my $s;
307        my $rate = $group->{brokendeps}{$_} ? 0 : (defined $group->{pkgrate}{$_} ? $group->{pkgrate}{$_} : $rpmsrate->[0]{$ratekey});
308        if ($scoreweight->[1]) {
309            $sf = ($size*9)/$maxsize + 1; # from 1 to 10
310            $s = $scoreweight->[0]*($rate + 1)/($scoreweight->[1]*$sf);
311        } else {
312            $s = $scoreweight->[0]*($rate + 1);
313        }
314        $group->{scorelist}{$_} = $s;
315        $s < $min[0] and @min = ($s, $_);
316        $s > $max[0] and @max = ($s, $_);
317
318        $total+=$s;
319        $i++
320    }
321    $i and log_("scoreList: minimal $min[0] ($min[1]), maximal $max[0] ($max[1]), average " . $total/$i . "\n", $config->{verbose}, $config->{LOG},3);
322    1
323}
324
325sub autodeps {
326    my ($class, $group, $rpmlist) = @_;
327    my $scoredeps = $group->{score}[2];
328    if (!$scoredeps) { 
329        log_("autodeps: deps score is null, bypassing autodeps\n",1, $config->{LOG},1);
330        return 1
331    }
332    log_("autodeps: compute reversed depslist.ordered ($scoredeps)\n", $config->{verbose}, $config->{LOG},2);
333    my $revDeps = $group->{revdeps};
334    my %rpm;
335    foreach my $k (values %$rpmlist) { foreach (keys %$k) { $rpm{$_} = $k->{$_} } }
336    # FIXME this algo is not correct
337    ref $group->{urpm}{depslist} or return 0;
338    for (my $i = @{$group->{urpm}{depslist}} - 1; $i >= 0; $i--) {
339        my $rpm = $group->{depslistid}[$i];
340        if (!$rpm{$rpm}) { 
341            #log_("autodeps: ignoring $rpm\n",1, $config->{LOG});
342            #push @{$group->{rejected}{$rpm}}, [ "autodeps", $1 ];
343            next
344        }
345        if ($rpm{$rpm}{ignore}) { log_("autodeps: $rpm has ignore flag, do not add deps score\n", $config->{verbose}, $config->{LOG},3); next }
346        foreach (@{$revDeps->[$i]}) {
347            $group->{scorelist}{$rpm} += $scoredeps * $group->{scorelist}{$group->{depslistid}[$_]};
348        }
349    }
350    1
351}
352
353sub reverseDepslist {
354    my ($class, $group, $rpmfile) = @_;
355    my $urpm = $group->{urpm};
356    my $depslist = $urpm->{depslist};
357    if (!$depslist) {
358        log_("WARNING reverseDepslist: no depslist found\n", $config->{verbose}, $config->{LOG},3);
359        return ()
360    }
361    my $locales = $group->{lang};
362    my (@revdeps, %skip);
363    log_("reverseDepslist\n", $config->{verbose}, $config->{LOG},2);
364    for (my $i; $i < @$depslist; $i++) {
365        my $d = $depslist->[$i];
366        my $rpm = sprintf "%s-%s-%s.%s", $d->name, $d->version, $d->release, $d->arch;
367        $group->{depslistid}[$i] = $rpm;
368        my $l = find_list($group, $rpm);
369        my %rev;
370        # FIXME deps is deprecated, the correct function to use it packages->requires
371        # but using deps and check_version is faster
372        foreach (split(' ', $urpm->{deps}[$i])) {
373            if (!$group->{options}{nodeps} && !$class->{config}{nodeps} && !(defined $rpmfile->{$l}{$rpm} && $rpmfile->{$l}{$rpm}{nodeps}) && m/NOTFOUND_(\S*)/) {
374                $skip{$i} = 1;
375                $group->{brokendeps}{$rpm} = 2;
376                push @{$group->{rejected}{$rpm}}, [ "deps", $1 ];
377                log_("WARNING reverseDepslist: $rpm has unresolved dependencies ($1)\n", $config->{verbose}, $config->{LOG}, 1);
378                next
379            }
380            if (/\|/) { 
381                my $s = [split '\|', $_];
382                my (@tmp_s, $msg_tot);
383                foreach (@$s) { 
384                    my ($ok, $msg) = check_version($d, $depslist->[$_], $rpm);
385                    log_("ERROR check_version: $msg\n", $config->{verbose}, $config->{LOG}, 0) if $msg;
386                    if ($ok) {
387                        push @tmp_s, $_ 
388                    } else { 
389                        $msg_tot .= $msg
390                    }
391                    $skip{$_} or push @{$revdeps[$_]}, $i 
392                }
393                if (@tmp_s) {
394                    push @{$group->{pkgdeps}{$rpm}}, \@tmp_s
395                } else {
396                    $skip{$i} = 1;
397                    $group->{brokendeps}{$rpm} = 2;
398                    log_("WARNING reverseDepslist: rejecting $rpm on $_\n", $config->{verbose}, $config->{LOG}, 4);
399                    push @{$group->{rejected}{$rpm}}, [ "deps", $msg_tot ]
400                }
401            } else { 
402                if ($locales && $group->{depslistid}[$_] =~ /locales-([^-]+)-[^-]+-[^-]+\.[^.]+/)  {
403                    if (!$locales->{$1}) {
404                        log_("reverseDepslist: locale $1 ($group->{depslistid}[$_]) skipped for $rpm\n", $config->{verbose}, $config->{LOG}, 2);
405                        $skip{$i} = 1;
406                        !$group->{brokendeps}{$rpm} and $group->{brokendeps}{$rpm} = 1 
407                    }
408                }
409       
410                my ($ok, $msg) = check_version($d, $depslist->[$_], $rpm);
411                log_("ERROR check_version: $msg\n", $config->{verbose}, $config->{LOG}, 0) if $msg;
412                if ($ok) {
413                    push @{$group->{pkgdeps}{$rpm}}, $_ 
414                } else { 
415                    $skip{$i} = 1;
416                    $group->{brokendeps}{$rpm} = 2;
417                    log_("WARNING reverseDepslist: rejecting $rpm on $_\n", $config->{verbose}, $config->{LOG}, 4);
418                    push @{$group->{rejected}{$rpm}}, [ "deps", $msg ]
419                }
420                $skip{$_} or push @{$revdeps[$_]}, $i
421            }
422        }
423    }
424    return \@revdeps
425}
426
427# check if ONE require is satisfied
428sub check_version {
429    my ($d, $deps_d, $rpm, $special_require) = @_;
430    my ($msg, $real_ok, $ok);
431    $ok = 1;
432    my $deps_v = sprintf "%s-%s", $deps_d->version, $deps_d->release;
433    my $deps_rpm = sprintf "%s-%s.%s", $deps_d->name, $deps_v, $deps_d->arch;
434    $rpm ||= sprintf "%s-%s-%s.%s", $d->name, $d->version, $d->release, $d->arch;
435    foreach my $req ($d->requires) {
436        my ($n, $s) = $req =~ /^([^\s\[]*)(?:\[\*\])?\[?([^\s\]]*\s*[^\s\]]*)/;
437        # perl needs major checking
438        $n eq 'perl' and next;
439        # Some deps are broken and as a consequence using the major rejects some packages that shouldn't
440        #$s and ($s =~ /:/ or $s =~ s/([>=<]+) /$1 0:/);
441        $s =~ /:/ and $s =~ s/ \d+:/ /;
442        if ($n && $s) {
443            # nok is usefull in case the package provides several times the require, each time with a different version
444            my $tok;
445            foreach my $prov ($deps_d->provides) {
446                my ($deps_n, $deps_s) = $prov =~ /^([^\s\[]*)(?:\[\*\])?\[?([^\s\]]*\s*[^\s\]]*)/;
447                #$deps_s and ($deps_s =~ /:/ or $deps_s =~ s/([>=<]+) /$1 0:/);
448                $deps_s =~ /:/ and $deps_s =~ s/ \d+:/ /;
449                $deps_s ||= $s =~ /-/ ? "= $deps_v" : "= " . $deps_d->version;
450                if ($deps_n && $deps_s) {
451                    if ($deps_n eq $n) { 
452                        if (URPM::ranges_overlap($deps_s, $s)) {
453                            $real_ok = 1 if !$special_require || $special_require eq $n;
454                        } else {
455                            my $t = "$deps_rpm provides $deps_n $deps_s but $rpm needs $n $s";
456                            $msg .= " $t";
457                        }
458                    }
459                }
460            }
461        } else {
462            foreach my $prov ($deps_d->provides) {
463                my ($deps_n) = $prov =~ /^([^\s\[]*)(?:\[\*\])?\[?([^\s\]]*\s*[^\s\]]*)/;
464                if ($deps_n eq $n) { 
465                    $real_ok = 1 if !$special_require || $special_require eq $n;
466                }
467            }
468        }
469    }
470    ($ok, $msg, $real_ok)
471}
472
473sub closeRpmsList {
474    my ($group, $rpmfile) = @_;
475    my $n = 1;
476    my %done;
477    my %doneName;
478    my %alternatives;
479    while ($n) {
480        $n = 0;
481        foreach my $listnumber (@{$group->{orderedlist}{rpm}}) {
482            foreach my $rpm (keys %{$rpmfile->{$listnumber}}) {
483                # FIXME if the different packages have different deps, old packages may be better.
484                # this should be done in buildDisc, or better packages have to be selected here.
485                if (!$group->{options}{dup}) {
486                    my ($name, $version, $release, $arch) = $rpm =~ /^(.*)-([^-]+)-([^-]+)\.([^.]+)$/;
487                    if ($doneName{$name}) {
488                        if (!($doneName{$name}[0] eq "$version-$release.$arch")) {
489                            log_("WARNING closeRpmsList: $name-$version-$release.$arch duplicated with $doneName{$name}[0]\n", $config->{verbose}, $config->{LOG}, 1);
490                            my ($v, $r, $a) = @{$doneName{$name}[1]};   
491                            my $todel;
492                            my $vers;
493                            my $ret = rpmVersionCompare($rpm, "$name-$v-$r.$a");
494                            if ($ret < 0) {
495                                $todel = $rpm;
496                                $vers = [$v, $r, $a]
497                            } elsif ($ret > 0) {
498                                $todel = "$name-$v-$r.$a";
499                                $vers = [$version, $release, $arch]
500                            } else {
501                                log_("ERROR closeRpmsList: oops, something not possible happened in duplicate version comparaison ($rpm and $name-$v-$r.$a)\n",1, $config->{LOG});
502                            }
503                            if ($todel) {
504                                log_("closeRpmsList: deleting $todel\n", $config->{verbose}, $config->{LOG},2);
505                                $doneName{$name} = [ "$vers->[0]-$vers->[1].$vers->[2]", $vers ];
506                                #$group->{brokendeps}{$todel} = 3;
507                                #push @{$group->{rejected}{$todel}}, [ "old_version", "$name-$vers->[0]-$vers->[1].$vers->[2]"];
508                                delete $rpmfile->{$listnumber}{$todel};
509                                $todel eq $rpm and next 
510                            }
511                            $n = 1
512                        }
513                    } else {
514                        $doneName{$name} = [ "$version-$release.$arch", [$version, $release, $arch] ]
515                    }
516                }
517                if ($group->{brokendeps}{$rpm} == 2 || $group->{brokendeps}{$rpm} == 3) {
518                    log_("closeRpmsList: deleting $rpm (list $listnumber)\n", $config->{verbose}, $config->{LOG},2);
519                    delete $rpmfile->{$listnumber}{$rpm};
520                    $n = 1;
521                    next
522                }
523                $done{$rpm} and next;
524                $rpmfile->{$listnumber}{$rpm}{nodeps} and next;
525                my $needed;
526                # FIXME the right thing to do would be to put the require in the rep just before the one of the $rpm, and not to force it.
527                $needed = 1 if $rpmfile->{$listnumber}{$rpm}{force};
528                $needed ||= $rpmfile->{$listnumber}{$rpm}{done};
529                $needed ||= $rpmfile->{$listnumber}{$rpm}{needed};
530                # $needed and log_("closeRpmsList: $rpm needed set to $needed (force $rpmfile->{$listnumber}{$rpm}{force} done $rpmfile->{$listnumber}{$rpm}{done} needed $rpmfile->{$listnumber}{$rpm}{needed})\n", $config->{verbose}, $config->{LOG});
531                foreach (@{$group->{pkgdeps}{$rpm}}) {
532                    if (m/NOTFOUND_(.*)/) { log_("ERROR closeRpmsList: $1 not provided\n", $config->{verbose}, $config->{LOG},1); next }
533                    my $rpmdep;
534                    my $rpmdeplist;
535                    my $specialrpmdep;
536                    if (ref $_) {
537                        if ($alternatives{"@$_"}) {
538                            ($rpmdep, $rpmdeplist) = @{$alternatives{"@$_"}};
539                            log_("closeRpmsList: $rpm taking alternatives from already selected package ($rpmdep $rpmdeplist)\n", $config->{verbose}, $config->{LOG}, 4)
540                        }
541                        if (! ref $rpmfile->{$rpmdeplist}{$rpmdep}) {
542                            foreach my $testalt (1,0) {
543                                ($rpmdep, $rpmdeplist) = (undef,undef);
544                                # FIXME this is wrong, package can come from any list
545                                my @score = ($group->{maxlist}{rpm}, int @{$group->{list}{$listnumber}{rpm}}, $group->{maxsize});
546                                my @specialscore = (int @{$group->{list}{$listnumber}{rpm}}, $group->{maxsize});
547                                log_("closeRpmsList: $rpm @$_ (maxscore @score) alternative\n", $config->{verbose}, $config->{LOG}, 4);
548                                foreach (@$_) {
549                                    my $pkg = $group->{depslistid}[$_];
550                                    log_("closeRpmsList: trying $pkg (brokendeps $group->{brokendeps}{$pkg})\n", $config->{verbose}, $config->{LOG}, 4);
551                                    $group->{brokendeps}{$pkg} == 2 and next;
552                                    $group->{brokendeps}{$pkg} == 3 and next;
553                                    my $pkglist = find_list($group, $pkg, $listnumber);
554                                    if (!$pkglist) {
555                                        log_("closeRpmsList: $pkg list could not be used for $rpm dependencies\n", $config->{verbose}, $config->{LOG}, 4);
556                                        next
557                                    }
558                                    log_("closeRpmsList: list $pkglist\n", $config->{verbose}, $config->{LOG}, 4);
559
560                                    if ($rpmfile->{$pkglist}{$pkg}) {
561                                        $rpmfile->{$pkglist}{$pkg}{limit} and next;
562                                        $testalt and $rpmfile->{$pkglist}{$pkg}{noalternatives} and next;
563                                    }
564                                    my $rep = $group->{size}{$pkg}{$pkglist}[2];
565                                    my $s = $group->{size}{$pkg}{$pkglist}[0];
566                                    my $l = $group->{listsort}{$pkglist}{rpm};
567                                    log_("\t$pkg ($l, $rep, $s) (@score)\n", $config->{verbose}, $config->{LOG}, 5);
568                                    # also put an alternative from this list
569                                    if ($pkglist == $listnumber) {
570                                        if ($rep < $specialscore[1]) {
571                                            @specialscore = ($rep, $s);
572                                            $specialrpmdep = $pkg;
573                                        } elsif ($rep == $specialscore[1] && $s < $specialscore[2]) {
574                                            @specialscore = ($rep, $s);
575                                            $specialrpmdep = $pkg;
576                                        }               
577                                    }
578                                    if ($l < $score[0]) {
579                                        @score = ($l, $rep, $s);
580                                        $rpmdep = $pkg;
581                                        $rpmdeplist = $pkglist;
582                                        log_("1 $rpmdep -- $rpmdeplist -- $l, $rep, $s\n", $config->{verbose}, $config->{LOG}, 6);
583                                    } elsif ($l == $score[0]) {
584                                        if ($pkglist == $listnumber) {
585                                            if ($rep < $score[1]) {
586                                                @score = ($l, $rep, $s);
587                                                $rpmdep = $pkg;
588                                                $rpmdeplist = $pkglist;
589                                                log_("2 $rpmdep -- $rpmdeplist -- $l, $rep, $s\n", $config->{verbose}, $config->{LOG}, 6);
590                                            } elsif ($rep == $score[1] && $s < $score[2]) {
591                                                @score = ($l, $rep, $s);
592                                                $rpmdep = $pkg;
593                                                $rpmdeplist = $pkglist;
594                                                log_("3 $rpmdep -- $rpmdeplist -- $l, $rep, $s\n", $config->{verbose}, $config->{LOG}, 6);
595                                            }
596                                        } elsif ($s < $score[2]) {
597                                            @score = ($l, $rep, $s);
598                                            $rpmdep = $pkg;
599                                            $rpmdeplist = $pkglist;
600                                            log_("4 $rpmdep -- $rpmdeplist -- $l, $rep, $s\n", $config->{verbose}, $config->{LOG}, 6);
601                                        }
602
603                                    }
604                                }
605                                last if $rpmdep && $rpmdeplist
606                            }
607                            if ($rpmdep && $rpmdeplist) {
608                                log_("\tResult:\t$rpmdep\n", $config->{verbose}, $config->{LOG}, 4);
609                                $alternatives{"@$_"} = [ $rpmdep, $rpmdeplist ]
610                            } else {
611                                log_("WARNING: $rpm has unresolved or excluded dependencies, removed\n", $config->{verbose}, $config->{LOG}, 1);
612                                log_("closeRpmsList: deleting $rpm (list $listnumber)\n", $config->{verbose}, $config->{LOG}, 2);
613                                delete $rpmfile->{$listnumber}{$rpm};
614                                $n = 1;
615                                $group->{brokendeps}{$rpm} = 2;
616                                push @{$group->{rejected}{$rpm}}, ["deps_rejected", (join ' ', map { $group->{depslistid}[$_] } @$_)];
617                            }
618                        }
619                    } else {   
620                        # TODO verify that there is no need to do $rpmfile->{$pkglist}{$rpmdep} or brokendeps;
621                        $rpmdep = $group->{depslistid}[$_];
622                        $rpmdeplist = find_list($group, $rpmdep, $listnumber);
623                    }
624                    # log_("rpmdep $rpmdep rpmdeplist $rpmdeplist rpm $rpm\n",1, $config->{LOG});
625                    if ($rpmdep) {
626                        if (!$rpmdeplist || $group->{brokendeps}{$rpmdep} == 2 || $group->{brokendeps}{$rpmdep} == 3) {
627                            $group->{brokendeps}{$rpm} = $group->{brokendeps}{$rpmdep};
628                            push @{$group->{rejected}{$rpm}}, [ "deps_rejected", $rpmdep ];
629                            $n = 1;
630                            log_("WARNING closeRpmsList: $rpm has unresolved or excluded dependencies ($rpmdep list $rpmdeplist), removed\n", $config->{verbose}, $config->{LOG}, 1);
631                            log_("closeRpmsList: deleting $rpm (list $listnumber)\n", $config->{verbose}, $config->{LOG}, 2);
632                            delete $rpmfile->{$listnumber}{$rpm};
633                            next
634                        }
635                        if (! ref $rpmfile->{$rpmdeplist}{$rpmdep}) {
636                            if (!$group->{done}{rep}{$rpmdep} || $needed && $group->{done}{rep}{$rpmdep} > $needed){
637                            $n = 1;
638                            log_("closeRpmsList: ADDED $rpmdep (list $rpmdeplist) needed $needed\n", $config->{verbose}, $config->{LOG}, 3);
639                            $rpmfile->{$rpmdeplist}{$rpmdep} = { needed => $needed }
640                        }
641                        } elsif ($needed && !$group->{done}{rep}{$rpmdep} || $group->{done}{rep}{$rpmdep} > $needed) {
642                            my $n = $rpmfile->{$rpmdeplist}{$rpmdep}{needed};
643                            $rpmfile->{$rpmdeplist}{$rpmdep}{needed} = !$n || $needed < $n ? $needed : $n;
644                            log_("closeRpmsList: setting $rpmdep needed option to $rpmfile->{$rpmdeplist}{$rpmdep}{needed}\n", $config->{verbose}, $config->{LOG}, 4);
645                        }
646                    }
647                    if ($specialrpmdep) {
648                        if (! ref $rpmfile->{$listnumber}{$specialrpmdep}) {
649                            $n = 1;
650                            log_("closeRpmsList: ADDED $specialrpmdep (list $listnumber)\n", $config->{verbose}, $config->{LOG}, 3);
651                            $rpmfile->{$listnumber}{$specialrpmdep} = { }
652                        }
653                    }
654                }
655                $done{$rpm} = 1;
656            }
657            log_("closeRpmsList: $listnumber [$n]\n", $config->{verbose}, $config->{LOG}, 2);
658        }
659    }
660}
661
662sub addRPMToList {
663    my ($group, $listnumber, $rpmfile, $done, $rpms, $fentry, $name) = @_;
664    my $exclude = sub {
665        my ($rpm, $name) = @_;
666        log_("addRPMToList: excluding $_\n",1, $config->{LOG}, 1);
667        $group->{brokendeps}{$rpm} = 3;
668        push @{$group->{rejected}{$rpm}}, ["excluded", $name];
669    };
670    $name =~ s/\+/\\+/g;
671    my @toadd;
672    if ($fentry->{regexp}) { @toadd = grep { /$name/ } @$rpms } 
673    else { @toadd = grep { /^$name-[^-]+-[^-]+\.[^.]*$/ } @$rpms }
674    log_("addRPMToList: toadd $name (regexp $fentry->{regexp}) (@toadd)\n", $config->{verbose}, $config->{LOG}, 3);
675    if ($fentry->{done}) {
676        foreach (@toadd) {
677            my ($pkg) = /^(.*)-[^-]+-[^-]+\.[^.]*$/;
678            my %ht;
679            foreach my $k (keys %$fentry) { $ht{$k} = $fentry->{$k} }   
680            $rpmfile->{$listnumber}{$_} = \%ht;
681            my $a = [ $_, $group->{size}{$_}{$listnumber}[2], \%ht, $listnumber ];
682            $done->{name}{$pkg} = $a;
683            $done->{full}{$pkg} = 1;
684            log_("addRPMToList: ADDED done $_ (list $listnumber)\n", $config->{verbose}, $config->{LOG}, 4)
685        }
686        return
687    }
688    my %pkg;
689    if ($fentry->{regexp}) { 
690        foreach (@toadd) {
691            if ($rpmfile->{$listnumber}{$_}) { log_("WARNING addRPMToList: do not replace $_ entry in rpmfile\n", $config->{verbose}, $config->{LOG}, 1); next }
692            if (!$_) { log_("ERROR addRPMToList: empty rpm\n", $config->{verbose}, $config->{LOG}, 2); next }
693            $group->{size}{$_}{$listnumber} or next;
694            $group->{brokendeps}{$_} == 2 and next;
695            $group->{brokendeps}{$_} == 3 and next;
696            my ($pkgname) = /^(.*)-[^-]+-[^-]+\.[^.]*$/;
697            $done->{full}{$_} and next;
698            my $rep = $group->{size}{$_}{$listnumber}[2];
699            if ($fentry->{exclude}) {
700                $exclude->($_, $name);
701                next
702            }
703            if ($done->{name}{$pkgname} && $done->{name}{$pkgname}[3] == $listnumber) {
704                if (!$fentry->{update} || !$done->{name}{$pkgname}[2]{done}) {
705                    if ($rep < $done->{name}{$pkgname}[1]) {
706                        $pkg{$done->{name}{$pkgname}[0]} = 0;
707                        log_("REPLACING $done->{name}{$pkgname}[0] with $_ (list $listnumber)\n", $config->{verbose}, $config->{LOG}, 4);
708                        $pkg{$_} = 1;
709                        my $a = [ $_, $rep, $fentry, $listnumber ];
710                        $done->{name}{$pkgname} = $a;
711                        $done->{full}{$_} = 1
712                    } elsif ($done->{name}{$pkgname}[1] == $rep) {
713                        if (rpmVersionCompare($done->{name}{$pkgname}[0], $_) < 0) {
714                            $pkg{$done->{name}{$pkgname}[0]} = 0;
715                            log_("REPLACING $done->{name}{$pkgname}[0] with $_ (list $listnumber)\n", $config->{verbose}, $config->{LOG}, 4);
716                            $pkg{$_} = 1;
717                            my $a = [ $_, $rep, $fentry, $listnumber ];
718                            $done->{name}{$pkgname} = $a;
719                            $done->{full}{$_} = 1
720                        }
721                    }
722                }
723            } else { 
724                $pkg{$_} = 1; 
725                my $a  = [ $_, $rep, $fentry, $listnumber ];
726                $done->{name}{$pkgname} = $a;
727                $done->{full}{$_} = 1 }
728        }
729    } else {
730        my $rep = -1;
731        my $pkg;
732        # FIXME present algorythm selects only one package per version, and choose the one in the list declared first.
733        # Maybe adding all the version and letting closeRRPMsList choose the right one is better.
734        foreach (@toadd) {
735            if (!$_) { log_("ERROR addRPMToList: empty rpm\n",1, $config->{LOG}, 2); next }
736            if ($rpmfile->{$listnumber}{$_}) { log_("WARNING addRPMToList: do not replace $_ entry in rpmfile\n", $config->{verbose}, $config->{LOG}, 1); next }
737            $group->{size}{$_}{$listnumber} or next;
738            $group->{brokendeps}{$_} == 2 and next;
739            $group->{brokendeps}{$_} == 3 and next;
740            if ($fentry->{exclude}) {
741                $exclude->($_, $name);
742                next;
743            }
744            if ($group->{size}{$_}{$listnumber}[2] < $rep || $rep == -1)  {
745                $rep = $group->{size}{$_}{$listnumber}[2];
746                log_("addRPMToList: choosing $_ (rep $rep)\n", $config->{verbose}, $config->{LOG}, 2);
747                $pkg = $_
748            } elsif ($group->{size}{$_}{$listnumber}[2] == $rep) {
749                if (rpmVersionCompare($pkg, $_) < 0) {
750                    $rep = $group->{size}{$_}{$listnumber}[2];
751                    log_("addRPMToList: choosing $_ (rep $rep)\n", $config->{verbose}, $config->{LOG}, 2);
752                    $pkg = $_
753                }
754            }
755        }
756        my ($pkgname) = $pkg =~ /^(.*)-[^-]+-[^-]+\.[^.]*$/;
757        if (!$done->{name}{$pkgname}) { 
758            $pkg{$pkg} = 1; 
759            my $a = [ $pkg, $rep, $fentry, $listnumber ]; 
760            $done->{name}{$pkgname} = $a;
761            $done->{full}{$pkg} = 1 }
762    }
763    $fentry->{exclude} and return 1;
764    foreach (keys %pkg) {
765        if ($rpmfile->{$listnumber}{$_}) {log_("WARNING addRPMToList: do not replace $_ entry in rpmfile\n", $config->{verbose}, $config->{LOG}, 1); next }
766        $pkg{$_} or next;
767        defined $fentry->{rate} and $group->{pkgrate}{$_} = $fentry->{rate} and log_("addRPMToList: setting $_ rate to $fentry->{rate}\n",1, $config->{LOG}, 2);
768        my %ht;
769        foreach my $k (keys %$fentry) { $ht{$k} = $fentry->{$k} }
770        $rpmfile->{$listnumber}{$_} = \%ht;     
771        log_("addRPMToList: ADDED $_ (list $listnumber) options " . join(" ", keys %ht) . "\n", $config->{verbose}, $config->{LOG}, 4)
772    }
773}
774
775sub build_list {
776    my ($class, $group) = @_;
777    my %rpmfile;
778    my $filelist = $group->{filelist};
779    my @fullrpm = keys %{$group->{urpm}{rpm}};
780    my @section = keys %{$group->{rpmsrate}[1]};
781    my %done;
782    foreach my $listnumber (@{$group->{orderedlist}{rpm}}) {
783        log_("build_list: list $listnumber ($group->{listrpm}{$listnumber})\n", $config->{verbose}, $config->{LOG}, 2);
784        my $rpms = $group->{listrpm}{$listnumber};
785        if (ref $rpms) {
786            log_("$listnumber -- $group->{filelist} -- " . keys(%{$group->{filelist}}) . "\n", $config->{verbose}, $config->{LOG}, 3);
787            if (!ref $filelist->{$listnumber}) { log_("WARNING: list $listnumber has an empty file list\n", $config->{verbose}, $config->{LOG}, 1); next }
788            log_("build_list: FILE LIST $listnumber (" . int @{$filelist->{$listnumber}} . ")\n", $config->{verbose}, $config->{LOG}, 4);
789            foreach my $fentry (@{$filelist->{$listnumber}}) {
790                my $name = $fentry->[0];
791                my $opt = $fentry->[1]; 
792                log_("build_list: processing $name " . join(' ', keys %$opt) . "\n", $config->{verbose}, $config->{LOG}, 5);
793                my @toadd;
794                if ($opt->{section}) {
795                    my $level = $opt->{section};
796                    log_("build_list: selecting rpmsrate package of section $name with score higher than $level\n", $config->{verbose}, $config->{LOG}, 2);
797                    $opt->{section} = 0;
798                    if ($opt->{regexp}) {
799                        $opt->{regexp} = 0;
800                        @toadd = grep { /$name/ } @section;
801                        log_("$name (@section) -> @toadd\n", $config->{verbose}, $config->{LOG}, 4);
802                        foreach (@toadd) {
803                            foreach (@{$group->{rpmsrate}[1]{$_}}) {
804                                log_("$_ -> $group->{rpmsrate}[0]{$_}\n", $config->{verbose}, $config->{LOG}, 4);
805                                if ($group->{rpmsrate}[0]{$_} >= $level) {
806                                    addRPMToList($group, $listnumber, \%rpmfile, \%done, $rpms, $opt, $_);
807                                }
808                            }
809                        }
810                    } else {
811                        my $rpmlist = $group->{rpmsrate}[1]{$name} or do { log_("ERROR build_list: $name unknown rpmsrate section\n", $config->{verbose}, $config->{LOG}, 0); next };
812                        foreach (@$rpmlist) {
813                            if ($group->{rpmsrate}[0]{$_} >= $level) {
814                                addRPMToList($group, $listnumber, \%rpmfile, \%done, $rpms, $opt, $_)
815                            }
816                        }
817                    }
818                } else {
819                    addRPMToList($group, $listnumber, \%rpmfile, \%done, $rpms, $opt, $name);
820                }
821            }
822        } else {
823            log_("WARNING: List $listnumber is empty, ignoring\n", $config->{verbose}, $config->{LOG}, 0);     
824            $class->{config}{list}[$listnumber]{empty} = 1;
825        }
826    }
827    my $revdeps;
828    if (!$class->{config}{nodeps} && !$group->{options}{nodeps}) {
829        my @toadd = grep { /^basesystem-[^-]+-[^-]+\.[^.]*$/ } @fullrpm; 
830        my $pkg;
831        my $listnumber;
832        foreach (@toadd) {
833            my $l = find_list($group, $_);
834            if ($group->{listmatrix}{rpm}{$listnumber}{$l} || !$listnumber) {
835                $pkg = $_;
836                $listnumber = $l
837            }
838        }
839        if ($pkg) {
840            $rpmfile{$listnumber}{$pkg} = {};
841            log_("build_list ADDED $pkg (list $listnumber)\n", $config->{verbose}, $config->{LOG}, 4);
842        } else { log_("ERROR: basesystem package is not available.\n",1, $config->{LOG}) }
843
844        $revdeps = reverseDepslist($class, $group, \%rpmfile);
845        # add deps
846        closeRpmsList($group, \%rpmfile)
847    }
848    (\%rpmfile, $revdeps)
849}
850
851sub addRPMToDiff {
852    my ($rpm, $rpmd, $diff, $cdnum, $repnumber, $i, $list, $curdir, $size, $rpmsize, $totrpmsize, $repnum, $done, $packages) = @_;
853    my @data;
854    for (my $s; $s < @$rpm; $s++) {
855        push @data, [$rpm->[$s],1, $rpmd->[$s], $rpmsize->[$s]];
856        log_("addRPMToDiff: $rpm->[$s] put in rep $repnumber\n", $config->{verbose}, $config->{LOG}, 4);
857        $done->{rep}{$rpm->[$s]} = $repnumber;
858        $done->{list}{$rpm->[$s]} = $list;
859    }
860    my $idx = push @{$diff->{data}}, [ $curdir, $i, $list, $repnum, 1, \@data, $rpmd, $totrpmsize ];
861    push @{$diff->{idx}}, --$idx;
862    $size->{disc}[$cdnum] += $totrpmsize;
863    $size->{rep}{$cdnum}{$curdir->[1]}{$list} += $totrpmsize;
864    log_("addRPMToDiff: SIZE disc $cdnum: $size->{disc}[$cdnum] (+ @$rpm $totrpmsize ID $idx) added rpmd $rpmd\n", $config->{verbose}, $config->{LOG}, 3);
865    1
866}
867
868sub find_list {
869    my ($group, $r, $list, $notdone) = @_;
870    my $l;
871    foreach (keys %{$group->{size}{$r}}) {
872        #log_("find_list: for $r trying list $_ (listmatrix $l - $_ -> $group->{listmatrix}{rpm}{$l}{$_} listmatrix $list - $_ -> $group->{listmatrix}{rpm}{$list}{$_})\n",$config->{verbose}, $config->{LOG}, 7);
873        $l = $_ if ( ($l && $group->{listmatrix}{rpm}{$l}{$_}
874                       || 
875                     (!$l && ($group->{listmatrix}{rpm}{$list}{$_} || !$list)))
876                   && ($notdone && !$config->{list}[$_]{done} || !$notdone))
877    }
878    return $l
879}
880
881sub processDeps {
882    my ($r, $group, $done, $rpmlist, $topush, $intopush, $depsdisc, $rpmd, $list, $loop, $i, $tobedone, $buildlist, $rpm, $needed) = @_;
883    log_("processDeps: deps $r\n", $config->{verbose}, $config->{LOG}, 3);
884    my $tcd = $done->{rep}{$r} if !$rpmlist->[$i]{$done->{list}{$r}}{$r}{noprovide};
885    my $l = find_list($group, $r, $list, !$tcd);
886    if ($group->{rejected}{$r}) { 
887        log_("ERROR processDeps: deps $r rejected, rejecting @$rpm\n",1, $config->{LOG}, 1);
888        log_("Rejecting @$rpm $r\n", $config->{verbose}, $config->{LOG},1);
889        foreach (@$rpm) { push @{$group->{rejected}{$_}}, ["deps_rejected", $r] }
890        $$loop = 1; %$topush = (); return 0 
891    }
892    if ($tcd) {
893        if ($tcd > $$depsdisc) { $$depsdisc = $tcd };
894        log_("processDeps: deps done $r on rep $tcd ($$depsdisc) list $done->{list}{$r}\n", $config->{verbose}, $config->{LOG}, 4);
895        return 2 
896    }
897    if ($tobedone->{$r}) {
898        if ($l == $list) {
899            log_("$r tobedone\n", $config->{verbose}, $config->{LOG},3);
900            if ($intopush->{$r}) { log_("WARNING processDeps: $r added twice\n", $config->{verbose}, $config->{LOG}, 3); return 1 }
901            push @$rpmd, [$r, $rpmlist->[$i]{$l}{$r}];
902            $intopush->{$r} = 1;
903            push @{$topush->{$l}}, $rpmd; 
904            log_("processDeps: adding looping deps $r ($_ -- $l) with @$rpm\n", $config->{verbose}, $config->{LOG},3)
905        } else {
906                if ($group->{listmatrix}{rpm}{$list}{$l}) {
907                    # FIXME tobedone may not mean dependencies loop in parallel mode for different list.
908                    log_("processDeps: $r is already scheduled on list $l, waiting.\n", $config->{verbose}, $config->{LOG},4);
909                    %$topush = ();
910                    push @{$buildlist->[$i]{$list}}, @$rpmd > 1 ? $rpmd : $rpmd->[0];
911                    return 3
912                    #$intopush{$r} and log_("ERROR: $r added twice\n",1, $config->{LOG}) and return 0;
913                    #$intopush{$r} = 1;
914                    #push @{$topush{$l}}, [$r, $rpmlist->[$i]{$l}{$r}];
915                    #log_("DEPS $r ($_ -- $l)\n", $config->{verbose}, $config->{LOG})
916                } else {
917                    log_("ERROR processDeps: deps $r could not be put in directory before packages @$rpm\n", $config->{verbose}, $config->{LOG},1);
918                    log_("Rejecting @$rpm $r\n", $config->{verbose}, $config->{LOG},1);
919                    reject_rpm($rpm, $group, 'order_pb', $r, \$loop, $topush);
920                    return 0
921            }
922        }
923    } else {
924        if ($l == $list) {
925            if ($intopush->{$r}) { log_("WARNING processDeps: $r added twice\n",1, $config->{LOG},2); return 1}
926            $intopush->{$r} = 1;
927            push @{$topush->{$l}}, [$r, $rpmlist->[$i]{$l}{$r}]; 
928            log_("processDeps: adding normal deps $r ($_ -- $l)\n", $config->{verbose}, $config->{LOG},3)
929        } else {
930            if ($group->{options}{sequential}) {
931                log_("WARNING processDeps: could not add interlist deps in sequential mode\n",1, $config->{LOG},2);
932                reject_rpm($rpm, $group, 'sequential', $r, \$loop, $topush);
933                return 0
934            } else {
935                if (defined $needed->{$list}{asap} && grep { $l == $_->[0] } @{$needed->{$list}{asap}}) {
936                    log_("ERROR processDeps: list of deps $r is already wainting for @$rpm list\n",1, $config->{LOG},1);
937                    reject_rpm($rpm, $group, 'order_pb', $r, \$loop);
938                    return 0
939                } else {
940                    if ($group->{listmatrix}{rpm}{$list}{$l}) {
941                        if ($intopush->{$r}) { log_("WARNING processDeps: $r added twice\n",1, $config->{LOG},2); return 1 }
942                        $intopush->{$r} = 1;
943                        push @{$topush->{$l}}, [$r, $rpmlist->[$i]{$l}{$r}]; 
944                        log_("processDeps: adding normal deps $r ($_ -- $l)\n", $config->{verbose}, $config->{LOG},3)
945                    } else {
946                        log_("ERROR processDeps: deps $r could not be put in directory before packages @$rpm\n",1, $config->{LOG},1);
947                        reject_rpm($rpm, $group, 'order_pb', $r, \$loop);
948                        return 0
949                    } 
950                }
951            }
952        }
953    }
954}
955
956sub reject_rpm {
957    my ($rpm, $group, $reason, $r, $loop, $topush) = @_;
958    log_("Rejecting @$rpm\n", $config->{verbose}, $config->{LOG},1);
959    foreach (@$rpm) { push @{$group->{rejected}{$_}}, [ $reason, $r ] }
960    %$topush = ();
961    $$loop = 1;
962}
963
964sub updateGenericLimit {
965    my ($groups, $cdsize) = @_;
966    log_("updateGenericLimit\n", $config->{verbose}, $config->{LOG},2);
967    for (my $i; $i < @$groups; $i++) {
968        foreach my $type (keys %{$groups->[$i]{orderedlist}}) {
969            foreach my $list (@{$groups->[$i]{orderedlist}{$type}}) {
970                foreach my $r (@{$groups->[$i]{list}{$list}{$type}}) {
971                    my ($cd, $rep, $repopt) = @$r;
972                    #log_("trying to update disc $cd rep $rep list $list limit repopt $repopt (",1, $config->{LOG}),keys %$repopt,") opt $opt (",keys %$opt,")\n";
973                    $config->{list}[$list]{disc}{$cd}{$rep}{done} and next;
974                    $repopt->{limit} or next;
975                    $repopt->{limit}{size} = $repopt->{limit}{value} * $cdsize->[$cd];
976                    log_("updateGenericLimit: setting disc $cd rep $rep list $list limit to $repopt->{limit}{size} ($repopt->{limit}{value} * $cdsize->[$cd])\n", $config->{verbose}, $config->{LOG}, 3);
977                }
978            }
979        }
980    }
981}
982
983sub testSoftLimit {
984    my ($opt, $cd, $groups, $buildlist) = @_;
985    log_("testSoftLimit\n", $config->{verbose}, $config->{LOG}, 2);
986    my $softnok = 1;
987    # FIXME this code must be tested
988    if ($opt->{limit} && $opt->{limit}{soft}) {
989        foreach my $l (@{$config->{disc}[$cd]{fastgeneric}}) {
990            my $lst = $l->[2]{list};
991            for (my $i; $i < @$groups; $i++) {
992                $groups->[$i]{list}{$lst} or next;     
993                $softnok = 0 if (@{$buildlist->[$i]{$lst}} && !($lst->{limit} && $lst->{limit}{soft}))   
994            }
995        }
996    }
997    return $softnok;
998}
999
1000sub add_one_disc {
1001    my ($cdlists, $group, $cdsize, $list, $cds, $sources, $size, $g) = @_;
1002    my $ncd;
1003    foreach (keys %$cdlists) {
1004        $ncd = $_ + 1 if $ncd <= $_
1005    }
1006    log_("add_one_disc: $config->{list}[$list]{cd} -- $ncd\n", $config->{verbose}, $config->{LOG}, 3);
1007    if (!$config->{list}[$list]{cd} || $config->{list}[$list]{cd} >= $ncd) {
1008        log_("add_one_disc: adding new disc $ncd\n", $config->{verbose}, $config->{LOG}, 4);
1009        $config->{disc}[$ncd]{size} = $config->{discsize};
1010        my $functions = $config->{group}{disc}{functions}{functions};
1011        $cdsize->[$ncd] = $config->{discsize};
1012        $config->{disc}[$ncd]{name} = $ncd;
1013        $size->{optimize_space}{disc}{$ncd} = $cdsize->[$ncd];
1014        $group->{disc_impacted}{$ncd} = 1;
1015        my ($curdir, $srpmcurdir);
1016        my $tmp = "$config->{tmp}/build/$config->{name}";
1017        my $f = "$tmp/$ncd.list";
1018        -f $f and unlink $f;
1019        if ($config->{nolive}) {
1020            log_("makeDisc: removing $tmp/$ncd\n", $config->{verbose}, $config->{LOG}, 3);
1021            rmtree "$tmp/$ncd";
1022            mkpath "$tmp/$ncd";
1023        } else {
1024            my $dir = "$config->{topdir}/build/$config->{name}";
1025            rmtree "$dir/$ncd";
1026            rmtree "$dir/first/$ncd";
1027            mkpath "$dir/$ncd"
1028        }
1029        my $instcd = $group->{installDisc};
1030        my ($rep, $src_rep);
1031
1032        if ($sources && $config->{list}[$list]{sources} && $config->{list}[$list]{sources}{separate}) {
1033            $config->{disc}[$ncd]{serial} = "$config->{name}-$ncd-src";
1034            $config->{disc}[$ncd]{longname} = "MandrakeLinux $config->{name} sources";
1035            $config->{disc}[$ncd]{appname} = "MandrakeLinux $config->{name} sources disc $ncd";
1036            $config->{disc}[$ncd]{label} = substr "MandrakeLinux-$config->{name}-$ncd.src", 0, 32;
1037            $config->{disc}[$ncd]{group_list}{$g}{$list}{srpm} = 1;
1038            &{$functions->{dir}[0][5]}($ncd, 3, "srpms", "Mandrake/SRPMS");
1039            &{$functions->{generic}[0][5]}($ncd, 4, "srpms",1);
1040            &{$functions->{generic}[1][5]}($ncd, 5, { source => 1 });
1041            push @{$config->{disc}[$instcd]{function}{data}{installation}[1]{srpmsdir}}, [ 0, $ncd, "srpms" ];
1042            $srpmcurdir = [ $ncd, "srpms" ];
1043            push @{$group->{list}{$list}{srpm}}, $srpmcurdir;
1044            $src_rep = $group->{maxrep}{srpm};
1045            push @{$group->{replist}{srpm}}, [ $ncd, 'srpms', $group->{maxrep}{srpm}++, { $list => $srpmcurdir } ];
1046        } else {
1047            $config->{disc}[$ncd]{serial} = "$config->{name}-$ncd";
1048            $config->{disc}[$ncd]{longname} = "MandrakeLinux $config->{name}";
1049            $config->{disc}[$ncd]{appname} = "MandrakeLinux $config->{name} disc $ncd";
1050            $config->{disc}[$ncd]{label} = substr "MandrakeLinux-$config->{name}-$ncd.i586", 0, 32;
1051            $config->{disc}[$ncd]{group_list}{$g}{$list}{rpm} = 1;
1052            &{$functions->{dir}[0][5]}($ncd, 1, "rpms", "Mandrake/RPMS$ncd");
1053            &{$functions->{generic}[0][5]}($ncd, 2, "rpms", 1);
1054            $group->{orderedrep}{rpm}{"$ncd/rpms"} = $ncd;
1055            #
1056            # generic has no FIXED part, otherwize a call to generic with fixed=0
1057            # would have been needed
1058            #
1059            $curdir = [$ncd, "rpms"];
1060            push @{$group->{list}{$list}{rpm}}, $curdir;
1061            $rep = $group->{maxrep}{rpm};
1062            if ($group->{replist}{rpm}[$group->{maxrep}{rpm}-1]) {
1063                die "FATAL add_one_disc: rep $group->{maxrep}{rpm} should not exist !\n"
1064            } else {
1065                $group->{replist}{rpm}[$group->{maxrep}{rpm}-1], [ $ncd, 'rpms', $group->{maxrep}{rpm}++, { $list => $curdir } ];
1066            }
1067            push @{$config->{disc}[$instcd]{function}{data}{installation}[1]{rpmsdir}}, [ 0, $ncd, "rpms" ];
1068            if ($config->{list}[$list]{sources}) {
1069                &{$functions->{dir}[0][5]}($ncd,3, "srpms", "Mandrake/SRPMS");
1070                &{$functions->{generic}[0][5]}($ncd,4, "srpms",1);
1071                &{$functions->{generic}[1][5]}($ncd,5, { source => 1 });
1072                push @{$config->{disc}[$instcd]{function}{data}{installation}[1]{srpmsdir}}, [ 0, $ncd, "srpms" ];
1073                $srpmcurdir = [ $ncd, "srpms" ];
1074                $src_rep = $group->{maxrep}{srpm};
1075                if ($group->{replist}{srpm}[$group->{maxrep}{srpm}-1]) {
1076                    die "FATAL add_one_disc: rep $group->{maxrep}{srpm} should not exist !\n"
1077                } else {
1078                    $group->{replist}{srpm}[$group->{maxrep}{srpm}-1], [ $ncd, 'srpms', $group->{maxrep}{srpm}++, { $list => $srpmcurdir } ];
1079                } 
1080                push @{$group->{list}{$list}{srpm}}, $srpmcurdir
1081            }
1082        }
1083        push @$cds, $ncd;
1084        $cdlists->{$ncd} = 2;
1085        return $curdir, $rep, $srpmcurdir, $src_rep
1086    } else { return 0 }
1087}
1088
1089sub addSRPMToDiff {
1090    my ($rpmd, $done, $diff, $size, $srpmrep, $srpmsize, $curdir, $srpm, $list, $i, $cdnum) = @_;
1091    for (my $s; $s < @$rpmd; $s++) {
1092        if (!$rpmd->[$s][1]{nosrc} && !$done->{rep}{$srpm->[$s]}) {
1093            my $srep = $srpmrep->{$srpm->[$s]};
1094            my $idx = push @{$diff->{data}}, [ $srep->[2], $i, $list, $srep->[1], 2, [[$srpm->[$s],1, $rpmd->[$s], $srpmsize->[$s]]], 0, $srpmsize->[$s] ];
1095            push @{$diff->{idx}}, $idx - 1;
1096            $size->{disc}[$srep->[0]] += $srpmsize->[$s];
1097            $size->{rep}{$srep->[0]}{$srep->[2][1]}{$list} += $srpmsize->[$s];
1098            log_("SIZE disc $srep->[0]: $size->{disc}[$srep->[0]] (+ $srpm->[$s] $srpmsize->[$s])\n", $config->{verbose}, $config->{LOG}, 2);
1099        }
1100        $done->{rep}{$srpm->[$s]}++;
1101        $done->{list}{$srpm->[$s]} = $list
1102    }
1103    1
1104}
1105
1106sub sourcesSizeCheck {
1107    my ($done, $rpmd, $srpm, $group, $groups, $size, $cdsize, $list, $cdlists, $cdnum, $rpmsize, $buildlist, $cds, $i, $diff) = @_;
1108    my %srpmrep;   
1109    my $srpmok = 1;
1110    my @srpmsize;
1111    for (my $s; $s < @$srpm; $s++) {
1112        $done->{rep}{$srpm->[$s]} and next;
1113        $rpmd->[$s][1]{nosrc} and next;
1114        my $srpmsize = $group->{size}{$srpm->[$s]}{$list}[0];
1115        $srpmsize[$s] = $srpmsize;
1116        for (my $k; $k < @{$group->{list}{$list}{srpm}}; $k++) {
1117            my $srpmdir = $group->{list}{$list}{srpm}[$k];
1118            my ($srccd, $srcrepname, $srcopt) = @$srpmdir;
1119            my $src_rep_num = $group->{orderedrep}{srpm}{"$srccd/$srcrepname"};
1120            log_("trying source disc $srccd\n", $config->{verbose}, $config->{LOG}, 2);
1121            $cdlists->{$srccd} > 1 or next;
1122            my $currentrpm;
1123            $cdnum == $srccd and $currentrpm = $rpmsize;
1124            my $softnok = testSoftLimit($srcopt, $srccd, $groups, $buildlist);
1125            my $gain = $size->{disc}[$srccd] + $srpmsize + $currentrpm - $cdsize->[$srccd];
1126            # FIXME this need to be tested
1127            if ($gain <= 0 && !($srcopt->{limit} && ($softnok || !$srcopt->{limit}{soft}) && $size->{rep}{$srccd}{$srcrepname}{$list} > $srcopt->{limit}{size})) {
1128                $srpmrep{$srpm->[$s]} = [$srccd, $src_rep_num, $srpmdir];
1129                last
1130            } elsif ($k == $#{$group->{list}{$list}{srpm}}) {
1131                if (optimize_space($config, $groups, $diff, $size, $cdsize, $srccd, $gain, $cdlists,0, $i, $list, 'srpm', $srpmsize + $currentrpm) < $gain) {
1132                    $srpmok = 0
1133                } else {
1134                    $srpmrep{$srpm->[$s]} = [$srccd, $src_rep_num, $srpmdir];
1135                }
1136            }
1137        }
1138        if (!$srpmrep{$srpm->[$s]}) {
1139            $srpmok = 0
1140            # no last here because if in autoMode a CD will be added after and we will not retest for each srpm if it could be put on an existing CD.
1141        }
1142    }
1143    if (!$srpmok && $config->{list}[$list]{auto}) {
1144        my (undef, undef, $srpmdir, $repnum) = add_one_disc($cdlists, $group, $cdsize, $list, $cds, 1, $size, $i);
1145        if ($srpmdir) {
1146            for (my $s; $s < @$srpm; $s++) {
1147                if (!$srpmrep{$srpm->[$s]}) {
1148                    $srpmrep{$srpm->[$s]} = [$srpmdir->[0], $repnum, $srpmdir];
1149                }
1150            }
1151            $srpmok = 1
1152        }
1153    }
1154    return \%srpmrep, \@srpmsize, $srpmok
1155}
1156
1157sub choose_alt {
1158    my ($deps, $rpmlist, $group, $cdnum, $repname, $list, $buildlist, $intopush, $tobedone, $needed) = @_;
1159    my $r = -1;
1160    my $score = [ 0, $group->{maxlist} ];
1161    my $done = $group->{done};
1162    foreach my $testalt (1,0) {
1163        foreach (@$deps) {
1164            # FIXME it may have a problem here, as depslistid are not erased when the
1165            # package is removed, that is to say that if the previous deps failed for
1166            # any reason, alternates deps may be added, although excluded before
1167            # however this _must_ not happen, and signify a bug somewhere else.
1168            my $pkg = $group->{depslistid}[$_];
1169
1170            my $l = find_list($group, $pkg, $list);
1171            if ($testalt && $rpmlist->{$l}{$pkg}{noalternatives}) { log_("choose_alt: $pkg is not selected in first pass for alternatives\n", $config->{verbose}, $config->{LOG},6); next }
1172            $intopush->{$pkg} and $r = $pkg and last;
1173            log_("choose_alt: alternatives deps $pkg\n", $config->{verbose}, $config->{LOG}, 6);
1174            if ($group->{rejected}{$pkg}) { log_("choose_alt: $pkg is rejected, ignoring\n", $config->{verbose}, $config->{LOG}, 6); next }
1175            my $tcd = $done->{rep}{$pkg} if !$rpmlist->{$done->{list}{$pkg}}{$pkg}{noprovide} || $done->{rep}{$pkg} <= $group->{orderedrep}{rpm}{"$cdnum/$repname"};
1176            if ($tcd && $tcd <= $group->{orderedrep}{rpm}{"$cdnum/$repname"}) {
1177                log_("$pkg ($tcd) done\n", $config->{verbose}, $config->{LOG}, 6);
1178                $r = 0;
1179                last
1180            } 
1181            my $s = $group->{scorelist}{$pkg};
1182            my $pkgList = find_list($group, $pkg, $list, !$tcd);
1183            #log_("choose_alt: pkg $pkg buildlist $buildlist list $pkgList other list $list tcd $tcd list $l ($buildlist->{$pkgList})\n", $config->{verbose}, $config->{LOG}, 6);
1184            if ($pkgList && $list != $pkgList && ((defined $needed->{$pkgList}{asap} && grep { $list == $_->[0] } @{$needed->{$pkgList}{asap}}) || ($group->{options}{sequential} && !$config->{list}[$pkgList]{done} && @{$buildlist->{$pkgList}}))) { next }
1185            log_("choose_alt: $pkg list $pkgList\n", $config->{verbose}, $config->{LOG}, 6);
1186            if (!$tcd && $group->{listmatrix}{rpm}{$list}{$pkgList}) {
1187                if ($group->{listsort}{$pkgList}{rpm} < $score->[1] || $group->{listsort}{$pkgList}{rpm} == $score->[1] && $s > $score->[0]) {
1188                    log_("choose_alt: choosing $pkg ($s, $group->{listsort}{$pkgList}{rpm})\n", $config->{verbose}, $config->{LOG}, 6);
1189                    $score = [ $s, $group->{listsort}{$pkgList}{rpm} ];
1190                    $r = $pkg;
1191                    last if $tobedone->{$r} 
1192                }
1193            }
1194        }
1195        $r and last
1196    }
1197    return $r
1198}
1199
1200sub check_deps {
1201    my ($rpmd, $group, $done, $rpmlist, $list, $i, $tobedone, $buildlist, $rpm, $cdnum, $repname, $needed, $thisorderrep) = @_;
1202    my $deps = get_pkgs_deps($rpmd, $group);
1203    my $loop;
1204    if (@$deps) {
1205        my ($waiting, %topush, %intopush, $depsdisc);
1206        foreach (@$deps) {
1207            if (!ref $_) {
1208                my $a = processDeps($group->{depslistid}[$_], $group, $done, $rpmlist, \%topush, \%intopush, \$depsdisc, $rpmd, $list, \$loop, $i, $tobedone, $buildlist, $rpm, $needed->[$i]);
1209                if ($a < 0) { return 0 } elsif ($a == 0) { last } elsif ($a == 2) { next } elsif ($a == 3) { $waiting = 1; last  }
1210            } else {
1211                # must create a virtual package that install all of them in one loop
1212                log_("check_deps: alternatives deps @$_\n", $config->{verbose}, $config->{LOG}, 5);
1213                my $r = choose_alt($_, $rpmlist->[$i], $group, $cdnum, $repname, $list, $buildlist->[$i], \%intopush, $tobedone, $needed->[$i]);
1214                $intopush{$r} and next;
1215                if ($r == -1) {
1216                    log_("ERROR check_deps: alternatives deps (@$_) could not be put in directory before packages @$rpm\n", $config->{verbose}, $config->{LOG}, 2);
1217                    log_("Rejecting @$rpm\n", $config->{verbose}, $config->{LOG},2);
1218                    foreach my $p (@$rpm) { push @{$group->{rejected}{$p}}, ["order_pb", "@$_"] }
1219                    %topush = ();
1220                    $loop = 1;
1221                    last
1222                }
1223                if ($r) { 
1224                    my $a = processDeps($r, $group, $done, $rpmlist, \%topush, \%intopush, \$depsdisc, $rpmd, $list, \$loop, $i, $tobedone, $buildlist, $rpm, $needed->[$i]);
1225                    if ($a < 0) { return 0 } elsif ($a == 0) { last } elsif ($a == 2) { next } elsif ($a == 3) { $waiting = 1; last  }
1226                } else {
1227                    log_("Finding better alternatives rep (@$_ - $depsdisc)\n", $config->{verbose}, $config->{LOG}, 4);
1228                    my $bestdisc = keys %{$group->{orderedrep}{rpm}};
1229                    if ($bestdisc >= $depsdisc) {
1230                        foreach (@$_) {
1231                            my $pkg = $group->{depslistid}[$_];
1232                            if ($group->{rejected}{$pkg}) { log_("$pkg rejected\n", $config->{verbose}, $config->{LOG}, 2); next }
1233                            my $tcd = $done->{rep}{$pkg};
1234                            $tcd or next;
1235                            log_("$pkg => rep $tcd\n", $config->{verbose}, $config->{LOG}, 4);
1236                            if ($tcd < $bestdisc) { $bestdisc = $tcd }
1237                        }
1238                        $bestdisc > $depsdisc and $depsdisc = $bestdisc
1239                    }
1240                    log_("Finding better alternatives rep result $depsdisc\n", $config->{verbose}, $config->{LOG}, 4);
1241                }
1242            }
1243        }
1244        $waiting and return 1;
1245        if (keys %topush) {
1246            $loop = 1;
1247            log_("Adding dependencies, looping\n", $config->{verbose}, $config->{LOG}, 3);
1248            my $test = @$rpmd > 1 ? $rpmd : $rpmd->[0];
1249            push @{$buildlist->[$i]{$list}}, @$rpmd > 1 ? $rpmd : $rpmd->[0];
1250            foreach (keys %topush) {
1251                $list != $_ and push @{$needed->[$i]{$list}{asap}}, [ $_, int @{$buildlist->[$i]{$_}} ];
1252                push @{$buildlist->[$i]{$_}}, @{$topush{$_}}
1253            }
1254        } elsif ($thisorderrep < $depsdisc) {
1255            $loop = 1;
1256            if ($group->{listmaxrep}{rpm}{$list} >= $depsdisc) {
1257                # has a chance to put it after depsdic
1258                log_("Dependencies on further directories ($depsdisc)\n", $config->{verbose}, $config->{LOG}, 3);
1259            } else {
1260                log_("check_deps: dependencies are in further directories, rejecting @$rpm\n", $config->{verbose}, $config->{LOG}, 2);
1261                foreach (@$rpm) { push @{$group->{rejected}{$_}}, ["order_pb", ""] }
1262            }
1263        }
1264    }
1265    $loop
1266}
1267
1268sub put_in_rep {
1269    my ($i, $groups, $group, $size, $rpmsize, $all_rpmsize, $cdsize, $needed, $rpm, $rpmd, $list, $cdlists, $buildlist, $diff, $cds, $done, $tobedone, $rpmlist, $nosrcfit) = @_; 
1270    my $loop;
1271    my $dn;
1272    log_("put_in_rep: @$rpm\n", $config->{verbose}, $config->{LOG}, 3);
1273    for (my $j; !$loop && !$dn && $j < @{$group->{list}{$list}{rpm}}; $j++) {
1274        $loop = 0;
1275        my $curdir = $group->{list}{$list}{rpm}[$j];
1276        $config->{list}[$list]{disc}{$curdir->[0]}{$curdir->[1]}{done} and next;
1277        my ($cdnum, $repname, $repopt) = @$curdir;
1278        my $rep_num = $group->{orderedrep}{rpm}{"$cdnum/$repname"};
1279        $cdlists->{$cdnum} > 1 or next;
1280        my $thisorderrep = $group->{orderedrep}{rpm}{"$cdnum/$repname"};
1281        my $softnok = testSoftLimit($repopt, $cdnum, $groups, $buildlist);
1282        my $gain = $size->{disc}[$cdnum] + $all_rpmsize - $cdsize->[$cdnum];
1283        log_("put_in_rep: curdir cd $cdnum (space $gain rpm size $all_rpmsize) rep $repname rep_num $rep_num softnok $softnok\n", $config->{verbose}, $config->{LOG}, 4);
1284        if ($gain > 0 || $repopt->{limit} && ($softnok || !$repopt->{limit}{soft}) && $size->{rep}{$cdnum}{$repname}{$list} + $all_rpmsize > $repopt->{limit}{size}) {
1285            if ($j == $#{$group->{list}{$list}{rpm}}) {
1286                if (!($repopt->{limit} && !$softnok && $repopt->{limit}{soft})) {
1287                    if (optimize_space($config, $groups, $diff, $size, $cdsize, $cdnum, $gain, $cdlists,0, $i, $list, 'rpm', $all_rpmsize) < $gain) {
1288                        if ($config->{list}[$list]{auto}) {
1289                            ($curdir, $rep_num) = add_one_disc($cdlists, $group, $cdsize, $list, $cds,0, $size, $i);
1290                            if ($curdir) {
1291                                $cdnum = $curdir->[0]
1292                            } else {
1293                                log_("Could not add more disc, rejecting @$rpm\n", $config->{verbose}, $config->{LOG}, 2);
1294                                foreach my $p (@$rpm) { push @{$group->{rejected}{$p}}, [ "no_disc", "" ] }
1295                                next
1296                            }
1297                        } else {
1298                            log_("Rejecting @$rpm\n", $config->{verbose}, $config->{LOG}, 2);
1299                            foreach my $p (@$rpm) { push @{$group->{rejected}{$p}}, ["no_space", ""] }
1300                            next
1301                        }
1302                    }
1303                } else { 
1304                    foreach my $l (@{$config->{disc}[$cdnum]{fastgeneric}}) {
1305                        my $lst = $l->[2]{list};
1306                        $list == $lst and next;
1307                        for (my $i; $i < @$groups; $i++) {
1308                            $groups->[$i]{list}{$lst}{rpm} or next;     
1309                            push @{$needed->[$i]{$list}{asap}}, [ $lst, 0 ] if (!($lst->{limit} && $lst->{limit}{soft}))
1310                        }
1311                    }
1312                }
1313            } else { next }
1314        }
1315        if (!$config->{nodeps} && !$group->{options}{nodeps}) {
1316           $loop = check_deps($rpmd, $group, $done, $rpmlist, $list, $i, $tobedone->[$i], $buildlist, $rpm, $cdnum, $repname, $needed, $thisorderrep)
1317        }
1318        $loop and next; 
1319        log_("@$rpm deps ok\n", $config->{verbose}, $config->{LOG}, 4);
1320        my $nosrc = 1;
1321        my @srpm;
1322        my $donesrpm = 1;
1323        if (!$group->{options}{nosources} && @{$group->{list}{$list}{srpm}}) {
1324            for (my $s; $s < @$rpmd; $s++) {
1325                my $srpm = $group->{urpm}{sourcerpm}{$rpm->[$s]}; 
1326                $srpm =~ s/\.rpm$//;
1327                if (!$group->{size}{$srpm}{$list}) {
1328                    log_("put_in_rep ERROR: $srpm not available, trying alternatives => ", $config->{verbose}, $config->{LOG}, 5);
1329                    my ($srpmname) = $srpm =~ /(.*)-[^-]+-[^-]+\.src/;
1330                    $srpm = $group->{srpmname}{$srpmname};
1331                    if ($group->{size}{$srpm}{$list}) { 
1332                        log_(" $srpm\n", $config->{verbose}, $config->{LOG}) 
1333                    } else {
1334                        if ($srpm) {
1335                            log_("not found (but a srpm $srpm exist in another list)\n", $config->{verbose}, $config->{LOG}, 5);
1336                            $srpm = 0
1337                        } else {
1338                            log_("not found\n", $config->{verbose}, $config->{LOG}, 5) 
1339                        }
1340                    }
1341                }
1342                if ($srpm) { 
1343                    $done->{rep}{$srpm} or $donesrpm = 0;
1344                    $srpm[$s] = $srpm;
1345                    $rpmd->[$s][1]{nosrc} or $nosrc = 0 
1346                }
1347            }
1348        }
1349        log_("put_in_rep: group $i list $list: @$rpm (@srpm) -- $curdir->[0] -- $curdir->[1] -- disc $cdnum\n", $config->{verbose}, $config->{LOG}, 4);
1350        if ($config->{nosrc} || $group->{options}{nosources} || !@{$group->{list}{$list}{srpm}} || $nosrc || $donesrpm) {
1351            ($dn) = addRPMToDiff($rpm, $rpmd, $diff, $cdnum, $group->{orderedrep}{rpm}{"$cdnum/$repname"}, $i, $list, $curdir, $size, $rpmsize, $all_rpmsize, $rep_num, $done)
1352        } else {
1353            if ($config->{nosrcfit} || $group->{options}{nosrcfit}) {
1354                $dn = addRPMToDiff($rpm, $rpmd, $diff, $cdnum, $group->{orderedrep}{rpm}{"$cdnum/$repname"}, $i, $list, $curdir, $size, $rpmsize, $all_rpmsize, $rep_num, $done);
1355                push @$nosrcfit, [$rpmd, \@srpm, $list, $i, $curdir, $cdnum]
1356            } else {
1357                my ($srpmrep, $srpmsize, $srpmok) = sourcesSizeCheck($done, $rpmd, \@srpm, $group, $groups, $size, $cdsize, $list, $cdlists, $cdnum, $all_rpmsize, $buildlist, $cds, $i, $diff);
1358                if ($srpmok) {
1359                    addRPMToDiff($rpm, $rpmd, $diff, $cdnum, $group->{orderedrep}{rpm}{"$cdnum/$repname"}, $i, $list, $curdir, $size, $rpmsize, $all_rpmsize, $rep_num, $done);
1360                    $dn = addSRPMToDiff($rpmd, $done, $diff, $size, $srpmrep, $srpmsize, $curdir, \@srpm, $list, $i, $cdnum);
1361                } else {
1362                    log_("WARNING: @srpm does not fit on the discs\n",1, $config->{LOG}, 2)
1363                }
1364            }
1365            if (!$dn) {
1366                foreach my $p (@$rpm) { push @{$group->{rejected}{$p}}, ["no_space", ""] }
1367                log_("WARNING: @$rpm does not fit on the disc ($size->{disc}[$cdnum] + $all_rpmsize > $cdsize->[$cdnum]) \n", $config->{verbose}, $config->{LOG}, 1)
1368            }
1369        }
1370    }
1371    return $dn
1372}
1373
1374sub loop_on_lists {
1375    my ($i, $groups, $group, $groupok, $needed, $buildlist, $tobedone, $diff, $nosrcfit, $size, $cdsize, $cds, $rpmlist, $cdlists, $ok) = @_; 
1376    #
1377    # FIXME source rpms are not shared between group, it may be usefull for mutilple installation
1378    # with common source dir, so that the same source rpm is shared (but this is not so common).
1379    #
1380
1381    my $done = $group->{done};
1382    my $dn;
1383    log_("loop_on_lists: group $i (@{$group->{orderedlist}{rpm}})\n", $config->{verbose}, $config->{LOG}, 2);
1384    while (!$dn) {
1385        $groupok->[$i] = 1;
1386        foreach my $list (@{$group->{orderedlist}{rpm}}) {
1387            log_("loop_on_lists: list $list (empty $config->{list}[$list]{empty} done $config->{list}[$list]{done})\n", $config->{verbose}, $config->{LOG}, 3);
1388            do {
1389                $config->{list}[$list]{done} and goto end;
1390                $config->{list}[$list]{empty} and goto end;
1391                my $next;
1392                foreach (@{$needed->[$i]{$list}{asap}}) {
1393                    my $nb_elt = @{$buildlist->[$i]{$_->[0]}};
1394                    log_("List $list need list $_->[0] to be <= $_->[1] ($nb_elt)\n", $config->{verbose}, $config->{LOG}, 4);
1395                    $nb_elt <= $_->[1] or $next = 1
1396                }
1397                if ($next){
1398                    log_("List $list waiting\n",1, $config->{LOG},4);
1399                    goto end
1400                }
1401                $needed->[$i]{$list}{asap} = [];
1402                my ($trpmd, $k, $goon, @rpmd);
1403                do { 
1404                    $trpmd = pop @{$buildlist->[$i]{$list}} or goto end;
1405                    if (ref $trpmd->[0]) {
1406                        foreach (@$trpmd) {
1407                            log_("Testing $_->[0]\n", $config->{verbose}, $config->{LOG},7);
1408                            if (!$done->{rep}{$_->[0]} || $rpmlist->[$i]{$done->{list}{$_->[0]}}{$_->[0]}{noprovide}) { push @rpmd, $_ }
1409                        }
1410                    } else { 
1411                        log_("Testing $trpmd->[0]\n", $config->{verbose}, $config->{LOG},7);
1412                        if (!$done->{rep}{$trpmd->[0]} || $rpmlist->[$i]{$done->{list}{$trpmd->[0]}}{$trpmd->[0]}{noprovide}) { push @rpmd, $trpmd } }
1413                } until @rpmd;
1414                $groupok->[$i] = 0;
1415                $ok = 0;
1416                my @rpm;
1417                my $all_rpmsize;
1418                my @rpmsize;
1419                foreach (@rpmd) {
1420                    my $r = $_->[0];
1421                    !$r and log_("ERROR loop_on_lists: empty package @$_\n", $config->{verbose}, $config->{LOG}, 2);
1422                    push @rpm, $r;
1423                    log_("RPM $r (group $i list $list)\n", $config->{verbose}, $config->{LOG},6);
1424                    $tobedone->[$i]{$r} = 1;
1425                    $all_rpmsize += $group->{size}{$r}{$list}[0];
1426                    push @rpmsize, $group->{size}{$r}{$list}[0]
1427                }
1428                $dn = put_in_rep($i, $groups, $group, $size, \@rpmsize, $all_rpmsize, $cdsize, $needed, \@rpm, \@rpmd, $list, $cdlists, $buildlist, $diff, $cds, $done, $tobedone, $rpmlist, $nosrcfit); 
1429            } while $group->{options}{sequential} && @{$buildlist->[$i]{$list}};
1430            end:
1431            last if $group->{options}{sequential} && @{$buildlist->[$i]{$list}} && !$config->{list}[$list]{done}
1432        } 
1433        $groupok->[$i] and $dn = 1
1434    }
1435    return $ok
1436}
1437
1438sub calc_needed_size {
1439    my ($group, $i, $needed, $needed_size, $buildlist, $rpmlist, $tobedone) = @_;
1440    my ($msg, %local_done);
1441    $msg = "calc_needed_size\n";
1442    my $done = $group->{done};
1443    foreach my $rep (@{$group->{replist}{rpm}}) {
1444        my ($cd, $repname, $num, $l) = @$rep;
1445        $msg .= "calc_needed_size: rep $num\n";
1446        foreach my $list (keys %$needed) {
1447            $l->{$list} or next;
1448            if ($config->{list}[$list]{disc}{$cd}{$repname}{done}){
1449                log_("calc_needed_size: rep $cd/$repname for list $list is done, ignoring\n", $config->{verbose}, $config->{LOG}, 5);
1450                next
1451            }
1452            foreach my $elt (@{$needed->{$list}{alap}[$num]}) {
1453                my $rpm = $elt->[0];
1454                if (($done->{rep}{$rpm} && !$rpmlist->[$i]{$group->{done}{list}{$rpm}}{$rpm}{noprovide}) || $local_done{$rpm}) {
1455                    next
1456                }
1457                if ($group->{rejected}{$rpm}) {
1458                    $msg .= "ERROR: $rpm is rejected, ignoring\n";
1459                    next
1460                }
1461                $msg .= "calc_needed_size: list $list rpm $rpm size $group->{size}{$rpm}{$list}[0]\n";
1462                $needed_size->[$num]{fix} += $group->{size}{$rpm}{$list}[0];
1463                $local_done{$rpm} = 1;
1464                # FIXME This following code is a simplified version of check_deps. It may be overkill to use
1465                # full check_deps as anyway check_deps will be used to put the package at the end.
1466                foreach (@{$group->{pkgdeps}{$rpm}}) {
1467                    if (ref $_) {
1468                        $local_done{"@$_"} and next;
1469                        $local_done{"@$_"} = 1;
1470                        my $r = choose_alt($_, $rpmlist->[$i], $group, $cd, $num, $list, $buildlist, $tobedone, $needed);
1471                        if ($r != -1 && $r != 0) {
1472                            next if $local_done{$r};
1473                            $needed_size->[$num]{var} += $group->{size}{$r}{$list}[0];
1474                        }
1475                    } else {
1476                        my $pkg = $group->{depslistid}[$_];
1477                        next if ($done->{rep}{$pkg} && !$rpmlist->[$i]{$group->{done}{list}{$rpm}}{$rpm}{noprovide}) || $local_done{$pkg};
1478                        $local_done{$pkg} = 1;
1479                        $needed_size->[$num]{var} += $group->{size}{$pkg}{$list}[0];
1480                    }
1481                }
1482            }
1483        }
1484    }
1485    log_($msg, $config->{verbose}, $config->{LOG}, 3)
1486}
1487
1488sub revert_to {
1489    my ($groups, $i, $p2r, $diff, $size, $buildlist) = @_;
1490    log_("revert_to: try to find $p2r\n", $config->{verbose}, $config->{LOG}, 3);
1491    foreach (@{$diff->{data}}) {
1492        $_ or next; 
1493        foreach (@{$_->[5]}) {
1494            goto revert_to_ok if $_->[0] eq $p2r
1495        } 
1496    }
1497    log_("ERROR revert_to: $p2r is not present in movement history\n", $config->{verbose}, $config->{LOG}, 2);
1498    return 0;
1499    revert_to_ok:
1500    log_("revert_to: $p2r found\n", $config->{verbose}, $config->{LOG}, 5);
1501    my @keep;
1502    my $idx;
1503    do {
1504        $idx = pop @{$diff->{idx}};
1505        goto revert_to_endloop if any { $_->[0] eq $p2r } @{$diff->{data}[$idx][5]}; 
1506        my $step = $diff->{data}[$idx];
1507        if ($groups->[$i]{conflict}{$step->[1]}) {
1508            my ($curdir, $g, $list) = @$step;
1509            my $cdnum = $curdir->[0];
1510            foreach (@{$step->[5]}) { 
1511                my ($rpm, undef, undef, $rpmsize) = @$_; 
1512                delete $groups->[$g]{done}{rep}{$rpm}; 
1513                delete $groups->[$g]{done}{list}{$rpm}; 
1514                $diff->{data}[$idx] = 0;
1515                $size->{disc}[$cdnum] -= $rpmsize; 
1516                $size->{rep}{$cdnum}{$curdir->[1]}{$list} -= $rpmsize;
1517                log_("revert_to: reverting $rpm ID $idx for $p2r on cd $cdnum group $g list $list (cd size $size->{disc}[$cdnum])\n", $config->{verbose}, $config->{LOG}, 3)
1518            }
1519            push @{$buildlist->{$list}}, $step->[6] if $step->[4] == 1
1520        } else {
1521            unshift @keep, $idx;
1522        }
1523    } while @{$diff->{idx}};
1524revert_to_endloop:
1525    die "FATAL revert_to: diff data are empty\n" if ! @{$diff->{data}};
1526    push @{$diff->{idx}}, $idx, @keep;
1527    1
1528}
1529
1530sub mark_and_check_lists {
1531    my ($groups, $i, $needed, $diff, $buildlist, $rpmlist, $mark, $size, $cdsize, $ok, $tobedone) = @_;
1532    my @needed_size;
1533    my $group = $groups->[$i];
1534    my $need_to_calc;
1535    foreach my $list (@{$group->{orderedlist}{rpm}}) {
1536        ref $buildlist->{$list} or next;
1537        log_("mark_and_check_list: list $list\n", $config->{verbose}, $config->{LOG}, 3);
1538        if ($config->{list}[$list]{done}) {
1539            log_("mark_and_check_lists: list $list is done, ignoring\n", $config->{verbose}, $config->{LOG}, 5);
1540            next
1541        }
1542        if (defined $mark->{cur}{$list}) {
1543            $need_to_calc = 1;
1544            my $m = $mark->{cur}{$list};
1545            my $m_rpm = $m->[0];
1546            if ($group->{done}{rep}{$m_rpm}) {
1547                log_("mark_and_check_list: $m_rpm done, deleting mark for list $list\n", $config->{verbose}, $config->{LOG},4);
1548                push @{$mark->{his}}, $m;
1549                delete $mark->{cur}{$list}
1550            } elsif ($group->{rejected}{$m_rpm}) {
1551                log_("mark_and_check_list: $m_rpm rejected, deleting mark for list $list\n", $config->{verbose}, $config->{LOG},4);
1552                delete $mark->{cur}{$list}
1553            } elsif (!@{$buildlist->{$list}}) {
1554                log_("mark_and_check_list: list $list finished and $m_rpm not done or rejected\n",1, $config->{LOG},4)
1555            }
1556        }
1557        if (!defined $mark->{cur}{$list} && @{$buildlist->{$list}}) {
1558            my $rpm;
1559            for (my $j = $#{$buildlist->{$list}}; $j >= 0; $j--) {
1560                my $t = $buildlist->{$list}[$j];
1561                $rpm = ref $t->[0] ? $t->[0] : $t;
1562                if (!$group->{done}{rep}{$rpm->[0]} || $rpmlist->[$i]{$group->{done}{list}{$rpm->[0]}}{$rpm->[0]}{noprovide} ) {
1563                    last
1564                } 
1565                # this is not necessary, but when we are at it...
1566                log_("mark_and_check_list: $rpm done (list $group->{done}{list}{$rpm->[0]} cd $group->{done}{rep}{$rpm->[0]}), removing from queue\n", $config->{verbose}, $config->{LOG},4);
1567                pop @{$buildlist->{$list}}
1568            }
1569            $mark->{cur}{$list} = $rpm;
1570            log_("mark_and_check_list: marking $rpm->[0] for $list\n", $config->{verbose}, $config->{LOG},3);
1571        }
1572    }
1573    if ($need_to_calc || $ok) {
1574        calc_needed_size($group, $i, $needed, \@needed_size, $buildlist, $rpmlist, $tobedone);
1575        my ($need_in_rep, $av_in_rep, %done_disc);
1576        #
1577        # First impression would have been to check needed in reverse order, because we could imagine
1578        # that, in the current configuration, if needed 2 does not fit, for exemple, one package
1579        # is removed, needed 2 is put. But if needed does not fit at this moment, needed 2 is removed,
1580        # and needed 3 put, then needed 2 does not fit, and it is needed to revert more to make both of
1581        # them fit.
1582        #
1583        # If fact this could not happen, because if needed 3 does not fit when needed 2 has just been
1584        # put, this mean that the calc_needed_size if bogus.
1585        #
1586        foreach my $rep (@{$group->{replist}{rpm}}) {
1587            my ($cd, undef, $num) = @$rep;
1588            $need_in_rep += $needed_size[$num]{var} + $needed_size[$num]{fix};
1589            if (! $done_disc{$num}) {
1590                $av_in_rep += $cdsize->[$cd] - $size->{disc}[$cd];
1591                $done_disc{$num} = 1
1592            }
1593            log_("mark_and_check_list: rep $num need_in_rep $need_in_rep av_in_rep $av_in_rep needed_size $needed_size[$num]{fix} disc_av_space ($cdsize->[$cd] - $size->{disc}[$cd])\n", $config->{verbose}, $config->{LOG}, 4);
1594            if ($need_in_rep && $need_in_rep > $av_in_rep || $needed_size[$num]{fix} > $cdsize->[$cd] - $size->{disc}[$cd]) {
1595                log_("mark_and_check_list: not enough space for needed in rep $num on disc $cd\n", $config->{verbose}, $config->{LOG}, 3);
1596                pop @{$mark->{his}};
1597                my $p2r = pop @{$mark->{his}};
1598                log_("mark_and_check_list: trying to revert $p2r->[0]\n", $config->{verbose}, $config->{LOG}, 4);
1599                if (revert_to($groups, $i, $p2r->[0], $diff, $size, $buildlist)) {
1600                    log_("mark_and_check_list: $p2r->[0] reverted\n", $config->{verbose}, $config->{LOG}, 3);
1601                    foreach my $idx (0 .. @{$group->{orderedlist}{rpm}}) {
1602                        my $list = $group->{orderedlist}{rpm}[$idx];
1603                        $needed->{$list} or next;
1604                        my $elt;
1605                        foreach my $tr (1 .. $num) {
1606                            foreach my $elt (@{$needed->{$list}{alap}[$tr]}) {
1607                                my $rpm = $elt->[0];
1608                                if ($group->{rejected}{$rpm}) {
1609                                    log_("ERROR: $rpm is rejected, ignoring\n", $config->{verbose}, $config->{LOG}, 3);
1610                                    next
1611                                }
1612                                push @{$buildlist->{$list}}, $elt;
1613                            }
1614                        }
1615                        $mark->{cur}{$list} = $elt->[0];
1616                        my $l_idx = $#{$buildlist->{$list}};
1617                        next if $l_idx < 0;
1618                        foreach my $tidx ($idx + 1 .. @{$group->{orderedlist}{rpm}}) {
1619                            my $l = $group->{orderedlist}{rpm}[$tidx];
1620                            push @{$needed->{$l}{asap}}, [ $list, $l_idx ]
1621                        }
1622                    }
1623                } else {
1624                    log_("ERROR mark_and_check_list: reverting to $p2r->[0] failed\n", $config->{verbose}, $config->{LOG}, 4)
1625                }
1626               
1627            }
1628        }
1629    }
1630    return $ok
1631}
1632
1633# TODO the algo is not as beautiful as it should be
1634# ... but it is getting better
1635# ... and better
1636sub buildDiscs {
1637    my ($class, $groups, $buildlist, $rpmlist, $groupok, $size, $cdsize, $cdlists, $cds, $needed, $diff, $n) = @_;
1638    log_("buildDiscs\n", $config->{verbose}, $config->{LOG}, 3);
1639    $config = $class->{config};
1640    if ($n > 1) {
1641        foreach my $i (reverse @$cds) {
1642            $size->{optimize_space}{disc}{$i} = $size->{disc}[$i];
1643            if ($size->{disc}[$i] > $cdsize->[$i]) { 
1644                my $gain = ($size->{disc}[$i] - $cdsize->[$i])/2;
1645                next if $gain < 0;
1646                optimize_space($config, $groups, $diff, $size, $cdsize, $i, $gain, $cdlists,1)
1647            } else {
1648                log_("buildDiscs: disc $i size OK $size->{disc}[$i] ($cdsize->[$i])\n", $config->{verbose}, $config->{LOG},2)
1649            }
1650        }
1651    }
1652    my ($ok, $iti);
1653    my @groupok;
1654    my (@tobedone, @nosrcfit);
1655    my @mark = ({}) x @$groups;
1656    updateGenericLimit($groups, $cdsize);
1657    while (!$ok) {
1658        log_("iti: " . $iti++ . "\n", $config->{verbose}, $config->{LOG},4);
1659        $ok = 1;
1660        for (my $i = 0; $i < @$groups; $i++) {
1661            my $group = $groups->[$i];
1662            if (!$config->{fast}) {
1663                $groupok[$i] = mark_and_check_lists($groups, $i, $needed->[$i], $diff, $buildlist->[$i], $rpmlist, $mark[$i], $size, $cdsize, $groupok[$i], $tobedone[$i]);
1664                $groupok[$i] and next;
1665            }
1666            $ok = loop_on_lists($i, $groups, $group, \@groupok, $needed, $buildlist, \@tobedone, $diff, \@nosrcfit, $size, $cdsize, $cds, $rpmlist, $cdlists, $ok); 
1667        }
1668    }
1669    foreach (@nosrcfit) {
1670        my ($rpmd, $srpm, $list, $i, $curdir, $cdnum) = @$_;
1671        my $group = $groups->[$i];
1672        my $done = $group->{done};
1673        my ($srpmrep, $srpmsize, $srpmok) = sourcesSizeCheck($done, $rpmd, $srpm, $group, $groups, $size, $cdsize, $list, $cdlists,0,0, $buildlist, $cds, $i, $diff);
1674        if ($srpmok) {
1675            addSRPMToDiff($rpmd, $done, $diff, $size, $srpmrep, $srpmsize, $curdir, $srpm, $list, $i, $cdnum);
1676        } else {
1677            log_("WARNING: @$srpm does not fit on the discs\n",1, $config->{LOG},2)
1678        }
1679    }
1680    my $is_rejected;
1681    log_("buildDiscs: rejected packages\n", $config->{verbose}, $config->{LOG},2);
1682    for (my $i; $i < @$groups; $i++) {
1683        $groups->[$i]{rejected} or next;
1684        my $gh = $groups->[$i]{rejected};
1685        foreach (keys %$gh) {
1686            if (!$is_rejected) {
1687                $is_rejected = 1 if any { $_->[0] =~ /no_disc/ || $_->[0] =~ /no_space/ } @{$gh->{$_}};
1688            }
1689            log_("WARNING buildDisc: group $i REJECTED $_ (",1, $config->{LOG},2);
1690            ref $groups->[$i]{rejected}{$_} and log_((join ',', map { "$config->{rejected_options}{$_->[0]}: $_->[1]" } @{$groups->[$i]{rejected}{$_}}),1, $config->{LOG},2);
1691            log_(")\n",1, $config->{LOG});
1692        }
1693    }
1694    ($is_rejected)
1695}
16961
1697
1698# Changelog
1699#
1700# 2002 02 21
1701# change false $j comparaison to $depsdisc in buildDisc to new $thisorderrep value.
1702#
1703# 2002 03 03
1704# new limit option handling.
1705# add updateGenericSoft function
1706# add testSoftLimit function
1707# update size to check rep size
1708#
1709# 2002 03 08
1710# fix autoMode CD adding
1711#
1712# 2002 03 13
1713# better selection of alternatives in multi-list to take the one in the first lists.
1714#
1715# 2002 03 14
1716# add sources new sources handling method
1717# in nosrcfit mode sources are added afterwards
1718#
1719# 2002 03 19
1720# add prelist in geList for cdcom, will be useful for oem too I guess.
1721#
1722# 2002 05 02
1723# add_one_disc: add separate mode for sources mode
1724#
1725# 2002 05 09
1726# add graft structure for md5 and graft point handling
1727#
1728# 2002 05 13
1729# fix a tricky bugs in build_list about fentry shared and not recreated for each packages.
1730#
1731# 2002 06 01
1732# use perl-URPM
1733#
1734# 2002 06 15
1735# new diff mode, global, shared between disc and group, only one table.
1736#
1737# 2002 08 16
1738# new diff_idx table to sort diff data
1739#
1740# 2002 08 24
1741# optimize_space first version, still need to handle correctly needed and more advanced optimization methods.
1742#
1743# 2002 09 18
1744# optimize_space work, fixes and updates.
1745#
1746# 2002 10 25
1747# fix needed assignation pb in closeRPMslist
Note: See TracBrowser for help on using the repository browser.