1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

feat(build): add the delta updater

This commit is contained in:
antony-jr 2019-07-13 20:04:35 +05:30
parent 56af9c0be2
commit 5eea8ba27f
No known key found for this signature in database
GPG Key ID: 13089CB6F3D41A27
9 changed files with 205 additions and 13 deletions

View File

@ -26,6 +26,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
option(PLATFORM_EXTENSIONS "Enable platform specific extensions, requires extra dependencies" ON) option(PLATFORM_EXTENSIONS "Enable platform specific extensions, requires extra dependencies" ON)
option(USE_FILTERAUDIO "Enable the echo canceling backend" ON) option(USE_FILTERAUDIO "Enable the echo canceling backend" ON)
option(UPDATE_CHECK "Enable automatic update check" ON) option(UPDATE_CHECK "Enable automatic update check" ON)
option(APPIMAGE_UPDATER_BRIDGE "Use AppImageUpdaterBridge to do the update" OFF)
option(USE_CCACHE "Use ccache when available" ON) option(USE_CCACHE "Use ccache when available" ON)
option(SPELL_CHECK "Enable spell cheching support" ON) option(SPELL_CHECK "Enable spell cheching support" ON)
option(SVGZ_ICON "Compress the SVG icon of qTox" ON) option(SVGZ_ICON "Compress the SVG icon of qTox" ON)
@ -690,6 +691,13 @@ endif()
if(${UPDATE_CHECK}) if(${UPDATE_CHECK})
add_definitions(-DUPDATE_CHECK_ENABLED=1) add_definitions(-DUPDATE_CHECK_ENABLED=1)
if(APPIMAGE_UPDATER_BRIDGE_SRC_DIR AND APPIMAGE_UPDATER_BRIDGE_BUILD_DIR)
message(STATUS "using AppImageUpdaterBridge")
add_definitions(-DAPPIMAGE_UPDATER_BRIDGE_ENABLED=1)
include_directories(${APPIMAGE_UPDATER_BRIDGE_SRC_DIR})
else()
message(STATUS "NOT using AppImageUpdaterBridge")
endif()
set(${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_SOURCES} set(${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_SOURCES}
src/net/updatecheck.cpp src/net/updatecheck.cpp
src/net/updatecheck.h) src/net/updatecheck.h)
@ -729,10 +737,18 @@ add_library(${PROJECT_NAME}_static
${${PROJECT_NAME}_SOURCES} ${${PROJECT_NAME}_SOURCES}
${${PROJECT_NAME}_QM_FILES} ${${PROJECT_NAME}_QM_FILES}
${${PROJECT_NAME}_RESOURCES}) ${${PROJECT_NAME}_RESOURCES})
target_link_libraries(${PROJECT_NAME}_static
${CMAKE_REQUIRED_LIBRARIES}
${ALL_LIBRARIES})
if(APPIMAGE_UPDATER_BRIDGE_BUILD_DIR AND APPIMAGE_UPDATER_BRIDGE_SRC_DIR AND UPDATE_CHECK)
target_link_libraries(${PROJECT_NAME}_static
${CMAKE_REQUIRED_LIBRARIES}
${ALL_LIBRARIES}
${APPIMAGE_UPDATER_BRIDGE_BUILD_DIR}/libAppImageUpdaterBridge.a)
else()
target_link_libraries(${PROJECT_NAME}_static
${CMAKE_REQUIRED_LIBRARIES}
${ALL_LIBRARIES})
endif()
add_executable(${PROJECT_NAME} add_executable(${PROJECT_NAME}
WIN32 WIN32
MACOSX_BUNDLE MACOSX_BUNDLE

View File

@ -2,7 +2,7 @@
# MIT License # MIT License
# #
# Copyright © 2019 by The qTox Project Contributors # Copyright © 2018 by The qTox Project Contributors
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal # of this software and associated documentation files (the "Software"), to deal
@ -29,6 +29,10 @@
readonly DEBUG="$1" readonly DEBUG="$1"
# Set this to True to upload the PR version of the
# AppImage to transfer.sh for testing.
readonly UPLOAD_PR_APPIMAGE="True"
# Fail out on error # Fail out on error
set -exo pipefail set -exo pipefail
@ -57,16 +61,41 @@ then
/bin/bash /bin/bash
else else
docker run --rm \ docker run --rm \
-e CIRP_GITHUB_REPO_SLUG \
-e TRAVIS_EVENT_TYPE \
-e TRAVIS_COMMIT \
-e TRAVIS_TAG \
-v $PWD:/qtox \ -v $PWD:/qtox \
-v $PWD/output:/output \ -v $PWD/output:/output \
debian:stretch-slim \ debian:stretch-slim \
/bin/bash -c "/qtox/appimage/build.sh" /bin/bash -c "/qtox/appimage/build.sh"
fi fi
# use the version number in the name when building a tag on Travis CI # use the version number in the name when building a tag on Travis CI
if [ -n "$TRAVIS_TAG" ] if [ -n "$TRAVIS_TAG" ]
then then
# the aitool should have written the appimage in the same name
# as below so no need to move things , it should have also written
# the .zsync meta file as the given name below with .zsync
# extension.
readonly OUTFILE=./output/qTox-"$TRAVIS_TAG".x86_64.AppImage readonly OUTFILE=./output/qTox-"$TRAVIS_TAG".x86_64.AppImage
mv ./output/*.AppImage "$OUTFILE"
# just check if the files are in the right place
eval "ls $OUTFILE"
eval "ls $OUTFILE.zsync"
sha256sum "$OUTFILE" > "$OUTFILE".sha256 sha256sum "$OUTFILE" > "$OUTFILE".sha256
else
if [ "$UPLOAD_PR_APPIMAGE" == "True" ]
then
# upload PR builds to test them.
echo "Uploading AppImage to transfer.sh"
curl --upload-file "./output/qTox-$TRAVIS_COMMIT-x86_64.AppImage" \
"https://transfer.sh/qTox-$TRAVIS_COMMIT-x86_64.AppImage" > ./upload
echo "$(cat ./upload)"
echo -n "$(cat ./upload)\\n" >> ./uploaded-to
rm -rf ./upload ./uploaded-to
sha256sum "./output/qTox-$TRAVIS_COMMIT-x86_64.AppImage"
fi
fi fi

View File

@ -2,7 +2,7 @@
# MIT License # MIT License
# #
# Copyright © 2019 by The qTox Project Contributors # Copyright © 2018 by The qTox Project Contributors
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal # of this software and associated documentation files (the "Software"), to deal
@ -22,6 +22,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. # THE SOFTWARE.
# Fail out on error # Fail out on error
set -exuo pipefail set -exuo pipefail
@ -39,11 +40,31 @@ readonly AITOOL_BUILD_DIR="$BUILD_DIR"/aitool
readonly SQLCIPHER_BUILD_DIR="$BUILD_DIR"/sqlcipher readonly SQLCIPHER_BUILD_DIR="$BUILD_DIR"/sqlcipher
# ldqt binary # ldqt binary
readonly LDQT_BIN="/usr/lib/x86_64-linux-gnu/qt5/bin/linuxdeployqt" readonly LDQT_BIN="/usr/lib/x86_64-linux-gnu/qt5/bin/linuxdeployqt"
# aitool binary
readonly AITOOL_BIN="/usr/local/bin/appimagetool"
readonly APPRUN_BIN="/usr/local/bin/AppRun"
readonly APT_FLAGS="-y --no-install-recommends" readonly APT_FLAGS="-y --no-install-recommends"
# snorenotify source # snorenotify source
readonly SNORE_GIT="https://github.com/KDE/snorenotify" readonly SNORE_GIT="https://github.com/KDE/snorenotify"
# snorenotify build directory # snorenotify build directory
readonly SNORE_BUILD_DIR="$BUILD_DIR"/snorenotify readonly SNORE_BUILD_DIR="$BUILD_DIR"/snorenotify
# "appimage updater bridge" becomes aub
readonly AUB_SRC_DIR="$BUILD_DIR"/aub
# aub source
readonly AUB_GIT="https://github.com/antony-jr/AppImageUpdaterBridge"
# aub build dir
readonly AUB_BUILD_DIR="$BUILD_DIR"/aub/build
# update information to be embeded in AppImage
if [ "cron" == "${TRAVIS_EVENT_TYPE:-}" ]
then
# update information for nightly version
readonly NIGHTLY_REPO_SLUG=$(echo "$CIRP_GITHUB_REPO_SLUG" | tr "/" "|")
readonly UPDATE_INFO="gh-releases-zsync|$NIGHTLY_REPO_SLUG|ci-master-latest|qTox-*-x86_64.AppImage.zsync"
else
# update information for stable version
readonly UPDATE_INFO="gh-releases-zsync|qTox|qTox|latest|qTox-*.x86_64.AppImage.zsync"
fi
# use multiple cores when building # use multiple cores when building
export MAKEFLAGS="-j$(nproc)" export MAKEFLAGS="-j$(nproc)"
@ -89,6 +110,17 @@ LDFLAGS="-lcrypto"
make make
make install make install
# build aub into a static library and later use it in
# qTox
git clone "$AUB_GIT" "$AUB_SRC_DIR"
cd "$AUB_SRC_DIR" # we need to checkout first
git checkout tags/v1.1.1
mkdir $AUB_BUILD_DIR
cd $AUB_BUILD_DIR
cmake .. -DLOGGING_DISABLED=ON
make
# copy qtox source # copy qtox source
cp -r "$QTOX_SRC_DIR" "$QTOX_BUILD_DIR" cp -r "$QTOX_SRC_DIR" "$QTOX_BUILD_DIR"
cd "$QTOX_BUILD_DIR" cd "$QTOX_BUILD_DIR"
@ -103,7 +135,10 @@ mkdir -p ./_build
cd _build cd _build
# need to build with -DDESKTOP_NOTIFICATIONS=True for snorenotify # need to build with -DDESKTOP_NOTIFICATIONS=True for snorenotify
cmake -DDESKTOP_NOTIFICATIONS=True ../ cmake -DDESKTOP_NOTIFICATIONS=True \
-DUPDATE_CHECK=True \
-DAPPIMAGE_UPDATER_BRIDGE_SRC_DIR="$AUB_SRC_DIR" \
-DAPPIMAGE_UPDATER_BRIDGE_BUILD_DIR="$AUB_BUILD_DIR" ../
make make
@ -139,7 +174,7 @@ cd build
export PKG_CONFIG_PATH=/deps/lib/pkgconfig/ export PKG_CONFIG_PATH=/deps/lib/pkgconfig/
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=ON \ cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=ON \
-DAPPIMAGEKIT_PACKAGE_DEBS=ON -DUPDATE_CHECK=ON -DAPPIMAGEKIT_PACKAGE_DEBS=ON
make make
make install make install
@ -152,7 +187,18 @@ readonly QTOX_DESKTOP_FILE="$QTOX_APP_DIR"/usr/local/share/applications/*.deskto
eval "$LDQT_BIN $QTOX_DESKTOP_FILE -bundle-non-qt-libs -extra-plugins=libsnore-qt5" eval "$LDQT_BIN $QTOX_DESKTOP_FILE -bundle-non-qt-libs -extra-plugins=libsnore-qt5"
eval "$LDQT_BIN $QTOX_DESKTOP_FILE -appimage" # Move the required files to the correct directory
mv "$QTOX_APP_DIR"/usr/* "$QTOX_APP_DIR/"
rm -rf "$QTOX_APP_DIR/usr"
# this is important , aitool automatically uses the same filename in .zsync meta file.
# if this name does not match with the one we upload , the update always fails.
if [ -n "$TRAVIS_TAG" ]
then
eval "$AITOOL_BIN -u \"$UPDATE_INFO\" $QTOX_APP_DIR qTox-$TRAVIS_TAG.x86_64.AppImage"
else
eval "$AITOOL_BIN -u \"$UPDATE_INFO\" $QTOX_APP_DIR qTox-$TRAVIS_COMMIT-x86_64.AppImage"
fi
# Chmod since everything is root:root # Chmod since everything is root:root
chmod 755 -R "$OUTPUT_DIR" chmod 755 -R "$OUTPUT_DIR"

View File

@ -19,7 +19,14 @@
#include "src/net/updatecheck.h" #include "src/net/updatecheck.h"
#include "src/persistence/settings.h" #include "src/persistence/settings.h"
#ifndef APPIMAGE_UPDATER_BRIDGE_ENABLED
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#else
#include <QApplication>
#include <QScreen>
#include <AppImageUpdaterBridge>
#include <AppImageUpdaterDialog>
#endif
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <QRegularExpression> #include <QRegularExpression>
@ -29,16 +36,34 @@
#include <QDebug> #include <QDebug>
#include <cassert> #include <cassert>
#ifndef APPIMAGE_UPDATER_BRIDGE_ENABLED
namespace { namespace {
const QString versionUrl{QStringLiteral("https://api.github.com/repos/qTox/qTox/releases/latest")}; const QString versionUrl{QStringLiteral("https://api.github.com/repos/qTox/qTox/releases/latest")};
} // namespace } // namespace
#else
using AppImageUpdaterBridge::AppImageDeltaRevisioner;
using AppImageUpdaterBridge::AppImageUpdaterDialog;
#endif
UpdateCheck::UpdateCheck(const Settings& settings) UpdateCheck::UpdateCheck(const Settings& settings)
: settings(settings) : settings(settings)
{ {
updateTimer.start(1000 * 60 * 60 * 24 /* 1 day */); updateTimer.start(1000 * 60 * 60 * 24 /* 1 day */);
connect(&updateTimer, &QTimer::timeout, this, &UpdateCheck::checkForUpdate); connect(&updateTimer, &QTimer::timeout, this, &UpdateCheck::checkForUpdate);
#ifndef APPIMAGE_UPDATER_BRIDGE_ENABLED
connect(&manager, &QNetworkAccessManager::finished, this, &UpdateCheck::handleResponse); connect(&manager, &QNetworkAccessManager::finished, this, &UpdateCheck::handleResponse);
#else
connect(&revisioner, &AppImageDeltaRevisioner::updateAvailable, this, &UpdateCheck::handleUpdate);
connect(&revisioner, &AppImageDeltaRevisioner::error, this, &UpdateCheck::updateCheckFailed,
Qt::DirectConnection);
updateDialog.reset(new AppImageUpdaterDialog(QPixmap(":/img/icons/qtox.svg")));
connect(updateDialog.data(), &AppImageUpdaterDialog::quit, QApplication::instance(),
&QApplication::quit, Qt::QueuedConnection);
connect(updateDialog.data(), &AppImageUpdaterDialog::canceled, this, &UpdateCheck::handleUpdateEnd);
connect(updateDialog.data(), &AppImageUpdaterDialog::finished, this, &UpdateCheck::handleUpdateEnd);
connect(updateDialog.data(), &AppImageUpdaterDialog::error, this, &UpdateCheck::handleUpdateEnd);
#endif
} }
void UpdateCheck::checkForUpdate() void UpdateCheck::checkForUpdate()
@ -47,11 +72,30 @@ void UpdateCheck::checkForUpdate()
// still run the timer to check periodically incase setting changes // still run the timer to check periodically incase setting changes
return; return;
} }
#ifndef APPIMAGE_UPDATER_BRIDGE_ENABLED
manager.setProxy(settings.getProxy()); manager.setProxy(settings.getProxy());
QNetworkRequest request{versionUrl}; QNetworkRequest request{versionUrl};
manager.get(request); manager.get(request);
#else
revisioner.clear();
revisioner.setProxy(settings.getProxy());
revisioner.checkForUpdate();
#endif
} }
#ifdef APPIMAGE_UPDATER_BRIDGE_ENABLED
void UpdateCheck::initUpdate()
{
disconnect(&revisioner, &AppImageDeltaRevisioner::updateAvailable, this,
&UpdateCheck::handleUpdate);
disconnect(&revisioner, &AppImageDeltaRevisioner::error, this, &UpdateCheck::updateCheckFailed);
updateDialog->move(QGuiApplication::primaryScreen()->geometry().center()
- updateDialog->rect().center());
updateDialog->init(&revisioner);
}
#endif
#ifndef APPIMAGE_UPDATER_BRIDGE_ENABLED
void UpdateCheck::handleResponse(QNetworkReply *reply) void UpdateCheck::handleResponse(QNetworkReply *reply)
{ {
assert(reply != nullptr); assert(reply != nullptr);
@ -92,3 +136,23 @@ void UpdateCheck::handleResponse(QNetworkReply *reply)
} }
reply->deleteLater(); reply->deleteLater();
} }
#else
void UpdateCheck::handleUpdate(bool aval)
{
if (aval) {
qInfo() << "Update available";
emit updateAvailable();
return;
}
qInfo() << "qTox is up to date";
emit upToDate();
}
void UpdateCheck::handleUpdateEnd()
{
connect(&revisioner, &AppImageDeltaRevisioner::error, this, &UpdateCheck::updateCheckFailed,
(Qt::ConnectionType)(Qt::DirectConnection | Qt::UniqueConnection));
connect(&revisioner, &AppImageDeltaRevisioner::updateAvailable, this,
&UpdateCheck::handleUpdate, Qt::UniqueConnection);
}
#endif // APPIMAGE_UPDATER_BRIDGE_ENABLED

View File

@ -20,6 +20,12 @@
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QTimer> #include <QTimer>
#ifdef APPIMAGE_UPDATER_BRIDGE_ENABLED
#include <QScopedPointer>
#include <AppImageUpdaterBridge>
#include <AppImageUpdaterDialog>
#endif // APPIMAGE_UPDATER_BRIDGE_ENABLED
#include <memory> #include <memory>
class Settings; class Settings;
@ -35,15 +41,29 @@ public:
void checkForUpdate(); void checkForUpdate();
signals: signals:
#ifndef APPIMAGE_UPDATER_BRIDGE_ENABLED
void updateAvailable(QString latestVersion, QUrl link); void updateAvailable(QString latestVersion, QUrl link);
#else
void updateAvailable();
#endif
void upToDate(); void upToDate();
void updateCheckFailed(); void updateCheckFailed();
#ifndef APPIMAGE_UPDATER_BRIDGE_ENABLED
private slots: private slots:
void handleResponse(QNetworkReply *reply); void handleResponse(QNetworkReply* reply);
public slots:
void initUpdate();
#else
private: private:
#ifndef APPIMAGE_UPDATER_BRIDGE_ENABLED
QNetworkAccessManager manager; QNetworkAccessManager manager;
#else
AppImageUpdaterBridge::AppImageDeltaRevisioner revisioner;
QScopedPointer<AppImageUpdaterBridge::AppImageUpdaterDialog> updateDialog;
#endif // APPIMAGE_UPDATER_BRIDGE_ENABLED
QTimer updateTimer; QTimer updateTimer;
const Settings& settings; const Settings& settings;
}; };

View File

@ -96,6 +96,10 @@ void AboutForm::replaceVersions()
connect(updateCheck, &UpdateCheck::updateAvailable, this, &AboutForm::onUpdateAvailable); connect(updateCheck, &UpdateCheck::updateAvailable, this, &AboutForm::onUpdateAvailable);
connect(updateCheck, &UpdateCheck::upToDate, this, &AboutForm::onUpToDate); connect(updateCheck, &UpdateCheck::upToDate, this, &AboutForm::onUpToDate);
connect(updateCheck, &UpdateCheck::updateCheckFailed, this, &AboutForm::onUpdateCheckFailed); connect(updateCheck, &UpdateCheck::updateCheckFailed, this, &AboutForm::onUpdateCheckFailed);
#ifdef APPIMAGE_UPDATER_BRIDGE_ENABLED
connect(bodyUI->updateAvailableButton, &QPushButton::clicked, updateCheck,
&UpdateCheck::initUpdate);
#endif
} else { } else {
qWarning() << "AboutForm passed null UpdateCheck!"; qWarning() << "AboutForm passed null UpdateCheck!";
} }
@ -165,6 +169,7 @@ void AboutForm::replaceVersions()
bodyUI->authorInfo->setText(authorInfo); bodyUI->authorInfo->setText(authorInfo);
} }
#ifndef APPIMAGE_UPDATER_BRIDGE_ENABLED
void AboutForm::onUpdateAvailable(QString latestVersion, QUrl link) void AboutForm::onUpdateAvailable(QString latestVersion, QUrl link)
{ {
QObject::disconnect(linkConnection); QObject::disconnect(linkConnection);
@ -173,6 +178,12 @@ void AboutForm::onUpdateAvailable(QString latestVersion, QUrl link)
}); });
bodyUI->updateStack->setCurrentIndex(static_cast<int>(updateIndex::available)); bodyUI->updateStack->setCurrentIndex(static_cast<int>(updateIndex::available));
} }
#else
void AboutForm::onUpdateAvailable()
{
bodyUI->updateStack->setCurrentIndex(static_cast<int>(updateIndex::available));
}
#endif
void AboutForm::onUpToDate() void AboutForm::onUpToDate()
{ {

View File

@ -45,7 +45,11 @@ public:
} }
public slots: public slots:
#ifndef APPIMAGE_UPDATER_BRIDGE_ENABLED
void onUpdateAvailable(QString latestVersion, QUrl link); void onUpdateAvailable(QString latestVersion, QUrl link);
#else
void onUpdateAvailable();
#endif
void onUpToDate(); void onUpToDate();
void onUpdateCheckFailed(); void onUpdateCheckFailed();
@ -58,7 +62,9 @@ private:
Ui::AboutSettings* bodyUI; Ui::AboutSettings* bodyUI;
QTimer* progressTimer; QTimer* progressTimer;
UpdateCheck* updateCheck; UpdateCheck* updateCheck;
#ifndef APPIMAGE_UPDATER_BRIDGE_ENABLED
QMetaObject::Connection linkConnection; QMetaObject::Connection linkConnection;
#endif
}; };
#endif // ABOUTFORM_H #endif // ABOUTFORM_H

View File

@ -1791,7 +1791,7 @@ void Widget::toggleFullscreen()
} }
} }
void Widget::onUpdateAvailable(QString /*latestVersion*/, QUrl /*link*/) void Widget::onUpdateAvailable()
{ {
ui->settingsButton->setProperty("update-available", true); ui->settingsButton->setProperty("update-available", true);
ui->settingsButton->style()->unpolish(ui->settingsButton); ui->settingsButton->style()->unpolish(ui->settingsButton);

View File

@ -192,7 +192,7 @@ public slots:
void onGroupDialogShown(Group* g); void onGroupDialogShown(Group* g);
void toggleFullscreen(); void toggleFullscreen();
void refreshPeerListsLocal(const QString& username); void refreshPeerListsLocal(const QString& username);
void onUpdateAvailable(QString latestVersion, QUrl link); void onUpdateAvailable();
void onCoreChanged(Core& core); void onCoreChanged(Core& core);
signals: signals: