source: soft/build_system/build_system/mkcd/tags/Corpo_2_1_1/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: 14.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);
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}[1]{reploc}")
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                my $tmphdlist = "$class->{config}{tmp}/.mkcd_build_hdlist";
154                foreach (@{list_hdlist([$opt->{hdlist}], $config->{verbose}, 1, $tmphdlist)}) {
155                    log_("getBuiltDiscs: adding $_\n", $config->{verbose}, $config->{LOG},6);
156                    $discsFiles->[$cd]{$rep}{$l}{$_} = ''
157                }
158            } else { 
159                my $dir = "$class->{config}{topdir}/build/$class->{config}{name}/$cd/$class->{config}{disc}[$cd]{function}{data}{dir}{$rep}[1]{reploc}";
160                #
161                # FIXME maybe need to unshift instead of push
162                #
163                $repopt->{source} ? push(@{$class->{config}{list}[$l]{packages}[0]{srpm}}, $dir) : push(@{$class->{config}{list}[$l]{packages}[0]{rpm}}, $dir);
164                log_("getBuiltDiscs: get files from $dir\n", $config->{verbose}, $config->{LOG},2);
165                opendir my $A, $dir;
166                foreach (readdir $A) {
167                    /(.*)\.rpm/ or next;
168                    # FIXME need to check if it is well placed in getList function
169                    # $group->{done}{$rpm} = $group->{orderedrep}{"$cd/$rep"};
170                    $discsFiles->[$cd]{$rep}{$l}{$1} = $dir
171                }
172            }
173        }
174    }
175    1
176}
177
178sub write_graft {
179    my ($graft, $file, $exclude) = @_;
180    log_("write_graft: $file ($graft)\n", $config->{verbose}, $config->{LOG},2); 
181    local *A; open A, ">$file";
182    local *B; open B, ">$exclude";
183    foreach my $d (sort keys %$graft) {
184        if (ref $graft->{$d}) {
185            map { print A "$d=$_\n" } keys %{$graft->{$d}}
186        } elsif ($graft->{$d} == 3) {
187            print B "$d\n"
188        }
189    }
190}
191
192sub graft_to_md5 {
193    my ($graft, $dir, $serial) = @_;
194    my $mdfile = ".$serial.md5";
195    log_("graft_to_md5: $serial -> $dir/$mdfile ($graft)\n", $config->{verbose}, $config->{LOG},2); 
196    local *A; open A, ">$dir/$mdfile";
197    my %ignore;
198    my @to_check;
199    $graft->{$mdfile}{"$dir/$mdfile"} = 0;
200    foreach my $f (keys %$graft) { 
201        if (ref $graft->{$f}) { 
202            foreach (keys %{$graft->{$f}}) {
203                my ($file) = m,/([^/]+)$,;
204                my $dest = $f =~ m,/$, ? "/$f/$file" : "/$f";
205                if ($graft->{$f}{$_}) {
206                    push @to_check, [ $dest, $_ ];
207                } else {
208                    $ignore{$dest} = 1;
209                    print A "$f\n"
210                }
211            }
212        } else {
213            $ignore{$f} = 1;
214            print A "$f\n"
215        }
216    }
217    my $digest = compute_md5(\@to_check, \%ignore);
218    print A "$digest - $serial\n"
219}   
220
221sub makeDiscs {
222    my ($class, $fixed, $lists, $cds, $size, $mkisos, $discsFile, $graft, $inode, $cdfile) = @_;
223    my $dir;
224    my $name = $class->{config}{name};
225    my $topdir = $class->{config}{topdir};
226    my $tmp = "$config->{tmp}/build/$name";
227
228    if (!$class->{config}{nolive}) {
229        $dir = "$topdir/build/$name";
230        -d $dir or mkpath $dir;
231        -d $tmp or mkpath $tmp;
232    } else {
233        $dir = "$config->{tmp}/build/$name";
234        -d $dir or mkpath $dir;
235    }
236    if ($fixed == -1) {
237        buildISO($class->{config},$topdir,$name,$lists,$fixed,$mkisos,$size,$cds,$cdfile,0);
238        return 1
239    }
240    log_("makeDiscs: Discs @$cds topdir $dir\n", $config->{verbose}, $config->{LOG},1);
241    foreach my $i (@$cds) {
242        $lists->{$i} > 1 or next;
243        my $cd = $class->{config}{disc}[$i];
244        $graft->{$i} ||= {};
245        if ($fixed > 1 && $cdfile->[$i] == 0) {
246            log_("makeDiscs: nothing to do for disc $i\n", $config->{verbose}, $config->{LOG},2);
247            next
248        }
249        if (!$fixed) {
250            log_("makeDisc: Fixed part of disc $i\n", $config->{verbose}, $config->{LOG},3);
251            if ($class->{config}{nolive}) {
252                log_("makeDisc: removing $dir/$i.list\n", $config->{verbose}, $config->{LOG},3);
253                -f "$dir/$i.list" and unlink "$dir/$i.list";
254                log_("makeDisc: removing $dir/$i\n", $config->{verbose}, $config->{LOG},3);
255                rmtree "$dir/$i";
256                mkdir "$dir/$i"
257            } else {
258                -d "$tmp/$i" or mkpath "$tmp/$i";
259                foreach ("$topdir/build/$name/$i", "$topdir/build/$name/first/$i") { rmtree $_; mkdir $_ }
260            }
261        } else { log_("Finalizing disc $i\n", $config->{verbose}, $config->{LOG},2) }
262        my $sz;
263        if (ref $cd->{steps}) {
264            for (my $j; $j < @{$cd->{steps}}; $j++) {
265                my $name = $cd->{steps}[$j][0];
266                log_("makeDiscs: $name ($fixed)\n", $config->{verbose}, $config->{LOG},2);
267                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) }
268                else { log_("ERROR: unrecognized function name $name\n",0, $config->{LOG}) }
269                log_("SIZE ($name) $sz\n", $config->{verbose}, $config->{LOG},4);
270            }
271        } else {
272            die "FATAL make_discs: impossible to find definition of disc $i, problem in config file ?"
273        }
274        if ($class->{config}{nolive}) {
275            log_("SIZE $size->{disc}[$i] + $sz\n", $config->{verbose}, $config->{LOG},4);
276            $size->{disc}[$i] += $sz
277        } else {
278            $size->{disc}[$i] = du("$dir/$i") + $sz
279        }
280        log_("disc $i ($dir/$i) size: $size->{disc}[$i] ($sz)\n", $config->{verbose}, $config->{LOG},3);
281        my $mkisoopt = $class->{config}{mkisoopt};
282        if ($fixed) {
283            my $isodir = $class->{config}{isodir} ? $class->{config}{isodir} : "$topdir/iso/$name";
284            $graft->{$i}{".rr_moved"} = 0;
285            my $publisher = $config->{Publisher} || $config->{disc}[$i]{Publisher};
286            my $commkiso = qq(-A "$cd->{appname}" -P "$publisher" -volset "$cd->{serial}" -V "$cd->{label}" -o $isodir/$i-$name.iso);
287            if ($config->{nolive}) {
288                # include_md5 replaces md5 per files
289                #graft_to_md5($graft->{$i},"$dir/$i",$cd->{serial});
290                write_graft($graft->{$i}, "$dir/$i.list", "$dir/$i-exclude.list");
291                #write_sort($sort->{$i}, "$dir/$i.sort");
292                #$mkisos->[$i] = "$mkisoopt -graft-points -path-list $dir/$i.list -sort $dir/$i.sort " . (-f "$dir/$i-exclude.list" ? "-exclude-list $dir/$i-exclude.list" : "") . " $commkiso $mkisos->[$i]" if $fixed == 1
293                $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
294            } else {
295                $graft->{$i}{"/"}{"$dir/$i/"} = 1;
296                # include_md5 replaces md5 per files
297                #graft_to_md5($graft->{$i},"$dir/$i",$cd->{serial});
298                if ($mkisos->[$i]) {
299                    $mkisos->[$i] = "$mkisoopt $commkiso $mkisos->[$i] $dir/$i" if $fixed == 1
300                } else {
301                    $mkisos->[$i] = qq($mkisoopt $commkiso "$dir/$i") if $fixed == 1
302                }
303            }
304        }
305    }
306    !$fixed and return 1;
307    buildISO($class->{config},$topdir,$name,$lists,$fixed,$mkisos,$size,$cds,$cdfile,1);
308    1
309}
310
311sub buildISO {
312    my ($config, $topdir, $name, $lists, $fixed, $mkisos, $size, $cds, $cdfile, $checksize) = @_;
313    my $log = $config->{LOG};
314    -d "$topdir/iso/$name" or mkpath "$topdir/iso/$name";
315    foreach my $i (@$cds) {
316        $lists->{$i} > 1 or next;
317        if ($fixed > 1 && $cdfile->[$i] == 0) {
318            log_("makeDiscs: nothing to do for disc $i\n",0, $config->{LOG});
319            next
320        }
321        my $cmd = $checksize ? "mkisofs -print-size -quiet $mkisos->[$i]" : "mkisofs $mkisos->[$i]";
322        if ($checksize) {
323            $size->{disc}[$i] = 1024 * 2 * `$cmd`;
324            log_("MKISOFS disc $i size $size->{disc}[$i]\n", $config->{verbose}, $config->{LOG},1);
325        } elsif (!$config->{noiso}) {
326            $cmd .= " > /dev/null" if !$config->{verbose};
327            my $err = system $cmd;
328            log_("disc $i: $cmd\n", 1, $config->{LOG});
329            if ($err) {
330                log_("ERROR: disc $i $cmd failed ($!)\n", 1, $config->{LOG});
331                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:
332                $cmd\n "
333            }
334            if (!$checksize) {
335                include_md5("$topdir/iso/$name/$i-$name.iso",1);
336                $size->{disc}[$i] = du("$topdir/iso/$name/$i-$name.iso")
337            }
338        }
339    }
340}
341
342sub checkSize {
343    my ($class, $n, $size, $cdsize, $cds, $rejected) = @_;
344    my $ok = 1;
345    foreach my $i (@$cds) {
346        if ($size->{save}{disc}[$i] != $size->{disc}[$i]) {
347            $size->{save}{disc}[$i] = $size->{disc}[$i];
348            $ok = 0
349        }
350    }
351    if ($ok) {
352        log_("checkSize: disc sizes has not changed, exiting\n",1, $config->{LOG});
353        return 1
354    }
355    my $ok = 1;
356    foreach my $i (@$cds) {
357        $size->{disc}[$i] or next;
358        my $origcdsize = $class->{config}{disc}[$i]{size};
359        log_("checkSize: disc $i size $size->{disc}[$i] ($origcdsize)\n",1, $config->{LOG});
360        my $d = $size->{disc}[$i] - $origcdsize;
361        if ($size->{disc}[$i] > $origcdsize) {
362            if ($d > $origcdsize/10) {
363                log_("ERROR: an error must have happen, disc $i is far too big ($size->{disc}[$i] > $origcdsize), ignoring\n",1, $config->{LOG});
364                next
365            }
366            if ($d > 0 && $d > ($origcdsize*$n)/1000) {
367                $ok = 0;
368                $cdsize->[$i] -= $d;
369                log_("ERROR: disc $i is too big ($size->{disc}[$i] > $origcdsize ($d)\n",1, $config->{LOG})
370            } else {
371                $cdsize->[$i] = $size->{disc}[$i]+1;       
372            }
373        } else {
374            if ($d < 0 && $rejected) {
375                $d = -$d;
376                # FIXME heuristic: do not change CD size if diff is greater than 10% of the original CD size
377                if ($d > $origcdsize/10) {
378                    log_("ERROR: an error must have happen, disc $i is far too small ($size->{disc}[$i] << $origcdsize), ignoring\n",1, $config->{LOG});
379                    next
380                }
381                if ($d > ($origcdsize*$n)/300) {
382                    $ok = 0;
383                    #$cdsize->[$i] += $d/2;
384                    log_("ERROR: disc $i is too small ($size->{disc}[$i] < $origcdsize, ($d)\n",1, $config->{LOG})
385                }
386            }
387        }
388        log_("checkSize: new disc $i size $cdsize->[$i]\n",1, $config->{LOG});
389    }
390    return $ok
391}
392
3931
394
395# Changelog
396#
397# 2002 05 22
398# fix a pb in graft_to_md5 that made dest incomplete when dest is a directory
399#
400# 2002 08 25
401# improve checkSize to better work with optimize_space
Note: See TracBrowser for help on using the repository browser.