source: soft/build_system/build_system/upload/robot/trunk/gendistrib2 @ 1

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

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

File size: 26.1 KB
Line 
1#!/usr/bin/perl
2
3(our $VERSION) = q$Id: gendistrib 38689 2006-07-10 12:03:34Z mandrake $
4        =~ /(\b\d+\b)/;
5
6use strict;
7use Cwd;
8use URPM;
9use URPM::Build;
10use Getopt::Long;
11use MDV::Distribconf::Build;
12use MDV::Packdrakeng;
13use Pod::Usage;
14use MDK::Common qw(all);
15use File::Temp 'mktemp';
16
17my $urpm = new URPM;
18my $tempdir = -d $ENV{TMPDIR} ? $ENV{TMPDIR} : -d "$ENV{HOME}/tmp" ? "$ENV{HOME}/tmp" : "/tmp";
19my $headers_dir = $tempdir . "/.build_hdlist";
20
21sub usage () {
22    pod2usage({ -verbose => 1 });
23    exit 0;
24}
25
26my %urpmfiles;
27
28GetOptions(
29    'blind' => \my $blind,
30    'compss=s' => \$urpmfiles{compss},
31    'depslist=s' => \$urpmfiles{depslist},
32    'destdir=s' => \my $destdir,
33    'fast' => \my $fast,
34    'hdlists=s' => \$urpmfiles{hdlists},
35    'headersdir=s' => \$headers_dir,
36    'help|h' => \&usage,
37    'mediacfg=s' => \$urpmfiles{mediacfg},
38    'nobadrpm' => \my $dontdie,
39    'nochkdep' => \my $nochkdep,
40    'noclean' => \my $noclean,
41    'noemptymedia' => \my $noemptymedia,
42    'nomd5sum' => \my $nomd5sum,
43    'nosynthesis' => \my $nosynthesis,
44    'nomediainfo' => \my $nomediainfo,
45    'provides=s' => \$urpmfiles{provides},
46    'skipmissingdir' => \my $skipmissingdir,
47    's' => \my $nooutput,
48    'v|version' => sub { warn "$0 version $VERSION\n"; exit 0 },
49);
50
51(my @root = grep { $_ } @ARGV) > 0 or usage();
52
53my $distrib = MDV::Distribconf::Build->new($root[0]);
54
55$distrib->loadtree or die "$root[0] does not seem to be a distribution tree\n";
56
57if (defined($urpmfiles{mediacfg})) {
58    $distrib->parse_mediacfg($urpmfiles{mediacfg})
59        or die "Can't read $urpmfiles{mediacfg}\n";
60} elsif (defined($urpmfiles{hdlists})) {
61    $distrib->parse_hdlists($urpmfiles{hdlists})
62        or die "Can't read $urpmfiles{hdlists}\n";
63} else {
64    $distrib->parse_mediacfg || $distrib->parse_hdlists
65        or die "Can't read the distrib config\n";
66}
67
68my $destinfodir = $destdir ?
69    $destdir . '/' . $distrib->getpath(undef, "infodir") :
70    $distrib->getfullpath(undef, "infodir");
71
72my %default_urpmfiles = (
73    depslist => $destinfodir . "/depslist.ordered",
74    provides => $destinfodir . "/provides",
75    compss =>   $destinfodir . "/compss",
76    version =>  $destdir ?
77        $destdir . $distrib->getpath(undef, "VERSION") :
78        $distrib->getfullpath(undef, "VERSION"),
79    md5sum =>   $destinfodir . "/MD5SUM",
80);
81
82while (my ($k, $v) = each(%default_urpmfiles)) {
83    $urpmfiles{$k} ||= $v;
84}
85
86$distrib->check(\*STDERR) unless $nooutput;
87
88my @hdlists;
89my @media_missing_dirs;
90foreach ($distrib->listmedia) {
91    $distrib->getvalue($_, 'askmedia') || $distrib->getvalue($_, 'suppl') and next;
92
93
94    if (! -d ($distrib->getfullpath($_, 'path'))) {
95        if ($skipmissingdir) {
96            printf(STDERR
97                "Skipping missing media %s\n",
98                $distrib->getpath($_, 'path')
99            ) unless $nooutput;
100        } else {
101            # delaying error report to report all errors, not only the first ones
102            push(@media_missing_dirs, $_);
103        }
104        next;
105    }
106
107    push @hdlists, {
108        synthesis => $destdir ?
109            $destdir . '/' . $distrib->getpath($_, 'synthesis') :
110            $distrib->getfullpath($_, 'synthesis'),
111        hdlist => $destdir ?
112            $destdir . '/' .$distrib->getpath($_, 'hdlist') :
113            $distrib->getfullpath($_, 'hdlist'),
114        dir => $distrib->getpath($_, 'path'),
115        descr => $distrib->getvalue($_, 'name'),
116        mediainfo => $destdir ?
117            $destdir . '/' . $distrib->getpath(undef, 'infodir') :
118            $distrib->getfullpath(undef, 'infodir'),
119        thismediainfo => ($destdir ?
120            $destdir . '/' . $distrib->getpath($_, 'path') :
121            $distrib->getfullpath($_, 'path')) . "/media_info",
122        synthesis2 => ($destdir ?
123            $destdir . '/' . $distrib->getpath($_, 'path') :
124            $distrib->getfullpath($_, 'path')) . "/media_info/synthesis.hdlist.cz",
125        hdlist2 => ($destdir ?
126            $destdir . '/' . $distrib->getpath($_, 'path') :
127            $distrib->getfullpath($_, 'path')) . "/media_info/hdlist.cz",
128        md5sum => ($destdir ?
129            $destdir . '/' . $distrib->getpath($_, 'path') :
130            $distrib->getfullpath($_, 'path')) . "/media_info/MD5SUM",
131    };
132}
133
134# if there is result here, $skipmissingdir is not set and there is errors:
135if (@media_missing_dirs) {
136    foreach my $media (@media_missing_dirs) {
137        printf(STDERR
138            "Missing dir '%s' for media '%s'\n",
139            $distrib->getpath($media, 'path'),
140            $distrib->getvalue($media, 'name')
141        ) unless $nooutput;
142    }
143    die "Stopping because dirs are missing, specify --skipmissingdir to ignore\n";
144}
145
146if (!-d $destinfodir) {
147    mkdir $destinfodir, 0755
148        or die qq(Can't create directory "$destinfodir": $!\n);
149}
150
151foreach my $e (@hdlists) {
152    for my $d (qw(mediainfo thismediainfo)) {
153        if (! -d $e->{$d}) {
154            mkdir $e->{$d}, 0755
155                or die qq(Can't create directory "$e->{$d}": $!\n);
156        }
157    }
158}
159
160sub clean_cache {
161    unless ($noclean) {
162        system($ENV{LD_LOADER} ? $ENV{LD_LOADER} : @{[]}, "rm", "-rf", $headers_dir);
163        mkdir $headers_dir
164            or die qq(Can't create directory "$headers_dir": $!\n);
165    }
166}
167
168clean_cache();
169
170my $to_build = [];
171my $to_remove = [];
172my @hdlist_path;
173
174check_hdlist();
175
176sub check_hdlist {
177    foreach (0..$#hdlists) {
178        my $e = $hdlists[$_];
179        my $r;
180        $to_build->[$_] = [];
181        $to_remove->[$_] = {};
182
183        #- try to find the right repository where can be found the directory
184        #- listed in the hdlist file.
185        #- if the number of roots is equal to the number of media, assume one
186        #- media per root, else try to find a valid root containing the media.
187        $r ||= $root[0];
188        if (scalar(@hdlists) == scalar(@root)) {
189            $r = $root[$_];
190        } else {
191            foreach (@root) {
192                -d "$_/$e->{dir}" and $r = $_, last;
193            }
194        }
195
196        #- fake build of architecture dependent directory.
197        my @files;
198        if ($e->{dir} =~ /%{ARCH}/) {
199            foreach my $arch (qw(i686 i586 i486 i386 k8 k7 k6 amd64 amd32 x86_64 x86_32 ia64 ia32
200                ppc sparc sparc32 sparc64 alpha noarch)) {
201                my $dir = $e->{dir};
202                $dir =~ s|%{ARCH}|$arch|g;
203                push @files, glob("$r/$dir/*.$arch.rpm");
204            }
205        } else {
206            push @files, glob("$r/$e->{dir}/*.rpm");
207        }
208        @files or do {
209            print STDERR "unable to find rpm files in $e->{dir}\n" unless $nooutput;
210            next;
211        };
212
213        my @headers;
214        if ($fast) {
215            print STDERR "listing rpm files in directory $r/$e->{dir}\n" unless $nooutput;
216            $hdlist_path[$_] = "$r/$e->{dir}";
217            @headers = grep { s/\.rpm$// } all("$r/$e->{dir}")
218        } else {
219            print STDERR "parsing rpm files in directory $r/$e->{dir}\n" unless $nooutput;
220            @headers = $urpm->parse_rpms_build_headers(
221                dir  => $headers_dir,
222                rpms => \@files,
223                dontdie => $dontdie,
224                silent => $nooutput,
225            );
226            # TODO if @headers is empty ?
227            $e->{headers} = \@headers;
228        }
229        if (!$blind) {
230            # checking if hdlist rebuild is needed
231            print STDERR "Checking if hdlist need to be rebuild for media $e->{descr}\n" unless $nooutput;
232            if ($fast) {
233                print "Comparing headers with synthesis\n";
234                if(!compare_headers_with_synthesis($e->{synthesis}, $to_build->[$_], $to_remove->[$_], @headers)) {
235                    $e->{noneedrebuild} = 1;
236                    print "No\n" unless $nooutput;
237                } else {
238                    print "Yes\n" unless $nooutput;
239                }
240            } else {
241                print "Comparing headers with hdlist\n";
242                if(!compare_headers_with_hdlist($e->{hdlist}, @headers)) {
243                    $e->{noneedrebuild} = 1;
244                    print "No\n" unless $nooutput;
245                } else {
246                    print "Yes\n" unless $nooutput;
247                }
248            }
249        }
250    }
251}
252
253# return 1 if differ, 0 otherwise
254sub compare_headers_with_hdlist {
255    my ($hdlist, @headers) = @_;
256    if (my $pack = MDV::Packdrakeng->open(archive => $hdlist)) {
257        my %exists_headers;
258        $exists_headers{$_} = 0 foreach(@headers);
259        my (undef, $files, undef) = $pack->getcontent();
260        foreach my $file (@{$files || []}) {
261            if (exists($exists_headers{$file})) {
262                # TODO checking somethings else that name
263                delete($exists_headers{$file});
264            } else {
265                print "$file differs\n";
266                # one file is in hdlist, not in our headers => differ
267                return 1;
268            }
269        }
270        # if the same files are in hdlist, and headers list,
271        # nothing left
272        if (keys %exists_headers) {
273            return 1;
274        }
275    } else {
276        # no valid hdlist, it differ for sure !
277        return 1;
278    }
279    return 0; # no diff
280}
281
282sub compare_headers_with_synthesis {
283    my ($synthesis, $to_build, $to_remove, @headers) = @_;
284    if (open my $pack, "zcat $synthesis |") {
285        my %exists_headers;
286        $exists_headers{$_} = 0 foreach(@headers);
287        while (<$pack>) {
288            my ($file) = /^\@info\@([^@]+)\@/ or next;
289            if (exists($exists_headers{$file})) {
290                # TODO checking somethings else that name
291                delete($exists_headers{$file});
292            } else {
293                # one file is in hdlist, not in our headers => differ
294                $to_remove->{$file} = 1
295            }
296        }
297        # if the same files are in hdlist, and headers list,
298        # nothing left
299        if (keys %exists_headers) {
300            push @$to_build, keys %exists_headers;
301            return 1;
302        } 
303        return 1 if (%$to_remove) 
304    } else {
305        # no valid synthesis, it differ for sure !
306        return 1;
307    }
308    return 0; # no diff
309}
310
311if ($fast) {
312    my $need_full_rebuild;
313    my (%provides, %requires);
314
315    if (!$nosynthesis) {                # a.k.a. if synthesis
316        foreach my $hid (0 .. $#hdlists) {
317            my $e = $hdlists[$hid];
318            if (open my $pack, "zcat $e->{synthesis} |") {
319                while (<$pack>) {
320                    my (@prov, @req);
321                    if (/^\@provides@(.*)/) {
322                        foreach my $p (split '@', $1) {
323                            $p =~ /([^[]+)(?:\[(.*)\])?/g;
324                            push @prov, [$1, $2 || 1]
325                        }
326                    } elsif (/\@requires\@(.*)/) {
327                        foreach my $p (split '@', $1) {
328                            $p =~ /([^[]+)(?:\[(.*)\])?/g;
329                            push @req, [$1, $2 || 1]
330                        }
331                    } elsif (/\@info\@([^@]+)@/) {
332                        my $rpm = $1;
333
334                        # must not add requires and provides of packages
335                        # which will be removed
336
337                        if (!$to_remove->[$hid]{$rpm}) {
338                            foreach my $p (@prov) {
339                                my ($a, $b) = @$p;
340                                $a =~ s/\[\*\]//;
341                                $provides{$a} = $b
342                            } 
343                            foreach my $r (@req) {
344                                my ($a, $b) = @$r;
345                                $a =~ s/\[\*\]//;
346                                $requires{$a} = $b
347                            }
348                        }
349                    }
350                }
351                close $pack
352            }
353        }
354    } # end if synthesis
355
356    foreach my $hid (0 .. $#hdlists) {
357        my $e = $hdlists[$hid];
358        if ($e->{noneedrebuild}) { next }
359
360        print STDERR "Checking $e->{hdlist} ($e->{synthesis})\n";
361        print STDERR "TO ADD @{$to_build->[$hid]}\n";
362        print STDERR "TO REMOVE ", join(' ', keys %{$to_remove->[$hid]}), "\n";
363
364        my %done;
365        my $build_urpm = new URPM;
366        my $new_urpm = new URPM;
367        my ($start, $end) = $build_urpm->parse_hdlist($e->{hdlist});
368        # $start == $end and next;
369
370        print STDERR "START: $start END: $end\n";
371        print STDERR "Extracting headers\n";
372
373        my %rpm_id;
374        if ($end) {
375            foreach ($start .. $end) {
376                my $pkg = $build_urpm->{depslist}[$_];
377                my $filename = $pkg->fullname;
378                $rpm_id{$filename} = $_;
379                unless (-s "$headers_dir/$filename") {
380                    open my $fh, ">$headers_dir/$filename"
381                        or die "unable to open $headers_dir/$filename for writing\n";
382                    $pkg->build_header(fileno $fh);
383                    close $fh;
384                }
385                if (!$to_remove->[$hid]{$filename}) {
386                    push @{$e->{headers}}, $filename 
387                }
388            }
389        }
390
391        my %rpm_to_add;
392        foreach (@{$to_build->[$hid]}) {
393            my ($name, $arch) = /(.*)-[^-]+-[^-]+\.([^.]+)$/ or next;
394            print "Adding $_\n";
395            $rpm_to_add{$arch}{$name} = $_;
396            $rpm_id{$_} = get_info("$hdlist_path[$hid]/$_.rpm", $build_urpm, 0, \%provides, \%requires)
397        }
398
399        if ($nosynthesis) {
400            print STDERR qq(removing not updated synthesis $e->{synthesis}\n) unless $nooutput;
401            unlink $e->{synthesis}
402        } else {
403            my $err;
404            print "Rebuild synthesis $e->{synthesis}\n";
405
406            if (open my $pack, "zcat $e->{synthesis} |") {
407                my $temp_synthesis = $tempdir . '/synthesis' . $$;
408                unlink $temp_synthesis;
409                open my $new_synthesis, "| gzip - >'$temp_synthesis'";
410                binmode $new_synthesis;
411
412                my $info;
413                PACK: while (<$pack>) {
414                    $info .= $_;
415                    if (my ($rpm) = /^\@info\@([^@]+)\@/) {
416                        if ($to_remove->[$hid]{$rpm}) {
417                            my ($name, $arch) = $rpm =~ /(.*)-[^-]+-[^-]+\.([^.]+)$/;
418                            my $add = $rpm_to_add{$arch}{$name};
419                            if ($add) {
420                                push @{$new_urpm->{depslist}}, $build_urpm->{depslist}[$rpm_id{$add}];
421                                print "Replacing $rpm with $add ($rpm_id{$add}), parsing $hdlist_path[$hid]/$add.rpm\n";
422                                $err = add_info("$hdlist_path[$hid]/$add.rpm", $new_synthesis, $build_urpm, $rpm_id{$add}, \%provides, \%requires);
423                                last PACK if $err == -1;
424                                $done{$add} = 1
425                            } else {
426                                print "Removing $rpm\n"
427                            }
428                        } else {
429                            push @{$new_urpm->{depslist}}, $build_urpm->{depslist}[$rpm_id{$rpm}];
430                            print $new_synthesis "$info";
431                        }
432                        $info = ''
433                    }
434                }
435                if ($err != -1) {
436                    foreach (@{$to_build->[$hid]}) {
437                        $done{$_} and next;
438                        print "Adding $_ ($rpm_id{$_})\n";
439                        my $id = $rpm_id{$_};
440                        push @{$new_urpm->{depslist}}, $build_urpm->{depslist}[$id];
441                        $err = add_info("$hdlist_path[$hid]/$_.rpm", $new_synthesis, $build_urpm, $id, \%provides, \%requires)
442                    }
443                } elsif ($err == -1) {
444                    # this should be prevented if we can get the file list and regenerated the according synthesis entries
445                    print STDERR qq(dependencies may not been correct, recomputing complete dependencies\n) unless $nooutput;
446                    $need_full_rebuild = 1;
447                    last
448                }
449                close $new_synthesis;
450                print "$temp_synthesis -- $e->{synthesis}\n";
451                system('/bin/mv', $temp_synthesis, "$e->{synthesis}") and die "Cannot create $e->{synthesis}";
452                close $pack
453            }
454        }
455        my $temp_hdlist = $tempdir . '/hdlist' . $$;
456        unlink $temp_hdlist;
457        print "Rebuilding $e->{hdlist}\n";
458        $new_urpm->build_hdlist(start  => 0,
459            end    => $#{$new_urpm->{depslist}},
460            dir    => $headers_dir,
461            hdlist => $temp_hdlist,
462            ratio  => 9);
463        system('/bin/mv', $temp_hdlist, "$e->{hdlist}");
464
465        unless ($nomediainfo) {
466            print STDERR qq(link alternate locations of synthesis and hdlists\n) unless $nooutput;
467            unlink $e->{hdlist2}, $e->{synthesis2};
468            link $e->{hdlist}, $e->{hdlist2}
469                or print STDERR qq(link failed for "$e->{hdlist2}": $!\n);
470            if ($nosynthesis) {
471                print STDERR qq(removing not updated synthesis $e->{synthesis2}) unless $nooutput;
472                unlink $e->{synthesis2}
473            } else {
474                link $e->{synthesis}, $e->{synthesis2}
475                    or print STDERR qq(link failed for "$e->{synthesis2}": $!\n);
476            }
477        }
478        unless ($nomd5sum) {
479            print STDERR qq(generate media-specific MD5SUM in $e->{thismediainfo}\n) unless $nooutput;
480            my $here = getcwd();
481            chdir $e->{thismediainfo};
482            my $md5sum;
483            if ($nosynthesis) {
484                $md5sum = `/usr/bin/md5sum hdlist*`;
485            } else {
486                $md5sum = `/usr/bin/md5sum hdlist* synthesis*`;
487            }
488            chdir $here;
489            if (open my $md5sumfh, '>', $e->{md5sum}) {
490                print $md5sumfh $md5sum;
491                close $md5sumfh;
492            } else {
493                print STDERR qq(Can't create "$e->{md5sum}": $!\n);
494            }
495        }
496    }
497    unless ($nomd5sum) {
498        my $here = getcwd();
499        chdir $destinfodir;
500        my $md5sum;
501        if (!$nosynthesis) {
502            $md5sum = `/usr/bin/md5sum hdlist*`;
503        } else {
504            $md5sum = `/usr/bin/md5sum hdlist* synthesis*`;
505        }
506        chdir $here;
507        if (open my $md5sumfh, '>', $urpmfiles{md5sum}) {
508            print $md5sumfh $md5sum;
509            close $md5sumfh;
510        } else {
511            print STDERR qq(Can't create "$urpmfiles{md5sum}": $!\n);
512        }
513    }
514    if ($need_full_rebuild) { 
515        $fast = 0;
516        check_hdlist();
517    } else {
518        exit
519    }
520}
521
522sub get_info {
523    my ($rpm, $build_urpm, $prev_id, $provides, $requires) = @_;
524    my $tmp_urpm;
525    if ($prev_id) {
526        print STDERR "Replacing $prev_id with $rpm\n";
527        $tmp_urpm = new URPM
528    } else {
529        $tmp_urpm = $build_urpm
530    }
531    my $id = $tmp_urpm->parse_rpm($rpm);
532    print STDERR "$rpm ID $id ($prev_id)\n";
533    my $pkg = $tmp_urpm->{depslist}[$id];
534    die "FATAL: could not parse $rpm (id $id pkg $pkg)" if ! ref $pkg;
535    my $filename = $pkg->fullname;
536    unless (-s "$headers_dir/$filename") {
537        print STDERR "Creating $headers_dir/$filename\n";
538        open my $fh, ">$headers_dir/$filename" or die "unable to open $headers_dir/$filename for writing\n";
539        $pkg->build_header(fileno $fh);
540        close $fh;
541    }
542    foreach my $p ($pkg->requires) {
543        $p =~ /([^[]+)(?:\[(.*)\])?/g;
544        $requires->{$1} = $2 || 1
545    }
546    foreach my $p ($pkg->provides) {
547        $p =~ /([^[]+)(?:\[(.*)\])?/g;
548        $provides->{$1} = $2 || 1
549    }
550
551    if ($prev_id) {
552        $build_urpm->{depslist}[$prev_id] = $pkg
553    }
554    $id
555}
556
557sub add_info {
558    my ($rpm, $fh, $build_urpm, $prev_id, $provides, $requires) = @_;
559    my $pkg = $build_urpm->{depslist}[$prev_id];
560
561    # adding all the files which has a requires
562    my @files = grep { $requires->{$_} } $pkg->files;
563    # try to find if all the requires on files are satisfied
564    # Do not need to do version checking here, this code is just needed for deps on files
565    my @unsatisfied = grep { s/\[\*\]//; defined $provides->{$_} && m,^/, } $pkg->requires;
566    if (@unsatisfied) {
567        print STDERR "Warning, $rpm has unsatisfied requires (@unsatisfied), forcing complete rebuild\n";
568        return -1
569    }
570    my $files = join '@', @files;
571    $pkg->pack_header;
572    #@files{@{$pkg->files}} = undef;                                                                                                     
573    my $tmp_file = mktemp("$tempdir/gendistrib.tmp.XXXXX");
574    open my $tmp, ">$tmp_file" or die "Could not open $tmp_file";
575    #print "Adding packages files $files\n";
576    $pkg->build_info(fileno $tmp, join('@', $files));
577    close $tmp;
578    open my $tmp, $tmp_file;
579    {
580        local $/;
581        my $data = <$tmp>;
582        print $fh $data;
583    }
584    close $tmp;
585    $prev_id
586}
587
588if ($noemptymedia) {
589    foreach my $e (@hdlists) {
590        $e->{headers} or die "Empty media were found, stopping\n";
591    }
592}
593
594#- clean everything to start second pass.
595print STDERR "clean data for second pass\n" unless $nooutput;
596$urpm->unresolved_provides_clean;
597
598#- temporary file where to build hdlists
599my $temp_hdlist = mktemp("$tempdir/hdlistXXXXX");
600foreach (0..$#hdlists) {
601    my $e = $hdlists[$_];
602
603    if ($e->{headers}) { # We have rpms in this media
604
605        print STDERR qq(parsing headers for "$e->{descr}"\n) unless $nooutput;
606        my ($start, $end) = $urpm->parse_headers(dir     => $headers_dir,
607            headers => $e->{headers},
608            dontdie => $dontdie,
609            silent  => $nooutput);
610
611        print STDERR "computing deps\n" unless $nooutput;
612        $urpm->compute_deps;
613
614        # No media change, nothing to write
615        next if $e->{noneedrebuild};
616
617        print STDERR qq(building hdlist for medium "$e->{descr}"\n) unless $nooutput;
618        unlink $temp_hdlist;
619        $urpm->build_hdlist(start  => $start,
620            end    => $end,
621            dir    => $headers_dir,
622            hdlist => $temp_hdlist,
623            ratio  => 9);
624        system('/bin/mv', $temp_hdlist, $e->{hdlist});
625
626        print STDERR qq(building synthesis for medium "$e->{descr}"\n) unless $nooutput;
627        $urpm->build_synthesis(start     => $start,
628            end       => $end,
629            synthesis => $e->{synthesis});
630
631    } else { # no rpm, creating empty but valid index
632        if (my $pack = MDV::Packdrakeng->new(archive => $temp_hdlist)) {
633            $pack = undef; # closing archive
634            system('/bin/mv', $temp_hdlist, $e->{hdlist});
635        } else {
636            print STDERR "Can't create empty archive $temp_hdlist: $MDV::Packdrakeng::error\n";
637        }
638        open(my $hsynth, "| /bin/gzip > $e->{synthesis}")
639            or print STDERR "Can't create empty synthesis $e->{synthesis}: $!\n";
640        close($hsynth);
641    }
642
643    unless ($nomediainfo) {
644        print STDERR qq(link alternate locations of synthesis and hdlists\n) unless $nooutput;
645        unlink $e->{hdlist2}, $e->{synthesis2};
646        link $e->{hdlist}, $e->{hdlist2}
647            or print STDERR qq(link failed for "$e->{hdlist2}": $!\n);
648        link $e->{synthesis}, $e->{synthesis2}
649            or print STDERR qq(link failed for "$e->{synthesis2}": $!\n);
650    }
651
652    unless ($nomd5sum) {
653        print STDERR qq(generate media-specific MD5SUM in $e->{thismediainfo}\n) unless $nooutput;
654        my $here = getcwd();
655        chdir $e->{thismediainfo};
656        my $md5sum = `/usr/bin/md5sum hdlist* synthesis*`;
657        chdir $here;
658        if (open my $md5sumfh, '>', $e->{md5sum}) {
659            print $md5sumfh $md5sum;
660            close $md5sumfh;
661        } else {
662            print STDERR qq(Can't create "$e->{md5sum}": $!\n);
663        }
664    }
665}
666
667clean_cache();
668
669if (grep { ! $_->{noneedrebuild} } @hdlists) {
670
671    print STDERR "building base files\n" unless $nooutput;
672    $urpm->build_base_files(
673        depslist => $urpmfiles{depslist},
674        provides => $urpmfiles{provides},
675        compss   => $urpmfiles{compss},
676    );
677
678    if (-f $destinfodir . '/media.cfg') {
679        if (! -f $destinfodir . '/hdlists' ||
680            ((stat($distrib->getfullpath(undef, 'infodir') . '/media.cfg'))[9] >
681                (stat($destinfodir . '/hdlists'))[9])) {
682            print STDERR "Write hdlists file\n" unless $nooutput;
683            $distrib->write_hdlists($destinfodir . '/hdlists')
684                or print STDERR "Can't write $destinfodir/hdlists file\n";
685        }
686    }
687
688    #- safety cleaning
689    unlink $urpmfiles{md5sum};
690    unless ($nomd5sum) {
691        my $here = getcwd();
692        chdir $destinfodir;
693        my $md5sum = `/usr/bin/md5sum hdlist* synthesis*`;
694        chdir $here;
695        if (open my $md5sumfh, '>', $urpmfiles{md5sum}) {
696            print $md5sumfh $md5sum;
697            close $md5sumfh;
698        } else {
699            print STDERR qq(Can't create "$urpmfiles{md5sum}": $!\n);
700        }
701    }
702
703    print STDERR "Building version file\n" unless $nooutput;
704    $distrib->write_version($urpmfiles{version});
705}
706
707#- check if there are NOTFOUND in dependencies, check if they are in other media, warn the user.
708if ($nooutput || !$nochkdep) {
709    foreach (0 .. $#{$urpm->{depslist}}) {
710        my $pkg = $urpm->{depslist}[$_];
711
712        foreach (split " ", $urpm->{deps}[$_]) {
713            /NOTFOUND_(.*)/ or next;
714            print STDERR $pkg->fullname . " requires [$1] which\n";
715            if ($urpm->{provides}{$1}) {
716                print STDERR "  is available on packages not listed in this medium or previous medium:\n";
717                foreach (keys %{$urpm->{provides}{$1}}) {
718                    my $dep_pkg = $urpm->{depslist}[$_];
719                    print STDERR "    " . $dep_pkg->fullname . "\n";
720                }
721            } else {
722                print STDERR "  is not available in any medium listed\n";
723                if (/NOTFOUND_(\D*)(\d+[\.\-\d]*)?(.*)?\.so\./) {
724                    my $re = (quotemeta $1) . '(\d+[\.\-\d]*)' . (!$2 && "?") . '\.so\.';
725                    foreach (keys %{$urpm->{provides}}) {
726                        /$re/ or next;
727                        print STDERR "  but a similar provides is available as [$_], need rebuild ?\n";
728                    }
729                }
730            }
731        }
732    }
733}
734
735__END__
736
737=head1 NAME
738
739gendistrib - generates a mirror tree for a distribution
740
741=head1 SYNOPSIS
742
743    gendistrib [options] directory
744
745=head1 OPTIONS
746
747=over 4
748
749=item --blind
750
751Always rebuild indexes, without checking whether it's needed.
752
753=item --compss file
754
755Path of F<compss> file (defaults to F<media/media_info/compss>).
756
757=item --depslist file
758
759Path of F<depslist> file (defaults to F<media/media_info/depslist.ordered>).
760
761=item --destdir dir
762
763Create all new files in the specified directory. All subdirectories should
764exist. This option is mostly useful for testing, or while using a read-only
765repository.
766
767=item --hdlists file
768
769Path of the F<hdlists> file (defaults to F<media/media_info/hdlists>)
770
771=item --headersdir dir
772
773Put temporary files in this directory (defaults to TMPDIR).
774
775=item --mediacfg file
776
777Use the specified F<media.cfg> file (defaults to F<media/media_info/media.cfg>).
778
779=item --nobadrpm
780
781Don't abort when encountering bad rpms.
782
783=item --nochkdep
784
785Don't search for missing dependencies.
786
787=item --noclean
788
789Keep cache files.
790
791=item --noemptymedia
792
793Stop and abort if an empty media is found.
794
795=item --nomd5sum
796
797Don't generate MD5SUM files.
798
799=item --nosynthesis
800
801Don't generate synthesis in fast mode
802
803=item --nomediainfo
804
805Don't create per-media F<media_info> subdirectories.
806
807=item --provides file
808
809Path of F<provides> file (defaults to F<media/media_info/provides>)
810
811=item --skipmissingdir
812
813If a media dir is missing, ignore it instead of aborting.
814
815=item -s
816
817Silent mode.
818
819=back
820
821=head1 DESCRIPTION
822
823F<gendistrib> is a tool that helps to generate the structure of a Mandriva
824RPM repository, compatible with Mandriva tools (F<urpmi>, F<rpmdrake>,
825etc.)
826
827=head2 General Structure of a Repository
828
829A typical repository, under a root directory F</ROOT/>, has the following
830structure:
831
832    ROOT/ - media/
833            |- contrib/
834            |   `- media_info/
835            |- main/
836            |   `- media_info/
837            `- media_info/
838
839In this example, we have two media, called I<main> and I<contrib>. The
840RPMs packages are placed in the F<main> and F<contrib> subdirectories.
841Repository metadata is contained in the top-level F<media_info> directory.
842Per-media metadata are contained in the F<main/media_info> and
843F<contrib/media_info> subdirectories.
844
845=head2 Configuration of the distribution tree
846
847Before using F<gendistrib>, you must create a file F<media_info/media.cfg>
848to describe your repository. (An empty file will work, but this isn't
849recommended.) The syntax of this file is reminiscent of F<.ini> files.
850
851A first section C<[media_info]> contains global information about the
852repository:
853
854    [media_info]
855    version=2006.0
856    branch=Cooker
857    arch=i586
858
859Then, supply one section per media.
860
861    [main]
862    hdlist=hdlist_main.cz
863    name=Main
864
865Here, the C<hdlist> parameter specifies what will be the name of the
866hdlist file in the top-level F<media_info> directory. C<name> is a human
867readable label for the media.
868
869=head2 Operation
870
871F<genhdlist> should be passed the F<ROOT> directory as parameter. It will
872then generate the hdlist and synthesis files and all other files needed
873for proper repository operation.
874
875F<genhdlist> will also verify any broken dependencies in your repository
876and report them.
877
878=head1 SEE ALSO
879
880genhdlist(1), and MDV::Distribconf(3) for description of the format of the
881F<media.cfg> file.
882
883=head1 COPYRIGHT
884
885Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 MandrakeSoft SA
886
887Copyright (C) 2005, 2006 Mandriva SA
888
889This program is free software; you can redistribute it and/or modify
890it under the terms of the GNU General Public License as published by
891the Free Software Foundation; either version 2, or (at your option)
892any later version.
893
894This program is distributed in the hope that it will be useful,
895but WITHOUT ANY WARRANTY; without even the implied warranty of
896MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
897GNU General Public License for more details.
898
899You should have received a copy of the GNU General Public License
900along with this program; if not, write to the Free Software
901Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
902
903=cut
Note: See TracBrowser for help on using the repository browser.