}
_serverNormalQueryEntries.clear();
- for (auto &e : _localNormalQueryEntries) {
- // Remove the virtual file suffix
- auto name = e.name;
- if (e.isVirtualFile && isVfsWithSuffix()) {
- chopVirtualFileSuffix(name);
- auto &entry = entries[name];
- // If there is both a virtual file and a real file, we must keep the real file
- if (!entry.localEntry.isValid())
- entry.localEntry = std::move(e);
- } else {
- entries[name].localEntry = std::move(e);
- }
- }
- _localNormalQueryEntries.clear();
-
// fetch all the name from the DB
auto pathU8 = _currentFolder._original.toUtf8();
if (!_discoveryData->_statedb->listFilesInPath(pathU8, [&](const SyncJournalFileRecord &rec) {
return;
}
+ for (auto &e : _localNormalQueryEntries) {
+ // Normally for vfs-suffix files the local entries need the suffix removed.
+ // However, don't do it if "foo.owncloud" exists on the server or in the db
+ // (as a non-virtual file): we don't want to create two entries.
+ auto name = e.name;
+ if (e.isVirtualFile && isVfsWithSuffix() && entries.find(name) == entries.end()) {
+ chopVirtualFileSuffix(name);
+ // If there is both a virtual file and a real file, we must keep the real file
+ if (entries[name].localEntry.isValid())
+ continue;
+ }
+ entries[name].localEntry = std::move(e);
+ }
+ _localNormalQueryEntries.clear();
+
//
// Iterate over entries and process them
//
if (e.dbEntry.isVirtualFile()) {
ASSERT(hasVirtualFileSuffix(e.dbEntry._path));
addVirtualFileSuffix(path._original);
- } else if (e.localEntry.isVirtualFile) {
+ } else if (e.localEntry.isVirtualFile && !e.dbEntry.isValid()) {
// We don't have a db entry - but it should be at this path
addVirtualFileSuffix(path._original);
}
if (item->_type == ItemTypeVirtualFileDehydration)
item->_type = ItemTypeFile;
+ // VFS suffixed files on the server are ignored
+ if (isVfsWithSuffix()) {
+ if (hasVirtualFileSuffix(serverEntry.name)
+ || (localEntry.isVirtualFile && !dbEntry.isVirtualFile() && hasVirtualFileSuffix(dbEntry._path))) {
+ item->_instruction = CSYNC_INSTRUCTION_IGNORE;
+ item->_errorString = tr("File has extension reserved for virtual files.");
+ _childIgnored = true;
+ emit _discoveryData->itemDiscovered(item);
+ return;
+ }
+ }
+
if (serverEntry.isValid()) {
processFileAnalyzeRemoteInfo(item, path, localEntry, serverEntry, dbEntry);
return;
item->_direction = SyncFileItem::Down;
item->_instruction = CSYNC_INSTRUCTION_NEW;
item->_type = ItemTypeVirtualFile;
+ } else {
+ qCInfo(lcDisco) << "Virtual file with non-virtual db entry, ignoring:" << item->_file;
+ item->_instruction = CSYNC_INSTRUCTION_IGNORE;
}
}
} else if (!typeChange && ((dbEntry._modtime == localEntry.modtime && dbEntry._fileSize == localEntry.size) || localEntry.isDirectory)) {
void testNewVirtuals()
{
FakeFolder fakeFolder{ FileInfo() };
- SyncOptions syncOptions = vfsSyncOptions(fakeFolder);
- fakeFolder.syncEngine().setSyncOptions(syncOptions);
+ fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
auto setPin = [&] (const QByteArray &path, PinState state) {
QVERIFY(fakeFolder.currentLocalState().find("local/file1"));
QVERIFY(fakeFolder.currentLocalState().find("unspec/file1.nextcloud"));
}
+
+ // Check what happens if vfs-suffixed files exist on the server or in the db
+ void testSuffixOnServerOrDb()
+ {
+ FakeFolder fakeFolder{ FileInfo() };
+
+ QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
+ auto cleanup = [&]() {
+ completeSpy.clear();
+ };
+ cleanup();
+
+ // file1.nextcloud is happily synced with Vfs::Off
+ fakeFolder.remoteModifier().mkdir("A");
+ fakeFolder.remoteModifier().insert("A/file1.nextcloud");
+ QVERIFY(fakeFolder.syncOnce());
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ cleanup();
+
+ // Enable suffix vfs
+ fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+
+ // Local changes of suffixed file do nothing
+ fakeFolder.localModifier().appendByte("A/file1.nextcloud");
+ QVERIFY(fakeFolder.syncOnce());
+ QVERIFY(itemInstruction(completeSpy, "A/file1.nextcloud", CSYNC_INSTRUCTION_IGNORE));
+ cleanup();
+
+ // Remote don't do anything either
+ fakeFolder.remoteModifier().appendByte("A/file1.nextcloud");
+ QVERIFY(fakeFolder.syncOnce());
+ QVERIFY(itemInstruction(completeSpy, "A/file1.nextcloud", CSYNC_INSTRUCTION_IGNORE));
+ cleanup();
+
+ // New files with a suffix aren't propagated downwards in the first place
+ fakeFolder.remoteModifier().insert("A/file2.nextcloud");
+ QVERIFY(fakeFolder.syncOnce());
+ QVERIFY(itemInstruction(completeSpy, "A/file2.nextcloud", CSYNC_INSTRUCTION_IGNORE));
+ QVERIFY(fakeFolder.currentRemoteState().find("A/file2.nextcloud"));
+ QVERIFY(!fakeFolder.currentLocalState().find("A/file2"));
+ QVERIFY(!fakeFolder.currentLocalState().find("A/file2.nextcloud"));
+ QVERIFY(!fakeFolder.currentLocalState().find("A/file2.nextcloud.nextcloud"));
+ cleanup();
+ }
};
QTEST_GUILESS_MAIN(TestSyncVirtualFiles)