summaryrefslogtreecommitdiff
path: root/eclass/greadme.eclass
blob: a4335b1a62868f0bf3fe21e33ef76f14b6d9df57 (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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# Copyright 1999-2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

# @ECLASS: greadme.eclass
# @MAINTAINER:
# Florian Schmaus <flow@gentoo.org>
# @SUPPORTED_EAPIS: 8
# @BLURB: install a doc file, that will be conditionally shown via elog messages
# @DESCRIPTION:
# An eclass for installing a README.gentoo doc file with important
# information for the user.  The content of README.gentoo will shown be
# via elog messages either on fresh installations or if the contents of
# the file have changed.  Furthermore, the README.gentoo file will be
# installed under /usr/share/doc/${PF} for later consultation.
#
# This eclass was inspired by readme.gentoo-r1.eclass.  The main
# differences are as follows.  Firstly, it only displays the doc file
# contents if they have changed (unless GREADME_SHOW is set).
# Secondly, it provides a convenient API to install the doc file via
# stdin.
#
# @CODE
# inherit greadme
#
# src_install() {
#   ...
#   greadme_stdin <<-EOF
#   This is the content of the created readme doc file.
#   EOF
#   ...
#   if use foo; then
#     greadme_stdin --append <<-EOF
#     This is conditional readme content, based on USE=foo.
#     EOF
#   fi
# }
# @CODE
#
# If the ebuild overrides the default pkg_preinst or respectively
# pkg_postinst, then it must call greadme_pkg_preinst and
# greadme_pkg_postinst explicitly.

if [[ -z ${_GREADME_ECLASS} ]]; then
_GREADME_ECLASS=1

case ${EAPI} in
	8) ;;
	*) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
esac

_GREADME_TMP_FILE="${T}/README.gentoo"
_GREADME_REL_PATH="/usr/share/doc/${PF}/README.gentoo"

# @ECLASS_VARIABLE: GREADME_SHOW
# @DEFAULT_UNSET
# @DESCRIPTION:
# If set to "yes" then unconditionally show the contents of the readme
# file in pkg_postinst via elog. If set to "no", then do not show the
# contents of the readme file, even if they have changed.

# @ECLASS_VARIABLE: GREADME_DISABLE_AUTOFORMAT
# @DEFAULT_UNSET
# @DESCRIPTION:
# If non-empty, the readme file will not be automatically formatted.

# @FUNCTION: greadme_stdin
# @USAGE: [--append]
# @DESCRIPTION:
# Create the readme doc via stdin.  You can use --append to append to an
# existing readme doc.
greadme_stdin() {
	debug-print-function ${FUNCNAME} "$@"

	local append
	if [[ ${1} = --append ]]; then
		append=1
		shift
	fi

	[[ $# -eq 0 ]] || die "${FUNCNAME[0]}: Bad parameters: $*"

	if [[ -n ${append} ]]; then
		if [[ ! -f ${_GREADME_TMP_FILE} ]]; then
			die "Gentoo README does not exist when trying to append to it"
		fi

		cat >> "${_GREADME_TMP_FILE}" || die
	else
		cat > "${_GREADME_TMP_FILE}" || die
	fi

	_greadme_install_doc
}

# @FUNCTION: greadme_file
# @USAGE: <file>
# @DESCRIPTION:
# Installs the provided file as readme doc.
greadme_file() {
	debug-print-function ${FUNCNAME} "$@"

	local input_doc_file="${1}"
	if [[ -z ${input_doc_file} ]]; then
		die "No file specified"
	fi

	cp "${input_doc_file}" "${_GREADME_TMP_FILE}" || die

	_greadme_install_doc
}

# @FUNCTION: _greadme_install_doc
# @INTERNAL
# @DESCRIPTION:
# Installs the readme file from the temp directory into the image.
_greadme_install_doc() {
	debug-print-function ${FUNCNAME} "$@"

	local greadme="${_GREADME_TMP_FILE}"
	if [[ ! ${GREADME_DISABLE_AUTOFORMAT} ]]; then
		greadme="${_GREADME_TMP_FILE}".formatted

		# Use fold, followed by a sed to strip trailing whitespace.
		# https://bugs.gentoo.org/460050#c7
		fold -s -w 70 "${_GREADME_TMP_FILE}" |
			sed 's/[[:space:]]*$//' > "${greadme}"
		assert "failed to autoformat README.gentoo"
	fi

	# Subshell to avoid pollution of calling environment.
	(
		docinto .
		newdoc "${greadme}" "README.gentoo"
	)

	# Exclude the readme file from compression, so that its contents can
	# be easily compared.
	docompress -x "${_GREADME_REL_PATH}"

	# Save the contents of the of the readme. Unfortunately we have to
	# do this in src_* phase, because FEATURES=nodoc is applied right
	# after src_install and not after pkg_preinst.
	_GREADME_CONTENT=$(< "${greadme}")
}

# @FUNCTION: greadme_pkg_preinst
# @DESCRIPTION:
# Performs checks like comparing the readme doc from the image with a
# potentially existing one in the live system.
greadme_pkg_preinst() {
	debug-print-function ${FUNCNAME} "$@"

	if [[ -z ${REPLACING_VERSIONS} ]]; then
		_GREADME_SHOW="fresh-install"
		return
	fi

	if [[ -v GREADME_SHOW ]]; then
		case ${GREADME_SHOW} in
			yes)
				_GREADME_SHOW="forced"
				;;
			no)
				_GREADME_SHOW=""
				;;
			*)
				die "Invalid argument of GREADME_SHOW: ${GREADME_SHOW}"
				;;
		esac
		return
	fi

	local image_greadme_file="${ED}${_GREADME_REL_PATH}"
	if [[ ! -f ${image_greadme_file} ]]; then
		if [[ -v _GREADME_CONTENT ]]; then
			# There is no greadme in the image but the ebuild created
			# one. This is likely because FEATURES=nodoc is active.
			# Unconditionally show greadme's contents.
			_GREADME_SHOW="nodoc-active"
		else
			# No README file was created by the ebuild.
			_GREADME_SHOW=""
		fi

		return
	fi

	check_live_doc_file() {
		local cur_pvr=$1
		local live_greadme_file="${EROOT}/usr/share/doc/${PN}-${cur_pvr}/README.gentoo"

		if [[ ! -f ${live_greadme_file} ]]; then
			_GREADME_SHOW="no-current-greadme"
			return
		fi

		cmp -s "${live_greadme_file}" "${image_greadme_file}"
		case $? in
			0)
				_GREADME_SHOW=""
				;;
			1)
				_GREADME_SHOW="content-differs"
				;;
			*)
				die "cmp failed with $?"
				;;
		esac
	}

	local replaced_version
	for replaced_version in ${REPLACING_VERSIONS}; do
		check_live_doc_file ${replaced_version}

		# Once _GREADME_SHOW is non empty, we found a reason to show the
		# readme and we can abort the loop.
		if [[ -n ${_GREADME_SHOW} ]]; then
			break
		fi
	done
}

# @FUNCTION: greadme_pkg_postinst
# @DESCRIPTION:
# Conditionally shows the contents of the readme doc via elog.
greadme_pkg_postinst() {
	debug-print-function ${FUNCNAME} "$@"

	if [[ ! -v _GREADME_SHOW ]]; then
		die "_GREADME_SHOW not set. Did you call greadme_pkg_preinst?"
	fi

	if [[ -z ${_GREADME_SHOW} ]]; then
		# If _GREADME_SHOW is empty, then there is no reason to show the contents.
		return
	fi

	local line
	printf '%s\n' "${_GREADME_CONTENT}" | while read -r line; do
		elog "${line}"
	done
	elog ""
	elog "NOTE: Above message is only printed the first time package is"
	elog "installed or if the message changed. Please look at"
	elog "${EPREFIX}${_GREADME_REL_PATH}"
	elog "for future reference."
}

fi

EXPORT_FUNCTIONS pkg_preinst pkg_postinst