diff options
Diffstat (limited to 'include/init.sh')
| -rw-r--r-- | include/init.sh | 525 | 
1 files changed, 395 insertions, 130 deletions
diff --git a/include/init.sh b/include/init.sh index a322370b..abd06862 100644 --- a/include/init.sh +++ b/include/init.sh @@ -1,4 +1,5 @@  # SPDX-License-Identifier: GPL-3.0-only +  # Copyright (c) 2022 Caleb La Grange <thonkpeasant@protonmail.com>  # Copyright (c) 2022 Ferass El Hafidi <vitali64pmemail@protonmail.com>  # Copyright (c) 2020-2025 Leah Rowe <leah@libreboot.org> @@ -10,60 +11,355 @@ export LC_ALL=C  projectname="libreboot"  projectsite="https://libreboot.org/" -[ -z "${PATH+x}" ] && \ -    export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games" -xbmkpath="$PATH" - -eval "`setvars "" _nogit board reinstall versiondate aur_notice configdir \ -    datadir version xbmkpwd relname xbmkpwd xbmktmp python pyver xbmklocal \ -    xbmklock`" +if [ -z "${PATH+x}" ]; then +	export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games" +fi + +sha512sum="util/sbase/sha512sum" + +aur_notice="" +basetmp="" +board="" +checkvarschk="" +checkvarsxbmk="" +configdir="" +datadir="" +is_child="" +python="" +pyver="" +reinstall="" +relname="" +version="" +versiondate="" +xbmklock="" +xbmkpath="" +xbmkpwd="" +xbmkpwd="" +xbtmp=""  xbmk_init()  { -	xbmkpwd="`pwd`" || err "Cannot generate PWD" -	xbmklocal="$xbmkpwd/tmp" +	xbmkpwd="`pwd || err "Cannot generate PWD"`" || err "!" xbmk_init "$@"  	xbmklock="$xbmkpwd/lock" +	basetmp="$xbmkpwd/xbmkwd" +	sha512sum="$xbmkpwd/util/sbase/sha512sum" -	export PWD="$xbmkpwd" +	if [ $# -gt 0 ] && [ "$1" = "dependencies" ]; then +		x_ xbmkpkg "$@" -	[ $# -gt 0 ] && [ "$1" = "dependencies" ] && x_ xbmkpkg "$@" && exit 0 +		exit 0 +	fi + +	id -u 1>/dev/null 2>/dev/null || \ +	    err "suid check failed" "xbmk_init" "$@" -	id -u 1>/dev/null 2>/dev/null || err "suid check failed (id -u)" -	[ "$(id -u)" != "0" ] || err "this command as root is not permitted" +	if [ "$(id -u)" = "0" ]; then +		err "this command as root is not permitted" "xbmk_init" "$@" +	fi -	for init_cmd in set_pyver set_version set_env git_init create_tmpdir \ -	    lock create_pathdirs child_exec; do -		xbmk_$init_cmd "$@" || break +	export PWD="$xbmkpwd" +	x_ xbmkdir "$basetmp" + +	if [ ! -e "cache" ]; then +		x_ xbmkdir "cache" +	fi + +	for init_cmd in get_version set_env set_threads git_init child_exec; do +		if ! xbmk_$init_cmd "$@"; then +			break +		fi  	done  }  xbmkpkg()  { -	[ $# -lt 2 ] && err "fewer than two arguments" -	[ $# -gt 2 ] && reinstall="$3" +	xchk xbmkpkg "$@" + +	if [ $# -gt 2 ]; then +		reinstall="$3" +	fi + +	. "config/dependencies/$2" || \ +	    err "Can't read 'config/dependencies/$2'" "xbmkpkg" "$@" + +	if [ -z "$pkg_add" ] || [ -z "$pkglist" ]; then +		err "pkg_add/pkglist not both set" "xbmkpkg" "$@" +	fi + +	x_ $pkg_add $pkglist + +	if [ -n "$aur_notice" ]; then +		printf "You need AUR packages: %s\n" "$aur_notice" 1>&2 +	fi +} + +xbmk_get_version() +{ +	if [ -f ".version" ]; then +		read -r version < ".version" || \ +		    err "can't read version file" "xbmk_get_version" "$@" +	fi +	if [ -f ".versiondate" ]; then +		read -r versiondate < ".versiondate" || \ +		    err "can't read versiondate" xbmk_get_version "$@" +	fi + +	if [ -f ".version" ] && [ -z "$version" ]; then +		err "version not set" "xbmk_get_version" "$@" +	fi +	if [ -f ".versiondate" ] && [ -z "$versiondate" ]; then +		err "versiondate not set" "xbmk_get_version" "$@" +	fi + +	if [ ! -e ".git" ] && [ ! -f ".version" ]; then +		version="unknown" +	fi +	if [ ! -e ".git" ] && [ ! -f ".versiondate" ]; then +		versiondate="1716415872" +	fi + +	xbmk_sanitize_version + +	if [ -n "$version" ]; then +		relname="$projectname-$version" +	fi +} + +# a parent instance will cause this function to return 0. +# a child instance will return 1, skipping further initialisation +# after this function is called. +xbmk_set_env() +{ +	is_child="n" + +	xbmkpath="$PATH" + +	# unify all temporary files/directories in a single TMPDIR +	if [ -n "${TMPDIR+x}" ] && [ "${TMPDIR%_*}" != "$basetmp/xbmk" ]; then +		unset TMPDIR +	fi +	if [ -n "${TMPDIR+x}" ]; then +		export TMPDIR="$TMPDIR" +		xbtmp="$TMPDIR" +	fi +	if [ -n "${TMPDIR+x}" ]; then +		is_child="y" +	fi + +	if [ "$is_child" = "y" ] +	then +		# child instance of xbmk, so we stop init after this point +		# and execute the given user command upon return: + +		xbmk_child_set_env + +		return 1 +	else +		# parent instance of xbmk, so we continue initialising. +		# a parent instance of xbmk never processes its own +		# command directly; instead, it calls a child instance +		# of xbmk, and exits with the corresponding return status. +		 +		xbmk_parent_set_env + +		return 0 +	fi +} + +xbmk_child_set_env() +{ +	xbmk_child_set_tmp + +	if [ -z "${XBMK_CACHE+x}" ]; then +		err "XBMK_CACHE unset on child" "xbmk_set_env" "$@" +	fi +	if [ -z "${XBMK_THREADS+x}" ]; then +		xbmk_set_threads; : +	fi +	if [ -z "${XBMK_CACHE_MIRROR+x}" ]; then +		xbmk_set_mirror +	fi +} + +xbmk_child_set_tmp() +{ +	badtmp="" +	locktmp="" +	xbtmpchk="" -	eval "`setcfg "config/dependencies/$2"`" +	xbtmpchk="`findpath "$TMPDIR" || err "!findpath $TMPDIR"`" || \ +	    err "!findpath '$TMPDIR'" "xbmk_child_set_tmp" "$@" -	chkvars pkg_add pkglist -	$pkg_add $pkglist || err "Cannot install packages" +	read -r locktmp < "$xbmklock" || \ +	    err "can't read '$xbmklock'" "xbmk_child_set_tmp" "$@" + +	if [ "$locktmp" != "$xbtmpchk" ]; then +		badtmp="TMPDIR '$xbtmpchk' changed; was '$locktmp'" + +		printf "bad TMPDIR init, '%s': %s\n" "$TMPDIR" "$badtmp" 1>&2 +		err "'$xbmklock' present with bad tmpdir. is a build running?" +	fi -	[ -n "$aur_notice" ] && \ -	    printf "You need AUR packages: %s\n" "$aur_notice" 1>&2; : +	xbtmp="$xbtmpchk" +	export TMPDIR="$xbtmpchk" +} + +xbmk_parent_set_env() +{ +	xbmk_parent_check_tmp + +	printf "%s\n" "$xbtmp" > "$xbmklock" || \ +	    err "cannot create '$xbmklock'" xbmk_set_env "$@"; : + +	# not really critical for security, but it's a barrier +	# against the user to make them think twice before deleting it +	# in case an actual instance of xbmk is already running: + +	x_ chmod -w "$xbmklock" + +	xbmk_parent_set_export +	xbmk_set_version + +	remkdir "$xbtmp" "$xbtmp/gnupath" "$xbtmp/xbmkpath" + +	xbmk_set_pyver +	xbmk_set_mirror +} + +xbmk_parent_check_tmp() +{ +	export TMPDIR="$basetmp" + +	xbmklist="`mktemp || err "can't make tmplist"`" || \ +	    err "can't make tmplist" xbmk_parent_check_tmp "$@" + +	x_ rm -f "$xbmklist" +	x_ touch "$xbmklist" + +	for xtmpdir in "$basetmp"/xbmk_*; do +		if [ -e "$xtmpdir" ]; then +			printf "%s\n" "$xtmpdir" >> "$xbmklist" || \ +			    err "can't write '$xtmpdir' to '$xbmklist'" \ +			    "xbmk_parent_check_tmp" "$@"; : +		fi +	done + +	# set up a unified temporary directory, for common deletion later: +	export TMPDIR="`x_ mktemp -d -t xbmk_XXXXXXXX`" || \ +	    err "can't export TMPDIR" "xbmk_parent_check_tmp" "$@" +	xbtmp="$TMPDIR" + +	while read -r xtmpdir; do +		if [ "$xtmpdir" = "$xbtmp" ]; then +			err "pre-existing '$xbtmp'" "xbmk_parent_check_tmp" "$@" +		fi +	done < "$xbmklist" || \ +	    err "Can't read xbmklist: '$xbmklist'" "xbmk_parent_check_tmp" "$@" + +	x_ rm -f "$xbmklist" +} + +xbmk_parent_set_export() +{ +	export XBMK_CACHE="$xbmkpwd/cache" + +	if [ -e "$XBMK_CACHE" ] && [ ! -d "$XBMK_CACHE" ]; then +		err "cachedir '$XBMK_CACHE' is a file" \ +		    "xbmk_parent_set_export" "$@" +	fi + +	export PATH="$xbtmp/xbmkpath:$xbtmp/gnupath:$PATH" +	xbmkpath="$PATH" + +	# if "y": a coreboot target won't be built if target.cfg says release=n +	# (this is used to exclude certain build targets from releases) + +	if [ -z "${XBMK_RELEASE+x}" ]; then +		export XBMK_RELEASE="n" +	fi +	if [ "$XBMK_RELEASE" = "Y" ]; then +		export XBMK_RELEASE="y" +	fi +	if [ "$XBMK_RELEASE" != "y" ]; then +		export XBMK_RELEASE="n" +	fi +} + +xbmk_set_threads() +{ +	if [ -z "${XBMK_THREADS+x}" ]; then +		export XBMK_THREADS=1 +	fi +	if ! expr "X$XBMK_THREADS" : "X-\{0,1\}[0123456789][0123456789]*$" \ +	    1>/dev/null 2>/dev/null; then +		export XBMK_THREADS=1 +	fi +} + +xbmk_set_version() +{ +	version_="$version" +	if [ -e ".git" ]; then +		version="$(git describe --tags HEAD 2>&1)" || \ +		    version="git-$(git rev-parse HEAD 2>&1)" || \ +		    version="$version_" +	fi + +	versiondate_="$versiondate" +	if [ -e ".git" ]; then +		versiondate="$(git show --no-patch --no-notes \ +		    --pretty='%ct' HEAD)" || versiondate="$versiondate_" +	fi + +	if [ -z "$version" ] || [ -z "$versiondate" ]; then +		err "version and/or versiondate unset" "xbmk_set_version" "$@" +	fi + +	update_xbmkver "." + +	relname="$projectname-$version" +	export LOCALVERSION="-$projectname-${version%%-*}"  }  xbmk_set_pyver()  { -	pyv="import sys; print(sys.version_info[:])"  	python="python3" -	pybin python3 1>/dev/null || python="python" -	pyver="2" && [ "$python" = "python3" ] && pyver="3" -	pybin "$python" 1>/dev/null || pyver="" -	[ -z "$pyver" ] || "`pybin "$python"`" -c "$pyv" 1>/dev/null \ -	    2>/dev/null || err "Cannot detect host Python version." -	[ -n "$pyver" ] && \ -	    pyver="$("$(pybin "$python")" -c "$pyv" | awk '{print $1}')" && \ -	    pyver="${pyver#(}" && pyver="${pyver%,}" -	[ "${pyver%%.*}" = "3" ] || err "Bad python version (must by 3.x)"; : +	pyver="2" +	pyv="import sys; print(sys.version_info[:])" + +	if ! pybin python3 1>/dev/null; then +		python="python" +	fi +	if [ "$python" = "python3" ]; then +		pyver="3" +	fi +	if ! pybin "$python" 1>/dev/null; then +		pyver="" +	fi +	if [ -n "$pyver" ]; then +		"`x_ pybin "$python"`" -c "$pyv" 1>/dev/null \ +		    2>/dev/null || \ +		    err "Can't detect Python version." "xbmk_set_pyver" "$@" +	fi +	if [ -n "$pyver" ]; then +		pyver="$("$(pybin "$python")" -c "$pyv" | awk '{print $1}')" +		pyver="${pyver#(}" +		pyver="${pyver%,}" +	fi +	if [ "${pyver%%.*}" != "3" ]; then +		err "Bad python version (must by 3.x)" "xbmk_set_pyver" "$@" +	fi + +	# set up python in PATH (environmental variable): + +	( +		x_ cd "$xbtmp/xbmkpath" + +		x_ ln -s "`x_ pybin "$python"`" python || \ +		    err "can't make symlink" "xbmk_set_pyver" "$@" + +	) || \ +	    err "Can't link Python in $xbtmp/xbmkpath" "xbmk_set_pyver" "$@"; :  }  # Use direct path, to prevent a hang if Python is using a virtual environment, @@ -74,88 +370,92 @@ pybin()  	py="import sys; quit(1) if sys.prefix == sys.base_prefix else quit(0)"  	venv=1 -	command -v "$1" 1>/dev/null 2>/dev/null || venv=0 -	[ $venv -lt 1 ] || "$1" -c "$py" 1>/dev/null 2>/dev/null || venv=0 +	if ! command -v "$1" 1>/dev/null 2>/dev/null; then +		venv=0 +	fi +	if [ $venv -gt 0 ]; then +		if ! "$1" -c "$py" 1>/dev/null 2>/dev/null; then +			venv=0 +		fi +	fi  	# ideally, don't rely on PATH or hardcoded paths if python venv. -	# use the *real*, direct executable linked to by the venv symlink +	# use the *real*, direct executable linked to by the venv symlink: +  	if [ $venv -gt 0 ] && [ -L "`command -v "$1" 2>/dev/null`" ]; then  		pypath="$(findpath \  		    "$(command -v "$1" 2>/dev/null)" 2>/dev/null || :)" -		[ -e "$pypath" ] && [ ! -d "$pypath" ] && \ -		    [ -x "$pypath" ] && printf "%s\n" "$pypath" && return 0; : -	fi -	# if python venv: fall back to common PATH directories for checking -	[ $venv -gt 0 ] && for pypath in "/usr/local/bin" "/usr/bin"; do -		[ -e "$pypath/$1" ] && [ ! -d "$pypath/$1" ] && \ -		    [ -x "$pypath/$1" ] && printf "%s/%s\n" "$pypath" "$1" && \ -		    return 0 -	done && return 1 +		if [ -e "$pypath" ] && [ ! -d "$pypath" ] && \ +		    [ -x "$pypath" ]; then -	# Defer to normal command -v if not a venv -	command -v "$1" 2>/dev/null || return 1 -} +			printf "%s\n" "$pypath" -xbmk_set_version() -{ -	[ ! -f ".version" ] || read -r version < ".version" || :; : -	[ ! -f ".versiondate" ] || read -r versiondate < ".versiondate" || :; : +			return 0 +		fi +	fi -	[ -e ".git" ] || [ -f ".version" ] || printf "unknown\n" > ".version" \ -	    || err "Cannot generate unknown .version file" -	[ -e ".git" ] || [ -f ".versiondate" ] || printf "1716415872\n" > \ -	    ".versiondate" || err "Can't generate unknown versiondate file"; : +	# if python venv: fall back to common PATH directories for checking: -	version_="$version" -	[ ! -e ".git" ] || version="$(git describe --tags HEAD 2>&1)" || \ -	    version="git-$(git rev-parse HEAD 2>&1)" || version="$version_" -	versiondate_="$versiondate" -	[ ! -e ".git" ] || versiondate="$(git show --no-patch --no-notes \ -	    --pretty='%ct' HEAD)" || versiondate="$versiondate_" +	[ $venv -gt 0 ] && for pypath in "/usr/local/bin" "/usr/bin"; do +		if [ -e "$pypath/$1" ] && [ ! -d "$pypath/$1" ] && \ +		    [ -x "$pypath/$1" ]; then -	chkvars version versiondate -	printf "%s\n" "$version" > ".version" || err "can't save version" -	printf "%s\n" "$versiondate" > ".versiondate" || err "can't save date" +			printf "%s/%s\n" "$pypath" "$1" -	relname="$projectname-$version" +			return 0 +		fi +	done && return 1 + +	# Defer to normal command -v if not a venv +	if ! command -v "$1" 2>/dev/null; then +		return 1 +	fi  } -xbmk_set_env() +xbmk_set_mirror()  { -	export LOCALVERSION="-$projectname-${version%%-*}" +	# defines whether cache/clone/ (regular clones) +	# or cache/mirror (--mirror clones) are used, per project -	# XBMK_CACHE is a directory, for caching downloads and git repon -	[ -z "${XBMK_CACHE+x}" ] && export XBMK_CACHE="$xbmkpwd/cache" -	[ -z "$XBMK_CACHE" ] && export XBMK_CACHE="$xbmkpwd/cache" -	[ -L "$XBMK_CACHE" ] && [ "$XBMK_CACHE" = "$xbmkpwd/cache" ] && \ -	    err "cachedir '$xbmkpwd/cache' is a symlink" -	[ -L "$XBMK_CACHE" ] && export XBMK_CACHE="$xbmkpwd/cache" -	xbmkcache="`findpath "$XBMK_CACHE"`" || \ -	    err "Can't resolve cachedir: '$XBMK_CACHE'" -	export XBMK_CACHE="$xbmkcache" -	[ -d "$XBMK_CACHE" ] || err "cachedir '$XBMK_CACHE' is a file"; : - -	# if "y": a coreboot target won't be built if target.cfg says release="n" -	# (this is used to exclude certain build targets from releases) -	[ -z "${XBMK_RELEASE+x}" ] && export XBMK_RELEASE="n" -	[ "$XBMK_RELEASE" = "y" ] || export XBMK_RELEASE="n" +	# to use cache/mirror/ do: export XBMK_CACHE_MIRROR="y" +	# mirror/ stores a separate directory per repository, even per backup. +	# it's slower, and uses more disk space, and some upstreams might not +	# appreciate it, so it should only be used for development or archival -	[ -z "${XBMK_THREADS+x}" ] && export XBMK_THREADS=1 -	expr "X$XBMK_THREADS" : "X-\{0,1\}[0123456789][0123456789]*$" \ -	    1>/dev/null 2>/dev/null || export XBMK_THREADS=1; : +	if [ -z "${XBMK_CACHE_MIRROR+x}" ]; then +		export XBMK_CACHE_MIRROR="n" +	fi +	if [ "$XBMK_CACHE_MIRROR" != "y" ]; then +		export XBMK_CACHE_MIRROR="n" +	fi  }  xbmk_git_init()  {  	for gitarg in "--global user.name" "--global user.email"; do -		gitcmd="git config $gitarg"; $gitcmd 1>/dev/null 2>/dev/null \ -		    || err "Run this first: $gitcmd \"your ${gitcmd##*.}\"" +		gitcmd="git config $gitarg" +		if ! $gitcmd 1>/dev/null 2>/dev/null; then +			err "Run this first: $gitcmd \"your ${gitcmd##*.}\"" \ +			    "xbmk_git_init" "$@" +		fi  	done -	[ -L ".git" ] && return 1 -	[ -e ".git" ] && return 0 -	eval "`setvars "$(date -Rud @$versiondate)" cdate _nogit`" +	if [ -L ".git" ]; then +		err "'$xbmkpwd/.git' is a symlink" "xbmk_git_init" "$@" +	fi +	if [ -e ".git" ]; then +		return 0 +	fi + +	# GNU-specific extensions of date are used. +	# TODO: that is a bug. fix it! + +	x_ date --version | grep "GNU coreutils" 1>/dev/null 2>/dev/null || \ +	    err "Non-GNU date implementation" "xbmk_git_init" "$@" + +	cdate="`x_ date -Rud @$versiondate || err "can't get date"`" || \ +	    err "can't get date" "xbmk_git_init" "$@"  	x_ git init 1>/dev/null 2>/dev/null  	x_ git add -A . 1>/dev/null 2>/dev/null @@ -165,50 +465,15 @@ xbmk_git_init()  	    2>/dev/null; :  } -xbmk_create_tmpdir() -{ -	x_ mkdir -p "$xbmklocal" - -	# unify all temporary files/directories in a single TMPDIR -	[ -z "${TMPDIR+x}" ] || [ "${TMPDIR%_*}" = "/tmp/xbmk" ] || \ -	    unset TMPDIR -	[ -n "${TMPDIR+x}" ] && export TMPDIR="$TMPDIR" && xbmktmp="$TMPDIR" -	[ -z "${TMPDIR+x}" ] || return 1 # child instance, so return - -	# parent instance of xbmk, so don't return. set up TMPDIR -	export TMPDIR="/tmp" -	export TMPDIR="$(mktemp -d -t xbmk_XXXXXXXX)" -	xbmktmp="$TMPDIR" - -	# /tmp might be a tmpfs, so for large files we use ./tmp, -	# not to be confused with xbmktmp (xbmktmp points to /tmp) -	remkdir "$xbmktmp" "$xbmklocal" -} - -xbmk_lock() -{ -	[ -f "$xbmklock" ] && err "'$xbmklock' exists. Is a build running?" -	touch "$xbmklock" || err "cannot create '$xbmklock'"; : -} - -xbmk_create_pathdirs() -{ -	remkdir "$XBMK_CACHE/gnupath" "$XBMK_CACHE/xbmkpath" -	export PATH="$XBMK_CACHE/xbmkpath:$XBMK_CACHE/gnupath:$PATH" -	( -	# set up python v3.x in PATH, in case it's not set up correctly. -	# see code above that detected the correct python3 command. -	cd "$XBMK_CACHE/xbmkpath" || err "can't cd $XBMK_CACHE/xbmkpath" -	x_ ln -s "`pybin "$python"`" python -	) || err "Can't set up python symlink in $XBMK_CACHE/xbmkpath"; : -} -  xbmk_child_exec()  {  	xbmk_rval=0 +  	( x_ ./mk "$@" ) || xbmk_rval=1 -	( x_ rm -Rf "$xbmklocal" "$xbmktmp" ) || xbmk_rval=1 + +	( x_ rm -Rf "$xbtmp" ) || xbmk_rval=1  	( x_ rm -f "$xbmklock" ) || xbmk_rval=1 +  	exit $xbmk_rval  }  | 
