mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-28 08:49:42 -05:00
Merge remote-tracking branch 'origin/master' into develop
This commit is contained in:
commit
7db7747cb0
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1,6 +1,7 @@
|
||||
src/version.h.cmake export-subst
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
.github export-ignore
|
||||
.travis.yml export-ignore
|
||||
.tx export-ignore
|
||||
snapcraft.yaml export-ignore
|
||||
|
@ -39,26 +39,54 @@ mkdir -p $APP.AppDir
|
||||
wget -q https://github.com/probonopd/AppImages/raw/master/functions.sh -O ./functions.sh
|
||||
. ./functions.sh
|
||||
|
||||
LIB_DIR=./usr/lib
|
||||
if [ -d ./usr/lib/x86_64-linux-gnu ]; then
|
||||
LIB_DIR=./usr/lib/x86_64-linux-gnu
|
||||
fi
|
||||
|
||||
cd $APP.AppDir
|
||||
cp -a ../../bin-release/* .
|
||||
mv ./usr/local/* ./usr
|
||||
rmdir ./usr/local
|
||||
patch_strings_in_file /usr/local ./
|
||||
cp -a ./usr/local/* ./usr
|
||||
rm -R ./usr/local
|
||||
rmdir ./opt 2> /dev/null
|
||||
patch_strings_in_file /usr/local ././
|
||||
patch_strings_in_file /usr ./
|
||||
|
||||
# bundle Qt platform plugins and themes
|
||||
QXCB_PLUGIN="$(find /usr/lib -name 'libqxcb.so' 2> /dev/null)"
|
||||
if [ "$QXCB_PLUGIN" == "" ]; then
|
||||
QXCB_PLUGIN="$(find /opt/qt*/plugins -name 'libqxcb.so' 2> /dev/null)"
|
||||
fi
|
||||
QT_PLUGIN_PATH="$(dirname $(dirname $QXCB_PLUGIN))"
|
||||
mkdir -p ".${QT_PLUGIN_PATH}/platforms"
|
||||
cp "$QXCB_PLUGIN" ".${QT_PLUGIN_PATH}/platforms/"
|
||||
|
||||
get_apprun
|
||||
copy_deps
|
||||
delete_blacklisted
|
||||
|
||||
# remove dbus and systemd libs as they are not blacklisted
|
||||
find . -name libdbus-1.so.3 -exec rm {} \;
|
||||
find . -name libsystemd.so.0 -exec rm {} \;
|
||||
|
||||
get_desktop
|
||||
get_icon
|
||||
cat << EOF > ./usr/bin/keepassxc_env
|
||||
#!/usr/bin/env bash
|
||||
#export QT_QPA_PLATFORMTHEME=gtk2
|
||||
export LD_LIBRARY_PATH="../opt/qt58/lib:\${LD_LIBRARY_PATH}"
|
||||
export QT_PLUGIN_PATH="..${QT_PLUGIN_PATH}"
|
||||
exec keepassxc "\$@"
|
||||
EOF
|
||||
chmod +x ./usr/bin/keepassxc_env
|
||||
sed -i 's/Exec=keepassxc/Exec=keepassxc_env/' keepassxc.desktop
|
||||
get_desktopintegration $LOWERAPP
|
||||
|
||||
GLIBC_NEEDED=$(glibc_needed)
|
||||
|
||||
cd ..
|
||||
|
||||
generate_appimage
|
||||
generate_type2_appimage
|
||||
|
||||
mv ../out/*.AppImage ..
|
||||
rmdir ../out > /dev/null 2>&1
|
||||
|
10
CHANGELOG
10
CHANGELOG
@ -1,3 +1,13 @@
|
||||
2.1.1 (2017-02-06)
|
||||
=========================
|
||||
|
||||
- Enabled HTTP plugin build; plugin is disabled by default and limited to localhost [#147]
|
||||
- Escape HTML in dialog boxes [#247]
|
||||
- Corrected crashes in favicon download and password generator [#233, #226]
|
||||
- Increase font size of password meter [#228]
|
||||
- Fixed compatibility with Qt 5.8 [#211]
|
||||
- Use consistent button heights in password generator [#229]
|
||||
|
||||
2.1.0 (2017-01-22)
|
||||
=========================
|
||||
|
||||
|
@ -38,8 +38,8 @@ option(WITH_XC_AUTOTYPE "Include Autotype." OFF)
|
||||
option(WITH_XC_HTTP "Include KeePassHTTP." OFF)
|
||||
option(WITH_XC_YUBIKEY "Include Yubikey support." OFF)
|
||||
|
||||
set(KEEPASSXC_VERSION "2.1.0")
|
||||
set(KEEPASSXC_VERSION_NUM "2.1.0")
|
||||
set(KEEPASSXC_VERSION "2.1.1")
|
||||
set(KEEPASSXC_VERSION_NUM "2.1.1")
|
||||
|
||||
if("${CMAKE_C_COMPILER}" MATCHES "clang$" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CMAKE_COMPILER_IS_CLANG 1)
|
||||
@ -172,6 +172,8 @@ set(CMAKE_AUTOMOC ON)
|
||||
# Make sure we don't enable asserts there.
|
||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_NONE QT_NO_DEBUG)
|
||||
|
||||
find_package(LibGPGError REQUIRED)
|
||||
|
||||
find_package(Gcrypt 1.6.0 REQUIRED)
|
||||
|
||||
if (WITH_XC_HTTP)
|
||||
|
32
Dockerfile
32
Dockerfile
@ -14,21 +14,41 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
FROM ubuntu:16.04
|
||||
FROM ubuntu:14.04
|
||||
|
||||
RUN set -x && apt-get update
|
||||
RUN set -x \
|
||||
&& apt-get update \
|
||||
&& apt-get install --yes software-properties-common
|
||||
|
||||
RUN set -x \
|
||||
&& add-apt-repository --yes ppa:beineri/opt-qt58-trusty
|
||||
|
||||
RUN set -x \
|
||||
&& apt-get update \
|
||||
&& apt-get install --yes \
|
||||
g++ \
|
||||
cmake \
|
||||
libgcrypt20-dev \
|
||||
qtbase5-dev \
|
||||
qttools5-dev-tools \
|
||||
qt58base \
|
||||
qt58tools \
|
||||
qt58x11extras \
|
||||
libmicrohttpd-dev \
|
||||
libqt5x11extras5-dev \
|
||||
libxi-dev \
|
||||
libxtst-dev \
|
||||
zlib1g-dev
|
||||
zlib1g-dev \
|
||||
wget \
|
||||
file \
|
||||
fuse \
|
||||
python
|
||||
|
||||
RUN set -x \
|
||||
&& apt-get install --yes mesa-common-dev
|
||||
|
||||
VOLUME /keepassxc/src
|
||||
VOLUME /keepassxc/out
|
||||
WORKDIR /keepassxc
|
||||
|
||||
ENV CMAKE_PREFIX_PATH=/opt/qt58/lib/cmake
|
||||
ENV LD_LIBRARY_PATH=/opt/qt58/lib
|
||||
RUN set -x \
|
||||
&& echo /opt/qt58/lib > /etc/ld.so.conf.d/qt58.conf
|
||||
|
9
cmake/FindLibGPGError.cmake
Normal file
9
cmake/FindLibGPGError.cmake
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
find_path(GPGERROR_INCLUDE_DIR gpg-error.h)
|
||||
|
||||
find_library(GPGERROR_LIBRARIES gpg-error)
|
||||
|
||||
mark_as_advanced(GPGERROR_LIBRARIES GPGERROR_INCLUDE_DIR)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LibGPGError DEFAULT_MSG GPGERROR_LIBRARIES GPGERROR_INCLUDE_DIR)
|
350
make_release.sh
350
make_release.sh
@ -1,350 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# KeePassXC Release Preparation Helper
|
||||
# Copyright (C) 2017 KeePassXC team <https://keepassxc.org/>
|
||||
#
|
||||
# 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
|
||||
# the Free Software Foundation, either version 2 or (at your option)
|
||||
# version 3 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
echo -e "\e[1m\e[32mKeePassXC\e[0m Release Preparation Helper"
|
||||
echo -e "Copyright (C) 2017 KeePassXC Team <https://keepassxc.org/>\n"
|
||||
|
||||
|
||||
# default values
|
||||
RELEASE_NAME=""
|
||||
APP_NAME="KeePassXC"
|
||||
APP_NAME_LOWER="keepassxc"
|
||||
SRC_DIR="."
|
||||
GPG_KEY="CFB4C2166397D0D2"
|
||||
GPG_GIT_KEY=""
|
||||
OUTPUT_DIR="release"
|
||||
BRANCH=""
|
||||
RELEASE_BRANCH="master"
|
||||
TAG_NAME=""
|
||||
BUILD_SOURCES=false
|
||||
DOCKER_IMAGE=""
|
||||
DOCKER_CONTAINER_NAME="${APP_NAME_LOWER}-build-container"
|
||||
CMAKE_OPTIONS=""
|
||||
COMPILER="g++"
|
||||
MAKE_OPTIONS="-j8"
|
||||
BUILD_PLUGINS="autotype"
|
||||
INSTALL_PREFIX="/usr/local"
|
||||
|
||||
ORIG_BRANCH="$(git rev-parse --abbrev-ref HEAD 2> /dev/null)"
|
||||
ORIG_CWD="$(pwd)"
|
||||
|
||||
|
||||
# helper functions
|
||||
printUsage() {
|
||||
echo -e "\e[1mUsage:\e[0m $(basename $0) [options]"
|
||||
cat << EOF
|
||||
|
||||
Options:
|
||||
-v, --version Release version number or name (required)
|
||||
-a, --app-name Application name (default: '${APP_NAME}')
|
||||
-s, --source-dir Source directory (default: '${SRC_DIR}')
|
||||
-k, --gpg-key GPG key used to sign the release tarball
|
||||
(default: '${GPG_KEY}')
|
||||
-g, --gpg-git-key GPG key used to sign the merge commit and release tag,
|
||||
leave empty to let Git choose your default key
|
||||
(default: '${GPG_GIT_KEY}')
|
||||
-o, --output-dir Output directory where to build the release
|
||||
(default: '${OUTPUT_DIR}')
|
||||
--develop-branch Development branch to merge from (default: 'release/VERSION')
|
||||
--release-branch Target release branch to merge to (default: '${RELEASE_BRANCH}')
|
||||
-t, --tag-name Override release tag name (defaults to version number)
|
||||
-b, --build Build sources after exporting release
|
||||
-d, --docker-image Use the specified Docker image to compile the application.
|
||||
The image must have all required build dependencies installed.
|
||||
This option has no effect if --build is not set.
|
||||
--container-name Docker container name (default: '${DOCKER_CONTAINER_NAME}')
|
||||
The container must not exist already
|
||||
-c, --cmake-options Additional CMake options for compiling the sources
|
||||
--compiler Compiler to use (default: '${COMPILER}')
|
||||
-m, --make-options Make options for compiling sources (default: '${MAKE_OPTIONS}')
|
||||
-i, --install-prefix Install prefix (default: '${INSTALL_PREFIX}')
|
||||
-p, --plugins Space-separated list of plugins to build
|
||||
(default: ${BUILD_PLUGINS})
|
||||
-h, --help Show this help
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
logInfo() {
|
||||
echo -e "\e[1m[ \e[34mINFO\e[39m ]\e[0m $1"
|
||||
}
|
||||
|
||||
logError() {
|
||||
echo -e "\e[1m[ \e[31mERROR\e[39m ]\e[0m $1" >&2
|
||||
}
|
||||
|
||||
exitError() {
|
||||
logError "$1"
|
||||
if [ "" != "$ORIG_BRANCH" ]; then
|
||||
git checkout "$ORIG_BRANCH" > /dev/null 2>&1
|
||||
fi
|
||||
cd "$ORIG_CWD"
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
# parse command line options
|
||||
while [ $# -ge 1 ]; do
|
||||
arg="$1"
|
||||
|
||||
case "$arg" in
|
||||
-a|--app-name)
|
||||
APP_NAME="$2"
|
||||
shift ;;
|
||||
|
||||
-s|--source-dir)
|
||||
SRC_DIR"$2"
|
||||
shift ;;
|
||||
|
||||
-v|--version)
|
||||
RELEASE_NAME="$2"
|
||||
shift ;;
|
||||
|
||||
-k|--gpg-key)
|
||||
GPG_KEY="$2"
|
||||
shift ;;
|
||||
|
||||
-g|--gpg-git-key)
|
||||
GPG_GIT_KEY="$2"
|
||||
shift ;;
|
||||
|
||||
-o|--output-dir)
|
||||
OUTPUT_DIR="$2"
|
||||
shift ;;
|
||||
|
||||
--develop-branch)
|
||||
BRANCH="$2"
|
||||
shift ;;
|
||||
|
||||
--release-branch)
|
||||
RELEASE_BRANCH="$2"
|
||||
shift ;;
|
||||
|
||||
-t|--tag-name)
|
||||
TAG_NAME="$2"
|
||||
shift ;;
|
||||
|
||||
-b|--build)
|
||||
BUILD_SOURCES=true ;;
|
||||
|
||||
-d|--docker-image)
|
||||
DOCKER_IMAGE="$2"
|
||||
shift ;;
|
||||
|
||||
--container-name)
|
||||
DOCKER_CONTAINER_NAME="$2"
|
||||
shift ;;
|
||||
|
||||
-c|--cmake-options)
|
||||
CMAKE_OPTIONS="$2"
|
||||
shift ;;
|
||||
|
||||
-m|--make-options)
|
||||
MAKE_OPTIONS="$2"
|
||||
shift ;;
|
||||
|
||||
--compiler)
|
||||
COMPILER="$2"
|
||||
shift ;;
|
||||
|
||||
-p|--plugins)
|
||||
BUILD_PLUGINS="$2"
|
||||
shift ;;
|
||||
|
||||
-h|--help)
|
||||
printUsage
|
||||
exit ;;
|
||||
|
||||
*)
|
||||
logError "Unknown option '$arg'\n"
|
||||
printUsage
|
||||
exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
|
||||
if [ "" == "$RELEASE_NAME" ]; then
|
||||
logError "Missing arguments, --version is required!\n"
|
||||
printUsage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "" == "$TAG_NAME" ]; then
|
||||
TAG_NAME="$RELEASE_NAME"
|
||||
fi
|
||||
if [ "" == "$BRANCH" ]; then
|
||||
BRANCH="release/${RELEASE_NAME}"
|
||||
fi
|
||||
APP_NAME_LOWER="$(echo "$APP_NAME" | tr '[:upper:]' '[:lower:]')"
|
||||
APP_NAME_UPPER="$(echo "$APP_NAME" | tr '[:lower:]' '[:upper:]')"
|
||||
|
||||
SRC_DIR="$(realpath "$SRC_DIR")"
|
||||
OUTPUT_DIR="$(realpath "$OUTPUT_DIR")"
|
||||
if [ ! -d "$SRC_DIR" ]; then
|
||||
exitError "Source directory '${SRC_DIR}' does not exist!"
|
||||
fi
|
||||
|
||||
logInfo "Changing to source directory..."
|
||||
cd "${SRC_DIR}"
|
||||
|
||||
logInfo "Performing basic checks..."
|
||||
|
||||
if [ -e "$OUTPUT_DIR" ]; then
|
||||
exitError "Output directory '$OUTPUT_DIR' already exists. Please choose a different location!"
|
||||
fi
|
||||
|
||||
if [ ! -d .git ] || [ ! -f CHANGELOG ]; then
|
||||
exitError "Source directory is not a valid Git repository!"
|
||||
fi
|
||||
|
||||
git tag | grep -q "$RELEASE_NAME"
|
||||
if [ $? -eq 0 ]; then
|
||||
exitError "Release '$RELEASE_NAME' already exists!"
|
||||
fi
|
||||
|
||||
git diff-index --quiet HEAD --
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "Current working tree is not clean! Please commit or unstage any changes."
|
||||
fi
|
||||
|
||||
git checkout "$BRANCH" > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "Source branch '$BRANCH' does not exist!"
|
||||
fi
|
||||
|
||||
grep -q "${APP_NAME_UPPER}_VERSION \"${RELEASE_NAME}\"" CMakeLists.txt
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "${APP_NAME_UPPER}_VERSION version not updated to '${RELEASE_NAME}' in CMakeLists.txt!"
|
||||
fi
|
||||
|
||||
grep -q "${APP_NAME_UPPER}_VERSION_NUM \"${RELEASE_NAME}\"" CMakeLists.txt
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "${APP_NAME_UPPER}_VERSION_NUM version not updated to '${RELEASE_NAME}' in CMakeLists.txt!"
|
||||
fi
|
||||
|
||||
if [ ! -f CHANGELOG ]; then
|
||||
exitError "No CHANGELOG file found!"
|
||||
fi
|
||||
|
||||
grep -qPzo "${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n=+\n" CHANGELOG
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "CHANGELOG does not contain any information about the '${RELEASE_NAME}' release!"
|
||||
fi
|
||||
|
||||
git checkout "$RELEASE_BRANCH" > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "Release branch '$RELEASE_BRANCH' does not exist!"
|
||||
fi
|
||||
|
||||
logInfo "All checks pass, getting our hands dirty now!"
|
||||
|
||||
logInfo "Merging '${BRANCH}' into '${RELEASE_BRANCH}'..."
|
||||
|
||||
CHANGELOG=$(grep -Pzo "(?<=${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n)=+\n\n(?:.|\n)+?\n(?=\n)" \
|
||||
CHANGELOG | grep -Pzo '(?<=\n\n)(.|\n)+' | tr -d \\0)
|
||||
COMMIT_MSG="Release ${RELEASE_NAME}"
|
||||
|
||||
git merge "$BRANCH" --no-ff -m "$COMMIT_MSG" -m "${CHANGELOG}" "$BRANCH" -S"$GPG_GIT_KEY"
|
||||
|
||||
logInfo "Creating tag '${RELEASE_NAME}'..."
|
||||
if [ "" == "$GPG_GIT_KEY" ]; then
|
||||
git tag -a "$RELEASE_NAME" -m "$COMMIT_MSG" -m "${CHANGELOG}" -s
|
||||
else
|
||||
git tag -a "$RELEASE_NAME" -m "$COMMIT_MSG" -m "${CHANGELOG}" -s -u "$GPG_GIT_KEY"
|
||||
fi
|
||||
|
||||
logInfo "Merge done, creating target directory..."
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "Failed to create output directory!"
|
||||
fi
|
||||
|
||||
logInfo "Creating source tarball..."
|
||||
TARBALL_NAME="${APP_NAME_LOWER}-${RELEASE_NAME}-src.tar.bz2"
|
||||
git archive --format=tar "$RELEASE_BRANCH" --prefix="${APP_NAME_LOWER}-${RELEASE_NAME}/" \
|
||||
| bzip2 -9 > "${OUTPUT_DIR}/${TARBALL_NAME}"
|
||||
|
||||
|
||||
if $BUILD_SOURCES; then
|
||||
logInfo "Creating build directory..."
|
||||
mkdir -p "${OUTPUT_DIR}/build-release"
|
||||
mkdir -p "${OUTPUT_DIR}/bin-release"
|
||||
cd "${OUTPUT_DIR}/build-release"
|
||||
|
||||
logInfo "Configuring sources..."
|
||||
for p in $BUILD_PLUGINS; do
|
||||
CMAKE_OPTIONS="${CMAKE_OPTIONS} -DWITH_XC_$(echo $p | tr '[:lower:]' '[:upper:]')=On"
|
||||
done
|
||||
|
||||
if [ "$COMPILER" == "g++" ]; then
|
||||
export CC=gcc
|
||||
elif [ "$COMPILER" == "clang++" ]; then
|
||||
export CC=clang
|
||||
fi
|
||||
export CXX="$COMPILER"
|
||||
|
||||
if [ "" == "$DOCKER_IMAGE" ]; then
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=Off $CMAKE_OPTIONS \
|
||||
-DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" "$SRC_DIR"
|
||||
|
||||
logInfo "Compiling sources..."
|
||||
make $MAKE_OPTIONS
|
||||
|
||||
logInfo "Installing to bin dir..."
|
||||
make DESTDIR="${OUTPUT_DIR}/bin-release" install/strip
|
||||
else
|
||||
logInfo "Launching Docker container to compile sources..."
|
||||
|
||||
docker run --name "$DOCKER_CONTAINER_NAME" --rm \
|
||||
-e "CC=${CC}" -e "CXX=${CXX}" \
|
||||
-v "$(realpath "$SRC_DIR"):/keepassxc/src:ro" \
|
||||
-v "$(realpath "$OUTPUT_DIR"):/keepassxc/out:rw" \
|
||||
"$DOCKER_IMAGE" \
|
||||
bash -c "cd /keepassxc/out/build-release && \
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=Off $CMAKE_OPTIONS \
|
||||
-DCMAKE_INSTALL_PREFIX=\"${INSTALL_PREFIX}\" /keepassxc/src && \
|
||||
make $MAKE_OPTIONS && make DESTDIR=/keepassxc/out/bin-release install/strip"
|
||||
|
||||
logInfo "Build finished, Docker container terminated."
|
||||
fi
|
||||
|
||||
logInfo "Creating AppImage..."
|
||||
${SRC_DIR}/AppImage-Recipe.sh "$APP_NAME" "$RELEASE_NAME"
|
||||
|
||||
cd ..
|
||||
logInfo "Signing source tarball..."
|
||||
gpg --output "${TARBALL_NAME}.sig" --armor --local-user "$GPG_KEY" --detach-sig "$TARBALL_NAME"
|
||||
|
||||
logInfo "Signing AppImage..."
|
||||
APPIMAGE_NAME="${APP_NAME}-${RELEASE_NAME}-x86_64.AppImage"
|
||||
gpg --output "${APPIMAGE_NAME}.sig" --armor --local-user "$GPG_KEY" --detach-sig "$APPIMAGE_NAME"
|
||||
|
||||
logInfo "Creating digests..."
|
||||
sha256sum "$TARBALL_NAME" > "${TARBALL_NAME}.DIGEST"
|
||||
sha256sum "$APPIMAGE_NAME" > "${APPIMAGE_NAME}.DIGEST"
|
||||
fi
|
||||
|
||||
logInfo "Leaving source directory..."
|
||||
cd "$ORIG_CWD"
|
||||
git checkout "$ORIG_BRANCH" > /dev/null 2>&1
|
||||
|
||||
logInfo "All done!"
|
||||
logInfo "Please merge the release branch back into the develop branch now and then push your changes."
|
||||
logInfo "Don't forget to also push the tags using \e[1mgit push --tags\e[0m."
|
682
release-tool
Executable file
682
release-tool
Executable file
@ -0,0 +1,682 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# KeePassXC Release Preparation Helper
|
||||
# Copyright (C) 2017 KeePassXC team <https://keepassxc.org/>
|
||||
#
|
||||
# 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
|
||||
# the Free Software Foundation, either version 2 or (at your option)
|
||||
# version 3 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
echo -e "\e[1m\e[32mKeePassXC\e[0m Release Preparation Helper"
|
||||
echo -e "Copyright (C) 2017 KeePassXC Team <https://keepassxc.org/>\n"
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# global default values
|
||||
# -----------------------------------------------------------------------
|
||||
RELEASE_NAME=""
|
||||
APP_NAME="KeePassXC"
|
||||
SRC_DIR="."
|
||||
GPG_KEY="CFB4C2166397D0D2"
|
||||
GPG_GIT_KEY=""
|
||||
OUTPUT_DIR="release"
|
||||
SOURCE_BRANCH=""
|
||||
TARGET_BRANCH="master"
|
||||
TAG_NAME=""
|
||||
DOCKER_IMAGE=""
|
||||
DOCKER_CONTAINER_NAME="keepassxc-build-container"
|
||||
CMAKE_OPTIONS=""
|
||||
COMPILER="g++"
|
||||
MAKE_OPTIONS="-j8"
|
||||
BUILD_PLUGINS="autotype"
|
||||
INSTALL_PREFIX="/usr/local"
|
||||
BUILD_SOURCE_TARBALL=true
|
||||
ORIG_BRANCH=""
|
||||
ORIG_CWD="$(pwd)"
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# helper functions
|
||||
# -----------------------------------------------------------------------
|
||||
printUsage() {
|
||||
local cmd
|
||||
if [ "" == "$1" ] || [ "help" == "$1" ]; then
|
||||
cmd="COMMAND"
|
||||
elif [ "merge" == "$1" ] || [ "build" == "$1" ] || [ "sign" == "$1" ]; then
|
||||
cmd="$1"
|
||||
else
|
||||
logError "Unknown command: '$1'\n"
|
||||
cmd="COMMAND"
|
||||
fi
|
||||
|
||||
echo -e "\e[1mUsage:\e[0m $(basename $0) $cmd [options]"
|
||||
|
||||
if [ "COMMAND" == "$cmd" ]; then
|
||||
cat << EOF
|
||||
|
||||
Commands:
|
||||
merge Merge release branch into main branch and create release tags
|
||||
build Build and package binary release from sources
|
||||
sign Sign previously compiled release packages
|
||||
help Show help for the given command
|
||||
EOF
|
||||
elif [ "merge" == "$cmd" ]; then
|
||||
cat << EOF
|
||||
|
||||
Merge release branch into main branch and create release tags
|
||||
|
||||
Options:
|
||||
-v, --version Release version number or name (required)
|
||||
-a, --app-name Application name (default: '${APP_NAME}')
|
||||
-s, --source-dir Source directory (default: '${SRC_DIR}')
|
||||
-g, --gpg-key GPG key used to sign the merge commit and release tag,
|
||||
leave empty to let Git choose your default key
|
||||
(default: '${GPG_GIT_KEY}')
|
||||
-r, --release-branch Source release branch to merge from (default: 'release/VERSION')
|
||||
--target-branch Target branch to merge to (default: '${TARGET_BRANCH}')
|
||||
-t, --tag-name Override release tag name (defaults to version number)
|
||||
-h, --help Show this help
|
||||
EOF
|
||||
elif [ "build" == "$cmd" ]; then
|
||||
cat << EOF
|
||||
|
||||
Build and package binary release from sources
|
||||
|
||||
Options:
|
||||
-v, --version Release version number or name (required)
|
||||
-a, --app-name Application name (default: '${APP_NAME}')
|
||||
-s, --source-dir Source directory (default: '${SRC_DIR}')
|
||||
-o, --output-dir Output directory where to build the release
|
||||
(default: '${OUTPUT_DIR}')
|
||||
-t, --tag-name Release tag to check out (defaults to version number)
|
||||
-b, --build Build sources after exporting release
|
||||
-d, --docker-image Use the specified Docker image to compile the application.
|
||||
The image must have all required build dependencies installed.
|
||||
This option has no effect if --build is not set.
|
||||
--container-name Docker container name (default: '${DOCKER_CONTAINER_NAME}')
|
||||
The container must not exist already
|
||||
-c, --cmake-options Additional CMake options for compiling the sources
|
||||
--compiler Compiler to use (default: '${COMPILER}')
|
||||
-m, --make-options Make options for compiling sources (default: '${MAKE_OPTIONS}')
|
||||
-i, --install-prefix Install prefix (default: '${INSTALL_PREFIX}')
|
||||
-p, --plugins Space-separated list of plugins to build
|
||||
(default: ${BUILD_PLUGINS})
|
||||
-n, --no-source-tarball Don't build source tarball
|
||||
-h, --help Show this help
|
||||
EOF
|
||||
elif [ "sign" == "$cmd" ]; then
|
||||
cat << EOF
|
||||
|
||||
Sign previously compiled release packages
|
||||
|
||||
Options:
|
||||
-f, --files Files to sign (required)
|
||||
-g, --gpg-key GPG key used to sign the files (default: '${GPG_KEY}')
|
||||
-h, --help Show this help
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
logInfo() {
|
||||
echo -e "\e[1m[ \e[34mINFO\e[39m ]\e[0m $1"
|
||||
}
|
||||
|
||||
logError() {
|
||||
echo -e "\e[1m[ \e[31mERROR\e[39m ]\e[0m $1" >&2
|
||||
}
|
||||
|
||||
init() {
|
||||
ORIG_CWD="$(pwd)"
|
||||
cd "$SRC_DIR" > /dev/null 2>&1
|
||||
ORIG_BRANCH="$(git rev-parse --abbrev-ref HEAD 2> /dev/null)"
|
||||
cd "$ORIG_CWD"
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
logInfo "Checking out original branch..."
|
||||
if [ "" != "$ORIG_BRANCH" ]; then
|
||||
git checkout "$ORIG_BRANCH" > /dev/null 2>&1
|
||||
fi
|
||||
logInfo "Leaving source directory..."
|
||||
cd "$ORIG_CWD"
|
||||
}
|
||||
|
||||
exitError() {
|
||||
logError "$1"
|
||||
cleanup
|
||||
exit 1
|
||||
}
|
||||
|
||||
exitTrap() {
|
||||
exitError "Existing upon user request..."
|
||||
}
|
||||
|
||||
checkSourceDirExists() {
|
||||
if [ ! -d "$SRC_DIR" ]; then
|
||||
exitError "Source directory '${SRC_DIR}' does not exist!"
|
||||
fi
|
||||
}
|
||||
|
||||
checkOutputDirDoesNotExist() {
|
||||
if [ -e "$OUTPUT_DIR" ]; then
|
||||
exitError "Output directory '$OUTPUT_DIR' already exists. Please choose a different location!"
|
||||
fi
|
||||
}
|
||||
|
||||
checkGitRepository() {
|
||||
if [ ! -d .git ] || [ ! -f CHANGELOG ]; then
|
||||
exitError "Source directory is not a valid Git repository!"
|
||||
fi
|
||||
}
|
||||
|
||||
checkTagExists() {
|
||||
git tag | grep -q "$TAG_NAME"
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "Tag '${TAG_NAME}' does not exist!"
|
||||
fi
|
||||
}
|
||||
|
||||
checkReleaseDoesNotExist() {
|
||||
git tag | grep -q "$TAG_NAME"
|
||||
if [ $? -eq 0 ]; then
|
||||
exitError "Release '$RELEASE_NAME' (tag: '$TAG_NAME') already exists!"
|
||||
fi
|
||||
}
|
||||
|
||||
checkWorkingTreeClean() {
|
||||
git diff-index --quiet HEAD --
|
||||
if [ $? -ne 0 ]; 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
|
||||
exitError "Source branch '$SOURCE_BRANCH' does not exist!"
|
||||
fi
|
||||
}
|
||||
|
||||
checkTargetBranchExists() {
|
||||
git rev-parse "$TARGET_BRANCH" > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "Target branch '$TARGET_BRANCH' does not exist!"
|
||||
fi
|
||||
}
|
||||
|
||||
checkVersionInCMake() {
|
||||
local app_name_upper="$(echo "$APP_NAME" | tr '[:lower:]' '[:upper:]')"
|
||||
|
||||
grep -q "${app_name_upper}_VERSION \"${RELEASE_NAME}\"" CMakeLists.txt
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "${app_name_upper}_VERSION version not updated to '${RELEASE_NAME}' in CMakeLists.txt!"
|
||||
fi
|
||||
|
||||
grep -q "${app_name_upper}_VERSION_NUM \"${RELEASE_NAME}\"" CMakeLists.txt
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "${app_name_upper}_VERSION_NUM version not updated to '${RELEASE_NAME}' in CMakeLists.txt!"
|
||||
fi
|
||||
}
|
||||
|
||||
checkChangeLog() {
|
||||
if [ ! -f CHANGELOG ]; then
|
||||
exitError "No CHANGELOG file found!"
|
||||
fi
|
||||
|
||||
grep -qPzo "${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n=+\n" CHANGELOG
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "CHANGELOG does not contain any information about the '${RELEASE_NAME}' release!"
|
||||
fi
|
||||
}
|
||||
|
||||
checkTransifexCommandExists() {
|
||||
command -v tx > /dev/null
|
||||
if [ 0 -ne $? ]; then
|
||||
exitError "Transifex tool 'tx' not installed! Please install it using 'pip install transifex-client'"
|
||||
fi
|
||||
}
|
||||
|
||||
# re-implement realpath for OS X (thanks mschrag)
|
||||
# https://superuser.com/questions/205127/
|
||||
if $(command -v realpath > /dev/null); then
|
||||
realpath() {
|
||||
pushd . > /dev/null
|
||||
if [ -d "$1" ]; then
|
||||
cd "$1"
|
||||
dirs -l +0
|
||||
else
|
||||
cd "$(dirname "$1")"
|
||||
cur_dir=$(dirs -l +0)
|
||||
|
||||
if [ "$cur_dir" == "/" ]; then
|
||||
echo "$cur_dir$(basename "$1")"
|
||||
else
|
||||
echo "$cur_dir/$(basename "$1")"
|
||||
fi
|
||||
fi
|
||||
popd > /dev/null
|
||||
}
|
||||
fi
|
||||
|
||||
|
||||
trap exitTrap SIGINT SIGTERM
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# merge command
|
||||
# -----------------------------------------------------------------------
|
||||
merge() {
|
||||
while [ $# -ge 1 ]; do
|
||||
local arg="$1"
|
||||
case "$arg" in
|
||||
-v|--version)
|
||||
RELEASE_NAME="$2"
|
||||
shift ;;
|
||||
|
||||
-a|--app-name)
|
||||
APP_NAME="$2"
|
||||
shift ;;
|
||||
|
||||
-s|--source-dir)
|
||||
SRC_DIR="$2"
|
||||
shift ;;
|
||||
|
||||
-g|--gpg-key)
|
||||
GPG_GIT_KEY="$2"
|
||||
shift ;;
|
||||
|
||||
-r|--release-branch)
|
||||
SOURCE_BRANCH="$2"
|
||||
shift ;;
|
||||
|
||||
--target-branch)
|
||||
TARGET_BRANCH="$2"
|
||||
shift ;;
|
||||
|
||||
-t|--tag-name)
|
||||
TAG_NAME="$2"
|
||||
shift ;;
|
||||
|
||||
-h|--help)
|
||||
printUsage "merge"
|
||||
exit ;;
|
||||
|
||||
*)
|
||||
logError "Unknown option '$arg'\n"
|
||||
printUsage "merge"
|
||||
exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ "" == "$RELEASE_NAME" ]; then
|
||||
logError "Missing arguments, --version is required!\n"
|
||||
printUsage "merge"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "" == "$TAG_NAME" ]; then
|
||||
TAG_NAME="$RELEASE_NAME"
|
||||
fi
|
||||
|
||||
if [ "" == "$SOURCE_BRANCH" ]; then
|
||||
SOURCE_BRANCH="release/${RELEASE_NAME}"
|
||||
fi
|
||||
|
||||
init
|
||||
|
||||
SRC_DIR="$(realpath "$SRC_DIR")"
|
||||
|
||||
logInfo "Performing basic checks..."
|
||||
|
||||
checkSourceDirExists
|
||||
|
||||
logInfo "Changing to source directory..."
|
||||
cd "${SRC_DIR}"
|
||||
|
||||
checkTransifexCommandExists
|
||||
checkGitRepository
|
||||
checkReleaseDoesNotExist
|
||||
checkWorkingTreeClean
|
||||
checkSourceBranchExists
|
||||
checkTargetBranchExists
|
||||
checkVersionInCMake
|
||||
checkChangeLog
|
||||
|
||||
logInfo "All checks pass, getting our hands dirty now!"
|
||||
|
||||
logInfo "Checking out source branch..."
|
||||
git checkout "$SOURCE_BRANCH"
|
||||
|
||||
logInfo "Updating language files..."
|
||||
./share/translations/update.sh
|
||||
if [ 0 -ne $? ]; then
|
||||
exitError "Updating translations failed!"
|
||||
fi
|
||||
git diff-index --quiet HEAD --
|
||||
if [ $? -ne 0 ]; then
|
||||
git add ./share/translations/*
|
||||
logInfo "Committing changes..."
|
||||
if [ "" == "$GPG_GIT_KEY" ]; then
|
||||
git commit -m "Update translations"
|
||||
else
|
||||
git commit -m "Update translations" -S"$GPG_GIT_KEY"
|
||||
fi
|
||||
fi
|
||||
|
||||
logInfo "Checking out target branch '${TARGET_BRANCH}'..."
|
||||
git checkout "$TARGET_BRANCH"
|
||||
|
||||
logInfo "Merging '${SOURCE_BRANCH}' into '${TARGET_BRANCH}'..."
|
||||
|
||||
CHANGELOG=$(grep -Pzo "(?<=${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n)=+\n\n?(?:.|\n)+?\n(?=\n)" \
|
||||
CHANGELOG | grep -Pzo '(?<=\n\n)(.|\n)+' | tr -d \\0)
|
||||
COMMIT_MSG="Release ${RELEASE_NAME}"
|
||||
|
||||
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
|
||||
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"
|
||||
fi
|
||||
|
||||
cleanup
|
||||
|
||||
logInfo "All done!"
|
||||
logInfo "Please merge the release branch back into the develop branch now and then push your changes."
|
||||
logInfo "Don't forget to also push the tags using \e[1mgit push --tags\e[0m."
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# build command
|
||||
# -----------------------------------------------------------------------
|
||||
build() {
|
||||
while [ $# -ge 1 ]; do
|
||||
local arg="$1"
|
||||
case "$arg" in
|
||||
-v|--version)
|
||||
RELEASE_NAME="$2"
|
||||
shift ;;
|
||||
|
||||
-a|--app-name)
|
||||
APP_NAME="$2"
|
||||
shift ;;
|
||||
|
||||
-s|--source-dir)
|
||||
SRC_DIR="$2"
|
||||
shift ;;
|
||||
|
||||
-o|--output-dir)
|
||||
OUTPUT_DIR="$2"
|
||||
shift ;;
|
||||
|
||||
-t|--tag-name)
|
||||
TAG_NAME="$2"
|
||||
shift ;;
|
||||
|
||||
-d|--docker-image)
|
||||
DOCKER_IMAGE="$2"
|
||||
shift ;;
|
||||
|
||||
--container-name)
|
||||
DOCKER_CONTAINER_NAME="$2"
|
||||
shift ;;
|
||||
|
||||
-c|--cmake-options)
|
||||
CMAKE_OPTIONS="$2"
|
||||
shift ;;
|
||||
|
||||
--compiler)
|
||||
COMPILER="$2"
|
||||
shift ;;
|
||||
|
||||
-m|--make-options)
|
||||
MAKE_OPTIONS="$2"
|
||||
shift ;;
|
||||
|
||||
-i|--install-prefix)
|
||||
INSTALL_PREFIX="$2"
|
||||
shift ;;
|
||||
|
||||
-p|--plugins)
|
||||
BUILD_PLUGINS="$2"
|
||||
shift ;;
|
||||
|
||||
-n|--no-source-tarball)
|
||||
BUILD_SOURCE_TARBALL=false ;;
|
||||
|
||||
-h|--help)
|
||||
printUsage "build"
|
||||
exit ;;
|
||||
|
||||
*)
|
||||
logError "Unknown option '$arg'\n"
|
||||
printUsage "build"
|
||||
exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ "" == "$RELEASE_NAME" ]; then
|
||||
logError "Missing arguments, --version is required!\n"
|
||||
printUsage "build"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "" == "$TAG_NAME" ]; then
|
||||
TAG_NAME="$RELEASE_NAME"
|
||||
fi
|
||||
|
||||
init
|
||||
|
||||
SRC_DIR="$(realpath "$SRC_DIR")"
|
||||
OUTPUT_DIR="$(realpath "$OUTPUT_DIR")"
|
||||
|
||||
logInfo "Performing basic checks..."
|
||||
|
||||
checkSourceDirExists
|
||||
|
||||
logInfo "Changing to source directory..."
|
||||
cd "${SRC_DIR}"
|
||||
|
||||
checkTagExists
|
||||
checkGitRepository
|
||||
checkWorkingTreeClean
|
||||
checkOutputDirDoesNotExist
|
||||
|
||||
logInfo "All checks pass, getting our hands dirty now!"
|
||||
|
||||
logInfo "Checking out release tag '${TAG_NAME}'..."
|
||||
git checkout "$TAG_NAME"
|
||||
|
||||
logInfo "Creating output directory..."
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
exitError "Failed to create output directory!"
|
||||
fi
|
||||
|
||||
if $BUILD_SOURCE_TARBALL; then
|
||||
logInfo "Creating source tarball..."
|
||||
local app_name_lower="$(echo "$APP_NAME" | tr '[:upper:]' '[:lower:]')"
|
||||
TARBALL_NAME="${app_name_lower}-${RELEASE_NAME}-src.tar.xz"
|
||||
git archive --format=tar "$TAG_NAME" --prefix="${app_name_lower}-${RELEASE_NAME}/" \
|
||||
| xz -6 > "${OUTPUT_DIR}/${TARBALL_NAME}"
|
||||
fi
|
||||
|
||||
logInfo "Creating build directory..."
|
||||
mkdir -p "${OUTPUT_DIR}/build-release"
|
||||
cd "${OUTPUT_DIR}/build-release"
|
||||
|
||||
logInfo "Configuring sources..."
|
||||
for p in $BUILD_PLUGINS; do
|
||||
CMAKE_OPTIONS="${CMAKE_OPTIONS} -DWITH_XC_$(echo $p | tr '[:lower:]' '[:upper:]')=On"
|
||||
done
|
||||
|
||||
if [ "$COMPILER" == "g++" ]; then
|
||||
export CC=gcc
|
||||
elif [ "$COMPILER" == "clang++" ]; then
|
||||
export CC=clang
|
||||
fi
|
||||
export CXX="$COMPILER"
|
||||
|
||||
if [ "" == "$DOCKER_IMAGE" ]; then
|
||||
if [ "$(uname -s)" == "Darwin" ]; then
|
||||
# Building on OS X
|
||||
local qt_vers="$(ls /usr/local/Cellar/qt5 2> /dev/null | sort -r | head -n1)"
|
||||
if [ "" == "$qt_vers" ]; then
|
||||
exitError "Couldn't find Qt5! Please make sure it is available in '/usr/local/Cellar/qt5'."
|
||||
fi
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.7
|
||||
|
||||
logInfo "Configuring build..."
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" \
|
||||
-DCMAKE_OSX_ARCHITECTURES=x86_64 -DWITH_CXX11=OFF \
|
||||
-DCMAKE_PREFIX_PATH="/usr/local/Cellar/qt5/${qt_vers}/lib/cmake" \
|
||||
-DQT_BINARY_DIR="/usr/local/Cellar/qt5/${qt_vers}/bin" $CMAKE_OPTIONS "$SRC_DIR"
|
||||
|
||||
logInfo "Compiling and packaging sources..."
|
||||
make $MAKE_OPTIONS package
|
||||
|
||||
mv "./${APP_NAME}-${RELEASE_NAME}.dmg" ../
|
||||
elif [ "$(uname -o)" == "Msys" ]; then
|
||||
# Building on Windows with Msys
|
||||
logInfo "Configuring build..."
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=Off -G"MSYS Makefiles" \
|
||||
-DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" $CMAKE_OPTIONS "$SRC_DIR"
|
||||
|
||||
logInfo "Compiling and packaging sources..."
|
||||
make $MAKE_OPTIONS package
|
||||
|
||||
mv "./${APP_NAME}-${RELEASE_NAME}-"*.{exe,zip} ../
|
||||
else
|
||||
mkdir -p "${OUTPUT_DIR}/bin-release"
|
||||
|
||||
# Building on Linux without Docker container
|
||||
logInfo "Configuring build..."
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=Off $CMAKE_OPTIONS \
|
||||
-DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" "$SRC_DIR"
|
||||
|
||||
logInfo "Compiling sources..."
|
||||
make $MAKE_OPTIONS
|
||||
|
||||
logInfo "Installing to bin dir..."
|
||||
make DESTDIR="${OUTPUT_DIR}/bin-release" install/strip
|
||||
|
||||
logInfo "Creating AppImage..."
|
||||
${SRC_DIR}/AppImage-Recipe.sh "$APP_NAME" "$RELEASE_NAME"
|
||||
fi
|
||||
else
|
||||
mkdir -p "${OUTPUT_DIR}/bin-release"
|
||||
|
||||
logInfo "Launching Docker container to compile sources..."
|
||||
|
||||
docker run --name "$DOCKER_CONTAINER_NAME" --rm \
|
||||
--cap-add SYS_ADMIN --device /dev/fuse \
|
||||
-e "CC=${CC}" -e "CXX=${CXX}" \
|
||||
-v "$(realpath "$SRC_DIR"):/keepassxc/src:ro" \
|
||||
-v "$(realpath "$OUTPUT_DIR"):/keepassxc/out:rw" \
|
||||
"$DOCKER_IMAGE" \
|
||||
bash -c "cd /keepassxc/out/build-release && \
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=Off $CMAKE_OPTIONS \
|
||||
-DCMAKE_INSTALL_PREFIX=\"${INSTALL_PREFIX}\" /keepassxc/src && \
|
||||
make $MAKE_OPTIONS && make DESTDIR=/keepassxc/out/bin-release install/strip && \
|
||||
/keepassxc/src/AppImage-Recipe.sh "$APP_NAME" "$RELEASE_NAME""
|
||||
|
||||
if [ 0 -ne $? ]; then
|
||||
exitError "Docker build failed!"
|
||||
fi
|
||||
|
||||
logInfo "Build finished, Docker container terminated."
|
||||
fi
|
||||
|
||||
cleanup
|
||||
|
||||
logInfo "All done!"
|
||||
}
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# sign command
|
||||
# -----------------------------------------------------------------------
|
||||
sign() {
|
||||
SIGN_FILES=()
|
||||
|
||||
while [ $# -ge 1 ]; do
|
||||
local arg="$1"
|
||||
case "$arg" in
|
||||
-f|--files)
|
||||
while [ "${2:0:1}" != "-" ] && [ $# -ge 2 ]; do
|
||||
SIGN_FILES+=("$2")
|
||||
shift
|
||||
done ;;
|
||||
|
||||
-g|--gpg-key)
|
||||
GPG_KEY="$2"
|
||||
shift ;;
|
||||
|
||||
-h|--help)
|
||||
printUsage "sign"
|
||||
exit ;;
|
||||
|
||||
*)
|
||||
logError "Unknown option '$arg'\n"
|
||||
printUsage "sign"
|
||||
exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ -z "$SIGN_FILES" ]; then
|
||||
logError "Missing arguments, --files is required!\n"
|
||||
printUsage "sign"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for f in "${SIGN_FILES[@]}"; do
|
||||
if [ ! -f "$f" ]; then
|
||||
exitError "File '${f}' does not exist!"
|
||||
fi
|
||||
|
||||
logInfo "Signing file '${f}'..."
|
||||
gpg --output "${f}.sig" --armor --local-user "$GPG_KEY" --detach-sig "$f"
|
||||
|
||||
if [ 0 -ne $? ]; then
|
||||
exitError "Signing failed!"
|
||||
fi
|
||||
|
||||
logInfo "Creating digest for file '${f}'..."
|
||||
sha256sum "$f" > "${f}.DIGEST"
|
||||
done
|
||||
|
||||
logInfo "All done!"
|
||||
}
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# parse global command line
|
||||
# -----------------------------------------------------------------------
|
||||
MODE="$1"
|
||||
shift
|
||||
if [ "" == "$MODE" ]; then
|
||||
logError "Missing arguments!\n"
|
||||
printUsage
|
||||
exit 1
|
||||
elif [ "help" == "$MODE" ]; then
|
||||
printUsage "$1"
|
||||
exit
|
||||
elif [ "merge" == "$MODE" ] || [ "build" == "$MODE" ] || [ "sign" == "$MODE" ]; then
|
||||
$MODE "$@"
|
||||
else
|
||||
printUsage "$MODE"
|
||||
fi
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,11 @@
|
||||
<source>KeePassXC is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Extensions:
|
||||
</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AccessControlDialog</name>
|
||||
@ -475,6 +480,46 @@ Do you want to save it anyway?</source>
|
||||
<source>No Results</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Execute command?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Do you really want to execute the following command?<br><br>%1<br></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remember my choice</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Autoreload Request</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The database file has changed. Do you want to load the changes?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Merge Request</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The database file has changed and you have unsaved changes.Do you want to merge your changes?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Autoreload Failed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not parse or unlock the new database file while attempting to autoreload this database.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not open the new database file while attempting to autoreload this database.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditEntryWidget</name>
|
||||
@ -669,10 +714,6 @@ Do you want to save it anyway?</source>
|
||||
<source>Repeat:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Gen.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>URL:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -830,6 +871,13 @@ Do you want to save it anyway?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Entry</name>
|
||||
<message>
|
||||
<source> - Clone</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EntryAttributesModel</name>
|
||||
<message>
|
||||
@ -1226,6 +1274,10 @@ This is a one-way migration. You won't be able to open the imported databas
|
||||
<source>Re&pair database</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Password Generator</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OptionDialog</name>
|
||||
@ -1299,14 +1351,6 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned<
|
||||
<source>Automatic creates or updates are not supported for string fields!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HTTP Host:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default host: localhost</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HTTP Port:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -1315,11 +1359,6 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned<
|
||||
<source>Default port: 19455</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable KeepassXC Http protocol
|
||||
This is required for accessing your databases from ChromeIPass or PassIFox</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Re&quest to unlock the database if it is locked</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -1328,6 +1367,24 @@ This is required for accessing your databases from ChromeIPass or PassIFox</sour
|
||||
<source>Sort &matching entries by title</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable KeepassXC HTTP protocol
|
||||
This is required for accessing your databases from ChromeIPass or PassIFox</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>KeePassXC will listen to this port on 127.0.0.1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind to privileged ports</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind to privileged ports below 1024!
|
||||
Using default port 19455.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PasswordGeneratorWidget</name>
|
||||
@ -1335,10 +1392,6 @@ This is required for accessing your databases from ChromeIPass or PassIFox</sour
|
||||
<source>Password:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Length:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Character Types</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -1364,11 +1417,63 @@ This is required for accessing your databases from ChromeIPass or PassIFox</sour
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ensure that the password contains characters from every group</source>
|
||||
<source>Accept</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Accept</source>
|
||||
<source>%p%</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>strength</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>entropy</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Length:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pick characters from every group</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Generate</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Close</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Apply</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Entropy: %1 bit</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Password Quality: %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Poor</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Weak</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Good</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Excellent</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
@ -1415,16 +1520,20 @@ This is required for accessing your databases from ChromeIPass or PassIFox</sour
|
||||
</context>
|
||||
<context>
|
||||
<name>SearchWidget</name>
|
||||
<message>
|
||||
<source>Find:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Case Sensitive</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Search Current Group</source>
|
||||
<source>Search</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Find</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clear</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
@ -1536,10 +1645,6 @@ give it a unique name to identify and accept it.</source>
|
||||
<source>Remember last databases</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open previous databases on startup</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Automatically save on exit</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -1581,11 +1686,19 @@ give it a unique name to identify and accept it.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hide window to system tray instead of App Exit</source>
|
||||
<source>Load previous databases on startup</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hide window to system tray on App start</source>
|
||||
<source>Automatically reload the database when modified externally</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hide window to system tray instead of app exit</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Minimize window at application startup</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
@ -1615,6 +1728,10 @@ give it a unique name to identify and accept it.</source>
|
||||
<source>Lock databases after minimizing the window</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Don't require password repeat when it is visible</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>UnlockDatabaseWidget</name>
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
BIN
share/windows/installer-header.bmp
Normal file
BIN
share/windows/installer-header.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
share/windows/installer-wizard.bmp
Normal file
BIN
share/windows/installer-wizard.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 151 KiB |
@ -218,6 +218,7 @@ target_link_libraries(${PROGNAME}
|
||||
Qt5::Widgets
|
||||
Qt5::Network
|
||||
${GCRYPT_LIBRARIES}
|
||||
${GPGERROR_LIBRARIES}
|
||||
${ZLIB_LIBRARIES})
|
||||
|
||||
set_target_properties(${PROGNAME} PROPERTIES ENABLE_EXPORTS ON)
|
||||
@ -257,9 +258,25 @@ if(APPLE)
|
||||
endif()
|
||||
|
||||
if(MINGW)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
string(REPLACE "AMD" "Win" OUTPUT_FILE_POSTFIX "${CMAKE_HOST_SYSTEM_PROCESSOR}")
|
||||
set(CPACK_GENERATOR "ZIP;NSIS")
|
||||
set(CPACK_STRIP_FILES ON)
|
||||
set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSXC_VERSION_NUM}")
|
||||
set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSXC_VERSION}-${OUTPUT_FILE_POSTFIX}")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${PROGNAME})
|
||||
set(CPACK_PACKAGE_VERSION ${KEEPASSXC_VERSION})
|
||||
set(CPACK_PACKAGE_VENDOR "${PROGNAME} Team")
|
||||
string(REGEX REPLACE "/" "\\\\\\\\" CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/share/windows/installer-header.bmp")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.GPL-2")
|
||||
set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/share/windows/keepassxc.ico")
|
||||
set(CPACK_NSIS_MUI_UNIICON "${CPACK_NSIS_MUI_ICON}")
|
||||
set(CPACK_NSIS_INSTALLED_ICON_NAME "\\\\${PROGNAME}.exe")
|
||||
string(REGEX REPLACE "/" "\\\\\\\\" CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP "${CMAKE_SOURCE_DIR}/share/windows/installer-wizard.bmp")
|
||||
set(CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP "${CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP}")
|
||||
set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${PROGNAME}.lnk' '$INSTDIR\\\\${PROGNAME}.exe'")
|
||||
set(CPACK_NSIS_DELETE_ICONS_EXTRA "Delete '$SMPROGRAMS\\\\$START_MENU\\\\${PROGNAME}.lnk'")
|
||||
set(CPACK_NSIS_URL_INFO_ABOUT "https://keepassxc.org")
|
||||
set(CPACK_NSIS_PACKAGE_NAME "${PROGNAME} v${KEEPASSXC_VERSION}")
|
||||
set(CPACK_NSIS_MUI_FINISHPAGE_RUN "../${PROGNAME}.exe")
|
||||
include(CPack)
|
||||
|
||||
install(CODE "
|
||||
@ -267,5 +284,9 @@ if(MINGW)
|
||||
" COMPONENT Runtime)
|
||||
|
||||
include(DeployQt4)
|
||||
install_qt4_executable(${PROGNAME}.exe "qjpeg;qgif;qico;qtaccessiblewidgets")
|
||||
install_qt4_executable(${PROGNAME}.exe)
|
||||
add_custom_command(TARGET ${PROGNAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${Qt5Core_DIR}/../../../share/qt5/plugins/platforms/qwindows$<$<CONFIG:Debug>:d>.dll
|
||||
$<TARGET_FILE_DIR:${PROGNAME}>)
|
||||
install(FILES $<TARGET_FILE_DIR:${PROGNAME}>/qwindows$<$<CONFIG:Debug>:d>.dll DESTINATION "platforms")
|
||||
endif()
|
||||
|
@ -246,7 +246,7 @@ bool DatabaseTabWidget::closeDatabase(Database* db)
|
||||
QMessageBox::StandardButton result =
|
||||
MessageBox::question(
|
||||
this, tr("Close?"),
|
||||
tr("\"%1\" is in edit mode.\nDiscard changes and close anyway?").arg(dbName),
|
||||
tr("\"%1\" is in edit mode.\nDiscard changes and close anyway?").arg(dbName.toHtmlEscaped()),
|
||||
QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel);
|
||||
if (result == QMessageBox::Cancel) {
|
||||
return false;
|
||||
@ -262,7 +262,7 @@ bool DatabaseTabWidget::closeDatabase(Database* db)
|
||||
QMessageBox::StandardButton result =
|
||||
MessageBox::question(
|
||||
this, tr("Save changes?"),
|
||||
tr("\"%1\" was modified.\nSave changes?").arg(dbName),
|
||||
tr("\"%1\" was modified.\nSave changes?").arg(dbName.toHtmlEscaped()),
|
||||
QMessageBox::Yes | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Yes);
|
||||
if (result == QMessageBox::Yes) {
|
||||
if (!saveDatabase(db)) {
|
||||
|
@ -344,7 +344,7 @@ void DatabaseWidget::deleteEntries()
|
||||
result = MessageBox::question(
|
||||
this, tr("Delete entry?"),
|
||||
tr("Do you really want to delete the entry \"%1\" for good?")
|
||||
.arg(selectedEntries.first()->title()),
|
||||
.arg(selectedEntries.first()->title().toHtmlEscaped()),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
}
|
||||
else {
|
||||
@ -368,7 +368,7 @@ void DatabaseWidget::deleteEntries()
|
||||
result = MessageBox::question(
|
||||
this, tr("Move entry to recycle bin?"),
|
||||
tr("Do you really want to move entry \"%1\" to the recycle bin?")
|
||||
.arg(selectedEntries.first()->title()),
|
||||
.arg(selectedEntries.first()->title().toHtmlEscaped()),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
}
|
||||
else {
|
||||
@ -573,7 +573,7 @@ void DatabaseWidget::deleteGroup()
|
||||
QMessageBox::StandardButton result = MessageBox::question(
|
||||
this, tr("Delete group?"),
|
||||
tr("Do you really want to delete the group \"%1\" for good?")
|
||||
.arg(currentGroup->name()),
|
||||
.arg(currentGroup->name().toHtmlEscaped()),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (result == QMessageBox::Yes) {
|
||||
delete currentGroup;
|
||||
|
@ -190,6 +190,10 @@ void EditWidgetIcons::abortFaviconDownload(bool clearRedirect)
|
||||
|
||||
void EditWidgetIcons::onRequestFinished(QNetworkReply *reply)
|
||||
{
|
||||
if (m_database == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!reply->error()) {
|
||||
QImage image;
|
||||
image.loadFromData(reply->readAll());
|
||||
|
@ -45,11 +45,15 @@ PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent)
|
||||
|
||||
connect(m_ui->optionButtons, SIGNAL(buttonClicked(int)), SLOT(updateGenerator()));
|
||||
|
||||
// set font size of password quality and entropy labels dynamically to 80% of the default font size
|
||||
// set font size of password quality and entropy labels dynamically to 80% of
|
||||
// the default font size, but make it no smaller than 8pt
|
||||
QFont defaultFont;
|
||||
defaultFont.setPointSize(static_cast<int>(defaultFont.pointSize() * 0.8f));
|
||||
m_ui->entropyLabel->setFont(defaultFont);
|
||||
m_ui->strengthLabel->setFont(defaultFont);
|
||||
int smallerSize = static_cast<int>(defaultFont.pointSize() * 0.8f);
|
||||
if (smallerSize >= 8) {
|
||||
defaultFont.setPointSize(smallerSize);
|
||||
m_ui->entropyLabel->setFont(defaultFont);
|
||||
m_ui->strengthLabel->setFont(defaultFont);
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
reset();
|
||||
@ -132,8 +136,10 @@ void PasswordGeneratorWidget::updatePasswordStrength(const QString& password)
|
||||
|
||||
void PasswordGeneratorWidget::generatePassword()
|
||||
{
|
||||
QString password = m_generator->generatePassword();
|
||||
m_ui->editNewPassword->setText(password);
|
||||
if (m_generator->isValid()) {
|
||||
QString password = m_generator->generatePassword();
|
||||
m_ui->editNewPassword->setText(password);
|
||||
}
|
||||
}
|
||||
|
||||
void PasswordGeneratorWidget::applyPassword()
|
||||
@ -279,5 +285,11 @@ void PasswordGeneratorWidget::updateGenerator()
|
||||
m_generator->setCharClasses(classes);
|
||||
m_generator->setFlags(flags);
|
||||
|
||||
if (m_generator->isValid()) {
|
||||
m_ui->buttonGenerate->setEnabled(true);
|
||||
} else {
|
||||
m_ui->buttonGenerate->setEnabled(false);
|
||||
}
|
||||
|
||||
regeneratePassword();
|
||||
}
|
||||
|
@ -104,11 +104,6 @@ QProgressBar::chunk {
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>strength</string>
|
||||
</property>
|
||||
@ -144,11 +139,6 @@ QProgressBar::chunk {
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>entropy</string>
|
||||
</property>
|
||||
@ -295,6 +285,12 @@ QProgressBar::chunk {
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="checkBoxNumbers">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
@ -314,6 +310,12 @@ QProgressBar::chunk {
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="checkBoxSpecialChars">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
|
@ -272,14 +272,15 @@ void EditEntryWidget::loadEntry(Entry* entry, bool create, bool history, const Q
|
||||
m_history = history;
|
||||
|
||||
if (history) {
|
||||
setHeadline(QString("%1 > %2").arg(parentName, tr("Entry history")));
|
||||
setHeadline(QString("%1 > %2").arg(parentName.toHtmlEscaped(), tr("Entry history")));
|
||||
}
|
||||
else {
|
||||
if (create) {
|
||||
setHeadline(QString("%1 > %2").arg(parentName, tr("Add entry")));
|
||||
setHeadline(QString("%1 > %2").arg(parentName.toHtmlEscaped(), tr("Add entry")));
|
||||
}
|
||||
else {
|
||||
setHeadline(QString("%1 > %2 > %3").arg(parentName, entry->title(), tr("Edit entry")));
|
||||
setHeadline(QString("%1 > %2 > %3").arg(parentName.toHtmlEscaped(),
|
||||
entry->title().toHtmlEscaped(), tr("Edit entry")));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -480,7 +480,8 @@ void Service::updateEntry(const QString &, const QString &uuid, const QString &l
|
||||
//ShowNotification(QString("%0: You have an entry change prompt waiting, click to activate").arg(requestId));
|
||||
if ( HttpSettings::alwaysAllowUpdate()
|
||||
|| QMessageBox::warning(0, tr("KeePassXC: Update Entry"),
|
||||
tr("Do you want to update the information in %1 - %2?").arg(QUrl(url).host()).arg(u),
|
||||
tr("Do you want to update the information in %1 - %2?")
|
||||
.arg(QUrl(url).host().toHtmlEscaped()).arg(u.toHtmlEscaped()),
|
||||
QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes ) {
|
||||
entry->beginUpdate();
|
||||
entry->setUsername(login);
|
||||
|
10
src/main.cpp
10
src/main.cpp
@ -28,6 +28,16 @@
|
||||
#include "gui/MainWindow.h"
|
||||
#include "gui/MessageBox.h"
|
||||
|
||||
#ifdef QT_STATIC
|
||||
#include <QtPlugin>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
|
||||
#elif Q_OS_LINUX
|
||||
Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
#ifdef QT_NO_DEBUG
|
||||
|
@ -92,6 +92,7 @@ set(TEST_LIBRARIES
|
||||
Qt5::Widgets
|
||||
Qt5::Test
|
||||
${GCRYPT_LIBRARIES}
|
||||
${GPGERROR_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
)
|
||||
|
||||
|
@ -20,6 +20,7 @@ target_link_libraries(kdbx-extract
|
||||
keepassx_core
|
||||
Qt5::Core
|
||||
${GCRYPT_LIBRARIES}
|
||||
${GPGERROR_LIBRARIES}
|
||||
${ZLIB_LIBRARIES})
|
||||
|
||||
add_executable(kdbx-merge kdbx-merge.cpp)
|
||||
@ -27,6 +28,7 @@ target_link_libraries(kdbx-merge
|
||||
keepassx_core
|
||||
Qt5::Core
|
||||
${GCRYPT_LIBRARIES}
|
||||
${GPGERROR_LIBRARIES}
|
||||
${ZLIB_LIBRARIES})
|
||||
|
||||
|
||||
|
@ -101,9 +101,10 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (line[0])
|
||||
if (line[0]) {
|
||||
calculate(line,advanced);
|
||||
printf("> ");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user