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

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

rpmbuild-bot: Print elapsed time after each succeded step and overall.

The overall elapsed time is printed even on failure. Also the start and
end datetime of the overall build process is printed.

File size: 24.7 KB
RevLine 
[467]1#!/bin/sh
2
[518]3#
[749]4# rpmbuild-bot.sh: RPM Build Bot version 1.1.0.
[518]5#
[724]6# Author: Dmitriy Kuminov <coding@dmik.org>
[518]7#
[724]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.
[518]10#
[724]11# Synopsis
12# --------
13#
[728]14# This script performs a build of RPM packages from a given .spec file in
[724]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#
[738]24# > rpmbuild-bot.sh SPEC[=VERSION]
[765]25# > [ upload[=REPO] | test[=MODE] | clean[=test] |
26# > move[=FROM_REPO=TO_REPO] | remove[=REPO] ]
[738]27# > [-f]
[724]28#
[749]29# MYAPP is the name of the RPM package spec file (extension is optional,
[724]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#
[728]35# The second argument defines the command to perform. The default command is
[724]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#
[748]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#
[724]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
[765]84# parameter to the "test" command which may take one of the following values:
[724]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
[744]93# the %clean section so that a new "install" execution is
[724]94# necessary for "pack" to succeed.
95#
[765]96# When no MODE parameter is given, all steps are executed in a proper order.
[724]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#
[748]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#
[724]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
[765]111# rpmbuild-bot-env.sh. The REPO parameter specifies one of the configured
[724]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#
[738]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#
[739]130# The "clean" command needs log files from the "build" command and will fail
131# otherwise.
132#
[765]133# If the "clean" command is given a "test" parameter, it will clean up the
[739]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#
[765]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#
[738]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
[765]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).
[738]172#
[765]173# Note that the log files from the "build" and "upload" commands are also
174# removed by this command upon sucessful package removal.
[738]175#
[724]176# Return value
177# ------------
178#
179# The rpmbuild-bot.sh script will return a zero exit code upon successful
[749]180# completion and non-zero otherwise. The script output and log files should be
181# inspected to check for a reason of the failure.
[724]182#
[467]183
[724]184#
185# Helpers.
186#
187
[769]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
[467]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 $@
[769]225 quit $rc
[467]226 fi
227}
228
229log_run()
230{
231 log="$1"
232 shift
[768]233 rm -f "$log"
[724]234 "$@" >"$log" 2>&1
[467]235 local rc=$?
236 if test $rc != 0 ; then
237 echo "ERROR: The following command failed with error code $rc:"
238 echo $@
[724]239 echo "You will find more information in file '$log'."
240 echo "Here are the last 10 lines of output:"
[769]241 echo "------------------------------------------------------------------------------"
[724]242 tail "$log" -n 10
[769]243 echo "------------------------------------------------------------------------------"
244 quit $rc
[467]245 fi
246}
247
[724]248warn()
249{
250 echo "WARNING: $1"
251}
252
[467]253die()
254{
[724]255 echo "ERROR: $1"
[769]256 quit 1
[467]257}
258
[724]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}
[467]265
[737]266read_file_list()
267{
[765]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)
[737]274
[738]275 local list="$1"
[737]276 local _read_file_list_ret=
[738]277
[737]278 # Check timestamps.
279 while read l; do
[765]280 local file_pre=
281 local file_post=
[738]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."
[769]287 echo "Checking timestamp of $file..."
[738]288 local act_ts=`stat -c '%Y' "$file"`
289 if [ "$ts" != "$act_ts" ] ; then
290 die "Recorded timestamp $ts doesn't match actual timestamp $act_ts for '$file'."
[737]291 fi
[765]292 _read_file_list_ret="$_read_file_list_ret${_read_file_list_ret:+ }$file_pre$file$file_post"
[738]293 done < "$list"
[737]294 # Return the files (if requested).
295 [ -n "$2" ] && eval "$2=\$_read_file_list_ret"
296}
297
[724]298usage()
299{
[749]300 echo "Usage:"
301 sed -n -e "s/rpmbuild-bot.sh/${0##*/}/g" -e 's/^# > / /p' < "$0"
[769]302 quit 255
[724]303}
[467]304
[748]305sync_aux_src()
306{
307 [ -n "$src_dir" ] || die "src_dir is empty."
308 [ -n "$spec_full" ] || die "spec_full is empty."
309
310 # Aux source dir is expected along the .spec file.
311 local aux_src_dir="${spec_full%.spec}"
312
313 # Return early if there is no aux source dir.
314 [ -d "$aux_src_dir" ] || return
315
316 echo "Copying auxiliary sources for '$spec' to $src_dir..."
317
318 for f in "$aux_src_dir"/* ; do
319 local ts=`stat -c '%Y' "$f"`
320 local trg_ts=
321 local trg_f="$src_dir/${f##*/}"
322 [ -f "$trg_f" ] && trg_ts=`stat -c '%Y' "$trg_f"`
323 if [ "$ts" != "$trg_ts" ] ; then
324 echo "Copying $f..."
325 run cp -p "$f" "$trg_f"
326 fi
327 done
328}
329
[724]330build_cmd()
331{
332 local base_arch="${RPMBUILD_BOT_ARCH_LIST##* }"
333
334 echo "Spec file: $spec_full"
335 echo "Targets: $RPMBUILD_BOT_ARCH_LIST + SRPM + ZIP ($base_arch)"
336
[748]337 sync_aux_src
338
[724]339 if [ -f "$spec_list" ] ; then
340 if [ -z "$force" ] ; then
341 die "File '$spec_list' already exists.
342This file indicates a successful build that was not yet uploaded.
343Either run the '"'upload'"' command to upload the generated RPM and ZIP
344packages to the distribution repository or use the -f option to
345force their removal if you are sure they should be discarded."
346 fi
347
348 echo "Detected successful build in $spec_list, cleaning up due to -f option..."
[737]349 local files=
350 read_file_list "$spec_list" files
351 for f in $files; do
[724]352 echo "Removing $f..."
[737]353 run rm -f "$f"
354 done
355 unset files
[724]356
357 echo "Removing $log_base.*.log and .list files..."
358 rm -f "$log_base".*.log "$log_base".*.list "$log_base".list
359 fi
360
[769]361 local start_time=
362
[724]363 # Generate RPMs.
364 for arch in $RPMBUILD_BOT_ARCH_LIST ; do
365 echo "Creating RPMs for '$arch' target (logging to $log_base.$arch.log)..."
[769]366 start_time=$(date +%s)
[729]367 log_run "$log_base.$arch.log" rpmbuild.exe --target=$arch -bb "$spec_full"
[769]368 print_elapsed start_time "Completed in \$e."
[724]369 done
370
371 # Generate SRPM.
372 echo "Creating SRPM (logging to $log_base.srpm.log)..."
[769]373 start_time=$(date +%s)
[729]374 log_run "$log_base.srpm.log" rpmbuild -bs "$spec_full"
[769]375 print_elapsed start_time "Completed in \$e."
[724]376
377 # Find SRPM file name in the log.
378 local src_rpm=`grep "^Wrote: \+.*\.src\.rpm$" "$log_base.srpm.log" | sed -e "s#^Wrote: \+##g"`
379 [ -n "$src_rpm" ] || die "Cannot find .src.rpm file name in '$log_base.srpm.log'."
380
[728]381 # Find package version.
[724]382 local ver_full="${src_rpm%.src.rpm}"
[736]383 ver_full="${ver_full##*/}"
384 [ "${ver_full%%-[0-9]*}" = "$spec_name" ] || die \
385"SRPM name '${src_rpm##*/}' does not match .spec name ('$spec_name').
386Either rename '$spec_name.spec' to '${ver_full%%-[0-9]*}.spec' or set 'Name:' tag to '$spec_name'."
387 ver_full="${ver_full#${spec_name}-}"
[724]388 [ -n "$ver_full" ] || die "Cannot deduce package version from '$src_rpm'."
389
[728]390 # Find all RPM packages for the base arch (note the quotes around `` - it's to preserve multi-line result).
391 local rpms="`grep "^Wrote: \+.*\.\($base_arch\.rpm\|noarch\.rpm\)$" "$log_base.$base_arch.log" | sed -e "s#^Wrote: \+##g"`"
[724]392 [ -n "$rpms" ] || die "Cannot find .$base_arch.rpm/.noarch.rpm file names in '$log_base.base_arch.log'."
393
394 local ver_full_zip=`echo $ver_full | tr . _`
395 local zip="$zip_dir/$spec_name-$ver_full_zip.zip"
396
397 # Generate ZIP.
398 echo "Creating ZIP (logging to $log_base.zip.log)..."
[769]399 start_time=$(date +%s)
[724]400 create_zip()
401 {(
402 run cd "$zip_dir"
403 rm -r "@unixroot" 2> /dev/null
[728]404 # Note no quoters around $rpms - it's to split at EOL.
405 for f in $rpms ; do
[724]406 echo "Unpacking $f..."
407 run rpm2cpio "$f" | cpio -idm
408 done
409 rm -f "$zip" 2> /dev/null
410 echo "Creating '$zip'..."
411 run zip -mry9 "$zip" "@unixroot"
412 )}
413 log_run "$log_base.zip.log" create_zip
[769]414 print_elapsed start_time "Completed in \$e."
[724]415
416 local ver_list="$log_base.$ver_full.list"
417
418 # Generate list of all generated packages for further reference.
419 echo "Creating list file ($ver_list)..."
[768]420 rm -f "$ver_list"
[737]421 echo `stat -c '%Y' "$src_rpm"`"|$src_rpm" > "$ver_list"
422 echo `stat -c '%Y' "$zip"`"|$zip" >> "$ver_list"
[724]423 # Save base arch RPMs.
[737]424 for f in $rpms ; do
425 echo `stat -c '%Y' "$f"`"|$f" >> "$ver_list"
[724]426 done
427 # Save other arch RPMs.
428 for arch in ${RPMBUILD_BOT_ARCH_LIST%${base_arch}} ; do
[728]429 rpms="`grep "^Wrote: \+.*\.$arch\.rpm$" "$log_base.$arch.log" | sed -e "s#^Wrote: \+##g"`"
[724]430 [ -n "$rpms" ] || die "Cannot find .$arch.rpm file names in '$log_base.arch.log'."
[728]431 for f in $rpms ; do
[737]432 echo `stat -c '%Y' "$f"`"|$f" >> "$ver_list"
[724]433 done
434 done
435
436 # Everything succeeded. Symlink the list file so that "upload" can find it.
437 run ln -s "${ver_list##*/}" "$log_base.list"
438}
439
440test_cmd()
441{
442 echo "Spec file: $spec_full"
443
[748]444 sync_aux_src
445
[724]446 local base_arch="${RPMBUILD_BOT_ARCH_LIST##* }"
[732]447 local cmds=
[724]448
449 [ -z "$command_arg" ] && command_arg="all"
450
451 case "$command_arg" in
452 all)
453 cmds="$cmds -bb"
454 ;;
455 prep)
456 cmds="$cmds -bp --short-circuit"
457 ;;
458 build)
459 cmds="$cmds -bc --short-circuit"
460 ;;
461 install)
462 cmds="$cmds -bi --short-circuit"
463 ;;
464 pack)
465 cmds="$cmds -bb --short-circuit"
466 ;;
467 *)
468 die "Invalid test build sub-command '$command_arg'."
469 ;;
470 esac
471
472 local log_file="$log_dir/test/$spec_name.log"
473
474 if [ -f "$log_file" ] ; then
475 rm -f "$log_file.bak"
476 run mv "$log_file" "$log_file.bak"
477 fi
478
479 echo "Doing test RPM build for '$base_arch' target (logging to $log_file)..."
[732]480 log_run "$log_file" rpmbuild.exe "--define=dist %nil" --target=$base_arch $cmds $spec_full
[724]481
482 # Show the generated RPMs when appropriate.
483 if [ "$command_arg" = "all" -o "$command_arg" = "pack" ] ; then
[744]484 # Find all RPM packages for the base arch (note the quotes around `` - it's to preserve multi-line result).
485 local rpms="`grep "^Wrote: \+.*\.\($base_arch\.rpm\|noarch\.rpm\)$" "$log_file" | sed -e "s#^Wrote: \+##g"`"
[724]486 if [ -n "$rpms" ] ; then
487 echo "Successfully generated the following RPMs:"
[739]488 for f in $rpms; do
[724]489 echo "$f"
490 done
491 else
492 warn "Cannot find .$base_arch.rpm/.noarch.rpm file names in '$log_file'."
493 fi
494 fi
495}
496
[738]497repo_dir_for_file()
498{
499 # $1 = input file name
500 # $2 = var name to save dir to
501
502 [ -n "$1" -a -n "$2" ] || die "Invalid arguments."
503
504 local _repo_dir_for_file_ret=
505 case "$1" in
506 *.src.rpm)
507 eval _repo_dir_for_file_ret="$RPMBUILD_BOT_UPLOAD_REPO_LAYOUT_srpm"
508 ;;
509 *.*.rpm)
510 local arch="${1%.rpm}"
511 arch="${arch##*.}"
512 [ -n "$arch" ] || die "No arch spec in file name '$1'."
513 eval _repo_dir_for_file_ret="$RPMBUILD_BOT_UPLOAD_REPO_LAYOUT_rpm"
514 ;;
515 *.zip)
516 eval _repo_dir_for_file_ret="$RPMBUILD_BOT_UPLOAD_REPO_LAYOUT_zip"
517 ;;
518 esac
519
520 eval "$2=\$_repo_dir_for_file_ret"
521}
522
[724]523upload_cmd()
524{
525 # Check settings.
526 test -n "$RPMBUILD_BOT_UPLOAD_REPO_LIST" || die "RPMBUILD_BOT_UPLOAD_REPO_LIST is empty."
527
528 local repo="$command_arg"
529 [ -z "$repo" ] && repo="${RPMBUILD_BOT_UPLOAD_REPO_LIST%% *}"
530
531 check_dir_var "RPMBUILD_BOT_UPLOAD_${repo}_DIR"
532
533 eval local base="\$RPMBUILD_BOT_UPLOAD_${repo}_DIR"
534
535 [ -f "$spec_list" ] || die \
536"File '$spec_list' is not found.
[737]537You may need to build the packages using the 'build' command."
[724]538
[737]539 local files=
540 read_file_list "$spec_list" files
541 for f in $files; do
[738]542 local d=
543 repo_dir_for_file "$f" d
544 [ -n "$d" ] || die "Unsupported file name '$f' in '$spec_list'."
[724]545 [ -d "$d" ] || die "'$d' is not a directory."
546 [ -f "$d/${f##*/}" -a -z "$force" ] && die \
547"File '$d/${f##*/}' already exists.
548Use the -f option to force uploading if you are sure the existing
549packages in the repository should be discarded."
550 echo "Copying $f to $d..."
551 run cp -p "$f" "$d"
[737]552 done
[724]553
554 # On success, delete the uploaded packages and archive log files.
[737]555 for f in $files; do
[724]556 echo "Removing $f..."
[737]557 run rm -f "$f"
558 done
[724]559
560 # Note: versioned .list file will remain in archive forever (for further reference).
561 echo "Removing old '$spec_name' logs from $log_dir/archive..."
562 rm -f "$log_dir/archive/$spec_name".*.log "$log_dir/archive/$spec_name".list
563 echo "Moving '$spec_name' logs to $log_dir/archive..."
564 run mv "$log_base".*.log "$log_base".*.list "$log_base".list "$log_dir/archive/"
565}
566
[738]567clean_cmd()
568{
[739]569 if [ "$command_arg" = "test" ] ; then
570 # Cleanup after "test" command.
571 local base_arch="${RPMBUILD_BOT_ARCH_LIST##* }"
572 local log_file="$log_dir/test/$spec_name.log"
573
574 [ -f "$log_file" ] || die "File '$test_log' is not found."
575
[744]576 # Find all RPM packages for the base arch (note the quotes around `` - it's to preserve multi-line result).
577 local rpms="`grep "^Wrote: \+.*\.\($base_arch\.rpm\|noarch\.rpm\)$" "$log_file" | sed -e "s#^Wrote: \+##g"`"
[739]578 if [ -n "$rpms" ] ; then
579 for f in $rpms; do
580 echo "Removing $f..."
581 run rm -f "$f"
582 done
583 echo "Removing $log_file[.bak]..."
584 run rm -f "$log_file" "$log_file".bak
585 else
586 die "Cannot find .$base_arch.rpm/.noarch.rpm file names in '$log_file'."
587 fi
588
589 return
590 fi
591
592 # Cleanup after "build command".
[738]593 [ -f "$spec_list" ] || die \
594"File '$spec_list' is not found.
595You man need to build the packages using the 'build' command."
596
597 local files=
598 read_file_list "$spec_list" files
599
600 for f in $files; do
601 echo "Removing $f..."
602 run rm -f "$f"
603 done
604
605 echo "Removing '$spec_name' logs from $log_dir..."
606 rm -f "$log_base".*.log "$log_base".*.list "$log_base".list
607}
608
[765]609move_cmd()
610{
611 # Check settings.
612 [ -n "$spec_ver" ] || die "SPEC parameter lacks version specification."
613
614 test -n "$RPMBUILD_BOT_UPLOAD_REPO_LIST" || die "RPMBUILD_BOT_UPLOAD_REPO_LIST is empty."
615
616 local from_repo="${command_arg%%=*}"
617 local to_repo="${command_arg#*=}"
618
619 [ -n "$from_repo" ] || die "FROM_REPO parameter is missing."
620 [ "$from_repo" = "$to_repo" ] && die "TO_REPO parameter is missing (or equals to FROM_REPO)."
621
622 check_dir_var "RPMBUILD_BOT_UPLOAD_${from_repo}_DIR"
623 check_dir_var "RPMBUILD_BOT_UPLOAD_${to_repo}_DIR"
624
625 local ver_list="$log_dir/archive/$spec_name.$spec_ver.list"
626 [ -f "$ver_list" ] || die "File '$ver_list' is not found."
627
628 eval local from_base="\$RPMBUILD_BOT_UPLOAD_${from_repo}_DIR"
629 eval local to_base="\$RPMBUILD_BOT_UPLOAD_${to_repo}_DIR"
630
631 local files=
632 read_file_list "$ver_list" files '
633local dir=
634local base="$from_base"; repo_dir_for_file "$file" dir; file="${dir}/${file##*/}"
635base="$to_base"; repo_dir_for_file "$file" dir; file_post=">${dir}"
636'
637 for f in $files; do
638 local from="${f%%>*}"
639 local to="${f#*>}"
640 echo "Moving $from to $to/..."
641 run mv "$from" "$to/"
642 done
643}
644
[738]645remove_cmd()
646{
647 # Check settings.
648 [ -n "$spec_ver" ] || die "SPEC parameter lacks version specification."
649
650 test -n "$RPMBUILD_BOT_UPLOAD_REPO_LIST" || die "RPMBUILD_BOT_UPLOAD_REPO_LIST is empty."
651
652 local repo="$command_arg"
653 [ -z "$repo" ] && repo="${RPMBUILD_BOT_UPLOAD_REPO_LIST%% *}"
654
655 check_dir_var "RPMBUILD_BOT_UPLOAD_${repo}_DIR"
656
657 local ver_list="$log_dir/archive/$spec_name.$spec_ver.list"
658 [ -f "$ver_list" ] || die "File '$ver_list' is not found."
659
[765]660 eval local base="\$RPMBUILD_BOT_UPLOAD_${repo}_DIR"
661
[738]662 local files=
663 read_file_list "$ver_list" files 'local dir=; repo_dir_for_file $file dir; file="${dir}/${file##*/}"'
664
665 for f in $files; do
666 echo "Removing $f..."
667 run rm -f "$f"
668 done
669
670 echo "Removing $ver_list..."
671 run rm -f "$ver_list"
672
673 # Also remove the logs of last "build" if we are removing the last "build" package.
674 if [ -L "$log_dir/archive/$spec_name.list" -a \
675 `readlink "$log_dir/archive/$spec_name.list"` = "$spec_name.$spec_ver.list" ] ; then
676 echo "Removing '$spec_name' logs from $log_dir/archive..."
677 rm -f "$log_dir/archive/$spec_name".*.log "$log_dir/archive/$spec_name".list
678 fi
679}
680
[724]681#
682# Main.
683#
684
685# Parse command line.
686while [ -n "$1" ] ; do
687 case "$1" in
688 -*)
689 options="$*"
690 while [ -n "$1" ] ; do
691 case "$1" in
692 -f) force="-f"
693 ;;
694 *) usage
695 ;;
696 esac
697 shift
698 done
699 break
[518]700 ;;
[724]701 *)
702 if [ -z "$spec" ] ; then
703 spec="$1"
704 else
705 command="$1"
706 fi
[518]707 ;;
[724]708 esac
709 shift
[518]710done
711
[724]712[ -n "$spec" ] || usage
713[ -z "$command" ] && command="build"
[467]714
[738]715spec_ver="${spec#*=}"
716spec="${spec%=*}"
717[ "$spec" = "$spec_ver" ] && spec_ver=
718
[765]719command_name="${command%%=*}"
[724]720command_arg="${command#*=}"
721[ "$command_name" = "$command_arg" ] && command_arg=
[467]722
[738]723need_spec_file=
724
725# Validate commands.
[724]726case "$command_name" in
[738]727 build|test)
728 need_spec_file=1
[724]729 ;;
[765]730 upload|clean|move|remove)
[738]731 ;;
[724]732 *) usage
733 ;;
734esac
[467]735
[724]736# Query all rpmbuild macros in a single run as it may be slow.
[748]737eval `rpmbuild.exe --eval='rpmbuild_dir="%_topdir" ; spec_dir="%_specdir" ; src_dir="%_sourcedir"' | tr '\\\' /`
[467]738
[748]739[ -n "$rpmbuild_dir" -a -d "$rpmbuild_dir" ] || die "Falied to get %_topdir from rpmbuild or not directory ($rpmbuild_dir)."
740[ -n "$spec_dir" -a -d "$spec_dir" ] || die "Falied to get %_specdir from rpmbuild or not directory ($spec_dir)."
741[ -n "$src_dir" -a -d "$src_dir" ] || die "Falied to get %_sourcedir from rpmbuild or not directory ($src_dir)."
742
[724]743log_dir="$rpmbuild_dir/logs"
744zip_dir="$rpmbuild_dir/zip"
[467]745
[724]746spec=`echo $spec | tr '\\\' /`
[467]747
[724]748spec_name="${spec##*/}"
749
750if [ "$spec_name" = "$spec" ] ; then
751 # No path information, use SPECS
752 spec_full="$spec_dir/${spec_name%.spec}.spec"
753else
754 # Has some path, use it.
755 spec_full="${spec%.spec}.spec"
756fi
757
758spec_name="${spec_name%.spec}"
759
[738]760[ -z "$need_spec_file" -o -f "$spec_full" ] || die "Spec file '$spec_full' is not found."
[724]761
762# Prepare some (non-rpmbuild-standard) directories.
763run mkdir -p "$log_dir"
764run mkdir -p "$log_dir/archive"
765run mkdir -p "$log_dir/test"
766run mkdir -p "$zip_dir"
767
768log_base="$log_dir/$spec_name"
769spec_list="$log_base.list"
770
[769]771start_time=$(date +%s)
772
773echo "Build started on $(date -R)."
[724]774echo "Package: $spec_name"
775echo "Command: $command $options"
776
777# Set up the rpmbuild-bot environment.
778. "${0%%.sh}-env.sh"
779
[739]780# Check common settings.
781test -n "$RPMBUILD_BOT_ARCH_LIST" || die "RPMBUILD_BOT_ARCH_LIST is empty."
782
[724]783run eval "${command_name}_cmd"
784
[769]785quit 0
Note: See TracBrowser for help on using the repository browser.