* If the remote metadata changes, the local placeholder's metadata should possibly
* change as well.
*/
- Q_REQUIRED_RESULT virtual Result<void, QString> updateMetadata(const QString &filePath, time_t modtime, qint64 size, const QByteArray &fileId) = 0;
+ [[nodiscard]] virtual Result<void, QString> updateMetadata(const QString &filePath, time_t modtime, qint64 size, const QByteArray &fileId) = 0;
+
+ [[nodiscard]] virtual Result<Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderMarkInSync(const QString &filePath, const QByteArray &fileId) = 0;
+
+ [[nodiscard]] virtual bool isPlaceHolderInSync(const QString &filePath) const = 0;
/// Create a new dehydrated placeholder. Called from PropagateDownload.
Q_REQUIRED_RESULT virtual Result<void, QString> createPlaceholder(const SyncFileItem &item) = 0;
[[nodiscard]] bool isHydrating() const override { return false; }
Result<void, QString> updateMetadata(const QString &, time_t, qint64, const QByteArray &) override { return {}; }
+ Result<Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderMarkInSync(const QString &filePath, const QByteArray &fileId) override {Q_UNUSED(filePath) Q_UNUSED(fileId) return {QString{}};}
+ [[nodiscard]] bool isPlaceHolderInSync(const QString &filePath) const override { Q_UNUSED(filePath) return true; }
Result<void, QString> createPlaceholder(const SyncFileItem &) override { return {}; }
Result<void, QString> dehydratePlaceholder(const SyncFileItem &) override { return {}; }
Result<ConvertToPlaceholderResult, QString> convertToPlaceholder(const QString &, const SyncFileItem &, const QString &, const UpdateMetadataTypes) override { return ConvertToPlaceholderResult::Ok; }
CSYNC_INSTRUCTION_UPDATE_METADATA = 1 << 10, /* If the etag has been updated and need to be writen to the db,
but without any propagation (UPDATE|RECONCILE) */
CSYNC_INSTRUCTION_CASE_CLASH_CONFLICT = 1 << 12, /* The file need to be downloaded because it is a case clash conflict (RECONCILE) */
+ CSYNC_INSTRUCTION_UPDATE_VFS_METADATA = 1 << 13, /* vfs item metadata are out of sync and we need to tell operating system about it */
};
Q_ENUM_NS(SyncInstructions)
spurious = true;
if (auto pinState = _vfs->pinState(relativePath.toString())) {
- if (*pinState == PinState::AlwaysLocal && record.isVirtualFile())
+ if (*pinState == PinState::AlwaysLocal && record.isVirtualFile()) {
spurious = false;
- if (*pinState == PinState::OnlineOnly && record.isFile())
+ }
+ if (*pinState == PinState::OnlineOnly && record.isFile()) {
spurious = false;
+ }
} else {
spurious = false;
}
+ if (spurious && !_vfs->isPlaceHolderInSync(path)) {
+ spurious = false;
+ }
}
if (spurious) {
qCInfo(lcFolder) << "Ignoring spurious notification for file" << relativePath;
}
}
+ if (_discoveryData->_syncOptions._vfs &&
+ item->_type == CSyncEnums::ItemTypeFile &&
+ !_discoveryData->_syncOptions._vfs->isPlaceHolderInSync(_discoveryData->_localDir + path._local)) {
+ item->_instruction = CSyncEnums::CSYNC_INSTRUCTION_UPDATE_VFS_METADATA;
+ }
+
if (path._original != path._target && (item->_instruction == CSYNC_INSTRUCTION_UPDATE_METADATA || item->_instruction == CSYNC_INSTRUCTION_NONE)) {
ASSERT(_dirItem && _dirItem->_instruction == CSYNC_INSTRUCTION_RENAME);
// This is because otherwise subitems are not updated! (ideally renaming a directory could
} else {
return new PropagateLocalRename(this, item);
}
+ case CSYNC_INSTRUCTION_UPDATE_VFS_METADATA:
+ return new PropagateVfsUpdateMetadataJob(this, item);
case CSYNC_INSTRUCTION_IGNORE:
case CSYNC_INSTRUCTION_ERROR:
return new PropagateIgnoreJob(this, item);
done(status, _item->_errorString, ErrorCategory::NoError);
}
+void PropagateVfsUpdateMetadataJob::start()
+{
+ const auto fullFileName = propagator()->fullLocalPath(_item->_file);
+ const auto result = propagator()->syncOptions()._vfs->updatePlaceholderMarkInSync(fullFileName, _item->_fileId);
+ emit propagator()->touchedFile(fullFileName);
+ if (!result) {
+ qCWarning(lcPropagator()) << "error when updating VFS metadata" << result.error();
+ }
+ done(SyncFileItem::Success, {}, {});
+}
+
}
void start() override;
};
+class PropagateVfsUpdateMetadataJob : public PropagateItemJob
+{
+ Q_OBJECT
+public:
+ PropagateVfsUpdateMetadataJob(OwncloudPropagator *propagator, const SyncFileItemPtr &item)
+ : PropagateItemJob(propagator, item)
+ {
+ }
+ void start() override;
+};
+
class PropagateUploadFileCommon;
class OWNCLOUDSYNC_EXPORT OwncloudPropagator : public QObject
return QCoreApplication::translate("progress", "Error");
case CSYNC_INSTRUCTION_UPDATE_METADATA:
return QCoreApplication::translate("progress", "Updated local metadata");
+ case CSYNC_INSTRUCTION_UPDATE_VFS_METADATA:
+ return QCoreApplication::translate("progress", "Updated local virtual files metadata");
case CSYNC_INSTRUCTION_NONE:
case CSYNC_INSTRUCTION_EVAL:
return QCoreApplication::translate("progress", "Unknown");
return QCoreApplication::translate("progress", "error");
case CSYNC_INSTRUCTION_UPDATE_METADATA:
return QCoreApplication::translate("progress", "updating local metadata");
+ case CSYNC_INSTRUCTION_UPDATE_VFS_METADATA:
+ return QCoreApplication::translate("progress", "updating local virtual files metadata");
case CSYNC_INSTRUCTION_NONE:
case CSYNC_INSTRUCTION_EVAL:
break;
AllMetadata,
};
-OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderState(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath, CfApiUpdateMetadataType updateType)
+OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderState(const QString &path,
+ time_t modtime,
+ qint64 size,
+ const QByteArray &fileId,
+ const QString &replacesPath,
+ CfApiUpdateMetadataType updateType)
{
if (updateType == CfApiUpdateMetadataType::AllMetadata && modtime <= 0) {
return {QString{"Could not update metadata due to invalid modification time for %1: %2"}.arg(path).arg(modtime)};
{
return updatePlaceholderState(path, {}, {}, fileId, replacesPath, CfApiUpdateMetadataType::OnlyBasicMetadata);
}
+
+bool OCC::CfApiWrapper::isPlaceHolderInSync(const QString &filePath)
+{
+ if (const auto originalInfo = findPlaceholderInfo(filePath)) {
+ return originalInfo->InSyncState == CF_IN_SYNC_STATE_IN_SYNC;
+ }
+
+ return true;
+}
NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> convertToPlaceholder(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath);
NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> dehydratePlaceholder(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId);
NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderMarkInSync(const QString &path, const QByteArray &fileId, const QString &replacesPath = QString());
+NEXTCLOUD_CFAPI_EXPORT bool isPlaceHolderInSync(const QString &filePath);
}
}
}
+Result<Vfs::ConvertToPlaceholderResult, QString> VfsCfApi::updatePlaceholderMarkInSync(const QString &filePath, const QByteArray &fileId)
+{
+ return cfapi::updatePlaceholderMarkInSync(filePath, fileId, {});
+}
+
+bool VfsCfApi::isPlaceHolderInSync(const QString &filePath) const
+{
+ return cfapi::isPlaceHolderInSync(filePath);
+}
+
Result<void, QString> VfsCfApi::createPlaceholder(const SyncFileItem &item)
{
Q_ASSERT(params().filesystemPath.endsWith('/'));
Result<void, QString> updateMetadata(const QString &filePath, time_t modtime, qint64 size, const QByteArray &fileId) override;
+ Result<Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderMarkInSync(const QString &filePath, const QByteArray &fileId) override;
+
+ [[nodiscard]] bool isPlaceHolderInSync(const QString &filePath) const override;
+
Result<void, QString> createPlaceholder(const SyncFileItem &item) override;
Result<void, QString> dehydratePlaceholder(const SyncFileItem &item) override;
Result<Vfs::ConvertToPlaceholderResult, QString> convertToPlaceholder(const QString &filename, const SyncFileItem &item, const QString &replacesFile, UpdateMetadataTypes updateType) override;
[[nodiscard]] bool isHydrating() const override;
Result<void, QString> updateMetadata(const QString &filePath, time_t modtime, qint64 size, const QByteArray &fileId) override;
+ Result<Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderMarkInSync(const QString &filePath, const QByteArray &fileId) override {Q_UNUSED(filePath) Q_UNUSED(fileId) return {QString{}};}
+ [[nodiscard]] bool isPlaceHolderInSync(const QString &filePath) const override { Q_UNUSED(filePath) return true; }
Result<void, QString> createPlaceholder(const SyncFileItem &item) override;
Result<void, QString> dehydratePlaceholder(const SyncFileItem &item) override;
[[nodiscard]] bool isHydrating() const override;
Result<void, QString> updateMetadata(const QString &filePath, time_t modtime, qint64 size, const QByteArray &fileId) override;
+ Result<Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderMarkInSync(const QString &filePath, const QByteArray &fileId) override {Q_UNUSED(filePath) Q_UNUSED(fileId) return {QString{}};}
+ [[nodiscard]] bool isPlaceHolderInSync(const QString &filePath) const override { Q_UNUSED(filePath) return true; }
Result<void, QString> createPlaceholder(const SyncFileItem &item) override;
Result<void, QString> dehydratePlaceholder(const SyncFileItem &item) override;