if (item->isDirectory() && item->_instruction == CSYNC_INSTRUCTION_SYNC)
item->_instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
+ bool removed = item->_instruction == CSYNC_INSTRUCTION_REMOVE;
if (checkPermissions(item)) {
if (item->_isRestoration && item->isDirectory())
recurse = true;
}
if (recurse) {
auto job = new ProcessDirectoryJob(path, item, recurseQueryLocal, recurseQueryServer, this);
- if (item->_instruction == CSYNC_INSTRUCTION_REMOVE) {
+ if (removed) {
job->setParent(_discoveryData);
_discoveryData->_queuedDeletedDirectories[path._original] = job;
} else {
_queuedJobs.push_back(job);
}
} else {
- if (item->_instruction == CSYNC_INSTRUCTION_REMOVE
+ if (removed
// For the purpose of rename deletion, restored deleted placeholder is as if it was deleted
|| (item->_type == ItemTypeVirtualFile && item->_instruction == CSYNC_INSTRUCTION_NEW)) {
_discoveryData->_deletedItem[path._original] = item;
if (it != _deletedItem.end()) {
ENFORCE((*it)->_instruction == CSYNC_INSTRUCTION_REMOVE
// re-creation of virtual files count as a delete
- || ((*it)->_type == ItemTypeVirtualFile && (*it)->_instruction == CSYNC_INSTRUCTION_NEW));
+ || ((*it)->_type == ItemTypeVirtualFile && (*it)->_instruction == CSYNC_INSTRUCTION_NEW)
+ || ((*it)->_isRestoration && (*it)->_instruction == CSYNC_INSTRUCTION_NEW)
+ );
(*it)->_instruction = CSYNC_INSTRUCTION_NONE;
result = true;
oldEtag = (*it)->_etag;
QVERIFY(cls.find("zallowed/sub2"));
QVERIFY(cls.find("zallowed/sub2/file"));
}
+
+ // Test for issue #7293
+ void testAllowedMoveForbiddenDelete() {
+ FakeFolder fakeFolder{FileInfo{}};
+
+ // Some of this test depends on the order of discovery. With threading
+ // that order becomes effectively random, but we want to make sure to test
+ // all cases and thus disable threading.
+ auto syncOpts = fakeFolder.syncEngine().syncOptions();
+ syncOpts._parallelNetworkJobs = 1;
+ fakeFolder.syncEngine().setSyncOptions(syncOpts);
+
+ auto &lm = fakeFolder.localModifier();
+ auto &rm = fakeFolder.remoteModifier();
+ rm.mkdir("changeonly");
+ rm.mkdir("changeonly/sub1");
+ rm.insert("changeonly/sub1/file1");
+ rm.insert("changeonly/sub1/filetorname1a");
+ rm.insert("changeonly/sub1/filetorname1z");
+ rm.mkdir("changeonly/sub2");
+ rm.insert("changeonly/sub2/file2");
+ rm.insert("changeonly/sub2/filetorname2a");
+ rm.insert("changeonly/sub2/filetorname2z");
+
+ setAllPerm(rm.find("changeonly"), RemotePermissions::fromServerString("NSV"));
+
+ QVERIFY(fakeFolder.syncOnce());
+
+ lm.rename("changeonly/sub1/filetorname1a", "changeonly/sub1/aaa1_renamed");
+ lm.rename("changeonly/sub1/filetorname1z", "changeonly/sub1/zzz1_renamed");
+
+ lm.rename("changeonly/sub2/filetorname2a", "changeonly/sub2/aaa2_renamed");
+ lm.rename("changeonly/sub2/filetorname2z", "changeonly/sub2/zzz2_renamed");
+
+ lm.rename("changeonly/sub1", "changeonly/aaa");
+ lm.rename("changeonly/sub2", "changeonly/zzz");
+
+
+ auto expectedState = fakeFolder.currentLocalState();
+
+ QVERIFY(fakeFolder.syncOnce());
+ QCOMPARE(fakeFolder.currentLocalState(), expectedState);
+ QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
+ }
};
QTEST_GUILESS_MAIN(TestPermissions)