From f330c25a7de95f96848128e06c1ffc5316ba46e7 Mon Sep 17 00:00:00 2001 From: zenb Date: Mon, 21 Sep 2026 01:59:19 +0300 Subject: [PATCH] fix(vfs/windows): do not skip incomplete directory stubs on on-demand listing Signed-off-by: zenb --- src/libsync/account.cpp | 59 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/src/libsync/account.cpp b/src/libsync/account.cpp index d55b7951eae09..70cf2337b48c1 100644 --- a/src/libsync/account.cpp +++ b/src/libsync/account.cpp @@ -1214,6 +1214,52 @@ void Account::setAskUserForMnemonic(const bool ask) emit askUserForMnemonicChanged(); } + +namespace { + +bool journalHasDirectChildren(SyncJournalDb *journal, const QByteArray &path) +{ + bool found = false; + journal->listFilesInPath(path, [&found](const SyncJournalFileRecord &) { + found = true; + }); + return found; +} + +bool shouldSkipExistingItemForOnDemandListing( + const SyncJournalFileRecord &record, + SyncJournalDb *journal, + const RemoteInfo &remoteInfo) +{ + if (!record.isDirectory()) { + if (record._inode == 0) { + return false; + } + if (!remoteInfo.etag.isEmpty() && record._etag != remoteInfo.etag) { + return false; + } + if (!remoteInfo.fileId.isEmpty() && record._fileId != remoteInfo.fileId) { + return false; + } + return true; + } + + if (journalHasDirectChildren(journal, record._path)) { + return true; + } + + if (remoteInfo.folderQuota.bytesUsed > 0) { + return false; + } + if (remoteInfo.sizeOfFolder > 0) { + return false; + } + + return true; +} + +} // namespace + void Account::listRemoteFolder(QPromise *promise, const QString &remoteSyncRootPath, const QString &subPath, SyncJournalDb *journalForFolder) { qCInfo(lcAccount()) << "ls col job requested for" << subPath; @@ -1273,12 +1319,6 @@ void Account::listRemoteFolder(QPromise *promise, co const auto itemFileName = completeDavPath.mid(slash + 1); const auto absoluteItemPathName = syncRootPath.isEmpty() ? itemFileName : Utility::noTrailingSlashPath(syncRootPath) + '/' + itemFileName; - auto currentItemDbRecord = SyncJournalFileRecord{}; - if (journalForFolder->getFileRecord(absoluteItemPathName, ¤tItemDbRecord) && currentItemDbRecord.isValid()) { - qCWarning(lcAccount()) << "skip existing item" << absoluteItemPathName; - return; - } - auto newEntry = RemoteInfo{}; newEntry.name = itemFileName; newEntry.size = -1; @@ -1295,6 +1335,13 @@ void Account::listRemoteFolder(QPromise *promise, co return; } + auto currentItemDbRecord = SyncJournalFileRecord{}; + if (journalForFolder->getFileRecord(absoluteItemPathName, ¤tItemDbRecord) && currentItemDbRecord.isValid() + && shouldSkipExistingItemForOnDemandListing(currentItemDbRecord, journalForFolder, newEntry)) { + qCWarning(lcAccount()) << "skip existing item" << absoluteItemPathName; + return; + } + promise->emplaceResult(itemFileName, itemFileName.toStdWString(), absoluteItemPathName, newEntry); });