source: rpmbuild-bot/rpmbuild-bot.sh@ 862

Last change on this file since 862 was 862, checked in by dmik, 9 years ago

rpmbuild-bot: Run rpmbuild only once for noarch-only specs.

It makes no sense to build noarch packages several times for different
architectures if there are no architecture specific pakgages. Unfortunately,
we cannot avoud duplicate noarch builds for specs with architecture
specific packages because rpmbuild doesn't seem to allow to exclude noarch
from the build.

Note that this revision also fixes a regression of building noarch-only
specs with rpmbuild-bot introduced somewhere in the past.

File size: 25.5 KB
Line 
1#!/bin/sh
2
3#
4# rpmbuild-bot.sh: RPM Build Bot version 1.1.0.
5#
6# Author: Dmitriy Kuminov <coding@dmik.org>
7#
8# This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
9# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
10#
11# Synopsis
12# --------
13#
14# This script performs a build of RPM packages from a given .spec file in
15# controlled environment to guarantee consistent results when building RPMs
16# different machines. It uses a separate file rpmbuild-bot-env.sh located
17# in the same directory to set up the environment and control the build
18# process. The main purpose of this script is to build RPM packages for a
19# specific distribution channel maintaining distribution-siecific rules.
20#
21# Usage
22# -----
23#
24# > rpmbuild-bot.sh SPEC[=VERSION]
25# > [ upload[=REPO] | test[=MODE] | clean[=test] |
26# > move[=FROM_REPO=TO_REPO] | remove[=REPO] ]
27# > [-f]
28#
29# MYAPP is the name of the RPM package spec file (extension is optional,
30# .spec is assumed). The spec file is searched in the SPECS directory of the
31# rpmbuild tree (usually $USER/rpmbuild/SPECS, rpmbuild --eval='%_specdir'
32# will show the exact location). This may be overriden by giving a spec file
33# with a path specification.
34#
35# The second argument defines the command to perform. The default command is
36# "build". The following sections will describe each command.
37#
38# Building packages
39# -----------------
40#
41# The "build" is the main command which is used to generate packages for
42# distribution. This command does the following:
43#
44# 1. Build all RPM packages for all architectures specified in
45# $RPMBUILD_BOT_ARCH_LIST. The packages are stored in the RPMS
46# directory of the rpmbuild tree.
47# 2. Build the source RPM. Stored in the SRPMS directory.
48# 3. Create a ZIP package from the RPMs for the architecture specified
49# last in $RPMBUILD_BOT_ARCH_LIST.
50#
51# The build process for each architecture is stored in a log file in the logs
52# directory of the rpmbuild tree (`rpmbuild --eval='%_topdir'/logs`). Creation
53# of the source RPM and ZIP files is also logged, into separate log files.
54#
55# The "build" command will fail if the log directory contains files from a
56# successfull run of another "build" command for this package. This is to
57# prevent overwriting successfully built packages that are not yet uploaded to
58# the distribution repository (see the "upload" command). You should either
59# run the "upload" command or use the -f option to force removal of these
60# log files and the corresponding package files if you are absolutely sure they
61# should be discarded.
62#
63# The "build" command will also check if there is a directory named SPEC in the
64# same directory where the given .spec file resides. If such a directory
65# exists, all files in it are assumed to be auxiliary source files used by the
66# .spec file via SourceN: directives. These files will be automatically copied
67# to the SOURCES directory in the rpmbuild tree befure starting the build
68# process.
69#
70# Doing test builds
71# -----------------
72#
73# The "test" command is used to build packages for one architecture for testing
74# purposes. In this more, neither the source RPM nor the ZIP file is created.
75# Also, a special option is automatically passed to rpmbuild to clear the %dist
76# variable to indicate that this is a local, non-distribution build. Such
77# packages will always be "older" than the corresponding builds with %dist
78# so that they will be automatically updated on the next yum update to the
79# %dist ones. The packages built in "test" mode are NOT intended for
80# distribution, they are meant only for local testing before performing the
81# full build of everything.
82#
83# It is possible to configure which steps of the build to perform using the MODE
84# parameter to the "test" command which may take one of the following values:
85#
86# prep Execute the %prep section of the spec file only.
87# build Execute the %build section only (requres %prep to be executed
88# before). May be run multiple times.
89# install Execute the %install sectuion only (requires "prep" and "build"
90# to be executed before). May be run multiple times.
91# pack Create the RPM packages (requires "prep", "build" and "install"
92# to be executed before). Note that this step will also execute
93# the %clean section so that a new "install" execution is
94# necessary for "pack" to succeed.
95#
96# When no MODE parameter is given, all steps are executed in a proper order.
97#
98# The results of the "test" command are stored in a log file in the logs/test
99# directory of the rpmbuild tree. The previous log file, if any, is given a .bak
100# extension (the previous .bak file will be deleted).
101#
102# The "test" command will copy auxiliary source files for the .spec file, if any,
103# to the proper location before rpmbuild execution -- the same way the "build"
104# command does it.
105#
106# Uploading packages
107# ------------------
108#
109# The "upload" command will upload the packages built with the "build"
110# command to the official distribution channel configured in
111# rpmbuild-bot-env.sh. The REPO parameter specifies one of the configured
112# repositories. When REPO is not given, the default repository is used
113# (usually experimental or similar).
114#
115# Note that the "upload" command needs log files from the "build" command
116# and will fail otherwise.
117#
118# Upon successful completion, the "upload" command will remove all uploaded
119# RPM and ZIP packages and will move all "build" log files to logs/archive.
120#
121# Cleaning packages
122# -----------------
123#
124# The "clean" command will delete packages built with the "build" command
125# and their log files without uploading them to a repository. This is useful
126# when the successful build needs to be canceled for some reason (wrong source
127# tree state, wrong patches etc.). Note that normally you don't need to use
128# this command; it's an emergency-only tool.
129#
130# The "clean" command needs log files from the "build" command and will fail
131# otherwise.
132#
133# If the "clean" command is given a "test" parameter, it will clean up the
134# results of the "test" command instead of "build". The log file from the
135# "test" command needs to be present or the command will fail.
136#
137# Moving packages between repositories
138# ------------------------------------
139#
140# The "move" command allows to move a particular version of the packages
141# built with the "build" command and uploaded with the "upload" command from one
142# repository to another one. The "move" command is normally used to move
143# packages from a test repository to a production one when they are ready for
144# wide distribution.
145#
146# The "move" command needs log files from the "build" and "upload" commands
147# and will fail otherwise. It also requires the VERSION parameter for the SPEC
148# argument to be given (to specify the version of the packages to remove) and
149# requires the FROM_REPO=TO_REPO parameter itself to specify the source
150# repository and the target repository, respectively.
151#
152# The log files from the "build" and "upload" commands are not removed by the
153# "move" command so it may be performed multiple times. The current location
154# of the packages is not tracked in the log files so the command will fail
155# if the source repository doesn't have the package files or if the target
156# repository already has them.
157#
158# Removing packages
159# -----------------
160#
161# The "remove" command allows to remove a particular version of the packages
162# built with the "build" command and uploaded with the "upload" command from a
163# repository. This is useful when the successful build needs to be canceled for
164# some reason (wrong source tree state, wrong patches etc.). Note that normally
165# you don't need to use this command; it's an emergency-only tool.
166#
167# The "remove" command needs log files from the "build" and "upload" commands
168# and will fail otherwise. It also requires the VERSION parameter for the SPEC
169# argument to be given (to specify the version of the packages to remove) and
170# accepts the REPO parameter itself just like the "upload" command does (to
171# specify a repository to remove the packages from).
172#
173# Note that the log files from the "build" and "upload" commands are also
174# removed by this command upon sucessful package removal.
175#
176# Return value
177# ------------
178#
179# The rpmbuild-bot.sh script will return a zero exit code upon successful
180# completion and non-zero otherwise. The script output and log files should be
181# inspected to check for a reason of the failure.
182#
183
184#
185# Helpers.
186#
187
188print_elapsed()
189{
190 # $1 = start timestamp, in seconds (as returned by `date +%s`)
191 # $2 = string containg \$e (will be replaced with the elapsed time)
192
193 [ -z "$1" -o -z "$2" ] && return
194
195 local e=$(($(date +%s) - $1))
196 local e_min=$(($e / 60))
197 local e_sec=$(($e % 60))
198 local e_hrs=$((e_min / 60))
199 e_min=$((e_min % 60))
200 e="${e_hrs}h ${e_min}m ${e_sec}s"
201
202 eval "echo \"$2\""
203}
204
205quit()
206{
207 if [ -n "$start_time" ] ; then
208 echo "Build ended on $(date -R)."
209 if [ $1 = 0 ] ; then
210 print_elapsed start_time "Build succeeded (took \$e)."
211 else
212 print_elapsed start_time "Build failed (took \$e)."
213 fi
214 fi
215 exit $1
216}
217
218run()
219{
220 "$@"
221 local rc=$?
222 if test $rc != 0 ; then
223 echo "ERROR: The following command failed with error code $rc:"
224 echo $@
225 quit $rc
226 fi
227}
228
229log_run()
230{
231 log="$1"
232 shift
233 rm -f "$log"
234 "$@" >"$log" 2>&1
235 local rc=$?
236 if test $rc != 0 ; then
237 echo "ERROR: The following command failed with error code $rc:"
238 echo $@
239 echo "You will find more information in file '$log'."
240 echo "Here are the last 10 lines of output:"
241 echo "------------------------------------------------------------------------------"
242 tail "$log" -n 10
243 echo "------------------------------------------------------------------------------"
244 quit $rc
245 fi
246}
247
248warn()
249{
250 echo "WARNING: $1"
251}
252
253die()
254{
255 echo "ERROR: $1"
256 quit 1
257}
258
259check_dir_var()
260{
261 eval local val="\$$1"
262 [ -n "$val" ] || die "$1 is empty."
263 [ -d "$val" ] || die "$1 is '$val', not a valid directory."
264}
265
266read_file_list()
267{
268 # $1 = file list filename
269 # $2 = var name where to save the list of read file names (optional)
270 # $3 = function name to call for each file (optional), it may assign a new
271 # file name to $file and also set $file_pre and $file_post that will
272 # be prepended and appended to $file when saving it to the list in $2
273 # (but not when checking for file existence and timestamp)
274
275 local list="$1"
276 local _read_file_list_ret=
277
278 # Check timestamps.
279 while read l; do
280 local file_pre=
281 local file_post=
282 local file="${l#*|}"
283 local ts="${l%%|*}"
284 [ "$file" = "$ts" ] && die "Line '$l' in '$list' does not contain timestamps."
285 [ -n "$3" ] && eval $3
286 [ -f "$file" ] || die "File '$file' is not found."
287 echo "Checking timestamp of $file..."
288 local act_ts=`stat -c '%Y' "$file"`
289 # Drop fractional part of seconds reported by older coreutils
290 ts="${ts%%.*}"
291 act_ts="${act_ts%%.*}"
292 if [ "$ts" != "$act_ts" ] ; then
293 die "Recorded timestamp $ts doesn't match actual timestamp $act_ts for '$file'."
294 fi
295 _read_file_list_ret="$_read_file_list_ret${_read_file_list_ret:+ }$file_pre$file$file_post"
296 done < "$list"
297 # Return the files (if requested).
298 [ -n "$2" ] && eval "$2=\$_read_file_list_ret"
299}
300
301usage()
302{
303 echo "Usage:"
304 sed -n -e "s/rpmbuild-bot.sh/${0##*/}/g" -e 's/^# > / /p' < "$0"
305 quit 255
306}
307
308sync_aux_src()
309{
310 [ -n "$src_dir" ] || die "src_dir is empty."
311 [ -n "$spec_full" ] || die "spec_full is empty."
312
313 # Aux source dir is expected along the .spec file.
314 local aux_src_dir="${spec_full%.spec}"
315
316 # Return early if there is no aux source dir.
317 [ -d "$aux_src_dir" ] || return
318
319 echo "Copying auxiliary sources for '$spec' to $src_dir..."
320
321 for f in "$aux_src_dir"/* ; do
322 local ts=`stat -c '%Y' "$f"`
323 local trg_ts=
324 local trg_f="$src_dir/${f##*/}"
325 [ -f "$trg_f" ] && trg_ts=`stat -c '%Y' "$trg_f"`
326 if [ "$ts" != "$trg_ts" ] ; then
327 echo "Copying $f..."
328 run cp -p "$f" "$trg_f"
329 fi
330 done
331}
332
333build_cmd()
334{
335 local spec_name_=`echo "${spec_name}" | tr - _`
336 eval local arch_list="\${RPMBUILD_BOT_ARCH_LIST_${spec_name_}}"
337 [ -z "$arch_list" ] && arch_list="${RPMBUILD_BOT_ARCH_LIST}"
338
339 local base_arch="${arch_list##* }"
340
341 echo "Spec file: $spec_full"
342 echo "Targets: $arch_list + SRPM + ZIP ($base_arch)"
343
344 sync_aux_src
345
346 if [ -f "$spec_list" ] ; then
347 if [ -z "$force" ] ; then
348 die "File '$spec_list' already exists.
349This file indicates a successful build that was not yet uploaded.
350Either run the '"'upload'"' command to upload the generated RPM and ZIP
351packages to the distribution repository or use the -f option to
352force their removal if you are sure they should be discarded."
353 fi
354
355 echo "Detected successful build in $spec_list, cleaning up due to -f option..."
356 local files=
357 read_file_list "$spec_list" files
358 for f in $files; do
359 echo "Removing $f..."
360 run rm -f "$f"
361 done
362 unset files
363
364 echo "Removing $log_base.*.log and .list files..."
365 rm -f "$log_base".*.log "$log_base".*.list "$log_base".list
366 fi
367
368 local noarch_only=
369 local start_time=
370
371 # Generate RPMs (note that base_arch always goes first).
372 for arch in $base_arch ${arch_list%${base_arch}} ; do
373 echo "Creating RPMs for '$arch' target (logging to $log_base.$arch.log)..."
374 start_time=$(date +%s)
375 log_run "$log_base.$arch.log" rpmbuild.exe --target=$arch -bb "$spec_full"
376 print_elapsed start_time "Completed in \$e."
377 if ! grep -q "^Wrote: \+.*\.$arch\.rpm$" "$log_base.$arch.log" ; then
378 if ! grep -q "^Wrote: \+.*\.noarch\.rpm$" "$log_base.$arch.log" ; then
379 die "Target '$arch' did not produce any RPMs."
380 fi
381 noarch_only=1
382 echo "Skipping other targets because '$arch' produced only 'noarch' RPMs."
383 break
384 fi
385 done
386
387 # Generate SRPM.
388 echo "Creating SRPM (logging to $log_base.srpm.log)..."
389 start_time=$(date +%s)
390 log_run "$log_base.srpm.log" rpmbuild -bs "$spec_full"
391 print_elapsed start_time "Completed in \$e."
392
393 # Find SRPM file name in the log.
394 local src_rpm=`grep "^Wrote: \+.*\.src\.rpm$" "$log_base.srpm.log" | sed -e "s#^Wrote: \+##g"`
395 [ -n "$src_rpm" ] || die "Cannot find .src.rpm file name in '$log_base.srpm.log'."
396
397 # Find package version.
398 local ver_full="${src_rpm%.src.rpm}"
399 ver_full="${ver_full##*/}"
400 [ "${ver_full%%-[0-9]*}" = "$spec_name" ] || die \
401"SRPM name '${src_rpm##*/}' does not match .spec name ('$spec_name').
402Either rename '$spec_name.spec' to '${ver_full%%-[0-9]*}.spec' or set 'Name:' tag to '$spec_name'."
403 ver_full="${ver_full#${spec_name}-}"
404 [ -n "$ver_full" ] || die "Cannot deduce package version from '$src_rpm'."
405
406 # Find all RPM packages for the base arch (note the quotes around `` - it's to preserve multi-line result).
407 local rpms="`grep "^Wrote: \+.*\.\($base_arch\.rpm\|noarch\.rpm\)$" "$log_base.$base_arch.log" | sed -e "s#^Wrote: \+##g"`"
408 [ -n "$rpms" ] || die "Cannot find .$base_arch.rpm/.noarch.rpm file names in '$log_base.base_arch.log'."
409
410 local ver_full_zip=`echo $ver_full | tr . _`
411 local zip="$zip_dir/$spec_name-$ver_full_zip.zip"
412
413 # Generate ZIP.
414 echo "Creating ZIP (logging to $log_base.zip.log)..."
415 start_time=$(date +%s)
416 create_zip()
417 {(
418 run cd "$zip_dir"
419 rm -r "@unixroot" 2> /dev/null
420 # Note no quoters around $rpms - it's to split at EOL.
421 for f in $rpms ; do
422 echo "Unpacking $f..."
423 run rpm2cpio "$f" | cpio -idm
424 done
425 rm -f "$zip" 2> /dev/null
426 echo "Creating '$zip'..."
427 run zip -mry9 "$zip" "@unixroot"
428 )}
429 log_run "$log_base.zip.log" create_zip
430 print_elapsed start_time "Completed in \$e."
431
432 local ver_list="$log_base.$ver_full.list"
433
434 # Generate list of all generated packages for further reference.
435 echo "Creating list file ($ver_list)..."
436 rm -f "$ver_list"
437 echo `stat -c '%Y' "$src_rpm"`"|$src_rpm" > "$ver_list"
438 echo `stat -c '%Y' "$zip"`"|$zip" >> "$ver_list"
439 # Save base arch RPMs.
440 for f in $rpms ; do
441 echo `stat -c '%Y' "$f"`"|$f" >> "$ver_list"
442 done
443 # Save other arch RPMs (only if there is anything but noarch).
444 if [ -z "$noarch_only" ] ; then
445 for arch in ${arch_list%${base_arch}} ; do
446 rpms="`grep "^Wrote: \+.*\.$arch\.rpm$" "$log_base.$arch.log" | sed -e "s#^Wrote: \+##g"`"
447 [ -n "$rpms" ] || die "Cannot find .$arch.rpm file names in '$log_base.arch.log'."
448 for f in $rpms ; do
449 echo `stat -c '%Y' "$f"`"|$f" >> "$ver_list"
450 done
451 done
452 fi
453
454 # Everything succeeded. Symlink the list file so that "upload" can find it.
455 run ln -s "${ver_list##*/}" "$log_base.list"
456}
457
458test_cmd()
459{
460 echo "Spec file: $spec_full"
461
462 sync_aux_src
463
464 local base_arch="${RPMBUILD_BOT_ARCH_LIST##* }"
465 local cmds=
466
467 [ -z "$command_arg" ] && command_arg="all"
468
469 case "$command_arg" in
470 all)
471 cmds="$cmds -bb"
472 ;;
473 prep)
474 cmds="$cmds -bp --short-circuit"
475 ;;
476 build)
477 cmds="$cmds -bc --short-circuit"
478 ;;
479 install)
480 cmds="$cmds -bi --short-circuit"
481 ;;
482 pack)
483 cmds="$cmds -bb --short-circuit"
484 ;;
485 *)
486 die "Invalid test build sub-command '$command_arg'."
487 ;;
488 esac
489
490 local log_file="$log_dir/test/$spec_name.log"
491
492 if [ -f "$log_file" ] ; then
493 rm -f "$log_file.bak"
494 run mv "$log_file" "$log_file.bak"
495 fi
496
497 echo "Doing test RPM build for '$base_arch' target (logging to $log_file)..."
498 log_run "$log_file" rpmbuild.exe "--define=dist %nil" --target=$base_arch $cmds $spec_full
499
500 # Show the generated RPMs when appropriate.
501 if [ "$command_arg" = "all" -o "$command_arg" = "pack" ] ; then
502 # Find all RPM packages for the base arch (note the quotes around `` - it's to preserve multi-line result).
503 local rpms="`grep "^Wrote: \+.*\.\($base_arch\.rpm\|noarch\.rpm\)$" "$log_file" | sed -e "s#^Wrote: \+##g"`"
504 if [ -n "$rpms" ] ; then
505 echo "Successfully generated the following RPMs:"
506 for f in $rpms; do
507 echo "$f"
508 done
509 else
510 warn "Cannot find .$base_arch.rpm/.noarch.rpm file names in '$log_file'."
511 fi
512 fi
513}
514
515repo_dir_for_file()
516{
517 # $1 = input file name
518 # $2 = var name to save dir to
519
520 [ -n "$1" -a -n "$2" ] || die "Invalid arguments."
521
522 local _repo_dir_for_file_ret=
523 case "$1" in
524 *.src.rpm)
525 eval _repo_dir_for_file_ret="$RPMBUILD_BOT_UPLOAD_REPO_LAYOUT_srpm"
526 ;;
527 *.*.rpm)
528 local arch="${1%.rpm}"
529 arch="${arch##*.}"
530 [ -n "$arch" ] || die "No arch spec in file name '$1'."
531 eval _repo_dir_for_file_ret="$RPMBUILD_BOT_UPLOAD_REPO_LAYOUT_rpm"
532 ;;
533 *.zip)
534 eval _repo_dir_for_file_ret="$RPMBUILD_BOT_UPLOAD_REPO_LAYOUT_zip"
535 ;;
536 esac
537
538 eval "$2=\$_repo_dir_for_file_ret"
539}
540
541upload_cmd()
542{
543 # Check settings.
544 test -n "$RPMBUILD_BOT_UPLOAD_REPO_LIST" || die "RPMBUILD_BOT_UPLOAD_REPO_LIST is empty."
545
546 local repo="$command_arg"
547 [ -z "$repo" ] && repo="${RPMBUILD_BOT_UPLOAD_REPO_LIST%% *}"
548
549 check_dir_var "RPMBUILD_BOT_UPLOAD_${repo}_DIR"
550
551 eval local base="\$RPMBUILD_BOT_UPLOAD_${repo}_DIR"
552
553 [ -f "$spec_list" ] || die \
554"File '$spec_list' is not found.
555You may need to build the packages using the 'build' command."
556
557 local files=
558 read_file_list "$spec_list" files
559 for f in $files; do
560 local d=
561 repo_dir_for_file "$f" d
562 [ -n "$d" ] || die "Unsupported file name '$f' in '$spec_list'."
563 [ -d "$d" ] || die "'$d' is not a directory."
564 [ -f "$d/${f##*/}" -a -z "$force" ] && die \
565"File '$d/${f##*/}' already exists.
566Use the -f option to force uploading if you are sure the existing
567packages in the repository should be discarded."
568 echo "Copying $f to $d..."
569 run cp -p "$f" "$d"
570 done
571
572 # On success, delete the uploaded packages and archive log files.
573 for f in $files; do
574 echo "Removing $f..."
575 run rm -f "$f"
576 done
577
578 # Note: versioned .list file will remain in archive forever (for further reference).
579 echo "Removing old '$spec_name' logs from $log_dir/archive..."
580 rm -f "$log_dir/archive/$spec_name".*.log "$log_dir/archive/$spec_name".list
581 echo "Moving '$spec_name' logs to $log_dir/archive..."
582 run mv "$log_base".*.log "$log_base".*.list "$log_base".list "$log_dir/archive/"
583}
584
585clean_cmd()
586{
587 if [ "$command_arg" = "test" ] ; then
588 # Cleanup after "test" command.
589 local base_arch="${RPMBUILD_BOT_ARCH_LIST##* }"
590 local log_file="$log_dir/test/$spec_name.log"
591
592 [ -f "$log_file" ] || die "File '$test_log' is not found."
593
594 # Find all RPM packages for the base arch (note the quotes around `` - it's to preserve multi-line result).
595 local rpms="`grep "^Wrote: \+.*\.\($base_arch\.rpm\|noarch\.rpm\)$" "$log_file" | sed -e "s#^Wrote: \+##g"`"
596 if [ -n "$rpms" ] ; then
597 for f in $rpms; do
598 echo "Removing $f..."
599 run rm -f "$f"
600 done
601 echo "Removing $log_file[.bak]..."
602 run rm -f "$log_file" "$log_file".bak
603 else
604 die "Cannot find .$base_arch.rpm/.noarch.rpm file names in '$log_file'."
605 fi
606
607 return
608 fi
609
610 # Cleanup after "build command".
611 [ -f "$spec_list" ] || die \
612"File '$spec_list' is not found.
613You man need to build the packages using the 'build' command."
614
615 local files=
616 read_file_list "$spec_list" files
617
618 for f in $files; do
619 echo "Removing $f..."
620 run rm -f "$f"
621 done
622
623 echo "Removing '$spec_name' logs from $log_dir..."
624 rm -f "$log_base".*.log "$log_base".*.list "$log_base".list
625}
626
627move_cmd()
628{
629 # Check settings.
630 [ -n "$spec_ver" ] || die "SPEC parameter lacks version specification."
631
632 test -n "$RPMBUILD_BOT_UPLOAD_REPO_LIST" || die "RPMBUILD_BOT_UPLOAD_REPO_LIST is empty."
633
634 local from_repo="${command_arg%%=*}"
635 local to_repo="${command_arg#*=}"
636
637 [ -n "$from_repo" ] || die "FROM_REPO parameter is missing."
638 [ "$from_repo" = "$to_repo" ] && die "TO_REPO parameter is missing (or equals to FROM_REPO)."
639
640 check_dir_var "RPMBUILD_BOT_UPLOAD_${from_repo}_DIR"
641 check_dir_var "RPMBUILD_BOT_UPLOAD_${to_repo}_DIR"
642
643 local ver_list="$log_dir/archive/$spec_name.$spec_ver.list"
644 [ -f "$ver_list" ] || die "File '$ver_list' is not found."
645
646 eval local from_base="\$RPMBUILD_BOT_UPLOAD_${from_repo}_DIR"
647 eval local to_base="\$RPMBUILD_BOT_UPLOAD_${to_repo}_DIR"
648
649 local files=
650 read_file_list "$ver_list" files '
651local dir=
652local base="$from_base"; repo_dir_for_file "$file" dir; file="${dir}/${file##*/}"
653base="$to_base"; repo_dir_for_file "$file" dir; file_post=">${dir}"
654'
655 for f in $files; do
656 local from="${f%%>*}"
657 local to="${f#*>}"
658 echo "Moving $from to $to/..."
659 run mv "$from" "$to/"
660 done
661}
662
663remove_cmd()
664{
665 # Check settings.
666 [ -n "$spec_ver" ] || die "SPEC parameter lacks version specification."
667
668 test -n "$RPMBUILD_BOT_UPLOAD_REPO_LIST" || die "RPMBUILD_BOT_UPLOAD_REPO_LIST is empty."
669
670 local repo="$command_arg"
671 [ -z "$repo" ] && repo="${RPMBUILD_BOT_UPLOAD_REPO_LIST%% *}"
672
673 check_dir_var "RPMBUILD_BOT_UPLOAD_${repo}_DIR"
674
675 local ver_list="$log_dir/archive/$spec_name.$spec_ver.list"
676 [ -f "$ver_list" ] || die "File '$ver_list' is not found."
677
678 eval local base="\$RPMBUILD_BOT_UPLOAD_${repo}_DIR"
679
680 local files=
681 read_file_list "$ver_list" files 'local dir=; repo_dir_for_file $file dir; file="${dir}/${file##*/}"'
682
683 for f in $files; do
684 echo "Removing $f..."
685 run rm -f "$f"
686 done
687
688 echo "Removing $ver_list..."
689 run rm -f "$ver_list"
690
691 # Also remove the logs of last "build" if we are removing the last "build" package.
692 if [ -L "$log_dir/archive/$spec_name.list" -a \
693 `readlink "$log_dir/archive/$spec_name.list"` = "$spec_name.$spec_ver.list" ] ; then
694 echo "Removing '$spec_name' logs from $log_dir/archive..."
695 rm -f "$log_dir/archive/$spec_name".*.log "$log_dir/archive/$spec_name".list
696 fi
697}
698
699#
700# Main.
701#
702
703# Parse command line.
704while [ -n "$1" ] ; do
705 case "$1" in
706 -*)
707 options="$*"
708 while [ -n "$1" ] ; do
709 case "$1" in
710 -f) force="-f"
711 ;;
712 *) usage
713 ;;
714 esac
715 shift
716 done
717 break
718 ;;
719 *)
720 if [ -z "$spec" ] ; then
721 spec="$1"
722 else
723 command="$1"
724 fi
725 ;;
726 esac
727 shift
728done
729
730[ -n "$spec" ] || usage
731[ -z "$command" ] && command="build"
732
733spec_ver="${spec#*=}"
734spec="${spec%=*}"
735[ "$spec" = "$spec_ver" ] && spec_ver=
736
737command_name="${command%%=*}"
738command_arg="${command#*=}"
739[ "$command_name" = "$command_arg" ] && command_arg=
740
741need_spec_file=
742
743# Validate commands.
744case "$command_name" in
745 build|test)
746 need_spec_file=1
747 ;;
748 upload|clean|move|remove)
749 ;;
750 *) usage
751 ;;
752esac
753
754# Query all rpmbuild macros in a single run as it may be slow.
755eval `rpmbuild.exe --eval='rpmbuild_dir="%_topdir" ; spec_dir="%_specdir" ; src_dir="%_sourcedir"' | tr '\\\' /`
756
757[ -n "$rpmbuild_dir" -a -d "$rpmbuild_dir" ] || die "Falied to get %_topdir from rpmbuild or not directory ($rpmbuild_dir)."
758[ -n "$spec_dir" -a -d "$spec_dir" ] || die "Falied to get %_specdir from rpmbuild or not directory ($spec_dir)."
759[ -n "$src_dir" -a -d "$src_dir" ] || die "Falied to get %_sourcedir from rpmbuild or not directory ($src_dir)."
760
761log_dir="$rpmbuild_dir/logs"
762zip_dir="$rpmbuild_dir/zip"
763
764spec=`echo $spec | tr '\\\' /`
765
766spec_name="${spec##*/}"
767
768if [ "$spec_name" = "$spec" ] ; then
769 # No path information, use SPECS
770 spec_full="$spec_dir/${spec_name%.spec}.spec"
771else
772 # Has some path, use it.
773 spec_full="${spec%.spec}.spec"
774fi
775
776spec_name="${spec_name%.spec}"
777
778[ -z "$need_spec_file" -o -f "$spec_full" ] || die "Spec file '$spec_full' is not found."
779
780# Prepare some (non-rpmbuild-standard) directories.
781run mkdir -p "$log_dir"
782run mkdir -p "$log_dir/archive"
783run mkdir -p "$log_dir/test"
784run mkdir -p "$zip_dir"
785
786log_base="$log_dir/$spec_name"
787spec_list="$log_base.list"
788
789start_time=$(date +%s)
790
791echo "Build started on $(date -R)."
792echo "Package: $spec_name"
793echo "Command: $command $options"
794
795# Set up the rpmbuild-bot environment.
796. "${0%%.sh}-env.sh"
797
798# Check common settings.
799test -n "$RPMBUILD_BOT_ARCH_LIST" || die "RPMBUILD_BOT_ARCH_LIST is empty."
800
801run eval "${command_name}_cmd"
802
803quit 0
Note: See TracBrowser for help on using the repository browser.