Add support for --keepgoing option to smock.
authorRichard W.M. Jones <rjones@redhat.com>
Fri, 23 Jan 2009 21:04:04 +0000 (21:04 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Fri, 23 Jan 2009 21:04:04 +0000 (21:04 +0000)
build-everything-in-mock.sh
smock/smock.pl

index 12275e8..bdc81e3 100755 (executable)
@@ -3,6 +3,9 @@
 # These are the packages we don't want to build yet:
 nobuild=$(grep -v '^#' IGNORE)
 
+# Keep going (not safe).  Comment out for a safe build.
+keepgoing=--keepgoing
+
 rm -f */*.src.rpm
 
 # If any extra SRPMS need to be considered, list them here.  Otherwise
@@ -15,7 +18,7 @@ for dir in *; do
                if ! rpmbuild -bs --define "_sourcedir $(pwd)/$dir" --define "_srcrpmdir $(pwd)/$dir" $dir/*.spec; then
                  echo "Failed to create a source RPM in directory $dir."
                  echo "If you want to ignore this directory, you should add"
-                 echo "it to the 'nobuild' list in this script."
+                 echo "it to the IGNORE file in the top level directory."
                  exit 1
                fi
                srpms="$srpms $(pwd)/$dir/*.src.rpm"
@@ -28,4 +31,5 @@ smock/smock.pl \
   --arch=x86_64 \
   --distro=fedora-rawhide \
   --distro=fedora-10 \
+  $keepgoing \
   $srpms
index 34a5ec0..1ba7f7e 100755 (executable)
@@ -28,6 +28,7 @@ my @arches = ();
 my @distros = ();
 my $localrepo = $ENV{HOME} . "/public_html/smock/yum";
 my $dryrun = 0;
+my $keepgoing = 0;
 my $chain = 0;
 my $help = 0;
 my $man = 0;
@@ -37,6 +38,7 @@ GetOptions (
     "distro=s" => \@distros,
     "localrepo=s" => \$localrepo,
     "dryrun" => \$dryrun,
+    "keepgoing" => \$keepgoing,
     "chain" => \$chain,
     "help|?" => \$help,
     "man" => \$man
@@ -96,6 +98,16 @@ Local repository.  Defaults to C<$HOME/public_html/smock/yum>
 Don't run any commands, just print the packages in the order
 in which they must be built.
 
+=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<--chain>
 
 Don't run any commands, just print the packages in the correct
@@ -196,30 +208,42 @@ sub dependency_in
     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 = @_;
 
-foreach my $name (@names) {
-    my @buildrequires = @{$srpms{$name}->{buildrequires}};
-    foreach (@buildrequires) {
-       print $fh "$_ $name\n"
+    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"
     }
-    # 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;
+
+    get_lines "tsort $filename";
 }
-close $fh;
 
-my @buildorder = 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.
 
@@ -299,7 +323,9 @@ if (! -d "$localrepo/scratch") {
        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.
@@ -323,17 +349,24 @@ foreach my $arch (@arches) {
                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);
+               my $scratchdir = "$localrepo/scratch/$name-$distro-$arch";
+               mkdir $scratchdir;
+
+               if (system ("mock -r $distro-$arch --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";
+                   createrepo ($arch, $distro);
+               }
+               else {
+                   push @errors, "$name-$distro-$arch";
+                   print STDERR "Build failed, return code $?\nLeaving the logs in $scratchdir\n";
+                   die unless $keepgoing;
+               }
            }
            else
            {
@@ -342,3 +375,11 @@ foreach my $arch (@arches) {
        }
     }
 }
+
+if (@errors) {
+    print "\n\n\nBuild failed for the following packages:\n";
+    print "  $_\n" foreach @errors;
+    exit 1
+}
+
+exit 0