added patch from Greg Fitzgerald <netzdamon@gmail.com> to fix bzr
[ule.git] / update-live-ebuilds
blob1bf57bc2dd7891c28a122f09493e0e3a425faad0
1 #!/bin/bash
2 ## update-live-ebuilds - Program to update ebuilds that pull from various portage-type repositories.
3 ## Copyright (C) 2006-2009 Avuton Olrich <avuton@gmail.com>
4 ##
5 ## This program is free software: you can redistribute it and/or modify
6 ## it under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation, either version 3 of the License, or
8 ## (at your option) any later version.
9 ##
10 ## This program is distributed in the hope that it will be useful,
11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ## GNU General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with this program. If not, see <http://www.gnu.org/licenses/>.
18 function vecho() {
19 [ ${VERBOSE} -eq ${true} ] && echo "$@"
22 function decho() {
23 [ ${DEBUG} -eq ${true} ] && echo "$@"
26 function email_details() {
27 echo "Please email details about this bug to "
28 echo "Avuton Olrich <avuton@gmail.com>, so I "
29 echo "can improve this script."
32 ################################################################################################################################################
33 ## Updates ${ebuild_epoch};
34 ## This is a function since portage has never put the correct epoch time in /var/db/pkg/*/*/COUNTER.
35 ################################################################################################################################################
36 ## Rather than grepping the CONTENTS, I would just use ${dir}/COUNTER, but portage doesn't not use epoch, and I'm not really quite sure
37 ## what it uses for a counter. I know all package managers use epoch in the CONTENTS file.
38 function update_ebuild_epoch() {
39 export ebuild_epoch
40 if [ ${spec} -eq ${portage} ]; then
41 ebuild_epoch=`grep obj ${dir}/CONTENTS | tail -n1 | awk '{sub(/^.* /,"")} 1'`
42 else
43 ebuild_epoch=$(cat ${dir}/COUNTER)
45 CUREXPORTS="${CUREXPORTS} ebuild_epoch"
48 ################################################################################################################################################
49 ## SCM success detector;
50 ## This is a convience function used in conjunction with a SCM's return argument to detect success/failure and report appropriately.
52 ## Returns;
53 ## The true if the first argument is true, otherwise false.
55 ## Argument;
56 ## $1: The argument given by the SCM's execution
57 ################################################################################################################################################
58 function update_check() {
59 [ ${1} -eq ${true} ] && return ${true}
61 echo "Package ${provide} failed to update with error code: ${1}"
62 echo "If it is believed this is a problem with update-live-ebuilds, send me a verbose bug report"
63 email_details
64 UPDATE_FAIL_PACKAGES="${UPDATE_FAIL_PACKAGES} ${provide}"
65 return ${false}
68 ################################################################################################################################################
69 ## Write to the ULE database;
70 ## This simply writes any information that will be needed next time to the update-live-ebuilds database in a format that can be sourced
71 ## for easy retreival.
73 ## Returns;
74 ## None
76 ## Arguments;
77 ## $1: The ULE "key" or "cookie", basically the unique identifier that ULE uses to detect a difference between the last installed
78 ## repository revision and the current revision.
79 ## $2: The ULE database directory.
80 ################################################################################################################################################
81 function write_to_db() {
82 [ ! -d "`dirname ${ule_file}`" ] && mkdir -p "`dirname ${ule_file}`"
83 echo "ULE_COOKIE=\"${1}\"" > "${ule_file}"
86 ################################################################################################################################################
87 ## Extract a variable out of the current ebuild's portage database environment file;
88 ## This function simply automates detecting a variable in the portage database's environment file and extracts it into the current shell
89 ## for use by this script.
91 ## Returns;
92 ## The number of failed variable extractions.
94 ## Arguments;
95 ## $@: An unlimited amount of variables to find in the environment file in the portage database.
96 ################################################################################################################################################
97 function extract_env() {
98 local tempvar
99 local ret=0
100 for num in $@; do
101 tempvar=$(bzip2 -cd "${dir}/environment.bz2" | grep "^${num}=")
102 if [ $? -ne ${true} ]; then
103 tempvar=$(bzip2 -cd "${dir}/environment.bz2" | grep "^declare -[x-] ${num}=")
104 if [ $? -ne ${true} ]; then
105 tempvar=$(bzip2 -cd "${dir}/environment.bz2" | grep "^export ${num}=")
106 if [ $? -eq ${false} ]; then
107 decho "Could not find variable ${num} for ${provide}"
108 ret=$(($ret+1))
109 continue
111 tempvar="${tempvar/export /}"
113 tempvar=`echo $tempvar | sed -r 's/declare -[x-] ([^=]*)=\"(.*)\"$/\1=\2/'`
116 decho "Found variable ${num} for ${provide}"
117 export "${tempvar//\'}"
118 CUREXPORTS="${CUREXPORTS} ${tempvar//=*}"
119 done
121 return ${ret}
124 ################################################################################################################################################
125 ## Convience wrapper for extract_env() to require no failure;
126 ## This wrapper simply executes the input in extract_env() and provides a failure message in the case that a failure occured.
128 ## Returns;
129 ## Boolean
131 ## Arguments;
132 ## $@: An unlimited amount of variables to find in the environment file in the portage database.
133 ################################################################################################################################################
134 function secure_env() {
135 local ret=0
136 extract_env $@
137 ret=$?
139 [ ${ret} -ne ${true} ] && vecho "${provide} inherits ${type} but doesn't have necessary variables; skipping"
140 return ${ret}
143 ################################################################################################################################################
144 ## Local repository directory detection;
145 ## This detects the local directory for repositories, and if it isn't found this will emit an error
147 ## Returns;
148 ## Boolean
150 ## Arguments;
151 ## $1: The directory to detect
152 ## $2: The name of the package provide
153 ################################################################################################################################################
154 function check_for_found() {
155 local provide="${2}"
156 local dir="${1}"
158 ## This must be called with something beyond the directory, such as an info file or directory.
159 ## This regexp does a basic 'dirname' without forking a shell
160 if [[ "${dir}" =~ '/.*/' ]] && [ ! -d "${BASH_REMATCH[0]%%\/}" ]; then
161 echo -n "Couldn't find the original directory for ${provide}, "
162 [ ${locbase} -eq ${true} ] && echo 'skipping.' && return 1
164 echo 'reemerging.'
165 emerger ${false} || return ${false}
166 export locbase=${true}
169 if [ ! -d "${dir}" ] && [ ! -f "${dir}" ]; then
170 if [ ${ALL} -eq ${false} ] && [ ${BASELINE} -eq ${true} ]; then
171 [ "${BASELINE}" -eq ${true} ] && echo "Cannot find the directory to baseline: ${dir}" && return ${false}
173 [[ "${dir}" =~ '.*/(.*)' ]] ## Basename
174 echo '--'
175 echo "Couldn't find the ${BASH_REMATCH[1]} information directory for ${provide}"
176 echo "Please provide details about where this package stores itself."
177 echo "Use -a to OVERRIDE this warning and reemerge"
178 email_details
179 echo '--'
180 return ${false}
183 emerger ${false} || return ${false}
184 export locbase=${true}
187 return ${true}
190 ################################################################################################################################################
191 ## Portage compatible installer execution;
192 ## This is where all portage compatible installation is executed. It is all done here so everywhere emerge is neede will have uniform
193 ## error detection.
195 ## Returns;
196 ## Boolean
198 ## Arguments;
199 ## $1: Boolean to baseline the package or not.
200 ################################################################################################################################################
201 function emerger() {
202 local locopts
203 [ ${PRETEND} -eq ${true} ] && locopts="${locopts} ${EMERGE_PRETEND[${spec}]}"
205 ## Handle ULE_ASK_FILE
206 if [ -f "${ULE_ASK_FILE}" ]; then
207 grep -Eq "^($pprovide|${provide})$" "${ULE_ASK_FILE}"
208 if [ $? -eq ${true} ]; then
209 vecho "Package (${provide}) found in ULE_ASK, will ask before emerging..."
210 if [ -z "${EMERGE_ASK_OPTS[${spec}]}" ]; then
211 ${EMERGE_BINARY[${spec}]} ${EMERGE_EXT_OPTS[${spec}]} ${EMERGE_PRETEND[${spec}]} ${provide}
213 local tmpopt
214 while true; do
215 echo -n "Would you like to install this package? [yes/no] "
216 read tmpopt
218 [ "${tmpopt}" == "no" ] && return ${true}
219 [ "${tmpopt}" == "yes" ] && break
220 done
221 else
222 locopts="${locopts} ${EMERGE_ASK_OPTS[${spec}]}"
227 ## Since we didn't continue above, we emerge now.
228 ${EMERGE_BINARY[${spec}]} ${locopts} ${EMERGE_EXT_OPTS[${spec}]} ${provide}
230 if [ $? -ne ${true} ]; then
231 echo "It appears emerge of ${provide} failed, try again later..."
232 export FAILED_PACKAGES="${FAILED_PACKAGES} ${provide}"
233 return ${false}
236 ## We need to pull the hash again, to ensure we have the correct hash, in case of PEEK
237 locbase=${true}
238 get_hash
240 if [ ${1} -eq ${true} ] && [ ${PRETEND} -eq ${false} ]; then
241 write_to_db "${newhash}" "${ULE_LOC}/${provide}"
243 ## Add to the success packages
244 export SUCCESS_PACKAGES="${SUCCESS_PACKAGES} ${provide}"
247 return ${true}
250 ################################################################################################################################################
251 ## Hash detection begins;
252 ## This can either go through looking directly at the repository, or we update the local repository to detect updates.
253 ## Of course, local updating is the prefered method, though it is probably more likely to succeed in the objective, as the SCMs command
254 ## line interface may change and this would obviously cause problems, which will cause user notification at the update_check() after the
255 ## case statement completes.
257 ## To developers considering adding another SCM or fixing up an SCM detection, here's a few things to consider.
258 ## 1) Please make a peek mode if the SCM supports it.
259 ## 2) Attempt to use the ebuild's variables as much as possible, as these may change and it would be more accurate to take
260 ## the newer, maintained variables.
261 ## 3) Use ${prescm} and secure_env(), these will find problems before they happen.
262 ## 4) Don't rely on environment variables through sudo or ${prescm}. Sudo by default resets the environment during privelege drop.
263 ## 5) Avoid HASH_PROGRAM use; depend on native 'cookies', if possible.
264 ## 6) newhash needs to be the final calculation so the update_check() at the end of the case statement does it's job.
265 ## 7) When possible, don't use 'cd', use a repository updating argument.
266 ## 8) Be aware secure_env() is a costly function; use it only as necessary.
267 ################################################################################################################################################
268 function get_hash() {
269 ## No need to check the local repository when ALL is selected, but we do need the newhash.
270 [ ${ALL} -eq ${true} ] && local locbase=${true}
272 export newhash
273 local found
275 case "${type}" in
276 'subversion' )
277 secure_env 'ESVN_REPO_URI' || continue
278 extract_env 'ESVN_REVISION'
279 ESVN_REPO_URI="${ESVN_REPO_URI%%/}"
281 ## This is a simple test to test for: svn://svn.blah.org/svn/blah@592 (being the revision)
282 test="${ESVN_REPO_URI##*@}"
283 if [ "${test//[[:digit:]]}" == '' ] && [ -n "${ESVN_REPO_URI}" ]; then
284 newhash="${ESVN_REPO_URI##*@}"
285 decho "Newhash generated from ESVN_REPO_URI."
287 unset test
289 if [ "${ESVN_REVISION}" == '' ] && [ -n "${ESVN_REVISION}" ]; then
290 newhash="${ESVN_REVISION}"
291 decho "Newhash generated from ESVN_REVISION."
294 if [ ${PEEK} -eq ${true} ] && [ ${locbase} -eq ${false} ] && [ -n ${newhash} ]; then
295 newhash=$(svn info ${ESVN_REPO_URI} | grep 'Last Changed Rev' | awk '{sub(/^.* /,"")} 1')
298 ## Subversions' binaries are extremely unreliable. Cannot count on svn info to give something useful.
299 if [ -z "${newhash}" ]; then
300 secure_env 'ESVN_STORE_DIR' 'ESVN_PROJECT' 'ESVN_UPDATE_CMD' 'ESVN_OPTIONS' || continue
302 found="${ESVN_STORE_DIR}/${ESVN_PROJECT}/${ESVN_REPO_URI##*/}"
303 check_for_found "${found}/.svn" "${provide}" || continue
305 if [ ${locbase} -eq ${false} ]; then
306 decho ${prescm} ${ESVN_UPDATE_CMD} ${ESVN_OPTIONS} --quiet --config-dir="${ESVN_STORE_DIR}/.subversion" ${found}
307 ${prescm} ${ESVN_UPDATE_CMD} ${ESVN_OPTIONS} --quiet --config-dir="${ESVN_STORE_DIR}/.subversion" ${found}
308 update_check $? ${provide} || continue
310 newhash=$(svnversion -c ${found} | awk '{sub(/.*:/,"")} 1')
312 ## Check the repository for modification, this is usually a sign of trouble.
313 if [ ${newhash} == *M ]; then
314 log "${found} repository has modifications. This could be a serious problem, as something"
315 log "has modified the repository in your distfiles directory, which should never happen."
317 ## This removes the trailing M, because 'svnversion' output and svn info output would needlessly differ
318 ## in this case
319 newhash="${newhash%M}"
323 'git' )
324 secure_env 'EGIT_REPO_URI' || continue
326 ## This is actually necessary due to newer eclasses which inherit git.eclass but not the EGIT_BRANCH variable.
327 extract_env 'EGIT_BRANCH' || EGIT_BRANCH='master'
331 ## GIT only allows git peek-remote to be done on certain protocols, thus listed at the end.
332 if [ ${PEEK} -eq ${true} ] && [ ${locbase} -eq ${false} ] && [[ "${EGIT_REPO_URI}" =~ ^(git|ssh|file|ssh+git|git+ssh).* ]]; then
333 newhash=$(git peek-remote ${EGIT_REPO_URI} | grep "heads/${EGIT_BRANCH}$" | awk '{sub(/\t.*$/,"")} 1')
334 else
335 secure_env 'EGIT_STORE_DIR' 'EGIT_PROJECT' || continue
337 found="${EGIT_STORE_DIR}/${EGIT_PROJECT}"
338 check_for_found "${found}/info" "${provide}" || continue
340 if [ ${locbase} -eq ${false} ]; then
341 secure_env 'EGIT_UPDATE_CMD' || continue
343 ${prescm} git --git-dir="${found}" fetch origin ${EGIT_BRANCH}:${EGIT_BRANCH}&>/dev/null
344 update_check $? ${provide} || continue
346 newhash="$(git --git-dir="${found}" rev-parse ${EGIT_BRANCH})"
349 'cvs')
350 ## CVS_RSH gets extracted, but is not used anywhere by design.
351 secure_env 'CVS_PASSFILE' 'CVS_RSH' 'ECVS_AUTH' 'ECVS_CVS_COMMAND' \
352 'ECVS_SERVER' 'ECVS_TOP_DIR' 'ECVS_UP_OPTS' 'ECVS_USER' || continue
354 ## The obvious "optional only", these don't exist at all in some ebuilds.
355 extract_env 'ECVS_MODULE' 'ECVS_LOCALNAME' 'ECVS_OPTIONS' 'ECVS_COMPRESS' 'ECVS_PASS' 'T'
357 if [ -n "${ECVS_LOCALNAME}" ]; then
358 found="${ECVS_TOP_DIR}/${ECVS_LOCALNAME}"
359 elif [ -n "${ECVS_MODULE}" ]; then
360 found="${ECVS_TOP_DIR}/${ECVS_MODULE}"
361 else
362 echo "Couldn't find the directory for ${provide}, skipping..."
363 email_details
364 continue
367 [ -z "${T}" ] && T="`dirname ${CVS_PASSFILE}`"
369 check_for_found "${found}/CVS" "${provide}" || continue
371 cd "${found}"
372 if [ ${locbase} -eq ${false} ]; then
373 ## From the cvs.eclass
374 [ -d "${T}" ] || mkdir -p "${T}"
375 touch "${CVS_PASSFILE}"
376 chown ${EMERGE_USER[${spec}]} ${CVS_PASSFILE}
378 ## DON'T login as ${prescm}, it causes all sorts of problems when the sudo environment is reset.
379 decho -d:${ECVS_AUTH}:${ECVS_USER}:${ECVS_PASS}@${ECVS_SERVER} ${ECVS_CVS_COMMAND} -Q login \>/dev/null
380 ${ECVS_CVS_COMMAND} -d:${ECVS_AUTH}:${ECVS_USER}:${ECVS_PASS}@${ECVS_SERVER} -Q login > /dev/null
381 [ $? -ne 0 ] && vecho "Couldn't login to cvs server for ${provide}" && continue
383 decho ${prescm} ${ECVS_CVS_COMMAND} -d:${ECVS_AUTH}:${ECVS_USER}:${ECVS_PASS}@${ECVS_SERVER} -Q update ${ECVS_UP_OPTS} ${ECVS_LOCALNAME}
384 ${prescm} ${ECVS_CVS_COMMAND} -d:${ECVS_AUTH}:${ECVS_USER}:${ECVS_PASS}@${ECVS_SERVER} -Q update ${ECVS_UP_OPTS} ${ECVS_LOCALNAME}
385 update_check $? ${provide} || continue
387 newhash="$(find ${found} -type f -name Entries -exec cat {} \; | ${HASH_PROGRAM} | sed -e 's/ .*//')"
389 'darcs')
390 secure_env 'EDARCS_DARCS_CMD' || continue
392 if [ ${PEEK} -eq ${true} ] && [ ${locbase} -eq ${false} ]; then
393 secure_env 'EDARCS_REPOSITORY' || continue
394 newhash="$(${EDARCS_DARCS_CMD} changes --last 1 --xml-output --repo="${EDARCS_REPOSITORY}" | grep hash | sed "s/^.*hash='\(.*\).gz.*$/\1/")"
395 else
396 secure_env 'EDARCS_TOP_DIR' 'EDARCS_LOCALREPO' 'EDARCS_UPDATE_CMD' 'EDARCS_OPTIONS' || continue
398 found="${EDARCS_TOP_DIR}/${EDARCS_LOCALREPO}"
399 check_for_found "${found}/_darcs" "${provide}" || continue
401 cd "${found}"
402 if [ ${locbase} -eq ${false} ]; then
403 ${prescm} ${EDARCS_DARCS_CMD} ${EDARCS_UPDATE_CMD} --all ${EDARCS_OPTIONS} -q>/dev/null
404 update_check $? ${provide} || continue
406 newhash="$(${prescm} ${EDARCS_DARCS_CMD} changes --last 1 --xml-output | grep hash | sed "s/^.*hash='\(.*\).gz.*$/\1/")"
409 'mercurial')
410 secure_env 'EHG_REPO_URI' || continue
412 if [ ${EHG_STORE_DIR} -eq '']; then
413 EHG_STORE_DIR='/usr/portage/distfiles/hg-src/'
414 EHG_STORE_DIR="${EHG_STORE_DIR}$(echo ${EHG_REPO_URI} | sed 's/\/$//' | sed -r 's/(.*)\/(.+)/\2/')"
417 found="${EHG_STORE_DIR}/${EHG_PROJECT}"
419 ## Takes a little more time, but the mercurial eclass is a little less mature than most of the others,
420 ## so we must search inside the STORE_DIR in the case that it's a module inside that.
421 ## ie. EHG_STORE_DIR=/usr/distfiles/hg-src/alsa-drivers , but .hg is in ..alsa-drivers/alsa-kernel
422 found="`find ${found} -name .hg -type d -printf '%h\n'`"
423 check_for_found "${found}" "${provide}" || continue
425 ## To avoid mercurial warnings prescm is run below.
426 ## Mercurial returns 1 when there is no updates (don't ask me.)
427 if [ ${PEEK} -eq ${true} ]; then
428 ${prescm} hg -R "${found}" incoming>/dev/null
429 if [ $? -eq 0 ]; then
430 newhash='0101' ## fake hash
431 elif [ $? -ne 1 ]; then
432 update_check $? ${provide}
434 else
435 if [ ${locbase} -eq ${false} ]; then
436 ${prescm} ${EHG_PULL_CMD} --repository "${found}">/dev/null
437 [ $? -ne 1 ] && update_check $? ${provide}
441 ## This must be run even with peek in the case that the repository is on an NFS mount.
442 if [ -n "${newhash}" ]; then
443 newhash="$(${prescm} hg --quiet --repository "${found}" tip)"
444 [ $? -ne 1 ] && update_check $? ${provide}
447 'tla')
448 ## These are the workings; it works, but with permissions it fails. If someone can fix the permissions problems, by
449 ## putting ${prescm} before the TLA commands and before the tla commands; the only way it runs successfully now is to run
450 ## without the prescm commands due to the CACHE_DIR permissions problems. Send patches if you want this fixed.
451 secure_env 'ETLA_TOP_DIR' 'ETLA_TLA_CMD' 'ETLA_UPDATE_CMD' 'ETLA_CACHE_DIR' 'ETLA_VERSION' 'ETLA_ARCHIVES' 'WORKDIR' 'P' || continue
452 found="${ETLA_TOP_DIR}/${ETLA_CACHE_DIR}"
453 check_for_found "${found}" "${provide}" || continue
455 if [ ${locbase} -eq ${false} ]; then
456 ETLA_TLA_CMD="${ETLA_TLA_CMD} --dir "${found}""
458 mkdir -p -m 0700 "${WORKDIR}/${P}"
459 chown ${EMERGE_USER[$spec]} "${WORKDIR}/${P}"
460 ${prescm} cp -Rf "$ETLA_TOP_DIR/$ETLA_CACHE_DIR"/* "${WORKDIR}/${P}"
461 for archive in ${ETLA_ARCHIVES}; do
462 ${prescm} ${ETLA_TLA_CMD} register-archive -f ${archive} || echo "Couldn't register ${archive}" && continue
463 done
465 tla_archive=`${prescm} ${ETLA_TLA_CMD} parse-package-name --arch ${ETLA_VERSION}`
466 tla_version=`${prescm} ${ETLA_TLA_CMD} parse-package-name --package-version ${ETLA_VERSION}`
467 oldversion="`${prescm} ${ETLA_TLA_CMD} tree-version`"
468 [ "${tla_archive}/${tla_version}" != "${oldversion}" ] && ${prescm} ${ETLA_TLA_CMD} set-tree-version ${tla_archive}/${tla_version}
470 ${prescm} ${ETLA_TLA_CMD} ${ETLA_UPDATE_CMD} ${ETLA_VERSION}>/dev/null
471 update_check $? ${provide} || continue
474 newhash="$(${HASH_PROGRAM} "${ETLA_TOP_DIR}/${ETLA_CACHE_DIR}"/\{arch\}/tine-treesqls | sed -e 's/ .*//g')"
476 'bazaar')
477 secure_env 'EBAZAAR_REPO_URI' || continue
479 if [ ${PEEK} -eq ${true} ] && [ ${locbase} -eq ${false} ]; then
480 newhash="$(bzr version-info "${EBAZAAR_REPO_URI}" | grep revision-id | awk '{sub(/^.* /,"")} 1')"
481 else
482 secure_env 'EBAZAAR_REGISTER_CMD' 'EBAZAAR_REGISTER_URI' 'EBAZAAR_STORE_DIR' \
483 'EBAZAAR_REGISTER_CMD' 'EBAZAAR_PROJECT' || continue
484 found="${EBAZAAR_STORE_DIR}/${EBAZAAR_PROJECT}/${EBAZAAR_REPO_URI##*/}"
486 check_for_found "${found} ${provide}" || continue
488 decho "${prescm} ${EBAZAAR_REGISTER_CMD} ${EBAZAAR_REGISTER_URI} --dir "${found}">/dev/null"
489 ${prescm} ${EBAZAAR_REGISTER_CMD} ${EBAZAAR_REGISTER_URI} --dir "${found}">/dev/null
490 update_check $? ${provide} || continue
492 decho "${prescm} ${EBAZAAR_UPDATE_CMD} --dir "${found}">/dev/null"
493 ${prescm} ${EBAZAAR_UPDATE_CMD} --dir "${found}">/dev/null
494 update_check $? ${provide} || continue
496 newhash="$(bzr version-info "${found}" | grep revision-id | awk '{sub(/^.* /,"")} 1')"
499 'bzr')
500 if [ ${PEEK} -eq ${true} ] && [ ${locbase} -eq ${false} ]; then
501 secure_env 'EBZR_REPO_URI' || continue
502 found="${EBZR_REPO_URI}"
503 else
504 secure_env 'EBZR_STORE_DIR' 'EBZR_CACHE_DIR' || continue
505 found="${EBZR_STORE_DIR}/${EBZR_CACHE_DIR}"
507 check_for_found "${found}" || continue
509 newhash="`bzr revno ${found} &>/dev/stdout | tail -n1`"
511 esac
513 return $?
516 ################################################################################################################################################
517 ## Begin ULE;
518 ## This is the actual beginning of update-live-ebuilds, skipping past all the functions. This beginning checks a few prerequisites.
519 ################################################################################################################################################
520 trap 'echo; exit ${USER_INTERRUPT}' TERM INT
521 [ "${BASH_VERSION//.*}" -lt 3 ] && echo "Requires BASH v3 or better" && exit 5
523 if [ ! -f "/etc/ule/ule.conf" ]; then
524 echo -n "This script failed a sanity check, cannot continue without"
525 echo "/etc/ule/ule.conf"
526 exit 2
528 source /etc/ule/ule.conf
530 if [ "${UID}" -ne 0 ]; then
531 echo "${0}: root access required."
532 exit 3
535 ## Variables that don't need to be in the conf
536 CUREXPORTS=''
537 DB_LOC='/var/db/pkg'
538 PACKAGES_SO_FAR=''
540 ## Defaults
541 ALL=${false}
542 BASELINE=${false}
543 DATE_FORMAT="%x %X"
544 PRETEND=${false}
545 REPORT=${false}
546 TOTAL=''
547 USAGE=${false}
548 USER_INTERRUPT=13
550 while getopts "abhpqr" opt; do
551 case "${opt}" in
552 a) ALL=${true} ;;
553 b) BASELINE=${true} ;;
554 h) USAGE=${true} ;;
555 p) PRETEND=${true} ;;
556 q) VERBOSE=${false} ;;
557 r) REPORT=${true} ;;
558 esac
559 done
560 shift $(($OPTIND - 1))
562 if [ ${USAGE} -eq ${true} ]; then
563 cat << USAGE
564 Usage: ${0} [OPTION] [PKGSPEC]
565 Example: ${0} -v net-www/gnash
566 Search for live repository ebuilds that need updating, and update them if necessary.
568 -a Reemerge all packages fetched from various repositories
569 -b Baseline the ebuild (write into the database without updating)
570 -h This help file
571 -p If update is required, only pretend to emerge.
572 -q Show less output
573 -r Report information about packages that are tracked by update-live-ebuilds
575 See man 8 update-live-ebuilds for more information.
576 Report bugs to Avuton Olrich <avuton@gmail.com>
577 USAGE
578 exit 0
580 unset USAGE
582 if [ ${BASELINE} -eq ${true} ] && [ ${PRETEND} -eq ${true} ]; then
583 echo "Baseline and pretend are not compatible."
584 exit 22
587 ################################################################################################################################################
588 ## Update only support;
589 ## The purpose of doing things this way is so we update libraries in the order of:
590 ## 1) Libraries
591 ## 2) Everything but libraries and plugins
592 ## 3) Plugins
593 ## This is done like this to make sure libraries are updated first in the case that the packages (#2 & #3) that depend on the
594 ## libraries have the latest and greatest to link to, if necessary. Plugins are done last as they may depend on the
595 ## packages in #2.
597 ## if;
598 ## This is a bit of mumbo jumbo, mostly for the reason that we don't yet track version numbers, only by provide
599 ## A side effect of not being able to track version numbers means we need to glob for the version in the db's directory
600 ## which may grab two seperate directorys with the same name, but one longer like: foo-1.1 and foobar-2.1. It's not
601 ## a great side effect, but in reality shouldn't hit too many people. A more elegant solution is wanted, but complexity
602 ## is not.
603 ## else;
604 ## Self-explanatory.
605 ################################################################################################################################################
606 if [ -n "${1}" ]; then
607 for ebuild in $@; do
608 [ "${ebuild:0:1}" == '=' ] && ebuild="${ebuild:1}"
610 ebuild="${ebuild//:[[:digit:]]}" # Remove the slot for now
612 for mydir in `[[ ${ebuild} == */* ]] && echo ${DB_LOC}/${ebuild}* || echo ${DB_LOC}/*/${ebuild}*`; do
613 [ ! -d "${mydir}" ] && vecho "Directory doesn't exist: ${mydir}, continuing..." && continue
614 if [[ "${mydir}" == *libs* ]]; then
615 libs="${libs} ${mydir}"
616 elif [[ "${mydir}" == *plugin* ]]; then
617 plugin="${plugin} ${mydir}"
618 else
619 nlibs="${nlibs} ${mydir}"
621 done
622 done
624 [ -z "${nlibs}" ] && [ -z "${plugin}" ] && [ -z "${libs}" ] && echo "No packages found." && exit 5
625 else
626 libs="`find "${DB_LOC}" -mindepth 2 -maxdepth 2 -type d -wholename "*libs*"`"
627 plugin="`find "${DB_LOC}" -mindepth 2 -maxdepth 2 -type d -wholename "*plugin*"`"
628 nlibs="`find "${DB_LOC}" -mindepth 2 -maxdepth 2 -type d -not \( -wholename "*plugin*" -o -wholename "*libs*" \)`"
631 ################################################################################################################################################
632 ## Begin looping for SCM detection and emersion
633 ## Beyond this, each ebuild runs in this for loop. Attempt is made to weed out the non-SCM ebuilds immediately to prevent any unnecessary
634 ## CPU time incurred.
635 ################################################################################################################################################
636 for dir in ${libs} ${nlibs} ${plugin}; do
637 type=${false}
638 locbase=${BASELINE}
639 newhash=${false}
640 prescm=${false}
642 ################################################################################################################################################
643 ## Cleanup;
644 ## This prevents bugs.
645 ################################################################################################################################################
646 unset ${CUREXPORTS} CUREXPORTS
648 ################################################################################################################################################
649 ## Detect INHERITED location;
650 ## This should always go in the first block; the only reason it wouldn't is if the user used pkgcore to install a package, as pkgcore
651 ## doesn't install an INHERITED file.
652 ################################################################################################################################################
653 if [ -f "${dir}/INHERITED" ]; then
654 INHERITED="$(cat ${dir}/INHERITED)"
655 elif [ -f "${dir}"/*.ebuild ]; then
656 extract_env 'INHERITED'
657 else
658 continue ## This really shouldn't happen unless something is trashing the portage database.
661 ## The inherit line is checked here for the various scms defined in the config, and executed below.
662 for scm in ${SCM_SUPPORT[@]}; do
663 [[ "${INHERITED}" = *${scm}* ]] && type="${scm}" && break
664 done
666 ## .. or next file
667 [ "${type}" == ${false} ] && continue
669 if [ ! -f "${dir}/environment.bz2" ]; then
670 echo 'Error: Failed a sanity check.'
671 echo "dir: ${dir} has no environment.bz2 file!"
673 echo 'Correct this condition by manually reemerging.'
674 echo "If you believe this is a script error,"
675 email_details
676 exit 6
679 secure_env 'CATEGORY' 'PN' 'SLOT'
680 if [ $? -ne ${true} ]; then
681 echo "This is an assertion, you probably have a corrupt portage database for dir ${dir}."
682 email_details
683 continue
686 ## Finish this
687 # if [ "${PN}" == ${ebuild/${ebuild%%:[[:digit:]]}:} ]; then
688 # echo blah
689 # fi
691 provide="${CATEGORY}/${PN}:${SLOT}"
692 pprovide="${CATEGORY}/${PN}"
693 ule_file="${ULE_LOC}/${provide/:*}/ULE_INFO.${SLOT}"
694 ULE_DB_FILES="${ULE_DB_FILES} ${ule_file}"
695 decho "${provide} uses the ${scm} SCM".
697 [ -f "${ULE_LOC}/${provide}/ULE_INFO" ] && mv "${ULE_LOC}/${provide}/ULE_INFO" "${ule_file}"
699 if [ -f "${ule_file}" ]; then
700 decho 'Sourcing ULE_INFO'
701 source "${ule_file}"
704 TOTAL="${TOTAL} ${provide}"
706 ################################################################################################################################################
707 ## Begin ebuild masking detection;
708 ## This looks for an ebuild on a line in the ULE_MASK_FILE, if it exists, this will simply begin analyzation of the next ebuild in the
709 ## queue, if applicable.
710 ################################################################################################################################################
711 if [ -f "${ULE_MASK_FILE}" ]; then
712 grep -Eq "^(${pprovide}|${provide})$" "${ULE_MASK_FILE}"
714 if [ $? -eq ${true} ]; then
715 vecho "Package (${provide}) found in ULE_MASK, skipping..."
716 continue
720 ################################################################################################################################################
721 ## Portage compatible installer and privelege dropping autodetection;
722 ## This is where autodetection takes place. This will make it not only automatically detect which portage compatible installer to use,
723 ## but it will also use exactly what was used on the package last time, in the case that one of the portage compatible installers cause
724 ## breakage. This is hacky and can break with changes to the package managers, though it will be fixed, I do hope that portage adds
725 ## PKGMANAGER in the future.
726 ################################################################################################################################################
727 spec="${DEFAULT_EMERGE_PROGRAM}"
728 if [ ${FORCE_DEFAULT_EMERGE_PROGRAM} -eq ${false} ]; then
729 if [ -f "${dir}/PKGMANAGER" ]; then
730 tmp=$(cat "${dir}/PKGMANAGER")
731 if [[ "${tmp}" =~ (paludis)-.* ]] && [ "${BASH_REMATCH[1]}" == paludis ]; then
732 spec=${paludis}
733 ## Versions prior to 22 didn't have the ability to be run as non-superuser.
734 [ -n ${PALVER} ] && export PALVER=`paludis --version | head -n1 | sed -e 's/.* [0-9].\([0-9][0-9]\)..*/\1/g'`
735 if [ ${PALVER} -gt 21 ]; then
736 decho "Paludis version ${tmp} (greater than version 0.22.0) is the portage compatible installer"
737 prescm=${true}
738 else
739 decho "Paludis version ${tmp} (less than version 0.22.0) is the portage compatible installer"
741 elif [[ "${tmp}" =~ (pkgcore)-.* ]] && [ "${BASH_REMATCH[1]}" == pkgcore ]; then
742 decho "Pkgcore is the portage compatible installer"
743 spec=${pkgcore}
744 else
745 ## Problems
746 echo "Your portage compatible installer was not recognized, please report this problem"
747 echo "Continuing using default portage compatible installer ${EMERGE_BINARY[${DEFAULT_EMERGE_PROGRAM}]}"
748 email_details
750 else
751 decho "Emerge is the portage compatible installer"
752 spec=${portage}
756 ################################################################################################################################################
757 ## Begin date detection;
758 ## This looks for a ebuild/date combination for the current ebuild being analyzed, if it exists, this will detect if it has been updated
759 ## since the date in the ebuild/date combination and if it has, it will not attempt to emerge again until that time has expired.
760 ################################################################################################################################################
761 [ ${REPORT} -eq ${false} ] && [ -f "${ULE_DATE_FILE}" ] &&
762 userdays=`grep -E "^(\*\/\*\:${SLOT}|${CATEGORY}\/\*|${pprovide}|${provide}) [0-9]*" "${ULE_DATE_FILE}" | tail -n1`
764 if [ ${ALL} -eq ${false} ] && [ ${BASELINE} -eq ${false} ] && [ -n "${userdays}" ]; then
766 if [[ ${userdays} =~ (\*\/\*\:${SLOT} )(.*) ]] || [[ ${userdays} =~ (${CATEGORY}\/\* )(.*) ]] || \
767 [[ ${userdays} =~ (${pprovide} )(.*) ]] || [[ ${userdays} =~ (${provide} )(.*) ]]; then
769 [ -n ${ebuild_epoch} ] && update_ebuild_epoch
770 curepoch=`date +%s`
771 updateepoch=$(((86400*${BASH_REMATCH[2]})+${ebuild_epoch}))
772 diffepoch=$((${updateepoch} - ${curepoch}))
774 if [ ${diffepoch} -ne 0 ] && [ ${updateepoch} -gt ${curepoch} ]; then
775 if [ ${diffepoch} -gt 86400 ]; then
776 vecho "$((${diffepoch}/86400)) days until scheduled update attempts resume for ${provide}."
777 else
778 vecho "Less than a day until scheduled update attempts resume for ${provide}"
780 continue
784 unset updateepoch curepoch userdays
786 if [ ${REPORT} -eq ${true} ]; then
787 if [ -n ${ebuild_epoch} ]; then
788 update_ebuild_epoch
789 printf "\n"
792 source ${ule_file}
793 printf "${provide}\n"
794 printf "\tRevision: ${ULE_COOKIE}\n"
795 printf "\tEmerged on: `date -d \"1970-01-01 UTC ${ebuild_epoch} sec\" \"+${DATE_FORMAT}\"`\n\n"
796 continue
799 vecho "Attempting to check if ${provide} needs an update."
801 if [ -f /etc/make.conf ] && [ ${spec} -eq ${portage} ] || [ ${spec} -eq ${pkgcore} ]; then
802 grep 'userpriv' /etc/make.conf | grep -v '.*#.*userpriv.*'&>/dev/null
803 [ $? -eq 0 ] && prescm=${true}
806 if [ ${prescm} -eq ${true} ]; then
807 decho "Dropping privileges for ${provide}."
808 prescm="sudo -u ${EMERGE_USER[${spec}]}"
809 else
810 decho "Not dropping privileges for ${provide}."
811 prescm=''
814 get_hash
816 ## As long as 'newhash' was calculated last in the section above, this should be the outcome of it.
817 update_check $? "${provide}"
819 ################################################################################################################################################
820 ## Where the magic happens;
822 ## if;
823 ## We cannot locbase here, because we can't guarantee the repository has only been updated locally, it's basically assurance that
824 ## the cookie that goes into the ule database is the version that's installed.
825 ## elif;
826 ## In this case ALL is in the case that the user wants to reinstall and reupdate the ule database, reguardless of updates. The
827 ## locbase is also showing that we assume we didn't previously use the emerger().
828 ## elif;
829 ## This is the case where the ULE_COOKIE matches the newhash (no updates!), we're going to skip the emerge and simply baseline,
830 ## or we've got an empty newhash, which should absolutely, positively never happen. The only reason it would happen is
831 ## if there aren't enough update_check()s sprinkled above. This can also be caused by the SCM command line interface
832 ## throwing the wrong exit code, for example throwing 0 on failure (see Subversion bug 2414).
833 ## After fi;
834 ## Finally, this will be where 90-95% of all emerger() inits go, we cleanup prior to it then set the emerger to emerge with
835 ## ule db updating.
836 ################################################################################################################################################
837 if [ -z "${ULE_COOKIE}" ] && [ ${locbase} -eq ${false} ]; then
838 vecho "No previous cookie detected, reemerging"
839 elif [ ${ALL} -eq ${true} ] && [ ${locbase} -eq ${false} ]; then
840 vecho "Emerging all, reemerging"
841 elif [ "${ULE_COOKIE}" == "${newhash}" ] || [ ${locbase} -eq ${true} ] || [ -z "${newhash}" ]; then
842 if [ ${locbase} -eq ${true} ]; then
843 vecho "Baselineing ${provide}"
844 write_to_db "${newhash}" "${ULE_LOC}/${provide}"
846 [ -z "${newhash}" ] && vecho "Newhash empty, this should never happen unless errors that wern't caught previously"
847 unset ${CUREXPORTS} CUREXPORTS
848 continue
851 unset ${CUREXPORTS} CUREXPORTS
853 emerger ${true}
855 unset provide newhash type locbase
856 done
858 [ ${REPORT} -eq ${true} ] && exit 0
860 [ ${VERBOSE} -eq ${true} ] && echo 'Update complete'
862 [ -n "${1}" ] && exit 0
864 ## Update-only cannot make it this far; thus this should be fine.
866 ## Cleanup the ULE directory
867 echo "Cleaning ULE database"
868 for file in ${ULE_DB_FILES}; do
869 [ -n "${PACKAGES}" ] && PACKAGES="${PACKAGES} -a"
870 PACKAGES="${PACKAGES} -not -wholename "${file}""
871 done
873 ## Find and remove the ULE_INFO files
874 find ${ULE_LOC} -maxdepth 3 -mindepth 3 ${PACKAGES} -exec rm -v {} \;
876 ## Clean out the empty directories
877 find ${ULE_LOC} -depth -empty -type d -exec rmdir -v {} \;
879 if [ -n "${SUCCESS_PACKAGES}" ] && [ "${VERBOSE}" -eq ${true} ]; then
880 echo "The following packages were updated: ${SUCCESS_PACKAGES}"
881 unset SUCCESS_PACKAGES
884 if [ -n "${FAILED_PACKAGES}" ]; then
885 echo "The following programs failed: ${FAILED_PACKAGES}."
886 echo "You could either rerun this program at a later date, or you could do it on an individual"
887 echo "basis by just using the package spec as a argument: i.e. ${0} net-www/gnash"
888 unset FAILED_PACKAGES
891 if [ -n "${UPDATE_FAIL_PACKAGES}" ]; then
892 echo "The following programs failed when trying to be updated by update-live-ebuilds: ${UPDATE_FAIL_PACKAGES}"
893 unset UPDATE_FAIL_PACKAGES