source: soft/build_system/build_system/mkcd/tags/V3_3_6_1mdk/pm/Mkcd/Disc.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: 13.1 KB
Line 
1package Mkcd::Disc;
2
3my $VERSION = '0.1.1';
4
5use strict;
6use File::Path;
7use Mkcd::Functions;
8use Mkcd::Tools qw(du compute_md5 log_ include_md5);
9
10=head1 NAME
11
12Disc - mkcd disc functions
13
14=head1 SYNOPSYS
15
16    require Mkcd::Disc;
17
18=head1 DESCRIPTION
19
20C<Mkcd::Disc> include the mkcd disc handling subroutines.
21
22=head1 SEE ALSO
23
24mkcd
25
26=head1 COPYRIGHT
27
28Copyright (C) 2000,2001 MandrakeSoft <warly@mandrakesoft.com>
29
30This program is free software; you can redistribute it and/or modify
31it under the terms of the GNU General Public License as published by
32the Free Software Foundation; either version 2, or (at your option)
33any later version.
34
35This program is distributed in the hope that it will be useful,
36but WITHOUT ANY WARRANTY; without even the implied warranty of
37MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38GNU General Public License for more details.
39
40You should have received a copy of the GNU General Public License
41along with this program; if not, write to the Free Software
42Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43
44=cut
45
46my $config;
47
48sub new {
49    my ($class, $conf) = @_;
50    $config = $conf;
51    bless {
52           config       => $conf,
53           functions    => new Mkcd::Functions($config)
54          }, $class;
55}
56
57# FIXME must add space for synthesis, however they are negligeable compared to hdlist. Only
58# a pb with very small CD.
59
60sub guessHdlistSize {
61    my ($class,$group,$size,$cdsize,$lists, $discsFiles) = @_;
62    my $FACTOR = 130;
63    my $SynFACTOR = 90;
64    my $msg;
65    my $depsRep = "$config->{tmp}/$class->{config}{name}/$group->{depsrep}";
66    $msg = "guessHdlistSize: depsRep $depsRep\n";
67    # FIXME heuristic for hdlist size on installation disc, (RPMS size / $FACTOR) per discs
68    # need genDeps to write hdlist/synthesis, overkill
69    my $depsSize = du("$depsRep");
70    my $instdisc = $group->{installDisc};
71    my $sz;
72    my (@notdone, @rem_size);
73    push @rem_size, @$cdsize;
74    foreach my $list (keys %{$group->{list}}) {
75        if ($config->{list}[$list]{auto}) {
76            if ($config->{list}[$list]{cd}) {
77                my $tsize = ($config->{discsize}/$FACTOR) * $config->{list}[$list]{cd}; 
78                $sz += $tsize < $depsSize ? $tsize : $depsSize;
79            } else {
80                $sz += $depsSize
81            }
82        } else {
83            my $ok;
84            my $listsize = $group->{listsize}{$list}{rpm};
85            foreach my $rd (@{$group->{list}{$list}{rpm}}) {
86                my ($cdrep,undef,undef, $opt) = @$rd;
87                if ($opt->{nodeps}) { $ok = 1; next }
88                if ($lists->{$cdrep}) {
89                    if ($listsize > $cdsize->[$cdrep]) {
90                        $sz += $rem_size[$cdrep] / $FACTOR;
91                        $listsize -= $rem_size[$cdrep];
92                        $rem_size[$cdrep] = 0
93                    } else {
94                        $sz += $listsize / $FACTOR;
95                        $rem_size[$cdrep] -= $listsize;
96                        last
97                    }
98                }
99            }
100            $ok and push @notdone, $list       
101        }
102    }
103    $msg .= "guessHdlistSize: reserving ";
104    if ($depsSize < $sz && $depsSize > 10000) { 
105        $msg .= "$depsSize";
106        $size->{disc}[$instdisc] += int $depsSize;
107        if ($config->{disc}[$instdisc]{function}{data}{installation}[1]{synthesis}) { $size->{disc}[$instdisc] += int($depsSize / $SynFACTOR) }
108    } elsif ($sz > 10000) { 
109        $msg .= "$sz"; 
110        $size->{disc}[$instdisc] += int $sz;
111        if ($config->{disc}[$instdisc]{function}{data}{installation}[1]{synthesis}) { $size->{disc}[$instdisc] += int($sz / $SynFACTOR) }
112    } else {
113        log_("ERROR guessHdlistSize: possibly wrong estimated dependencies file size\n", $config->{verbose}, $config->{LOG},2) 
114    }
115    $msg .= " (new size $size->{disc}[$instdisc]) on disc $instdisc ($depsSize/$sz) for dependencies files\n";
116    log_($msg, $config->{verbose}, $config->{LOG},2);
117    @notdone or return 1;
118    $sz = 0;
119    foreach my $list (@notdone) {
120        foreach my $rd (@{$group->{list}{$list}{rpm}}) {
121            my ($cd,$rep,$repopt, $opt) = @$rd;
122            if ($lists->{$cd} == 1) {
123                $sz += du("$class-{config}{topdir}/build/$class->{config}{name}/$cd/$class->{config}{disc}[$cd]{function}{data}{dir}{$rep}")
124            } elsif ($lists->{$cd} == 2) {
125                foreach my $rpm (keys %{$discsFiles->[$cd]{$rep}{$list}}) {
126                    $sz += du("$discsFiles->[$cd]{$rep}{$list}{$rpm}/$rpm.rpm")
127                }
128            }
129        }
130    }
131    $sz /= $FACTOR;
132    $msg = "guessHdlistSize: reserving $sz";
133    $size->{disc}[$instdisc] += $sz;
134    if ($config->{disc}[$instdisc]{function}{data}{installation}[1]{synthesis}) { $size->{disc}[$instdisc] += $sz / $SynFACTOR }
135    $msg .= " (new size $size->{disc}[$instdisc]) on disc $instdisc ($sz) for extra dependencies files\n";
136    log_($msg, $config->{verbose}, $config->{LOG},1)
137}               
138
139sub getBuiltDiscs {
140    my ($class, $lists, $group, $discsFiles) = @_;
141    foreach my $l (keys %{$group->{list}}) {
142        my @rpmlist;
143        ref $group->{list}{$l}{rpm} and push @rpmlist, @{$group->{list}{$l}{rpm}};
144        ref $group->{list}{$l}{srpm} and push @rpmlist, @{$group->{list}{$l}{srpm}};
145        for (my $i; $i < @rpmlist; $i++) {
146            my ($cd,$rep, $repopt) = @{$rpmlist[$i]};
147            $lists->{$cd} == 1 or next;
148            my $dir = "$class->{config}{topdir}/build/$class->{config}{name}/$cd/$class->{config}{disc}[$cd]{function}{data}{dir}{$rep}";
149            #
150            # FIXME maybe need to unshift instead of push
151            #
152            $repopt->{source} or push @{$class->{config}{list}[$l]{packages}}, [$dir];
153            $class->{config}{list}[$l]{disc}{$cd}{$rep}{done} = 1;
154            log_("getBuiltDiscs: get files from $dir\n",0, $config->{LOG},2);
155            local *A; opendir A,$dir;
156            foreach (readdir A) {
157                /(.*)\.rpm/ or next;
158                # FIXME need to check if it is well placed in getList function
159                # $group->{done}{$rpm} = $group->{orderedrep}{"$cd/$rep"};
160                $discsFiles->[$cd]{$rep}{$l}{$1} = $dir
161            }
162        }
163    }
164    1
165}
166
167sub write_graft {
168    my ($graft, $file, $exclude) = @_;
169    log_("write_graft: $file ($graft)\n",$config->{verbose}, $config->{LOG},2); 
170    local *A; open A, ">$file";
171    local *B; open B, ">$exclude";
172    foreach my $d (sort keys %$graft) {
173        if (ref $graft->{$d}) {
174            map { print A "$d=$_\n" } keys %{$graft->{$d}}
175        } elsif ($graft->{$d} == 3) {
176            print B "$d\n"
177        }
178    }
179}
180
181sub graft_to_md5 {
182    my ($graft,$dir, $serial) = @_;
183    my $mdfile = ".$serial.md5";
184    log_("graft_to_md5: $serial -> $dir/$mdfile ($graft)\n",$config->{verbose}, $config->{LOG},2); 
185    local *A; open A, ">$dir/$mdfile";
186    my %ignore;
187    my @to_check;
188    $graft->{$mdfile}{"$dir/$mdfile"} = 0;
189    foreach my $f (keys %$graft) { 
190        if (ref $graft->{$f}) { 
191            foreach (keys %{$graft->{$f}}) {
192                my ($file) = /\/([^\/]+)$/;
193                my $dest = $f =~ /\/$/ ? "/$f/$file" : "/$f";
194                if ($graft->{$f}{$_}) { 
195                    push @to_check, [ $dest, $_ ];
196                } else { 
197                    $ignore{$dest} = 1;
198                    print A "$f\n" 
199                }
200            }
201        } else { 
202            $ignore{$f} = 1;
203            print A "$f\n" 
204        }
205    }
206    my $digest = compute_md5(\@to_check, \%ignore);
207    print A "$digest - $serial\n"
208}   
209
210sub makeDiscs {
211    my ($class,$fixed,$lists,$cds,$size,$mkisos,$discsFile,$graft,$inode, $cdfile) = @_;
212    my $dir;
213    my $name = $class->{config}{name};
214    my $topdir = $class->{config}{topdir};
215    my $tmp = "$config->{tmp}/build/$name";
216
217    if (!$class->{config}{nolive}) {
218        $dir = "$topdir/build/$name";
219        -d $dir or mkpath "$dir";
220        -d $tmp or mkpath $tmp;
221    } else {
222        $dir = "$config->{tmp}/build/$name";
223        -d "$dir" or mkpath "$dir";
224    }
225    if ($fixed == -1) {
226        buildISO($class->{config},$topdir,$name,$lists,$fixed,$mkisos,$size,$cds,$cdfile,0);
227        return 1
228    }
229    log_("makeDiscs: Discs @$cds topdir $dir\n",$config->{verbose}, $config->{LOG},1);
230    foreach my $i (@$cds) {
231        $lists->{$i} > 1 or next;
232        my $cd = $class->{config}{disc}[$i];
233        $graft->{$i} ||= {};
234        if ($fixed > 1 && $cdfile->[$i] == 0) { 
235            log_("makeDiscs: nothing to do for disc $i\n",$config->{verbose}, $config->{LOG},2);
236            next 
237        }
238        if (!$fixed) {
239            log_("makeDisc: Fixed part of disc $i\n",$config->{verbose}, $config->{LOG},3);
240            if ($class->{config}{nolive}) {
241                log_("makeDisc: removing $dir/$i.list\n",$config->{verbose}, $config->{LOG},3);
242                -f "$dir/$i.list" and unlink "$dir/$i.list";
243                log_("makeDisc: removing $dir/$i\n",$config->{verbose}, $config->{LOG},3);
244                rmtree "$dir/$i";
245                mkdir "$dir/$i"
246            } else {
247                -d "$tmp/$i" or mkpath "$tmp/$i";
248                foreach ("$topdir/build/$name/$i", "$topdir/build/$name/first/$i") { rmtree $_; mkdir $_ } 
249            }
250        } else { log_("Finalizing disc $i\n",$config->{verbose}, $config->{LOG},2) }
251        my $sz;
252        if (ref $cd->{steps}){
253            for (my $j; $j < @{$cd->{steps}}; $j++){
254                my $name = $cd->{steps}[$j][0];
255                log_("makeDiscs: $name ($fixed)\n",$config->{verbose}, $config->{LOG},2);
256                if (defined $Mkcd::Functions::{$name}) { $sz += &{$Mkcd::Functions::{$name}}($class->{disc}->{functions},$cd->{steps}[$j],$dir,$fixed,$class->{config}{nolive},$i,$cd,$cdfile,$lists,$mkisos,$graft,$inode->{$i},$discsFile)}
257                else {log_("ERROR: unrecognized function name $name\n",0,$config->{LOG})}
258                log_("SIZE ($name) $sz\n",$config->{verbose},$config->{LOG},4);
259            }
260        } else {
261            die "FATAL make_discs: impossible to find definition of disc $i, problem in config file ?"
262        }
263        if ($class->{config}{nolive}){
264            log_("SIZE $size->{disc}[$i] + $sz\n",$config->{verbose},$config->{LOG},4);
265            $size->{disc}[$i] += $sz
266        }else{
267            $size->{disc}[$i] = du("$dir/$i") + $sz
268        }
269        log_("disc $i ($dir/$i) size: $size->{disc}[$i] ($sz)\n",$config->{verbose},$config->{LOG},3);
270        my $mkisoopt = $class->{config}{mkisoopt};
271        if ($fixed) {
272            my $isodir = $class->{config}{isodir} ? $class->{config}{isodir} : "$topdir/iso/$name";
273            $graft->{$i}{".rr_moved"} = 0;
274            my $publisher = $config->{Publisher} || $config->{disc}[$i]{Publisher};
275            my $commkiso = "-A \"$cd->{appname}\" -P \"$publisher\" -volset \"$cd->{serial}\" -V \"$cd->{label}\" -o $isodir/$i-$name.iso"; 
276            if ($config->{nolive}){
277                # include_md5 replaces md5 per files
278                #graft_to_md5($graft->{$i},"$dir/$i",$cd->{serial});
279                write_graft($graft->{$i},"$dir/$i.list","$dir/$i-exclude.list");
280                $mkisos->[$i] = "$mkisoopt -graft-points -path-list $dir/$i.list " . (-f "$dir/$i-exclude.list" ? "-exclude-list $dir/$i-exclude.list" : ""). " $commkiso $mkisos->[$i]" if ($fixed == 1)
281            }else{
282                $graft->{$i}{"/"}{"$dir/$i/"} = 1;
283                # include_md5 replaces md5 per files
284                #graft_to_md5($graft->{$i},"$dir/$i",$cd->{serial});
285                if ($mkisos->[$i]) { 
286                    $mkisos->[$i] = "$mkisoopt $commkiso $mkisos->[$i] $dir/$i" if ($fixed == 1)
287                } else { 
288                    $mkisos->[$i] = qq|$mkisoopt $commkiso "$dir/$i"| if ($fixed == 1)
289                }
290            }
291        }
292    }
293    !$fixed and return 1;
294    buildISO($class->{config},$topdir,$name,$lists,$fixed,$mkisos,$size,$cds,$cdfile,1);
295    1
296}
297
298sub buildISO {
299    my ($config,$topdir,$name,$lists,$fixed,$mkisos,$size,$cds,$cdfile,$checksize) = @_;
300    -d "$topdir/iso/$name" or mkpath "$topdir/iso/$name"; 
301    foreach my $i (@$cds){
302        $lists->{$i} > 1 or next;
303        if ($fixed > 1 && $cdfile->[$i] == 0){ 
304            log_("makeDiscs: nothing to do for disc $i\n",0,$config->{LOG});
305            next 
306        }
307        my $cmd = $checksize ? "mkisofs -print-size -quiet $mkisos->[$i]" : "mkisofs $mkisos->[$i]";
308        if ($checksize){
309            $size->{disc}[$i] = 1024 * 2 * `$cmd`;
310            log_("MKISOFS disc $i size $size->{disc}[$i]\n",$config->{verbose},$config->{LOG},1);
311        } elsif(!$config->{noiso}) { 
312            $cmd .= " > /dev/null" if !$config->{verbose};
313            my $err = system $cmd;
314            if ($err){ 
315                log_("ERROR: disc $i $cmd failed ($!)\n",1,$config->{LOG});
316                print { $config->{LOG} } "WARNING: a problem may have appear, if ISOs files are not OK and you want to retry to build the ISOs, type the following command:
317                $cmd\n "
318            }
319            if (!$checksize){
320                include_md5("$topdir/iso/$name/$i-$name.iso",1);
321                $size->{disc}[$i] = du("$topdir/iso/$name/$i-$name.iso")
322            }
323        }
324    }
325}
326
327sub checkSize{
328    my ($class, $n,$size,$cdsize,$cds,$rejected) = @_;
329    my $ok = 1;
330    foreach my $i (@$cds) {
331        if ($size->{save}{disc}[$i] != $size->{disc}[$i]){
332            $size->{save}{disc}[$i] = $size->{disc}[$i];
333            $ok = 0
334        }
335    }
336    if ($ok) {
337        log_("checkSize: disc sizes has not changed, exiting\n",1,$config->{LOG});
338        return 1
339    }
340    my $ok = 1;
341    foreach my $i (@$cds) {
342        $size->{disc}[$i] or next;
343        my $origcdsize = $class->{config}{disc}[$i]{size};
344        log_("checkSize: disc $i size $size->{disc}[$i] ($origcdsize)\n",1,$config->{LOG});
345        my $d = ($size->{disc}[$i] - $origcdsize);
346        if ($size->{disc}[$i] > $origcdsize) {
347            if ($d > $origcdsize/10){
348                log_("ERROR: an error must have happen, disc $i is far too big ($size->{disc}[$i] > $origcdsize), ignoring\n",1,$config->{LOG});
349                next
350            }
351            if ($d > 0 && $d > ($origcdsize*$n)/1000) { 
352                $ok = 0;
353                $cdsize->[$i] -= $d;
354                log_("ERROR: disc $i is too big ($size->{disc}[$i] > $origcdsize ($d)\n",1,$config->{LOG})
355            } else {
356                $cdsize->[$i] = $size->{disc}[$i]+1;       
357            }
358        } else {
359            if ($d < 0 && $rejected){
360                $d = -$d;
361                # FIXME heuristic: do not change CD size if diff is greater than 10% of the original CD size
362                if ($d > $origcdsize/10){
363                    log_("ERROR: an error must have happen, disc $i is far too small ($size->{disc}[$i] << $origcdsize), ignoring\n",1,$config->{LOG});
364                    next
365                }
366                if ($d > ($origcdsize*$n)/300) { 
367                    $ok = 0;
368                    #$cdsize->[$i] += $d/2;
369                    log_("ERROR: disc $i is too small ($size->{disc}[$i] < $origcdsize, ($d)\n",1,$config->{LOG}) 
370                }
371            }
372        }
373        log_("checkSize: new disc $i size $cdsize->[$i]\n",1,$config->{LOG});
374    }
375    return $ok
376}
377
3781
379
380# Changelog
381#
382# 2002 05 22
383# fix a pb in graft_to_md5 that made dest incomplete when dest is a directory
384#
385# 2002 08 25
386# improve checkSize to better work with optimize_space
Note: See TracBrowser for help on using the repository browser.