Skip to content

Commit 969881f

Browse files
committed
feat(vfs/folders): enable on demand fetch of folder content
will enable to dynamically fetch the list of files inside a folder for now, only basic infrastructure plugging into CfApi is there Signed-off-by: Matthieu Gallien <[email protected]>
1 parent 1b3f78d commit 969881f

17 files changed

+302
-67
lines changed

src/common/vfs.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,9 @@ class OCSYNC_EXPORT Vfs : public QObject
179179
* If the remote metadata changes, the local placeholder's metadata should possibly
180180
* change as well.
181181
*/
182-
[[nodiscard]] virtual Result<void, QString> updateMetadata(const QString &filePath, time_t modtime, qint64 size, const QByteArray &fileId) = 0;
182+
[[nodiscard]] virtual Result<void, QString> updateMetadata(const QString &filePath, const SyncFileItem &item) = 0;
183183

184-
[[nodiscard]] virtual Result<Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderMarkInSync(const QString &filePath, const QByteArray &fileId) = 0;
184+
[[nodiscard]] virtual Result<Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderMarkInSync(const QString &filePath, const SyncFileItem &item) = 0;
185185

186186
[[nodiscard]] virtual bool isPlaceHolderInSync(const QString &filePath) const = 0;
187187

@@ -320,8 +320,8 @@ class OCSYNC_EXPORT VfsOff : public Vfs
320320
[[nodiscard]] bool socketApiPinStateActionsShown() const override { return false; }
321321
[[nodiscard]] bool isHydrating() const override { return false; }
322322

323-
Result<void, QString> updateMetadata(const QString &, time_t, qint64, const QByteArray &) override { return {}; }
324-
Result<Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderMarkInSync(const QString &filePath, const QByteArray &fileId) override {Q_UNUSED(filePath) Q_UNUSED(fileId) return {QString{}};}
323+
Result<void, QString> updateMetadata(const QString &, const SyncFileItem &) override { return {}; }
324+
Result<Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderMarkInSync(const QString &filePath, const SyncFileItem &item) override {Q_UNUSED(filePath) Q_UNUSED(item) return {QString{}};}
325325
[[nodiscard]] bool isPlaceHolderInSync(const QString &filePath) const override { Q_UNUSED(filePath) return true; }
326326
Result<void, QString> createPlaceholder(const SyncFileItem &) override { return {}; }
327327
Result<void, QString> dehydratePlaceholder(const SyncFileItem &) override { return {}; }

src/gui/folder.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,8 @@ void Folder::slotFilesLockReleased(const QSet<QString> &files)
684684
SyncJournalFileRecord rec;
685685
const auto isFileRecordValid = journalDb()->getFileRecord(fileRecordPath, &rec) && rec.isValid();
686686
if (isFileRecordValid) {
687-
[[maybe_unused]] const auto result = _vfs->updatePlaceholderMarkInSync(path() + rec.path(), rec._fileId);
687+
const auto itemPointer = SyncFileItem::fromSyncJournalFileRecord(rec);
688+
[[maybe_unused]] const auto result = _vfs->updatePlaceholderMarkInSync(path() + rec.path(), *itemPointer);
688689
}
689690
const auto canUnlockFile = isFileRecordValid
690691
&& rec._lockstate._locked
@@ -728,7 +729,8 @@ void Folder::slotFilesLockImposed(const QSet<QString> &files)
728729
const auto fileRecordPath = fileFromLocalPath(file);
729730
SyncJournalFileRecord rec;
730731
if (journalDb()->getFileRecord(fileRecordPath, &rec) && rec.isValid()) {
731-
[[maybe_unused]] const auto result = _vfs->updatePlaceholderMarkInSync(path() + rec.path(), rec._fileId);
732+
const auto itemPointer = SyncFileItem::fromSyncJournalFileRecord(rec);
733+
[[maybe_unused]] const auto result = _vfs->updatePlaceholderMarkInSync(path() + rec.path(), *itemPointer);
732734
}
733735
}
734736
}

src/libsync/abstractnetworkjob.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44
* SPDX-License-Identifier: GPL-2.0-or-later
55
*/
66

7+
#include "common/asserts.h"
8+
#include "networkjobs.h"
9+
#include "account.h"
10+
#include "owncloudpropagator.h"
11+
#include "httplogger.h"
12+
#include "accessmanager.h"
13+
14+
#include "creds/abstractcredentials.h"
15+
716
#include <QLoggingCategory>
817
#include <QNetworkRequest>
918
#include <QNetworkAccessManager>
@@ -21,14 +30,6 @@
2130
#include <QMetaEnum>
2231
#include <QRegularExpression>
2332

24-
#include "common/asserts.h"
25-
#include "networkjobs.h"
26-
#include "account.h"
27-
#include "owncloudpropagator.h"
28-
#include "httplogger.h"
29-
30-
#include "creds/abstractcredentials.h"
31-
3233
Q_DECLARE_METATYPE(QTimer *)
3334

3435
namespace OCC {
@@ -117,8 +118,10 @@ QNetworkReply *AbstractNetworkJob::addTimer(QNetworkReply *reply)
117118
return reply;
118119
}
119120

120-
QNetworkReply *AbstractNetworkJob::sendRequest(const QByteArray &verb, const QUrl &url,
121-
QNetworkRequest req, QIODevice *requestBody)
121+
QNetworkReply *AbstractNetworkJob::sendRequest(const QByteArray &verb,
122+
const QUrl &url,
123+
QNetworkRequest req,
124+
QIODevice *requestBody)
122125
{
123126
auto reply = _account->sendRawRequest(verb, url, req, requestBody);
124127
_requestBody = requestBody;
@@ -129,8 +132,10 @@ QNetworkReply *AbstractNetworkJob::sendRequest(const QByteArray &verb, const QUr
129132
return reply;
130133
}
131134

132-
QNetworkReply *AbstractNetworkJob::sendRequest(const QByteArray &verb, const QUrl &url,
133-
QNetworkRequest req, const QByteArray &requestBody)
135+
QNetworkReply *AbstractNetworkJob::sendRequest(const QByteArray &verb,
136+
const QUrl &url,
137+
QNetworkRequest req,
138+
const QByteArray &requestBody)
134139
{
135140
auto reply = _account->sendRawRequest(verb, url, req, requestBody);
136141
_requestBody = nullptr;

src/libsync/abstractnetworkjob.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class QUrl;
2424
namespace OCC {
2525

2626
class AbstractSslErrorHandler;
27+
class AccessManager;
2728

2829
/**
2930
* @brief The AbstractNetworkJob class

src/libsync/account.cpp

Lines changed: 96 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -423,17 +423,20 @@ void Account::resetNetworkAccessManager()
423423
this, &Account::proxyAuthenticationRequired);
424424
}
425425

426-
QNetworkAccessManager *Account::networkAccessManager()
426+
QNetworkAccessManager *Account::networkAccessManager() const
427427
{
428428
return _networkAccessManager.data();
429429
}
430430

431-
QSharedPointer<QNetworkAccessManager> Account::sharedNetworkAccessManager()
431+
QSharedPointer<QNetworkAccessManager> Account::sharedNetworkAccessManager() const
432432
{
433433
return _networkAccessManager;
434434
}
435435

436-
QNetworkReply *Account::sendRawRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data)
436+
QNetworkReply *Account::sendRawRequest(const QByteArray &verb,
437+
const QUrl &url,
438+
QNetworkRequest req,
439+
QIODevice *data)
437440
{
438441
req.setUrl(url);
439442
req.setSslConfiguration(this->getOrCreateSslConfig());
@@ -451,7 +454,10 @@ QNetworkReply *Account::sendRawRequest(const QByteArray &verb, const QUrl &url,
451454
return _networkAccessManager->sendCustomRequest(req, verb, data);
452455
}
453456

454-
QNetworkReply *Account::sendRawRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, const QByteArray &data)
457+
QNetworkReply *Account::sendRawRequest(const QByteArray &verb,
458+
const QUrl &url,
459+
QNetworkRequest req,
460+
const QByteArray &data)
455461
{
456462
req.setUrl(url);
457463
req.setSslConfiguration(this->getOrCreateSslConfig());
@@ -469,7 +475,10 @@ QNetworkReply *Account::sendRawRequest(const QByteArray &verb, const QUrl &url,
469475
return _networkAccessManager->sendCustomRequest(req, verb, data);
470476
}
471477

472-
QNetworkReply *Account::sendRawRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QHttpMultiPart *data)
478+
QNetworkReply *Account::sendRawRequest(const QByteArray &verb,
479+
const QUrl &url,
480+
QNetworkRequest req,
481+
QHttpMultiPart *data)
473482
{
474483
req.setUrl(url);
475484
req.setSslConfiguration(this->getOrCreateSslConfig());
@@ -1138,6 +1147,88 @@ void Account::setAskUserForMnemonic(const bool ask)
11381147
emit askUserForMnemonicChanged();
11391148
}
11401149

1150+
void Account::listRemoteFolder(QPromise<QStringList> *promise, const QString &path)
1151+
{
1152+
qCInfo(lcAccount()) << "ls col job requested for" << path;
1153+
1154+
if (!credentials()->ready()) {
1155+
qCWarning(lcAccount()) << "credentials are not ready" << path;
1156+
promise->finish();
1157+
return;
1158+
}
1159+
1160+
auto listFolderJob = new OCC::LsColJob{sharedFromThis(), path};
1161+
1162+
QList<QByteArray> props;
1163+
props << "resourcetype"
1164+
<< "getlastmodified"
1165+
<< "getcontentlength"
1166+
<< "getetag"
1167+
<< "quota-available-bytes"
1168+
<< "quota-used-bytes"
1169+
<< "http://owncloud.org/ns:size"
1170+
<< "http://owncloud.org/ns:id"
1171+
<< "http://owncloud.org/ns:fileid"
1172+
<< "http://owncloud.org/ns:downloadURL"
1173+
<< "http://owncloud.org/ns:dDC"
1174+
<< "http://owncloud.org/ns:permissions"
1175+
<< "http://owncloud.org/ns:checksums"
1176+
<< "http://nextcloud.org/ns:is-encrypted"
1177+
<< "http://nextcloud.org/ns:metadata-files-live-photo"
1178+
<< "http://owncloud.org/ns:share-types";
1179+
1180+
if (capabilities().filesLockAvailable()) {
1181+
props << "http://nextcloud.org/ns:lock"
1182+
<< "http://nextcloud.org/ns:lock-owner-displayname"
1183+
<< "http://nextcloud.org/ns:lock-owner"
1184+
<< "http://nextcloud.org/ns:lock-owner-type"
1185+
<< "http://nextcloud.org/ns:lock-owner-editor"
1186+
<< "http://nextcloud.org/ns:lock-time"
1187+
<< "http://nextcloud.org/ns:lock-timeout"
1188+
<< "http://nextcloud.org/ns:lock-token";
1189+
}
1190+
props << "http://nextcloud.org/ns:is-mount-root";
1191+
1192+
listFolderJob->setProperties(props);
1193+
1194+
QObject::connect(listFolderJob, &OCC::LsColJob::networkError, this, [promise, path] (QNetworkReply *reply) {
1195+
if (reply) {
1196+
qCWarning(lcAccount()) << "ls col job" << path << "error" << reply->errorString();
1197+
}
1198+
1199+
qCWarning(lcAccount()) << "ls col job" << path << "error without a reply";
1200+
promise->finish();
1201+
});
1202+
1203+
QObject::connect(listFolderJob, &OCC::LsColJob::finishedWithError, this, [promise, path] (QNetworkReply *reply) {
1204+
if (reply) {
1205+
qCWarning(lcAccount()) << "ls col job" << path << "error" << reply->errorString();
1206+
}
1207+
1208+
qCWarning(lcAccount()) << "ls col job" << path << "error without a reply";
1209+
promise->finish();
1210+
});
1211+
1212+
QObject::connect(listFolderJob, &OCC::LsColJob::finishedWithoutError, this, [promise, path] () {
1213+
qCInfo(lcAccount()) << "ls col job" << path << "finished";
1214+
promise->finish();
1215+
});
1216+
1217+
QObject::connect(listFolderJob, &OCC::LsColJob::directoryListingSubfolders, this, [promise, path] (const QStringList &items) {
1218+
qCInfo(lcAccount()) << "ls col job" << path << "new sub-folders" << items.join(", ");
1219+
promise->addResult(items);
1220+
});
1221+
1222+
QObject::connect(listFolderJob, &OCC::LsColJob::directoryListingIterated, this, [promise, path] (const QString &name, const QMap<QString, QString> &properties) {
1223+
qCInfo(lcAccount()) << "ls col job" << path << "new file" << name << properties.count();
1224+
promise->emplaceResult(name);
1225+
});
1226+
1227+
promise->start();
1228+
listFolderJob->start();
1229+
qCInfo(lcAccount()) << "ls col job started";
1230+
}
1231+
11411232
bool Account::serverHasValidSubscription() const
11421233
{
11431234
return _serverHasValidSubscription;

src/libsync/account.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -201,15 +201,19 @@ class OWNCLOUDSYNC_EXPORT Account : public QObject
201201
* sendRequest().
202202
*/
203203
QNetworkReply *sendRawRequest(const QByteArray &verb,
204-
const QUrl &url,
205-
QNetworkRequest req = QNetworkRequest(),
206-
QIODevice *data = nullptr);
204+
const QUrl &url,
205+
QNetworkRequest req = QNetworkRequest(),
206+
QIODevice *data = nullptr);
207207

208208
QNetworkReply *sendRawRequest(const QByteArray &verb,
209-
const QUrl &url, QNetworkRequest req, const QByteArray &data);
209+
const QUrl &url,
210+
QNetworkRequest req,
211+
const QByteArray &data);
210212

211213
QNetworkReply *sendRawRequest(const QByteArray &verb,
212-
const QUrl &url, QNetworkRequest req, QHttpMultiPart *data);
214+
const QUrl &url,
215+
QNetworkRequest req,
216+
QHttpMultiPart *data);
213217

214218
/** Create and start network job for a simple one-off request.
215219
*
@@ -312,8 +316,8 @@ class OWNCLOUDSYNC_EXPORT Account : public QObject
312316
QString cookieJarPath();
313317

314318
void resetNetworkAccessManager();
315-
QNetworkAccessManager *networkAccessManager();
316-
QSharedPointer<QNetworkAccessManager> sharedNetworkAccessManager();
319+
[[nodiscard]] QNetworkAccessManager *networkAccessManager() const;
320+
[[nodiscard]] QSharedPointer<QNetworkAccessManager> sharedNetworkAccessManager() const;
317321

318322
/// Called by network jobs on credential errors, emits invalidCredentials()
319323
void handleInvalidCredentials();
@@ -424,6 +428,9 @@ public slots:
424428
void slotHandleSslErrors(QNetworkReply *, QList<QSslError>);
425429
void setAskUserForMnemonic(const bool ask);
426430

431+
void listRemoteFolder(QPromise<QStringList> *promise,
432+
const QString &path);
433+
427434
signals:
428435
/// Emitted whenever there's network activity
429436
void propagatorNetworkActivity();

src/libsync/discovery.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1862,7 +1862,7 @@ void ProcessDirectoryJob::processFileFinalize(
18621862
Q_ASSERT(false);
18631863
}
18641864

1865-
if (recurse) {
1865+
if (recurse && _discoveryData->shouldDiscoverChildFolder(path._server)) {
18661866
auto job = new ProcessDirectoryJob(path, item, recurseQueryLocal, recurseQueryServer,
18671867
_lastSyncTimestamp, this);
18681868
job->setInsideEncryptedTree(isInsideEncryptedTree() || item->isEncrypted());

src/libsync/discoveryphase.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,12 @@ void DiscoveryPhase::setSelectiveSyncWhiteList(const QStringList &list)
275275
_selectiveSyncWhiteList.sort();
276276
}
277277

278+
bool DiscoveryPhase::shouldDiscoverChildFolder(const QString &path) const
279+
{
280+
qCInfo(lcDiscovery()) << "do not discover" << path;
281+
return false;
282+
}
283+
278284
bool DiscoveryPhase::isRenamed(const QString &p) const
279285
{
280286
return _renamedItemsLocal.contains(p) || _renamedItemsRemote.contains(p);

src/libsync/discoveryphase.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,8 @@ class DiscoveryPhase : public QObject
347347
void setSelectiveSyncBlackList(const QStringList &list);
348348
void setSelectiveSyncWhiteList(const QStringList &list);
349349

350+
bool shouldDiscoverChildFolder(const QString &path) const;
351+
350352
// output
351353
QByteArray _dataFingerprint;
352354
bool _anotherSyncNeeded = false;

src/libsync/owncloudpropagator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1808,7 +1808,7 @@ void PropagateIgnoreJob::start()
18081808
void PropagateVfsUpdateMetadataJob::start()
18091809
{
18101810
const auto fullFileName = propagator()->fullLocalPath(_item->_file);
1811-
const auto result = propagator()->syncOptions()._vfs->updatePlaceholderMarkInSync(fullFileName, _item->_fileId);
1811+
const auto result = propagator()->syncOptions()._vfs->updatePlaceholderMarkInSync(fullFileName, *_item);
18121812
emit propagator()->touchedFile(fullFileName);
18131813
if (!result) {
18141814
qCWarning(lcPropagator()) << "error when updating VFS metadata" << result.error();

0 commit comments

Comments
 (0)