From 29d2d9add145c39210e21ae01c42b24d98568ef7 Mon Sep 17 00:00:00 2001 From: Hannah von Reth Date: Tue, 6 Apr 2021 14:45:55 +0200 Subject: [PATCH] Log when we begin and end a backup requested on a socket --- changelog/unreleased/8437 | 1 + src/gui/folder.cpp | 2 +- src/gui/protocolwidget.cpp | 14 ++++---- src/gui/socketapi/socketuploadjob.cpp | 52 ++++++++++++++++++++------- src/gui/socketapi/socketuploadjob.h | 3 ++ src/libsync/progressdispatcher.cpp | 12 ------- src/libsync/progressdispatcher.h | 5 --- src/libsync/syncfileitem.h | 1 + 8 files changed, 53 insertions(+), 37 deletions(-) diff --git a/changelog/unreleased/8437 b/changelog/unreleased/8437 index fd7d0aa4012..29e8cefc1cd 100644 --- a/changelog/unreleased/8437 +++ b/changelog/unreleased/8437 @@ -3,3 +3,4 @@ Enhancement: Add initial support for backups triggered by an external tool We added a socket api function which allows creation of backups. https://github.com/owncloud/client/pull/8437 +https://github.com/owncloud/client/pull/8535 diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index 2b56cc92e1f..8e0810a138b 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -1001,7 +1001,7 @@ void Folder::slotEmitFinishedDelayed() void Folder::slotTransmissionProgress(const ProgressInfo &pi) { emit progressInfo(pi); - ProgressDispatcher::instance()->setProgressInfo(alias(), pi); + emit ProgressDispatcher::instance()->progressInfo(alias(), pi); } // a item is completed: count the errors and forward to the ProgressDispatcher diff --git a/src/gui/protocolwidget.cpp b/src/gui/protocolwidget.cpp index 87ce43e55f0..4555badcfa2 100644 --- a/src/gui/protocolwidget.cpp +++ b/src/gui/protocolwidget.cpp @@ -55,12 +55,9 @@ void ProtocolItem::setExtraData(QTreeWidgetItem *item, const ExtraData &data) item->setData(0, Qt::UserRole, QVariant::fromValue(data)); } -ProtocolItem *ProtocolItem::create(const QString &folder, const SyncFileItem &item) +ProtocolItem *ProtocolItem::create(const QString &folderName, const SyncFileItem &item) { - auto f = FolderMan::instance()->folder(folder); - if (!f) { - return nullptr; - } + auto folder = FolderMan::instance()->folder(folderName); QStringList columns; QDateTime timestamp = QDateTime::currentDateTime(); @@ -69,10 +66,13 @@ ProtocolItem *ProtocolItem::create(const QString &folder, const SyncFileItem &it columns << timeStr; columns << Utility::fileNameForGuiUse(item._originalFile); - columns << f->shortGuiLocalPath(); + columns << (folder ? folder->shortGuiLocalPath() : QDir::toNativeSeparators(folderName)); // If the error string is set, it's prefered because it is a useful user message. QString message = item._errorString; + if (message.isEmpty()) { + message = item._messageString; + } if (message.isEmpty()) { message = Progress::asResultString(item); } @@ -103,7 +103,7 @@ ProtocolItem *ProtocolItem::create(const QString &folder, const SyncFileItem &it ProtocolItem::ExtraData data; data.timestamp = timestamp; data.path = item.destination(); - data.folderName = folder; + data.folderName = folderName; data.status = item._status; data.size = item._size; data.direction = item._direction; diff --git a/src/gui/socketapi/socketuploadjob.cpp b/src/gui/socketapi/socketuploadjob.cpp index 26adea0679f..b3ef82bab8b 100644 --- a/src/gui/socketapi/socketuploadjob.cpp +++ b/src/gui/socketapi/socketuploadjob.cpp @@ -17,8 +17,10 @@ #include "accountmanager.h" #include "common/syncjournaldb.h" +#include "progressdispatcher.h" #include "syncengine.h" +#include #include #include #include @@ -26,15 +28,29 @@ using namespace OCC; +namespace { + +// create a fake SyncFileItemPtr to display a message in the protocol +void logMessage(const QString &localPath, const QString &message) +{ + auto item = SyncFileItemPtr::create(); + item->_status = SyncFileItem::Success; + item->_messageString = message; + item->_responseTimeStamp = QDateTime::currentDateTime().toString(Qt::RFC2822Date).toUtf8(); + Q_EMIT ProgressDispatcher::instance()->itemCompleted(QDir::toNativeSeparators(localPath), item); +} +} + SocketUploadJob::SocketUploadJob(const QSharedPointer &job) : _apiJob(job) { connect(job.data(), &SocketApiJobV2::finished, this, &SocketUploadJob::deleteLater); } + void SocketUploadJob::start() { - const auto localPath = _apiJob->arguments()[QLatin1String("localPath")].toString(); + _localPath = _apiJob->arguments()[QLatin1String("localPath")].toString(); auto remotePath = _apiJob->arguments()[QLatin1String("remotePath")].toString(); if (!remotePath.startsWith(QLatin1Char('/'))) { remotePath = QLatin1Char('/') + remotePath; @@ -45,42 +61,48 @@ void SocketUploadJob::start() AccountStatePtr account; account = AccountManager::instance()->account(accname); + logMessage(_localPath, tr("Backup of %1 started").arg(QDir::toNativeSeparators(_localPath))); + if (!account) { - _apiJob->failure(QStringLiteral("Failed to find %1").arg(QString::fromUtf8(QJsonDocument(_apiJob->arguments()[QLatin1String("account")].toObject()).toJson()))); + fail(tr("Failed to find %1").arg(QString::fromUtf8(QJsonDocument(_apiJob->arguments()[QLatin1String("account")].toObject()).toJson()))); return; } - if (!QFileInfo(localPath).isAbsolute()) { - _apiJob->failure(QStringLiteral("Local path must be a an absolute path")); + if (!QFileInfo(_localPath).isAbsolute()) { + fail(tr("Local path must be a an absolute path")); return; } auto tmp = new QTemporaryFile(this); if (!tmp->open()) { - _apiJob->failure(QStringLiteral("Failed to create temporary database")); + fail(tr("Failed to create temporary database")); return; } auto db = new SyncJournalDb(tmp->fileName(), this); - auto engine = new SyncEngine(account->account(), localPath.endsWith(QLatin1Char('/')) ? localPath : localPath + QLatin1Char('/'), remotePath, db); + auto engine = new SyncEngine(account->account(), _localPath.endsWith(QLatin1Char('/')) ? _localPath : _localPath + QLatin1Char('/'), remotePath, db); engine->setParent(db); + connect(engine, &OCC::SyncEngine::transmissionProgress, this, [this](const ProgressInfo &info) { + Q_EMIT ProgressDispatcher::instance()->progressInfo(_localPath, info); + }); connect(engine, &OCC::SyncEngine::itemCompleted, this, [this](const OCC::SyncFileItemPtr item) { _syncedFiles.append(item->_file); }); - connect(engine, &OCC::SyncEngine::finished, this, [this, localPath](bool ok) { + connect(engine, &OCC::SyncEngine::finished, this, [this](bool ok) { if (ok) { - _apiJob->success({ { "localPath", localPath }, { "syncedFiles", QJsonArray::fromStringList(_syncedFiles) } }); + logMessage(_localPath, tr("Backup of %1 succeeded").arg(QDir::toNativeSeparators(_localPath))); + _apiJob->success({ { QStringLiteral("localPath"), _localPath }, { QStringLiteral("syncedFiles"), QJsonArray::fromStringList(_syncedFiles) } }); } }); connect(engine, &OCC::SyncEngine::syncError, this, [this](const QString &error, ErrorCategory) { - _apiJob->failure(error); + fail(error); }); auto opt = engine->syncOptions(); opt.setFilePattern(pattern); if (!opt.fileRegex().isValid()) { - _apiJob->failure(opt.fileRegex().errorString()); + fail(opt.fileRegex().errorString()); return; } engine->setSyncOptions(opt); @@ -92,10 +114,16 @@ void SocketUploadJob::start() if (reply->error() == QNetworkReply::NoError) { engine->startSync(); } else if (reply->error() == 202) { - _apiJob->failure(QStringLiteral("Destination %1 already exists").arg(remotePath)); + fail(QStringLiteral("Destination %1 already exists").arg(remotePath)); } else { - _apiJob->failure(reply->errorString()); + fail(reply->errorString()); } }); mkdir->start(); } + +void SocketUploadJob::fail(const QString &error) +{ + logMessage(_localPath, tr("Backup of %1 failed with: %2").arg(QDir::toNativeSeparators(_localPath), error)); + _apiJob->failure(error); +} diff --git a/src/gui/socketapi/socketuploadjob.h b/src/gui/socketapi/socketuploadjob.h index f7a80fe7a2e..f9dd248386f 100644 --- a/src/gui/socketapi/socketuploadjob.h +++ b/src/gui/socketapi/socketuploadjob.h @@ -30,6 +30,9 @@ class SocketUploadJob : public QObject void start(); private: + void fail(const QString &error); + + QString _localPath; QSharedPointer _apiJob; QStringList _syncedFiles; }; diff --git a/src/libsync/progressdispatcher.cpp b/src/libsync/progressdispatcher.cpp index 99b6b3ca8dc..b4cbf2d66e0 100644 --- a/src/libsync/progressdispatcher.cpp +++ b/src/libsync/progressdispatcher.cpp @@ -122,18 +122,6 @@ ProgressDispatcher::~ProgressDispatcher() { } -void ProgressDispatcher::setProgressInfo(const QString &folder, const ProgressInfo &progress) -{ - if (folder.isEmpty()) - // The update phase now also has progress - // (progress._currentItems.size() == 0 - // && progress._totalFileCount == 0) ) - { - return; - } - emit progressInfo(folder, progress); -} - ProgressInfo::ProgressInfo() { connect(&_updateEstimatesTimer, &QTimer::timeout, this, &ProgressInfo::updateEstimates); diff --git a/src/libsync/progressdispatcher.h b/src/libsync/progressdispatcher.h index daf3dd976cc..a5ed53624af 100644 --- a/src/libsync/progressdispatcher.h +++ b/src/libsync/progressdispatcher.h @@ -288,8 +288,6 @@ enum class ErrorCategory { class OWNCLOUDSYNC_EXPORT ProgressDispatcher : public QObject { Q_OBJECT - - friend class Folder; // only allow Folder class to access the setting slots. public: static ProgressDispatcher *instance(); ~ProgressDispatcher() override; @@ -318,9 +316,6 @@ class OWNCLOUDSYNC_EXPORT ProgressDispatcher : public QObject */ void folderConflicts(const QString &folder, const QStringList &conflictPaths); -protected: - void setProgressInfo(const QString &folder, const ProgressInfo &progress); - private: ProgressDispatcher(QObject *parent = nullptr); diff --git a/src/libsync/syncfileitem.h b/src/libsync/syncfileitem.h index ca92eccc33e..84ce2b2390e 100644 --- a/src/libsync/syncfileitem.h +++ b/src/libsync/syncfileitem.h @@ -246,6 +246,7 @@ class OWNCLOUDSYNC_EXPORT SyncFileItem quint16 _httpErrorCode; RemotePermissions _remotePerm; QString _errorString; // Contains a string only in case of error + QString _messageString; // Contains a string only in case of hand crafted events QByteArray _responseTimeStamp; QByteArray _requestId; // X-Request-Id of the failed request quint32 _affectedItems; // the number of affected items by the operation on this item.