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

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

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

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