X-Git-Url: http://git.annexia.org/?p=fedora-mingw.git;a=blobdiff_plain;f=smock%2Fsmock.pl;h=d0d0042883c8298476bd9c4c489530a7ae001a3b;hp=0833b68744dcaeab31231def9a1bffbd87a5648d;hb=966f55f8692da3f842da077e57c22ff501e380e1;hpb=37cc331df869845de4861c271d56c323c4563e45 diff --git a/smock/smock.pl b/smock/smock.pl index 0833b68..d0d0042 100755 --- a/smock/smock.pl +++ b/smock/smock.pl @@ -25,17 +25,27 @@ use Pod::Usage; use File::Temp qw(tempfile); my @arches = (); +my $chain = 0; my @distros = (); -my $localrepo = $ENV{HOME} . "/public_html/smock/yum"; +my $dryrun = 0; my $help = 0; +my $keepgoing = 0; +my $localrepo = $ENV{HOME} . "/public_html/smock/yum"; my $man = 0; +my $overwrite = 0; +my $suffix = ""; GetOptions ( "arch=s" => \@arches, + "chain" => \$chain, "distro=s" => \@distros, - "localrepo=s" => \$localrepo, + "dryrun" => \$dryrun, "help|?" => \$help, - "man" => \$man + "keepgoing" => \$keepgoing, + "localrepo=s" => \$localrepo, + "man" => \$man, + "overwrite" => \$overwrite, + "suffix=s" => \$suffix, ) or pod2usage (2); pod2usage (1) if $help; pod2usage (-exitstatus => 0, -verbose => 2) if $man; @@ -67,7 +77,7 @@ must bump the release number or delete the binary RPM from the localrepo directory). B Please read the README file first. You need to set up mock -and a web server before you can use this command. +and optionally a web server before you can use this command. =head1 OPTIONS @@ -78,15 +88,58 @@ and a web server before you can use this command. Specify the architecture(s) to build, eg. i386, x86_64. You can list this option several times to build several architectures. +=item B<--chain> + +Don't run any commands, just print the packages in the correct +format for chain building. See: +L + =item B<--distro> Specify the distribution(s) to build, eg. fedora-9, fedora-10. You can list this option several times to build several distributions. +=item B<--dryrun> + +Don't run any commands, just print the packages in the order +in which they must be built. + +=item B<--help> + +Print this help. + +=item B<--keepgoing> + +Don't exit if a package fails, but keep building. + +Note that this isn't always safe because new packages may be built +against older packages, in the case where the older package couldn't +be rebuilt because of an error. + +However, it is very useful. + =item B<--localrepo> Local repository. Defaults to C<$HOME/public_html/smock/yum> +=item B<--man> + +Show this help using man. + +=item B<--overwrite> + +Overwrite existing files that are already in the repository. By default the +build of an SRPM is skipped if there is already a package with the same name, +version and release in the localrepo. With this option, the new build +overwrites the old one. This may lead to unexpected results, if the new build +does not create the same subpackages as the old one, because then the old +subpackages will still be accessible in the repository. + +=item B<--suffix> + +Append a suffix to the mock configuration file in order to use +a custom one. + =back =cut @@ -123,8 +176,8 @@ sub get_lines open PIPE, "$_[0] |" or die "$_[0]: $!"; my @lines; foreach () { - chomp; - push @lines, $_; + chomp; + push @lines, $_; } close PIPE; return @lines; @@ -146,11 +199,11 @@ foreach my $srpm (@srpms) { #print " buildrequires = ", join (",", @buildrequires), "\n"; $srpms{$name} = { - name => $name, - version => $version, - release => $release, - buildrequires => \@buildrequires, - filename => $srpm + name => $name, + version => $version, + release => $release, + buildrequires => \@buildrequires, + filename => $srpm } } @@ -162,49 +215,104 @@ sub is_member_of my $item = shift; foreach (@_) { - return 1 if $item eq $_; + return 1 if $item eq $_; } 0; } sub dependency_in { - my $dep = shift; # eg. dbus-devel + my $dep = shift; # eg. dbus-devel while ($dep) { - return $dep if is_member_of ($dep, @_); - my $newdep = $dep; - $newdep =~ s/-\w+$//; # eg. dbus-devel -> dbus - last if $newdep eq $dep; - $dep = $newdep; + return $dep if is_member_of ($dep, @_); + my $newdep = $dep; + $newdep =~ s/-\w+$//; # eg. dbus-devel -> dbus + last if $newdep eq $dep; + $dep = $newdep; } 0; } -my @names = sort keys %srpms; -foreach my $name (@names) { +foreach my $name (keys %srpms) { my @buildrequires = @{$srpms{$name}->{buildrequires}}; - @buildrequires = grep { $_ = dependency_in ($_, @names) } @buildrequires; + @buildrequires = + grep { $_ = dependency_in ($_, keys %srpms) } @buildrequires; $srpms{$name}{buildrequires} = \@buildrequires; } -# Now sort the SRPMs into the correct order for building +# This function takes a list of package names and sorts them into the +# correct order for building, given the existing %srpms hash +# containing buildrequires. We use the external 'tsort' program. -my ($fh, $filename) = tempfile (); +sub tsort +{ + my @names = @_; + + my ($fh, $filename) = tempfile (); + + foreach my $name (@names) { + my @buildrequires = @{$srpms{$name}->{buildrequires}}; + foreach (@buildrequires) { + print $fh "$_ $name\n" + } + # Add a self->self dependency. This ensures that any + # packages which don't have or appear as a dependency of + # any other package still get built. + print $fh "$name $name\n" + } + close $fh; -foreach my $name (@names) { - my @buildrequires = @{$srpms{$name}->{buildrequires}}; - foreach (@buildrequires) { - print $fh "$_ $name\n" + get_lines "tsort $filename"; +} + +# Sort the initial list of package names. + +my @names = sort keys %srpms; +my @buildorder = tsort (@names); + +# With --chain flag we print the packages in groups for chain building. + +if ($chain) { + my %group = (); + my $name; + + print 'make chain-build CHAIN="'; + + foreach $name (@buildorder) { + my @br = @{$srpms{$name}->{buildrequires}}; + + # If a BR occurs within the current group, then start the next group. + my $occurs = 0; + foreach (@br) { + if (exists $group{$_}) { + $occurs = 1; + last; + } + } + + if ($occurs) { + %group = (); + print ": "; + } + + $group{$name} = 1; + print "$name "; } + print "\"\n"; + + exit 0 } -close $fh; -my @buildorder = get_lines "tsort $filename"; +# With --dryrun flag we just print the packages in build order then exit. + +if ($dryrun) { + foreach (@buildorder) { + print "$_\n"; + } -#foreach (@buildorder) { -# print "$_\n"; -#} + exit 0 +} # Now we can build each SRPM. @@ -213,7 +321,7 @@ sub my_mkdir local $_ = $_[0]; if (! -d $_) { - mkdir ($_, 0755) or die "mkdir $_: $!" + mkdir ($_, 0755) or die "mkdir $_: $!" } } @@ -226,61 +334,85 @@ sub createrepo my_mkdir "$localrepo/$distro/src"; my_mkdir "$localrepo/$distro/src/SRPMS"; system ("cd $localrepo/$distro/src && rm -rf repodata && createrepo -q .") == 0 - or die "createrepo failed: $?\n"; + or die "createrepo failed: $?\n"; my_mkdir "$localrepo/$distro/$arch"; my_mkdir "$localrepo/$distro/$arch/RPMS"; my_mkdir "$localrepo/$distro/$arch/logs"; system ("cd $localrepo/$distro/$arch && rm -rf repodata && createrepo -q --exclude 'logs/*rpm' .") == 0 - or die "createrepo failed: $?\n"; + or die "createrepo failed: $?\n"; } if (! -d "$localrepo/scratch") { mkdir "$localrepo/scratch" - or die "mkdir $localrepo/scratch: $!\nIf you haven't set up a local repository yet, you must read the README file.\n"; + or die "mkdir $localrepo/scratch: $!\nIf you haven't set up a local repository yet, you must read the README file.\n"; } -system "rm -f $localrepo/scratch/*"; +system "rm -rf $localrepo/scratch/*"; + +my @errors = (); # NB: Need to do the arch/distro in the outer loop to work # around the caching bug in mock/yum. foreach my $arch (@arches) { foreach my $distro (@distros) { - foreach my $name (@buildorder) { - my $version = $srpms{$name}->{version}; - my $release = $srpms{$name}->{release}; - my $srpm_filename = $srpms{$name}->{filename}; - - $release =~ s/\.fc?\d+$//; # "1.fc9" -> "1" - - # Does the built (binary) package exist already? - my $pattern = "$localrepo/$distro/$arch/RPMS/$name-$version-$release.*.rpm"; - #print "pattern = $pattern\n"; - my @binaries = glob $pattern; - - if (@binaries == 0) - { - # Rebuild the package. - print "*** building $name-$version-$release $arch $distro ***\n"; - - createrepo ($arch, $distro); - system ("mock -r $distro-$arch --resultdir $localrepo/scratch $srpm_filename") == 0 - or die "Build failed, return code $?\nLeaving the logs in $localrepo/scratch\n"; - - # Build was a success so move the final RPMs into the - # mock repo for next time. - system ("mv $localrepo/scratch/*.src.rpm $localrepo/$distro/src/SRPMS") == 0 or die "mv"; - system ("mv $localrepo/scratch/*.rpm $localrepo/$distro/$arch/RPMS") == 0 or die "mv"; - my_mkdir "$localrepo/$distro/$arch/logs/$name-$version-$release"; - system ("mv $localrepo/scratch/*.log $localrepo/$distro/$arch/logs/$name-$version-$release/") == 0 or die "mv"; - - createrepo ($arch, $distro); - } - else - { - print "skipping $name-$version-$release $arch $distro\n"; - } - } + foreach my $name (@buildorder) { + my $version = $srpms{$name}->{version}; + my $release = $srpms{$name}->{release}; + my $srpm_filename = $srpms{$name}->{filename}; + + $release =~ s/\.fc?\d+$//; # "1.fc9" -> "1" + + # Does the built (binary) package exist already? + my $pattern = "$localrepo/$distro/$arch/RPMS/$name-$version-$release.*.rpm"; + #print "pattern = $pattern\n"; + my @binaries = glob $pattern; + + if (@binaries != 0 && $overwrite) { + print "*** overwriting $name-$version-$release $arch $distro ***\n"; + } + + if (@binaries == 0 || $overwrite) + { + # Rebuild the package. + print "*** building $name-$version-$release $arch $distro ***\n"; + + createrepo ($arch, $distro); + + my $scratchdir = "$localrepo/scratch/$name-$distro-$arch"; + mkdir $scratchdir; + + if (system ("mock -r $distro-$arch$suffix --resultdir $scratchdir $srpm_filename") == 0) { + # Build was a success so move the final RPMs into the + # mock repo for next time. + system ("mv $scratchdir/*.src.rpm $localrepo/$distro/src/SRPMS") == 0 or die "mv"; + system ("mv $scratchdir/*.rpm $localrepo/$distro/$arch/RPMS") == 0 or die "mv"; + my_mkdir "$localrepo/$distro/$arch/logs/$name-$version-$release"; + system ("mv $scratchdir/*.log $localrepo/$distro/$arch/logs/$name-$version-$release/") == 0 or die "mv"; + system "rm -rf $scratchdir"; + + createrepo ($arch, $distro); + + } + else { + push @errors, "$name-$distro-$arch$suffix"; + print STDERR "Build failed, return code $?\nLeaving the logs in $scratchdir\n"; + exit 1 unless $keepgoing; + } + } + else + { + print "skipping $name-$version-$release $arch $distro\n"; + } + } } } + +if (@errors) { + print "\n\n\nBuild failed for the following packages:\n"; + print " $_\n" foreach @errors; + exit 1 +} + +exit 0