smock: add --overwrite option
[fedora-mingw.git] / smock / smock.pl
index 76a1a54..d0d0042 100755 (executable)
@@ -25,25 +25,27 @@ use Pod::Usage;
 use File::Temp qw(tempfile);
 
 my @arches = ();
+my $chain = 0;
 my @distros = ();
-my $suffix = "";
-my $localrepo = $ENV{HOME} . "/public_html/smock/yum";
 my $dryrun = 0;
-my $keepgoing = 0;
-my $chain = 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,
-    "suffix=s" => \$suffix,
-    "localrepo=s" => \$localrepo,
     "dryrun" => \$dryrun,
-    "keepgoing" => \$keepgoing,
-    "chain" => \$chain,
     "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;
@@ -75,7 +77,7 @@ must bump the release number or delete the binary RPM from the
 localrepo directory).
 
 B<NOTE:> 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
 
@@ -86,20 +88,26 @@ 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<http://fedoraproject.org/wiki/Koji/UsingKoji#Chained_builds>
+
 =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<--localrepo>
-
-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<--help>
+
+Print this help.
+
 =item B<--keepgoing>
 
 Don't exit if a package fails, but keep building.
@@ -110,11 +118,22 @@ be rebuilt because of an error.
 
 However, it is very useful.
 
-=item B<--chain>
+=item B<--localrepo>
 
-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>
+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>
 
@@ -157,8 +176,8 @@ sub get_lines
     open PIPE, "$_[0] |" or die "$_[0]: $!";
     my @lines;
     foreach (<PIPE>) {
-       chomp;
-       push @lines, $_;
+        chomp;
+        push @lines, $_;
     }
     close PIPE;
     return @lines;
@@ -180,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
     }
 }
 
@@ -196,21 +215,21 @@ 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;
 }
@@ -218,7 +237,7 @@ sub dependency_in
 foreach my $name (keys %srpms) {
     my @buildrequires = @{$srpms{$name}->{buildrequires}};
     @buildrequires =
-       grep { $_ = dependency_in ($_, keys %srpms) } @buildrequires;
+        grep { $_ = dependency_in ($_, keys %srpms) } @buildrequires;
     $srpms{$name}{buildrequires} = \@buildrequires;
 }
 
@@ -233,14 +252,14 @@ sub tsort
     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"
+        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;
 
@@ -261,24 +280,24 @@ if ($chain) {
     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";
 
@@ -289,7 +308,7 @@ if ($chain) {
 
 if ($dryrun) {
     foreach (@buildorder) {
-       print "$_\n";
+        print "$_\n";
     }
 
     exit 0
@@ -302,7 +321,7 @@ sub my_mkdir
     local $_ = $_[0];
 
     if (! -d $_) {
-       mkdir ($_, 0755) or die "mkdir $_: $!"
+        mkdir ($_, 0755) or die "mkdir $_: $!"
     }
 }
 
@@ -315,19 +334,19 @@ 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 -rf $localrepo/scratch/*";
@@ -338,51 +357,55 @@ my @errors = ();
 # 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);
-
-               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";
-           }
-       }
+        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";
+            }
+        }
     }
 }