Allows for better attribute preservation.
Also add verifyFileUnchanged() call before dehydration to avoid data
loss when discovery takes a while.
virtual bool updateMetadata(const QString &filePath, time_t modtime, quint64 size, const QByteArray &fileId, QString *error) = 0;
/// Create a new dehydrated placeholder. Called from PropagateDownload.
- virtual void createPlaceholder(const QString &syncFolder, const SyncFileItem &item) = 0;
+ virtual void createPlaceholder(const SyncFileItem &item) = 0;
+
+ /** Convert a hydrated placeholder to a dehydrated one. Called from PropagateDownlaod.
+ *
+ * This is different from delete+create because preserving some file metadata
+ * (like pin states) may be essential for some vfs plugins.
+ */
+ virtual void dehydratePlaceholder(const SyncFileItem &item) = 0;
/** Convert a new file to a hydrated placeholder.
*
bool isHydrating() const override { return false; }
bool updateMetadata(const QString &, time_t, quint64, const QByteArray &, QString *) override { return true; }
- void createPlaceholder(const QString &, const SyncFileItem &) override {}
+ void createPlaceholder(const SyncFileItem &) override {}
+ void dehydratePlaceholder(const SyncFileItem &) override {}
void convertToPlaceholder(const QString &, const SyncFileItem &, const QString &) override {}
bool isDehydratedPlaceholder(const QString &) override { return false; }
auto &syncOptions = propagator()->syncOptions();
auto &vfs = syncOptions._vfs;
- // For virtual files just create the file and be done
+ // For virtual files just dehydrate or create the file and be done
if (_item->_type == ItemTypeVirtualFileDehydration) {
- _item->_type = ItemTypeVirtualFile;
- // TODO: Could dehydrate without wiping the file entirely
- // TODO: That would be useful as it could preserve file attributes (pins)
- auto fn = propagator()->getFilePath(_item->_file);
- qCDebug(lcPropagateDownload) << "dehydration: wiping base file" << fn;
- propagator()->_journal->deleteFileRecord(_item->_file);
- QFile::remove(fn);
-
- if (vfs->mode() == Vfs::WithSuffix) {
- // Normally new suffix-virtual files already have the suffix included in the path
- // but for dehydrations that isn't the case. Adjust it here.
- _item->_file.append(vfs->fileSuffix());
+ QString fsPath = propagator()->getFilePath(_item->_file);
+ if (!FileSystem::verifyFileUnchanged(fsPath, _item->_previousSize, _item->_previousModtime)) {
+ propagator()->_anotherSyncNeeded = true;
+ done(SyncFileItem::SoftError, tr("File has changed since discovery"));
+ return;
}
+
+ qCDebug(lcPropagateDownload) << "dehydrating file" << _item->_file;
+ _item->_type = ItemTypeVirtualFile; // Needed?
+ vfs->dehydratePlaceholder(*_item);
+ propagator()->_journal->deleteFileRecord(_item->_file);
+ updateMetadata(false);
+ return;
}
if (vfs->mode() == Vfs::Off && _item->_type == ItemTypeVirtualFile) {
qCWarning(lcPropagateDownload) << "ignored virtual file type of" << _item->_file;
_item->_type = ItemTypeFile;
}
if (_item->_type == ItemTypeVirtualFile) {
- auto fn = propagator()->getFilePath(_item->_file);
- qCDebug(lcPropagateDownload) << "creating virtual file" << fn;
-
- vfs->createPlaceholder(propagator()->_localDir, *_item);
+ qCDebug(lcPropagateDownload) << "creating virtual file" << _item->_file;
+ vfs->createPlaceholder(*_item);
updateMetadata(false);
return;
}
return true;
}
-void VfsSuffix::createPlaceholder(const QString &syncFolder, const SyncFileItem &item)
+void VfsSuffix::createPlaceholder(const SyncFileItem &item)
{
// The concrete shape of the placeholder is also used in isDehydratedPlaceholder() below
- QString fn = syncFolder + item._file;
+ QString fn = _setupParams.filesystemPath + item._file;
QFile file(fn);
file.open(QFile::ReadWrite | QFile::Truncate);
file.write(" ");
FileSystem::setModTime(fn, item._modtime);
}
+void VfsSuffix::dehydratePlaceholder(const SyncFileItem &item)
+{
+ QFile::remove(_setupParams.filesystemPath + item._file);
+ SyncFileItem virtualItem(item);
+ virtualItem._file.append(fileSuffix());
+ createPlaceholder(virtualItem);
+}
+
void VfsSuffix::convertToPlaceholder(const QString &, const SyncFileItem &, const QString &)
{
// Nothing necessary
bool updateMetadata(const QString &filePath, time_t modtime, quint64 size, const QByteArray &fileId, QString *error) override;
- void createPlaceholder(const QString &syncFolder, const SyncFileItem &item) override;
+ void createPlaceholder(const SyncFileItem &item) override;
+ void dehydratePlaceholder(const SyncFileItem &item) override;
void convertToPlaceholder(const QString &filename, const SyncFileItem &item, const QString &) override;
bool isDehydratedPlaceholder(const QString &filePath) override;