]> TLD Linux GIT Repositories - packages/rpm-build-tools.git/blob - builder.sh
a5b8edc233598c0ddd26de77c09cb6baa916ba6e
[packages/rpm-build-tools.git] / builder.sh
1 #!/bin/ksh
2 #
3 # This program is free software, distributed under the terms of
4 # the GNU General Public License Version 2.
5 #
6 # -----------
7 # Exit codes:
8 #         0 - succesful
9 #         1 - help displayed
10 #         2 - no spec file name in cmdl parameters
11 #         3 - spec file not stored in repo
12 #         4 - some source, patch or icon files not stored in repo
13 #         5 - package build failed
14 #         6 - spec file with errors
15 #         7 - wrong source in /etc/poldek.conf
16 #         8 - Failed installing buildrequirements and subrequirements
17 #         9 - Requested tag already exist
18 #        10 - Refused to build fractional release
19 #       100 - Unknown error (should not happen)
20 #   110 - Functions not yet implemented
21
22 # Notes (todo/bugs):
23 # - when Icon: field is present, -5 and -a5 doesn't work
24 # - builder -R skips installing BR if spec is not present before builder invocation (need to run builder twice)
25 # - does not respect NoSource: X, and tries to cvs up such files [ example: VirtualBox-bin.spec and its Source0 ]
26 # TODO:
27 # - ability to do ./builder -bb foo.spec foo2.spec foo3.spec
28 # - funny bug, if source-md5 is set then builder will download from distfiles even if there is no url present:
29 #   Source10:   forwardfix.pl
30 #   # Source10-md5:     8bf85f7368933a4e0cb4f875bac28733
31 # - builder --help:
32 #       basename: missing operand
33 #       Try `basename --help' for more information.
34 #       -- and the normal usage info --
35
36 PROGRAM=${0##*/}
37 APPDIR=$(d=$0; [ -L "$d" ] && d=$(readlink -f "$d"); dirname "$d")
38 VERSION="v0.35"
39 VERSIONSTRING="\
40 Build package utility from PLD Linux Packages repository
41 $VERSION (C) 1999-2020 Free Penguins".
42
43 # Clean PATH without /usr/local or user paths
44 CLEAN_PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin"
45
46 # required rpm-build-macros
47 RPM_MACROS_VER=1.534
48
49 COMMAND="build"
50 TARGET=""
51
52 SPECFILE=""
53 BE_VERBOSE=""
54 QUIET=""
55 CLEAN=""
56 DEBUG=""
57 NOURLS=""
58 NOCVSSPEC=""
59 NODIST=""
60 NOINIT=""
61 PREFMIRRORS=""
62 UPDATE=""
63 ADD5=""
64 NO5=""
65 ALWAYS_CVSUP=${ALWAYS_CVSUP:-"yes"}
66
67 # use rpm 4.4.6+ digest format instead of comments if non-zero
68 USEDIGEST=
69
70 # user agent when fetching files
71 USER_AGENT="TLD/Builder($VERSION)"
72
73 # It can be used i.e. in log file naming.
74 # See LOGFILE example.
75 DATE=`date +%Y-%m-%d_%H-%M-%S`
76
77 # target arch, can also be used for log file naming
78 TARGET=$(rpm -E %{_target})
79
80 # Note the *single* quotes, this allows using shell variables expanded at build time
81 # Example: LOGFILE='../log.$PACKAGE_NAME'
82 # Example: LOGFILE='../LOGS/log.$PACKAGE_NAME.$DATE'
83 # Example: LOGFILE='$PACKAGE_NAME/$PACKAGE_NAME.$DATE.log'
84 # Example: LOGFILE='$PACKAGE_NAME.$DATE.log'
85 # Example: LOGFILE='.log.$PACKAGE_NAME-$PACKAGE_VERSION-$PACKAGE_RELEASE.$TARGET.$DATE'
86 LOGFILE=''
87
88 # use teeboth Perl wrapper
89 # temporary option to disable if broken
90 USE_TEEBOTH=no
91
92 LOGDIR=""
93 LOGDIROK=""
94 LOGDIRFAIL=""
95 LASTLOG_FILE=""
96
97 CHMOD="no"
98 CHMOD_MODE="0644"
99 RPMOPTS=""
100 RPMUSERDEFS=""
101 RPMBUILDOPTS=""
102 BCOND=""
103 GROUP_BCONDS="no"
104
105 # create symlinks for tools in PACKAGE_DIR, see get_spec()
106 SYMLINK_TOOLS="yes"
107
108 PATCHES=""
109 SOURCES=""
110 ICONS=""
111 PACKAGE_RELEASE=""
112 PACKAGE_VERSION=""
113 PACKAGE_NAME=""
114 ASSUMED_NAME=""
115 PROTOCOL="http"
116 IPOPT=""
117
118 # use lftp by default when available
119 test -z "${USE_LFTP+x}" && lftp --version > /dev/null 2>&1 && USE_LFTP=yes
120 PARALLEL_DOWNLOADS=10
121
122 WGET_RETRIES=${MAX_WGET_RETRIES:-0}
123
124 # rsync repository with git refs of packages
125 PKGREVS_URL="http://pkgrevs.tld-linux.org"
126 PKGREVS_PREFIX="tld/"
127 SETPKGREV="false"
128
129 # TLD git/df config
130 TLD_GIT_SERVER="git://git.tld-linux.org"
131 TLD_GIT_PUSH="git@git.tld-linux.org:7272"
132 TLD_PACKAGES_DIR="packages"
133 TLD_DISTFILES_SERVER="://df.tld-linux.org"
134
135 # PLD git/df config
136 PLD_GIT_SERVER="git://git.pld-linux.org"
137 PLD_GIT_PUSH="git@git.pld-linux.org"
138 PLD_PACKAGES_DIR="packages"
139 PLD_DISTFILES_SERVER="://distfiles.pld-linux.org"
140
141 CVS_FORCE=""
142 CVSIGNORE_DF="yes"
143 CVSTAG=""
144 GIT_SERVER=${TLD_GIT_SERVER}
145 GIT_PUSH=${TLD_GIT_PUSH}
146 PACKAGES_DIR=${TLD_PACKAGES_DIR}
147 HEAD_DETACHED=""
148 DEPTH=""
149 ALL_BRANCHES=""
150 REMOTE_PLD="origin"
151 NEW_REPO=""
152
153 RES_FILE=""
154
155 DISTFILES_SERVER=${TLD_DISTFILES_SERVER}
156
157 DEF_NICE_LEVEL=19
158 SCHEDTOOL="auto"
159
160 FAIL_IF_NO_SOURCES="yes"
161
162 # let get_files skip over files which are present to get those damn files fetched
163 SKIP_EXISTING_FILES="no"
164
165 TRY_UPGRADE=""
166 # should the specfile be restored if upgrade failed?
167 REVERT_BROKEN_UPGRADE="yes"
168
169 if rpm --specsrpm 2>/dev/null; then
170         FETCH_BUILD_REQUIRES_RPMSPECSRPM="yes"
171         FETCH_BUILD_REQUIRES_RPMGETDEPS="no"
172 else
173         FETCH_BUILD_REQUIRES_RPMSPECSRPM="no"
174         if [ -x /usr/bin/rpm-getdeps ]; then
175                 FETCH_BUILD_REQUIRES_RPMGETDEPS="yes"
176         else
177                 FETCH_BUILD_REQUIRES_RPMGETDEPS="no"
178         fi
179 fi
180
181 UPDATE_POLDEK_INDEXES_OPTS=""
182
183 # Here we load saved user environment used to
184 # predefine options set above, or passed to builder
185 # in command line.
186 # This one reads global system environment settings:
187 if [ -f ~/etc/builderrc ]; then
188         . ~/etc/builderrc
189 fi
190 # And this one cascades settings using user personal
191 # builder settings.
192 # Example of ~/.builderrc:
193 #
194 #UPDATE_POLDEK_INDEXES="yes"
195 #UPDATE_POLDEK_INDEXES_OPTS="--mo=nodiff"
196 #FETCH_BUILD_REQUIRES="yes"
197 #REMOVE_BUILD_REQUIRES="force"
198 #GROUP_BCONDS="yes"
199 #LOGFILE='../LOGS/log.$PACKAGE_NAME.$DATE'
200 #TITLECHANGE=no
201
202 SU_SUDO="sudo"
203
204 if [ -n "$HOME_ETC" ]; then
205         USER_CFG="$HOME_ETC/.builderrc"
206         BUILDER_MACROS="$HOME_ETC/.builder-rpmmacros"
207 else
208         USER_CFG=~/.builderrc
209         BUILDER_MACROS=~/.builder-rpmmacros
210 fi
211
212 [ -f "$USER_CFG" ] && . "$USER_CFG"
213
214 if [ "$SCHEDTOOL" = "auto" ]; then
215         if [ -x /usr/bin/schedtool ] && schedtool -B -e echo >/dev/null; then
216                 SCHEDTOOL="schedtool -B -e"
217         else
218                 SCHEDTOOL="no"
219         fi
220 fi
221
222 if [ -n "$USE_PROZILLA" ]; then
223         GETURI=download_proz
224 elif [ -n "$USE_AXEL" ]; then
225         GETURI=download_axel
226 elif [ -n "$USE_LFTP" ]; then
227         GETURI=download_lftp
228 else
229         GETURI=download_wget
230 fi
231
232 GETLOCAL=${GETLOCAL:-cp -a}
233
234 RPM="rpm"
235 RPMBUILD="rpmbuild"
236
237 #
238 # sanity checks
239 #
240 if [ -d $HOME/rpm/SOURCES ]; then
241         echo "ERROR: ~/rpm/{SPECS,SOURCES} structure is obsolete" >&2
242         echo "ERROR: get rid of your ~/rpm/SOURCES" >&2
243         exit 1
244 fi
245
246 POLDEK_INDEX_DIR="$($RPM --eval %_rpmdir)/"
247 POLDEK_CMD="$SU_SUDO /usr/bin/poldek"
248
249 # TODO: add teeboth
250 # TODO: what this function does?
251 run_poldek() {
252         RES_FILE=$(tempfile)
253         if [ -n "$LOGFILE" ]; then
254                 LOG=`eval echo $LOGFILE`
255                 if [ -n "$LASTLOG_FILE" ]; then
256                         echo "LASTLOG=$LOG" > $LASTLOG_FILE
257                 fi
258                 (${NICE_COMMAND} ${POLDEK_CMD} --noask `while test $# -gt 0; do echo "$1 ";shift;done` ; echo $? > ${RES_FILE})|tee -a $LOG
259                 # FIXME $exit_pldk undefined
260                 return $exit_pldk
261         else
262                 (${NICE_COMMAND} ${POLDEK_CMD} --noask `while test $# -gt 0; do echo "$1 ";shift;done` ; echo $? > ${RES_FILE}) 1>&2 >/dev/null
263                 return `cat ${RES_FILE}`
264                 rm -rf ${RES_FILE}
265         fi
266 }
267
268 #---------------------------------------------
269 # functions
270
271 download_prozilla() {
272         local outfile=$1 url=$2 retval
273
274         proz --no-getch -r -P ./ -t$WGET_RETRIES $PROZILLA_OPTS -O "$outfile" "$url"
275         retval=$?
276
277         return $retval
278 }
279
280 download_axel() {
281         local outfile=$1 url=$2 retval
282
283         axel -a $AXEL_OPTS -o "$outfile" "$url"
284         retval=$?
285
286         return $retval
287 }
288
289 download_wget() {
290         local outfile=$1 url=$2 retval wget_help
291         if [ -z "${WGET_OPTS_SET+x}" ]; then
292                 wget_help="$(wget --help 2>&1)"
293                 echo "$wget_help" | grep -q -- ' --no-check-certificate ' && WGET_OPTS="$WGET_OPTS --no-check-certificate"
294                 echo "$wget_help" | grep -q -- ' --inet ' && WGET_OPTS="$WGET_OPTS --inet"
295                 echo "$wget_help" | grep -q -- ' --retry-connrefused ' && WGET_OPTS="$WGET_OPTS --retry-connrefused"
296                 echo "$wget_help" | grep -q -- ' --no-iri ' && WGET_OPTS="$WGET_OPTS --no-iri"
297                 WGET_OPTS="-c -nd -t$WGET_RETRIES $WGET_OPTS --user-agent=$USER_AGENT $IPOPT --passive-ftp"
298                 WGET_OPTS_SET=1
299         fi
300
301         wget $WGET_OPTS -O "$outfile" "$url"
302         retval=$?
303         if [ $retval -ne 0 ]; then
304                 if [ "`echo $url | grep -E 'ftp://'`" ]; then
305                         ${GETURI} -O "$outfile" "$url"
306                         retval=$?
307                 fi
308         fi
309         return $retval
310 }
311
312 download_lftp() {
313         local outfile=$1 url=$2 retval tmpfile
314         tmpfile=$(tempfile) || exit 1
315         lftp -c "
316                 $([ "$DEBUG" = "yes" ] && echo "debug 5;")
317                 $([ "$IPOPT" = "-4" ] && echo "set dns:order \"inet\";")
318                 $([ "$IPOPT" = "-6" ] && echo "set dns:order \"inet6\";")
319                 set ssl:verify-certificate no;
320                 set net:max-retries $WGET_RETRIES;
321                 set http:user-agent \"$USER_AGENT\";
322                 pget -n $PARALLEL_DOWNLOADS -c \"$url\" -o \"$tmpfile\"
323         "
324
325         retval=$?
326         if [ $retval -eq 0 ]; then
327                 mv -f "$tmpfile" "$outfile"
328         else
329                 rm -f "$tmpfile"
330         fi
331         return $retval
332 }
333
334 usage() {
335         if [ -n "$DEBUG" ]; then set -xv; fi
336 # NOTE:
337 # to make this output parseable by bash-completion _parse_help()
338 # if the line contains short and long option, it will take only the long option
339 # but if you want both being completed, put the short option to separate line
340         echo "\
341 Usage: builder [--all-branches] [-D|--debug] [-V|--version] [--short-version]
342 [-a|--add_cvs] [-b|-ba|--build] [-bb|--build-binary] [-bs|--build-source]
343 [-bc] [-bi] [-bl] [-u|--try-upgrade] [{-cf|--cvs-force}] [{-B|--branch} <branch>]
344 [--depth <number>] [-g|--get] [-h|--help] [--ftp] [--http] [{-l|--logtofile} <logfile>]
345 [-m|--mr-proper] [-q|--quiet] [--date <yyyy-mm-dd>] [-r <tag>]
346 [-nu|--no-urls] [-v|--verbose] [--opts <rpm opts>] [--short-circuit]
347 [--show-bconds] [--with/--without <feature>] [--define <macro> <value>]
348 [--git-pld|--git-tld] [--pkgrev] [-lp]
349 <package>[.spec][:tag]
350
351 -4                  - force IPv4 when transferring files
352 -6                  - force IPv6 when transferring files
353 -5,
354 --update-md5        - update md5 comments in spec, implies -nd -ncs
355 -a5,
356 --add-md5           - add md5 comments to URL sources, implies -nc -nd -ncs
357 --all-branches      - make shallow fetch of all branches; --depth required
358 -n5, --no-md5       - ignore md5 comments in spec
359 -D, --debug         - enable builder script debugging mode,
360 -debug              - produce rpm debug package (same as --opts -debug)
361 -V, --version       - output builder version string
362 --short-version     - output builder short version
363 -a                  - try add new package to PLD repo.
364 -b,
365 -ba
366                     - get all files from PLD repo or HTTP/FTP and build package
367                       from <package>.spec,
368 -bb                 - get all files from PLD repo or HTTP/FTP and build binary
369                       only package from <package>.spec,
370 -bp                 - execute the %prep phase of <package>.spec,
371 -bc                 - execute the %build phase of <package>.spec,
372 -bi                 - execute the %install phase of <package>.spec
373 -bl                 - execute the %files phase of <package>.spec
374 -bs                 - get all files from PLD repo or HTTP/FTP and only pack
375                       them into src.rpm,
376 --short-circuit     - short-circuit build
377 -B, --branch        - add branch
378 -c,
379 --clean             - clean all temporarily created files (in BUILD\$RPM_BUILD_ROOT) after rpmbuild commands.
380                       may be used with building process.
381 -m, --mr-proper     - clean all temporarily created files (in BUILD, SOURCES,
382                       SPECS and \$RPM_BUILD_ROOT). Doesn't run any rpm building.
383 -cf, --cvs-force    - use -f when tagging
384 --define '<macro> <value>'
385                     - define a macro <macro> with value <value>,
386 --depth <number>    - make shallow fetch
387 --alt_kernel <kernel>
388                     - same as --define 'alt_kernel <kernel>'
389 --nodeps            - rpm won't check any dependences
390 -g
391 --get               - get <package>.spec and all related files from PLD repo
392 -h, --help          - this message,
393 -j N                - set %_smp_mflags to propagate concurrent jobs
394 --ftp               - use FTP protocol to access distfiles server
395 --http              - use HTTP protocol to access distfiles server
396 -l <logfile>, --logtofile=<logfile>
397                     - log all to file,
398 -ncs, --no-cvs-specs
399                     - don't pull from PLD repo
400 -nd, --no-distfiles - don't download from distfiles
401 -nm, --no-mirrors   - don't download from mirror, if source URL is given,
402 -nu, --no-urls      - don't try to download from FTP/HTTP location,
403 -ns, --no-srcs      - don't download Sources/Patches
404 -ns0, --no-source0  - don't download Source0
405 -nn, --no-net       - don't download anything from the net
406 -p N                - set PARALLEL_DOWNLOADS to N (default $PARALLEL_DOWNLOADS)
407 -pm, --prefer-mirrors
408                     - prefer mirrors (if any) over distfiles for SOURCES
409 --no-init           - don't initialize builder paths (SPECS and SOURCES)
410 -ske,
411 --skip-existing-files
412                     - skip existing files in get_files
413 --opts <rpm opts>   - additional options for rpm
414 -q, --quiet         - be quiet,
415 --date yyyy-mm-dd   - build package using resources from specified date,
416 -r <tag>, --cvstag <ref>
417                     - build package using resources from specified branch/tag,
418 -A                  - build package using master branch as any sticky tags/branch/date being reset.
419 -R, --fetch-build-requires
420                     - fetch what is BuildRequired,
421 -RB, --remove-build-requires
422                     - remove all you fetched with -R or --fetch-build-requires
423                       remember, this option requires confirmation,
424 -FRB, --force-remove-build-requires
425                     - remove all you fetched with -R or --fetch-build-requires
426                       remember, this option works without confirmation,
427 -sd, --source-distfiles
428                     - list sources available from distfiles (intended for offline
429                       operations; does not work when Icon field is present
430                       but icon file is absent),
431 -sc, --source-cvs   - list sources available from PLD repo
432 -sdp, --source-distfiles-paths
433                     - list sources available from distfiles -
434                       paths relative to distfiles directory (intended for offline
435                       operations; does not work when Icon field is present
436                       but icon file is absent),
437 -sf, --source-files - list sources - bare filenames (intended for offline
438                       operations; does not work when Icon field is present
439                       but icon file is absent),
440 -lsp, --source-paths
441                     - list sources - filenames with full local paths (intended for
442                       offline operations; does not work when Icon field is present
443                       but icon file is absent),
444 -su, --source-urls  - list urls - urls to sources and patches
445                       intended for copying urls with spec with lots of macros in urls
446 -ir, --integer-release-only
447                     - allow only integer and snapshot releases
448 -v, --verbose       - be verbose,
449 -u, --try-upgrade   - check version, and try to upgrade package
450 -un, --try-upgrade-with-float-version
451                     - as above, but allow float version
452                       php-pear-Services_Digg/
453 --upgrade-version   - upgrade to specified version in try-upgrade
454 -U, --update        - refetch sources, don't use distfiles, and update md5 comments
455 -Upi, --update-poldek-indexes
456                     - refresh or make poldek package index files.
457 -sp <patchnumber>,
458 --skip-patch <patchnumber>
459                     - don't apply <patchnumber>. may be repeated.
460 -np <patchnumber>,
461 --nopatch <patchnumber>
462                     - abort instead of applying patch <patchnumber>
463 --noinit
464                     - do not initialize SPECS_DIR and SOURCES_DIR (set them to .)
465 --show-bconds       - show available conditional builds, which can be used
466                     - with --with and/or --without switches.
467 --show-bcond-args   - show active bconds, from ~/.bcondrc. this is used by ./repackage.sh script.
468                       In other words, the output is parseable by scripts.
469 --show-avail-bconds - show available bconds
470 --with <feature>,
471 --without <feature>
472                     - conditional build package depending on %_with_<feature>/
473                       %_without_<feature> macro switch.  You may now use
474                       --with feat1 feat2 feat3 --without feat4 feat5 --with feat6
475                       constructions. Set GROUP_BCONDS to yes to make use of it.
476 --target <platform>, --target=<platform>
477                     - build for platform <platform>.
478 --init-rpm-dir, --init
479                     - initialize ~/rpm directory structure
480 --git-pld           - force use of PLD git and distfiles
481 --git-tld           - force use of TLD git and distfiles (note: it will fall
482                       back to PLD git/df if package doesn't exist in TLD git)
483 --pkgrev            - save git revision of package being built into pkgrevs
484                       (note: only official TLD source builders are allowed to do so)
485 -lp                 - list pkgrevs for specified package
486 "
487 }
488
489 is_rpmorg() {
490         local v
491
492         v=$(LC_ALL=C LANG=C rpm --version 2>&1)
493         v=${v#RPM version } # rpm 4
494         v=${v#rpm \(RPM\) } # rpm 5
495
496         case "$v" in
497                 4.5|5.*)
498                         return 1
499                         ;;
500                 4.*)
501                         return 0;
502                         ;;
503                 *)
504                         echo "ERROR: unsupported RPM version $v" >&2
505                         exit 1
506         esac
507 }
508
509 # create tempfile. as secure as possible
510 tempfile() {
511         local prefix=builder.$PACKAGE_NAME${1:+.$1}
512         mktemp --tmpdir -t $prefix.XXXXXX || echo ${TMPDIR:-/tmp}/$prefix.$RANDOM.$$
513 }
514
515 tempdir() {
516         local prefix=builder.$PACKAGE_NAME${1:+.$1}
517         mktemp --tmpdir -d $prefix.XXXXXX
518 }
519
520 # inserts git log instead of %changelog
521 # @output directory containing modified specfile
522 insert_gitlog() {
523         local SPECFILE=$1 specdir=$(tempdir) gitlog=$(tempfile) speclog=$(tempfile)
524
525         # allow this being customized
526         local log_entries=$(rpm -E '%{?_buildchangelogtruncate}')
527
528         # rpm5.org/rpm.org do not parse any other date format than 'Wed Jan 1 1997'
529         # otherwise i'd use --date=iso here
530         # http://rpm5.org/cvs/fileview?f=rpm/build/parseChangelog.c&v=2.44.2.1
531         # http://rpm.org/gitweb?p=rpm.git;a=blob;f=build/parseChangelog.c;h=56ba69daa41d65ec9fd18c9f371b8ff14118cdca;hb=a113baa510a004476edc44b5ebaaf559238a18b6#l33
532         # NOTE: changelog date is always in UTC for rpmbuild
533         # * 1265749244 +0000 Random Hacker <nikt@pld-linux.org> 9370900
534         git rev-list --date-order -${log_entries:-20} HEAD 2>/dev/null | while read sha1; do
535                 local logfmt='%B%n'
536                 git notes list $sha1 > /dev/null 2>&1 && logfmt='%N'
537                 git log -n 1 $sha1 --format=format:"* %ad %an <%ae> %h%n- ${logfmt}%n" --date=raw | sed -re 's/^- +- */- /'| sed '/^$/q'
538         done > $gitlog
539
540         # add link to full git logs
541         local giturl="http://git.tld-linux.org/?p=packages/${SPECFILE%.spec}.git;a=log"
542         if [ -n "$CVSTAG" ]; then
543                 giturl="$giturl;h=$CVSTAG"
544         fi
545         local gitauthor="TLD Linux <feedback@tld-linux.org>"
546         LC_ALL=C gawk -vgiturl="$giturl" -vgitauthor="$gitauthor" -vpackage=$PACKAGE_NAME 'BEGIN{
547                 printf("* %s %s\n- For complete changelog see: %s\n", strftime("%a %b %d %Y"), gitauthor, giturl);
548                 print;
549                 exit
550         }' > $speclog
551
552         LC_ALL=C gawk '/^\* /{printf("* %s %s\n", strftime("%a %b %d %Y", $2), substr($0, length($1)+length($2)+length($3)+4)); next}{print}' $gitlog >> $speclog
553         sed '/^%changelog/,$d' $SPECFILE | sed -e "\${
554                         a%changelog
555                         r $speclog
556                 }
557         " > $specdir/$SPECFILE
558         rm -f $gitlog $speclog
559         echo $specdir
560 }
561
562 # @param string logfile
563 # @param varargs... commands to execute
564 teeboth() {
565         local rc
566         # use teeboth from toys/cleanbuild, if available and enabled
567         if [ "$USE_TEEBOTH" = "yes" ] && [ -x $APPDIR/teeboth ]; then
568                 $APPDIR/teeboth "$@"
569                 rc=$?
570         else
571                 local efile rc logfile=$1; shift
572                 if [ "$logfile" ]; then
573                         efile=$(tempfile)
574                         { "$@" 2>&1; echo $? > $efile; } | tee $logfile
575                         rc=$(< $efile)
576                         rm -f $efile
577                 else
578                         "$@"
579                         rc=$?
580                 fi
581         fi
582         return $rc
583 }
584
585 # change dependency to specname
586 # common changes:
587 # - perl(Package::Name) -> perl-Package-Name
588 depspecname() {
589         local DEPS
590
591         if [ $# -gt 0 ]; then
592                 DEPS="$@"
593         else
594                 DEPS=$(cat)
595         fi
596
597         echo "$DEPS" | tr ' ' '\n' | sed -re '
598                 # perl virtual deps
599                 /perl\(.*\)/{
600                         s/perl\((.*)\)/perl-\1/
601                         s/::/-/g
602                 }
603
604                 s/apache\(EAPI\)-devel/apache-devel/
605
606                 s/db-devel/db5.3-devel/
607                 s/libjpeg-devel/libjpeg-turbo-devel/
608         '
609 }
610
611 update_shell_title() {
612         [ -t 2 ] || return
613         local len=${COLUMNS:-80}
614         local msg="$(echo "$*" | cut -c-$len)"
615
616         if [ -n "$BE_VERBOSE" ]; then
617                 echo >&2 "$(date +%s.%N) $*"
618         fi
619
620         if [ "x$TITLECHANGE" = "xyes" -o "x$TITLECHANGE" = "x" ]; then
621                 local pkg
622                 if [ -n "$PACKAGE_NAME" ]; then
623                         pkg=${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}
624                 else
625                         pkg=${SPECFILE}
626                 fi
627
628                 msg="$pkg: ${SHELL_TITLE_PREFIX:+$SHELL_TITLE_PREFIX }$msg"
629                 msg=$(echo $msg | tr -d '\n\r')
630                 case "$TERM" in
631                         cygwin|xterm*)
632                         echo >&2 -ne "\033]1;$msg\007\033]2;$msg\007"
633                 ;;
634                         screen*)
635                         echo >&2 -ne "\033]0;$msg\007"
636                 ;;
637                 esac
638         fi
639 }
640
641 # set TARGET from BuildArch: from SPECFILE
642 set_spec_target() {
643         if [ -n "$SPECFILE" ] && [ -z "$TARGET" ]; then
644                 local tmp=$(awk '/^BuildArch:/ { print $NF; exit }' $ASSUMED_NAME/$SPECFILE)
645                 if [ "$tmp" ]; then
646                                 local target_platform=$(rpm -E '%{_target_vendor}-%{_target_os}%{?_gnu}')
647                                 TARGET="$tmp"
648                                 case "$RPMBUILD" in
649                                 "rpmbuild")
650                                         TARGET_SWITCH="--target ${TARGET}-${target_platform}" ;;
651                                 "rpm")
652                                         TARGET_SWITCH="--target=$TARGET" ;;
653                                 esac
654                 fi
655         fi
656 }
657
658 # runs rpm with minimal macroset
659 minirpm() {
660         # TODO: move these to /usr/lib/rpm/macros
661         cat > $BUILDER_MACROS <<'EOF'
662 %x8664 x86_64 amd64 ia32e
663 %alt_kernel %{nil}
664 %_alt_kernel %{nil}
665 %bootstrap_release() %{1}
666 %requires_releq_kernel_up(s:n:) %{nil}
667 %requires_releq_kernel_smp(s:n:) %{nil}
668 %requires_releq_kernel(s:n:) %{nil}
669 %requires_releq() %{nil}
670 %pyrequires_eq() %{nil}
671 %requires_eq() %{nil}
672 %requires_eq_to() %{nil}
673 %requires_ge() %{nil}
674 %requires_ge_to() %{nil}
675 %requires_ge() %{nil}
676 %releq_kernel_up(n:) ERROR
677 %releq_kernel_smp(n:) ERROR
678 %releq_kernel(n:) ERROR
679 %py_postclean(x:) ERROR
680 %kgcc_package ERROR
681 %_fontsdir ERROR
682 %ruby_version ERROR
683 %ruby_ver_requires_eq() %{nil}
684 %ruby_mod_ver_requires_eq() %{nil}
685 %__php_api_requires() %{nil}
686 %php_major_version ERROR
687 %php_api_version ERROR
688 %requires_xorg_xserver_extension %{nil}
689 %requires_xorg_xserver_xinput %{nil}
690 %requires_xorg_xserver_font %{nil}
691 %requires_xorg_xserver_videodrv %{nil}
692 %py_ver ERROR
693 %perl_vendorarch ERROR
694 %perl_vendorlib ERROR
695 # damn. need it here! - copied from /usr/lib/rpm/macros.build
696 %tmpdir         %(echo "${TMPDIR:-/tmp}")
697 %patchset_source(f:b:) %(
698         base=%{-b*}%{!-b*:10000};
699         start=$(expr $base + %1);
700         end=$(expr $base + %{?2}%{!?2:%{1}});
701         # we need to call seq twice as it doesn't allow two formats
702         seq -f 'Patch%g:' $start $end > %{tmpdir}/__ps1;
703         seq -f '%{-f*}' %1 %{?2}%{!?2:%{1}} > %{tmpdir}/__ps2;
704         paste %{tmpdir}/__ps{1,2};
705         rm -f %{tmpdir}/__ps{1,2};
706 ) \
707 %{nil}
708 %add_etc_shells(p) %{p:<lua>}
709 %remove_etc_shells(p) %{p:<lua>}
710 %lua_add_etc_shells()  %{nil}
711 %lua_remove_etc_shells() %{nil}
712 %required_jdk jdk
713 %buildrequires_jdk %{nil}
714 %pear_package_print_optionalpackages %{nil}
715 EOF
716         if [ "$NOINIT" = "yes" ] ; then
717                 cat >> $BUILDER_MACROS <<'EOF'
718 %_specdir ./
719 %_sourcedir ./
720 EOF
721         fi
722         if ! is_rpmorg; then
723                 local safe_macrofiles
724                 safe_macrofiles=$(rpm $TARGET_SWITCH --showrc | awk -F: '/^macrofiles/ { gsub(/^macrofiles[ \t]+:/, "", $0); print $0 } ')
725                 eval PATH=$CLEAN_PATH $RPMBUILD $TARGET_SWITCH --macros "$safe_macrofiles:$BUILDER_MACROS" $QUIET $RPMOPTS $RPMUSERDEFS $RPMBUILDOPTS $BCOND $* 2>&1
726         else
727                 eval PATH=$CLEAN_PATH $RPMBUILD $TARGET_SWITCH --load "$BUILDER_MACROS" $QUIET $RPMOPTS $RPMUSERDEFS $RPMBUILDOPTS $BCOND $* 2>&1
728         fi
729 }
730
731 cache_rpm_dump() {
732         local SPEC_PATH
733         if [ -n "$DEBUG" ]; then
734                 set -x
735                 set -v
736         fi
737
738         if [ ! -z "$1" ]; then
739                 SPEC_PATH="$1"
740         else
741                 SPEC_PATH="$PACKAGE_DIR/$SPECFILE"
742         fi
743         if [ -x /usr/bin/rpm-specdump ]; then
744                 update_shell_title "cache_rpm_dump using rpm-specdump command"
745                 rpm_dump_cache=$(eval rpm-specdump $TARGET_SWITCH $BCOND $RPMUSERDEFS --define \'_specdir $PACKAGE_DIR\' --define \'_sourcedir $PACKAGE_DIR\' $SPEC_PATH)
746         else
747                 update_shell_title "cache_rpm_dump using rpmbuild command"
748                 local rpm_dump
749                 rpm_dump=`
750                         # what we need from dump is NAME, VERSION, RELEASE and PATCHES/SOURCES.
751                         dump='%{echo:dummy: PACKAGE_NAME %{name} }%dump'
752                         case "$RPMBUILD" in
753                         rpm)
754                                 ARGS='-bp'
755                                 ;;
756                         rpmbuild)
757                                 ARGS='--nodigest --nosignature --nobuild'
758                                 ;;
759                         esac
760                         minirpm $ARGS --define "'prep $dump'" --nodeps $SPECFILE
761                 `
762                 if [ $? -gt 0 ]; then
763                         error=$(echo "$rpm_dump" | sed -ne '/^error:/,$p')
764                         echo "$error" >&2
765                         Exit_error err_build_fail
766                 fi
767
768                 # make small dump cache
769                 rpm_dump_cache=`echo "$rpm_dump" | awk '
770                         $2 ~ /^SOURCEURL/ {print}
771                         $2 ~ /^PATCHURL/  {print}
772                         $2 ~ /^nosource/ {print}
773                         $2 ~ /^PACKAGE_/ {print}
774                 '`
775         fi
776
777         update_shell_title "cache_rpm_dump: OK!"
778 }
779
780 rpm_dump() {
781         if [ -z "$rpm_dump_cache" ] ; then
782                 echo >&2 "internal error: cache_rpm_dump not called! (missing %prep?)"
783         fi
784         echo "$rpm_dump_cache"
785 }
786
787 get_icons() {
788         update_shell_title "get icons"
789         ICONS=$(awk '/^Icon:/ {print $2}' $PACKAGE_DIR/${SPECFILE})
790         if [ -z "$ICONS" ]; then
791                 return
792         fi
793
794         rpm_dump_cache="kalasaba" NODIST="yes" get_files $ICONS
795 }
796
797 parse_spec() {
798         update_shell_title "parsing specfile"
799         if [ -n "$DEBUG" ]; then
800                 set -x
801                 set -v
802         fi
803
804         # icons are needed for successful spec parse
805         get_icons
806
807         cd $PACKAGE_DIR
808         cache_rpm_dump "$1"
809
810         if rpm_dump | grep -qEi ":.*nosource.*1"; then
811                 FAIL_IF_NO_SOURCES="no"
812         fi
813
814         if [ "$NOSRCS" != "yes" ]; then
815                 SOURCES=$(rpm_dump | awk '$2 ~ /^SOURCEURL[0-9]+/ {print substr($2, length("SOURCEURL") + 1), $3}' | LC_ALL=C sort -n | awk '{print $2}')
816                 PATCHES=$(rpm_dump | awk '$2 ~ /^PATCHURL[0-9]+/ {print substr($2, length("PATCHURL") + 1), $3}' | LC_ALL=C sort -n | awk '{print $2}')
817                 ICONS=$(awk '/^Icon:/ {print $2}' ${SPECFILE})
818         fi
819
820         PACKAGE_NAME=$(rpm_dump | awk '$2 == "PACKAGE_NAME" { print $3; exit}')
821         PACKAGE_VERSION=$(rpm_dump | awk '$2 == "PACKAGE_VERSION" { print $3; exit}')
822         PACKAGE_RELEASE=$(rpm_dump | awk '$2 == "PACKAGE_RELEASE" { print $3; exit}')
823
824         if [ "$PACKAGE_NAME" != "$ASSUMED_NAME" ]; then
825                 echo >&2 "WARNING! Spec name ($ASSUMED_NAME) does not agree with package name ($PACKAGE_NAME)"
826         fi
827
828         if [ -n "$BE_VERBOSE" ]; then
829                 echo "- Sources :  `nourl $SOURCES`"
830                 if [ -n "$PATCHES" ]; then
831                         echo "- Patches :  `nourl $PATCHES`"
832                 else
833                         echo "- Patches :  *no patches needed*"
834                 fi
835                 if [ -n "$ICONS" ]; then
836                         echo "- Icon    :  `nourl $ICONS`"
837                 else
838                         echo "- Icon    :  *no package icon*"
839                 fi
840                 echo "- Name    : $PACKAGE_NAME"
841                 echo "- Version : $PACKAGE_VERSION"
842                 echo "- Release : $PACKAGE_RELEASE"
843         fi
844
845         update_shell_title "parse_spec: OK!"
846 }
847
848 # aborts program abnormally
849 die() {
850         local rc=${2:-1}
851         echo >&2 "$PROGRAM: ERROR: $*"
852         exit $rc
853 }
854
855 Exit_error() {
856         if [ -n "$DEBUG" ]; then
857                 set -x
858                 set -v
859         fi
860
861         cd "$__PWD"
862
863         case "$1" in
864                 "err_no_spec_in_cmdl" )
865                         remove_build_requires
866                         echo >&2 "ERROR: spec file name not specified."
867                         exit 2 ;;
868                 "err_invalid_cmdline" )
869                         echo >&2 "ERROR: invalid command line arg ($2)."
870                         exit 2 ;;
871                 "err_no_spec_in_repo" )
872                         remove_build_requires
873                         echo >&2 "Error: spec file not stored in repository."
874                         if [ -n "$2" ]; then
875                                 echo >&2 "Tried: $2"
876                         fi
877
878                         exit 3 ;;
879                 "err_no_source_in_repo" )
880                         remove_build_requires
881                         echo >&2 "Error: some source, patch or icon files not stored in PLD repo. ($2)"
882                         exit 4 ;;
883                 "err_cvs_add_failed" )
884                         echo >&2 "Error: failed to add package to PLD repo."
885                         exit 4 ;;
886                 "err_build_fail" )
887                         remove_build_requires
888                         echo >&2 "Error: package build failed. (${2:-no more info})"
889                         exit 5 ;;
890                 "err_no_package_data" )
891                         remove_build_requires
892                         echo >&2 "Error: couldn't get out package name/version/release from spec file."
893                         exit 6 ;;
894                 "err_pkgrev_exists" )
895                         remove_build_requires
896                         echo >&2 "Error: package revision ${2} already exists"
897                         exit 9 ;;
898                 "err_fract_rel" )
899                         remove_build_requires
900                         echo >&2 "Release ${2} not integer and not a snapshot."
901                         exit 10 ;;
902                 "err_branch_exists" )
903                         remove_build_requires
904                         echo >&2 "Tree branch already exists (${2})."
905                         exit 11 ;;
906                 "err_acl_deny" )
907                         remove_build_requires
908                         echo >&2 "Error: conditions reject building this spec (${2})."
909                         exit 12 ;;
910                 "err_remote_problem" )
911                         remove_build_requires
912                         echo >&2 "Error: problem with remote (${2})"
913                         exit 13 ;;
914                 "err_no_checkut" )
915                         echo >&2 "Error: cannot checkout ${2}"
916                         exit 14 ;;
917                 "err_pkgrev_set" )
918                         echo >&2 "Error: failed to set package revision for tag ${2}"
919                         exit 15 ;;
920                 "err_pkgrev_get" )
921                         echo >&2 "Error: failed to get package revision for tag ${2}"
922                         exit 16 ;;
923                 "err_not_implemented" )
924                         remove_build_requires
925                         echo >&2 "Error: functionality not yet imlemented"
926                         exit 110 ;;
927         esac
928         echo >&2 "Unknown error."
929         exit 100
930 }
931
932 init_builder() {
933         if [ -n "$DEBUG" ]; then
934                 set -x
935                 set -v
936         fi
937
938         if [ "$NOINIT" != "yes" ] ; then
939                 TOP_DIR=$(eval $RPM $RPMOPTS $RPMUSERDEFS --eval '%{_topdir}')
940
941                 local macros_ver=$(rpm -E %?rpm_build_macros)
942                 if [ -z "$macros_ver" ]; then
943                         REPO_DIR=$TOP_DIR/packages
944                         PACKAGE_DIR=$TOP_DIR/packages/$ASSUMED_NAME
945                 else
946                         if awk "BEGIN{exit($macros_ver>=$RPM_MACROS_VER)}"; then
947                                 echo >&2 "builder requires rpm-build-macros >= $RPM_MACROS_VER"
948                                 exit 1
949                         fi
950                         REPO_DIR=$TOP_DIR
951                         PACKAGE_DIR=$REPO_DIR/$ASSUMED_NAME
952                 fi
953         else
954                 TOP_DIR=$(pwd)
955                 PACKAGE_DIR=$TOP_DIR
956                 REPO_DIR=$PACKAGE_DIR
957                 RPMBUILDOPTS="$RPMBUILDOPTS --define '_topdir $TOP_DIR' --define '_builddir %_topdir' --define '_rpmdir %_topdir' --define '_srcrpmdir %_topdir'"
958         fi
959         export GIT_WORK_TREE=$PACKAGE_DIR
960         export GIT_DIR=$PACKAGE_DIR/.git
961
962         if [ -d "$GIT_DIR" ] &&  [ -z "$CVSTAG" ] && git rev-parse --verify -q HEAD > /dev/null; then
963                 if CVSTAG=$(GIT_DIR=$GIT_DIR git symbolic-ref HEAD) 2>/dev/null; then
964                         CVSTAG=${CVSTAG#refs/heads/}
965                         if [ "$CVSTAG" != "master" ]; then
966                                 echo >&2 "builder: Active branch $CVSTAG. Use -r BRANCHNAME to override"
967                         fi
968                 else
969                         echo >&2 "On detached HEAD. Use -r BRANCHNAME to override"
970                         HEAD_DETACHED="yes"
971                 fi
972         elif [ "$CVSTAG" = "HEAD" ]; then
973                 # assume -r HEAD is same as -A
974                 CVSTAG="master"
975         fi
976
977         __PWD=$(pwd)
978 }
979
980 create_git_repo() {
981         update_shell_title "add_package"
982
983         if [ -n "$DEBUG" ]; then
984                 set -x
985                 set -v
986         fi
987
988         cd "$REPO_DIR"
989         SPECFILE=$(basename $SPECFILE)
990         if [ ! -f "$ASSUMED_NAME/$SPECFILE" ]; then
991                 echo "ERROR: No package to add ($ASSUMED_NAME/$SPECFILE)" >&2
992                 exit 101
993         fi
994         [ -d "$ASSUMED_NAME/.git" ] || NEW_REPO=yes
995         ssh $GIT_PUSH create ${ASSUMED_NAME} || Exit_error err_cvs_add_failed
996         (
997         set -e
998         git init
999         git remote add $REMOTE_PLD ${GIT_SERVER}/${PACKAGES_DIR}/${ASSUMED_NAME}.git
1000         git remote set-url --push $REMOTE_PLD ssh://${GIT_PUSH}/${PACKAGES_DIR}/${ASSUMED_NAME}
1001
1002         git config --local push.default current
1003         git config --local branch.master.remote $REMOTE_PLD
1004         git config --local branch.master.merge refs/heads/master
1005         )
1006         test $? = 0 || Exit_error err_remote_problem $REMOTE_PLD
1007 }
1008
1009 get_spec() {
1010
1011         update_shell_title "get_spec"
1012
1013         if [ -n "$DEBUG" ]; then
1014                 set -x
1015                 set -v
1016         fi
1017
1018         cd "$REPO_DIR"
1019         SPECFILE=$(basename $SPECFILE)
1020         if [ "$NOCVSSPEC" != "yes" ]; then
1021                 if [ -z "$DEPTH" ]; then
1022                         if [ -d "$PACKAGE_DIR/.git" ]; then
1023                                 git fetch $IPOPT $REMOTE_PLD || Exit_error err_no_spec_in_repo
1024                         elif [ "$ADD_PACKAGE_CVS" = "yes" ]; then
1025                                 if [ ! -r "$PACKAGE_DIR/$SPECFILE" ]; then
1026                                         echo "ERROR: No package to add ($PACKAGE_DIR/$SPECFILE)" >&2
1027                                         exit 101
1028                                 fi
1029                                 Exit_error err_not_implemented
1030                         else
1031                                 (
1032                                         unset GIT_WORK_TREE
1033                                         git clone $IPOPT -o $REMOTE_PLD ${GIT_SERVER}/${PACKAGES_DIR}/${ASSUMED_NAME}.git || {
1034                                                 # softfail if new package, i.e not yet added to PLD rep
1035                                                 [ ! -f "$PACKAGE_DIR/$SPECFILE" ] && Exit_error err_no_spec_in_repo
1036                                                 echo "Warning: package not in Git - assuming new package"
1037                                                 NOCVSSPEC="yes"
1038                                         }
1039                                         git config --local --add "remote.$REMOTE_PLD.fetch" 'refs/notes/*:refs/notes/*'
1040                                         git config --local --add "remote.$REMOTE_PLD.push" 'refs/notes/*:refs/notes/*'
1041                                         git config --local --add "remote.$REMOTE_PLD.push" HEAD
1042                                         git config --local push.default current
1043                                         git remote set-url --push  $REMOTE_PLD ssh://${GIT_PUSH}/${PACKAGES_DIR}/${ASSUMED_NAME}
1044                                 )
1045                         fi
1046                 else
1047                         if [ ! -d "$PACKAGE_DIR/.git" ]; then
1048                                 if [ ! -d "$PACKAGE_DIR" ]; then
1049                                         install -d $PACKAGE_DIR
1050                                 fi
1051                                 git init
1052                                 git remote add $REMOTE_PLD ${GIT_SERVER}/${PACKAGES_DIR}/${ASSUMED_NAME}.git
1053                                 git config --local --add "remote.$REMOTE_PLD.fetch" 'refs/notes/*:refs/notes/*'
1054                                 git config --local --add "remote.$REMOTE_PLD.push" 'refs/heads/*:refs/remotes/origin/*'
1055                                 git config --local --add "remote.$REMOTE_PLD.push" HEAD
1056                                 git config --local push.default current
1057                                 git remote set-url --push  $REMOTE_PLD ssh://${GIT_PUSH}/${PACKAGES_DIR}/${ASSUMED_NAME}
1058                                 CVSTAG=${CVSTAG:-"master"}
1059                         fi
1060                         local refs=''
1061                         if [ -z "$ALL_BRANCHES" ]; then
1062                                 refs="${CVSTAG}:remotes/${REMOTE_PLD}/${CVSTAG}"
1063                         fi
1064                         git fetch $IPOPT $DEPTH $REMOTE_PLD $refs || {
1065                                 echo >&2 "Error: branch $CVSTAG does not exist"
1066                                 exit 3
1067                         }
1068                 fi
1069                 git fetch $IPOPT $REMOTE_PLD 'refs/notes/*:refs/notes/*'
1070
1071                 cvsignore_df .gitignore
1072
1073                 # add default log format to .gitignore if it is relative to package dir
1074                 if [ -n "$LOGFILE" -a "$LOGFILE" = "${LOGFILE##*/}" ]; then
1075                         # substitute known "macros" to glob
1076                         local logfile=$(echo "$LOGFILE" | sed -r -e 's,\$(PACKAGE_(NAME|VERSION|RELEASE)|DATE|TARGET),*,g')
1077                         if [ "$logfile" ]; then
1078                                 cvsignore_df "$logfile"
1079                         fi
1080                 fi
1081
1082                 # create symlinks for tools
1083                 if [ "$SYMLINK_TOOLS" != "no" -a -d "$PACKAGE_DIR" ]; then
1084                         for a in dropin md5 builder {relup,compile,repackage,rsync,pearize}.sh; do
1085                                 # skip tools that don't exist in top dir
1086                                 [ -f $a ] || continue
1087                                 # skip tools that already exist
1088                                 [ -f $PACKAGE_DIR/$a ] && continue
1089                                 ln -s ../$a $PACKAGE_DIR
1090                                 cvsignore_df $a
1091                         done
1092                 fi
1093         fi
1094
1095         if [ -n "$CVSTAG" ]; then
1096                 local _rev=$(get_pkgrev "$CVSTAG")
1097                 echo "$_rev" | grep -q -E "^ERROR$" || CVSTAG="$_rev"
1098                 if git rev-parse --verify -q "$CVSTAG" >/dev/null; then
1099                         # checkout only if differs, so this will not trash git reflog
1100                         if [ $(git rev-parse "$CVSTAG") != $(git rev-parse HEAD) ]; then
1101                                 git checkout "$CVSTAG" --
1102                         fi
1103                 elif git rev-parse --verify -q "refs/remotes/${REMOTE_PLD}/$CVSTAG"; then
1104                         git checkout -t "refs/remotes/${REMOTE_PLD}/$CVSTAG" > /dev/null
1105                 fi
1106                 if [ $(git rev-parse "$CVSTAG") != $(git rev-parse HEAD) ]; then
1107                         Exit_error "err_no_checkut" "$CVSTAG"
1108                 fi
1109
1110                 git merge --ff-only '@{u}'
1111                 git symbolic-ref -q HEAD > /dev/null && [ "$NOCVSSPEC" != "yes" ] &&
1112                 if [ -n "$CVSDATE" ]; then
1113                         git checkout $(git rev-list -n1 --before="'$CVSDATE'" $CVSTAG) || exit 1
1114                 fi
1115         fi
1116
1117         if [ ! -f "$PACKAGE_DIR/$SPECFILE" ]; then
1118                 Exit_error err_no_spec_in_repo "$PACKAGE_DIR/$SPECFILE"
1119         fi
1120
1121         if [ "$CHMOD" = "yes" -a -n "$SPECFILE" ]; then
1122                 chmod $CHMOD_MODE $PACKAGE_DIR/$SPECFILE
1123         fi
1124         unset OPTIONS
1125         [ -n "$DONT_PRINT_REVISION" ] || grep -E -m 1 "^#.*Revision:.*Date" $PACKAGE_DIR/$SPECFILE
1126
1127         set_spec_target
1128 }
1129
1130 # find mirrors in this order. first match wins:
1131 # - package dir (~/rpm/packages/foo)
1132 # - repository dir (~/rpm/packages)
1133 # - tools dir dir (~/rpm/packages/rpm-build-tools)
1134 find_mirror() {
1135         local url="$1"
1136
1137         update_shell_title "find_mirror[$url][$REPO_DIR]"
1138
1139         # NOTE: as while loop runs in subshell,
1140         # we use exit 2 to indicate  that the match was found
1141         # otherwise we end up outputing mirror url and origin url.
1142
1143         local origin mirror name rest ol prefix
1144         IFS="|"
1145         cat "$PACKAGE_DIR/mirrors" "$REPO_DIR/mirrors" "$REPO_DIR/../rpm-build-tools/mirrors" /dev/null 2>/dev/null | \
1146         while read origin mirror name rest; do
1147                 # skip comments and empty lines
1148                 if [ -z "$origin" ] || [ "${origin#\#}" != "$origin" ]; then
1149                         continue
1150                 fi
1151                 ol=$(echo -n "$origin" | wc -c)
1152                 prefix=$(echo -n "$url" | head -c $ol)
1153                 if [ "$prefix" = "$origin" ] ; then
1154                         suffix=$(echo "$url" | cut -b $((ol+1))-)
1155                         echo -n "$mirror$suffix"
1156                         exit 2
1157                 fi
1158         done && echo "$url"
1159 }
1160
1161 # Warning: unpredictable results if same URL used twice
1162 src_no() {
1163         local file="$1"
1164         # escape some regexp characters if part of file name
1165         file=$(echo "$file" | sed -e 's#\([\+\*\.\&\#\?]\)#\\\1#g')
1166         cd $PACKAGE_DIR
1167         rpm_dump | \
1168         grep -E "(SOURCE|PATCH)URL[0-9]*[       ]*${file}""[    ]*$" | \
1169         sed -e 's/.*\(SOURCE\|PATCH\)URL\([0-9][0-9]*\).*/\1\2/' | \
1170         head -n 1 | tr OURCEATH ourceath | xargs
1171 }
1172
1173 src_md5() {
1174         [ "$NO5" = "yes" ] && return
1175         no=$(src_no "$1")
1176         [ -z "$no" ] && return
1177         cd $PACKAGE_DIR
1178         local md5
1179
1180         # use "sources" file from package dir, like vim
1181         if [ -f sources ]; then
1182                 md5=$(grep -s -v '^#' sources | \
1183                 grep -E "[      *]$(basename "$1")([    ,]|\$)" | \
1184                 sed -e 's/^\([0-9a-f]\{32\}\).*/\1/' | \
1185                 grep -E '^[0-9a-f]{32}$')
1186
1187                 if [ "$md5" ]; then
1188                         if [ $(echo "$md5" | wc -l) != 1 ] ; then
1189                                 echo "$SPECFILE: more then one entry in sources for $1" 1>&2
1190                         fi
1191                         echo "$md5" | tail -n 1
1192                         return
1193                 fi
1194         fi
1195
1196         source_md5=$(grep -iE "^#[      ]*(No)?$no-md5[         ]*:" $SPECFILE | sed -e 's/.*://')
1197         if [ -n "$source_md5" ]; then
1198                 echo $source_md5
1199         else
1200                 source_md5=`grep -i "BuildRequires:[    ]*digest(%SOURCE$no)[   ]*=" $SPECFILE | sed -e 's/.*=//'`
1201                 if [ -n "$source_md5" ]; then
1202                         echo $source_md5
1203                 else
1204                         # we have empty SourceX-md5, but it is still possible
1205                         # that we have NoSourceX-md5 AND NoSource: X
1206                         nosource_md5=`grep -i "^#[       ]*No$no-md5[    ]*:" $SPECFILE | sed -e 's/.*://'`
1207                         if [ -n "$nosource_md5" -a -n "`grep -i "^NoSource:[     ]*$no$" $SPECFILE`" ] ; then
1208                                 echo $nosource_md5
1209                         fi
1210                 fi
1211         fi
1212 }
1213
1214 distfiles_path() {
1215         echo "by-md5/$(src_md5 "$1" | sed -e 's|^\(.\)\(.\)|\1/\2/&|')/$(basename "$1")"
1216 }
1217
1218 distfiles_url() {
1219         echo "$PROTOCOL$DISTFILES_SERVER/$(distfiles_path "$1")"
1220 }
1221
1222 good_md5() {
1223         md5=$(src_md5 "$1")
1224         [ "$md5" = "" ] || \
1225         [ "$md5" = "$(md5sum $(nourl "$1") 2> /dev/null | sed -e 's/ .*//')" ]
1226 }
1227
1228 good_size() {
1229         size=$(find $(nourl "$1") -printf "%s" 2>/dev/null)
1230         [ -n "$size" -a "$size" -gt 0 ]
1231 }
1232
1233 cvsignore_df() {
1234         if [ "$CVSIGNORE_DF" != "yes" ]; then
1235                 return
1236         fi
1237         local cvsignore=${PACKAGE_DIR}/.git/info/exclude
1238
1239         # add only if not yet there
1240         if ! awk -vf="$1" -vc=1 '$0 == f { c = 0 } END { exit c }' $cvsignore 2>/dev/null; then
1241                 echo "$1" >> $cvsignore
1242         fi
1243 }
1244
1245 # returns true if "$1" is ftp, http or https protocol url
1246 is_url() {
1247         case "$1" in
1248         ftp://*|http://*|https://*)
1249                 return 0
1250         ;;
1251         esac
1252         return 1
1253 }
1254
1255 update_md5() {
1256         if [ $# -eq 0 ]; then
1257                 return
1258         fi
1259
1260         update_shell_title "update md5"
1261         if [ -n "$DEBUG" ]; then
1262                 set -x
1263                 set -v
1264         fi
1265
1266         cd "$PACKAGE_DIR"
1267
1268         # pass 1: check files to be fetched
1269         local todo
1270         local need_files
1271         for i in "$@"; do
1272                 local fp=$(nourl "$i")
1273                 local srcno=$(src_no "$i")
1274                 if [ -n "$ADD5" ]; then
1275                         [ "$fp" = "$i" ] && continue # FIXME what is this check doing?
1276                         grep -qiE '^#[  ]*'$srcno'-md5[         ]*:' $PACKAGE_DIR/$SPECFILE && continue
1277                         grep -qiE '^BuildRequires:[     ]*digest[(]%SOURCE'$srcno'[)][  ]*=' $PACKAGE_DIR/$SPECFILE && continue
1278                 else
1279                         grep -qiE '^#[  ]*'$srcno'-md5[         ]*:' $PACKAGE_DIR/$SPECFILE || grep -qiE '^BuildRequires:[      ]*digest[(]%SOURCE'$srcno'[)][  ]*=' $PACKAGE_DIR/$SPECFILE || continue
1280                 fi
1281                 if [ ! -f "$fp" ] || [ $ALWAYS_CVSUP = "yes" ]; then
1282                         need_files="$need_files $i"
1283                 fi
1284         done
1285
1286         # pass 1a: get needed files
1287         if [ "$need_files" ]; then
1288                 get_files $need_files
1289         fi
1290
1291         # pass 2: proceed with md5 adding or updating
1292         for i in "$@"; do
1293                 local fp=$(nourl "$i")
1294                 local srcno=$(src_no "$i")
1295                 local md5=$(grep -iE '^#[       ]*(No)?'$srcno'-md5[    ]*:' $PACKAGE_DIR/$SPECFILE )
1296                 if [ -z "$md5" ]; then
1297                         md5=$(grep -iE '^[      ]*BuildRequires:[       ]*digest[(]%SOURCE'$srcno'[)][  ]*=' $PACKAGE_DIR/$SPECFILE )
1298                 fi
1299                 if [ -n "$ADD5" ] && is_url $i || [ -n "$md5" ]; then
1300                         local tag="# $srcno-md5:\t"
1301                         if [[ "$md5" == *NoSource* ]]; then
1302                                 tag="# No$srcno-md5:\t"
1303                         elif [ -n "$USEDIGEST" ]; then
1304                                 tag="BuildRequires:\tdigest(%SOURCE$srcno) = "
1305                         fi
1306                         md5=$(md5sum "$fp" | cut -f1 -d' ')
1307                         echo "Updating $srcno ($md5: $fp)."
1308                         perl -i -ne '
1309                                 print unless (/^\s*#\s*(No)?'$srcno'-md5\s*:/i or /^\s*BuildRequires:\s*digest\(%SOURCE'$srcno'\)/i);
1310                                 print "'"$tag$md5"'\n" if /^'$srcno'\s*:\s+/i;
1311                         ' \
1312                         $PACKAGE_DIR/$SPECFILE
1313                 fi
1314         done
1315 }
1316
1317 check_md5() {
1318         local bad
1319         [ "$NO5" = "yes" ] && return
1320
1321         update_shell_title "check md5"
1322
1323         for i in "$@"; do
1324                 bad=0
1325                 if ! good_md5 "$i"; then
1326                         echo -n "MD5 sum mismatch."
1327                         bad=1
1328                 fi
1329                 if ! good_size "$i"; then
1330                         echo -n "0 sized file."
1331                         bad=1
1332                 fi
1333
1334                 if [ $bad -eq 1 ]; then
1335                         echo " Use -U to refetch sources,"
1336                         echo "or -5 to update md5 sums, if you're sure files are correct."
1337                         Exit_error err_no_source_in_repo $i
1338                 fi
1339         done
1340 }
1341
1342 get_files() {
1343         update_shell_title "get_files"
1344
1345         if [ -n "$DEBUG" ]; then
1346                 set -x
1347                 set -v
1348         fi
1349
1350         if [ $# -gt 0 ]; then
1351                 cd "$PACKAGE_DIR"
1352
1353                 local nc=0
1354                 local get_files_cvs=""
1355                 for i in "$@"; do
1356                         nc=$((nc + 1))
1357                         local cvsup=0
1358                         SHELL_TITLE_PREFIX="get_files[$nc/$#]"
1359                         update_shell_title "$i"
1360                         local fp=`nourl "$i"`
1361                         if [ "$SKIP_EXISTING_FILES" = "yes" ] && [ -f "$fp" ]; then
1362                                 continue
1363                         fi
1364
1365                         FROM_DISTFILES=0
1366                         local srcmd5=$(src_md5 "$i")
1367
1368                         # we know if source/patch is present in cvs/distfiles
1369                         # - has md5 (in distfiles)
1370                         # - in cvs... ideas?
1371
1372                         # CHECK: local file didn't exist or always cvs up (first) requested.
1373                         if [ ! -f "$fp" ] || [ $ALWAYS_CVSUP = "yes" ]; then
1374                                 if echo $i | grep -vE '(http|ftp|https|cvs|svn)://' | grep -qE '\.(gz|bz2)$']; then
1375                                         echo "Warning: no URL given for $i"
1376                                 fi
1377                                 target="$fp"
1378
1379                                 if [ -z "$NODIST" ] && [ -n "$srcmd5" ]; then
1380                                         if good_md5 "$i" && good_size "$i"; then
1381                                                 echo "$fp having proper md5sum already exists"
1382                                                 continue
1383                                         fi
1384
1385                                         # optionally prefer mirror over distfiles if there's mirror
1386                                         # TODO: build url list and then try each url from the list
1387                                         if [ -n "$PREFMIRRORS" ] && [ -z "$NOMIRRORS" ] && im=$(find_mirror "$i") && [ "$im" != "$i" ]; then
1388                                                 url="$im"
1389                                         else
1390                                                 url=$(distfiles_url "$i")
1391                                         fi
1392
1393                                         FROM_DISTFILES=1
1394                                         # is $url local file?
1395                                         if [[ "$url" = [./]* ]]; then
1396                                                 update_shell_title "${GETLOCAL%% *}: $url"
1397                                                 ${GETLOCAL} $url $target
1398                                         else
1399                                                 local uri=${url}
1400                                                 # make shorter message for distfiles urls
1401                                                 if [[ "$uri" = ${PROTOCOL}${DISTFILES_SERVER}* ]]; then
1402                                                         uri=${uri#${PROTOCOL}${DISTFILES_SERVER}/by-md5/?/?/*/}
1403                                                         uri="df: $uri"
1404                                                 fi
1405                                                 update_shell_title "${GETURI%% *}: $uri"
1406                                                 ${GETURI} "$target" "$url"
1407                                         fi
1408
1409
1410                                         if [ -s "$target" ]; then
1411                                                 cvsignore_df $target
1412                                         else
1413                                                 rm -f "$target"
1414                                                 FROM_DISTFILES=0
1415                                         fi
1416                                 fi
1417
1418                                 if [ -z "$NOURLS" ] && [ ! -f "$fp" -o -n "$UPDATE" ] && [ "`echo $i | grep -E 'ftp://|http://|https://'`" ]; then
1419                                         if [ -z "$NOMIRRORS" ]; then
1420                                                 im=$(find_mirror "$i")
1421                                         else
1422                                                 im="$i"
1423                                         fi
1424                                         update_shell_title "${GETURI%% *}: $im"
1425                                         ${GETURI} "$target" "$im"
1426                                         test -s "$target" || rm -f "$target"
1427                                 fi
1428
1429                                 if [ "$cvsup" = 1 ]; then
1430                                         continue
1431                                 fi
1432
1433                         fi
1434
1435                         # the md5 check must be moved elsewhere as if we've called from update_md5 the md5 is wrong.
1436                         if [ ! -f "$fp" -a "$FAIL_IF_NO_SOURCES" != "no" ]; then
1437                                 Exit_error err_no_source_in_repo $i
1438                         fi
1439
1440                         # we check md5 here just only to refetch immediately
1441                         if good_md5 "$i" && good_size "$i"; then
1442                                 :
1443                         elif [ "$FROM_DISTFILES" = 1 ]; then
1444                                 # wrong md5 from distfiles: remove the file and try again
1445                                 # but only once ...
1446                                 echo "MD5 sum mismatch. Trying full fetch."
1447                                 FROM_DISTFILES=2
1448                                 rm -f $target
1449                                 update_shell_title "${GETURI%% *}: $url"
1450                                 ${GETURI} "$target" "$url"
1451                                 test -s "$target" || rm -f "$target"
1452                         fi
1453                 done
1454                 SHELL_TITLE_PREFIX=""
1455
1456
1457                 if [ "$CHMOD" = "yes" ]; then
1458                         CHMOD_FILES=$(nourl "$@")
1459                         if [ -n "$CHMOD_FILES" ]; then
1460                                 chmod $CHMOD_MODE $CHMOD_FILES
1461                         fi
1462                 fi
1463         fi
1464 }
1465
1466 make_pkgrev() {
1467         if [ -n "$DEBUG" ]; then
1468                 set -x
1469                 set -v
1470         fi
1471
1472         TAGVER=$(echo $PKGREVS_PREFIX$PACKAGE_NAME-$PACKAGE_VERSION-$PACKAGE_RELEASE)
1473
1474         # Remove @kernel.version_release from TAGVER because tagging sources
1475         # could occur with different kernel-headers than kernel-headers used at build time.
1476         # besides, %{_kernel_ver_str} is not expanded.
1477
1478         # TAGVER=auto-ac-madwifi-ng-0-0_20070225_1@%{_kernel_ver_str}
1479         # TAGVER=auto-ac-madwifi-ng-0-0_20070225_1
1480
1481         TAGVER=${TAGVER%@*}
1482         echo -n "$TAGVER"
1483 }
1484
1485 get_pkgrev() {
1486         [ -z "$1" ] && return 1
1487         local _tmp=$(mktemp /tmp/.builder-XXXX)
1488         rm $_tmp 2>/dev/null
1489         $GETURI $OUTFILEOPT $_tmp $PKGREVS_URL/get/$1 1>/dev/null 2>&1 || Exit_error err_pkgrev_get "$1"
1490         local result=$(cat $_tmp)
1491         rm $_tmp 2>/dev/null
1492         echo -n "$result"
1493 }
1494
1495 set_pkgrev() {
1496         local _tag
1497         parse_spec "$1"
1498         _tag=`make_pkgrev`
1499         echo "Writing git revision for tag $_tag"
1500         local _tmp=$(mktemp /tmp/.builder-XXXX)
1501         rm $_tmp 2>/dev/null
1502         local _rev=$(git rev-parse HEAD)
1503         $GETURI $OUTFILEOPT $_tmp $PKGREVS_URL/set/$_rev/$_tag 1>/dev/null 2>&1 || Exit_error err_pkgrev_get "$1"
1504         local result=$(cat $_tmp)
1505         rm $_tmp 2>/dev/null
1506         [ "$(get_pkgrev "$_tag")" = "$CVSTAG" ] && return 0
1507         echo "$result" | grep -q -E "^OK$" && return 0
1508         echo "$result" | grep -q -E "^EXISTS$" && Exit_error err_pkgrev_exists "$_tag"
1509         Exit_error err_pkgrev_set
1510 }
1511
1512 list_pkgrev() {
1513         local _tmp=$(mktemp /tmp/.builder-XXXX)
1514         rm $_tmp 2>/dev/null
1515         $GETURI $OUTFILEOPT $_tmp $PKGREVS_URL/list/$PACKAGE_NAME 1>/dev/null 2>&1
1516         cat $_tmp
1517         rm $_tmp 2>/dev/null
1518 }
1519
1520 branch_files() {
1521         TAG=$1
1522         echo "Git branch: $TAG"
1523         shift
1524
1525         if [ -n "$DEBUG" ]; then
1526                 set -x
1527                 set -v
1528         fi
1529
1530         local OPTIONS="branch $CVS_FORCE"
1531
1532         cd "$PACKAGE_DIR"
1533         git $OPTIONS $TAG || exit
1534 }
1535
1536
1537 # this function should exit early if package can't be built for this arch
1538 # this avoids unneccessary BR filling.
1539 check_buildarch() {
1540         local out ret
1541         out=$(minirpm --short-circuit -bp --define "'prep exit 0'" --nodeps $SPECFILE 2>&1)
1542         ret=$?
1543         if [ $ret -ne 0 ]; then
1544                 echo >&2 "$out"
1545                 exit $ret
1546         fi
1547 }
1548
1549 # from relup.sh
1550 set_release() {
1551         local specfile="$1"
1552         local rel="$2"
1553         local newrel="$3"
1554         sed -i -e "
1555                 s/^\(%define[ \t]\+_\?rel[ \t]\+\)$rel\$/\1$newrel/
1556                 s/^\(Release:[ \t]\+\)$rel\$/\1$newrel/
1557         " $specfile
1558 }
1559
1560 set_version() {
1561         local specfile="$1"
1562         local ver="$2" subver=$ver
1563         local newver="$3" newsubver=$newver
1564
1565         # try handling subver, everything that's not numeric-dotted in version
1566         if grep -Eq '%define\s+subver' $specfile; then
1567                 subver=$(echo "$ver" | sed -re 's,^[0-9.]+,,')
1568                 ver=${ver%$subver}
1569                 newsubver=$(echo "$newver" | sed -re 's,^[0-9.]+,,')
1570                 newver=${newver%$newsubver}
1571         fi
1572         sed -i -e "
1573                 s/^\(%define[ \t]\+_\?ver[ \t]\+\)$ver\$/\1$newver/
1574                 s/^\(%define[ \t]\+subver[ \t]\+\)$subver\$/\1$newsubver/
1575                 s/^\(Version:[ \t]\+\)$ver\$/\1$newver/
1576         " $specfile
1577 }
1578
1579 # try to upgrade .spec to new version
1580 # if --upgrade-version is specified, use that as new version, otherwise invoke pldnotify to find new version
1581 #
1582 # return 1: if .spec was updated
1583 # return 0: no changes to .spec
1584 # exit 1 in case of error
1585 try_upgrade() {
1586         if [ -z "$TRY_UPGRADE" ]; then
1587                 return 0
1588         fi
1589
1590         local TNOTIFY TNEWVER TOLDVER
1591         update_shell_title "build_package: try_upgrade"
1592
1593         cd "$PACKAGE_DIR"
1594
1595         if [ "$UPGRADE_VERSION" ]; then
1596                 TNEWVER=$UPGRADE_VERSION
1597                 echo "Updating spec file to version $TNEWVER"
1598         else
1599                 if [ -n "$FLOAT_VERSION" ]; then
1600                         TNOTIFY=$(pldnotify ${BE_VERBOSE:+-vDEBUG=1} $SPECFILE -n) || exit 1
1601                 else
1602                         TNOTIFY=$(pldnotify ${BE_VERBOSE:+-vDEBUG=1} $SPECFILE) || exit 1
1603                 fi
1604
1605                 # pldnotify does not set exit codes, but it has match for ERROR
1606                 # in output which means so.
1607                 if [[ "$TNOTIFY" = *ERROR* ]]; then
1608                         echo >&2 "$TNOTIFY"
1609                         exit 1
1610                 fi
1611
1612                 TOLDVER=`echo $TNOTIFY | awk '{ print $3; }'`
1613                 echo "New version found, updating spec file from $TOLDVER to version $TNEWVER"
1614
1615                 TNEWVER=$(echo $TNOTIFY | awk '{ match($4,/\[NEW\]/); print $5 }')
1616         fi
1617
1618         if [ -z "$TNEWVER" ]; then
1619                 return 0
1620         fi
1621
1622         if [ "$REVERT_BROKEN_UPGRADE" = "yes" ]; then
1623                 cp -f $SPECFILE $SPECFILE.bak
1624         fi
1625         chmod +w $SPECFILE
1626         set_version $SPECFILE $PACKAGE_VERSION $TNEWVER
1627         set_release $SPECFILE $PACKAGE_RELEASE 1
1628         parse_spec
1629         if [ "$PACKAGE_VERSION" != "$TNEWVER" ]; then
1630                 echo >&2 "Upgrading version failed, you need to update spec yourself"
1631                 exit 1
1632         fi
1633         return 1
1634 }
1635
1636 build_package() {
1637         update_shell_title "build_package"
1638         if [ -n "$DEBUG" ]; then
1639                 set -x
1640                 set -v
1641         fi
1642
1643         cd "$PACKAGE_DIR"
1644
1645         case "$COMMAND" in
1646                 build )
1647                         BUILD_SWITCH="-ba" ;;
1648                 build-binary )
1649                         BUILD_SWITCH="-bb" ;;
1650                 build-source )
1651                         BUILD_SWITCH="-bs --nodeps" ;;
1652                 build-prep )
1653                         BUILD_SWITCH="-bp --nodeps" ;;
1654                 build-build )
1655                         BUILD_SWITCH="-bc" ;;
1656                 build-install )
1657                         BUILD_SWITCH="-bi" ;;
1658                 build-list )
1659                         BUILD_SWITCH="-bl" ;;
1660
1661         esac
1662
1663         update_shell_title "build_package: $COMMAND"
1664         local logfile retval
1665         if [ -n "$LOGFILE" ]; then
1666                 logfile=`eval echo $LOGFILE`
1667                 if [ -d "$logfile" ]; then
1668                         echo "Log file $logfile is a directory."
1669                         echo "Parse error in the spec?"
1670                         Exit_error err_build_fail
1671                 fi
1672                 if [ -n "$LASTLOG_FILE" ]; then
1673                         echo "LASTLOG=$logfile" > $LASTLOG_FILE
1674                 fi
1675         fi
1676
1677         # unset these, should not be exposed to builder shell!
1678         unset GIT_WORK_TREE GIT_DIR
1679         # these are set by jenkins
1680         unset GIT_PREVIOUS_COMMIT GIT_URL GIT_PREVIOUS_SUCCESSFUL_COMMIT GIT_BRANCH GIT_COMMIT
1681         # this may be set by user
1682         unset GIT_SSH
1683         # may be set by user
1684         unset GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_TESTING_PORCELAIN_COMMAND_LIST
1685         # fail if something still set
1686         env | grep ^GIT_ && Exit_error err_build_fail
1687
1688         local specdir=$(insert_gitlog $SPECFILE)
1689         ulimit -c unlimited
1690         # If required exclude directories with systemd related files from package contents
1691         if grep -q -E 'systemd(unitdir|userunitdir|tmpfilesdir)' $specdir/$SPECFILE; then
1692                 sed -i -e '/^%exclude_systemd_files/d; /^%files/s/$/\n%exclude_systemd_files/g;' $specdir/$SPECFILE
1693         fi
1694         # Enable/disable distro wide bconds based on ~/.distbcond
1695         process_distbcond "$specdir/$SPECFILE"
1696         # Add %tld macro to release to allow release control
1697         sed -i -r -e '/^Release:/s/%\{\?tld\}//g; s/^Release:\s+(.*)$/Release:\t\1%{?tld}/;' $specdir/$SPECFILE
1698         # FIXME: eval here is exactly why?
1699         PATH=$CLEAN_PATH eval teeboth "'$logfile'" ${TIME_COMMAND} ${NICE_COMMAND} $RPMBUILD $TARGET_SWITCH $BUILD_SWITCH -v $QUIET $CLEAN $RPMOPTS $RPMUSERDEFS $RPMBUILDOPTS $BCOND --define \'_specdir $PACKAGE_DIR\' --define \'_sourcedir $PACKAGE_DIR\' $specdir/$SPECFILE
1700         retval=$?
1701
1702         # Set pkgrev if requested and build status is OK
1703         if [ ! -z "$SETPKGREV" ] && [ "$SETPKGREV" = "true" ] && [ "$retval" -eq "0" ]; then
1704                 set_pkgrev "$specdir/$SPECFILE"
1705         fi
1706
1707         rm -r $specdir
1708
1709         if [ -n "$logfile" ] && [ -n "$LOGDIROK" ] && [ -n "$LOGDIRFAIL" ]; then
1710                 if [ "$retval" -eq "0" ]; then
1711                         mv $logfile $LOGDIROK
1712                 else
1713                         mv $logfile $LOGDIRFAIL
1714                 fi
1715         fi
1716
1717         if [ "$retval" -ne "0" ]; then
1718                 if [ -n "$TRY_UPGRADE" ]; then
1719                         echo "\nUpgrade package to new version failed."
1720                         if [ "$REVERT_BROKEN_UPGRADE" = "yes" ]; then
1721                                 echo "Restoring old spec file."
1722                                 mv -f $SPECFILE.bak $SPECFILE
1723                         fi
1724                         echo ""
1725                 fi
1726                 Exit_error err_build_fail
1727         fi
1728         unset BUILD_SWITCH
1729 }
1730
1731 nourl() {
1732         echo "$@" | sed 's#\<\(ftp\|http\|https\|cvs\|svn\)://[^ ]*/##g'
1733 }
1734
1735 install_required_packages() {
1736         run_poldek -vi $1
1737         return $?
1738 }
1739
1740 find_spec_bcond() { # originally from /usr/lib/rpm/find-spec-bcond
1741         local SPEC="$1"
1742         awk -F"\n" '
1743         /^%changelog/ { exit }
1744         /^%bcond_with/{
1745                 match($0, /bcond_with(out)?[ \t]+[_a-zA-Z0-9]+/);
1746                 bcond = substr($0, RSTART + 6, RLENGTH - 6);
1747                 gsub(/[ \t]+/, "_", bcond);
1748                 print bcond
1749         }' $SPEC | LC_ALL=C sort -u
1750 }
1751
1752 process_bcondrc() {
1753         # expand bconds from ~/.bcondrc
1754         # The file structure is like gentoo's package.use:
1755         # ---
1756         # * -selinux
1757         # samba -mysql -pgsql
1758         # w32codec-installer license_agreement
1759         # php +mysqli
1760         # ---
1761         if [ -f $HOME/.bcondrc ] || ([ -n $HOME_ETC ] && [ -f $HOME_ETC/.bcondrc ]); then
1762                 :
1763         else
1764                 return
1765         fi
1766
1767         SN=${SPECFILE%%\.spec}
1768
1769         local bcondrc=$HOME/.bcondrc
1770         [ -n $HOME_ETC ] && [ -f $HOME_ETC/.bcondrc ] && bcondrc=$HOME_ETC/.bcondrc
1771
1772         local bcond_avail=$(find_spec_bcond $SPECFILE)
1773
1774         while read pkg flags; do
1775                 # ignore comments
1776                 [[ "$pkg" == \#* ]] && continue
1777
1778                 # any package or current package?
1779                 if [ "$pkg" = "*" ] || [ "$pkg" = "$PACKAGE_NAME" ] || [ "$pkg" = "$SN" ]; then
1780                         for flag in $flags; do
1781                                 local opt=${flag#[+-]}
1782
1783                                 # use only flags which are in this package.
1784                                 if [[ $bcond_avail = *${opt}* ]]; then
1785                                         if [[ $flag = -* ]]; then
1786                                                 if [[ $BCOND != *--with?${opt}* ]]; then
1787                                                         BCOND="$BCOND --without $opt"
1788                                                 fi
1789                                         else
1790                                                 if [[ $BCOND != *--without?${opt}* ]]; then
1791                                                         BCOND="$BCOND --with $opt"
1792                                                 fi
1793                                         fi
1794                                 fi
1795                         done
1796                 fi
1797         done < $bcondrc
1798         update_shell_title "parse ~/.bcondrc: DONE!"
1799 }
1800
1801 process_distbcond() {
1802         # apply bconds from ~/.distbcond to spec
1803         # The file structure is like gentoo's package.use:
1804         # ---
1805         # * -selinux
1806         # samba -mysql -pgsql
1807         # w32codec-installer license_agreement
1808         # php +mysqli
1809         # ---
1810         if [ -f $HOME/.distbcond ] || ([ -n $HOME_ETC ] && [ -f $HOME_ETC/.distbcond ]); then
1811                 :
1812         else
1813                 return
1814         fi
1815
1816         SN=${SPECFILE%%\.spec}
1817
1818         local distbcond=$HOME/.distbcond
1819         [ -n $HOME_ETC ] && [ -f $HOME_ETC/.distbcond ] && distbcond=$HOME_ETC/.distbcond
1820
1821         local bcond_avail=$(find_spec_bcond $SPECFILE)
1822
1823         while read pkg flags; do
1824                 # ignore comments
1825                 [[ "$pkg" == \#* ]] && continue
1826
1827                 # any package or current package?
1828                 if [ "$pkg" = "*" ] || [ "$pkg" = "$PACKAGE_NAME" ] || [ "$pkg" = "$SN" ]; then
1829                         for flag in $flags; do
1830                                 local opt=${flag#[+-]}
1831
1832                                 # use only flags which are in this package.
1833                                 if [[ $bcond_avail = *${opt}* ]]; then
1834                                         if [[ $flag = -* ]]; then
1835                                                 sed -i -r -e '/^%bcond_(with|without)\s+'$opt'/s/^%bcond_(with|without)/%bcond_with/g;' "$1"
1836                                         elif [[ $flag = +* ]]; then
1837                                                 sed -i -r -e '/^%bcond_(with|without)\s+'$opt'/s/^%bcond_(with|without)/%bcond_without/g;' "$1"
1838                                         fi
1839                                 fi
1840                         done
1841                 fi
1842         done < $distbcond
1843         update_shell_title "parse ~/.distbcond: DONE!"
1844 }
1845
1846 set_bconds_values() {
1847         update_shell_title "set bcond values"
1848
1849         AVAIL_BCONDS_WITHOUT=""
1850         AVAIL_BCONDS_WITH=""
1851
1852         if grep -Eq '^# *_with' ${SPECFILE}; then
1853                 echo >&2 "ERROR: This spec has old style bconds."
1854                 exit 1
1855         fi
1856
1857         if ! grep -q '^%bcond' ${SPECFILE}; then
1858                 return
1859         fi
1860
1861         local bcond_avail=$(find_spec_bcond $SPECFILE)
1862         process_bcondrc "$SPECFILE"
1863
1864         update_shell_title "parse bconds"
1865
1866         local opt bcond
1867         for opt in $bcond_avail; do
1868                 case "$opt" in
1869                 without_*)
1870                         bcond=${opt#without_}
1871                         case "$BCOND" in
1872                         *--without?${bcond}\ *|*--without?${bcond})
1873                                 AVAIL_BCONDS_WITHOUT="$AVAIL_BCONDS_WITHOUT <$bcond>"
1874                                 ;;
1875                         *)
1876                                 AVAIL_BCONDS_WITHOUT="$AVAIL_BCONDS_WITHOUT $bcond"
1877                                 ;;
1878                         esac
1879                         ;;
1880                 with_*)
1881                         bcond=${opt#with_}
1882                         case "$BCOND" in
1883                         *--with?${bcond}\ *|*--with?${bcond})
1884                                 AVAIL_BCONDS_WITH="$AVAIL_BCONDS_WITH <$bcond>"
1885                                 ;;
1886                         *)
1887                                 AVAIL_BCONDS_WITH="$AVAIL_BCONDS_WITH $bcond"
1888                                 ;;
1889                         esac
1890                         ;;
1891                 *)
1892                         echo >&2 "ERROR: unexpected '$opt' in set_bconds_values"
1893                         exit 1
1894                         ;;
1895                 esac
1896         done
1897 }
1898
1899 run_sub_builder() {
1900         package_name="${1}"
1901         update_shell_title "run_sub_builder $package_name"
1902         #
1903         # No i tutaj bym chciaÅ‚ zrobić sztucznÄ… inteligencjÄ™, która spróbuje tego
1904         # pakieta zbudować. Aktualnie niewiele dziala, bo generalnie nie widze do
1905         # konca algorytmu... Ale damy rade. :) Na razie po prostu sie wyjebie tak samo
1906         # jakby nie bylo tego kawalka kodu.
1907         #
1908         # Update: PoprawiÅ‚em parÄ™ rzeczy i zaczęło generować pakiety spoza zadanej listy.
1909         #         Jednym sÅ‚owem budowanie niespoldkowanych zależnoÅ›ci dziaÅ‚a w paru przypadkach.
1910         #
1911         #
1912         # y0shi.
1913         # kurwa. translate that ^^^^
1914
1915         parent_spec_name=''
1916
1917         # Istnieje taki spec? ${package}.spec
1918         if [ -f "${PACKAGE_DIR}/${package}.spec" ]; then
1919                 parent_spec_name=${package}.spec
1920         elif [ -f "${PACKAGE_DIR}/$(echo ${package_name} | sed -e s,-devel.*,,g -e s,-static,,g).spec" ]; then
1921                 parent_spec_name="$(echo ${package_name} | sed -e s,-devel.*,,g -e s,-static,,g).spec"
1922         else
1923                 for provides_line in $(grep -r ^Provides:.*$package ${PACKAGE_DIR}); do
1924                         echo $provides_line
1925                 done
1926         fi
1927
1928         if [ "${parent_spec_name}" != "" ]; then
1929                 spawn_sub_builder $parent_spec_name
1930         fi
1931         NOT_INSTALLED_PACKAGES="$NOT_INSTALLED_PACKAGES $package_name"
1932 }
1933
1934 # install package with poldek
1935 # @return exit code from poldek
1936 #
1937 # this requires following sudo rules:
1938 # - poldek --noask --caplookup -ug
1939 poldek_install() {
1940         LC_ALL=C LANG=C $POLDEK_CMD --noask --caplookup --uniq -ug "$@"
1941 }
1942
1943 # install packages
1944 #
1945 # this requires following sudo rules:
1946 # - poldek -q --update --upa
1947 install_packages() {
1948         # sync poldek indexes once per invocation
1949         if [ -z "$package_indexes_updated" ]; then
1950                 update_shell_title "poldek: update indexes"
1951                 $POLDEK_CMD -q --update --upa --mo=nodesc
1952                 package_indexes_updated=true
1953         fi
1954
1955         update_shell_title "install packages: $*"
1956         poldek_install "$@" && return
1957
1958         # retry install, install packages one by one
1959         # this is slower one
1960         local rc=0 package
1961         for package in $*; do
1962                 package=$(depspecname $package)
1963                 update_shell_title "install package: $package"
1964                 poldek_install "$package" || rc=$?
1965         done
1966         return $rc
1967 }
1968
1969 uninstall_packages() {
1970         update_shell_title "uninstall packages: $*"
1971         $POLDEK_CMD --noask --nofollow -ev "$@"
1972 }
1973
1974 spawn_sub_builder() {
1975         package_name="${1}"
1976         update_shell_title "spawn_sub_builder $package_name"
1977
1978         sub_builder_opts=''
1979         if [ "${FETCH_BUILD_REQUIRES}" = "yes" ]; then
1980                 sub_builder_opts="${sub_builder_opts} -R"
1981         fi
1982         if [ "${REMOVE_BUILD_REQUIRES}" = "nice" ]; then
1983                 sub_builder_opts="${sub_builder_opts} -RB"
1984         elif [ "${REMOVE_BUILD_REQUIRES}" = "force" ]; then
1985                 sub_builder_opts="${sub_builder_opts} -FRB"
1986         fi
1987         if [ "${UPDATE_POLDEK_INDEXES}" = "yes" ]; then
1988                 sub_builder_opts="${sub_builder_opts} -Upi"
1989         fi
1990
1991         cd "${PACKAGE_DIR}"
1992         ./builder ${sub_builder_opts} "$@"
1993 }
1994
1995 remove_build_requires() {
1996         if [ "$INSTALLED_PACKAGES" != "" ]; then
1997                 case "$REMOVE_BUILD_REQUIRES" in
1998                         "force")
1999                                 run_poldek --noask -ve $INSTALLED_PACKAGES
2000                                 ;;
2001                         "nice")
2002                                 run_poldek --ask -ve $INSTALLED_PACKAGES
2003                                 ;;
2004                         *)
2005                                 echo You may want to manually remove following BuildRequires fetched:
2006                                 echo $INSTALLED_PACKAGES
2007                                 echo "Try poldek -e \`cat $(pwd)/.${SPECFILE}_INSTALLED_PACKAGES\`"
2008                                 ;;
2009                 esac
2010         fi
2011 }
2012
2013 display_bconds() {
2014         if [ "$AVAIL_BCONDS_WITH" -o "$AVAIL_BCONDS_WITHOUT" ]; then
2015                 if [ "$BCOND" ]; then
2016                         echo ""
2017                         echo "Building $SPECFILE with the following conditional flags:"
2018                         echo -n "$BCOND"
2019                 else
2020                         echo ""
2021                         echo "No conditional flags passed"
2022                 fi
2023                 echo ""
2024                 echo "from available:"
2025                 echo "--with   :\t$AVAIL_BCONDS_WITH"
2026                 echo "--without:\t$AVAIL_BCONDS_WITHOUT"
2027                 echo ""
2028         fi
2029 }
2030
2031 display_branches() {
2032         echo -n "Available branches: "
2033         git branch -r 2>/dev/null | grep "^  ${REMOTE_PLD}" | grep -v ${REMOTE_PLD}/HEAD | sed "s#^ *${REMOTE_PLD}/##" | xargs
2034 }
2035
2036 # checks a given list of packages/files/provides against current rpmdb.
2037 # outputs all dependencies which current rpmdb doesn't satisfy.
2038 # input can be either STDIN or parameters
2039 _rpm_prov_check() {
2040         local deps out
2041
2042         if [ $# -gt 0 ]; then
2043                 deps="$@"
2044         else
2045                 deps=$(cat)
2046         fi
2047
2048         out=$(LC_ALL=C rpm -q --whatprovides $deps 2>&1)
2049
2050         # packages
2051         echo "$out" | awk '/^no package provides/ { print $NF }'
2052
2053         # other deps (files)
2054         echo "$out" | sed -rne 's/file (.*): No such file or directory/\1/p'
2055 }
2056
2057 # checks if given package/files/provides exists in rpmdb.
2058 # input can be either stdin or parameters
2059 # returns packages which are present in the rpmdb
2060 _rpm_cnfl_check() {
2061         local DEPS
2062
2063         if [ $# -gt 0 ]; then
2064                 DEPS="$@"
2065         else
2066                 DEPS=$(cat)
2067         fi
2068
2069         LC_ALL=C LANG=C rpm -q --whatprovides $DEPS 2>/dev/null | awk '!/no package provides/ { print }'
2070 }
2071
2072 # install deps via information from 'rpm-getdeps' or 'rpm --specsrpm'
2073 install_build_requires_rpmdeps() {
2074         local DEPS CNFL
2075         if [ "$FETCH_BUILD_REQUIRES_RPMGETDEPS" = "yes" ]; then
2076                 # TODO: Conflicts list doesn't check versions
2077                 CNFL=$(eval rpm-getdeps $BCOND $RPMOPTS $RPMUSERDEFS $SPECFILE 2> /dev/null | awk '/^\-/ { print $3 } ' | _rpm_cnfl_check | xargs)
2078                 DEPS=$(eval rpm-getdeps $BCOND $RPMOPTS $RPMUSERDEFS $SPECFILE 2> /dev/null | awk '/^\+/ { print $3 } ' | _rpm_prov_check | xargs)
2079         fi
2080         if [ "$FETCH_BUILD_REQUIRES_RPMSPECSRPM" = "yes" ]; then
2081                 CNFL=$(eval rpm -q --specsrpm --conflicts $BCOND $RPMOPTS $RPMUSERDEFS $SPECFILE | awk '{print $1}' | _rpm_cnfl_check | xargs)
2082                 DEPS=$(eval rpm -q --specsrpm --requires $BCOND $RPMOPTS $RPM_USERDEFS $SPECFILE | awk '{print $1}' | _rpm_prov_check | xargs)
2083         fi
2084
2085         if [ -n "$CNFL" ]; then
2086                 echo "Uninstall conflicting packages: $CNFL"
2087                 uninstall_packages $CNFL
2088         fi
2089
2090         if [ -n "$DEPS" ]; then
2091                 echo "Install dependencies: $DEPS"
2092                 install_packages $DEPS
2093         fi
2094 }
2095
2096 fetch_build_requires()
2097 {
2098         if [ "${FETCH_BUILD_REQUIRES}" != "yes" ]; then
2099                 return
2100         fi
2101
2102         update_shell_title "fetch build requires"
2103         if [ "$FETCH_BUILD_REQUIRES_RPMGETDEPS" = "yes" ] || [ "$FETCH_BUILD_REQUIRES_RPMSPECSRPM" = "yes" ]; then
2104                 install_build_requires_rpmdeps
2105                 return
2106         fi
2107
2108         die "need rpm-getdeps tool"
2109 }
2110
2111 init_repository() {
2112         local remoterepo=$1
2113         local localrepo=$2
2114
2115         if [ ! -e $localrepo ]; then
2116                 git clone $IPOPT -o $REMOTE_PLD ${GIT_SERVER}/$remoterepo $localrepo
2117                 git --git-dir=$localrepo/.git remote set-url --push  $REMOTE_PLD ssh://${GIT_PUSH}/$remoterepo
2118         fi
2119 }
2120
2121 init_rpm_dir() {
2122         local TOP_DIR=$(eval $RPM $RPMOPTS $RPMUSERDEFS --eval '%{_topdir}')
2123         local rpmdir=$(eval $RPM $RPMOPTS $RPMUSERDEFS --eval '%{_rpmdir}')
2124         local buildir=$(eval $RPM $RPMOPTS $RPMUSERDEFS --eval '%{_builddir}')
2125         local srpmdir=$(eval $RPM $RPMOPTS $RPMUSERDEFS --eval '%{_srcrpmdir}')
2126         local TEMPLATES=template-specs
2127         local tmp
2128
2129         echo "Initializing rpm directories to $TOP_DIR from $GIT_SERVER"
2130         mkdir -p $TOP_DIR $rpmdir $buildir $srpmdir
2131
2132         cd "$TOP_DIR"
2133         init_repository ${PACKAGES_DIR}/rpm-build-tools.git ../rpm-build-tools
2134         init_repository projects/$TEMPLATES ../$TEMPLATES
2135         for a in builder fetchsrc_request compile repackage; do
2136                 ln -sf ../rpm-build-tools/${a}.sh $a
2137         done
2138         for a in md5; do
2139                 ln -sf ../rpm-build-tools/${a} $a
2140         done
2141         ln -sf ../rpm-build-tools/mirrors mirrors
2142         init_builder
2143 }
2144
2145 mr_proper() {
2146         init_builder
2147         NOCVSSPEC="yes"
2148         DONT_PRINT_REVISION="yes"
2149
2150         # remove spec and sources
2151         PATH=$CLEAN_PATH $RPMBUILD --clean --rmsource --rmspec --nodeps --define "__urlgetfile() %nil" --define "_specdir $PACKAGE_DIR" --define "_sourcedir $PACKAGE_DIR" --define "_builddir $builddir" $PACKAGE_DIR/$SPECFILE
2152         rm -rf $PACKAGE_DIR/{.git,.gitignore}
2153         rmdir --ignore-fail-on-non-empty $PACKAGE_DIR
2154 }
2155
2156 #---------------------------------------------
2157 # main()
2158
2159 if [ $# = 0 ]; then
2160         usage
2161         exit 1
2162 fi
2163
2164 # stuff global $BUILDER_OPTS from env as args
2165 if [ "$BUILDER_OPTS" ]; then
2166         set -- "$BUILDER_OPTS" "$@"
2167 fi
2168
2169 while [ $# -gt 0 ]; do
2170         case "${1}" in
2171                 -4|-6)
2172                         IPOPT="${1}"
2173                         shift
2174                         ;;
2175                 -5 | --update-md5)
2176                         COMMAND="update_md5"
2177                         NODIST="yes"
2178                         NOCVSSPEC="yes"
2179                         shift ;;
2180                 -a5 | --add-md5 )
2181                         COMMAND="update_md5"
2182                         NODIST="yes"
2183                         NOCVSSPEC="yes"
2184                         ADD5="yes"
2185                         shift ;;
2186                 -n5 | --no-md5 )
2187                         NO5="yes"
2188                         shift ;;
2189                 -D | --debug )
2190                         DEBUG="yes"; shift ;;
2191                 -V | --version )
2192                         COMMAND="version"; shift ;;
2193                 --short-version )
2194                         COMMAND="short-version"; shift ;;
2195                 -a | --add_cvs)
2196                         COMMAND="add_cvs";
2197                         shift ;;
2198                 --all-branches )
2199                         ALL_BRANCHES="yes"
2200                         shift ;;
2201                 -b | -ba | --build )
2202                         COMMAND="build"; shift ;;
2203                 -bb | --build-binary )
2204                         COMMAND="build-binary"; shift ;;
2205                 -bc )
2206                         COMMAND="build-build"; shift ;;
2207                 -bi )
2208                         COMMAND="build-install"; shift ;;
2209                 -bl )
2210                         COMMAND="build-list"; shift ;;
2211                 -bp | --build-prep )
2212                         COMMAND="build-prep"; shift ;;
2213                 -bs | --build-source )
2214                         COMMAND="build-source"; shift ;;
2215                 -B | --branch )
2216                         COMMAND="branch"; shift; TAG="${1}"; shift;;
2217                 -c | --clean )
2218                         CLEAN="--clean"; shift ;;
2219                 -cf | --cvs-force )
2220                         CVS_FORCE="-f"; shift;;
2221                 --depth )
2222                         DEPTH="--depth=$2"
2223                         shift 2
2224                         ;;
2225                 -g | --get )
2226                         COMMAND="get"; shift ;;
2227                 -h | --help )
2228                         COMMAND="usage"; shift ;;
2229                 --ftp )
2230                         PROTOCOL="ftp"; shift ;;
2231                 --http )
2232                         PROTOCOL="http"; shift ;;
2233                 -j)
2234                         RPMOPTS="${RPMOPTS} --define \"_smp_mflags -j$2\""
2235                         shift 2
2236                         ;;
2237                 -j[0-9]*)
2238                         RPMOPTS="${RPMOPTS} --define \"_smp_mflags $1\""
2239                         shift
2240                         ;;
2241                 -p)
2242                         PARALLEL_DOWNLOADS=$2
2243                         shift 2
2244                         ;;
2245                 -p[0-9])
2246                         PARALLEL_DOWNLOADS=${1#-p}
2247                         shift
2248                         ;;
2249                 -l | --logtofile )
2250                         shift; LOGFILE="${1}"; shift ;;
2251                 -ni| --nice )
2252                         shift; DEF_NICE_LEVEL=${1}; shift ;;
2253                 -ske | --skip-existing-files)
2254                         SKIP_EXISTING_FILES="yes"; shift ;;
2255                 -m | --mr-proper )
2256                         COMMAND="mr-proper"; shift ;;
2257                 -ncs | --no-cvs-specs )
2258                         NOCVSSPEC="yes"; shift ;;
2259                 -nd | --no-distfiles )
2260                         NODIST="yes"; shift ;;
2261                 -nm | --no-mirrors )
2262                         NOMIRRORS="yes"; shift ;;
2263                 -nu | --no-urls )
2264                         NOURLS="yes"; shift ;;
2265                 -ns | --no-srcs )
2266                         NOSRCS="yes"; shift ;;
2267                 -ns0 | --no-source0 )
2268                         NOSOURCE0="yes"; shift ;;
2269                 -nn | --no-net )
2270                         NOCVSSPEC="yes"
2271                         NODIST="yes"
2272                         NOMIRRORS="yes"
2273                         NOURLS="yes"
2274                         NOSRCS="yes"
2275                         ALWAYS_CVSUP="no"
2276                         shift;;
2277                 -pm | --prefer-mirrors )
2278                         PREFMIRRORS="yes"
2279                         shift;;
2280                 --noinit | --no-init )
2281                         NOINIT="yes"
2282                         shift;;
2283                 --opts )
2284                         shift; RPMOPTS="${RPMOPTS} ${1}"; shift ;;
2285                 --nopatch | -np )
2286                         shift; RPMOPTS="${RPMOPTS} --define \"patch${1} : ignoring patch${1}; exit 1; \""; shift ;;
2287                 --skip-patch | -sp )
2288                         shift; RPMOPTS="${RPMOPTS} --define \"patch${1} : skiping patch${1}\""; shift ;;
2289                 --topdir)
2290                         RPMOPTS="${RPMOPTS} --define \"_topdir $2\""
2291                         shift 2
2292                         ;;
2293                 --with | --without )
2294                         case $GROUP_BCONDS in
2295                                 "yes")
2296                                         COND=${1}
2297                                         shift
2298                                         # XXX: broken: ./builder -bb ucspi-tcp.spec --without mysql
2299                                         while ! `echo ${1}|grep -qE '(^-|spec)'`
2300                                         do
2301                                                 BCOND="$BCOND $COND $1"
2302                                                 shift
2303                                         done;;
2304                                 "no")
2305                                         if [[ "$2" = *,* ]]; then
2306                                                 for a in $(echo "$2" | tr , ' '); do
2307                                                         BCOND="$BCOND $1 $a"
2308                                                 done
2309                                         else
2310                                                 BCOND="$BCOND $1 $2"
2311                                         fi
2312                                         shift 2 ;;
2313                         esac
2314                         ;;
2315                 --target )
2316                         shift; TARGET="${1}"; shift ;;
2317                 --target=* )
2318                         TARGET=$(echo "${1}" | sed 's/^--target=//'); shift ;;
2319                 -q | --quiet )
2320                         QUIET="--quiet"; shift ;;
2321                 --date )
2322                         CVSDATE="${2}"; shift 2
2323                         date -d "$CVSDATE" > /dev/null 2>&1 || { echo >&2 "No valid date specified"; exit 3; }
2324                         ;;
2325                 -r | --cvstag )
2326                         CVSTAG="$2"
2327                         shift 2
2328                         ;;
2329                 -A)
2330                         shift
2331                         CVSTAG="master"
2332                         ;;
2333                 -R | --fetch-build-requires)
2334                         FETCH_BUILD_REQUIRES="yes"
2335                         NOT_INSTALLED_PACKAGES=
2336                         shift ;;
2337                 -RB | --remove-build-requires)
2338                         REMOVE_BUILD_REQUIRES="nice"
2339                         shift ;;
2340                 -FRB | --force-remove-build-requires)
2341                         REMOVE_BUILD_REQUIRES="force"
2342                         shift ;;
2343                 -sc | --source-cvs)
2344                         COMMAND="list-sources-cvs"
2345                         shift ;;
2346                 -sd | --source-distfiles)
2347                         COMMAND="list-sources-distfiles"
2348                         shift ;;
2349                 -sdp | --source-distfiles-paths)
2350                         COMMAND="list-sources-distfiles-paths"
2351                         shift ;;
2352                 -sf | --source-files)
2353                         COMMAND="list-sources-files"
2354                         shift ;;
2355                 -lsp | --source-paths)
2356                         COMMAND="list-sources-local-paths"
2357                         shift ;;
2358                 -su | --source-urls)
2359                         COMMAND="list-sources-urls"
2360                         shift ;;
2361                 -ir | --integer-release-only )
2362                         INTEGER_RELEASE="yes"
2363                         shift;;
2364                 -U | --update )
2365                         COMMAND="update_md5"
2366                         UPDATE="yes"
2367                         NOCVSSPEC="yes"
2368                         NODIST="yes"
2369                         shift ;;
2370                 -Upi | --update-poldek-indexes )
2371                         UPDATE_POLDEK_INDEXES="yes"
2372                         shift ;;
2373                 --init-rpm-dir|--init)
2374                         COMMAND="init_rpm_dir"
2375                         shift ;;
2376                 -u | --try-upgrade )
2377                         TRY_UPGRADE="1"; shift ;;
2378                 --upgrade-version )
2379                         shift; UPGRADE_VERSION="$1"; shift;;
2380                 -un | --try-upgrade-with-float-version )
2381                         TRY_UPGRADE="1"; FLOAT_VERSION="1"; shift ;;
2382                 -v | --verbose )
2383                         BE_VERBOSE="1"; shift ;;
2384                 --define)
2385                         shift
2386                         MACRO="${1}"
2387                         shift
2388                         if echo "${MACRO}" | grep -q '\W'; then
2389                                 RPMUSERDEFS="${RPMUSERDEFS} --define \"${MACRO}\""
2390                         else
2391                                 VALUE="${1}"
2392                                 shift
2393                                 RPMUSERDEFS="${RPMUSERDEFS} --define \"${MACRO} ${VALUE}\""
2394                         fi
2395                         ;;
2396                 --alt_kernel)
2397                         shift
2398                         RPMOPTS="${RPMOPTS} --define \"alt_kernel $1\" --define \"build_kernels $1\""
2399                         shift
2400                         ;;
2401                 --short-circuit)
2402                         RPMBUILDOPTS="${RPMBUILDOPTS} --short-circuit"
2403                         shift
2404                         ;;
2405                 --show-bconds | -show-bconds | -print-bconds | --print-bconds | -display-bconds | --display-bconds )
2406                         COMMAND="show_bconds"
2407                         shift
2408                         ;;
2409                 --show-bcond-args)
2410                         COMMAND="show_bcond_args"
2411                         shift
2412                         ;;
2413                 --show-avail-bconds)
2414                         COMMAND="show_avail_bconds"
2415                         shift
2416                         ;;
2417                 --nodeps)
2418                         shift
2419                         RPMOPTS="${RPMOPTS} --nodeps"
2420                         ;;
2421                 -debug)
2422                         RPMBUILDOPTS="${RPMBUILDOPTS} -debug"; shift
2423                         ;;
2424                 --git-pld)
2425                         shift
2426                         GIT_SERVER=${PLD_GIT_SERVER}
2427                         GIT_PUSH=${PLD_GIT_PUSH}
2428                         PACKAGES_DIR=${PLD_PACKAGES_DIR}
2429                         DISTFILES_SERVER=${PLD_DISTFILES_SERVER}
2430                         ;;
2431                 --git-tld)
2432                         shift
2433                         GIT_SERVER=${TLD_GIT_SERVER}
2434                         GIT_PUSH=${TLD_GIT_PUSH}
2435                         PACKAGES_DIR=${TLD_PACKAGES_DIR}
2436                         DISTFILES_SERVER=${TLD_DISTFILES_SERVER}
2437                         ;;
2438                 --pkgrev)
2439                         SETPKGREV="true"
2440                         COMMAND="build-source"
2441                         shift;;
2442                 -lp)
2443                         COMMAND="list_pkgrev"
2444                         shift;;
2445                 -*)
2446                         Exit_error err_invalid_cmdline "$1"
2447                         ;;
2448                 *)
2449                         SPECFILE=${1%/}; shift
2450                         # check if specname was passed as specname:cvstag
2451                         if [ "${SPECFILE##*:}" != "${SPECFILE}" ]; then
2452                                 CVSTAG="${SPECFILE##*:}"
2453                                 SPECFILE="${SPECFILE%%:*}"
2454                         fi
2455                         # always have SPECFILE ending with .spec extension
2456                         SPECFILE=${SPECFILE%%.spec}.spec
2457                         ASSUMED_NAME=$(basename ${SPECFILE%%.spec})
2458         esac
2459 done
2460
2461 # Check if given package exists in TLD git
2462 if ! git ls-remote --heads ${GIT_SERVER}/${PACKAGES_DIR}/${ASSUMED_NAME} 1>/dev/null 2>&1; then
2463         # Nope, we don't have it in TLD, switch to PLD repositories
2464         GIT_SERVER=${PLD_GIT_SERVER}
2465         GIT_PUSH=${PLD_GIT_PUSH}
2466         PACKAGES_DIR=${PLD_PACKAGES_DIR}
2467         DISTFILES_SERVER=${PLD_DISTFILES_SERVER}
2468 fi
2469
2470 if [ "$CVSTAG" ]; then
2471         # pass $CVSTAG used by builder to rpmbuild too, so specs could use it
2472         RPMOPTS="$RPMOPTS --define \"_cvstag $CVSTAG\""
2473 fi
2474
2475 if [ -n "$ALL_BRANCHES" -a -z "$DEPTH" ]; then
2476         echo >&2 "--all branches requires --depth <number>"
2477         Exit_error err_invalid_cmdline
2478 fi
2479
2480 if [ -n "$DEBUG" ]; then
2481         set -x
2482         set -v
2483 fi
2484
2485 if [ -n "$TARGET" ]; then
2486         case "$RPMBUILD" in
2487                 "rpmbuild")
2488                         TARGET_SWITCH="--target $TARGET" ;;
2489                 "rpm")
2490                         TARGET_SWITCH="--target=$TARGET" ;;
2491         esac
2492 fi
2493
2494 if [ "$SCHEDTOOL" != "no" ]; then
2495         NICE_COMMAND="$SCHEDTOOL"
2496 else
2497         NICE_COMMAND="nice -n ${DEF_NICE_LEVEL}"
2498 fi
2499
2500 # see time(1) for output format that could be used
2501 TIME_COMMAND="time -p"
2502
2503 update_shell_title "$COMMAND"
2504 case "$COMMAND" in
2505         "show_bconds")
2506                 init_builder
2507                 if [ -z "$SPECFILE" ]; then
2508                         Exit_error err_no_spec_in_cmdl
2509                 fi
2510                 get_spec > /dev/null
2511                 parse_spec
2512                 set_bconds_values
2513                 display_bconds
2514                 ;;
2515         "show_bcond_args")
2516                 init_builder
2517                 if [ -z "$SPECFILE" ]; then
2518                         Exit_error err_no_spec_in_cmdl
2519                 fi
2520                 get_spec > /dev/null
2521                 parse_spec
2522                 set_bconds_values
2523                 echo "$BCOND"
2524                 ;;
2525         "show_avail_bconds")
2526                 init_builder
2527                 if [ -z "$SPECFILE" ]; then
2528                         Exit_error err_no_spec_in_cmdl
2529                 fi
2530
2531                 get_spec > /dev/null
2532                 parse_spec
2533                 local bcond_avail=$(find_spec_bcond $SPECFILE)
2534                 local opt bcond bconds
2535                 for opt in $bcond_avail; do
2536                         case "$opt" in
2537                         without_*)
2538                                 bcond=${opt#without_}
2539                                 bconds="$bconds $bcond"
2540                                 ;;
2541                         with_*)
2542                                 bcond=${opt#with_}
2543                                 bconds="$bconds $bcond"
2544                                 ;;
2545                         *)
2546                                 echo >&2 "ERROR: unexpected '$opt' in show_avail_bconds"
2547                                 exit 1
2548                                 ;;
2549                         esac
2550                 done
2551                 echo $bconds
2552
2553                 ;;
2554         "build" | "build-binary" | "build-source" | "build-prep" | "build-build" | "build-install" | "build-list")
2555                 init_builder
2556                 if [ -z "$SPECFILE" ]; then
2557                         Exit_error err_no_spec_in_cmdl
2558                 fi
2559
2560                 # display SMP make flags if set
2561                 smp_mflags=$(rpm -E %{?_smp_mflags})
2562                 if [ "$smp_mflags" ]; then
2563                         echo "builder: SMP make flags are set to $smp_mflags"
2564                 fi
2565
2566                 get_spec
2567                 parse_spec
2568                 set_bconds_values
2569                 display_bconds
2570                 display_branches
2571                 if [ "$COMMAND" != "build-source" ]; then
2572                         check_buildarch
2573                 fi
2574                 fetch_build_requires
2575                 if [ "$INTEGER_RELEASE" = "yes" ]; then
2576                         echo "Checking release $PACKAGE_RELEASE..."
2577                         if echo $PACKAGE_RELEASE | grep -q '^[^.]*\.[^.]*$' 2>/dev/null ; then
2578                                 Exit_error err_fract_rel "$PACKAGE_RELEASE"
2579                         fi
2580                 fi
2581
2582                 if [ -n "$NOSOURCE0" ] ; then
2583                         SOURCES=`echo $SOURCES | xargs | sed -e 's/[^ ]*//'`
2584                 fi
2585                 try_upgrade
2586                 case $? in
2587                         0)
2588                                 get_files $SOURCES $PATCHES
2589                                 check_md5 $SOURCES $PATCHES
2590                                 ;;
2591                         *)
2592                                 NODIST="yes" get_files $SOURCES $PATCHES
2593                                 update_md5 $SOURCES $PATCHES
2594                                 ;;
2595                 esac
2596                 build_package
2597                 if [ "$UPDATE_POLDEK_INDEXES" = "yes" ] && [ "$COMMAND" = "build" -o "$COMMAND" = "build-binary" ]; then
2598                         run_poldek --sdir="${POLDEK_INDEX_DIR}" ${UPDATE_POLDEK_INDEXES_OPTS} --mkidxz
2599                 fi
2600                 remove_build_requires
2601                 ;;
2602         "branch" )
2603                 init_builder
2604                 if [ -z "$SPECFILE" ]; then
2605                         Exit_error err_no_spec_in_cmdl
2606                 fi
2607
2608                 get_spec
2609                 parse_spec
2610                 branch_files $TAG
2611                 ;;
2612         "add_cvs" )
2613                 init_builder
2614                 if [ -z "$SPECFILE" ]; then
2615                         Exit_error err_no_spec_in_cmdl
2616                 fi
2617
2618                 create_git_repo
2619                 if [ -n "$NEW_REPO" ]; then
2620                         parse_spec
2621                         local file
2622                         for file in $SOURCES $PATCHES; do
2623                                 if [ -z $(src_md5 "$file") ]; then
2624                                         git add $file || Exit_error err_no_source_in_repo $file
2625                                 else
2626                                         cvsignore_df `nourl $file`
2627                                 fi
2628                         done
2629                         git add $SPECFILE
2630                         echo "When you are ready commit your changes and run git push origin master"
2631                 else
2632                         echo "You had already git repository. Push chosen branches to remote: ${REMOTE_PLD}"
2633                 fi
2634                 ;;
2635         "get" )
2636                 init_builder
2637                 if [ -z "$SPECFILE" ]; then
2638                         Exit_error err_no_spec_in_cmdl
2639                 fi
2640
2641                 get_spec
2642                 parse_spec
2643
2644                 if [ -n "$NOSOURCE0" ] ; then
2645                         SOURCES=`echo $SOURCES | xargs | sed -e 's/[^ ]*//'`
2646                 fi
2647                 get_files $SOURCES $PATCHES
2648                 check_md5 $SOURCES
2649                 fetch_build_requires
2650                 ;;
2651         "update_md5" )
2652                 init_builder
2653                 if [ -z "$SPECFILE" ]; then
2654                         Exit_error err_no_spec_in_cmdl
2655                 fi
2656
2657                 get_spec
2658                 parse_spec
2659
2660                 if [ -n "$NOSOURCE0" ] ; then
2661                         SOURCES=`echo $SOURCES | xargs | sed -e 's/[^ ]*//'`
2662                 fi
2663                 update_md5 $SOURCES $PATCHES
2664                 ;;
2665         "mr-proper" )
2666                 mr_proper
2667                 ;;
2668         "list-sources-files" )
2669                 init_builder
2670                 NOCVSSPEC="yes"
2671                 DONT_PRINT_REVISION="yes"
2672                 get_spec
2673                 parse_spec
2674                 for SAP in $SOURCES $PATCHES; do
2675                         echo $SAP | awk '{gsub(/.*\//,"") ; print}'
2676                 done
2677                 ;;
2678         "list-sources-urls" )
2679                 init_builder >&2
2680                 NOCVSSPEC="yes"
2681                 DONT_PRINT_REVISION="yes"
2682                 get_spec >&2
2683                 parse_spec >&2
2684                 SAPS="$SOURCES $PATCHES"
2685                 for SAP in $SAPS; do
2686                         echo $SAP
2687                 done
2688                 ;;
2689         "list-sources-local-paths" )
2690                 init_builder
2691                 NOCVSSPEC="yes"
2692                 DONT_PRINT_REVISION="yes"
2693                 get_spec
2694                 parse_spec
2695                 for SAP in $SOURCES $PATCHES; do
2696                         echo $PACKAGE_DIR/$(echo $SAP | awk '{gsub(/.*\//,"") ; print }')
2697                 done
2698                 ;;
2699         "list-sources-distfiles-paths" )
2700                 init_builder
2701                 NOCVSSPEC="yes"
2702                 DONT_PRINT_REVISION="yes"
2703                 get_spec
2704                 parse_spec
2705                 for SAP in $SOURCES $PATCHES; do
2706                         if [ -n "$(src_md5 "$SAP")" ]; then
2707                                 distfiles_path "$SAP"
2708                         fi
2709                 done
2710                 ;;
2711         "list-sources-distfiles" )
2712                 init_builder
2713                 NOCVSSPEC="yes"
2714                 DONT_PRINT_REVISION="yes"
2715                 get_spec
2716                 parse_spec
2717                 for SAP in $SOURCES $PATCHES; do
2718                         if [ -n "$(src_md5 "$SAP")" ]; then
2719                                 distfiles_url "$SAP"
2720                         fi
2721                 done
2722                 ;;
2723         "list-sources-cvs" )
2724                 init_builder
2725 #               NOCVSSPEC="yes"
2726                 DONT_PRINT_REVISION="yes"
2727                 get_spec
2728                 parse_spec
2729                 for SAP in $SOURCES $PATCHES; do
2730                         if [ -z "$(src_md5 "$SAP")" ]; then
2731                                 echo $SAP | awk '{gsub(/.*\//,"") ; print}'
2732                         fi
2733                 done
2734                 ;;
2735         "init_rpm_dir")
2736                 init_rpm_dir
2737                 ;;
2738         "usage" )
2739                 usage
2740                 ;;
2741         "short-version" )
2742                 echo "$VERSION"
2743                 ;;
2744         "version" )
2745                 echo "$VERSIONSTRING"
2746                 ;;
2747         "list_pkgrev" )
2748                 init_builder
2749                 if [ -z "$SPECFILE" ]; then
2750                         Exit_error err_no_spec_in_cmdl
2751                 fi
2752                 get_spec > /dev/null
2753                 parse_spec
2754                 list_pkgrev
2755                 ;;
2756 esac
2757 if [ -f "`pwd`/.${SPECFILE}_INSTALLED_PACKAGES" -a "$REMOVE_BUILD_REQUIRES" != "" ]; then
2758         rm "`pwd`/.${SPECFILE}_INSTALLED_PACKAGES"
2759 fi
2760 cd "$__PWD"
2761
2762 # vi:syntax=sh:ts=4:sw=4:noet