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