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