Fix a problem where smock forgot about packages which didn't have a dependency relati...
[fedora-mingw.git] / smock / smock.pl
index b33d07c..34a5ec0 100755 (executable)
@@ -2,6 +2,21 @@
 #
 # SMOCK - Simpler Mock
 # by Dan Berrange and Richard W.M. Jones.
+# Copyright (C) 2008 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 use strict;
 
@@ -12,6 +27,8 @@ use File::Temp qw(tempfile);
 my @arches = ();
 my @distros = ();
 my $localrepo = $ENV{HOME} . "/public_html/smock/yum";
+my $dryrun = 0;
+my $chain = 0;
 my $help = 0;
 my $man = 0;
 
@@ -19,6 +36,8 @@ GetOptions (
     "arch=s" => \@arches,
     "distro=s" => \@distros,
     "localrepo=s" => \$localrepo,
+    "dryrun" => \$dryrun,
+    "chain" => \$chain,
     "help|?" => \$help,
     "man" => \$man
     ) or pod2usage (2);
@@ -72,6 +91,17 @@ You can list this option several times to build several distributions.
 
 Local repository.  Defaults to C<$HOME/public_html/smock/yum>
 
+=item B<--dryrun>
+
+Don't run any commands, just print the packages in the order
+in which they must be built.
+
+=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>
+
 =back
 
 =cut
@@ -152,10 +182,24 @@ sub is_member_of
     0;
 }
 
-my @names = keys %srpms;
+sub dependency_in
+{
+    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;
+    }
+    0;
+}
+
+my @names = sort keys %srpms;
 foreach my $name (@names) {
     my @buildrequires = @{$srpms{$name}->{buildrequires}};
-    @buildrequires = grep { is_member_of ($_, @names) } @buildrequires;
+    @buildrequires = grep { $_ = dependency_in ($_, @names) } @buildrequires;
     $srpms{$name}{buildrequires} = \@buildrequires;
 }
 
@@ -168,14 +212,57 @@ foreach my $name (@names) {
     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;
 
 my @buildorder = get_lines "tsort $filename";
 
-#foreach (@buildorder) {
-#    print "$_\n";
-#}
+# 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
+}
+
+# With --dryrun flag we just print the packages in build order then exit.
+
+if ($dryrun) {
+    foreach (@buildorder) {
+       print "$_\n";
+    }
+
+    exit 0
+}
 
 # Now we can build each SRPM.
 
@@ -214,15 +301,17 @@ if (! -d "$localrepo/scratch") {
 
 system "rm -f $localrepo/scratch/*";
 
-foreach my $name (@buildorder) {
-    my $version = $srpms{$name}->{version};
-    my $release = $srpms{$name}->{release};
-    my $srpm_filename = $srpms{$name}->{filename};
+# 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"
+           $release =~ s/\.fc?\d+$//; # "1.fc9" -> "1"
 
-    foreach my $arch (@arches) {
-       foreach my $distro (@distros) {
            # Does the built (binary) package exist already?
            my $pattern = "$localrepo/$distro/$arch/RPMS/$name-$version-$release.*.rpm";
            #print "pattern = $pattern\n";