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