Update file's metadata in the local database when the etag changes while file remains unchanged. Fix subsequent conflict when locking and unlocking.

Signed-off-by: alex-z <blackslayer4@gmail.com>
This commit is contained in:
alex-z 2022-12-20 19:49:35 +01:00 committed by allexzander
parent d2d9de790f
commit 50ffc7373f
3 changed files with 69 additions and 3 deletions

View file

@ -1106,13 +1106,39 @@ void PropagateDownloadFile::contentChecksumComputed(const QByteArray &checksumTy
{
_item->_checksumHeader = makeChecksumHeader(checksumType, checksum);
const auto localFilePath = propagator()->fullLocalPath(_item->_file);
SyncJournalFileRecord record;
if (_item->_instruction != CSYNC_INSTRUCTION_CONFLICT && FileSystem::fileExists(localFilePath)
&& (propagator()->_journal->getFileRecord(_item->_file, &record) && record.isValid())
&& (record._modtime == _item->_modtime && record._etag != _item->_etag)) {
const auto computeChecksum = new ComputeChecksum(this);
computeChecksum->setChecksumType(checksumType);
connect(computeChecksum, &ComputeChecksum::done, this, &PropagateDownloadFile::localFileContentChecksumComputed);
computeChecksum->start(localFilePath);
return;
}
finalizeDownload();
}
void PropagateDownloadFile::localFileContentChecksumComputed(const QByteArray &checksumType, const QByteArray &checksum)
{
if (_item->_checksumHeader == makeChecksumHeader(checksumType, checksum)) {
FileSystem::remove(_tmpFile.fileName());
updateMetadata(false);
return;
}
finalizeDownload();
}
void PropagateDownloadFile::finalizeDownload()
{
if (_isEncrypted) {
if (_downloadEncryptedHelper->decryptFile(_tmpFile)) {
downloadFinished();
} else {
done(SyncFileItem::NormalError, _downloadEncryptedHelper->errorString());
}
} else {
downloadFinished();
}

View file

@ -230,6 +230,10 @@ private slots:
void transmissionChecksumValidated(const QByteArray &checksumType, const QByteArray &checksum);
/// Called when the download's checksum computation is done
void contentChecksumComputed(const QByteArray &checksumType, const QByteArray &checksum);
/// Called when the local file's checksum computation is done
void localFileContentChecksumComputed(const QByteArray &checksumType, const QByteArray &checksum);
void finalizeDownload();
void downloadFinished();
/// Called when it's time to update the db metadata
void updateMetadata(bool isConflict);

View file

@ -599,6 +599,42 @@ private slots:
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
}
void testEtagChangeFileNotChangedGeneratesNoConflicts()
{
FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
ItemCompletedSpy completeSpy(fakeFolder);
fakeFolder.remoteModifier().insert("A/fake_conflict", 'W');
QVERIFY(fakeFolder.syncOnce());
QVERIFY(!itemConflict(completeSpy, "A/fake_conflict"));
completeSpy.clear();
fakeFolder.remoteModifier().setContents("A/fake_conflict", 'W');
fakeFolder.localModifier().setContents("A/fake_conflict", 'W');
QVERIFY(fakeFolder.syncOnce());
QVERIFY(!itemConflict(completeSpy, "A/fake_conflict"));
}
void testEtagChangeFileChangedGeneratesConflicts()
{
FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
ItemCompletedSpy completeSpy(fakeFolder);
fakeFolder.remoteModifier().insert("A/real_conflict", 'W');
QVERIFY(fakeFolder.syncOnce());
QVERIFY(!itemConflict(completeSpy, "A/real_conflict"));
completeSpy.clear();
fakeFolder.remoteModifier().setContents("A/real_conflict", 'W');
fakeFolder.localModifier().setContents("A/real_conflict", 'L');
QVERIFY(fakeFolder.syncOnce());
QVERIFY(itemConflict(completeSpy, "A/real_conflict"));
}
// Test what happens if we remove entries both on the server, and locally
void testRemoveRemove()
{