diff --git a/release-tool b/release-tool
index adb1e4c61f..b838f87539 100755
--- a/release-tool
+++ b/release-tool
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
#
# KeePassXC Release Preparation Helper
-# Copyright (C) 2017 KeePassXC team
+# Copyright (C) 2021 KeePassXC team
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,8 +17,9 @@
# along with this program. If not, see .
printf "\e[1m\e[32mKeePassXC\e[0m Release Preparation Helper\n"
-printf "Copyright (C) 2017 KeePassXC Team \n\n"
+printf "Copyright (C) 2021 KeePassXC Team \n\n"
+set -eE -o pipefail
# -----------------------------------------------------------------------
# global default values
@@ -52,7 +53,7 @@ TIMESTAMP_SERVER="http://timestamp.sectigo.com"
# -----------------------------------------------------------------------
printUsage() {
local cmd
- if [ "" == "$1" ] || [ "help" == "$1" ]; then
+ if [ -z "$1" ] || [ "help" == "$1" ]; then
cmd="COMMAND"
elif [ "check" == "$1" ] || [ "merge" == "$1" ] || [ "build" == "$1" ] || [ "gpgsign" == "$1" ] || \
[ "appsign" == "$1" ] || [ "notarize" == "$1" ] || [ "appimage" == "$1" ] || [ "i18n" == "$1" ]; then
@@ -212,17 +213,17 @@ logError() {
}
init() {
- if [ "" == "$RELEASE_NAME" ]; then
+ if [ -z "$RELEASE_NAME" ]; then
logError "Missing arguments, --version is required!\n"
printUsage "check"
exit 1
fi
- if [ "" == "$TAG_NAME" ]; then
+ if [ -z "$TAG_NAME" ]; then
TAG_NAME="$RELEASE_NAME"
fi
- if [ "" == "$SOURCE_BRANCH" ]; then
+ if [ -z "$SOURCE_BRANCH" ]; then
SOURCE_BRANCH="release/${RELEASE_NAME}"
fi
@@ -285,29 +286,25 @@ checkGitRepository() {
}
checkReleaseDoesNotExist() {
- git tag | $GREP -q "^$TAG_NAME$"
- if [ $? -eq 0 ]; then
+ if ! git tag | $GREP -q "^$TAG_NAME$"; then
exitError "Release '$RELEASE_NAME' (tag: '$TAG_NAME') already exists!"
fi
}
checkWorkingTreeClean() {
- git diff-index --quiet HEAD --
- if [ $? -ne 0 ]; then
+ if ! git diff-index --quiet HEAD --; then
exitError "Current working tree is not clean! Please commit or unstage any changes."
fi
}
checkSourceBranchExists() {
- git rev-parse "$SOURCE_BRANCH" > /dev/null 2>&1
- if [ $? -ne 0 ]; then
+ if ! git rev-parse "$SOURCE_BRANCH" > /dev/null 2>&1; then
exitError "Source branch '$SOURCE_BRANCH' does not exist!"
fi
}
checkTargetBranchExists() {
- git rev-parse "$TARGET_BRANCH" > /dev/null 2>&1
- if [ $? -ne 0 ]; then
+ if ! git rev-parse "$TARGET_BRANCH" > /dev/null 2>&1; then
exitError "Target branch '$TARGET_BRANCH' does not exist!"
fi
}
@@ -318,18 +315,15 @@ checkVersionInCMake() {
local minor_num="$(echo ${RELEASE_NAME} | cut -f2 -d.)"
local patch_num="$(echo ${RELEASE_NAME} | cut -f3 -d. | cut -f1 -d-)"
- $GREP -q "${app_name_upper}_VERSION_MAJOR \"${major_num}\"" CMakeLists.txt
- if [ $? -ne 0 ]; then
+ if ! $GREP -q "${app_name_upper}_VERSION_MAJOR \"${major_num}\"" CMakeLists.txt; then
exitError "${app_name_upper}_VERSION_MAJOR not updated to '${major_num}' in CMakeLists.txt!"
fi
- $GREP -q "${app_name_upper}_VERSION_MINOR \"${minor_num}\"" CMakeLists.txt
- if [ $? -ne 0 ]; then
+ if ! $GREP -q "${app_name_upper}_VERSION_MINOR \"${minor_num}\"" CMakeLists.txt; then
exitError "${app_name_upper}_VERSION_MINOR not updated to '${minor_num}' in CMakeLists.txt!"
fi
- $GREP -q "${app_name_upper}_VERSION_PATCH \"${patch_num}\"" CMakeLists.txt
- if [ $? -ne 0 ]; then
+ if ! $GREP -q "${app_name_upper}_VERSION_PATCH \"${patch_num}\"" CMakeLists.txt; then
exitError "${app_name_upper}_VERSION_PATCH not updated to '${patch_num}' in CMakeLists.txt!"
fi
}
@@ -339,8 +333,7 @@ checkChangeLog() {
exitError "No CHANGELOG file found!"
fi
- $GREP -qPzo "## ${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n" CHANGELOG.md
- if [ $? -ne 0 ]; then
+ if ! $GREP -qPzo "## ${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n" CHANGELOG.md; then
exitError "'CHANGELOG.md' has not been updated to the '${RELEASE_NAME}' release!"
fi
}
@@ -350,8 +343,7 @@ checkAppStreamInfo() {
exitError "No AppStream info file found!"
fi
- $GREP -qPzo "" share/linux/org.keepassxc.KeePassXC.appdata.xml
- if [ $? -ne 0 ]; then
+ if ! $GREP -qPzo "" share/linux/org.keepassxc.KeePassXC.appdata.xml; then
exitError "'share/linux/org.keepassxc.KeePassXC.appdata.xml' has not been updated to the '${RELEASE_NAME}' release!"
fi
}
@@ -362,13 +354,11 @@ checkSnapcraft() {
return
fi
- $GREP -qPzo "version: ${RELEASE_NAME}" snap/snapcraft.yaml
- if [ $? -ne 0 ]; then
+ if ! $GREP -qPzo "version: ${RELEASE_NAME}" snap/snapcraft.yaml; then
exitError "'snapcraft.yaml' has not been updated to the '${RELEASE_NAME}' release!"
fi
- $GREP -qPzo "KEEPASSXC_BUILD_TYPE=Release" snap/snapcraft.yaml
- if [ $? -ne 0 ]; then
+ if ! $GREP -qPzo "KEEPASSXC_BUILD_TYPE=Release" snap/snapcraft.yaml; then
exitError "'snapcraft.yaml' is not set for a release build!"
fi
}
@@ -464,7 +454,7 @@ if ! cmdExists realpath; then
fi
-trap exitTrap SIGINT SIGTERM
+trap exitTrap SIGINT SIGTERM ERR
# -----------------------------------------------------------------------
# check command
@@ -551,11 +541,10 @@ merge() {
if [ 0 -ne $? ]; then
exitError "Updating translations failed!"
fi
- git diff-index --quiet HEAD --
- if [ $? -ne 0 ]; then
+ if ! git diff-index --quiet HEAD --; then
git add -A ./share/translations/
logInfo "Committing changes..."
- if [ "" == "$GPG_GIT_KEY" ]; then
+ if [ -z "$GPG_GIT_KEY" ]; then
git commit -m "Update translations"
else
git commit -m "Update translations" -S"$GPG_GIT_KEY"
@@ -574,7 +563,7 @@ merge() {
git merge "$SOURCE_BRANCH" --no-ff -m "$COMMIT_MSG" -m "${CHANGELOG}" "$SOURCE_BRANCH" -S"$GPG_GIT_KEY"
logInfo "Creating tag '${TAG_NAME}'..."
- if [ "" == "$GPG_GIT_KEY" ]; then
+ if [ -z "$GPG_GIT_KEY" ]; then
git tag -a "$TAG_NAME" -m "$COMMIT_MSG" -m "${CHANGELOG}" -s
else
git tag -a "$TAG_NAME" -m "$COMMIT_MSG" -m "${CHANGELOG}" -s -u "$GPG_GIT_KEY"
@@ -657,7 +646,7 @@ appimage() {
appdir="$(realpath "$appdir")"
local out="${OUTPUT_DIR}"
- if [ "" == "$out" ]; then
+ if [ -z "$out" ]; then
out="."
fi
mkdir -p "$out"
@@ -674,12 +663,12 @@ appimage() {
logInfo "Testing for AppImage tools..."
local docker_test_cmd
if [ "" != "$DOCKER_IMAGE" ]; then
- docker_test_cmd="docker run --rm ${DOCKER_IMAGE}"
+ docker_test_cmd="docker run -it --user $(id -u):$(id -g) --rm ${DOCKER_IMAGE}"
fi
# Test if linuxdeploy and linuxdeploy-plugin-qt are installed
# on the system or inside the Docker container
- if ! ${docker_test_cmd} which ${linuxdeploy} &> /dev/null; then
+ if ! ${docker_test_cmd} which ${linuxdeploy} > /dev/null; then
logInfo "Downloading linuxdeploy..."
linuxdeploy="./linuxdeploy"
linuxdeploy_cleanup="rm -f ${linuxdeploy}"
@@ -688,7 +677,7 @@ appimage() {
fi
chmod +x "$linuxdeploy"
fi
- if ! ${docker_test_cmd} which ${linuxdeploy_plugin_qt} &> /dev/null; then
+ if ! ${docker_test_cmd} which ${linuxdeploy_plugin_qt} > /dev/null; then
logInfo "Downloading linuxdeploy-plugin-qt..."
linuxdeploy_plugin_qt="./linuxdeploy-plugin-qt"
linuxdeploy_plugin_qt_cleanup="rm -f ${linuxdeploy_plugin_qt}"
@@ -710,49 +699,46 @@ appimage() {
fi
# Create custom AppRun wrapper
- cat << EOF > "${out_real}/KeePassXC-AppRun"
+ cat << 'EOF' > "${out_real}/KeePassXC-AppRun"
#!/usr/bin/env bash
-export PATH="\$(dirname \$0)/usr/bin:\${PATH}"
-export LD_LIBRARY_PATH="\$(dirname \$0)/usr/lib:\${LD_LIBRARY_PATH}"
+export PATH="$(dirname $0)/usr/bin:${PATH}"
+export LD_LIBRARY_PATH="$(dirname $0)/usr/lib:${LD_LIBRARY_PATH}"
-if [ "\${1}" == "cli" ]; then
+if [ "$1" == "cli" ]; then
shift
- exec keepassxc-cli "\$@"
-elif [ "\${1}" == "proxy" ]; then
+ exec keepassxc-cli "$@"
+elif [ "$1" == "proxy" ]; then
shift
- exec keepassxc-proxy "\$@"
+ exec keepassxc-proxy "$@"
elif [ -v CHROME_WRAPPER ] || [ -v MOZ_LAUNCHED_CHILD ]; then
- exec keepassxc-proxy "\$@"
+ exec keepassxc-proxy "$@"
else
- exec keepassxc "\$@"
+ exec keepassxc "$@"
fi
EOF
chmod +x "${out_real}/KeePassXC-AppRun"
# Find .desktop files, icons, and binaries to deploy
local desktop_file="$(find "$appdir" -name "org.keepassxc.KeePassXC.desktop" | head -n1)"
- local icon="$(find "$appdir" -name 'keepassxc.png' | $GREP -P 'application/256x256/apps/keepassxc.png$' | head -n1)"
- local executables="$(IFS=$'\n' find "$appdir" | $GREP -P '/usr/bin/keepassxc[^/]*$' | xargs -i printf " --executable={}")"
+ local icon="$(find "$appdir" -path '*/application/256x256/apps/keepassxc.png' | head -n1)"
+ local executables="$(find "$appdir" -type f -executable -path '*/bin/keepassxc*' -print0 | xargs -0 -i printf " --executable={}")"
logInfo "Collecting libs and patching binaries..."
- if [ "" == "$DOCKER_IMAGE" ]; then
+ if [ -z "$DOCKER_IMAGE" ]; then
"$linuxdeploy" --verbosity=${verbosity} --plugin=qt --appdir="$appdir" --desktop-file="$desktop_file" \
- --custom-apprun="${out_real}/KeePassXC-AppRun" --icon-file="$icon" ${executables} \
- --library=$(ldconfig -p | $GREP x86-64 | $GREP -oP '/[^\s]+/libgpg-error\.so\.\d+$' | head -n1)
+ --custom-apprun="${out_real}/KeePassXC-AppRun" --icon-file="$icon" ${executables}
else
- desktop_file="${desktop_file//${appdir}/\/keepassxc\/AppDir}"
- icon="${icon//${appdir}/\/keepassxc\/AppDir}"
- executables="${executables//${appdir}/\/keepassxc\/AppDir}"
-
docker run --name "$DOCKER_CONTAINER_NAME" --rm \
- --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse \
- -v "${appdir}:/keepassxc/AppDir:rw" \
- -v "${out_real}:/keepassxc/out:rw" \
+ --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse -it \
+ -v "${out_real}:${out_real}:rw" \
+ -v "${appdir}:${appdir}:rw" \
+ -w "$out_real" \
+ --user $(id -u):$(id -g) \
"$DOCKER_IMAGE" \
- bash -c "cd /keepassxc/out && ${linuxdeploy} --verbosity=${verbosity} --plugin=qt --appdir=/keepassxc/AppDir \
- --custom-apprun="/keepassxc/out/KeePassXC-AppRun" --desktop-file=${desktop_file} --icon-file=${icon} ${executables} \
- --library=\$(ldconfig -p | grep x86-64 | grep -oP '/[^\s]+/libgpg-error\.so\.\d+$' | head -n1)"
+ bash -c "${linuxdeploy} --verbosity=${verbosity} --plugin=qt \
+ --appdir='${appdir}' --custom-apprun='${out_real}/KeePassXC-AppRun' \
+ --desktop-file='${desktop_file}' --icon-file='${icon}' ${executables}"
fi
if [ $? -ne 0 ]; then
@@ -900,7 +886,6 @@ build() {
init
- OUTPUT_DIR="$(realpath "$OUTPUT_DIR")"
# Resolve appsign key to absolute path if under Windows
if [[ "${build_key}" && "$(uname -o)" == "Msys" ]]; then
build_key="$(realpath "${build_key}")"
@@ -930,10 +915,13 @@ build() {
git checkout "$TAG_NAME" > /dev/null 2>&1
fi
- logInfo "Creating output directory..."
- mkdir -p "$OUTPUT_DIR"
+ OUTPUT_DIR="$(realpath "$OUTPUT_DIR")"
+ if ! ${build_snapshot} && [ -d "$OUTPUT_DIR" ]; then
+ exitError "Output dir '${OUTPUT_DIR}' already exists."
+ fi
- if [ $? -ne 0 ]; then
+ logInfo "Creating output directory..."
+ if ! mkdir -p "$OUTPUT_DIR"; then
exitError "Failed to create output directory!"
fi
@@ -961,14 +949,6 @@ build() {
$xz -6 "${OUTPUT_DIR}/${tarball_name}"
fi
- if ! ${build_snapshot} && [ -e "${OUTPUT_DIR}/build-release" ]; then
- logInfo "Cleaning existing build directory..."
- rm -rf "${OUTPUT_DIR}/build-release" 2> /dev/null
- if [ $? -ne 0 ]; then
- exitError "Failed to clean existing build directory, please do it manually."
- fi
- fi
-
logInfo "Creating build directory..."
mkdir -p "${OUTPUT_DIR}/build-release"
cd "${OUTPUT_DIR}/build-release"
@@ -994,7 +974,7 @@ build() {
fi
export CXX="$COMPILER"
- if [ "" == "$DOCKER_IMAGE" ]; then
+ if [ -z "$DOCKER_IMAGE" ]; then
if [ "$(uname -s)" == "Darwin" ]; then
# Building on macOS
export MACOSX_DEPLOYMENT_TARGET
@@ -1068,7 +1048,7 @@ build() {
logInfo "Launching Docker contain to compile snapcraft..."
- sudo docker run --name "$DOCKER_CONTAINER_NAME" --rm \
+ sudo docker run --name "$DOCKER_CONTAINER_NAME" --rm -it --user $(id -u):$(id -g) \
-v "$(realpath "$SRC_DIR"):/keepassxc" -w "/keepassxc" \
"$DOCKER_IMAGE" snapcraft
else
@@ -1078,7 +1058,8 @@ build() {
docker run --name "$DOCKER_CONTAINER_NAME" --rm \
--cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse \
- -e "CC=${CC}" -e "CXX=${CXX}" \
+ --user $(id -u):$(id -g) \
+ -e "CC=${CC}" -e "CXX=${CXX}" -it \
-v "$(realpath "$SRC_DIR"):/keepassxc/src:ro" \
-v "$(realpath "$OUTPUT_DIR"):/keepassxc/out:rw" \
"$DOCKER_IMAGE" \
@@ -1108,7 +1089,7 @@ build() {
docker_image_flag="-d ${DOCKER_IMAGE}"
docker_container_name_flag="--container-name ${DOCKER_CONTAINER_NAME}"
fi
- appimage "-a" "${OUTPUT_DIR}/KeePassXC.AppDir" "-o" "${OUTPUT_DIR}" \
+ appimage -a "${OUTPUT_DIR}/KeePassXC.AppDir" -o "${OUTPUT_DIR}" \
${appsign_flag} ${appsign_key_flag} ${docker_image_flag} ${docker_container_name_flag}
fi
@@ -1376,7 +1357,7 @@ notarize() {
exit 1
fi
- if [ "$ac_username" == "" ]; then
+ if [ -z "$ac_username" ]; then
logError "Missing arguments, --username is required!"
printUsage "notarize"
exit 1
@@ -1441,7 +1422,7 @@ notarize() {
i18n() {
local cmd="$1"
- if [ "$cmd" == "" ]; then
+ if [ -z "$cmd" ]; then
logError "No subcommand specified.\n"
printUsage i18n
exit 1
@@ -1452,12 +1433,16 @@ i18n() {
fi
shift
+ checkGitRepository
+
if [ "$cmd" == "lupdate" ]; then
if [ ! -d share/translations ]; then
logError "Command must be called from repository root directory."
exit 1
fi
+ checkQt5LUpdateExists
+
logInfo "Updating source translation file..."
LUPDATE=lupdate-qt5
if ! command -v $LUPDATE > /dev/null; then
@@ -1469,6 +1454,8 @@ i18n() {
return 0
fi
+ checkTransifexCommandExists
+
local branch="$(git branch --show-current 2>&1)"
local real_branch="$branch"
if [[ "$branch" =~ ^release/ ]]; then
@@ -1504,8 +1491,8 @@ i18n() {
# parse global command line
# -----------------------------------------------------------------------
MODE="$1"
-shift
-if [ "" == "$MODE" ]; then
+shift || true
+if [ -z "$MODE" ]; then
logError "Missing arguments!\n"
printUsage
exit 1