source: soft/build_system/build_system/mkcd/tags/V4_1_8_1mdk/pm/Mkcd/Group.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: 40.3 KB
Line 
1package Mkcd::Group;
2
3my $VERSION = '2.0.3';
4
5use strict;
6use File::NCopy qw(copy);       
7use File::Path;
8use Mkcd::Disc;
9use Mkcd::List;
10use Mkcd::Build;
11use Mkcd::Tools qw(cleanrpmsrate printTable printDiscsFile readBatchFile printBatchFile log_);
12use Mkcd::Package qw(genDeps getSize);
13use Mkcd::Shell;
14use MDK::Common qw(any);
15#use Mkcd::Optimize qw(print_conflict_matrix);
16
17=head1 NAME
18
19Group - mkcd module
20
21=head1 SYNOPSYS
22
23    require Mkcd::Group;
24
25=head1 DESCRIPTION
26
27C<Mkcd::Group> include the mkcd high level disc building routines.
28
29=head1 SEE ALSO
30
31mkcd
32
33=head1 COPYRIGHT
34
35Copyright (C) 2000,2001,2002,2003,2004 Mandrakesoft <warly@mandrakesoft.com>
36
37This program is free software; you can redistribute it and/or modify
38it under the terms of the GNU General Public License as published by
39the Free Software Foundation; either version 2, or (at your option)
40any later version.
41
42This program is distributed in the hope that it will be useful,
43but WITHOUT ANY WARRANTY; without even the implied warranty of
44MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
45GNU General Public License for more details.
46
47You should have received a copy of the GNU General Public License
48along with this program; if not, write to the Free Software
49Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
50
51=cut
52
53my $config;
54
55sub new {
56    my ($class, $conf) = @_;
57    $config = $conf;
58    bless {
59            config      => $conf,
60            list        => new Mkcd::List($conf),
61            build       => new Mkcd::Build($conf),
62            disc        => new Mkcd::Disc($conf)
63       }, $class;
64}
65
66#
67# group structure
68#
69# $group[group number]{list}{rpm/srpm} = { list => [[cd, repname, {options}],[], ...,[]] }
70#
71# $group[group number]
72# brokendeps   => {
73#       rpm_depending_on_non_listed_locales => 1 ,
74#       rpm_which_deps_are_broken => 2,
75#       rpm_exluded_from_conf => 3 }
76# conflict     => { $group_number => 1 } this group have common disc with generic like function with group $group_number.
77# depslistid   => [ depslist id ]
78# depsrep      => deps repository name
79# discdep
80# discdeps     => { cd => { cds it depends on ] }
81# discrep
82# disc_impacted=> { cd => 1 }
83# done         => { rpm => rep number }
84# installDisc  => install disc for this group
85# filelist     => [FILELIST]
86# list
87# lang         => { locale1 => 1, locale2 => 1}
88# list_conflict=> { list => { type => { grp => { list => { type => 0/1 }}}}}
89# listmatrix
90# listmaxrep   => { rpm/srpm => { list => max ordered rep_name number for list list } }
91# listrpm      => { list => [ rpm ] }
92# listsize     => { rpm => { list => total rpm size, ... } }
93# listsort
94# maxlist
95# maxrep       => max ordered rep_name number
96# maxsize      => rpm maxsize
97# nodeps       => { list => 1}
98# options
99# orderedrep   => { rpm/srpm => { "rep_name" => num } }
100# orderedlist  => { rpm/srpm }
101# pkgdeps      => { package_name => [depslist dependencies ] }
102# pkgrate      => { rpm => rpmsrate_increase }
103# globrpm      => [ "path1/rpm1" ... "pathn/rpmq" ]
104# rejected     => { rpm => [ "error", "message" ] }
105# rep          => { type => list => [ { "path" => [pkg list] } } ]
106# rep_pkg      => { type => { "path" => [pkg list] } }
107# replist      => { $type => [ [ cd, repname, num, [ [related list, related curdir] [] ] ], [], ..., []] }
108# reploc
109# revdeps      => [ reversed depslist ]
110# rpmsrate     => { rpmsrate }
111# rpmsratepath => rpmsrate path
112# score        => [ score weight ]
113# scoredlist   => { rpm_name => score }
114# size         => { rpm_name => [filesize, list number, directory], ... }
115# srpmname     => { srpm => srpm-version-release }
116# sourcerpm    => { rpm => sourcerpm }
117# urpm         => URPM::urpm
118#     option added to urpm
119#     rpmkey
120#     sourcerpm
121#     rpm
122#
123
124sub getGroups {
125    my ($config, $lists) = @_;
126    my (@list, %cd, %done, %list, %repname);
127    log_("getGroups\n", $config->{verbose}, $config->{LOG}, 1);
128    foreach my $i (keys %$lists) {
129        log_("getGroups: disc $i\n", $config->{verbose}, $config->{LOG}, 2);
130        $cd{$i} = 1;
131        ref $config->{disc}[$i]{fastgeneric} or next;
132        foreach my $f (@{$config->{disc}[$i]{fastgeneric}}) {
133            my $repname = $f->[1]{repname};
134            my @k = keys %{$f->[1]};
135            ref $f->[1]{lists} or do { log_("ERROR getGroups: disc $i lists not defined for rep $repname\n", $config->{verbose}, $config->{LOG},3); next };
136            log_("getGroups: lists @{$f->[1]{lists}} repname $repname options (@k)\n", $config->{verbose}, $config->{LOG},3);
137            foreach my $g_list (@{$f->[1]{lists}}) {
138                log_("getGroups: list $g_list\n", $config->{verbose}, $config->{LOG}, 3);
139                my $idx;
140                $idx = push @{$list[$g_list]}, [ $i, ${repname}, $f->[1], {} ];
141                push @{$repname{$i}{$repname}}, [ $g_list, $idx - 1 ];
142                log_("getGroups: cd $i repname $repname list $g_list\n", $config->{verbose}, $config->{LOG},3);
143                $list{$g_list} = 0
144            }
145        }
146    }
147    my @group;
148    my $g = prepare_cloned_discs(\@group, \%done, $config, $lists);
149    my %donerep;
150    foreach my $i (keys %$lists) {
151        my $t = $config->{disc}[$i]{function}{data}{installation};
152        log_("getGroups: disc $i ($t)\n", $config->{verbose}, $config->{LOG},2);
153        ref $t and do {
154            log_("getGroups: install disc for group $g => ($i)\n", $config->{verbose}, $config->{LOG},3);
155            $group[$g]{installDisc} = $i;
156            $group[$g]{options} = $t->[1];
157            $group[$g]{score} ||= $t->[1]{score} || [1,1,1];
158            ($group[$g]{maxrep}{rpm}, $group[$g]{maxlist}{rpm}) = addRepList("rpm", $group[$g], $g, $t->[1]{rpmsdir}, $donerep{$g}, \%done, \%list, \%cd, \%repname, $i, \@list);
159            ($group[$g]{maxrep}{srpm}, $group[$g]{maxlist}{srpm}) = addRepList("srpm", $group[$g], $g, $t->[1]{srpmsdir}, $donerep{$g}, \%done, \%list, \%cd, \%repname, $i, \@list);
160            my $struct_v = $config->{struct_version};
161            my $media_info = $config->{struct}{$struct_v}{media_info};
162            $group[$g]{rpmsratepath} ||= $t->[1]{rpmsrate} || "$t->[1]{install}/$media_info/rpmsrate";
163            log_("getGroups: using $group[$g]{rpmsratepath} as rpmsrate file\n", $config->{verbose}, $config->{LOG},4);
164            $group[$g]{list} and $group[$g]{depsrep} = join '-', keys %{$group[$g]{list}};
165            log_("getGroups: $group[$g]{depsrep} defined as deps file directory\n", $config->{verbose}, $config->{LOG},4);
166            if (ref $t->[1]{lang}) {
167                foreach (@{$t->[1]{lang}}) { $group[$g]{lang}{$_} = 1 }
168            }
169
170            $group[$g]{discdeps}{$i} ||= {};
171            log_("getGroups DEBUG: discdep for group $g => ($group[$g]{discdep})\n", $config->{verbose}, $config->{LOG},5);
172            $g++;
173        }
174    }
175    my %alone;
176    foreach (keys %list) {
177        $list{$_} and next;
178        log_("getGroups: searching alone groups list $_\n", $config->{verbose}, $config->{LOG},2);
179        # FIXME not clean as now with the --group option of generic getAlone add new group
180        $group[$g]{score} = [1,1,1];
181        $group[$g]{depsrep} = $_;
182        $g = getAlone($list[$_], $_, \@group, $g, \%done, \%alone);
183        $list{$_}++;
184        log_("getGroups: adding a group $g for list $_\n", $config->{verbose}, $config->{LOG},2);
185        $g++
186    }
187
188    foreach my $i (keys %$lists) {
189        $done{$i} and next;
190        $done{$i} = {};
191        log_("getGroups: searching alone disc disc $i does not handled by any group, setting alone group\n", $config->{verbose}, $config->{LOG},2);
192        $group[$g]{discdeps}{$i} ||= {};
193        log_("getGroups: adding a group $g for disc $i\n", $config->{verbose}, $config->{LOG},2);
194        $g++
195    }
196   
197    for (my $i; $i < @group; $i++) {
198        $group[$i]{orderedlist}{rpm} ||= [];
199        foreach (@{$group[$i]{orderedlist}{rpm}}) {
200            $group[$i]{list}{$_}{srpm} ||= []
201        }
202        $group[$i]{orderedlist}{srpm} ||= [];
203        log_("getGroups: ordered rpm list for group $i: @{$group[$i]{orderedlist}{rpm}}\n", $config->{verbose}, $config->{LOG},2);     
204        log_("getGroups: ordered srpm list for group $i: @{$group[$i]{orderedlist}{srpm}}\n", $config->{verbose}, $config->{LOG},2);   
205    }
206   
207    # $config->{verbose} and printTable(\@group);
208    \@group
209}
210
211sub getAlone {
212    my ($list, $ls, $groups, $g, $done, $alone) = @_;
213    my $num = 1;
214    $list or return;
215    my $lnsort = 1;
216    my $replist_list;
217    my $group = $groups->[$g];
218    my $grp = $g;
219    my $inc;
220    foreach my $l (@$list) {
221        my ($cd, $rep, $opt) = @$l;
222        $done->{$cd}{$rep}{$ls} and next;
223        log_("WARNING getAlone: rep $rep of list $_ does not belong to any installation disc, setting alone group $g\n", $config->{verbose}, $config->{LOG}, 1);
224        my $type = $opt->{source} ? "srpm" : "rpm";
225        log_("getAlone: searching alone groups list $ls cd $cd rep $rep type $type\n", $config->{verbose}, $config->{LOG},1);
226        if ($opt->{group}) {
227            $num = 1;
228            if ($alone->{$opt->{group}}) {
229                $grp--;
230                $g = $alone->{$opt->{group}};
231                log_("getAlone: using existing group $g\n", $config->{verbose}, $config->{LOG},1);
232                $group = $groups->[$g]
233            } else {
234                if ($inc) {
235                    $grp++;
236                    log_("getAlone: creating a new group $g\n", $config->{verbose}, $config->{LOG},1);
237                    $groups->[$grp]{score} = [1,1,1];
238                    $groups->[$grp]{depsrep} = $ls;
239                }
240                $g = $grp;
241                $alone->{$opt->{group}} = $g;   
242                $group = $groups->[$g];
243                $inc = 1
244            }
245            log_("getAlone: adding list $ls cd $cd rep $rep type $type in group $opt->{group} ($g)\n", $config->{verbose}, $config->{LOG},1);
246        }
247        $group->{list}{$ls}{$type} or push @{$group->{orderedlist}{$type}}, $ls;       
248        log_("getAlone: ordered list for group $g type $type (@{$group->{orderedlist}{$type}})\n", $config->{verbose}, $config->{LOG},1);
249        $group->{listmatrix}{$type}{$ls}{$ls} = $num if !$group->{listmatrix}{$type}{$ls}{$ls} || $num < $group->{listmatrix}{$type}{$ls}{$ls};
250        $config->{list}[$ls]{disc}{$cd}{$rep}{master} ||= $g;
251        if (! exists $config->{disc}[$cd]{group_master}) {
252            log_("getAlone: setting group $g as master of disc $cd\n", $config->{verbose}, $config->{LOG},2);
253            $config->{disc}[$cd]{group_master} = $g;
254            push @{$group->{master_of_disc}}, $cd
255        }
256        $config->{disc}[$cd]{group_list}{$g}{$ls}{$type} = 1;
257        push @{$group->{list}{$ls}{$type}}, $l;
258        push @{$group->{list_cd}{$ls}{$cd}{$type}}, $l;
259        my $cur_num = \$group->{orderedrep}{$type}{"$cd/$rep"};
260        print "CUR_NUM group $group ($g) curnum $cur_num $$cur_num\n";
261        if (! $$cur_num) {
262            $$cur_num = $num;
263            $replist_list = { $ls => $l };
264            $group->{orderedrep}{$type}{"$cd/$rep"} = $num;
265            $group->{replist}{$type}[$num-1] = [ $cd, $rep, $num, $replist_list ];
266            $num++
267        } else {
268            $group->{replist}{$type}[$$cur_num-1][3]{$ls} = $l
269        }
270        print "CUR_NUM $cur_num $$cur_num\n";
271        foreach my $v (@{$config->{list}[$ls]{virtual}}) {
272            my ($d_cd, $d_rep) = ($v->{disc}, $v->{repname});
273            log_("getAlone: setting disc_prereq for disc on disc $d_cd for list $ls disc $cd group $g\n", $config->{verbose}, $config->{LOG},2);
274            $group->{disc_prereq}{$d_cd}++
275        }
276        if (!$group->{listsort}{$ls}{$type}) { $group->{listsort}{$ls}{$type} = $lnsort++ };
277        $done->{$cd}{$rep}{$ls}++;
278        log_("getAlone: searching alone groups group $g handle disc $l->[0]\n", $config->{verbose}, $config->{LOG},2);
279        # FIXME discdeps may be deprecated for group as hdlists are built without reading real directories.
280        $group->{discdeps}{$l->[0]} ||= {};
281        $group->{disc_impacted}{$l->[0]} = 1;
282        log_("getAlone: setting nodeps flag for group $g list $ls\n", $config->{verbose}, $config->{LOG},3) if $opt->{nodeps};
283        $group->{nodeps}{$ls} = $opt->{nodeps};
284        $group->{options}{nodeps} = $opt->{nodeps}
285    }
286    $grp
287}
288
289sub addRepList {
290    my ($type, $group, $g, $replist, $donerep, $done, $list, $disc, $repname, $i, $listTable) = @_;
291    my $num = 1;
292    my $lnsort = 1;
293    my $replist_list;
294    foreach (@$replist) {
295        my ($cdlist, $cd, $name) = @$_;
296        my $opt = $_->[3] || {};
297        log_("getGroups: group $g cd $cd repname $name list $cdlist noauto ($opt->{noauto})\n", $config->{verbose}, $config->{LOG},2);
298        if ($donerep->{$type}{$cd}{$name}{$cdlist}) {
299            log_("ERROR getGroups: $cd/$name/$cdlist is defined multiple time for group $g, ignoring\n", $config->{verbose}, $config->{LOG}); next }
300        $donerep->{$type}{$cd}{$name}{$cdlist} = 1;
301        if (!$disc->{$cd}) { log_("ERROR getGroups: disc $cd not in list, ignoring\n", $config->{verbose}, $config->{LOG}); next }
302        my $ln = $repname->{$cd}{$name};
303        if (!$ln) { log_("ERROR getGroups: $name on disc $cd does not exist\n", $config->{verbose}, $config->{LOG}); next }
304        my $cur_num = \$group->{orderedrep}{$type}{"$cd/$name"};
305        my $tmp_num = $num;
306        if (! $$cur_num) {
307            $$cur_num = $num;
308            $replist_list = {};
309            $group->{orderedrep}{$type}{"$cd/$name"} = $num;
310            @{$group->{reverse_rep}{$type}{$num}}{'cd','name'} = ($cd, $name);
311            log_("getGroups: reverse rep for $num type $type $group->{reverse_rep}{$type}{$num}{cd} - $group->{reverse_rep}{$type}{$num}{name}\n", $config->{verbose}, $config->{LOG},2);
312            $group->{replist}{$type}[$num-1] = [ $cd, $name, $num, $replist_list ];
313            $num++
314        } else {
315            $replist_list = $group->{replist}{$type}[$$cur_num-1][3]
316        }
317        $cd != $i and $group->{discdeps}{$i}{$cd}++;
318        $group->{disc_impacted}{$cd} = 1;
319        if ($cd != $i) { log_("getGroups: group $g ($i) handle disc $cd\n", $config->{verbose}, $config->{LOG},2) }
320        foreach my $l (@$ln) {
321            my ($ls, $idx) = @$l;
322            next if $cdlist && $cdlist != $ls;
323            next if $replist_list->{$ls};
324            my $list_options = $listTable->[$ls][$idx][2];
325            if ($group->{listmaxrep}{$type}{$ls} < $group->{orderedrep}{$type}{"$cd/$name"}) { $group->{listmaxrep}{$type}{$ls} = $group->{orderedrep}{$type}{"$cd/$name"} }
326            $group->{list}{$ls}{$type} or push @{$group->{orderedlist}{$type}}, $ls;   
327            foreach my $lst_ent (@$ln) { 
328                log_("addRepList: listmatrix $type list $ls list $lst_ent->[0] = $tmp_num\n", $config->{verbose}, $config->{LOG},2);
329                $group->{listmatrix}{$type}{$ls}{$lst_ent->[0]} = $tmp_num if !$group->{listmatrix}{$type}{$ls}{$lst_ent->[0]} || $tmp_num < $group->{listmatrix}{$type}{$ls}{$lst_ent->[0]}
330            } 
331            foreach my $lst (@{$group->{orderedlist}{$type}}) { 
332                log_("addRepList: listmatrix $type list $ls list $lst = $group->{listmatrix}{$type}{$lst}{$lst}\n", $config->{verbose}, $config->{LOG},2);
333                $group->{listmatrix}{$type}{$ls}{$lst} = $group->{listmatrix}{$type}{$lst}{$lst} if !$group->{listmatrix}{$type}{$ls}{$lst} || $group->{listmatrix}{$type}{$lst}{$lst} < $group->{listmatrix}{$type}{$ls}{$lst}
334            }
335           
336            if (!$group->{listsort}{$ls}{$type}) { $group->{listsort}{$ls}{$type} = $lnsort++ };
337            my $curdir = [ $cd, $name, $list_options, $opt ];
338            push @{$group->{list}{$ls}{$type}}, $curdir;
339            push @{$group->{list_cd}{$ls}{$cd}{$type}}, $curdir;
340            $replist_list->{$ls} = $curdir;
341            foreach my $v (@{$config->{list}[$ls]{virtual}}) {
342                my ($d_cd, $d_rep) = ($v->{disc}, $v->{repname});
343                log_("addRepList: setting disc_prereq for disc on disc $d_cd for list $ls disc $cd group $g\n", $config->{verbose}, $config->{LOG},2);
344                $group->{disc_prereq}{$d_cd}++
345            }
346            if ($opt->{fixed}) {
347                if (! exists $config->{list}[$ls]{disc}{$cd}{$name}{master}) {
348                    log_("WARNING addRepList: disc $cd list $ls rep $name has no master yet\n", $config->{verbose}, $config->{LOG},2) if !$config->{list}[$ls]{disc}{$cd}{$name}{master};
349                    $config->{list}[$ls]{disc}{$cd}{$name}{master} = $g
350                }
351            } else {
352                # this group is the master for this rep
353                log_("ERROR addRepList: group $g has already a master, overridding\n", $config->{verbose}, $config->{LOG},2) if $config->{list}[$ls]{disc}{$cd}{$name}{master};
354                $config->{list}[$ls]{disc}{$cd}{$name}{master} = $g;
355                if (! exists $config->{disc}[$cd]{group_master}) {
356                    log_("addRepList: setting group $g as master of disc $cd\n", $config->{verbose}, $config->{LOG},2);
357                    $config->{disc}[$cd]{group_master} = $g;
358                    push @{$group->{master_of_disc}}, $cd
359                }
360            }
361            $config->{disc}[$cd]{group_list}{$g}{$ls}{$type} = 1;
362            $list->{$ls}++;
363            $done->{$cd}{$name}{$ls}++;
364        }
365    }
366    if (ref $group->{master_of_disc}) {
367        my $seq_size = @{$group->{master_of_disc}};
368        my $i = 1;
369        foreach my $cd (@{$group->{master_of_disc}}) {
370            log_("addRepList: disc sequence $cd is $i/$seq_size\n", $config->{verbose}, $config->{LOG},2);
371            $config->{disc}[$cd]{seq_size} = $seq_size;
372            $config->{disc}[$cd]{seq_num} = $i++;
373        }
374    }
375    return $num, $lnsort
376}
377
378sub preCheck {
379    # TODO
380    # may not be necessary
381}
382
383sub orderGroups {
384    my ($config, $groups, $lists, $acds) = @_;
385    my @metagroups;
386    my @tmpmetagroups;
387    my @groupmeta;
388    my $ok;
389    my $check_group = sub {
390        my ($i, $og, $cd) = @_;
391        log_("orderGroups: checking group $i\n", $config->{verbose}, $config->{LOG},1);
392        if (ref $groups->[$i]{master_of_disc}) {
393            if ($groupmeta[$i] == $groupmeta[$og]) {
394                log_("orderGroups: setting group $i different from $og cos of disc $cd\n", $config->{verbose}, $config->{LOG},5);
395                $groupmeta[$i] = $groupmeta[$og] + 1;
396                return 0;
397            }
398        } elsif ($groupmeta[$i] != $groupmeta[$og] && $og == $config->{disc}[$cd]{group_master}) {
399            log_("orderGroups: setting group $i equal to $og cos of disc $cd\n", $config->{verbose}, $config->{LOG}, 5);
400            $groupmeta[$i] = $groupmeta[$og];
401            return 0
402        }
403        1
404    };
405    # FIXME This algo can create empty metagroups
406    while (!$ok) {
407        log_("orderGroups: ordering metagroups\n", $config->{verbose}, $config->{LOG}, 4);
408        $ok = 1;
409        my %handled;
410        for (my $i; $i < @$groups; $i++) {
411            if ($groups->[$i]{installDisc}) {
412                $lists->{$groups->[$i]{installDisc}} == 2 or next
413            }
414            log_("orderGroups: group $i (install disc $groups->[$i]{installDisc})\n", $config->{verbose}, $config->{LOG}, 6);
415            foreach my $list (keys %{$groups->[$i]{list}}) {
416                foreach my $type (keys %{$groups->[$i]{list}{$list}}) {
417                    foreach my $rep (@{$groups->[$i]{list}{$list}{$type}}) {
418                        my ($cd, $r) = ($rep->[0], $rep->[1]);
419                        $lists->{$cd} == 2 or next;
420                        my $og = $config->{disc}[$cd]{group_master};
421                        $handled{$cd}{$og} = 1;
422                        $og == $i and next;
423                        log_("orderGroups: master of disc $cd/$r = ($og)\n", $config->{verbose}, $config->{LOG}, 8);
424                        $ok &&= $check_group->($i,$og,$cd);
425                    }
426                }
427            }
428        }
429        for (my $i; $i < @$groups; $i++) {
430            foreach my $cd (keys %{$groups->[$i]{disc_prereq}}) {
431                log_("ordreGroups: searching for disc_prereq for group $i disc $cd\n", $config->{verbose}, $config->{LOG}, 5);
432                foreach (keys %{$handled{$cd}}) {
433                    $_ == $i and next;
434                    log_("ordreGroups: disc $cd handled by group $_\n", $config->{verbose}, $config->{LOG}, 5);
435                    # I do not want group to be set equal in prereq checking (this happen for alone groups when the CD is owned by another group)
436                    #$ok &&= $check_group->($i,$_,$cd);
437                    if ($groupmeta[$i] == $groupmeta[$_]) {
438                        log_("orderGroups: setting group $i different from $_ cos of disc $cd\n", $config->{verbose}, $config->{LOG}, 3);
439                        $groupmeta[$i] = $groupmeta[$_] + 1;
440                        $ok = 0
441                    } 
442                }
443            }
444        }
445    }
446    for (my $i; $i < @$groups; $i++) {
447        if ($groups->[$i]{installDisc}) {
448            $lists->{$groups->[$i]{installDisc}} == 2 or next
449        }
450        log_("orderGroups: group $i metagroup $groupmeta[$i]\n", $config->{verbose}, $config->{LOG}, 8);
451        push @{$tmpmetagroups[$groupmeta[$i]][0]}, $groups->[$i];
452    }
453    my %donedisc;
454    for (my $meta; $meta < @tmpmetagroups; $meta++) {
455        my $mg = $tmpmetagroups[$meta];
456        my %cd;
457        my %cdg;
458        my %iogroup;
459        my %cdiogroup;
460        my $i = 1;
461        foreach (@$acds) { $cd{$_} = $i; $cdiogroup{$_} = $i++ }
462        my $grps = $mg->[0];
463        my $i = 0;
464        foreach (0 .. $#$grps){ $iogroup{$_} = $i++ }
465        my $loop;
466        my $ok = 0;
467        my %groups_conflict;
468        my %old_values;
469        while (!$ok && !$loop) {
470ordering_loop: {
471            $ok = 1;
472            # WARNING group number are not definitive here, they must not be saved!
473            foreach my $gn (0 .. $#$grps) {
474                my $g = $grps->[$gn];
475                my @discdeps = (keys %{$g->{discdeps}});
476                my @lists =  (keys %{$g->{list}});
477                log_("orderGroups: group $gn discs @discdeps list @lists\n", $config->{verbose}, $config->{LOG}, 5);
478                foreach my $cd (@discdeps) {
479                    log_("orderGroups: disc $cd DONEDISC $donedisc{$cd} group $gn\n", $config->{verbose}, $config->{LOG}, 5);
480                    $donedisc{$cd} and next;
481                    if ($iogroup{$gn}) {
482                        log_("orderGroups: making disc $cd from group $gn in the same iogroup as group $gn ($iogroup{$gn})\n", $config->{verbose}, $config->{LOG}, 5);
483                        if ($iogroup{$gn} != $cdiogroup{$cd}) {
484                            if ($cdiogroup{$cd} == $old_values{$gn}) {
485                                log_("ERROR: orderGroups: loop in discs dependencies, taking manual order\n", $config->{verbose}, $config->{LOG}); 
486                                $loop = 1;
487                                last ordering_loop
488                            }
489                            $old_values{$gn} = $iogroup{$gn};
490                            $iogroup{$gn} = $cdiogroup{$cd};
491                            foreach my $all_cd (@discdeps) {
492                                $cdiogroup{$all_cd} = $iogroup{$gn};
493                            }
494                            $ok = 0
495                        }
496                    } else {
497                        $iogroup{$gn} = $cdiogroup{$cd}
498                    }
499                    $groups_conflict{$cd}{$gn} = 1;
500                    #$g->{conflict} = $groups_conflict{$cd};
501                    #log_("orderGroups: group $gn conflict with group $gn ($g->{conflict}{$gn})\n", $config->{verbose}, $config->{LOG}, 4);
502                    log_("orderGroups: orderGroups: disc $cd\n", $config->{verbose}, $config->{LOG}, 5);
503                    $lists->{$cd} >= 1 or next;
504                    $cdg{$cd} = {};
505                    if (ref $g->{discdeps}{$cd}) {
506                        foreach (keys %{$g->{discdeps}{$cd}}) {
507                            $donedisc{$_} and next;
508                            $cdiogroup{$_} = $cdiogroup{$cd}; 
509                            log_("orderGroups: disc $cd => $_\n", $config->{verbose}, $config->{LOG}, 7);
510                            if ($cdg{$cd}{$_}) { 
511                                log_("ERROR: orderGroups: loop in discs dependencies, taking manual order\n", $config->{verbose}, $config->{LOG}); 
512                                $loop = 1;
513                                last ordering_loop
514                            }
515                            $cdg{$cd}{$_} = 1;
516                            $cdg{$_} = {};
517                            if ($cd{$cd} <= $cd{$_}) { 
518                                $cd{$cd} = $cd{$_} + 1;
519                                $ok = 0
520                            }
521                        }
522                    }
523                }
524            }
525        }
526        }
527        # FIXME This code may not be needed, as the group with only fixed list are alone, and only linked to one disc, they should
528        # not be separated into a new IO group, but this I am not sure.
529        foreach my $gn (0 .. $#$grps) {
530            my $g = $grps->[$gn];
531            my @discdeps = (keys %{$g->{discdeps}});
532            my @lists =  (keys %{$g->{list}});
533            my $all_fixed = 1;
534            foreach my $list (@lists) {
535                $all_fixed &&= $config->{list}[$list]{fixed}
536            }
537            if ($all_fixed) {
538                # a fixed rep should only have one CD
539                my ($cd) = $discdeps[0];
540                log_("orderGroups: all the list are fixed for group $gn, including it into same iogroup as disc $cd ($cdiogroup{$cd})\n", $config->{verbose}, $config->{LOG}, 5);
541                $groups_conflict{$cd}{$gn} = 1;
542                $iogroup{$gn} = $cdiogroup{$cd};
543            }
544        }
545        if ($loop) {
546            # Does not take care of iogroup in manual mode
547            $metagroups[$meta][0][0] = $mg;
548            foreach my $c (@$acds) { $cdg{$c} and $lists->{$c} == 2 and push @{$metagroups[$meta][0][1]}, $c and $donedisc{$c} = 1 } 
549        } else {
550            my @siogroup = sort { $iogroup{$a} <=> $iogroup{$b} } keys %iogroup;
551            my %iogroupcd;
552            $metagroups[$meta][0][0] = [];
553            for (my ($i, $j); $i < @siogroup; $i++) {
554                if ($i && $iogroup{$siogroup[$i]} != $iogroup{$siogroup[$i-1]}) {
555                    $j++;
556                    $metagroups[$meta][$j][0] = []
557                }
558                log_("orderGroups: siogroup $i (j $j siogroup $siogroup[$i] iogroup $iogroup{$siogroup[$i]} cd " . join(',',keys %{$grps->[$siogroup[$i]]{disc_impacted}})  ." list " .  join(',',keys %{$grps->[$siogroup[$i]]{list}}) . ")\n", $config->{verbose}, $config->{LOG}, 8);
559                my $g = $grps->[$siogroup[$i]];
560                push @{$metagroups[$meta][$j][0]}, $g;
561                $iogroupcd{$_} = $j foreach keys %{$g->{disc_impacted}}
562            }
563            #foreach (keys %iogroup) {
564            #   log_("orderGroups: group $_ (CDs " . join(',', keys %{$grps->[$_]{disc_impacted}}) . ") in iogroup $iogroup{$_}\n", 1, $config->{LOG})
565            #}
566            my @scds = sort { $cd{$a} <=> $cd{$b} } keys %cdg;
567            foreach my $c (@scds) { $lists->{$c} == 2 and push @{$metagroups[$meta][$iogroupcd{$c}][1]}, $c and $donedisc{$c} = 1 }     
568        }
569        for (my $iogi; $iogi < @{$metagroups[$meta]}; $iogi++) {
570            ref $metagroups[$meta][$iogi][1] or next;
571            log_("orderGroups: IO group $iogi disc sorting @{$metagroups[$meta][$iogi][1]}\n", $config->{verbose}, $config->{LOG}, 4);
572        }
573       
574#       for (my $i = 0; $i < @$grps; $i++) {
575#           foreach my $ls (keys %{$grps->[$i]{list}}) {
576#               foreach my $l (keys %{$grps->[$i]{list}}) {
577#                   log_("orderGroups: group $i listmatrix list $ls - list $l -> $grps->[$i]{listmatrix}{rpm}{$ls}{$l}\n", $config->{verbose}, $config->{LOG})
578#               }
579#               foreach my $t (keys %{$grps->[$i]{list}{$ls}}) {
580#                   my $rep = $grps->[$i]{list}{$ls}{$t};
581#                   for (my $grp = 0; $grp < @$grps; $grp++) {
582#                       foreach my $list (keys %{$grps->[$grp]{list}}) {
583#                           foreach my $type (keys %{$grps->[$grp]{list}{$list}}) {
584#                               my $rep2 = $grps->[$grp]{list}{$list}{$type};
585#                               foreach my $a (@$rep) {
586#                                   if (any { $a->[0] == $_->[0] } @$rep2) {
587#                                       log_("orderGroups: group $i list $ls type $t conflicts with group $grp list $list type $type\n", $config->{verbose}, $config->{LOG});   
588#                                       $grps->[$i]{conflict}{$grp} = 1;
589#                                       $grps->[$i]{list_conflict}{$ls}{$t}{$grp}{$list}{$type} = 1;
590#                                       last
591#                                   }
592#                               }
593#                           }
594#                       }
595#                   }
596#               }
597#           }
598#       }
599    }
600    # add alone discs
601    my @cd;
602    foreach (keys %donedisc) {
603        $donedisc{$_} or push @cd, $_ 
604    }
605    @cd and push @metagroups, [[0, \@cd]];
606   
607    for (my $m = 0; $m < @metagroups; $m++) {
608        for (my $iog = 0; $iog < @{$metagroups[$m]}; $iog++) {
609            #log_("GROUP $i iog $iog: $metagroups[$m][$iog][0] (@{$metagroups[$m][$iog][0]})\n", $config->{verbose}, $config->{LOG}, 3);
610            my $grps = $metagroups[$m][$iog][0];
611            for (my $i = 0; $i < @$grps; $i++) {
612                foreach my $ls (keys %{$grps->[$i]{list}}) {
613                    foreach my $l (keys %{$grps->[$i]{list}}) {
614                        foreach my $t (keys %{$grps->[$i]{list}{$ls}}) {
615                            my $rep = $grps->[$i]{list}{$ls}{$t};
616                            for (my $grp = 0; $grp < @$grps; $grp++) {
617                                foreach my $list (keys %{$grps->[$grp]{list}}) {
618                                    foreach my $type (keys %{$grps->[$grp]{list}{$list}}) {
619                                        my $rep2 = $grps->[$grp]{list}{$list}{$type};
620                                        foreach my $a (@$rep) {
621                                            if (any { $a->[0] == $_->[0] } @$rep2) {
622                                                log_("orderGroups: group $i list $ls type $t conflicts with group $grp list $list type $type\n", $config->{verbose}, $config->{LOG});   
623                                                $grps->[$i]{conflict}{$grp} = 1;
624                                                $grps->[$grp]{conflict}{$i} = 1;
625                                                $grps->[$i]{list_conflict}{$ls}{$t}{$grp}{$list}{$type} = 1;
626                                                last
627                                            }
628                                        }
629                                    }
630                                }
631                            }
632                        }
633                    }   
634                }
635            }
636        }
637    }
638    \@metagroups
639}
640
641sub getGroupReps {
642    my ($config, $group, $discsFiles) = @_;
643    my $topdir = "$config->{topdir}/build/$config->{name}";
644    my $check_discsFiles = sub {
645        my ($cd, $rep, $listnumber, $rep_nb) = @_;
646        log_("getGroupReps check_discsfiles: disc $cd rep $rep list $listnumber\n", $config->{verbose} , $config->{LOG}, 5);
647        foreach (keys %{$discsFiles->[$cd]{$rep}{$listnumber}}) {
648            my $type = /src$/ ? 'srpm' : 'rpm';
649            my $d = $discsFiles->[$cd]{$rep}{$listnumber}{$_};
650            push @{$group->{rep}{$listnumber}[$rep_nb]{$type}{$d}}, $_;
651            push @{$group->{rep_pkg}{$type}{$d}}, $_
652        }
653    };
654    # FIXME sep_arch is not used, maybe a chech should prevent both sep_arch and non sep_arch mode.
655    # However current scheme is more robust.
656    my $check_dir = sub {
657        my ($dir, $listnumber, $rep_nb, $type, $test, $sep_arch) = @_;
658        log_("getGroupReps check_dir: dir $dir list $listnumber rep_nb $rep_nb type $type\n", $config->{verbose}, $config->{LOG},6);
659        my $add_rpm = sub {
660            my ($d, $rpm) = @_;
661            $rpm =~ /($test)\.rpm$/ or return;
662            $rpm = ~/(.*)\.rpm$/ or return;
663            push @{$group->{rep}{$listnumber}[$rep_nb]{$type}{$d}}, $1;
664            push @{$group->{rep_pkg}{$type}{$d}}, $1
665        };
666        my $RPMS;
667        if (!opendir $RPMS, $dir) { log_("WARNING getGroupReps: cannot open $dir\n", $config->{verbose}, $config->{LOG}); return }
668        foreach (readdir $RPMS) {
669            if (-d "$dir/$_") {
670                opendir my $rpm_dir, "$dir/$_";
671                foreach my $r (readdir $RPMS) {
672                    $add_rpm->("$dir/$_",$r)
673                }
674            } else {
675                $add_rpm->($dir,$_)
676            }
677        }
678        closedir $RPMS
679    };
680    my $testarch = join '|', keys %{$config->{ARCH}};
681    foreach my $listnumber (keys %{$group->{list}}) {
682        my $ok;
683        foreach (@{$group->{list}{$listnumber}{rpm}}) {
684            !$_->[3]{nodeps} and $ok = 1
685        }
686        if (!$ok) { $group->{nodeps}{$listnumber} = 1 }
687        log_("getGroupReps list $listnumber\n", $config->{verbose}, $config->{LOG},3);
688        my $rep_nb;
689        if (ref $config->{list}[$listnumber]{packages}) {
690            foreach (@{$config->{list}[$listnumber]{packages}}) {
691                log_("getGroupReps: rep num $rep_nb\n", $config->{verbose}, $config->{LOG},4);
692                foreach my $t ('rpm', 'srpm') {
693                    foreach my $d (@{$_->{$t}}) {
694                        log_("getGroupReps: $d\n", $config->{verbose}, $config->{LOG},5);
695                        $check_dir->($d, $listnumber, $rep_nb, $t, $t eq 'rpm' ? $testarch : 'src');
696                    }
697                }
698                $rep_nb++
699            }
700        }
701       
702        foreach my $d (@{$config->{list}[$listnumber]{virtual}}) {
703            my $cd = $d->{disc};
704            my $rep = $d->{repname};
705            my $path = $config->{disc}[$cd]{function}{data}{dir}{$rep}[1]{reploc};
706            my $sep_arch = $config->{disc}[$cd]{function}{data}{dir}{$rep}[1]{sep_arch};
707            my $dir = "$topdir/$cd/$path";
708            log_("getGroupReps: virtual disc $cd path $path (num $rep_nb) in $dir\n", $config->{verbose} , $config->{LOG},3);
709            if ($discsFiles->[$cd]{$rep}{$listnumber}) {
710                $check_discsFiles->($cd,$rep,$listnumber)
711            } elsif (-d $dir) {
712                $check_dir->($dir,$listnumber,$rep_nb, 'rpm',$testarch, $sep_arch);
713            } else {
714                log_("ERROR getGroupReps: could not find virtual disc $cd path $path\n", $config->{verbose} , $config->{LOG});
715                next
716            }
717            $rep_nb++
718        }
719        foreach my $cd (keys %{$config->{list}[$listnumber]{disc}}) {
720            foreach my $rep (keys %{$config->{list}[$listnumber]{disc}{$cd}}) {
721                if ($config->{list}[$listnumber]{disc}{$cd}{$rep}{done}) {
722                    $check_discsFiles->($cd, $rep, $listnumber)
723                }
724                $rep_nb++
725            }
726        }
727    }
728}
729
730# TODO at present clone only do full copy
731sub prepare_cloned_discs {
732    my ($group, $done, $config, $lists) = @_;
733    my $g;
734    foreach my $cd (keys %$lists) {
735        my $loc_conf = $config->{disc}[$cd]{function};
736        if ($loc_conf->{data}{clone}) {
737            log_("prepare_cloned_discs: disc $cd\n", $config->{verbose}, $config->{LOG},2);
738            # nothing to do, cp -r
739            #if (@{$loc_conf->{list}} == 1 && !$loc_conf->{list}[0][1]{to_del}) {
740            #
741            $loc_conf->{data}{clone}[0][1]{full_copy} = 1;
742            $group->[$g]{disc_impacted}{$cd} = 1;
743            $group->[$g]{discdeps}{$cd} = {};
744            log_("prepare_cloned_discs: setting group $g as master of disc $cd\n", $config->{verbose}, $config->{LOG}, 4);
745            $config->{disc}[$cd]{group_master} = int $g;
746            push @{$group->[$g]{master_of_disc}}, $cd;
747           
748            foreach (@{$loc_conf->{data}{clone}}) {
749                $group->[$g]{disc_prereq}{$_->[1]{disc}}++
750            }
751            $done->{$cd} = {};
752            $g++
753            #   next
754            #}
755        }
756    }
757    $g
758}
759
760sub find_cpu {
761    my $cpu;
762    open my $CPU, "/proc/cpuinfo"; 
763    while (<$CPU>) { /processor/ and $cpu++ };
764    $cpu
765}
766
767sub make_io_group {
768    my ($class, $iog, $config, $log, $lists, $discs_files, $cdsize, $size, $graft, $sort, $inode, $done_deps, $iotask, $metagroups, $mkisos) = @_;
769    my $cds = $iog->[1];
770    my $groups = $iog->[0];
771    print $log "Group: $iog ";
772    print $log "(@$cds -- $groups)\n";
773    # FIXME ordering metagroups can lead to empty groups with the -l option
774    $groups or next;
775
776    my (@buildlist, @rpmlist, @needed);
777    my @groupok;
778
779    #print_conflict_matrix($groups);
780    for (my $i; $i < @$groups; $i++) {
781        log_("Get already built discs lists\n", $config->{verbose}, $log, 3);
782        $groups->[$i]{done} = { rep => {}, list => {} };
783        $class->{disc}->getBuiltDiscs($lists, $groups->[$i], $discs_files, $size, $cdsize);
784
785        log_("GROUP $i\n", $config->{verbose}, $log, 5);
786        getGroupReps($config, $groups->[$i], $discs_files);
787
788        log_("genDeps\n", $config->{verbose}, $log, 3);
789        if (! $done_deps->{$groups->[$i]{depsrep}} && ref $groups->[$i]{rep_pkg}{rpm}) {
790            $done_deps->{$groups->[$i]{depsrep}} = genDeps("$config->{tmp}/$config->{name}/$groups->[$i]{depsrep}", $groups->[$i]{rep_pkg}{rpm}, $config->{deps}, $config->{verbose}, $config->{tmp}) or do { log_("ERROR: genDeps failed\n", $config->{verbose}, $log); return 0 }
791        }
792        $groups->[$i]{urpm} = $done_deps->{$groups->[$i]{depsrep}};
793        log_("getSize\n", $config->{verbose}, $log, 3);
794        my $redeps = getSize($groups->[$i],$config, $config->{verbose}) or do { log_("ERROR: getSize failed\n", $config->{verbose}, $log); return 0 };
795
796        $class->{disc}->guessHdlistSize($groups->[$i], $size, $cdsize, $lists, $discs_files);
797
798        # put in getList to handle package nodeps flag
799        #$groups->[$i]{revdeps} = $class->{list}->reverseDepslist($groups->[$i]);
800
801        ($groups->[$i]{filelist}, my $norpmsrate) = $class->{list}->getList($groups->[$i], $discs_files);
802
803        if ($groups->[$i]{rpmsratepath}) { 
804            my $struct_v = $config->{struct_version};
805            my $media_info = $config->{struct}{$struct_v}{media_info};
806            my $outputdir = "$config->{tmp}/build/$config->{name}/$groups->[$i]{installDisc}/$media_info/";
807            -d $outputdir or mkpath $outputdir;
808            my $output = "$outputdir/rpmsrate";
809            # FIXME currently the rpmsrate is updated at group creation,
810            # maybe need to be done again at disc finalizing stage only to include
811            # present packages. However it is harmfull to have packages into the rpmsrate not
812            # present on the discs.
813            log_("cleanrpmsrate $groups->[$i]{rpmsratepath} -> $output\n", $config->{verbose}, $log, 3);
814            $groups->[$i]{rpmsrate} = cleanrpmsrate($groups->[$i]{rpmsratepath}, $output, $norpmsrate, $groups->[$i]{rep_pkg}{rpm}, $groups->[$i]{urpm}) or log_("ERROR: cleanrpmsrate failed\n", $config->{verbose}, $log);
815            $groups->[$i]{options}{rpmsrate} = $output;
816        }
817
818        log_("build_list group $i\n", $config->{verbose}, $log, 3);
819        ($rpmlist[$i], $groups->[$i]{revdeps}) = $class->{list}->build_list($groups->[$i]) or return 0;
820
821        $class->{list}->scoreList($groups->[$i]) or return 0;
822        $class->{list}->autodeps($groups->[$i], $rpmlist[$i]);
823
824        foreach my $l (keys %{$rpmlist[$i]}) { 
825            log_("make_io_group: processing rpmlist $i list $l\n", $config->{verbose}, $log, 3);
826            my (@force, @need, @superforce, @limit, @b);
827            foreach (keys %{$rpmlist[$i]{$l}}) {
828                # in case of multiple entries
829                $groups->[$i]{limit}{$_} = 0;
830                if (!$_) {
831                    log_("ERROR: empty rpmlist key ($rpmlist[$i]{$l}{$_}) KEYS " .  keys(%{$rpmlist[$i]{$l}{$_}}) . " \n", $config->{verbose}, $log);
832                    next
833                }
834                my $elt = [ $_, $rpmlist[$i]{$l}{$_}, $groups->[$i]{scorelist}{$_} ];
835                if (!$config->{nodeps} && !$groups->[$i]{options}{nodeps} && !$groups->[$i]{nodeps}{$l} && /basesystem/) { 
836                    $elt->[1]{needed} = 1;
837                    push @superforce, $elt
838                } elsif ($rpmlist[$i]{$l}{$_}{force}) { 
839                    #$elt->[1]{needed} = 1;
840                    push @force, $elt
841                } elsif ($rpmlist[$i]{$l}{$_}{limit}) {
842                    $groups->[$i]{limit}{$_} = 1;
843                    push @limit, $elt
844                } else { 
845                    push @b, $elt
846                }
847                my $n = $rpmlist[$i]{$l}{$_}{needed};
848                push @{$needed[$i]{$l}{alap}[$n]}, $elt if $n;
849                # used to check which packages has beed rejected
850                push @{$groups->[$i]{buildlist}}, $_
851            }
852            $buildlist[$i]{$l} = [ sort { $a->[2] <=> $b->[2] } @b ];
853            unshift @{$buildlist[$i]{$l}}, sort { $a->[2] <=> $b->[2] } @limit;
854            # needed must not be put first.
855            #push @{$buildlist[$i]{$l}}, sort { $a->[2] <=> $b->[2] } @need;
856            push @{$buildlist[$i]{$l}}, sort { $a->[2] <=> $b->[2] } @force;
857            push @{$buildlist[$i]{$l}}, sort { $a->[2] <=> $b->[2] } @superforce
858        }
859    }
860
861    # FIXME it must have a cleaner manner to keep buildlist and do not have
862    # to copy it.
863    my @cb;
864    for (my $i = 0; $i < @buildlist; $i++) { 
865        foreach my $l (keys %{$buildlist[$i]}) { 
866            $cb[$i]{$l} = [];
867            foreach (@{$buildlist[$i]{$l}}) { 
868                log_("MakeWithGroups: copying buildlist group $i list $l package $_->[0] score $_->[2] options " . join(' ', %{$_->[1]}) . "\n", $config->{verbose}, $log, 4); 
869                push @{$cb[$i]{$l}}, $_
870            }
871        }
872    }
873
874    my $diff = { data => [], idx => [] };
875    my $rejected;
876    my $n=1;
877    my $shell;
878    my $shell_ok;
879    if ($config->{shell}) {
880        $shell = new Mkcd::Shell("mkcd version $config->{version}");
881        $shell_ok = $shell->prompt({ size => $size, discs_files => $discs_files, config => $config, metagroups => $metagroups });
882    } 
883    $rejected = $class->{build}->buildDiscs($groups, \@cb, \@rpmlist, \@groupok, $size, $cdsize, $lists,$cds, \@needed,$diff,$n) if @cb;
884    my $logi;
885    my ($cd, $diff) = $class->{build}->processDiff($groups,$diff, $discs_files);
886    my $ok;
887    # discs_files contains all the rpms, cd contains only the diff
888
889    if ($config->{shell}) {
890        $shell_ok = $shell->prompt({ size => $size, discs_files => $discs_files, config => $config, metagroups => $metagroups });
891    }
892    log_("make_io_group: $cd->[2]\n", $config->{verbose}, $log, 3);
893   
894    $class->{disc}->makeDiscs(1, $lists, $cds, $size, $mkisos, $discs_files, $graft, $sort, $inode, $cd) or return 0;
895    $ok = $class->{disc}->checkSize($n, $size, $cdsize, $cds, $rejected);
896    #log_("make_io_group: disc_building_tries $config->{disc_building_tries}\n",1,$log);
897    $ok = 1 if $config->{disc_building_tries} < 2;
898    while (!$ok || $shell_ok) {
899        $n++;
900        log_("make_io_group: trying to adjust disc size, try $n\n", $config->{verbose}, $log, 3);
901        $ok = 1;
902        my @cb;
903        for (my $i; $i < @buildlist; $i++) { 
904            foreach my $l (keys %{$buildlist[$i]}) { 
905                $cb[$i]{$l} = [];
906                foreach (@{$buildlist[$i]{$l}}) {
907                    push @{$cb[$i]{$l}}, $_ if $groups->[$i]{rejected}{$_->[0]}{$l}
908                }
909            }
910        }
911        if ($config->{shell}) {
912            $shell_ok = $shell->prompt({ size => $size, discs_files => $discs_files });
913        }
914        $rejected = $class->{build}->buildDiscs($groups, \@cb, \@rpmlist, \@groupok, $size, $cdsize, $lists, $cds, \@needed, $diff, $n) if @cb;
915        my ($cd, $diff) = $class->{build}->processDiff($groups, $diff, $discs_files);
916        $class->{disc}->makeDiscs($n, $lists, $cds, $size, $mkisos, $discs_files, $graft, $sort, $inode, $cd) or return 0;
917        $ok = $class->{disc}->checkSize($n, $size, $cdsize, $cds, $rejected);
918        !$ok and log_("ERROR: one or more disc are too big or too small, trying to correct\n", $config->{verbose}, $log, 2);
919        if ($n >= $config->{disc_building_tries}) { 
920            log_("ERROR: could not manage to build discs of correct size, exiting\n", $config->{verbose}, $log); 
921            last 
922        }
923    }
924    # finally really build the ISOs
925    if ($config->{nofork}) { 
926        $class->{disc}->makeDiscs(-1, $lists, $cds, $size, $mkisos, $discs_files, $graft, $sort, $inode, $cd);
927    } else {
928        # FIXME This algo is not correct, it happens that some IO tasks are still parallelized
929        my $pid = fork;
930        $pid and log_("make_io_group: fork to PID $pid to build ISO files\n", $config->{verbose}, $log, 1); 
931        if (!$pid) {
932            while (@$iotask) {
933                my $p = pop @$iotask;
934                log_("make_io_group: waiting for IOtask PID $p to finish\n", $config->{verbose}, $log, 2); 
935                waitpid $p, 0
936            }
937            $class->{disc}->makeDiscs(-1, $lists, $cds, $size, $mkisos, $discs_files, $graft, $sort, $inode, $cd);
938            exit
939        } else {
940            push @$iotask, $pid
941        }
942    }
943    for (my $i; $i < @$groups; $i++) {
944        foreach my $list (keys %{$groups->[$i]{list}}) {
945            foreach my $type (keys %{$groups->[$i]{list}{$list}}) {
946                foreach (@{$groups->[$i]{list}{$list}{$type}}) {
947                    $config->{list}[$list]{disc}{$_->[0]}{$_->[1]}{done} = 1
948                }
949            }
950        }       
951    }
952}
953
954sub makeWithGroups {
955    my ($class, $lists, $acds) = @_;
956    my $config = $class->{config};
957    my $log = $config->{LOG};
958    my $metagroups = orderGroups($config, getGroups($config, $lists), $lists, $acds);
959
960    my @discsFiles;
961    my (@cdsize, %size, %graft, %sort, %done_deps, %inode, @iotask, @mkisos);
962    for (my $i; $i < @{$config->{disc}}; $i++) { 
963        $cdsize[$i] = $config->{disc}[$i]{size}; 
964        $size{optimize_space}{disc}{$i} = $cdsize[$i]
965    }
966    foreach my $iog (@$metagroups) {
967        foreach (@$iog) {
968            ref $_->[1] or next;
969            log_("makeWithGroups: Group listing $_ (@{$_->[1]} -- $_->[0])\n", $config->{verbose}, $config->{LOG}, 3);
970            my $cds = $_->[1];
971            # Do not make first CDs in io groups to keep inter io groups alone directories safe.
972            $class->{disc}->makeDiscs(0, $lists, $cds, \%size, \@mkisos, \@discsFiles, \%graft, \%sort, \%inode);
973        }
974    }
975    $config->{cpu} = find_cpu() if !$config->{cpu};
976    log_("makeWithGroups: will try to use $config->{cpu} CPUs\n", $config->{verbose}, $config->{LOG}, 3);
977   
978    foreach my $g (@$metagroups) {
979        foreach my $iog (@$g) {
980            ref $iog->[1] or next;
981            make_io_group($class, $iog, $config, $log, $lists, \@discsFiles, \@cdsize, \%size, \%graft, \%sort, \%inode, \%done_deps, \@iotask, $metagroups, \@mkisos);
982        }
983    }
984    printDiscsFile($config, \@discsFiles, $config->{print}, $metagroups);
985    $config->{printscript} and printBatchFile($config, \@discsFiles, $config->{printscript});
986    foreach my $p (@iotask) {
987        waitpid $p, 0
988    }   
989    print "\n";
990    1
991}
992
9931
994
995#
996# Changelog
997#
998# 2002 02 21
999# add maxlistmaxrep value to group
1000#
1001# 2002 03 03
1002# change size to an hash that contains disc size and rep size
1003#
1004# 2002 03 09
1005# make group{discrep} and hash not to have loop in disc dependencies when there are multiple repository on one CD
1006#
1007# 2002 03 14
1008# BIG change of group source handling
1009#
1010# 2002 03 15
1011# use new source handling
1012#
1013# 2002 03 23
1014# change getAlone to be able to build generic CDs without installation
1015#
1016# 2002 06 16   
1017# add conflict in group
1018#
1019# 2002 08 30
1020# change reps structure, add pkg and pkg_rep in group
1021#
1022# 2004 05 28
1023# add IO group to be able to separate IO tasks from CPU tasks
Note: See TracBrowser for help on using the repository browser.