spiegel-keyman/linux/scripts/package-build.inc.sh
Eberhard Beilharz f339ceb722
maint(linux): fix Linux source tarball
Previously we tried to include all necessary files in the Linux source
tarball, so that a user would be able to successfully run the top-level
`build.sh` file. However, that causes problems when new dependencies
between sub-projects get introduced that would require adding additional
sub-projects to the tarball.

This change modifies the tarball to only include files that are necessary
to run the `linux/build.sh` file, i.e. necessary to build Keyman for
Linux. This is likely what users would expect when they download a source
tarball for Linux. If users want to build other parts of Keyman that are
buildable on Linux they can download the source tarball that the GitHub
releases page provides, or clone the repo.

In order to be able to still run the top-level `build.sh` script, this
change replaces the top-level `build.sh` with a script that simply
forwards the arguments to `linux/build.sh`.

This change also reverts the recent introduction of a *.pkg.tar.xz file
that contained all files necessary to build a Debian/Ubuntu package. There
wouldn't be a difference anymore between the two .tar.xz files.

Fixes: #16004
Fixes: #16005
Build-bot: skip build:linux
Test-bot: skip
2026-05-26 16:14:57 +02:00

214 lines
6.4 KiB
Bash

# shellcheck shell=bash
# Keyman is copyright (C) SIL Global. MIT License.
function checkPrerequisites() {
# Check the tier
if [[ -z "${KEYMAN_TIER:=}" ]]; then
echo "TIER.md or \${KEYMAN_TIER} must be set to (alpha, beta, stable) to use this script"
exit 1
fi
if ! builder_has_option --no-download && ! command -v xmllint > /dev/null; then
echo "you must install xmllint (libxml2-utils package) to use this script"
exit 1
fi
}
function downloadSource() {
local packageDir
packageDir=$1
# shellcheck disable=SC2154
cd "${KEYMAN_ROOT}/linux" || exit
./build.sh clean
# Update tier in Debian watch files (replacing any previously set tier) and remove comment
sed -e "s/\$tier\|alpha\|beta\|stable/${KEYMAN_TIER}/g" -e "s/^# .*$//" "${KEYMAN_ROOT}/linux/scripts/watch.in" > debian/watch
version=$(uscan --report --dehs|xmllint --xpath "//dehs/upstream-version/text()" -)
dirversion=$(uscan --report --dehs|xmllint --xpath "//dehs/upstream-url/text()" - | cut -d/ -f6)
echo "Keyman version is ${version}"
uscan || (echo "ERROR: No new version available for keyman" >&2 && exit 1)
cd ..
mv "keyman-${version}" "${KEYMAN_ROOT}/linux/${packageDir}"
mv "keyman_${version}.orig.tar.xz" "${KEYMAN_ROOT}/linux/${packageDir}"
mv "keyman-${version}.tar.xz" "${KEYMAN_ROOT}/linux/${packageDir}"
mv "keyman"*.asc "${KEYMAN_ROOT}/linux/${packageDir}"
rm "keyman"*.debian.tar.xz
cd "${KEYMAN_ROOT}/linux/${packageDir}" || exit
wget -N "https://downloads.keyman.com/linux/${KEYMAN_TIER}/${dirversion}/SHA256SUMS"
sha256sum -c --ignore-missing SHA256SUMS | grep "keyman"
}
function wait_for_apt_deb {
# from https://gist.github.com/hrpatel/117419dcc3a75e46f79a9f1dce99ef52
while sudo fuser /var/{lib/{dpkg,apt/lists},cache/apt/archives}/lock &>/dev/null 2>&1; do
echo "Waiting for apt/dpkg lock to release, sleeping 10s"
sleep 10
done
}
function checkAndInstallRequirements()
{
local TOINSTALL=""
for p in devscripts equivs python3-dev
do
if ! dpkg -s "${p}" >/dev/null 2>&1; then
TOINSTALL="${TOINSTALL} ${p}"
fi
done
if [[ -n "${TOINSTALL}" ]]; then
wait_for_apt_deb && sudo apt-get update
# shellcheck disable=SC2086
wait_for_apt_deb && sudo DEBIAN_FRONTEND="noninteractive" \
apt-get -qy install ${TOINSTALL}
fi
sudo mk-build-deps debian/control
wait_for_apt_deb && sudo DEBIAN_FRONTEND="noninteractive" \
apt-get -qy --allow-downgrades install ./keyman-build-deps_*.deb
rm -f keyman-build-deps_*
}
# Generate an array of files and directories to ignore, prefixed with --tar-ignore=keyman/
function generate_tar_ignore_list() {
local directory="$1"
local includes_var="$2"
local excludes_var="$3"
local list_var="$4"
local prefix="$5"
local includes_array="${includes_var}[@]"
# shellcheck disable=SC2034
local includes=("${!includes_array}")
local excludes_array="${excludes_var}[@]"
local excludes=("${!excludes_array}")
# Loop through excludes and put all without path in single_excludes
local single_excludes=()
for item in "${excludes[@]}"; do
if [[ ${item} != */* ]]; then
single_excludes+=("${item}")
fi
done
local ignore_list=()
_process_directory "${directory}" false
for item in "${ignore_list[@]}"; do
eval "${list_var}+=(\"--tar-ignore=${item}\")"
done
}
function _process_directory() {
local directory="$1"
local isParentIncluded="$2"
local all_items item
mapfile -t all_items < <(find "${directory}" -mindepth 1 -maxdepth 1 | sort)
for item in "${all_items[@]}"; do
debug "Checking item: ${item}"
if _is_exact_match "includes" "${item}"; then
debug " Including (full match): ${item}"
if [[ -d "${item}" ]]; then
_process_directory "${item}" true
fi
elif _starts_with "includes" "${item}"; then
debug " Including (partial match): ${item}"
if [[ -d "${item}" ]]; then
_process_directory "${item}" "${isParentIncluded}"
fi
elif _is_exact_match "excludes" "${item}"; then
debug " Excluding (full match): ${item}"
_add_to_list "${item}"
elif _ends_with "single_excludes" "${item}" || _is_wildcard_match "single_excludes" "${item}"; then
debug " Excluding (single exclude): ${item}"
_add_to_list "${item}"
elif [[ "${isParentIncluded}" == "false" ]]; then
debug " Excluding (not included): ${item}"
_add_to_list "${item}"
else
debug " Including (parent included): ${item}"
if [[ -d "${item}" ]]; then
_process_directory "${item}" "${isParentIncluded}"
fi
fi
done
}
function _add_to_list() {
local item="$1"
ignore_list+=("${prefix}/${item#./}")
}
# Returns true if one of the values in the $1 array equals ${file} ($2)
# Example: will return true for array=(path1/path2) file=./path1/path2
function _is_exact_match() {
local array_var="$1"
local file="$2"
local array_name="${array_var}[@]"
local haystack=("${!array_name}")
local item
for item in "${haystack[@]}"; do
if [[ "./${item#./}" == "${file}" ]]; then
return 0
fi
done
return 1
}
# Returns true if one of the values in the $1 array starts with ${file} ($2)
# Example: will return true for array=(path1/path2) file=./path1
function _starts_with() {
local array_var="$1"
local file="$2"
local array_name="${array_var}[@]"
local array_values=("${!array_name}")
local array_item
for array_item in "${array_values[@]}"; do
if [[ "./${array_item#./}" == ${file}* ]]; then
return 0
fi
done
return 1
}
# Returns true if ${file} ($2) ends with one of the values in the $1 array
# Example: will return true for array=(path2) file=./path1/path2
function _ends_with() {
local array_var="$1"
local file="$2"
local array_name="${array_var}[@]"
local array_values=("${!array_name}")
local array_item
for array_item in "${array_values[@]}"; do
if [[ "${file}" == */${array_item#./} ]]; then
return 0
fi
done
return 1
}
# Returns true if ${file} ($2) matches one of the values of the $1 array.
# These values may contain wildcards.
# Example: will return true for array=(*.sh) file=./path1/build.sh
function _is_wildcard_match() {
local array_var="$1"
local file="$2"
local array_name="${array_var}[@]"
local array_values=("${!array_name}")
local array_item
for array_item in "${array_values[@]}"; do
array_item=${array_item/./\\.}
if [[ "${file}" =~ /${array_item/\*/.\*}$ ]]; then
return 0
fi
done
return 1
}
function debug() {
# echo "$@"
return 0
}