Add anoncvs gentoo-x86 example in documentation of repos.conf.
[portage.git] / bin / helper-functions.sh
1 #!/bin/bash
2 # Copyright 1999-2012 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4
5 # For routines we want to use in ebuild-helpers/ but don't want to
6 # expose to the general ebuild environment.
7
8 source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
9
10 #
11 # API functions for doing parallel processing
12 #
13 __numjobs() {
14         # Copied from eutils.eclass:makeopts_jobs()
15         local jobs=$(echo " ${MAKEOPTS} " | \
16                 sed -r -n 's:.*[[:space:]](-j|--jobs[=[:space:]])[[:space:]]*([0-9]+).*:\2:p')
17         echo ${jobs:-1}
18 }
19
20 __multijob_init() {
21         # Setup a pipe for children to write their pids to when they finish.
22         mj_control_pipe=$(mktemp -t multijob.XXXXXX)
23         rm "${mj_control_pipe}"
24         mkfifo "${mj_control_pipe}"
25         __redirect_alloc_fd mj_control_fd "${mj_control_pipe}"
26         rm -f "${mj_control_pipe}"
27
28         # See how many children we can fork based on the user's settings.
29         mj_max_jobs=$(__numjobs)
30         mj_num_jobs=0
31 }
32
33 __multijob_child_init() {
34         trap 'echo ${BASHPID} $? >&'${mj_control_fd} EXIT
35         trap 'exit 1' INT TERM
36 }
37
38 __multijob_finish_one() {
39         local pid ret
40         read -r -u ${mj_control_fd} pid ret
41         : $(( --mj_num_jobs ))
42         return ${ret}
43 }
44
45 __multijob_finish() {
46         local ret=0
47         while [[ ${mj_num_jobs} -gt 0 ]] ; do
48                 __multijob_finish_one
49                 : $(( ret |= $? ))
50         done
51         # Let bash clean up its internal child tracking state.
52         wait
53         return ${ret}
54 }
55
56 __multijob_post_fork() {
57         : $(( ++mj_num_jobs ))
58         if [[ ${mj_num_jobs} -ge ${mj_max_jobs} ]] ; then
59                 __multijob_finish_one
60         fi
61         return $?
62 }
63
64 # @FUNCTION: __redirect_alloc_fd
65 # @USAGE: <var> <file> [redirection]
66 # @DESCRIPTION:
67 # Find a free fd and redirect the specified file via it.  Store the new
68 # fd in the specified variable.  Useful for the cases where we don't care
69 # about the exact fd #.
70 __redirect_alloc_fd() {
71         local var=$1 file=$2 redir=${3:-"<>"}
72
73         if [[ $(( (BASH_VERSINFO[0] << 8) + BASH_VERSINFO[1] )) -ge $(( (4 << 8) + 1 )) ]] ; then
74                         # Newer bash provides this functionality.
75                         eval "exec {${var}}${redir}'${file}'"
76         else
77                         # Need to provide the functionality ourselves.
78                         local fd=10
79                         local fddir=/dev/fd
80                         # Prefer /proc/self/fd if available (/dev/fd
81                         # doesn't work on solaris, see bug #474536).
82                         [[ -d /proc/self/fd ]] && fddir=/proc/self/fd
83                         while :; do
84                                         # Make sure the fd isn't open.  It could be a char device,
85                                         # or a symlink (possibly broken) to something else.
86                                         if [[ ! -e ${fddir}/${fd} ]] && [[ ! -L ${fddir}/${fd} ]] ; then
87                                                         eval "exec ${fd}${redir}'${file}'" && break
88                                         fi
89                                         [[ ${fd} -gt 1024 ]] && die "__redirect_alloc_fd failed"
90                                         : $(( ++fd ))
91                         done
92                         : $(( ${var} = fd ))
93         fi
94 }