4 # by Dan Berrange and Richard W.M. Jones.
10 use File::Temp qw(tempfile);
14 my $localrepo = $ENV{HOME} . "/public_html/smock/yum";
20 "distro=s" => \@distros,
21 "localrepo=s" => \$localrepo,
25 pod2usage (1) if $help;
26 pod2usage (-exitstatus => 0, -verbose => 2) if $man;
36 smock.pl --arch=i386 --arch=x86_64 --distro=fedora-10 list of SRPMs ...
40 This is a wrapper around I<mock> which lets you build a whole group of
41 mutually dependent SRPMs in one go.
43 The smock command will work out the correct order in which to build
44 the SRPMs, and makes the result of previous RPM builds available as
45 dependencies for later builds.
47 Smock also works incrementally. It won't rebuild RPMs which were
48 built already in a previous run, which means if a package fails to
49 build, you can just fix it and rerun the same smock command. (In the
50 unlikely case that you want to force smock to rebuild RPMs then you
51 must bump the release number or delete the binary RPM from the
54 B<NOTE:> Please read the README file first. You need to set up mock
55 and a web server before you can use this command.
63 Specify the architecture(s) to build, eg. i386, x86_64. You can
64 list this option several times to build several architectures.
68 Specify the distribution(s) to build, eg. fedora-9, fedora-10.
69 You can list this option several times to build several distributions.
73 Local repository. Defaults to C<$HOME/public_html/smock/yum>
82 die "smock: specify one or more architectures using --arch=<arch>\n"
86 die "smock: specify one or more distros using --distro=<distro>\n"
90 die "smock: specify one or more SRPMs to build on the command line\n"
93 # Resolve the names, dependency list, etc. of the SRPMs that were
98 open PIPE, "$_[0] |" or die "$_[0]: $!";
108 open PIPE, "$_[0] |" or die "$_[0]: $!";
119 foreach my $srpm (@srpms) {
120 my $name = get_one_line "rpm -q --qf '%{name}' -p '$srpm'";
121 my $version = get_one_line "rpm -q --qf '%{version}' -p '$srpm'";
122 my $release = get_one_line "rpm -q --qf '%{release}' -p '$srpm'";
124 my @buildrequires = get_lines "rpm -q --requires -p '$srpm' |
125 grep -Eo '^[^[:space:]]+'";
127 #print "Filename: $srpm\n";
128 #print " name = $name\n";
129 #print " version = $version\n";
130 #print " release = $release\n";
131 #print " buildrequires = ", join (",", @buildrequires), "\n";
137 buildrequires => \@buildrequires,
142 # We don't care about buildrequires unless they refer to other
143 # packages that we are building. So filter them on this condition.
150 return 1 if $item eq $_;
155 my @names = keys %srpms;
156 foreach my $name (@names) {
157 my @buildrequires = @{$srpms{$name}->{buildrequires}};
158 @buildrequires = grep { is_member_of ($_, @names) } @buildrequires;
159 $srpms{$name}{buildrequires} = \@buildrequires;
162 # Now sort the SRPMs into the correct order for building
164 my ($fh, $filename) = tempfile ();
166 foreach my $name (@names) {
167 my @buildrequires = @{$srpms{$name}->{buildrequires}};
168 foreach (@buildrequires) {
169 print $fh "$_ $name\n"
174 my @buildorder = get_lines "tsort $filename";
176 #foreach (@buildorder) {
180 # Now we can build each SRPM.
187 mkdir ($_, 0755) or die "mkdir $_: $!"
196 my_mkdir "$localrepo/$distro";
197 my_mkdir "$localrepo/$distro/src";
198 my_mkdir "$localrepo/$distro/src/SRPMS";
199 system ("cd $localrepo/$distro/src && rm -rf repodata && createrepo -q .") == 0
200 or die "createrepo failed: $?\n";
202 my_mkdir "$localrepo/$distro/$arch";
203 my_mkdir "$localrepo/$distro/$arch/RPMS";
204 my_mkdir "$localrepo/$distro/$arch/logs";
206 system ("cd $localrepo/$distro/$arch && rm -rf repodata && createrepo -q --exclude 'logs/*rpm' .") == 0
207 or die "createrepo failed: $?\n";
210 if (! -d "$localrepo/scratch") {
211 mkdir "$localrepo/scratch"
212 or die "mkdir $localrepo/scratch: $!\nIf you haven't set up a local repository yet, you must read the README file.\n";
215 system "rm -f $localrepo/scratch/*";
217 foreach my $name (@buildorder) {
218 my $version = $srpms{$name}->{version};
219 my $release = $srpms{$name}->{release};
220 my $srpm_filename = $srpms{$name}->{filename};
222 $release =~ s/\.fc?\d+$//; # "1.fc9" -> "1"
224 foreach my $arch (@arches) {
225 foreach my $distro (@distros) {
226 # Does the built (binary) package exist already?
227 my $pattern = "$localrepo/$distro/$arch/RPMS/$name-$version-$release.*.rpm";
228 #print "pattern = $pattern\n";
229 my @binaries = glob $pattern;
233 # Rebuild the package.
234 print "*** building $name-$version-$release $arch $distro ***\n";
236 createrepo ($arch, $distro);
237 system ("mock -r $distro-$arch --resultdir $localrepo/scratch $srpm_filename") == 0
238 or die "Build failed, return code $?\nLeaving the logs in $localrepo/scratch\n";
240 # Build was a success so move the final RPMs into the
241 # mock repo for next time.
242 system ("mv $localrepo/scratch/*.src.rpm $localrepo/$distro/src/SRPMS") == 0 or die "mv";
243 system ("mv $localrepo/scratch/*.rpm $localrepo/$distro/$arch/RPMS") == 0 or die "mv";
244 my_mkdir "$localrepo/$distro/$arch/logs/$name-$version-$release";
245 system ("mv $localrepo/scratch/*.log $localrepo/$distro/$arch/logs/$name-$version-$release/") == 0 or die "mv";
247 createrepo ($arch, $distro);
251 print "skipping $name-$version-$release $arch $distro\n";