source: soft/build_system/build_system/mkcd/tags/V4_1_8_1mdk/pm/Mkcd/Build.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: 57.5 KB
Line 
1package Mkcd::Build;
2
3my $VERSION = '3.0.0';
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_ find_list);
11use Mkcd::Optimize qw(optimize_space get_pkgs_deps);
12use MDK::Common qw(any if_);
13
14my $MIN_CHUNK = 0.0001;
15
16=head1 NAME
17
18Build - mkcd module
19
20=head1 SYNOPSYS
21
22    require Mkcd::Build;
23
24=head1 DESCRIPTION
25
26C<mkcd::Build> include the mkcd packages list functions.
27
28=head1 SEE ALSO
29
30mkcd
31
32=head1 COPYRIGHT
33
34Copyright (C) 2000-2004 Mandriva <warly@mandriva.com>
35
36This program is free software; you can redistribute it and/or modify
37it under the terms of the GNU General Public License as published by
38the Free Software Foundation; either version 2, or (at your option)
39any later version.
40
41This program is distributed in the hope that it will be useful,
42but WITHOUT ANY WARRANTY; without even the implied warranty of
43MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
44GNU General Public License for more details.
45
46You should have received a copy of the GNU General Public License
47along with this program; if not, write to the Free Software
48Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
49
50=cut
51
52my $config;
53
54sub new {
55    my ($class, $conf) = @_;
56    $config = $conf;
57    bless {
58           config       => $config,
59          }, $class;
60}
61
62sub addRPMToDiff {
63    my ($rpm, $rpmd, $diff, $cdnum, $repnumber, $i, $list, $curdir, $size, $rpmsize, $totrpmsize, $repnum, $done, $reallist, $realrepnum, $group) = @_;
64    my @data;
65    for (my $s; $s < @$rpm; $s++) {
66        push @data, [$rpm->[$s],1, $rpmd->[$s], $rpmsize->[$s]];
67        log_("addRPMToDiff: $rpm->[$s] put in rep $repnumber ($done->{rep})\n", $config->{verbose}, $config->{LOG}, 4);
68        $done->{rep}{$rpm->[$s]} = $repnumber;
69        $done->{list}{$rpm->[$s]} = $list;
70    }
71    my $diff_data = [ $curdir, $i, $list, $repnum, 1, \@data, $rpmd, $totrpmsize, $reallist ];
72    my $idx = push @{$diff->{data}}, $diff_data;
73    push @{$diff->{idx}}, --$idx;
74    push @{$group->{reploc}{$realrepnum}{diff}{$repnum}}, $diff_data if $realrepnum != $repnum;
75    $size->{disc}[$cdnum] += $totrpmsize;
76    $size->{rep}{$cdnum}{$curdir->[1]}{$list} += $totrpmsize;
77    log_("addRPMToDiff: SIZE disc $cdnum: $size->{disc}[$cdnum] (+ @$rpm $totrpmsize ID $idx) added rpmd $rpmd\n", $config->{verbose}, $config->{LOG}, 3);
78    1
79}
80
81sub check_last_relocatable {
82    my ($group, $cd, $repname, $repnum, $list, $curdir_old, $old) = @_;
83    my ($curdir, $new_repnum, $newlist);
84    if (defined $group->{reploc}{$repnum}{last}{list} && $group->{reploc}{$repnum}{last}{list} == $list) {
85        $new_repnum = $group->{reploc}{$repnum}{last}{rep};
86        log_("check_last_relocatable: using previous relocatable dir $new_repnum\n",1 , $config->{LOG}, 1);
87        $curdir = $group->{reploc}{$repnum}{last}{curdir};
88        $newlist = $group->{reploc}{$repnum}{last}{newlist}
89    } else {
90        my $last = $group->{reploc}{$repnum}{last}{rep} || $repnum - 1;
91        $new_repnum = $last+$MIN_CHUNK;
92        log_("check_last_relocatable: using new relocatable dir $new_repnum cd $cd repname $repname repnum $repnum\n",1 , $config->{LOG}, 1);
93        $group->{reploc}{$repnum}{last}{rep} = $new_repnum;
94        $group->{reploc}{$repnum}{last}{list} = $list;
95        $newlist = @{$config->{list}};
96        $config->{list}[$newlist] = {};
97        push @{$group->{reploc}{$repnum}{list}}, [ $new_repnum, $cd, $repname, $newlist ];
98        $curdir = [ $cd, $repname ];
99        push @$curdir, $curdir_old->[2], $curdir_old->[3] if ref $curdir_old;
100        $group->{reploc}{$repnum}{last}{newlist} = $newlist;
101        $group->{reploc}{$repnum}{last}{curdir} = $curdir;
102        $group->{reploc}{$repnum}{curdir}{$new_repnum} = $curdir;
103        $group->{reploc}{$repnum}{newlist}{$new_repnum} = $newlist;
104        $group->{reploc}{$repnum}{reallist}{$new_repnum} = $list;
105        $group->{reploc}{$repnum}{old}{$new_repnum} = $old 
106    }
107    return $new_repnum, $curdir, $newlist
108}
109
110sub add_relocatable_package {
111    my ($group, $tcd, $diff, $r, $list, $i, $repnum, $repname) = @_;
112    my $done = $group->{done};
113    log_("add_relocatable_package: going in relocatable mode for deps $r before $repnum\n",1 , $config->{LOG}, 1);
114    my ($new_repnum, $curdir, $newlist) = check_last_relocatable($group, @{$group->{reverse_rep}{rpm}{$tcd}}{'cd', 'name'}, $repnum, $list, 0, 1);
115    log_("add_relocatable_package: $r put in rep $new_repnum list $list\n", $config->{verbose}, $config->{LOG}, 4);
116    $done->{rep}{$r} = $new_repnum;
117    $done->{list}{$r} = $newlist;
118
119    my $totrpmsize = $group->{size}{$r}{$list}[0];
120    $group->{reploc}{$repnum}{size}{$new_repnum} += $totrpmsize;
121    my $rpmd = [[ $r, 0, 0 ]];
122    my $data = [[ $r, 1, 0, 0 ]];
123    my $diff_data = [ $curdir, $i, $newlist, $new_repnum, 1, $data, $rpmd, $totrpmsize, $list ];
124    my $idx = push @{$diff->{data}}, $diff_data;
125    push @{$diff->{idx}}, --$idx;
126    push @{$group->{reploc}{$repnum}{diff}{$new_repnum}}, $diff_data;
127    $new_repnum
128}
129
130sub all_rejected {
131    my ($all_l, $r) = @_;
132    foreach my $l (@$all_l) {
133        return 0 if !$r->{$l}
134    }
135    1
136}
137
138sub processDeps {
139    my ($r, $group, $cdnum, $repname, $done, $rpmlist, $topush, $intopush, $depsdisc, $rpmd, $list, $loop, $i, $tobedone, $buildlist, $rpm, $needed, $diff) = @_;
140    # FIXME I think that this is wrong, but not really sure
141    # It may happen that package get rejected because the non-done deps could not,
142    # for any reason, be used, and this package is not put after the done deps.
143    # However I guess that the put_in_rep loop over directories may save the
144    # stuff.
145   
146    # FIXME This is not correct, should iterate on the lists to find if an entry exist (not important)
147    #if (! defined $done->{rep}{$r} && ! defined $rpmlist->[$i]{$done->{list}{$r}}{$r}) {
148    #   log_("WARNING THIS SHOULD NOT HAPPEN processDeps: adding a non programmed deps $r\n", $config->{verbose}, $config->{LOG}, 1);
149    #}
150    my $repnum = $group->{orderedrep}{rpm}{"$cdnum/$repname"};
151    my $tcd = $done->{rep}{$r} if !$rpmlist->[$i]{$done->{list}{$r}}{$r}{noprovide} || $done->{rep}{$r} <= $repnum;
152    log_("processDeps: deps $r (tcd $tcd done $done->{rep}{$r})\n", $config->{verbose}, $config->{LOG}, 3);
153    if ($tcd > $repnum && $rpmlist->[$i]{$done->{list}{$r}}{$r}{relocatable}) {
154        $tcd = add_relocatable_package($group, $tcd, $diff, $r, $done->{list}{$r}, $i, $group->{orderedrep}{rpm}{"$cdnum/$repname"}, $repname)
155    }
156    my ($r_l, $all_l) = find_list($config, $group, $r, $list, !$tcd);
157    if (all_rejected($all_l, $group->{rejected}{$r})) { 
158        log_("ERROR processDeps: deps $r rejected, rejecting @$rpm (list @$all_l)\n",1 , $config->{LOG}, 1);
159        log_("Rejecting @$rpm $r\n", $config->{verbose}, $config->{LOG},1);
160        foreach my $p (@$rpm) { 
161            my (undef, $p_list) = find_list($config, $group, $p, $list, !$tcd);
162            foreach my $t_l (@$p_list) { push @{$group->{rejected}{$p}{$t_l}}, [ 'deps_rejected', $r] } 
163        }
164        $$loop = 1; %$topush = (); return 0 
165    }
166    if ($tcd) {
167        if ($tcd > $$depsdisc) { $$depsdisc = $tcd };
168        log_("processDeps: deps done $r on rep $tcd ($$depsdisc) list $done->{list}{$r}\n", $config->{verbose}, $config->{LOG}, 4);
169        return 2 
170    }
171    foreach my $l (@$all_l) {
172        if ($tobedone->{$r}{$l}) {
173            if ($l == $list) {
174                log_("$r tobedone\n", $config->{verbose}, $config->{LOG},3);
175                if ($intopush->{$r}) { log_("WARNING processDeps: $r added twice\n", $config->{verbose}, $config->{LOG}, 3); return 1 }
176                push @$rpmd, [$r, $rpmlist->[$i]{$l}{$r}];
177                $intopush->{$r} = 1;
178                push @{$topush->{$l}}, $rpmd; 
179                log_("processDeps: adding looping deps $r ($l) with @$rpm\n", $config->{verbose}, $config->{LOG},3);
180                return
181            } else {
182                if ($group->{listmatrix}{rpm}{$list}{$l} && !$group->{rejected}{$r}{$l}) {
183                    # FIXME tobedone may not mean dependencies loop in parallel mode for different list.
184                    log_("processDeps: $r is already scheduled on list $l, waiting.\n", $config->{verbose}, $config->{LOG},4);
185                    %$topush = ();
186                    push @{$buildlist->[$i]{$list}}, @$rpmd > 1 ? $rpmd : $rpmd->[0];
187                    return 3
188                    #$intopush{$r} and log_("ERROR: $r added twice\n",1, $config->{LOG}) and return 0;
189                    #$intopush{$r} = 1;
190                    #push @{$topush{$l}}, [$r, $rpmlist->[$i]{$l}{$r}];
191                    #log_("DEPS $r ($_ -- $l)\n", $config->{verbose}, $config->{LOG})
192                } else {
193                    log_("ERROR processDeps: deps $r could not be put in directory before packages @$rpm\n", $config->{verbose}, $config->{LOG},1);
194                    reject_rpm($rpm, $l, $group, 'order_pb', $r, \$loop, $topush);
195                    next
196                }
197            }
198        } else {
199            if ($l == $list) {
200                if ($intopush->{$r}) { log_("WARNING processDeps: $r added twice\n", 1, $config->{LOG}, 2); return 1 }
201                $intopush->{$r} = 1;
202                push @{$topush->{$l}}, [$r, $rpmlist->[$i]{$l}{$r}]; 
203                log_("processDeps: adding normal deps $r ($_ -- $l)\n", $config->{verbose}, $config->{LOG},3);
204                return
205            } else {
206                if ($config->{list}[$l]{done}) {
207                    log_("processDeps: list $l of deps $r is done, doing nothing.\n", $config->{verbose}, $config->{LOG},6);
208                    return
209                }
210                if ($group->{options}{sequential}) {
211                    log_("WARNING processDeps: could not add interlist deps in sequential mode\n",1, $config->{LOG},2);
212                    reject_rpm($rpm, $l, $group, 'sequential', $r, \$loop, $topush);
213                    next
214                } else {
215                    if (defined $needed->{$list}{asap} && grep { $l == $_->[0] } @{$needed->{$list}{asap}}) {
216                        log_("ERROR processDeps: list of deps $r is already waiting for @$rpm list\n",1, $config->{LOG},1);
217                        reject_rpm($rpm, $l, $group, 'order_pb', $r, \$loop);
218                        next
219                    } else {
220                        if ($group->{listmatrix}{rpm}{$list}{$l}) {
221                            if ($intopush->{$r}) { log_("WARNING processDeps: $r added twice\n",1, $config->{LOG},2); return 1 }
222                            $intopush->{$r} = 1;
223                            push @{$topush->{$l}}, [$r, $rpmlist->[$i]{$l}{$r}]; 
224                            log_("processDeps: adding normal deps $r ($_ -- $l)\n", $config->{verbose}, $config->{LOG},3);
225                            return
226                        } else {
227                            log_("ERROR processDeps: deps $r could not be put in directory before packages @$rpm\n",1, $config->{LOG},1);
228                            reject_rpm($rpm, $l, $group, 'order_pb', $r, \$loop);
229                            next
230                        } 
231                    }
232                }
233            }
234        }
235    }
236}
237
238sub reject_rpm {
239    my ($rpm, $list, $group, $reason, $r, $loop, $topush) = @_;
240    log_("Rejecting @$rpm\n", $config->{verbose}, $config->{LOG},1);
241    foreach (@$rpm) { push @{$group->{rejected}{$_}{$list}}, [ $reason, $r ] }
242    %$topush = ();
243    $$loop = 1;
244}
245
246sub updateGenericLimit {
247    my ($groups, $cdsize) = @_;
248    log_("updateGenericLimit\n", $config->{verbose}, $config->{LOG},2);
249    for (my $i; $i < @$groups; $i++) {
250        foreach my $type (keys %{$groups->[$i]{orderedlist}}) {
251            foreach my $list (@{$groups->[$i]{orderedlist}{$type}}) {
252                foreach my $r (@{$groups->[$i]{list}{$list}{$type}}) {
253                    my ($cd, $rep, $repopt) = @$r;
254                    #log_("trying to update disc $cd rep $rep list $list limit repopt $repopt (",1, $config->{LOG}),keys %$repopt,") opt $opt (",keys %$opt,")\n";
255                    $config->{list}[$list]{disc}{$cd}{$rep}{done} and next;
256                    $repopt->{limit} or next;
257                    $repopt->{limit}{size} = $repopt->{limit}{value} * $cdsize->[$cd];
258                    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);
259                }
260            }
261        }
262    }
263}
264
265sub testSoftLimit {
266    my ($opt, $cd, $groups, $buildlist) = @_;
267    log_("testSoftLimit\n", $config->{verbose}, $config->{LOG}, 2);
268    my $softnok = 1;
269    # FIXME this code must be tested
270    if ($opt->{limit} && $opt->{limit}{soft}) {
271        foreach my $l (@{$config->{disc}[$cd]{fastgeneric}}) {
272            my $lst = $l->[2]{list};
273            for (my $i; $i < @$groups; $i++) {
274                $groups->[$i]{list}{$lst} or next;     
275                $softnok = 0 if (@{$buildlist->[$i]{$lst}} && !($lst->{limit} && $lst->{limit}{soft}))   
276            }
277        }
278    }
279    return $softnok;
280}
281
282sub add_one_disc {
283    my ($cdlists, $group, $cdsize, $list, $cds, $sources, $size, $g) = @_;
284    my $ncd;
285    foreach (keys %$cdlists) {
286        $ncd = $_ + 1 if $ncd <= $_
287    }
288    log_("add_one_disc: $config->{list}[$list]{cd} -- $ncd\n", $config->{verbose}, $config->{LOG}, 3);
289    if (!$config->{list}[$list]{cd} || $config->{list}[$list]{cd} >= $ncd) {
290        log_("add_one_disc: adding new disc $ncd\n", $config->{verbose}, $config->{LOG}, 4);
291        $config->{disc}[$ncd]{size} = $config->{discsize};
292        my $functions = $config->{group}{disc}{functions}{functions};
293        $cdsize->[$ncd] = $config->{discsize};
294        $config->{disc}[$ncd]{name} = $ncd;
295        $size->{optimize_space}{disc}{$ncd} = $cdsize->[$ncd];
296        $group->{disc_impacted}{$ncd} = 1;
297        my ($curdir, $srpmcurdir);
298        my $tmp = "$config->{tmp}/build/$config->{name}";
299        my $f = "$tmp/$ncd.list";
300        -f $f and unlink $f;
301        if ($config->{nolive}) {
302            log_("makeDisc: removing $tmp/$ncd\n", $config->{verbose}, $config->{LOG}, 3);
303            rmtree "$tmp/$ncd";
304            mkpath "$tmp/$ncd";
305        } else {
306            my $dir = "$config->{topdir}/build/$config->{name}";
307            rmtree "$dir/$ncd";
308            rmtree "$dir/first/$ncd";
309            mkpath "$dir/$ncd"
310        }
311        my $instcd = $group->{installDisc};
312        my ($rep, $src_rep);
313
314        my $struct_v = $config->{struct_version};
315        my $media_srpm = $config->{struct}{$struct_v}{srpm_media};
316        my $media_dir = $config->{struct}{$struct_v}{media};
317        if ($sources && $config->{list}[$list]{sources} && $config->{list}[$list]{sources}{separate}) {
318            $config->{disc}[$ncd]{serial} = "$config->{name}-$ncd-src";
319            $config->{disc}[$ncd]{longname} = "Mandriva Linux $config->{name} sources";
320            $config->{disc}[$ncd]{appname} = "Mandriva Linux $config->{name} sources disc $ncd";
321            $config->{disc}[$ncd]{label} = substr "$config->{name}-src-Disc$ncd", 0, 32;
322            $config->{disc}[$ncd]{group_list}{$g}{$list}{srpm} = 1;
323            &{$functions->{dir}[0][5]}($ncd, 3, "srpms", $media_srpm);
324            &{$functions->{generic}[0][5]}($ncd, 4, "srpms",1);
325            &{$functions->{generic}[1][5]}($ncd, 5, { source => 1 });
326            push @{$config->{disc}[$instcd]{function}{data}{installation}[1]{srpmsdir}}, [ 0, $ncd, "srpms" ];
327            $srpmcurdir = [ $ncd, "srpms" ];
328            push @{$group->{list}{$list}{srpm}}, $srpmcurdir;
329            $src_rep = $group->{maxrep}{srpm};
330            push @{$group->{replist}{srpm}}, [ $ncd, 'srpms', $group->{maxrep}{srpm}++, { $list => $srpmcurdir } ];
331        } else {
332            $config->{disc}[$ncd]{serial} = "$config->{name}-$ncd";
333            $config->{disc}[$ncd]{longname} = "Mandriva Linux $config->{name}";
334            $config->{disc}[$ncd]{appname} = "Mandriva Linux $config->{name} disc $ncd";
335            $config->{disc}[$ncd]{label} = substr "$config->{name}-Disc$ncd", 0, 32;
336            $config->{disc}[$ncd]{group_list}{$g}{$list}{rpm} = 1;
337            &{$functions->{dir}[0][5]}($ncd, 1, "rpms","$media_dir$ncd");
338            &{$functions->{generic}[0][5]}($ncd, 2, "rpms", 1);
339            $group->{orderedrep}{rpm}{"$ncd/rpms"} = $ncd;
340            #
341            # generic has no FIXED part, otherwize a call to generic with fixed=0
342            # would have been needed
343            #
344            $curdir = [$ncd, "rpms"];
345            push @{$group->{list}{$list}{rpm}}, $curdir;
346            $rep = $group->{maxrep}{rpm};
347            if ($group->{replist}{rpm}[$group->{maxrep}{rpm}-1]) {
348                die "FATAL add_one_disc: rep $group->{maxrep}{rpm} should not exist !\n"
349            } else {
350                $group->{replist}{rpm}[$group->{maxrep}{rpm}-1], [ $ncd, 'rpms', $group->{maxrep}{rpm}++, { $list => $curdir } ];
351            }
352            push @{$config->{disc}[$instcd]{function}{data}{installation}[1]{rpmsdir}}, [ 0, $ncd, "rpms" ];
353            if ($config->{list}[$list]{sources}) {
354                &{$functions->{dir}[0][5]}($ncd,3, "srpms", $media_srpm);
355                &{$functions->{generic}[0][5]}($ncd,4, "srpms",1);
356                &{$functions->{generic}[1][5]}($ncd,5, { source => 1 });
357                push @{$config->{disc}[$instcd]{function}{data}{installation}[1]{srpmsdir}}, [ 0, $ncd, "srpms" ];
358                $srpmcurdir = [ $ncd, "srpms" ];
359                $src_rep = $group->{maxrep}{srpm};
360                if ($group->{replist}{srpm}[$group->{maxrep}{srpm}-1]) {
361                    die "FATAL add_one_disc: rep $group->{maxrep}{srpm} should not exist !\n"
362                } else {
363                    $group->{replist}{srpm}[$group->{maxrep}{srpm}-1], [ $ncd, 'srpms', $group->{maxrep}{srpm}++, { $list => $srpmcurdir } ];
364                } 
365                push @{$group->{list}{$list}{srpm}}, $srpmcurdir
366            }
367        }
368        push @$cds, $ncd;
369        $cdlists->{$ncd} = 2;
370        return $curdir, $rep, $srpmcurdir, $src_rep
371    } else { return 0 }
372}
373
374sub addSRPMToDiff {
375    my ($rpmd, $done, $diff, $size, $srpmrep, $srpmsize, $curdir, $srpm, $list, $i, $cdnum) = @_;
376    for (my $s; $s < @$rpmd; $s++) {
377        if (!$rpmd->[$s][1]{nosrc} && !$done->{rep}{$srpm->[$s]}) {
378            my $srep = $srpmrep->{$srpm->[$s]};
379            my $idx = push @{$diff->{data}}, [ $srep->[2], $i, $list, $srep->[1], 2, [[$srpm->[$s],1, $rpmd->[$s], $srpmsize->[$s]]], 0, $srpmsize->[$s] ];
380            push @{$diff->{idx}}, $idx - 1;
381            $size->{disc}[$srep->[0]] += $srpmsize->[$s];
382            $size->{rep}{$srep->[0]}{$srep->[2][1]}{$list} += $srpmsize->[$s];
383            log_("SIZE disc $srep->[0]: $size->{disc}[$srep->[0]] (+ $srpm->[$s] $srpmsize->[$s])\n", $config->{verbose}, $config->{LOG}, 2);
384        }
385        $done->{rep}{$srpm->[$s]}++;
386        $done->{list}{$srpm->[$s]} = $list
387    }
388    1
389}
390
391sub sourcesSizeCheck {
392    my ($done, $rpmd, $srpm, $group, $groups, $size, $cdsize, $list, $cdlists, $cdnum, $rpmsize, $buildlist, $cds, $i, $diff) = @_;
393    my %srpmrep;   
394    my $srpmok = 1;
395    my @srpmsize;
396    for (my $s; $s < @$srpm; $s++) {
397        $done->{rep}{$srpm->[$s]} and next;
398        $rpmd->[$s][1]{nosrc} and next;
399        my $srpmsize = $group->{size}{$srpm->[$s]}{$list}[0];
400        $srpmsize[$s] = $srpmsize;
401        for (my $k; $k < @{$group->{list}{$list}{srpm}}; $k++) {
402            my $srpmdir = $group->{list}{$list}{srpm}[$k];
403            my ($srccd, $srcrepname, $srcopt) = @$srpmdir;
404            my $src_rep_num = $group->{orderedrep}{srpm}{"$srccd/$srcrepname"};
405            log_("trying source disc $srccd\n", $config->{verbose}, $config->{LOG}, 2);
406            $cdlists->{$srccd} > 1 or next;
407            my $currentrpm;
408            $cdnum == $srccd and $currentrpm = $rpmsize;
409            my $softnok = testSoftLimit($srcopt, $srccd, $groups, $buildlist);
410            my $gain = $size->{disc}[$srccd] + $srpmsize + $currentrpm - $cdsize->[$srccd];
411            # FIXME this need to be tested
412            if ($gain <= 0 && !($srcopt->{limit} && ($softnok || !$srcopt->{limit}{soft}) && $size->{rep}{$srccd}{$srcrepname}{$list} > $srcopt->{limit}{size})) {
413                $srpmrep{$srpm->[$s]} = [$srccd, $src_rep_num, $srpmdir];
414                last
415            } elsif ($k == $#{$group->{list}{$list}{srpm}}) {
416                if (optimize_space($config, $groups, $diff, $size, $cdsize, $srccd, $gain, $cdlists,0, $i, $list, 'srpm', $srpmsize + $currentrpm) < $gain) {
417                    $srpmok = 0
418                } else {
419                    $done = $groups->[$i]{done};
420                    $srpmrep{$srpm->[$s]} = [$srccd, $src_rep_num, $srpmdir];
421                }
422            }
423        }
424        if (!$srpmrep{$srpm->[$s]}) {
425            $srpmok = 0
426            # 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.
427        }
428    }
429    if (!$srpmok && $config->{list}[$list]{auto}) {
430        my (undef, undef, $srpmdir, $repnum) = add_one_disc($cdlists, $group, $cdsize, $list, $cds, 1, $size, $i);
431        if ($srpmdir) {
432            for (my $s; $s < @$srpm; $s++) {
433                if (!$srpmrep{$srpm->[$s]}) {
434                    $srpmrep{$srpm->[$s]} = [$srpmdir->[0], $repnum, $srpmdir];
435                }
436            }
437            $srpmok = 1
438        }
439    }
440    return \%srpmrep, \@srpmsize, $srpmok
441}
442
443sub choose_alt {
444    my ($deps, $rpmlist, $group, $cdnum, $repname, $list, $buildlist, $intopush, $tobedone, $needed, $size_matter) = @_;
445    my $r = -1;
446    my $score = [ 0, $group->{maxlist} ];
447    my $done = $group->{done};
448    my $all_rejected = 1;
449    DEPS: {
450        foreach my $testalt (1,0) {
451            foreach (@$deps) {
452                # FIXME it may have a problem here, as depslistid are not erased when the
453                # package is removed, that is to say that if the previous deps failed for
454                # any reason, alternates deps may be added, although excluded before
455                # however this _must_ not happen, and signify a bug somewhere else.
456                # Update: This may happen when the schedule deps has been rejected, and thus
457                # only the previous not selected one coud fulfil the require.
458                my $pkg = $group->{depslistid}[$_];
459
460                my (undef, $all_l) = find_list($config, $group, $pkg, $list);
461                foreach my $pkg_list (@$all_l) {
462                    log_("choose_alt: $pkg, testing list $pkg_list (rejected $group->{rejected}{$pkg}{$pkg_list})\n", $config->{verbose}, $config->{LOG}, 6);
463                    if ($group->{rejected}{$pkg}{$pkg_list}) { log_("choose_alt: $pkg is rejected, ignoring\n", $config->{verbose}, $config->{LOG}, 6); last }
464                    $all_rejected = 0;
465                    if ($testalt && ! defined $rpmlist->{$pkg_list}{$pkg} || $rpmlist->{$pkg_list}{$pkg}{noalternatives}) { log_("choose_alt: $pkg is not selected in first pass for alternatives\n", $config->{verbose}, $config->{LOG},6); last }
466                    $intopush->{$pkg} and $r = $pkg and last DEPS;
467                    log_("choose_alt: alternatives deps $pkg (noprovide $rpmlist->{$done->{list}{$pkg}}{$pkg}{noprovide} done $done->{rep}{$pkg} orderedrep " . $group->{orderedrep}{rpm}{"$cdnum/$repname"} . ")\n", $config->{verbose}, $config->{LOG}, 6);
468                    my $tcd;
469                    if ($rpmlist->{$done->{list}{$pkg}}{$pkg}{relocatable}) {
470                        $tcd = $group->{orderedrep}{rpm}{"$cdnum/$repname"}
471                    } elsif (!$rpmlist->{$done->{list}{$pkg}}{$pkg}{noprovide} || $done->{rep}{$pkg} <= $group->{orderedrep}{rpm}{"$cdnum/$repname"}) {
472                        $tcd = $done->{rep}{$pkg}
473                    }
474                    if ($tcd && $tcd <= $group->{orderedrep}{rpm}{"$cdnum/$repname"}) {
475                        log_("$pkg ($tcd) done\n", $config->{verbose}, $config->{LOG}, 6);
476                        $r = 0;
477                        last DEPS
478                    } 
479                    my $s = $size_matter ? $group->{size}{$pkg}{$pkg_list}[0] : $group->{scorelist}{$pkg};
480                    #log_("choose_alt: pkg $pkg buildlist $buildlist list $pkgList other list $list tcd $tcd list $l ($buildlist->{$pkgList})\n", $config->{verbose}, $config->{LOG}, 6);
481
482                    #log_("choose_alt: ($needed->{$pkgList}{asap})\n", $config->{verbose}, $config->{LOG}, 6);
483                    if ($pkg_list 
484                    && 
485                    $list != $pkg_list 
486                    && 
487                    (defined $needed->{$pkg_list}{asap} && (any { 
488                        if (ref $_) { 
489                            $list == $_->[0] 
490                        } else { 
491                            log_("ERROR choose_alt: [$_] should be a reference (pkg $pkg list $pkg_list asap [@{$needed->{$pkg_list}{asap}}])\n", $config->{verbose}, $config->{LOG}, 6) 
492                        } 
493                    } @{$needed->{$pkg_list}{asap}})
494                    || 
495                    ($group->{options}{sequential} 
496                    && 
497                    !$config->{list}[$pkg_list]{done} 
498                    && 
499                    @{$buildlist->{$pkg_list}}))
500                    ) { next }
501                    log_("choose_alt: $pkg list $pkg_list (tcd $tcd listmatrix $group->{listmatrix}{rpm}{$list}{$pkg_list} listsort $group->{listsort}{$pkg_list}{rpm} score->[1] $score->[1] s $s)\n", $config->{verbose}, $config->{LOG}, 6);
502                    if (!$tcd && $group->{listmatrix}{rpm}{$list}{$pkg_list}) {
503                        if ($group->{listsort}{$pkg_list}{rpm} < $score->[1] || $group->{listsort}{$pkg_list}{rpm} == $score->[1] && $s > $score->[0]) {
504                            log_("choose_alt: choosing $pkg list $pkg_list ($s, $group->{listsort}{$pkg_list}{rpm})\n", $config->{verbose}, $config->{LOG}, 6);
505                            $score = [ $s, $group->{listsort}{$pkg_list}{rpm} ];
506                            $r = $pkg;
507                            last DEPS if $tobedone->{$r}{$pkg_list};
508                            last
509                        }
510                    }
511                }
512            }
513            last if $r != -1 && $r
514        }
515    }
516    return $r, $all_rejected
517}
518
519sub check_deps {
520    my ($rpmd, $group, $done, $rpmlist, $list, $i, $tobedone, $buildlist, $rpm, $cdnum, $repname, $needed, $rep_num, $diff) = @_;
521    log_("check_deps\n", $config->{verbose}, $config->{LOG}, 5);
522    my $deps = get_pkgs_deps($rpmd, $group);
523    my $loop;
524    if (@$deps) {
525        my ($waiting, %topush, %intopush, $depsdisc);
526        foreach (@$deps) {
527            if (!ref $_) {
528                my $a = processDeps($group->{depslistid}[$_], $group, $cdnum, $repname, $done, $rpmlist, \%topush, \%intopush, \$depsdisc, $rpmd, $list, \$loop, $i, $tobedone, $buildlist, $rpm, $needed->[$i], $diff);
529                if ($a < 0) { return 0 } elsif ($a == 0) { last } elsif ($a == 2) { next } elsif ($a == 3) { $waiting = 1; last  }
530            } else {
531                # must create a virtual package that install all of them in one loop
532                log_("check_deps: alternatives deps @$_\n", $config->{verbose}, $config->{LOG}, 5);
533                my ($r, $all_rejected) = choose_alt($_, $rpmlist->[$i], $group, $cdnum, $repname, $list, $buildlist->[$i], \%intopush, $tobedone, $needed->[$i]);
534                $intopush{$r} and next;
535                if ($r == -1) {
536                    my $reject = 0;
537                    my $msg;
538                    if ($all_rejected) {
539                        $msg = "all alternatives deps (@$_) rejected";
540                        $reject = 'deps_rejected'
541                    } elsif ($group->{orderedrep}{rpm}{"$cdnum/$repname"} >= $group->{listmaxrep}{rpm}{$list}) { 
542                        $msg = "ERROR check_deps: alternatives deps (@$_) could not be put in directory before packages @$rpm\n";
543                        $reject = 'order_pb'
544                    } else {
545                        $loop = 2
546                    }
547                    if ($reject) {
548                        my $deps_rpm = join ' ',map { $group->{depslistid}[$_] } @$_;
549                        log_("Rejecting @$rpm\n", $config->{verbose}, $config->{LOG},2);
550                        foreach my $p (@$rpm) { push @{$group->{rejected}{$p}{$list}}, [ $reject, $deps_rpm ] }
551                        %topush = ();
552                        $loop = 1;
553                    }
554                    last
555                }
556                if ($r) { 
557                    my $a = processDeps($r, $group, $cdnum, $repname, $done, $rpmlist, \%topush, \%intopush, \$depsdisc, $rpmd, $list, \$loop, $i, $tobedone, $buildlist, $rpm, $needed->[$i]);
558                    if ($a < 0) { return 0 } elsif ($a == 0) { last } elsif ($a == 2) { next } elsif ($a == 3) { $waiting = 1; last  }
559                } else {
560                    log_("Finding better alternatives rep (@$_ - $depsdisc)\n", $config->{verbose}, $config->{LOG}, 4);
561                    my $bestdisc = keys %{$group->{orderedrep}{rpm}};
562                    if ($bestdisc >= $depsdisc) {
563                        foreach (@$_) {
564                            my $pkg = $group->{depslistid}[$_];
565                            my ($r_l, $all_l) = find_list($config, $group, $pkg, $list);
566                            if (all_rejected($all_l, $group->{rejected}{$pkg})) { log_("$pkg rejected\n", $config->{verbose}, $config->{LOG}, 2); next }
567                            my $tcd;
568                            log_("$pkg done $done->{list}{$pkg} relocatable $rpmlist->[$i]{$done->{list}{$pkg}}{$pkg}{relocatable}\n", $config->{verbose}, $config->{LOG}, 4);
569                            if ($rpmlist->[$i]{$done->{list}{$pkg}}{$pkg}{relocatable}) {
570                                $tcd = $rep_num
571                            } else {
572                                $tcd = $done->{rep}{$pkg};
573                            }
574                            $tcd or next;
575                            log_("$pkg => rep $tcd\n", $config->{verbose}, $config->{LOG}, 4);
576                            if ($tcd < $bestdisc) { $bestdisc = $tcd }
577                        }
578                        $bestdisc > $depsdisc and $depsdisc = $bestdisc
579                    }
580                    log_("Finding better alternatives rep result $depsdisc\n", $config->{verbose}, $config->{LOG}, 4);
581                }
582            }
583        }
584        $waiting and return 1;
585        if (keys %topush) {
586            $loop = 1;
587            log_("Adding dependencies, looping\n", $config->{verbose}, $config->{LOG}, 3);
588            my $test = @$rpmd > 1 ? $rpmd : $rpmd->[0];
589            push @{$buildlist->[$i]{$list}}, (@$rpmd > 1 ? $rpmd : $rpmd->[0]);
590            foreach (keys %topush) {
591                $list != $_ and push @{$needed->[$i]{$list}{asap}}, [ $_, int @{$buildlist->[$i]{$_}} ];
592                push @{$buildlist->[$i]{$_}}, @{$topush{$_}}
593            }
594        } elsif ($rep_num < $depsdisc) {
595            if ($group->{listmaxrep}{rpm}{$list} >= $depsdisc) {
596                $loop = 2;
597                # has a chance to put it after depsdisc
598                log_("Dependencies on further directories ($depsdisc < $group->{listmaxrep}{rpm}{$list} rep_num $rep_num)\n", $config->{verbose}, $config->{LOG}, 3);
599            } else {
600                $loop = 1;
601                log_("check_deps: dependencies are in further directories, rejecting @$rpm\n", $config->{verbose}, $config->{LOG}, 2);
602                foreach (@$rpm) { push @{$group->{rejected}{$_}{$list}}, ["order_pb", ""] }
603            }
604        }
605    }
606    $loop
607}
608
609sub put_in_rep {
610    my ($i, $groups, $group, $size, $rpmsize, $all_rpmsize, $cdsize, $needed, $rpm, $rpmd, $list, $cdlists, $buildlist, $diff, $cds, $done, $tobedone, $rpmlist, $nosrcfit) = @_; 
611    my $loop;
612    my $dn;
613    my $reject_reason;
614    log_("put_in_rep: @$rpm\n", $config->{verbose}, $config->{LOG}, 3);
615    for (my $j; !$loop && !$dn && $j < @{$group->{list}{$list}{rpm}}; $j++) {
616        $loop = 0;
617        log_("put_in_rep: testing dir $j\n", $config->{verbose}, $config->{LOG}, 3);
618        my $curdir = $group->{list}{$list}{rpm}[$j];
619        $config->{list}[$list]{disc}{$curdir->[0]}{$curdir->[1]}{done} and next;
620        my ($cdnum, $repname, $repopt) = @$curdir;
621        my $rep_num = $group->{orderedrep}{rpm}{"$cdnum/$repname"};
622        log_("put_in_rep: testing dir $j cdnum $cdnum repname $repname\n", $config->{verbose}, $config->{LOG}, 3);
623        $cdlists->{$cdnum} > 1 or next;
624        my $not_good_rep;
625        foreach my $r (@$rpmd) {
626            if ($r->[1]{notinrep}{$rep_num} || ref $r->[1]{inrep} && $r->[1]{inrep}{$rep_num}) {
627                    log_("put_in_rep: $r->[0] notinrep $rep_num, testing other rep\n", $config->{verbose}, $config->{LOG}, 9);
628                    $not_good_rep = 1; 
629                    last
630                }
631        }
632        if ($not_good_rep) {
633           if ($rep_num == $group->{listmaxrep}{rpm}{$list}) {
634                log_("ERROR put_in_rep: could not handle inrep or notinrep flags for rpms @$rpm", $config->{verbose}, $config->{LOG}, 1);
635                foreach my $p (@$rpm) { push @{$group->{rejected}{$p}{$list}}, [ 'config', ""] }
636                last
637           } 
638           next
639        }
640        my ($relocatable_list, $relocatable_rep_num) = ($list, $rep_num);
641        if (defined $group->{reploc}{$rep_num} && ref $group->{reploc}{$rep_num}) {
642            ($relocatable_rep_num, $curdir, $relocatable_list) = check_last_relocatable($group, $cdnum, $repname, $rep_num, $list, $curdir);
643        }
644        my $softnok = testSoftLimit($repopt, $cdnum, $groups, $buildlist);
645        my $gain = $size->{disc}[$cdnum] + $all_rpmsize - $cdsize->[$cdnum];
646        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);
647        if ($gain > 0 || $repopt->{limit} && ($softnok || !$repopt->{limit}{soft}) && $size->{rep}{$cdnum}{$repname}{$list} + $all_rpmsize > $repopt->{limit}{size}) {
648            if ($j == $#{$group->{list}{$list}{rpm}}) {
649                if (!($repopt->{limit} && !$softnok && $repopt->{limit}{soft})) {
650                    if (optimize_space($config, $groups, $diff, $size, $cdsize, $cdnum, $gain, $cdlists,0, $i, $list, 'rpm', $all_rpmsize) < $gain) {
651                        # done is rebuilt inside optimize_space and the referece needs to be locally updated
652                        if ($config->{list}[$list]{auto}) {
653                            ($curdir, $rep_num) = add_one_disc($cdlists, $group, $cdsize, $list, $cds,0, $size, $i);
654                            if ($curdir) {
655                                $cdnum = $curdir->[0]
656                            } else {
657                                log_("Could not add more disc, rejecting @$rpm\n", $config->{verbose}, $config->{LOG}, 2);
658                                foreach my $p (@$rpm) { push @{$group->{rejected}{$p}{$list}}, [ "no_disc", "" ] }
659                                next
660                            }
661                        } else {
662                            log_("Rejecting @$rpm\n", $config->{verbose}, $config->{LOG}, 2);
663                            foreach my $p (@$rpm) { push @{$group->{rejected}{$p}{$list}}, ["no_space", ""] }
664                            next
665                        }
666                    } else {
667                        $done = $groups->[$i]{done}
668                    }
669                } else { 
670                    foreach my $l (@{$config->{disc}[$cdnum]{fastgeneric}}) {
671                        my $lst = $l->[2]{list};
672                        $list == $lst and next;
673                        for (my $grp; $grp < @$groups; $grp++) {
674                            $groups->[$grp]{list}{$lst}{rpm} or next;   
675                            push(@{$needed->[$grp]{$list}{asap}}, [ $lst, 0 ]) if (!($lst->{limit} && $lst->{limit}{soft}))
676                        }
677                    }
678                }
679            } else { next }
680        }
681        if (!$config->{nodeps} && !$group->{options}{nodeps}) {
682            $loop = check_deps($rpmd, $group, $done, $rpmlist, $list, $i, $tobedone->[$i], $buildlist, $rpm, $cdnum, $repname, $needed, $rep_num, $diff)
683        }
684        if ($loop) {
685            $loop = 0 if $loop == 2;   
686            next
687        }       
688        log_("@$rpm deps ok\n", $config->{verbose}, $config->{LOG}, 4);
689        my $nosrc = 1;
690        my @srpm;
691        my $donesrpm = 1;
692        if (!$group->{options}{nosources} && @{$group->{list}{$list}{srpm}}) {
693            for (my $s; $s < @$rpmd; $s++) {
694                my $srpm = $group->{urpm}{sourcerpm}{$rpm->[$s]}; 
695                $srpm =~ s/\.rpm$//;
696                if (!$group->{size}{$srpm}{$list}) {
697                    log_("put_in_rep ERROR: $srpm not available, trying alternatives => ", $config->{verbose}, $config->{LOG}, 5);
698                    my ($srpmname) = $srpm =~ /(.*)-[^-]+-[^-]+\.src/;
699                    $srpm = $group->{srpmname}{$srpmname};
700                    if ($group->{size}{$srpm}{$list}) { 
701                        log_(" $srpm\n", $config->{verbose}, $config->{LOG}) 
702                    } else {
703                        if ($srpm) {
704                            log_("not found (but a srpm $srpm exist in another list)\n", $config->{verbose}, $config->{LOG}, 5);
705                            $srpm = 0
706                        } else {
707                            log_("not found\n", $config->{verbose}, $config->{LOG}, 5) 
708                        }
709                    }
710                }
711                if ($srpm) { 
712                    $done->{rep}{$srpm} or $donesrpm = 0;
713                    $srpm[$s] = $srpm;
714                    $rpmd->[$s][1]{nosrc} or $nosrc = 0 
715                }
716            }
717        }
718        log_("put_in_rep: group $i list $list: @$rpm (@srpm) -- $curdir->[0] -- $curdir->[1] -- disc $cdnum\n", $config->{verbose}, $config->{LOG}, 4);
719        if ($config->{nosrc} || $group->{options}{nosources} || !@{$group->{list}{$list}{srpm}} || $nosrc || $donesrpm) {
720            ($dn) = addRPMToDiff($rpm, $rpmd, $diff, $cdnum, $group->{orderedrep}{rpm}{"$cdnum/$repname"}, $i, $relocatable_list, $curdir, $size, $rpmsize, $all_rpmsize, $relocatable_rep_num, $done, $list, $rep_num, $group)
721        } else {
722            if ($config->{nosrcfit} || $group->{options}{nosrcfit}) {
723                $dn = addRPMToDiff($rpm, $rpmd, $diff, $cdnum, $group->{orderedrep}{rpm}{"$cdnum/$repname"}, $i, $relocatable_list, $curdir, $size, $rpmsize, $all_rpmsize, $relocatable_rep_num, $done, $list, $rep_num, $group);
724                push @$nosrcfit, [$rpmd, \@srpm, $list, $i, $curdir, $cdnum]
725            } else {
726                my ($srpmrep, $srpmsize, $srpmok) = sourcesSizeCheck($done, $rpmd, \@srpm, $group, $groups, $size, $cdsize, $list, $cdlists, $cdnum, $all_rpmsize, $buildlist, $cds, $i, $diff);
727                $done = $groups->[$i]{done};
728                if ($srpmok) {
729                    addRPMToDiff($rpm, $rpmd, $diff, $cdnum, $group->{orderedrep}{rpm}{"$cdnum/$repname"}, $i, $relocatable_list, $curdir, $size, $rpmsize, $all_rpmsize, $relocatable_rep_num, $done, $list, $rep_num, $group);
730                    $dn = addSRPMToDiff($rpmd, $done, $diff, $size, $srpmrep, $srpmsize, $curdir, \@srpm, $list, $i, $cdnum);
731                } else {
732                    log_("WARNING: @srpm does not fit on the discs\n",1, $config->{LOG}, 2)
733                }
734            }
735            if (!$dn) {
736                foreach my $p (@$rpm) { push @{$group->{rejected}{$p}{$list}}, [ $reject_reason || "no_space", ""] }
737                log_("WARNING: @$rpm does not fit on the disc ($size->{disc}[$cdnum] + $all_rpmsize > $cdsize->[$cdnum]) \n", $config->{verbose}, $config->{LOG}, 1)
738            }
739        }
740    }
741    return $dn
742}
743
744sub loop_on_lists {
745    my ($i, $groups, $group, $groupok, $needed, $buildlist, $tobedone, $diff, $nosrcfit, $size, $cdsize, $cds, $rpmlist, $cdlists, $ok, $mark, $groupok) = @_; 
746    #
747    # FIXME source rpms are not shared between group, it may be usefull for mutilple installation
748    # with common source dir, so that the same source rpm is shared (but this is not so common).
749    #
750    my $done = $group->{done};
751    my $rpmd_add = sub {
752        my ($rpm, $rpmd, $r, $list) = @_;
753        log_("Testing $rpm\n", $config->{verbose}, $config->{LOG},7);
754        my $d = $done->{rep}{$rpm};
755        my $reloc = $rpmlist->[$i]{$done->{list}{$rpm}}{$rpm}{relocatable};
756        if (!$d || $rpmlist->[$i]{$done->{list}{$rpm}}{$rpm}{noprovide}) { 
757            push @$rpmd, $r
758        } elsif ($d && $reloc) { 
759            my $curdir = $group->{list}{$list}{rpm}[0];
760            my ($cdnum, $repname) = @$curdir;
761            my $repnum = $group->{orderedrep}{rpm}{"$cdnum/$repname"};
762            if (!check_deps([ $r ], $group, $done, $rpmlist, $list, $i, $tobedone->[$i], $buildlist, $rpm, $cdnum, $repname, $needed, $repnum, $diff)) {
763                add_relocatable_package($group, $d, $diff, $rpm, $done->{list}{$rpm}, $i, $repnum, $repname)
764            }
765            return 0
766        }
767        1
768    };
769    my $dn;
770    log_("loop_on_lists: group $i (@{$group->{orderedlist}{rpm}})\n", $config->{verbose}, $config->{LOG}, 2);
771    while (!$dn) {
772        $groupok->[$i] = 1;
773        foreach my $list (@{$group->{orderedlist}{rpm}}) {
774            my $nb = @{$buildlist->[$i]{$list}} if ref $buildlist->[$i]{$list};
775            log_("loop_on_lists: list $list (empty $config->{list}[$list]{empty} done $config->{list}[$list]{done} nb $nb)\n", $config->{verbose}, $config->{LOG}, 3);
776            do {
777                $config->{list}[$list]{done} and goto end;
778                $config->{list}[$list]{empty} and goto end;
779                my $next;
780                foreach my $need (@{$needed->[$i]{$list}{asap}}) {
781                    my $nb_elt = @{$buildlist->[$i]{$need->[0]}};
782                    log_("List $list need list $need->[0] to be <= $need->[1] ($nb_elt)\n", $config->{verbose}, $config->{LOG}, 4);
783                    $nb_elt <= $need->[1] or $next = 1
784                }
785                if ($next) {
786                    log_("List $list waiting\n",1, $config->{LOG},4);
787                    goto end
788                }
789                $needed->[$i]{$list}{asap} = [];
790                my ($trpmd, $k, $goon, @rpmd);
791                do { 
792                    $trpmd = pop @{$buildlist->[$i]{$list}} or goto end;
793                    if (ref $trpmd->[0]) {
794                        foreach (@$trpmd) {
795                            $rpmd_add->($_->[0], \@rpmd, $_, $list) or goto end;
796                        }
797                    } else { $rpmd_add->($trpmd->[0], \@rpmd, $trpmd, $list) or goto end }
798                } until @rpmd;
799                $groupok->[$i] = 0;
800                $ok = 0;
801                my @rpm;
802                my $all_rpmsize;
803                my @rpmsize;
804                foreach (@rpmd) {
805                    my $r = $_->[0];
806                    !$r and log_("ERROR loop_on_lists: empty package @$_\n", $config->{verbose}, $config->{LOG}, 2);
807                    push @rpm, $r;
808                    log_("RPM $r (group $i list $list)\n", $config->{verbose}, $config->{LOG},6);
809                    $tobedone->[$i]{$r}{$list} = 1;
810                    $all_rpmsize += $group->{size}{$r}{$list}[0];
811                    push @rpmsize, $group->{size}{$r}{$list}[0]
812                }
813                $dn = put_in_rep($i, $groups, $group, $size, \@rpmsize, $all_rpmsize, $cdsize, $needed, \@rpm, \@rpmd, $list, $cdlists, $buildlist, $diff, $cds, $done, $tobedone, $rpmlist, $nosrcfit); 
814                $done = $group->{done};
815                $groupok->[$i] = mark_and_check_lists($groups, $i, $needed->[$i], $diff, $buildlist->[$i], $rpmlist, $mark->[$i], $size, $cdsize, $groupok->[$i], $tobedone->[$i]) if $group->{options}{sequential}
816            } while $group->{options}{sequential} && @{$buildlist->[$i]{$list}};
817            end:
818            last if $group->{options}{sequential} && @{$buildlist->[$i]{$list}} && !$config->{list}[$list]{done}
819        }
820        $groupok->[$i] and $dn = 1
821    }
822    return $ok
823}
824
825sub calc_needed_size {
826    my ($group, $i, $needed, $needed_size, $buildlist, $rpmlist, $tobedone) = @_;
827    my ($msg, %local_done);
828    $msg = "calc_needed_size\n";
829    my $done = $group->{done};
830    my $all_done = 1;
831    foreach my $rep (@{$group->{replist}{rpm}}) {
832        my ($cd, $repname, $num, $l) = @$rep;
833        $msg .= "calc_needed_size: rep $num\n";
834        foreach my $list (keys %$needed) {
835            # 2 ways here, either pre-detect that some list are done and decrease the needed
836            # flag to the greater smaller not done rep, or just let the needed as this but
837            # handle the packages included into this needed list, even if the considered rep
838            # is not including this list. But later the mark_and_check list will see it and automatically schedule
839            # the package for the previous available rep.
840            # $l->{$list} or next;
841            my $ok;
842            $ok ||= $group->{listmatrix}{rpm}{$_}{$list} foreach keys %$l;
843            $ok or next;
844            if ($config->{list}[$list]{disc}{$cd}{$repname}{done} && $all_done) {
845                log_("calc_needed_size: rep $cd/$repname for list $list is done, ignoring\n", $config->{verbose}, $config->{LOG}, 5);
846                next
847            } else {
848                $all_done = 0
849            }
850            foreach my $elt (@{$needed->{$list}{alap}[$num]}) {
851                my $rpm = $elt->[0];
852                if ($done->{rep}{$rpm} && !$rpmlist->[$i]{$group->{done}{list}{$rpm}}{$rpm}{noprovide} || $local_done{$rpm}) {
853                    next
854                }
855                if ($group->{rejected}{$rpm}{$list}) {
856                    $msg .= "ERROR: $rpm is rejected, ignoring\n" if $config->{verbose} > 5;
857                    next
858                }
859                $needed_size->[$num]{fix} += $group->{size}{$rpm}{$list}[0];
860                $msg .= "calc_needed_size: list $list rpm $rpm size $group->{size}{$rpm}{$list}[0] (done $done->{rep}{$rpm} needed_size $num $needed_size->[$num]{fix})\n" if $config->{verbose} > 5;
861                $local_done{$rpm} = 1;
862                # FIXME This following code is a simplified version of check_deps. It may be overkill to use
863                # full check_deps as anyway check_deps will be used to put the package at the end.
864                foreach my $deps (@{$group->{pkgdeps}{$rpm}}) {
865                    if (ref $deps) {
866                        $local_done{"@$deps"} and next;
867                        $local_done{"@$deps"} = 1;
868                        my $r = choose_alt($deps, $rpmlist->[$i], $group, $cd, $num, $list, $buildlist, {}, $tobedone, $needed, 0);
869                        my ($deps_list) = find_list($config, $group, $r);
870                        if ($r != -1 && $r != 0) {
871                            next if $done->{rep}{$r} && !$rpmlist->[$i]{$group->{done}{list}{$r}}{$r}{noprovide} || $local_done{$r};
872                            $msg .= "calc_needed_size: list $deps_list deps $r size $group->{size}{$r}{$deps_list}[0] (done $done->{rep}{$r} needed_size $num $needed_size->[$num]{fix})\n" if $config->{verbose} > 5;
873                            $needed_size->[$num]{var} += $group->{size}{$r}{$deps_list}[0];
874                        }
875                    } else {
876                        my $pkg = $group->{depslistid}[$deps];
877                        next if $done->{rep}{$pkg} && !$rpmlist->[$i]{$group->{done}{list}{$pkg}}{$pkg}{noprovide} || $local_done{$pkg};
878                        $local_done{$pkg} = 1;
879                        my ($deps_list) = find_list($config, $group, $pkg);
880                        $msg .= "calc_needed_size: list $deps_list deps $pkg size $group->{size}{$pkg}{$deps_list}[0] (done $done->{rep}{$pkg} needed_size $num $needed_size->[$num]{fix})\n" if $config->{verbose} > 5;
881                        $needed_size->[$num]{var} += $group->{size}{$pkg}{$deps_list}[0];
882                    }
883                }
884            }
885        }
886    }
887    log_($msg, $config->{verbose}, $config->{LOG}, 4)
888}
889
890sub revert_to {
891    my ($groups, $i, $p2r, $diff, $size, $buildlist) = @_;
892    log_("revert_to: try to find $p2r (diff $diff $diff->{data} " . int @{$diff->{data}} . " $diff->{idx} " . int @{$diff->{idx}} . "\n", $config->{verbose}, $config->{LOG}, 3);
893    foreach (@{$diff->{data}}) {
894        $_ or next; 
895        foreach (@{$_->[5]}) {
896            goto revert_to_ok if $_->[0] eq $p2r
897        } 
898    }
899    log_("ERROR revert_to: $p2r is not present in movement history\n", $config->{verbose}, $config->{LOG}, 2);
900    return 0;
901    revert_to_ok:
902    log_("revert_to: $p2r found\n", $config->{verbose}, $config->{LOG}, 5);
903    my @keep;
904    my $idx;
905    do {
906        $idx = pop @{$diff->{idx}};
907        goto revert_to_endloop if any { $_->[0] eq $p2r } @{$diff->{data}[$idx][5]}; 
908        my $step = $diff->{data}[$idx];
909        if ($groups->[$i]{conflict}{$step->[1]}) {
910            my ($curdir, $g, $list) = @$step;
911            my $cdnum = $curdir->[0];
912            foreach (@{$step->[5]}) { 
913                my ($rpm, undef, undef, $rpmsize) = @$_; 
914                delete $groups->[$g]{done}{rep}{$rpm}; 
915                delete $groups->[$g]{done}{list}{$rpm}; 
916                $diff->{data}[$idx] = 0;
917                $size->{disc}[$cdnum] -= $rpmsize; 
918                $size->{rep}{$cdnum}{$curdir->[1]}{$list} -= $rpmsize;
919                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)
920            }
921            push @{$buildlist->{$list}}, $step->[6] if $step->[4] == 1
922        } else {
923            unshift @keep, $idx;
924        }
925    } while @{$diff->{idx}};
926    revert_to_endloop:
927    die "FATAL revert_to: diff data are empty\n" if ! @{$diff->{data}};
928    push @{$diff->{idx}}, $idx, @keep;
929    1
930}
931
932sub mark_and_check_lists {
933    my ($groups, $i, $needed, $diff, $buildlist, $rpmlist, $mark, $size, $cdsize, $ok, $tobedone, $force_calc) = @_;
934    my $group = $groups->[$i];
935    my $need_to_calc;
936    foreach my $list (@{$group->{orderedlist}{rpm}}) {
937        ref $buildlist->{$list} or next;
938        log_("mark_and_check_list: group $i list $list (mark $mark)\n", $config->{verbose}, $config->{LOG}, 3);
939        if ($config->{list}[$list]{done}) {
940            log_("mark_and_check_lists: list $list is done, ignoring\n", $config->{verbose}, $config->{LOG}, 5);
941            next
942        }
943        if (defined $mark->{cur}{$list}) {
944            log_("mark_and_check_list: mark defined ($mark->{cur}{$list}[0])\n", $config->{verbose}, $config->{LOG},4);
945            $need_to_calc = 1;
946            my $m = $mark->{cur}{$list};
947            my $m_rpm = $m->[0];
948            if ($group->{done}{rep}{$m_rpm}) {
949                log_("mark_and_check_list: $m_rpm done, deleting mark for list $list\n", $config->{verbose}, $config->{LOG},4);
950                push @{$mark->{his}},  $m;
951                delete $mark->{cur}{$list}
952            } elsif ($group->{rejected}{$m_rpm}{$list}) {
953                log_("mark_and_check_list: $m_rpm rejected, deleting mark for list $list\n", $config->{verbose}, $config->{LOG},4);
954                delete $mark->{cur}{$list}
955            } elsif (!@{$buildlist->{$list}}) {
956                log_("mark_and_check_list: list $list finished and $m_rpm not done or rejected\n",1, $config->{LOG},4)
957            }
958        }
959        if (!defined $mark->{cur}{$list} && @{$buildlist->{$list}}) {
960            my $rpm;
961            for (my $j = $#{$buildlist->{$list}}; $j >= 0; $j--) {
962                my $t = $buildlist->{$list}[$j];
963                $rpm = ref $t->[0] ? $t->[0] : $t;
964                if (!$group->{done}{rep}{$rpm->[0]} || $rpm->[1]{relocatable} || $rpm->[1]{noprovide}) {
965                    last
966                } 
967                # this is not necessary, but when we are at it...
968                log_("mark_and_check_list: $rpm->[0] done (list $group->{done}{list}{$rpm->[0]} rep $group->{done}{rep}{$rpm->[0]}), removing from queue\n", $config->{verbose}, $config->{LOG},4);
969                pop @{$buildlist->{$list}}
970            }
971            $mark->{cur}{$list} = $rpm;
972            log_("mark_and_check_list: marking $rpm->[0] for $list\n", $config->{verbose}, $config->{LOG},3);
973        }
974    }
975
976    my $calc = 0;
977    while ($need_to_calc) {
978        $need_to_calc = 0;
979        my $needed_size = $mark->{needed_size};
980        my ($need_in_rep, $av_in_rep, %done_disc) = (0, 0, {});
981        #
982        # First impression would have been to check needed in reverse order, because we could imagine
983        # that, in the current configuration, if needed 2 does not fit, for exemple, one package
984        # is removed, needed 2 is put. But if needed does not fit at this moment, needed 2 is removed,
985        # and needed 3 put, then needed 2 does not fit, and it is needed to revert more to make both of
986        # them fit.
987        #
988        # If fact this could not happen, because if needed 3 does not fit when needed 2 has just been
989        # put, this mean that the calc_needed_size is bogus.
990        #
991        foreach my $rep (@{$group->{replist}{rpm}}) {
992            my ($cd, undef, $num) = @$rep;
993            $need_in_rep += $needed_size->[$num]{var} + $needed_size->[$num]{fix};
994            if (! $done_disc{$cd}) {
995                $av_in_rep += $cdsize->[$cd] - $size->{disc}[$cd];
996                $done_disc{$cd} = 1
997            }
998            log_("mark_and_check_list: cd $cd 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);
999            # Later the difference between fix and var may be used, but right now there is no code to be sure a package is on a specific disc.
1000            # if ($need_in_rep && $need_in_rep > $av_in_rep || $needed_size->[$num]{fix} > $cdsize->[$cd] - $size->{disc}[$cd])
1001                if ($need_in_rep && $need_in_rep > $av_in_rep) {
1002                    if (!$calc) {
1003                        $calc = 1;
1004                        $mark->{needed_size} = [];
1005                        calc_needed_size($group, $i, $needed, $mark->{needed_size}, $buildlist, $rpmlist, $tobedone);
1006                        $need_to_calc = 1;
1007                        last
1008                    }
1009                    ref $mark->{his} or die "FATAL mark_and_check_list: needed packages will not fit on discs ($need_in_rep in disc $cd rep $num > $av_in_rep available)\n";
1010                    # TODO check if that is necessary or not
1011                    # I think it may have been when the choose_alt bug of not rejecting packages when all the alternatives are rejected.
1012                    #pop @{$mark->{his}} if @{$mark->{his}};
1013                    my $p2r;
1014                    #$p2r = pop @{$mark->{his}};
1015                    while (($p2r = pop @{$mark->{his}}) && defined $p2r->[1]{needed} && $p2r->[1]{needed} <= $num) { log_("mark_and_check_list: grepping packages history $p2r->[0] needed $p2r->[1]{needed} history " . (int @{$mark->{his}}) . " \n", $config->{verbose}, $config->{LOG}, 3); }
1016                    my $countdown = $mark->{cd}{$cd}{$p2r->[0]};
1017                    $p2r = pop @{$mark->{his}} while @{$mark->{his}} && $countdown-- >= 0;
1018                    if (!$p2r || $mark->{cd}{$cd}{$p2r->[0]} > 2) {
1019                        die "FATAL mark_and_check_list: a previous revert to put needed packages failed, cannot order packages correctly fo rep $num on disc $cd\n"
1020                    } else {
1021                        log_("mark_and_check_list: not enough space for needed in rep $num on disc $cd\n", $config->{verbose}, $config->{LOG}, 3);
1022                        $mark->{cd}{$cd}{$p2r->[0]}++;
1023                        log_("mark_and_check_list: trying to revert $p2r->[0]\n", $config->{verbose}, $config->{LOG}, 4);
1024                        if (revert_to($groups, $i, $p2r->[0], $diff, $size, $buildlist)) {
1025                            log_("mark_and_check_list: $p2r->[0] reverted\n", $config->{verbose}, $config->{LOG}, 3);
1026                            foreach my $idx (0 .. @{$group->{orderedlist}{rpm}}) {
1027                                my $list = $group->{orderedlist}{rpm}[$idx];
1028                                $needed->{$list} or next;
1029                                my $elt;
1030                                foreach my $tr (1 .. $num) {
1031                                    foreach my $elt (@{$needed->{$list}{alap}[$tr]}) {
1032                                        my $rpm = $elt->[0];
1033                                        if ($group->{rejected}{$rpm}{$list}) {
1034                                            log_("ERROR: $rpm is rejected, ignoring\n", $config->{verbose}, $config->{LOG}, 6);
1035                                            next
1036                                        }
1037                                        push @{$buildlist->{$list}}, $elt;
1038                                    }
1039                                }
1040                                $mark->{cur}{$list} = $elt->[0];
1041                                my $l_idx = $#{$buildlist->{$list}};
1042                                next if $l_idx < 0;
1043                                foreach my $tidx ($idx + 1 .. @{$group->{orderedlist}{rpm}}) {
1044                                    my $l = $group->{orderedlist}{rpm}[$tidx];
1045                                    push(@{$needed->{$l}{asap}}, [ $list, $l_idx ]) if !$config->{list}[$list]{done}
1046                                }
1047                            }
1048                            $calc = 0;
1049                            $need_to_calc = 1;
1050                            last
1051                        } else {
1052                            log_("ERROR mark_and_check_list: reverting to $p2r->[0] failed\n", $config->{verbose}, $config->{LOG}, 4)
1053                        }
1054                    }
1055                }
1056            }
1057        }
1058    return $ok
1059}
1060
1061# TODO the algo is not as beautiful as it should be
1062# ... but it is getting better
1063# ... and better
1064sub buildDiscs {
1065    my ($class, $groups, $buildlist, $rpmlist, $groupok, $size, $cdsize, $cdlists, $cds, $needed, $diff, $n) = @_;
1066    log_("buildDiscs\n", $config->{verbose}, $config->{LOG}, 3);
1067    $config = $class->{config};
1068    if ($n > 1) {
1069        foreach my $i (reverse @$cds) {
1070            $size->{optimize_space}{disc}{$i} = $size->{disc}[$i];
1071            if ($size->{disc}[$i] > $cdsize->[$i]) { 
1072                my $gain = ($size->{disc}[$i] - $cdsize->[$i])/2;
1073                next if $gain < 0;
1074                optimize_space($config, $groups, $diff, $size, $cdsize, $i, $gain, $cdlists,1)
1075            } else {
1076                log_("buildDiscs: disc $i size OK $size->{disc}[$i] ($cdsize->[$i])\n", $config->{verbose}, $config->{LOG},2)
1077            }
1078        }
1079    }
1080    my ($ok, $iti);
1081    my @groupok;
1082    my (@tobedone, @nosrcfit);
1083    my @mark;# = ({}) x @$groups;
1084    $mark[$_] = {} foreach (0 .. $#$groups);
1085    updateGenericLimit($groups, $cdsize);
1086    if (!$config->{fast}) {
1087        # need to initialise needed data
1088        for (my $i = 0; $i < @$groups; $i++) {
1089            my $group = $groups->[$i];
1090            $mark[$i]{needed_size} = [];
1091            calc_needed_size($group, $i, $needed->[$i], $mark[$i]{needed_size}, $buildlist->[$i], $rpmlist, $tobedone[$i]) 
1092        }
1093    }
1094    while (!$ok) {
1095        log_("iti: " . $iti++ . "\n", $config->{verbose}, $config->{LOG},4);
1096        $ok = 1;
1097        for (my $i = 0; $i < @$groups; $i++) {
1098            my $group = $groups->[$i];
1099            if (!$config->{fast}) {
1100                $groupok[$i] = mark_and_check_lists($groups, $i, $needed->[$i], $diff, $buildlist->[$i], $rpmlist, $mark[$i], $size, $cdsize, $groupok[$i], $tobedone[$i], !$groupok[$i]);
1101                $groupok[$i] and next;
1102            }
1103            $ok = loop_on_lists($i, $groups, $group, \@groupok, $needed, $buildlist, \@tobedone, $diff, \@nosrcfit, $size, $cdsize, $cds, $rpmlist, $cdlists, $ok, \@mark, \@groupok); 
1104        }
1105    }
1106    foreach (@nosrcfit) {
1107        my ($rpmd, $srpm, $list, $i, $curdir, $cdnum) = @$_;
1108        my $group = $groups->[$i];
1109        my $done = $group->{done};
1110        my ($srpmrep, $srpmsize, $srpmok) = sourcesSizeCheck($done, $rpmd, $srpm, $group, $groups, $size, $cdsize, $list, $cdlists,0,0, $buildlist, $cds, $i, $diff);
1111        if ($srpmok) {
1112            addSRPMToDiff($rpmd, $done, $diff, $size, $srpmrep, $srpmsize, $curdir, $srpm, $list, $i, $cdnum);
1113        } else {
1114            log_("WARNING: @$srpm does not fit on the discs\n",1, $config->{LOG},2)
1115        }
1116    }
1117    log_("buildDiscs: rejected packages\n", $config->{verbose}, $config->{LOG},2);
1118    my $is_rejected;
1119    for (my $i; $i < @$groups; $i++) {
1120        reprocess_relocatable($groups->[$i], $cdsize, $size);
1121        $groups->[$i]{rejected} or next;
1122        foreach my $rpm (%{$groups->[$i]{rejected}}) {
1123            my $local_rejected;
1124            my $gh = $groups->[$i]{rejected}{$rpm};
1125            my $msg;
1126            foreach my $list (keys %$gh) {
1127                $rpmlist->[$i]{$list}{$rpm}{limit} and next;
1128                $msg .= " [ list $list ] ";
1129                $local_rejected ||= any { $msg .= "$config->{rejected_options}{$_->[0]}: $_->[1],"; $_->[0] =~ /no_disc/ || $_->[0] =~ /no_space/ } @{$gh->{$list}};
1130                chop $msg
1131            }
1132            log_("WARNING buildDisc: group $i REJECTED $rpm ($msg)\n", $config->{verbose}, $config->{LOG}, 2) if $local_rejected;
1133            $is_rejected ||= $local_rejected
1134        }
1135    }
1136    ($is_rejected)
1137}
1138
1139sub reprocess_relocatable {
1140    my ($group, $cdsize, $size) = @_;
1141    # optimize number of hdlist given available space
1142    # and
1143    # add virtual media for installation
1144    my $inst_disc = $group->{installDisc};
1145    my $inst = $config->{disc}[$inst_disc]{function}{data}{installation};
1146    $inst->[1]{tmp_rpmsdir} = [];
1147    my %ignore;
1148    foreach my $c (@{$inst->[1]{rpmsdir}}) {
1149        my ($ls, $cdrep, $repname, $opts) = @$c;
1150        my $min;
1151        my $ok = 1;
1152        my $repnum = $group->{orderedrep}{rpm}{"$cdrep/$repname"};
1153        log_("reprocess_relocatable: list $ls cd $cdrep repname $repname repnum $repnum\n", $config->{verbose}, $config->{LOG},3);
1154        if (defined $group->{reploc}{$repnum} && ref $group->{reploc}{$repnum}{list}) {
1155            while ($ok) {
1156                $ok = 0;
1157                log_("reprocess_relocatable: disc usage $size->{disc}[$cdrep] (disc size $cdsize->[$cdrep])\n", $config->{verbose}, $config->{LOG},6);
1158                $min = $cdsize->[$cdrep];
1159                my $idx;
1160                for (my $i; $i < @{$group->{reploc}{$repnum}{list}}; $i++) {
1161                    my $r = $group->{reploc}{$repnum}{list}[$i];
1162                    my ($new_repnum) = @$r;
1163                    log_("reprocess_relocatable: new rep_num $new_repnum size $group->{reploc}{$repnum}{size}{$new_repnum} old $group->{reploc}{$repnum}{old}{$new_repnum}\n", $config->{verbose}, $config->{LOG},6);
1164                    if (!$ignore{$new_repnum} && $group->{reploc}{$repnum}{old}{$new_repnum} && $group->{reploc}{$repnum}{size}{$new_repnum} < $min) {
1165                        log_("reprocess_relocatable: min $min idx $i\n", $config->{verbose}, $config->{LOG},6);
1166                        $min = $group->{reploc}{$repnum}{size}{$new_repnum};
1167                        $idx = $i
1168                    }
1169                }
1170                if ($size->{disc}[$cdrep] + $min < $cdsize->[$cdrep]) {
1171                    $ok = 1;
1172                    $size->{disc}[$cdrep] += $min;
1173                    my $prev = $group->{reploc}{$repnum}{list}[$idx-1][0] if $idx > 0;
1174                    my $current = $group->{reploc}{$repnum}{list}[$idx][0];
1175                    my $next = $group->{reploc}{$repnum}{list}[$idx+1][0] if $idx < @{$group->{reploc}{$repnum}{list}};
1176                    if (!$prev) { $prev = $next; $next = 0 }
1177                    my $curdir = $group->{reploc}{$repnum}{curdir}{$prev};
1178                    my $list = $group->{reploc}{$repnum}{newlist}{$prev};
1179                    my $reallist = $group->{reploc}{$repnum}{reallist}{$prev};
1180                    log_("reprocess_relocatable: aggregating $current and $next with $prev list $list reallist $reallist\n", $config->{verbose}, $config->{LOG},6);
1181                    foreach my $rep ($current, $next) {
1182                        $rep or next;
1183                        foreach my $diff_data (@{$group->{reploc}{$repnum}{diff}{$rep}}) {
1184                            log_("reprocess_relocatable: updating diff for rep $rep rpm $diff_data->[5][0][0] (cd $curdir->[0] rep $curdir->[1])\n", $config->{verbose}, $config->{LOG},6);
1185                            $diff_data->[0] = $curdir;
1186                            $diff_data->[2] = $list;
1187                            $diff_data->[3] = $prev;
1188                            $diff_data->[8] = $reallist;
1189                            push @{$group->{reploc}{$repnum}{diff}{$prev}}, $diff_data
1190                        }
1191                    }
1192                    $group->{reploc}{$repnum}{list} = [ grep { $_->[0] != $current && $_->[0] != $next } @{$group->{reploc}{$repnum}{list}} ]
1193                }
1194            }
1195            my $fct = $config->{disc}[$cdrep]{function}{data}{generic}{$repname}[0];
1196            foreach my $r (@{$group->{reploc}{$repnum}{list}}) {
1197                my ($new_repnum, $cd, $repname, $newlist) = @$r;
1198                log_("reprocess_relocatable: new rep_num $new_repnum on cd $cd rep $repname list $newlist\n", $config->{verbose}, $config->{LOG},3);
1199                push @{$inst->[1]{tmp_rpmsdir}}, [ $newlist, $cd, $repname ];
1200                push @{$fct->[1]{lists}}, $newlist
1201            }
1202        }
1203        push @{$inst->[1]{tmp_rpmsdir}}, $c
1204    }
1205    my $i;
1206    foreach my $r (@{$inst->[1]{tmp_rpmsdir}}) {
1207        log_("reprocess_relocatable: testing $r->[1]/$r->[2] ($i)\n", $config->{verbose}, $config->{LOG},3);
1208        if (defined $inst->[1]{boot_medium} && $r->[1] == $inst_disc && $i) {
1209            log_("reprocess_relocatable: boot disc is $i\n", $config->{verbose}, $config->{LOG},3);
1210            $inst->[1]{boot_medium} = $i + 1;
1211            last
1212        }
1213        $i++
1214    }
1215}
1216
1217sub processDiff {
1218    my ($class, $groups, $diff, $discsFiles) = @_;
1219    my (@cd, @action);
1220    my %new;
1221    my $prev = $diff->{previous_idx} || {};
1222    foreach (@{$diff->{idx}}) {
1223        push @{$action[1]}, $_ if !$prev->{$_};
1224        $new{$_} = 1
1225    }
1226    foreach (keys %$prev) {
1227        push @{$action[2]}, $_ if !$new{$_}
1228    }
1229    foreach my $op (2,1) {
1230        foreach my $idx (@{$action[$op]}) {
1231            my $d = $diff->{data}[$idx];
1232            if (!$d) { log_("ERROR processDiff: THIS MUST NOT HAPPEN action is null ($d) op $op idx $idx\n", $config->{verbose}, $config->{LOG}); next }
1233            my ($curdir, $grp, $list, undef, undef, $data, undef, undef, $reallist) = @$d;
1234            my $cd = $curdir->[0];
1235            foreach my $ent (@$data) {
1236                my $rpm = $ent->[0];
1237                if (!$rpm) {
1238                    foreach (@$ent) {
1239                        if (ref $_) { log_("ERROR processDiff: @$_\n", $config->{verbose}, $config->{LOG},2) }
1240                        else { log_("ERROR processDiff: $_\n", $config->{verbose}, $config->{LOG},2) }
1241                    }
1242                }
1243                $rpm or next;
1244                my $source = $groups->[$grp]{size}{$rpm}{$reallist || $list}[1];
1245                log_("LOG disc $cd/$curdir->[1] list $list ($reallist) group $grp: ($op) $rpm ($source)\n", $config->{verbose}, $config->{LOG},3);
1246                push @{$cd[$cd]{$curdir->[1]}{$list}{$source}}, [$op, "$groups->[$grp]{urpm}{rpmkey}{rpm}{$rpm}.rpm"];
1247                if ($op == 1) { $discsFiles->[$cd]{$curdir->[1]}{$list}{$groups->[$grp]{urpm}{rpmkey}{rpm}{$rpm}} = $source }
1248                elsif ($op == 2) { delete $discsFiles->[$cd]{$curdir->[1]}{$list}{$groups->[$grp]{urpm}{rpmkey}{rpm}{$rpm}} }
1249            }
1250        }
1251    }
1252    my %new_diff;
1253    # clear diff
1254    foreach my $idx (@{$diff->{idx}}) {
1255        my $nidx = push @{$new_diff{data}}, $diff->{data}[$idx];
1256        push @{$new_diff{idx}}, $nidx - 1;
1257        $new_diff{previous_idx}{$nidx - 1} = 1
1258    }
1259    return \@cd, \%new_diff
1260}
1261
1262
12631
1264
1265# Changelog
1266#
1267# 2002 02 21
1268# change false $j comparaison to $depsdisc in buildDisc to new $thisorderrep value.
1269#
1270# 2002 03 03
1271# new limit option handling.
1272# add updateGenericSoft function
1273# add testSoftLimit function
1274# update size to check rep size
1275#
1276# 2002 03 08
1277# fix autoMode CD adding
1278#
1279# 2002 03 13
1280# better selection of alternatives in multi-list to take the one in the first lists.
1281#
1282# 2002 03 14
1283# add sources new sources handling method
1284# in nosrcfit mode sources are added afterwards
1285#
1286# 2002 03 19
1287# add prelist in geList for cdcom, will be useful for oem too I guess.
1288#
1289# 2002 05 02
1290# add_one_disc: add separate mode for sources mode
1291#
1292# 2002 05 09
1293# add graft structure for md5 and graft point handling
1294#
1295# 2002 05 13
1296# fix a tricky bugs in build_list about fentry shared and not recreated for each packages.
1297#
1298# 2002 06 01
1299# use perl-URPM
1300#
1301# 2002 06 15
1302# new diff mode, global, shared between disc and group, only one table.
1303#
1304# 2002 08 16
1305# new diff_idx table to sort diff data
1306#
1307# 2002 08 24
1308# optimize_space first version, still need to handle correctly needed and more advanced optimization methods.
1309#
1310# 2002 09 18
1311# optimize_space work, fixes and updates.
1312#
1313# 2002 10 25
1314# fix needed assignation pb in closeRPMslist
1315#
1316# 2004 05 27
1317# separate List.pm into List.pm and Build.pm
1318#
1319# 2004 05 28
1320# move find_list to tools as it is used in both Build and List
Note: See TracBrowser for help on using the repository browser.