Introduce synchronize merge method

* Create history-based merging that keeps older data in history instead of discarding or deleting it
* Extract merge logic into the Merger class
* Allows special merge behavior
* Improve handling of deletion and changes on groups
* Enable basic change tracking while merging
* Prevent unintended timestamp changes while merging
* Handle differences in timestamp precision
* Introduce comparison operators to allow for more sophisticated comparisons (ignore special properties, ...)
* Introduce Clock class to handle datetime across the app

Merge Strategies:
* Default (use inherited/fallback method)
* Duplicate (duplicate conflicting nodes, apply all deletions)
* KeepLocal (use local values, but apply all deletions)
* KeepRemote (use remote values, but apply all deletions)
* KeepNewer (merge history only)
* Synchronize (merge history, newest value stays on top, apply all deletions)
This commit is contained in:
Jonathan White 2018-09-30 08:45:06 -04:00 committed by Jonathan White
parent b40e5686dc
commit c1e9f45df9
43 changed files with 2777 additions and 585 deletions

View file

@ -18,6 +18,7 @@
#include "TestGroup.h"
#include "TestGlobal.h"
#include "stub/TestClock.h"
#include <QSignalSpy>
@ -26,6 +27,11 @@
QTEST_GUILESS_MAIN(TestGroup)
namespace
{
TestClock* m_clock = nullptr;
}
void TestGroup::initTestCase()
{
qRegisterMetaType<Entry*>("Entry*");
@ -33,6 +39,19 @@ void TestGroup::initTestCase()
QVERIFY(Crypto::init());
}
void TestGroup::init()
{
Q_ASSERT(m_clock == nullptr);
m_clock = new TestClock(2010, 5, 5, 10, 30, 10);
TestClock::setup(m_clock);
}
void TestGroup::cleanup()
{
TestClock::teardown();
m_clock = nullptr;
}
void TestGroup::testParenting()
{
Database* db = new Database();
@ -389,7 +408,7 @@ void TestGroup::testClone()
QVERIFY(clonedGroupNewUuid->uuid() != originalGroup->uuid());
// Making sure the new modification date is not the same.
QTest::qSleep(1);
m_clock->advanceSecond(1);
QScopedPointer<Group> clonedGroupResetTimeInfo(
originalGroup->clone(Entry::CloneNoFlags, Group::CloneNewUuid | Group::CloneResetTimeInfo));
@ -474,7 +493,7 @@ void TestGroup::testFindEntry()
Entry* entry;
entry = db->rootGroup()->findEntry(entry1->uuid().toRfc4122().toHex());
entry = db->rootGroup()->findEntry(entry1->uuidToHex());
QVERIFY(entry != nullptr);
QCOMPARE(entry->title(), QString("entry1"));
@ -491,7 +510,7 @@ void TestGroup::testFindEntry()
entry = db->rootGroup()->findEntry(QString("//entry1"));
QVERIFY(entry == nullptr);
entry = db->rootGroup()->findEntry(entry2->uuid().toRfc4122().toHex());
entry = db->rootGroup()->findEntry(entry2->uuidToHex());
QVERIFY(entry != nullptr);
QCOMPARE(entry->title(), QString("entry2"));