mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
refactor: remove unused merge methods
This commit is contained in:
parent
cc0530ba46
commit
f7fd3881e3
@ -5615,22 +5615,6 @@ We recommend you use the AppImage available on our downloads page.</source>
|
||||
<source>older entry merged from database "%1"</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Adding backup for older target %1 [%2]</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Adding backup for older source %1 [%2]</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reapplying older target entry on top of newer source %1 [%2]</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reapplying older source entry on top of newer target %1 [%2]</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Synchronizing from newer source %1 [%2]</source>
|
||||
<translation type="unfinished"></translation>
|
||||
|
@ -39,9 +39,6 @@ public:
|
||||
enum MergeMode
|
||||
{
|
||||
Default, // Determine merge strategy from parent or fallback (Synchronize)
|
||||
Duplicate, // lossy strategy regarding deletions, duplicate older changes in a new entry
|
||||
KeepLocal, // merge history forcing local as top regardless of age
|
||||
KeepRemote, // merge history forcing remote as top regardless of age
|
||||
KeepNewer, // merge history
|
||||
Synchronize, // merge history keeping most recent as top entry and applying deletions
|
||||
};
|
||||
|
@ -257,76 +257,6 @@ void Merger::eraseGroup(Group* group)
|
||||
database->setDeletedObjects(deletions);
|
||||
}
|
||||
|
||||
Merger::ChangeList
|
||||
Merger::resolveEntryConflict_Duplicate(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry)
|
||||
{
|
||||
ChangeList changes;
|
||||
const int comparison = compare(targetEntry->timeInfo().lastModificationTime(),
|
||||
sourceEntry->timeInfo().lastModificationTime(),
|
||||
CompareItemIgnoreMilliseconds);
|
||||
// if one entry is newer, create a clone and add it to the group
|
||||
if (comparison < 0) {
|
||||
Entry* clonedEntry = sourceEntry->clone(Entry::CloneNewUuid | Entry::CloneIncludeHistory);
|
||||
moveEntry(clonedEntry, context.m_targetGroup);
|
||||
markOlderEntry(targetEntry);
|
||||
changes << tr("Adding backup for older target %1 [%2]").arg(targetEntry->title(), targetEntry->uuidToHex());
|
||||
} else if (comparison > 0) {
|
||||
Entry* clonedEntry = sourceEntry->clone(Entry::CloneNewUuid | Entry::CloneIncludeHistory);
|
||||
moveEntry(clonedEntry, context.m_targetGroup);
|
||||
markOlderEntry(clonedEntry);
|
||||
changes << tr("Adding backup for older source %1 [%2]").arg(sourceEntry->title(), sourceEntry->uuidToHex());
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
Merger::ChangeList
|
||||
Merger::resolveEntryConflict_KeepLocal(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry)
|
||||
{
|
||||
Q_UNUSED(context);
|
||||
ChangeList changes;
|
||||
const int comparison = compare(targetEntry->timeInfo().lastModificationTime(),
|
||||
sourceEntry->timeInfo().lastModificationTime(),
|
||||
CompareItemIgnoreMilliseconds);
|
||||
if (comparison < 0) {
|
||||
// we need to make our older entry "newer" than the new entry - therefore
|
||||
// we just create a new history entry without any changes - this preserves
|
||||
// the old state before merging the new state and updates the timestamp
|
||||
// the merge takes care, that the newer entry is sorted inbetween both entries
|
||||
// this type of merge changes the database timestamp since reapplying the
|
||||
// old entry is an active change of the database!
|
||||
changes << tr("Reapplying older target entry on top of newer source %1 [%2]")
|
||||
.arg(targetEntry->title(), targetEntry->uuidToHex());
|
||||
Entry* agedTargetEntry = targetEntry->clone(Entry::CloneNoFlags);
|
||||
targetEntry->addHistoryItem(agedTargetEntry);
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
Merger::ChangeList
|
||||
Merger::resolveEntryConflict_KeepRemote(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry)
|
||||
{
|
||||
Q_UNUSED(context);
|
||||
ChangeList changes;
|
||||
const int comparison = compare(targetEntry->timeInfo().lastModificationTime(),
|
||||
sourceEntry->timeInfo().lastModificationTime(),
|
||||
CompareItemIgnoreMilliseconds);
|
||||
if (comparison > 0) {
|
||||
// we need to make our older entry "newer" than the new entry - therefore
|
||||
// we just create a new history entry without any changes - this preserves
|
||||
// the old state before merging the new state and updates the timestamp
|
||||
// the merge takes care, that the newer entry is sorted inbetween both entries
|
||||
// this type of merge changes the database timestamp since reapplying the
|
||||
// old entry is an active change of the database!
|
||||
changes << tr("Reapplying older source entry on top of newer target %1 [%2]")
|
||||
.arg(targetEntry->title(), targetEntry->uuidToHex());
|
||||
targetEntry->beginUpdate();
|
||||
targetEntry->copyDataFrom(sourceEntry);
|
||||
targetEntry->endUpdate();
|
||||
// History item is created by endUpdate since we should have changes
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
Merger::ChangeList Merger::resolveEntryConflict_MergeHistories(const MergeContext& context,
|
||||
const Entry* sourceEntry,
|
||||
Entry* targetEntry,
|
||||
@ -366,38 +296,12 @@ Merger::ChangeList Merger::resolveEntryConflict_MergeHistories(const MergeContex
|
||||
Merger::ChangeList
|
||||
Merger::resolveEntryConflict(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry)
|
||||
{
|
||||
ChangeList changes;
|
||||
// We need to cut off the milliseconds since the persistent format only supports times down to seconds
|
||||
// so when we import data from a remote source, it may represent the (or even some msec newer) data
|
||||
// which may be discarded due to higher runtime precision
|
||||
|
||||
Group::MergeMode mergeMode = m_mode == Group::Default ? context.m_targetGroup->mergeMode() : m_mode;
|
||||
switch (mergeMode) {
|
||||
case Group::Duplicate:
|
||||
changes << resolveEntryConflict_Duplicate(context, sourceEntry, targetEntry);
|
||||
break;
|
||||
|
||||
case Group::KeepLocal:
|
||||
changes << resolveEntryConflict_KeepLocal(context, sourceEntry, targetEntry);
|
||||
changes << resolveEntryConflict_MergeHistories(context, sourceEntry, targetEntry, mergeMode);
|
||||
break;
|
||||
|
||||
case Group::KeepRemote:
|
||||
changes << resolveEntryConflict_KeepRemote(context, sourceEntry, targetEntry);
|
||||
changes << resolveEntryConflict_MergeHistories(context, sourceEntry, targetEntry, mergeMode);
|
||||
break;
|
||||
|
||||
case Group::Synchronize:
|
||||
case Group::KeepNewer:
|
||||
// nothing special to do since resolveEntryConflictMergeHistories takes care to use the newest entry
|
||||
changes << resolveEntryConflict_MergeHistories(context, sourceEntry, targetEntry, mergeMode);
|
||||
break;
|
||||
|
||||
default:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
return changes;
|
||||
return resolveEntryConflict_MergeHistories(context, sourceEntry, targetEntry, mergeMode);
|
||||
}
|
||||
|
||||
bool Merger::mergeHistory(const Entry* sourceEntry, Entry* targetEntry, Group::MergeMode mergeMethod)
|
||||
@ -408,8 +312,8 @@ bool Merger::mergeHistory(const Entry* sourceEntry, Entry* targetEntry, Group::M
|
||||
const int comparison = compare(sourceEntry->timeInfo().lastModificationTime(),
|
||||
targetEntry->timeInfo().lastModificationTime(),
|
||||
CompareItemIgnoreMilliseconds);
|
||||
const bool preferLocal = mergeMethod == Group::KeepLocal || comparison < 0;
|
||||
const bool preferRemote = mergeMethod == Group::KeepRemote || comparison > 0;
|
||||
const bool preferLocal = comparison < 0;
|
||||
const bool preferRemote = comparison > 0;
|
||||
|
||||
QMap<QDateTime, Entry*> merged;
|
||||
for (Entry* historyItem : targetHistoryItems) {
|
||||
|
@ -59,12 +59,6 @@ private:
|
||||
void eraseGroup(Group* group);
|
||||
ChangeList resolveEntryConflict(const MergeContext& context, const Entry* existingEntry, Entry* otherEntry);
|
||||
ChangeList resolveGroupConflict(const MergeContext& context, const Group* existingGroup, Group* otherGroup);
|
||||
Merger::ChangeList
|
||||
resolveEntryConflict_Duplicate(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry);
|
||||
Merger::ChangeList
|
||||
resolveEntryConflict_KeepLocal(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry);
|
||||
Merger::ChangeList
|
||||
resolveEntryConflict_KeepRemote(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry);
|
||||
Merger::ChangeList resolveEntryConflict_MergeHistories(const MergeContext& context,
|
||||
const Entry* sourceEntry,
|
||||
Entry* targetEntry,
|
||||
|
@ -29,13 +29,6 @@ QTEST_GUILESS_MAIN(TestMerge)
|
||||
|
||||
namespace
|
||||
{
|
||||
TimeInfo modificationTime(TimeInfo timeInfo, int years, int months, int days)
|
||||
{
|
||||
const QDateTime time = timeInfo.lastModificationTime();
|
||||
timeInfo.setLastModificationTime(time.addYears(years).addMonths(months).addDays(days));
|
||||
return timeInfo;
|
||||
}
|
||||
|
||||
MockClock* m_clock = nullptr;
|
||||
} // namespace
|
||||
|
||||
@ -258,50 +251,6 @@ void TestMerge::testResolveConflictExisting()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the KeepBoth merge mode.
|
||||
*/
|
||||
void TestMerge::testResolveConflictDuplicate()
|
||||
{
|
||||
QScopedPointer<Database> dbDestination(createTestDatabase());
|
||||
QScopedPointer<Database> dbSource(
|
||||
createTestDatabaseStructureClone(dbDestination.data(), Entry::CloneIncludeHistory, Group::CloneIncludeEntries));
|
||||
|
||||
// sanity check
|
||||
QCOMPARE(dbDestination->rootGroup()->children().at(0)->entries().size(), 2);
|
||||
|
||||
// make this entry newer than in original db
|
||||
QPointer<Entry> updatedDestinationEntry = dbDestination->rootGroup()->children().at(0)->entries().at(0);
|
||||
const TimeInfo initialEntryTimeInfo = updatedDestinationEntry->timeInfo();
|
||||
const TimeInfo updatedEntryTimeInfo = modificationTime(initialEntryTimeInfo, 1, 0, 0);
|
||||
|
||||
updatedDestinationEntry->setTimeInfo(updatedEntryTimeInfo);
|
||||
|
||||
dbDestination->rootGroup()->setMergeMode(Group::MergeMode::Duplicate);
|
||||
|
||||
// Make sure the merge changes have a different timestamp.
|
||||
m_clock->advanceSecond(1);
|
||||
|
||||
Merger merger(dbSource.data(), dbDestination.data());
|
||||
merger.merge();
|
||||
|
||||
// one entry is duplicated because of mode
|
||||
QCOMPARE(dbDestination->rootGroup()->children().at(0)->entries().size(), 3);
|
||||
QCOMPARE(dbDestination->rootGroup()->children().at(0)->entries().at(0)->historyItems().isEmpty(), false);
|
||||
// the older entry was merged from the other db as last in the group
|
||||
QPointer<Entry> newerEntry = dbDestination->rootGroup()->children().at(0)->entries().at(0);
|
||||
QPointer<Entry> olderEntry = dbDestination->rootGroup()->children().at(0)->entries().at(2);
|
||||
QVERIFY(newerEntry->title() == olderEntry->title());
|
||||
QVERIFY2(!newerEntry->attributes()->hasKey("merged"), "newer entry is not marked with an attribute \"merged\"");
|
||||
QVERIFY2(olderEntry->attributes()->hasKey("merged"), "older entry is marked with an attribute \"merged\"");
|
||||
QCOMPARE(olderEntry->historyItems().isEmpty(), false);
|
||||
QCOMPARE(newerEntry->timeInfo(), updatedEntryTimeInfo);
|
||||
// TODO HNH: this may be subject to discussions since the entry itself is newer but represents an older one
|
||||
// QCOMPARE(olderEntry->timeInfo(), initialEntryTimeInfo);
|
||||
QVERIFY2(olderEntry->uuidToHex() != updatedDestinationEntry->uuidToHex(),
|
||||
"KeepBoth should not reuse the UUIDs when cloning.");
|
||||
}
|
||||
|
||||
void TestMerge::testResolveConflictTemplate(
|
||||
int mergeMode,
|
||||
std::function<void(Database*, const QMap<const char*, QDateTime>&)> verification)
|
||||
@ -733,26 +682,11 @@ void TestMerge::testDeletionConflictEntry_Synchronized()
|
||||
testDeletionConflictTemplate(Group::Synchronize, &TestMerge::assertDeletionNewerOnly);
|
||||
}
|
||||
|
||||
void TestMerge::testDeletionConflictEntry_KeepLocal()
|
||||
{
|
||||
testDeletionConflictTemplate(Group::KeepLocal, &TestMerge::assertDeletionLocalOnly);
|
||||
}
|
||||
|
||||
void TestMerge::testDeletionConflictEntry_KeepRemote()
|
||||
{
|
||||
testDeletionConflictTemplate(Group::KeepRemote, &TestMerge::assertDeletionLocalOnly);
|
||||
}
|
||||
|
||||
void TestMerge::testDeletionConflictEntry_KeepNewer()
|
||||
{
|
||||
testDeletionConflictTemplate(Group::KeepNewer, &TestMerge::assertDeletionLocalOnly);
|
||||
}
|
||||
|
||||
void TestMerge::testDeletionConflictEntry_Duplicate()
|
||||
{
|
||||
testDeletionConflictTemplate(Group::Duplicate, &TestMerge::assertDeletionLocalOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the KeepNewer mode concerning history.
|
||||
*/
|
||||
@ -766,29 +700,6 @@ void TestMerge::testResolveConflictEntry_Synchronize()
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the KeepExisting mode concerning history.
|
||||
*/
|
||||
void TestMerge::testResolveConflictEntry_KeepLocal()
|
||||
{
|
||||
testResolveConflictTemplate(Group::KeepLocal, [](Database* db, const QMap<const char*, QDateTime>& timestamps) {
|
||||
QPointer<Group> mergedRootGroup = db->rootGroup();
|
||||
QPointer<Group> mergedGroup1 = mergedRootGroup->children().at(0);
|
||||
TestMerge::assertUpdateMergedEntry1(mergedGroup1->entries().at(0), timestamps);
|
||||
TestMerge::assertUpdateReappliedEntry2(mergedGroup1->entries().at(1), timestamps);
|
||||
});
|
||||
}
|
||||
|
||||
void TestMerge::testResolveConflictEntry_KeepRemote()
|
||||
{
|
||||
testResolveConflictTemplate(Group::KeepRemote, [](Database* db, const QMap<const char*, QDateTime>& timestamps) {
|
||||
QPointer<Group> mergedRootGroup = db->rootGroup();
|
||||
QPointer<Group> mergedGroup1 = mergedRootGroup->children().at(0);
|
||||
TestMerge::assertUpdateReappliedEntry1(mergedGroup1->entries().at(0), timestamps);
|
||||
TestMerge::assertUpdateMergedEntry2(mergedGroup1->entries().at(1), timestamps);
|
||||
});
|
||||
}
|
||||
|
||||
void TestMerge::testResolveConflictEntry_KeepNewer()
|
||||
{
|
||||
testResolveConflictTemplate(Group::KeepNewer, [](Database* db, const QMap<const char*, QDateTime>& timestamps) {
|
||||
|
@ -35,15 +35,9 @@ private slots:
|
||||
void testResolveGroupConflictOlder();
|
||||
void testMergeNotModified();
|
||||
void testMergeModified();
|
||||
void testResolveConflictDuplicate();
|
||||
void testResolveConflictEntry_Synchronize();
|
||||
void testResolveConflictEntry_KeepLocal();
|
||||
void testResolveConflictEntry_KeepRemote();
|
||||
void testResolveConflictEntry_KeepNewer();
|
||||
void testDeletionConflictEntry_Duplicate();
|
||||
void testDeletionConflictEntry_Synchronized();
|
||||
void testDeletionConflictEntry_KeepLocal();
|
||||
void testDeletionConflictEntry_KeepRemote();
|
||||
void testDeletionConflictEntry_KeepNewer();
|
||||
void testMoveEntry();
|
||||
void testMoveEntryPreserveChanges();
|
||||
|
Loading…
Reference in New Issue
Block a user