4 # by Dan Berrange and Richard W.M. Jones.
5 # Copyright (C) 2008 Red Hat Inc.
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 use File::Temp qw(tempfile);
29 my $localrepo = $ENV{HOME} . "/public_html/smock/yum";
35 "distro=s" => \@distros,
36 "localrepo=s" => \$localrepo,
40 pod2usage (1) if $help;
41 pod2usage (-exitstatus => 0, -verbose => 2) if $man;
51 smock.pl --arch=i386 --arch=x86_64 --distro=fedora-10 list of SRPMs ...
55 This is a wrapper around I<mock> which lets you build a whole group of
56 mutually dependent SRPMs in one go.
58 The smock command will work out the correct order in which to build
59 the SRPMs, and makes the result of previous RPM builds available as
60 dependencies for later builds.
62 Smock also works incrementally. It won't rebuild RPMs which were
63 built already in a previous run, which means if a package fails to
64 build, you can just fix it and rerun the same smock command. (In the
65 unlikely case that you want to force smock to rebuild RPMs then you
66 must bump the release number or delete the binary RPM from the
69 B<NOTE:> Please read the README file first. You need to set up mock
70 and a web server before you can use this command.
78 Specify the architecture(s) to build, eg. i386, x86_64. You can
79 list this option several times to build several architectures.
83 Specify the distribution(s) to build, eg. fedora-9, fedora-10.
84 You can list this option several times to build several distributions.
88 Local repository. Defaults to C<$HOME/public_html/smock/yum>
97 die "smock: specify one or more architectures using --arch=<arch>\n"
101 die "smock: specify one or more distros using --distro=<distro>\n"
105 die "smock: specify one or more SRPMs to build on the command line\n"
108 # Resolve the names, dependency list, etc. of the SRPMs that were
113 open PIPE, "$_[0] |" or die "$_[0]: $!";
123 open PIPE, "$_[0] |" or die "$_[0]: $!";
134 foreach my $srpm (@srpms) {
135 my $name = get_one_line "rpm -q --qf '%{name}' -p '$srpm'";
136 my $version = get_one_line "rpm -q --qf '%{version}' -p '$srpm'";
137 my $release = get_one_line "rpm -q --qf '%{release}' -p '$srpm'";
139 my @buildrequires = get_lines "rpm -q --requires -p '$srpm' |
140 grep -Eo '^[^[:space:]]+'";
142 #print "Filename: $srpm\n";
143 #print " name = $name\n";
144 #print " version = $version\n";
145 #print " release = $release\n";
146 #print " buildrequires = ", join (",", @buildrequires), "\n";
152 buildrequires => \@buildrequires,
157 # We don't care about buildrequires unless they refer to other
158 # packages that we are building. So filter them on this condition.
165 return 1 if $item eq $_;
170 my @names = keys %srpms;
171 foreach my $name (@names) {
172 my @buildrequires = @{$srpms{$name}->{buildrequires}};
173 @buildrequires = grep { is_member_of ($_, @names) } @buildrequires;
174 $srpms{$name}{buildrequires} = \@buildrequires;
177 # Now sort the SRPMs into the correct order for building
179 my ($fh, $filename) = tempfile ();
181 foreach my $name (@names) {
182 my @buildrequires = @{$srpms{$name}->{buildrequires}};
183 foreach (@buildrequires) {
184 print $fh "$_ $name\n"
189 my @buildorder = get_lines "tsort $filename";
191 #foreach (@buildorder) {
195 # Now we can build each SRPM.
202 mkdir ($_, 0755) or die "mkdir $_: $!"
211 my_mkdir "$localrepo/$distro";
212 my_mkdir "$localrepo/$distro/src";
213 my_mkdir "$localrepo/$distro/src/SRPMS";
214 system ("cd $localrepo/$distro/src && rm -rf repodata && createrepo -q .") == 0
215 or die "createrepo failed: $?\n";
217 my_mkdir "$localrepo/$distro/$arch";
218 my_mkdir "$localrepo/$distro/$arch/RPMS";
219 my_mkdir "$localrepo/$distro/$arch/logs";
221 system ("cd $localrepo/$distro/$arch && rm -rf repodata && createrepo -q --exclude 'logs/*rpm' .") == 0
222 or die "createrepo failed: $?\n";
225 if (! -d "$localrepo/scratch") {
226 mkdir "$localrepo/scratch"
227 or die "mkdir $localrepo/scratch: $!\nIf you haven't set up a local repository yet, you must read the README file.\n";
230 system "rm -f $localrepo/scratch/*";
232 foreach my $name (@buildorder) {
233 my $version = $srpms{$name}->{version};
234 my $release = $srpms{$name}->{release};
235 my $srpm_filename = $srpms{$name}->{filename};
237 $release =~ s/\.fc?\d+$//; # "1.fc9" -> "1"
239 foreach my $arch (@arches) {
240 foreach my $distro (@distros) {
241 # Does the built (binary) package exist already?
242 my $pattern = "$localrepo/$distro/$arch/RPMS/$name-$version-$release.*.rpm";
243 #print "pattern = $pattern\n";
244 my @binaries = glob $pattern;
248 # Rebuild the package.
249 print "*** building $name-$version-$release $arch $distro ***\n";
251 createrepo ($arch, $distro);
252 system ("mock -r $distro-$arch --resultdir $localrepo/scratch $srpm_filename") == 0
253 or die "Build failed, return code $?\nLeaving the logs in $localrepo/scratch\n";
255 # Build was a success so move the final RPMs into the
256 # mock repo for next time.
257 system ("mv $localrepo/scratch/*.src.rpm $localrepo/$distro/src/SRPMS") == 0 or die "mv";
258 system ("mv $localrepo/scratch/*.rpm $localrepo/$distro/$arch/RPMS") == 0 or die "mv";
259 my_mkdir "$localrepo/$distro/$arch/logs/$name-$version-$release";
260 system ("mv $localrepo/scratch/*.log $localrepo/$distro/$arch/logs/$name-$version-$release/") == 0 or die "mv";
262 createrepo ($arch, $distro);
266 print "skipping $name-$version-$release $arch $distro\n";