зеркало из https://github.com/nextcloud/desktop.git
Merge pull request #3472 from owncloud/linux_restart_on_new_version
On Linux restart if new version is found on disk
This commit is contained in:
Коммит
6a20ea5e73
|
@ -88,6 +88,7 @@ Application::Application(int &argc, char **argv) :
|
||||||
_gui(0),
|
_gui(0),
|
||||||
_theme(Theme::instance()),
|
_theme(Theme::instance()),
|
||||||
_helpOnly(false),
|
_helpOnly(false),
|
||||||
|
_versionOnly(false),
|
||||||
_showLogWindow(false),
|
_showLogWindow(false),
|
||||||
_logExpire(0),
|
_logExpire(0),
|
||||||
_logFlush(false),
|
_logFlush(false),
|
||||||
|
@ -104,7 +105,7 @@ Application::Application(int &argc, char **argv) :
|
||||||
#endif
|
#endif
|
||||||
parseOptions(arguments());
|
parseOptions(arguments());
|
||||||
//no need to waste time;
|
//no need to waste time;
|
||||||
if ( _helpOnly ) return;
|
if ( _helpOnly || _versionOnly ) return;
|
||||||
|
|
||||||
if (isRunning())
|
if (isRunning())
|
||||||
return;
|
return;
|
||||||
|
@ -174,6 +175,11 @@ Application::Application(int &argc, char **argv) :
|
||||||
// Cleanup at Quit.
|
// Cleanup at Quit.
|
||||||
connect (this, SIGNAL(aboutToQuit()), SLOT(slotCleanup()));
|
connect (this, SIGNAL(aboutToQuit()), SLOT(slotCleanup()));
|
||||||
|
|
||||||
|
// remember the version of the currently running binary. On Linux it might happen that the
|
||||||
|
// package management updates the package while the app is running. This is detected in the
|
||||||
|
// updater slot: If the installed binary on the hd has a different version than the one
|
||||||
|
// running, the running app is restart. That happens in folderman.
|
||||||
|
_runningAppVersion = Utility::versionOfInstalledBinary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application()
|
Application::~Application()
|
||||||
|
@ -211,6 +217,16 @@ void Application::slotCleanup()
|
||||||
_gui->deleteLater();
|
_gui->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( Utility::isLinux() ) {
|
||||||
|
// on linux, check if the installed binary is still the same version
|
||||||
|
// as the one that is running. If not, restart if possible.
|
||||||
|
const QByteArray fsVersion = Utility::versionOfInstalledBinary();
|
||||||
|
|
||||||
|
if( !(fsVersion.isEmpty() || _runningAppVersion.isEmpty()) && fsVersion != _runningAppVersion ) {
|
||||||
|
_folderManager->slotScheduleAppRestart();
|
||||||
|
}
|
||||||
|
}
|
||||||
void Application::slotCheckConnection()
|
void Application::slotCheckConnection()
|
||||||
{
|
{
|
||||||
auto list = AccountManager::instance()->accounts();
|
auto list = AccountManager::instance()->accounts();
|
||||||
|
@ -339,6 +355,8 @@ void Application::parseOptions(const QStringList &options)
|
||||||
}
|
}
|
||||||
} else if (option == QLatin1String("--debug")) {
|
} else if (option == QLatin1String("--debug")) {
|
||||||
_debugMode = true;
|
_debugMode = true;
|
||||||
|
} else if (option == QLatin1String("--version")) {
|
||||||
|
_versionOnly = true;
|
||||||
} else {
|
} else {
|
||||||
showHint("Unrecognized option '" + option.toStdString() + "'");
|
showHint("Unrecognized option '" + option.toStdString() + "'");
|
||||||
}
|
}
|
||||||
|
@ -389,6 +407,17 @@ void Application::showHelp()
|
||||||
displayHelpText(helpText);
|
displayHelpText(helpText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::showVersion()
|
||||||
|
{
|
||||||
|
QString helpText;
|
||||||
|
QTextStream stream(&helpText);
|
||||||
|
stream << _theme->appName().toLatin1().constData()
|
||||||
|
<< QLatin1String(" version ")
|
||||||
|
<< _theme->version().toLatin1().constData() << endl;
|
||||||
|
|
||||||
|
displayHelpText(helpText);
|
||||||
|
}
|
||||||
|
|
||||||
void Application::showHint(std::string errorHint)
|
void Application::showHint(std::string errorHint)
|
||||||
{
|
{
|
||||||
static QString binName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
|
static QString binName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
|
||||||
|
@ -485,6 +514,11 @@ bool Application::giveHelp()
|
||||||
return _helpOnly;
|
return _helpOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Application::versionOnly()
|
||||||
|
{
|
||||||
|
return _versionOnly;
|
||||||
|
}
|
||||||
|
|
||||||
void Application::showSettingsDialog()
|
void Application::showSettingsDialog()
|
||||||
{
|
{
|
||||||
_gui->slotShowSettings();
|
_gui->slotShowSettings();
|
||||||
|
|
|
@ -58,6 +58,8 @@ public:
|
||||||
void showHelp();
|
void showHelp();
|
||||||
void showHint(std::string errorHint);
|
void showHint(std::string errorHint);
|
||||||
bool debugMode();
|
bool debugMode();
|
||||||
|
bool versionOnly(); // only display the version?
|
||||||
|
void showVersion();
|
||||||
|
|
||||||
void showSettingsDialog();
|
void showSettingsDialog();
|
||||||
|
|
||||||
|
@ -93,6 +95,7 @@ private:
|
||||||
Theme *_theme;
|
Theme *_theme;
|
||||||
|
|
||||||
bool _helpOnly;
|
bool _helpOnly;
|
||||||
|
bool _versionOnly;
|
||||||
|
|
||||||
// options from command line:
|
// options from command line:
|
||||||
bool _showLogWindow;
|
bool _showLogWindow;
|
||||||
|
@ -102,6 +105,7 @@ private:
|
||||||
bool _logFlush;
|
bool _logFlush;
|
||||||
bool _userTriggeredConnect;
|
bool _userTriggeredConnect;
|
||||||
bool _debugMode;
|
bool _debugMode;
|
||||||
|
QByteArray _runningAppVersion;
|
||||||
|
|
||||||
ClientProxy _proxy;
|
ClientProxy _proxy;
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,8 @@ static qint64 msBetweenRequestAndSync = 2000;
|
||||||
FolderMan::FolderMan(QObject *parent) :
|
FolderMan::FolderMan(QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
_currentSyncFolder(0),
|
_currentSyncFolder(0),
|
||||||
_syncEnabled( true )
|
_syncEnabled( true ),
|
||||||
|
_appRestartRequired(false)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!_instance);
|
Q_ASSERT(!_instance);
|
||||||
_instance = this;
|
_instance = this;
|
||||||
|
@ -473,6 +474,12 @@ void FolderMan::slotScheduleAllFolders()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FolderMan::slotScheduleAppRestart()
|
||||||
|
{
|
||||||
|
_appRestartRequired = true;
|
||||||
|
qDebug() << "## Application restart requested!";
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if a folder wants to be synced, it calls this slot and is added
|
* if a folder wants to be synced, it calls this slot and is added
|
||||||
* to the queue. The slot to actually start a sync is called afterwards.
|
* to the queue. The slot to actually start a sync is called afterwards.
|
||||||
|
@ -540,6 +547,11 @@ void FolderMan::slotRunOneEtagJob()
|
||||||
}
|
}
|
||||||
if (_currentEtagJob.isNull()) {
|
if (_currentEtagJob.isNull()) {
|
||||||
qDebug() << "No more remote ETag check jobs to schedule.";
|
qDebug() << "No more remote ETag check jobs to schedule.";
|
||||||
|
|
||||||
|
/* now it might be a good time to check for restarting... */
|
||||||
|
if( _currentSyncFolder == NULL && _appRestartRequired ) {
|
||||||
|
restartApplication();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Scheduling" << alias << "to check remote ETag";
|
qDebug() << "Scheduling" << alias << "to check remote ETag";
|
||||||
_currentEtagJob->start(); // on destroy/end it will continue the queue via slotEtagJobDestroyed
|
_currentEtagJob->start(); // on destroy/end it will continue the queue via slotEtagJobDestroyed
|
||||||
|
@ -1164,5 +1176,19 @@ QString FolderMan::checkPathValidityForNewFolder(const QString& path, bool forNe
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FolderMan::restartApplication()
|
||||||
|
{
|
||||||
|
if( Utility::isLinux() ) {
|
||||||
|
// restart:
|
||||||
|
qDebug() << "### Restarting application NOW, PID" << qApp->applicationPid() << "is ending.";
|
||||||
|
qApp->quit();
|
||||||
|
QStringList args = qApp->arguments();
|
||||||
|
QString prg = args.takeFirst();
|
||||||
|
|
||||||
|
QProcess::startDetached(prg, args);
|
||||||
|
} else {
|
||||||
|
qDebug() << "On this platform we do not restart.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace OCC
|
} // namespace OCC
|
||||||
|
|
|
@ -148,6 +148,11 @@ public slots:
|
||||||
*/
|
*/
|
||||||
void slotAccountStateChanged();
|
void slotAccountStateChanged();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* restart the client as soon as it is possible, ie. no folders syncing.
|
||||||
|
*/
|
||||||
|
void slotScheduleAppRestart();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
// slot to take the next folder from queue and start syncing.
|
// slot to take the next folder from queue and start syncing.
|
||||||
void slotStartScheduledFolderSync();
|
void slotStartScheduledFolderSync();
|
||||||
|
@ -176,6 +181,9 @@ private:
|
||||||
QString getBackupName( QString fullPathName ) const;
|
QString getBackupName( QString fullPathName ) const;
|
||||||
void registerFolderMonitor( Folder *folder );
|
void registerFolderMonitor( Folder *folder );
|
||||||
|
|
||||||
|
// restarts the application (Linux only)
|
||||||
|
void restartApplication();
|
||||||
|
|
||||||
QString unescapeAlias( const QString& ) const;
|
QString unescapeAlias( const QString& ) const;
|
||||||
|
|
||||||
QSet<Folder*> _disabledFolders;
|
QSet<Folder*> _disabledFolders;
|
||||||
|
@ -196,6 +204,8 @@ private:
|
||||||
/** When the timer expires one of the scheduled syncs will be started. */
|
/** When the timer expires one of the scheduled syncs will be started. */
|
||||||
QTimer _startScheduledSyncTimer;
|
QTimer _startScheduledSyncTimer;
|
||||||
|
|
||||||
|
bool _appRestartRequired;
|
||||||
|
|
||||||
static FolderMan *_instance;
|
static FolderMan *_instance;
|
||||||
explicit FolderMan(QObject *parent = 0);
|
explicit FolderMan(QObject *parent = 0);
|
||||||
friend class OCC::Application;
|
friend class OCC::Application;
|
||||||
|
|
|
@ -59,6 +59,10 @@ int main(int argc, char **argv)
|
||||||
app.showHelp();
|
app.showHelp();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if( app.versionOnly() ) {
|
||||||
|
app.showVersion();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// check a environment variable for core dumps
|
// check a environment variable for core dumps
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
|
|
|
@ -393,6 +393,35 @@ void Utility::crash()
|
||||||
*a = 1;
|
*a = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read the output of the owncloud --version command from the owncloud
|
||||||
|
// version that is on disk. This works for most versions of the client,
|
||||||
|
// because clients that do not yet know the --version flag return the
|
||||||
|
// version in the first line of the help output :-)
|
||||||
|
//
|
||||||
|
// This version only delivers output on linux, as Mac and Win get their
|
||||||
|
// restarting from the installer.
|
||||||
|
QByteArray Utility::versionOfInstalledBinary( const QString& command )
|
||||||
|
{
|
||||||
|
QByteArray re;
|
||||||
|
if( isLinux() ) {
|
||||||
|
QString binary(command);
|
||||||
|
if( binary.isEmpty() ) {
|
||||||
|
binary = qApp->arguments()[0];
|
||||||
|
}
|
||||||
|
QStringList params;
|
||||||
|
params << QLatin1String("--version");
|
||||||
|
QProcess process;
|
||||||
|
process.start(binary, params);
|
||||||
|
process.waitForFinished(); // sets current thread to sleep and waits for pingProcess end
|
||||||
|
re = process.readAllStandardOutput();
|
||||||
|
int newline = re.indexOf(QChar('\n'));
|
||||||
|
if( newline > 0 ) {
|
||||||
|
re.truncate( newline );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return re;
|
||||||
|
}
|
||||||
|
|
||||||
static const char STOPWATCH_END_TAG[] = "_STOPWATCH_END";
|
static const char STOPWATCH_END_TAG[] = "_STOPWATCH_END";
|
||||||
|
|
||||||
void Utility::StopWatch::start()
|
void Utility::StopWatch::start()
|
||||||
|
|
|
@ -98,6 +98,13 @@ namespace Utility
|
||||||
// if false, the two cases are two different files.
|
// if false, the two cases are two different files.
|
||||||
OWNCLOUDSYNC_EXPORT bool fsCasePreserving();
|
OWNCLOUDSYNC_EXPORT bool fsCasePreserving();
|
||||||
|
|
||||||
|
// Call the given command with the switch --version and retrun the first line
|
||||||
|
// of the output.
|
||||||
|
// If command is empty, the function calls the running application which, on
|
||||||
|
// Linux, might have changed while this one is running.
|
||||||
|
// For Mac and Windows, it returns QString()
|
||||||
|
OWNCLOUDSYNC_EXPORT QByteArray versionOfInstalledBinary(const QString& command = QString() );
|
||||||
|
|
||||||
class OWNCLOUDSYNC_EXPORT StopWatch {
|
class OWNCLOUDSYNC_EXPORT StopWatch {
|
||||||
private:
|
private:
|
||||||
QHash<QString, quint64> _lapTimes;
|
QHash<QString, quint64> _lapTimes;
|
||||||
|
|
|
@ -26,6 +26,8 @@ if( UNIX AND NOT APPLE )
|
||||||
owncloud_add_test(InotifyWatcher "${FolderWatcher_SRC}")
|
owncloud_add_test(InotifyWatcher "${FolderWatcher_SRC}")
|
||||||
endif(UNIX AND NOT APPLE)
|
endif(UNIX AND NOT APPLE)
|
||||||
|
|
||||||
|
configure_file(oc_bin.h.in oc_bin.h)
|
||||||
|
|
||||||
owncloud_add_test(CSyncSqlite "")
|
owncloud_add_test(CSyncSqlite "")
|
||||||
owncloud_add_test(NetrcParser ../src/cmd/netrcparser.cpp)
|
owncloud_add_test(NetrcParser ../src/cmd/netrcparser.cpp)
|
||||||
owncloud_add_test(OwnSql "")
|
owncloud_add_test(OwnSql "")
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
#define OWNCLOUD_BIN "@CMAKE_BINARY_DIR@/bin/owncloud"
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
|
#include "oc_bin.h"
|
||||||
|
|
||||||
using namespace OCC::Utility;
|
using namespace OCC::Utility;
|
||||||
|
|
||||||
class TestUtility : public QObject
|
class TestUtility : public QObject
|
||||||
|
@ -100,6 +102,20 @@ private slots:
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testVersionOfInstalledBinary()
|
||||||
|
{
|
||||||
|
if( isLinux() ) {
|
||||||
|
QString ver = versionOfInstalledBinary(OWNCLOUD_BIN);
|
||||||
|
qDebug() << "Version of installed ownCloud Binary: " << ver;
|
||||||
|
QVERIFY( !ver.isEmpty());
|
||||||
|
|
||||||
|
QRegExp rx( "ownCloud version \\d+\\.\\d+\\.\\d+.+" );
|
||||||
|
QVERIFY( rx.exactMatch(ver));
|
||||||
|
} else {
|
||||||
|
QVERIFY( versionOfInstalledBinary().isEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче