aboutsummaryrefslogtreecommitdiff
blob: 6a99a19e32e129c6981307b8420f91cdb111d858 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# Copyright 2010-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

# Based in part upon 'alternatives.exlib' from Exherbo, which is:
# Copyright 2008, 2009 Bo Ørsted Andresen
# Copyright 2008, 2009 Mike Kelly
# Copyright 2009 David Leverton

# If your package provides pkg_postinst or pkg_prerm phases, you need to be
# sure you explicitly run alternatives_pkg_{postinst,prerm} where appropriate.

ALTERNATIVES_DIR="/etc/env.d/alternatives"

DEPEND=">=app-admin/eselect-1.4-r100"
RDEPEND="${DEPEND}
	!app-admin/eselect-blas
	!app-admin/eselect-cblas
	!app-admin/eselect-lapack"

# alternatives_for alternative provider importance source target [ source target [...]]
alternatives_for() {
	#echo alternatives_for "${@}"

	(( $# >= 5 )) && (( ($#-3)%2 == 0)) || die "${FUNCNAME} requires exactly 3+N*2 arguments where N>=1"
	local x dupl alternative=${1} provider=${2} importance=${3} index unique src target ret=0
	shift 3

	# make sure importance is a signed integer
	if [[ -n ${importance} ]] && ! [[ ${importance} =~ ^[0-9]+(\.[0-9]+)*$ ]]; then
		eerror "Invalid importance (${importance}) detected"
		((ret++))
	fi

	[[ -d "${ED}${ALTERNATIVES_DIR}/${alternative}/${provider}" ]] || dodir "${ALTERNATIVES_DIR}/${alternative}/${provider}"

	# keep track of provided alternatives for use in pkg_{postinst,prerm}. keep a mapping between importance and
	# provided alternatives and make sure the former is set to only one value
	if ! has "${alternative}:${provider}" "${ALTERNATIVES_PROVIDED[@]}"; then
		index=${#ALTERNATIVES_PROVIDED[@]}
		ALTERNATIVES_PROVIDED+=( "${alternative}:${provider}" )
		ALTERNATIVES_IMPORTANCE[index]=${importance}
		[[ -n ${importance} ]] && echo "${importance}" > "${ED}${ALTERNATIVES_DIR}/${alternative}/${provider}/_importance"
	else
		for((index=0;index<${#ALTERNATIVES_PROVIDED[@]};index++)); do
			if [[ ${alternative}:${provider} == ${ALTERNATIVES_PROVIDED[index]} ]]; then
				if [[ -n ${ALTERNATIVES_IMPORTANCE[index]} ]]; then
					if [[ -n ${importance} && ${ALTERNATIVES_IMPORTANCE[index]} != ${importance} ]]; then
						eerror "Differing importance (${ALTERNATIVES_IMPORTANCE[index]} != ${importance}) detected"
						((ret++))
					fi
				else
					ALTERNATIVES_IMPORTANCE[index]=${importance}
					[[ -n ${importance} ]] && echo "${importance}" > "${ED}${ALTERNATIVES_DIR}/${alternative}/${provider}/_importance"
				fi
			fi
		done
	fi

	while (( $# >= 2 )); do
		src=${1//+(\/)/\/}; target=${2//+(\/)/\/}
		if [[ ${src} != /* ]]; then
			eerror "Source path must be absolute, but got ${src}"
			((ret++))

		else
			local reltarget= dir=${ALTERNATIVES_DIR}/${alternative}/${provider}${src%/*}
			while [[ -n ${dir} ]]; do
				reltarget+=../
				dir=${dir%/*}
			done

			reltarget=${reltarget%/}
			[[ ${target} == /* ]] || reltarget+=${src%/*}/
			reltarget+=${target}
			dodir "${ALTERNATIVES_DIR}/${alternative}/${provider}${src%/*}"
			dosym "${reltarget}" "${ALTERNATIVES_DIR}/${alternative}/${provider}${src}"

			# say ${ED}/sbin/init exists and links to /bin/systemd (which doesn't exist yet)
			# the -e test will fail, so check for -L also
			if [[ -e ${ED}${src} || -L ${ED}${src} ]]; then
				local fulltarget=${target}
				[[ ${fulltarget} != /* ]] && fulltarget=${src%/*}/${fulltarget}
				if [[ -e ${ED}${fulltarget} || -L ${ED}${fulltarget} ]]; then
					die "${src} defined as provider for ${fulltarget}, but both already exist in \${ED}"
				else
					mv "${ED}${src}" "${ED}${fulltarget}" || die
				fi
			fi
		fi
		shift 2
	done

	[[ ${ret} -eq 0 ]] || die "Errors detected for ${provider}, provided for ${alternative}"
}

cleanup_old_alternatives_module() {
	local alt=${1} old_module="${EROOT%/}/usr/share/eselect/modules/${alt}.eselect"
	if [[ -f "${old_module}" && "$(source "${old_module}" &>/dev/null; echo "${ALTERNATIVE}")" == "${alt}" ]]; then
		local version="$(source "${old_module}" &>/dev/null; echo "${VERSION}")"
		if [[ "${version}" == "0.1" || "${version}" == "20080924" ]]; then
			echo rm "${old_module}"
			rm "${old_module}" || eerror "rm ${old_module} failed"
		fi
	fi
}

alternatives-2_pkg_postinst() {
	local a alt provider module_version="20090908"
	for a in "${ALTERNATIVES_PROVIDED[@]}"; do
		alt="${a%:*}"
		provider="${a#*:}"
		if [[ ! -f "${EROOT%/}/usr/share/eselect/modules/auto/${alt}.eselect" \
			|| "$(source "${EROOT%/}/usr/share/eselect/modules/auto/${alt}.eselect" &>/dev/null; echo "${VERSION}")" \
				-ne "${module_version}" ]]; then
			#einfo "Creating alternatives module for ${alt}"
			if [[ ! -d ${EROOT%/}/usr/share/eselect/modules/auto ]]; then
				install -d "${EROOT%/}"/usr/share/eselect/modules/auto || eerror "Could not create eselect modules dir"
			fi
			cat > "${EROOT%/}/usr/share/eselect/modules/auto/${alt}.eselect" <<-EOF
				# This module was automatically generated by alternatives.eclass
				DESCRIPTION="Alternatives for ${alt}"
				VERSION="${module_version}"
				MAINTAINER="eselect@gentoo.org"
				ESELECT_MODULE_GROUP="Alternatives"

				ALTERNATIVE="${alt}"

				inherit alternatives
			EOF
		fi

		#echo eselect "${alt}" update "${provider}"
		einfo "Creating ${provider} alternative module for ${alt}"
		eselect "${alt}" update "${provider}"

		cleanup_old_alternatives_module ${alt}
	done
}

alternatives-2_pkg_prerm() {
	local a alt provider p ignore
	[[ -n ${REPLACED_BY_ID} ]] || ignore=" --ignore"
	for a in "${ALTERNATIVES_PROVIDED[@]}"; do
		alt="${a%:*}"
		provider="${a#*:}"
		#echo "Making sure ${alt} has a valid provider"
		#echo eselect "${alt}" update${ignore} "${provider}"
		eselect "${alt}" update${ignore} "${provider}" && continue
		einfo "Removing ${provider} alternative module for ${alt}, current is $(eselect ${alt} show)"
		case $? in
			0) : ;;
			2)
				einfo "Cleaning up unused alternatives module for ${alt}"
				rm "${EROOT%/}/usr/share/eselect/modules/auto/${alt}.eselect" || \
					eerror rm "${EROOT%/}/usr/share/eselect/modules/auto/${alt}.eselect" failed
				;;
			*)
				eerror eselect "${alt}" update "${provider}" returned $?
				;;
		esac
	done
}

EXPORT_FUNCTIONS pkg_postinst pkg_prerm