smock: substitute tab with 4 blanks for uniformity
[fedora-mingw.git] / smock / smock.pl
index 34a5ec0..fd5f17a 100755 (executable)
@@ -26,8 +26,10 @@ use File::Temp qw(tempfile);
 
 my @arches = ();
 my @distros = ();
 
 my @arches = ();
 my @distros = ();
+my $suffix = "";
 my $localrepo = $ENV{HOME} . "/public_html/smock/yum";
 my $dryrun = 0;
 my $localrepo = $ENV{HOME} . "/public_html/smock/yum";
 my $dryrun = 0;
+my $keepgoing = 0;
 my $chain = 0;
 my $help = 0;
 my $man = 0;
 my $chain = 0;
 my $help = 0;
 my $man = 0;
@@ -35,8 +37,10 @@ my $man = 0;
 GetOptions (
     "arch=s" => \@arches,
     "distro=s" => \@distros,
 GetOptions (
     "arch=s" => \@arches,
     "distro=s" => \@distros,
+    "suffix=s" => \$suffix,
     "localrepo=s" => \$localrepo,
     "dryrun" => \$dryrun,
     "localrepo=s" => \$localrepo,
     "dryrun" => \$dryrun,
+    "keepgoing" => \$keepgoing,
     "chain" => \$chain,
     "help|?" => \$help,
     "man" => \$man
     "chain" => \$chain,
     "help|?" => \$help,
     "man" => \$man
@@ -96,12 +100,27 @@ 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.
 
 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
 format for chain building.  See:
 L<http://fedoraproject.org/wiki/Koji/UsingKoji#Chained_builds>
 
 =item B<--chain>
 
 Don't run any commands, just print the packages in the correct
 format for chain building.  See:
 L<http://fedoraproject.org/wiki/Koji/UsingKoji#Chained_builds>
 
+=item B<--suffix>
+
+Append a suffix to the mock configuration file in order to use
+a custom one.
+
 =back
 
 =cut
 =back
 
 =cut
@@ -138,8 +157,8 @@ sub get_lines
     open PIPE, "$_[0] |" or die "$_[0]: $!";
     my @lines;
     foreach (<PIPE>) {
     open PIPE, "$_[0] |" or die "$_[0]: $!";
     my @lines;
     foreach (<PIPE>) {
-       chomp;
-       push @lines, $_;
+    chomp;
+    push @lines, $_;
     }
     close PIPE;
     return @lines;
     }
     close PIPE;
     return @lines;
@@ -161,11 +180,11 @@ foreach my $srpm (@srpms) {
     #print "  buildrequires = ", join (",", @buildrequires), "\n";
 
     $srpms{$name} = {
     #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
     }
 }
 
     }
 }
 
@@ -177,49 +196,61 @@ sub is_member_of
     my $item = shift;
 
     foreach (@_) {
     my $item = shift;
 
     foreach (@_) {
-       return 1 if $item eq $_;
+    return 1 if $item eq $_;
     }
     0;
 }
 
 sub dependency_in
 {
     }
     0;
 }
 
 sub dependency_in
 {
-    my $dep = shift;           # eg. dbus-devel
+    my $dep = shift;        # eg. dbus-devel
 
     while ($dep) {
 
     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;
 }
 
     }
     0;
 }
 
-my @names = sort keys %srpms;
-foreach my $name (@names) {
+foreach my $name (keys %srpms) {
     my @buildrequires = @{$srpms{$name}->{buildrequires}};
     my @buildrequires = @{$srpms{$name}->{buildrequires}};
-    @buildrequires = grep { $_ = dependency_in ($_, @names) } @buildrequires;
+    @buildrequires =
+    grep { $_ = dependency_in ($_, keys %srpms) } @buildrequires;
     $srpms{$name}{buildrequires} = \@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.
+
+sub tsort
+{
+    my @names = @_;
 
 
-my ($fh, $filename) = tempfile ();
+    my ($fh, $filename) = tempfile ();
 
 
-foreach my $name (@names) {
+    foreach my $name (@names) {
     my @buildrequires = @{$srpms{$name}->{buildrequires}};
     foreach (@buildrequires) {
     my @buildrequires = @{$srpms{$name}->{buildrequires}};
     foreach (@buildrequires) {
-       print $fh "$_ $name\n"
+        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.
 
 
 # With --chain flag we print the packages in groups for chain building.
 
@@ -230,24 +261,24 @@ if ($chain) {
     print 'make chain-build CHAIN="';
 
     foreach $name (@buildorder) {
     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 ";
+    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";
 
     }
     print "\"\n";
 
@@ -258,7 +289,7 @@ if ($chain) {
 
 if ($dryrun) {
     foreach (@buildorder) {
 
 if ($dryrun) {
     foreach (@buildorder) {
-       print "$_\n";
+    print "$_\n";
     }
 
     exit 0
     }
 
     exit 0
@@ -271,7 +302,7 @@ sub my_mkdir
     local $_ = $_[0];
 
     if (! -d $_) {
     local $_ = $_[0];
 
     if (! -d $_) {
-       mkdir ($_, 0755) or die "mkdir $_: $!"
+    mkdir ($_, 0755) or die "mkdir $_: $!"
     }
 }
 
     }
 }
 
@@ -284,61 +315,81 @@ sub createrepo
     my_mkdir "$localrepo/$distro/src";
     my_mkdir "$localrepo/$distro/src/SRPMS";
     system ("cd $localrepo/$distro/src && rm -rf repodata && createrepo -q .") == 0
     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
 
     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"
 }
 
 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) {
 
 # 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)
+        {
+        # 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