From: Christian Kamm Date: Thu, 5 Oct 2017 09:39:35 +0000 (+0200) Subject: Rename detection: File size must be equal X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~701^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=19c6757a0f971e5ba906ae70f3fce3d8af103e68;p=nextcloud-desktop.git Rename detection: File size must be equal Comparison of file sizes for potential conflicts was added in 0eb9401c624f20a128b46f8eb1fa5a984f9ef61e, but did not extend to checking the file size in case of potential local moves. This commit adds this check and adds tests for various move+change scenarios. --- diff --git a/src/csync/csync_update.cpp b/src/csync/csync_update.cpp index 9412d5185..0271b1c56 100644 --- a/src/csync/csync_update.cpp +++ b/src/csync/csync_update.cpp @@ -265,8 +265,8 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr f fs->instruction = CSYNC_INSTRUCTION_NEW; bool isRename = - base.isValid() && base._inode == fs->inode && base._type == fs->type - && (base._modtime == fs->modtime || fs->type == CSYNC_FTW_TYPE_DIR) + base.isValid() && base._type == fs->type + && ((base._modtime == fs->modtime && base._fileSize == fs->size) || fs->type == CSYNC_FTW_TYPE_DIR) #ifdef NO_RENAME_EXTENSION && _csync_sameextension(base._path, fs->path) #endif diff --git a/test/testsyncengine.cpp b/test/testsyncengine.cpp index 169c2e6fb..9c1b7a2c0 100644 --- a/test/testsyncengine.cpp +++ b/test/testsyncengine.cpp @@ -535,6 +535,84 @@ private slots: QCOMPARE(nPUT, 6); QCOMPARE(n507, 3); } + + void testLocalMove() + { + FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; + + int nPUT = 0; + int nDELETE = 0; + fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &) { + if (op == QNetworkAccessManager::PutOperation) + ++nPUT; + if (op == QNetworkAccessManager::DeleteOperation) + ++nDELETE; + return nullptr; + }); + + // For directly editing the remote checksum + FileInfo &remoteInfo = fakeFolder.remoteModifier(); + + // Simple move causing a remote rename + fakeFolder.localModifier().rename("A/a1", "A/a1m"); + QVERIFY(fakeFolder.syncOnce()); + QCOMPARE(fakeFolder.currentLocalState(), remoteInfo); + QCOMPARE(nPUT, 0); + + // Move-and-change, causing a upload and delete + fakeFolder.localModifier().rename("A/a2", "A/a2m"); + fakeFolder.localModifier().appendByte("A/a2m"); + QVERIFY(fakeFolder.syncOnce()); + QCOMPARE(fakeFolder.currentLocalState(), remoteInfo); + QCOMPARE(nPUT, 1); + QCOMPARE(nDELETE, 1); + + // Move-and-change, mtime+content only + fakeFolder.localModifier().rename("B/b1", "B/b1m"); + fakeFolder.localModifier().setContents("B/b1m", 'C'); + QVERIFY(fakeFolder.syncOnce()); + QCOMPARE(fakeFolder.currentLocalState(), remoteInfo); + QCOMPARE(nPUT, 2); + QCOMPARE(nDELETE, 2); + + // Move-and-change, size+content only + auto mtime = fakeFolder.remoteModifier().find("B/b2")->lastModified; + fakeFolder.localModifier().rename("B/b2", "B/b2m"); + fakeFolder.localModifier().appendByte("B/b2m"); + fakeFolder.localModifier().setModTime("B/b2m", mtime); + QVERIFY(fakeFolder.syncOnce()); + QCOMPARE(fakeFolder.currentLocalState(), remoteInfo); + QCOMPARE(nPUT, 3); + QCOMPARE(nDELETE, 3); + + // Move-and-change, content only -- c1 has no checksum, so we fail to detect this! + mtime = fakeFolder.remoteModifier().find("C/c1")->lastModified; + fakeFolder.localModifier().rename("C/c1", "C/c1m"); + fakeFolder.localModifier().setContents("C/c1m", 'C'); + fakeFolder.localModifier().setModTime("C/c1m", mtime); + QVERIFY(fakeFolder.syncOnce()); + QCOMPARE(nPUT, 3); + QCOMPARE(nDELETE, 3); + QVERIFY(!(fakeFolder.currentLocalState() == remoteInfo)); + + // cleanup, and upload a file that will have a checksum in the db + fakeFolder.localModifier().remove("C/c1m"); + fakeFolder.localModifier().insert("C/c3"); + QVERIFY(fakeFolder.syncOnce()); + QCOMPARE(fakeFolder.currentLocalState(), remoteInfo); + QCOMPARE(nPUT, 4); + QCOMPARE(nDELETE, 4); + + // Move-and-change, content only, this time while having a checksum + mtime = fakeFolder.remoteModifier().find("C/c3")->lastModified; + fakeFolder.localModifier().rename("C/c3", "C/c3m"); + fakeFolder.localModifier().setContents("C/c3m", 'C'); + fakeFolder.localModifier().setModTime("C/c3m", mtime); + QVERIFY(fakeFolder.syncOnce()); + QCOMPARE(nPUT, 5); + QCOMPARE(nDELETE, 5); + QCOMPARE(fakeFolder.currentLocalState(), remoteInfo); + } }; QTEST_GUILESS_MAIN(TestSyncEngine)