From 3d0882295b0298624cedfb7d91769d3d11a3cdb0 Mon Sep 17 00:00:00 2001 From: Patrizio Bekerle Date: Thu, 13 Feb 2020 16:31:46 +0100 Subject: [PATCH] Automatically remove duplicate conflicted notes.sqlite database files (#1625) --- CHANGELOG.md | 5 +++++ src/mainwindow.cpp | 27 ++++++++++++++++++++------- src/services/databaseservice.cpp | 25 +++++++++++++++++++++++++ src/services/databaseservice.h | 3 ++- src/utils/misc.cpp | 28 ++++++++++++++++++++++++++++ src/utils/misc.h | 2 ++ 6 files changed, 82 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9720276c0c..1c2391aaf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # QOwnNotes Changelog +## 20.2.4 +- conflicted copies of the note folder database `notes.sqlite` are now + immediately deleted if they are not different to the current `notes.sqlite` + (for [#1625](https://github.com/pbek/QOwnNotes/issues/1625)) + ## 20.2.3 - improved Setext-style headers highlighting with leading spaces (for [#101](https://github.com/pbek/qmarkdowntextedit/issues/101), thank you @Waqar144) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9450712913..3706a2d4ea 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3251,9 +3251,28 @@ void MainWindow::removeConflictedNotesDatabaseCopies() { QDirIterator it(NoteFolder::currentLocalPath(), filter, QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot); auto files = QStringList(); + const QSignalBlocker blocker(this->noteDirectoryWatcher); + Q_UNUSED(blocker) + + // we try to fix problems with the blocker + directoryWatcherWorkaround(true); while (it.hasNext()) { - files << it.next(); + const QString &file = it.next(); + + // check if conflicted database copy is the same as the current note + // folder database + if (Utils::Misc::isSameFile( + file, DatabaseService::getNoteFolderDatabasePath())) { + showStatusBarMessage( + tr(QFile::remove(file) + ? "Removed duplicate conflicted database: %1" + : "Could not remove duplicate conflicted database: %1") + .arg(file), + 4000); + } else { + files << file; + } } int count = files.count(); @@ -3276,12 +3295,6 @@ void MainWindow::removeConflictedNotesDatabaseCopies() { return; } - const QSignalBlocker blocker(this->noteDirectoryWatcher); - Q_UNUSED(blocker) - - // we try to fix problems with the blocker - directoryWatcherWorkaround(true); - count = 0; // remove the database files diff --git a/src/services/databaseservice.cpp b/src/services/databaseservice.cpp index e6c156c09e..0bd96b309f 100644 --- a/src/services/databaseservice.cpp +++ b/src/services/databaseservice.cpp @@ -835,3 +835,28 @@ QString DatabaseService::getAppData(const QString& name, return QString(); } + +/** + * WIP + * + * @param path + * @return + */ +bool DatabaseService::mergeNoteFolderDatabase(QString path) { + QSqlDatabase mergeDB = QSqlDatabase::addDatabase( + QStringLiteral("QSQLITE"), QStringLiteral("note_folder_merge")); + mergeDB.setDatabaseName(path); + + if (!mergeDB.open()) { + QMessageBox::critical( + nullptr, QWidget::tr("Cannot open database"), + QWidget::tr("Unable to establish a database connection with " + "note folder database to merge '%1'.\nAre the folder " + "and the file writeable?") + .arg(path), + QMessageBox::Ok); + return false; + } + + return true; +} diff --git a/src/services/databaseservice.h b/src/services/databaseservice.h index 2f62f49d77..ddbd82659b 100644 --- a/src/services/databaseservice.h +++ b/src/services/databaseservice.h @@ -22,11 +22,12 @@ class DatabaseService { static QSqlDatabase getNoteFolderDatabase(); static void closeDatabaseConnection(const QSqlDatabase& db, QSqlQuery& query); + static QString getNoteFolderDatabasePath(); private: - static QString getNoteFolderDatabasePath(); static bool createMemoryConnection(); static bool createDiskConnection(); + static bool mergeNoteFolderDatabase(QString path); }; #endif // DATABASESERVICE_H diff --git a/src/utils/misc.cpp b/src/utils/misc.cpp index d4b39834b9..4bef4808f2 100644 --- a/src/utils/misc.cpp +++ b/src/utils/misc.cpp @@ -1939,3 +1939,31 @@ QString Utils::Misc::localDictionariesPath() { dir.mkpath(path); return path; } + +/** + * Generates a SHA1 signature for a file + * + * @return + */ +QByteArray Utils::Misc::generateFileSha1Signature(const QString &path) { + QCryptographicHash hash(QCryptographicHash::Sha1); + QFile file(path); + + if (file.open(QIODevice::ReadOnly)) { + hash.addData(file.readAll()); + } else { + return QByteArray(); + } + + // retrieve the SHA1 signature of the file + return hash.result(); +} + +/** + * Checks if two files are the same + * + * @return + */ +bool Utils::Misc::isSameFile(const QString &path1, const QString &path2) { + return generateFileSha1Signature(path1) == generateFileSha1Signature(path2); +} diff --git a/src/utils/misc.h b/src/utils/misc.h index 0ee43b277f..422f48a974 100644 --- a/src/utils/misc.h +++ b/src/utils/misc.h @@ -128,6 +128,8 @@ QString remotePreviewImageTagToInlineImageTag(QString imageTag, int &imageWidth); QString createUuidString(); QString localDictionariesPath(); +QByteArray generateFileSha1Signature(const QString &path); +bool isSameFile(const QString &path1, const QString &path2); } // namespace Misc } // namespace Utils