[pacman-dev] [PATCH 1/2] makepkg: implement error codes

ivy.foster at gmail.com ivy.foster at gmail.com
Thu Sep 14 22:58:34 UTC 2017


From: Ivy Foster <ivy.foster at gmail.com>

For your convenience, makepkg now has 16 distinct ways to fail.
---
 doc/makepkg.8.txt     |  60 ++++++++++++++++++++++
 scripts/makepkg.sh.in | 140 ++++++++++++++++++++++++++++----------------------
 2 files changed, 139 insertions(+), 61 deletions(-)

diff --git a/doc/makepkg.8.txt b/doc/makepkg.8.txt
index 2dff1b19..224292a2 100644
--- a/doc/makepkg.8.txt
+++ b/doc/makepkg.8.txt
@@ -272,6 +272,66 @@ See linkman:makepkg.conf[5] for more details on configuring makepkg using the
 'makepkg.conf' file.
 
 
+Errors
+------
+On exit, makepkg will return one of the following error codes.
+
+**E_OK**=0::
+	Normal exit condition.
+
+**E_FAIL**=1::
+	Unknown cause of failure.
+
+// Exit code 2 is reserved by bash for misuse of shell builtins
+
+**E_CONFIG_ERROR**=3::
+	Error in configuration file.
+
+**E_INVALID_OPTION**=4::
+	User specified an invalid option
+
+**E_BUILD_FAILED**=5::
+	Error in PKGBUILD build function.
+
+**E_PACKAGE_FAILED**=6::
+	Failed to create a viable package.
+
+**E_MISSING_FILE**=7::
+	A source or auxiliary file specified in the PKGBUILD is
+	missing.
+
+**E_MISSING_PKGDIR**=8::
+	The PKGDIR is missing.
+
+**E_INSTALL_DEPS_FAILED**=9::
+	Failed to install dependencies.
+
+**E_REMOVE_DEPS_FAILED**=10::
+	Failed to remove dependencies.
+
+**E_ROOT**=11::
+	User attempted to run makepkg as root.
+
+**E_FS_PERMISSIONS**=12::
+	User lacks permissions to build or install to a given
+	location.
+
+**E_PKGBUILD_ERROR**=13::
+	Error parsing PKGBUILD.
+
+**E_ALREADY_BUILT**=14::
+	A package has already been built.
+
+**E_INSTALL_FAILED**=15::
+	The package failed to install.
+
+**E_MISSING_MAKEPKG_DEPS**=16::
+	Programs necessary to run makepkg are missing.
+
+**E_PRETTY_BAD_PRIVACY**=17::
+	Error signing package.
+
+
 See Also
 --------
 linkman:makepkg.conf[5], linkman:PKGBUILD[5], linkman:pacman[8]
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 20e9dd7e..8ef3c48d 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -87,6 +87,26 @@ SPLITPKG=0
 SOURCEONLY=0
 VERIFYSOURCE=0
 
+# Errors
+E_OK=0
+E_FAIL=1 # Generic error
+# exit code 2 reserved by bash for misuse of shell builtins
+E_CONFIG_ERROR=3
+E_INVALID_OPTION=4
+E_BUILD_FAILED=5
+E_PACKAGE_FAILED=6
+E_MISSING_FILE=7
+E_MISSING_PKGDIR=8
+E_INSTALL_DEPS_FAILED=9
+E_REMOVE_DEPS_FAILED=10
+E_ROOT=11
+E_FS_PERMISSIONS=12
+E_PKGBUILD_ERROR=13
+E_ALREADY_BUILT=14
+E_INSTALL_FAILED=15
+E_MISSING_MAKEPKG_DEPS=16
+E_PRETTY_BAD_PRIVACY=17
+
 export SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH:-$(date +%s)}
 
 PACMAN_OPTS=()
@@ -130,7 +150,7 @@ clean_up() {
 		return
 	fi
 
-	if (( ! EXIT_CODE && CLEANUP )); then
+	if (( (EXIT_CODE == E_OK || EXIT_CODE == 15) && CLEANUP )); then
 		local pkg file
 
 		# If it's a clean exit and -c/--clean has been passed...
@@ -184,7 +204,7 @@ update_pkgver() {
 	newpkgver=$(run_function_safe pkgver)
 	if ! check_pkgver "$newpkgver"; then
 		error "$(gettext "pkgver() generated an invalid version: %s")" "$newpkgver"
-		exit 1
+		exit $E_PKGBUILD_ERROR
 	fi
 
 	if [[ -n $newpkgver && $newpkgver != "$pkgver" ]]; then
@@ -192,7 +212,7 @@ update_pkgver() {
 			if ! @SEDINPLACE@ "s:^pkgver=[^ ]*:pkgver=$newpkgver:" "$BUILDFILE"; then
 				error "$(gettext "Failed to update %s from %s to %s")" \
 						"pkgver" "$pkgver" "$newpkgver"
-				exit 1
+				exit $E_PKGBUILD_ERROR
 			fi
 			@SEDINPLACE@ "s:^pkgrel=[^ ]*:pkgrel=1:" "$BUILDFILE"
 			source_safe "$BUILDFILE"
@@ -209,7 +229,7 @@ update_pkgver() {
 missing_source_file() {
 	error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")"
 	plain "$(gettext "Aborting...")"
-	exit 1 # $E_MISSING_FILE
+	exit $E_MISSING_FILE
 }
 
 run_pacman() {
@@ -263,7 +283,7 @@ handle_deps() {
 
 		if ! run_pacman -S --asdeps "${deplist[@]}"; then
 			error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN"
-			exit 1 # TODO: error code
+			exit $E_INSTALL_DEPS_FAILED
 		fi
 	fi
 
@@ -284,12 +304,12 @@ resolve_deps() {
 	# deplist cannot be declared like this: local deplist=$(foo)
 	# Otherwise, the return value will depend on the assignment.
 	local deplist
-	deplist=($(check_deps "$@")) || exit 1
+	deplist=($(check_deps "$@")) || exit $E_INSTALL_DEPS_FAILED
 	[[ -z $deplist ]] && return $R_DEPS_SATISFIED
 
 	if handle_deps "${deplist[@]}"; then
 		# check deps again to make sure they were resolved
-		deplist=$(check_deps "$@") || exit 1
+		deplist=$(check_deps "$@") || exit $E_INSTALL_DEPS_FAILED
 		[[ -z $deplist ]] && return $R_DEPS_SATISFIED
 	fi
 
@@ -310,7 +330,7 @@ remove_deps() {
 	if [[ -n $(grep -xvFf <(printf '%s\n' "${current_pkglist[@]}") \
 			<(printf '%s\n' "${original_pkglist[@]}")) ]]; then
 		warning "$(gettext "Failed to remove installed dependencies.")"
-		return 0
+		return $E_REMOVE_DEPS_FAILED
 	fi
 
 	local deplist
@@ -324,7 +344,7 @@ remove_deps() {
 	# exit cleanly on failure to remove deps as package has been built successfully
 	if ! run_pacman -Rn ${deplist[@]}; then
 		warning "$(gettext "Failed to remove installed dependencies.")"
-		return 0
+		return $E_REMOVE_DEPS_FAILED
 	fi
 }
 
@@ -337,14 +357,14 @@ error_function() {
 		error "$(gettext "A failure occurred in %s().")" "$1"
 		plain "$(gettext "Aborting...")"
 	fi
-	exit 2 # $E_BUILD_FAILED
+	exit $E_BUILD_FAILED
 }
 
 source_safe() {
 	shopt -u extglob
 	if ! source "$@"; then
 		error "$(gettext "Failed to source %s")" "$1"
-		exit 1
+		exit $E_MISSING_FILE
 	fi
 	shopt -s extglob
 }
@@ -615,7 +635,7 @@ write_kv_pair() {
 	for val in "$@"; do
 		if [[ $val = *$'\n'* ]]; then
 			error "$(gettext "Invalid value for %s: %s")" "$key" "$val"
-			exit 1
+			exit $E_PKGBUILD_ERROR
 		fi
 		printf "%s = %s\n" "$key" "$val"
 	done
@@ -704,7 +724,7 @@ create_package() {
 	if [[ ! -d $pkgdir ]]; then
 		error "$(gettext "Missing %s directory.")" "\$pkgdir/"
 		plain "$(gettext "Aborting...")"
-		exit 1 # $E_MISSING_PKGDIR
+		exit $E_MISSING_PKGDIR
 	fi
 
 	cd_safe "$pkgdir"
@@ -722,7 +742,7 @@ create_package() {
 			msg2 "$(gettext "Adding %s file...")" "$orig"
 			if ! cp "$startdir/${!orig}" "$dest"; then
 				error "$(gettext "Failed to add %s file to package.")" "$orig"
-				exit 1
+				exit $E_MISSING_FILE
 			fi
 			chmod 644 "$dest"
 		fi
@@ -768,7 +788,7 @@ create_package() {
 
 	if (( ret )); then
 		error "$(gettext "Failed to create package file.")"
-		exit 1 # TODO: error code
+		exit $E_PACKAGE_FAILED
 	fi
 }
 
@@ -864,14 +884,13 @@ create_srcpackage() {
 	cd_safe "${srclinks}"
 	if ! LANG=C bsdtar -cL ${TAR_OPT} -f "$pkg_file" ${pkgbase}; then
 		error "$(gettext "Failed to create source package file.")"
-		exit 1 # TODO: error code
+		exit $E_PACKAGE_FAILED
 	fi
 
 	cd_safe "${startdir}"
 	rm -rf "${srclinks}"
 }
 
-# this function always returns 0 to make sure clean-up will still occur
 install_package() {
 	(( ! INSTALL )) && return
 
@@ -897,7 +916,7 @@ install_package() {
 
 	if ! run_pacman -U "${pkglist[@]}"; then
 		warning "$(gettext "Failed to install built package(s).")"
-		return 0
+		return $E_INSTALL_FAILED
 	fi
 }
 
@@ -917,7 +936,7 @@ get_vcsclient() {
 	if [[ -z $client ]]; then
 		error "$(gettext "Unknown download protocol: %s")" "$proto"
 		plain "$(gettext "Aborting...")"
-		exit 1 # $E_CONFIG_ERROR
+		exit $E_CONFIG_ERROR
 	fi
 
 	printf "%s\n" "$client"
@@ -956,7 +975,7 @@ check_vcs_software() {
 					client=$(get_vcsclient "$proto") || exit $?
 					# ensure specified program is installed
 					local uninstalled
-					uninstalled=$(check_deps "$client") || exit 1
+					uninstalled=$(check_deps "$client") || exit $E_INSTALL_DEPS_FAILED
 					# if not installed, check presence in depends or makedepends
 					if [[ -n "$uninstalled" ]] && (( ! NODEPS || ( VERIFYSOURCE && !DEP_BIN ) )); then
 						if ! in_array "$client" ${all_deps[@]}; then
@@ -1081,11 +1100,11 @@ check_build_status() {
 				 && ! (( FORCE || SOURCEONLY || NOBUILD || NOARCHIVE)); then
 			if (( INSTALL )); then
 				warning "$(gettext "A package has already been built, installing existing package...")"
-				install_package
-				exit 0
+				status=$(install_package)
+				exit $status
 			else
 				error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f"
-				exit 1
+				exit $E_ALREADY_BUILT
 			fi
 		fi
 	else
@@ -1104,16 +1123,16 @@ check_build_status() {
 			if (( allpkgbuilt )); then
 				if (( INSTALL )); then
 					warning "$(gettext "The package group has already been built, installing existing packages...")"
-					install_package
-					exit 0
+					status=$(install_package)
+					exit $status
 				else
 					error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f"
-					exit 1
+					exit $E_ALREADY_BUILT
 				fi
 			fi
 			if (( somepkgbuilt && ! PKGVERFUNC )); then
 				error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f"
-				exit 1
+				exit $E_ALREADY_BUILT
 			fi
 		fi
 		unset allpkgbuilt somepkgbuilt
@@ -1148,7 +1167,7 @@ run_split_packaging() {
 		backup_package_variables
 		run_package $pkgname
 		tidy_install
-		lint_package || exit 1
+		lint_package || exit $E_PACKAGE_FAILED
 		create_package
 		restore_package_variables
 	done
@@ -1245,7 +1264,7 @@ OPT_LONG=('allsource' 'check' 'clean' 'cleanbuild' 'config:' 'force' 'geninteg'
 OPT_LONG+=('asdeps' 'noconfirm' 'needed' 'noprogressbar')
 
 if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
-	exit 1 # E_INVALID_OPTION;
+	exit $E_INVALID_OPTION;
 fi
 set -- "${OPTRET[@]}"
 unset OPT_SHORT OPT_LONG OPTRET
@@ -1294,8 +1313,8 @@ while true; do
 		-S|--source)      SOURCEONLY=1 ;;
 		--verifysource)   VERIFYSOURCE=1 ;;
 
-		-h|--help)        usage; exit 0 ;; # E_OK
-		-V|--version)     version; exit 0 ;; # E_OK
+		-h|--help)        usage; exit $E_OK ;;
+		-V|--version)     version; exit $E_OK ;;
 
 		--)               OPT_IND=0; shift; break 2;;
 	esac
@@ -1341,7 +1360,7 @@ if [[ -r $MAKEPKG_CONF ]]; then
 else
 	error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
 	plain "$(gettext "Aborting...")"
-	exit 1 # $E_CONFIG_ERROR
+	exit $E_CONFIG_ERROR
 fi
 
 # Source user-specific makepkg.conf overrides, but only if no override config
@@ -1375,14 +1394,14 @@ if [[ ! -d $BUILDDIR ]]; then
 	if ! mkdir -p "$BUILDDIR"; then
 		error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
 		plain "$(gettext "Aborting...")"
-		exit 1
+		exit $E_FS_PERMISSIONS
 	fi
 	chmod a-s "$BUILDDIR"
 fi
 if [[ ! -w $BUILDDIR ]]; then
 	error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
 	plain "$(gettext "Aborting...")"
-	exit 1
+	exit $E_FS_PERMISSIONS
 fi
 
 # override settings from extra variables on commandline, if any
@@ -1395,7 +1414,7 @@ PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
 if (( ! (NOBUILD || GENINTEG) )) && [[ ! -w $PKGDEST ]]; then
 	error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST"
 	plain "$(gettext "Aborting...")"
-	exit 1
+	exit $E_FS_PERMISSIONS
 fi
 
 SRCDEST=${_SRCDEST:-$SRCDEST}
@@ -1403,7 +1422,7 @@ SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined
 if [[ ! -w $SRCDEST ]] ; then
 	error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST"
 	plain "$(gettext "Aborting...")"
-	exit 1
+	exit $E_FS_PERMISSIONS
 fi
 
 SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
@@ -1412,7 +1431,7 @@ if (( SOURCEONLY )); then
 	if [[ ! -w $SRCPKGDEST ]]; then
 		error "$(gettext "You do not have write permission to store source tarballs in %s.")" "$SRCPKGDEST"
 		plain "$(gettext "Aborting...")"
-		exit 1
+		exit $E_FS_PERMISSIONS
 	fi
 
 	# If we're only making a source tarball, then we need to ignore architecture-
@@ -1425,7 +1444,7 @@ LOGDEST=${LOGDEST:-$startdir} #default to $startdir if undefined
 if (( LOGGING )) && [[ ! -w $LOGDEST ]]; then
 	error "$(gettext "You do not have write permission to store logs in %s.")" "$LOGDEST"
 	plain "$(gettext "Aborting...")"
-	exit 1
+	exit $E_FS_PERMISSIONS
 fi
 
 PKGEXT=${_PKGEXT:-$PKGEXT}
@@ -1439,12 +1458,12 @@ if (( ! INFAKEROOT )); then
 	if (( EUID == 0 )); then
 		error "$(gettext "Running %s as root is not allowed as it can cause permanent,\n\
 catastrophic damage to your system.")" "makepkg"
-		exit 1 # $E_USER_ABORT
+		exit $E_ROOT
 	fi
 else
 	if [[ -z $FAKEROOTKEY ]]; then
 		error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg"
-		exit 1 # TODO: error code
+		exit $E_INVALID_OPTION
 	fi
 fi
 
@@ -1459,16 +1478,17 @@ unset "${!sha384sums_@}" "${!sha512sums_@}"
 BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
 if [[ ! -f $BUILDFILE ]]; then
 	error "$(gettext "%s does not exist.")" "$BUILDFILE"
-	exit 1
+	exit $E_BUILD_FAILED=5
+
 else
 	if [[ $(<"$BUILDFILE") = *$'\r'* ]]; then
 		error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"
-		exit 1
+		exit $E_PKGBUILD_ERROR
 	fi
 
 	if [[ ! $BUILDFILE -ef $PWD/${BUILDFILE##*/} ]]; then
 		error "$(gettext "%s must be in the current working directory.")" "$BUILDFILE"
-		exit 1
+		exit $E_PKGBUILD_ERROR
 	fi
 
 	if [[ ${BUILDFILE:0:1} != "/" ]]; then
@@ -1480,7 +1500,7 @@ fi
 pkgbase=${pkgbase:-${pkgname[0]}}
 
 # check the PKGBUILD for some basic requirements
-lint_pkgbuild || exit 1
+lint_pkgbuild || exit $E_PKGBUILD_ERROR
 
 if (( !SOURCEONLY && !PRINTSRCINFO )); then
 	merge_arch_attrs
@@ -1506,7 +1526,7 @@ if (( GENINTEG )); then
 	cd_safe "$srcdir"
 	download_sources novcs allarch
 	generate_checksums
-	exit 0 # $E_OK
+	exit $E_OK
 fi
 
 if have_function pkgver; then
@@ -1514,7 +1534,7 @@ if have_function pkgver; then
 fi
 
 # check we have the software required to process the PKGBUILD
-check_software || exit 1
+check_software || exit $E_MISSING_MAKEPKG_DEPS
 
 if (( ${#pkgname[@]} > 1 )); then
 	SPLITPKG=1
@@ -1551,18 +1571,18 @@ if { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; } || [[ $SIGNPKG == 'y' ]];
 		else
 			error "$(gettext "There is no key in your keyring.")"
 		fi
-		exit 1
+		exit $E_PRETTY_BAD_PRIVACY
 	fi
 fi
 
 if (( PACKAGELIST )); then
 	print_all_package_names
-	exit 0
+	exit $E_OK
 fi
 
 if (( PRINTSRCINFO )); then
 	write_srcinfo_content
-	exit 0
+	exit $E_OK
 fi
 
 if (( ! PKGVERFUNC )); then
@@ -1574,7 +1594,7 @@ if (( INFAKEROOT )); then
 	if (( SOURCEONLY )); then
 		create_srcpackage
 		msg "$(gettext "Leaving %s environment.")" "fakeroot"
-		exit 0 # $E_OK
+		exit $E_OK
 	fi
 
 	prepare_buildenv
@@ -1587,7 +1607,7 @@ if (( INFAKEROOT )); then
 			run_package
 		fi
 		tidy_install
-		lint_package || exit 1
+		lint_package || exit $E_PACKAGE_FAILED
 		create_package
 		create_debug_package
 	else
@@ -1595,7 +1615,7 @@ if (( INFAKEROOT )); then
 	fi
 
 	msg "$(gettext "Leaving %s environment.")" "fakeroot"
-	exit 0 # $E_OK
+	exit $E_OK
 fi
 
 msg "$(gettext "Making package: %s")" "$pkgbase $basever ($(date))"
@@ -1605,7 +1625,7 @@ if (( SOURCEONLY )); then
 	if [[ -f $SRCPKGDEST/${pkgbase}-${basever}${SRCEXT} ]] \
 			&& (( ! FORCE )); then
 		error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f"
-		exit 1
+		exit $E_ALREADY_BUILT
 	fi
 
 	# Get back to our src directory so we can begin with sources.
@@ -1627,7 +1647,7 @@ if (( SOURCEONLY )); then
 	create_signature "$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}"
 
 	msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
-	exit 0
+	exit $E_OK
 fi
 
 if (( NODEPS || ( VERIFYSOURCE && !DEP_BIN ) )); then
@@ -1660,7 +1680,7 @@ else
 
 	if (( deperr )); then
 		error "$(gettext "Could not resolve all dependencies.")"
-		exit 1
+		exit $E_INSTALL_DEPS_FAILED
 	fi
 fi
 
@@ -1675,7 +1695,7 @@ if (( !REPKG )); then
 	else
 		download_sources
 		check_source_integrity
-		(( VERIFYSOURCE )) && exit 0 # $E_OK
+		(( VERIFYSOURCE )) && exit $E_OK
 
 		if (( CLEANBUILD )); then
 			msg "$(gettext "Removing existing %s directory...")" "\$srcdir/"
@@ -1697,7 +1717,7 @@ fi
 
 if (( NOBUILD )); then
 	msg "$(gettext "Sources are ready.")"
-	exit 0 #E_OK
+	exit $E_OK
 else
 	# clean existing pkg directory
 	if [[ -d $pkgdirbase ]]; then
@@ -1724,13 +1744,11 @@ fi
 # if inhibiting archive creation, go no further
 if (( NOARCHIVE )); then
 	msg "$(gettext "Package directory is ready.")"
-	exit 0
+	exit $E_OK
 fi
 
 msg "$(gettext "Finished making: %s")" "$pkgbase $basever ($(date))"
 
-install_package
-
-exit 0 #E_OK
+install_package && exit $E_OK || exit $E_INSTALL_FAILED
 
 # vim: set noet:
-- 
2.14.1


More information about the pacman-dev mailing list