Fix a problem where smock forgot about packages which didn't have a dependency relati...
[fedora-mingw.git] / smock / smock.pl
index ed32162..34a5ec0 100755 (executable)
@@ -27,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;
 
@@ -34,6 +36,8 @@ GetOptions (
     "arch=s" => \@arches,
     "distro=s" => \@distros,
     "localrepo=s" => \$localrepo,
+    "dryrun" => \$dryrun,
+    "chain" => \$chain,
     "help|?" => \$help,
     "man" => \$man
     ) or pod2usage (2);
@@ -87,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
@@ -167,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;
 }
 
@@ -183,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.
 
@@ -229,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";