#3296 libgit2: start with diff implementation
Some checks are pending
🏗️ Build QOwnNotes for Nix / 🏗️ Build nix-build on macos-14 (push) Waiting to run
🏗️ Build QOwnNotes for Nix / 🏗️ Build nix-build on macos-latest (push) Waiting to run
🏗️ Build QOwnNotes for Nix / 🏗️ Build nix-build on ubuntu-latest (push) Waiting to run
🏗️ Build QOwnNotes for Nix / 🏗️ Build nix-build-cmake-qt5 on macos-14 (push) Waiting to run
🏗️ Build QOwnNotes for Nix / 🏗️ Build nix-build-cmake-qt5 on macos-latest (push) Waiting to run
🏗️ Build QOwnNotes for Nix / 🏗️ Build nix-build-cmake-qt5 on ubuntu-latest (push) Waiting to run
Build QOwnNotes / build (false, macos-latest, 5.13.2) (push) Waiting to run
Build QOwnNotes / build (false, macos-latest, 5.14.2) (push) Waiting to run
Build QOwnNotes / build (false, macos-latest, 5.15.2) (push) Waiting to run
Build QOwnNotes / build (false, macos-latest, 5.9.9) (push) Waiting to run
Build QOwnNotes / build (false, ubuntu-22.04, 5.15.2) (push) Waiting to run
Build QOwnNotes / build (false, ubuntu-latest, 5.13.2) (push) Waiting to run
Build QOwnNotes / build (false, ubuntu-latest, 5.14.2) (push) Waiting to run
Build QOwnNotes / build (false, ubuntu-latest, 5.15.2) (push) Waiting to run
Build QOwnNotes / build (false, ubuntu-latest, 6.2.4) (push) Waiting to run
Build QOwnNotes / build (false, ubuntu-latest, 6.4.3) (push) Waiting to run
Build QOwnNotes / build (false, ubuntu-latest, 6.5.3) (push) Waiting to run
Build QOwnNotes / build (false, ubuntu-latest, 6.6.3) (push) Waiting to run
Build QOwnNotes / build (false, windows-2019, 5.13.2) (push) Waiting to run
Build QOwnNotes / build (false, windows-2019, 5.14.2) (push) Waiting to run
Build QOwnNotes / build (false, windows-2019, 5.15.2) (push) Waiting to run
Build QOwnNotes / build (false, windows-2019, 6.6.3) (push) Waiting to run
Build QOwnNotes / build (true, macos-latest, 6.2.4) (push) Waiting to run
Build QOwnNotes / build (true, macos-latest, 6.4.3) (push) Waiting to run
Build QOwnNotes / build (true, macos-latest, 6.5.3) (push) Waiting to run
Build QOwnNotes / build (true, macos-latest, 6.6.3) (push) Waiting to run
📄 Check formatting / 📄 Check code formatting with "just fmt" (push) Waiting to run

Signed-off-by: Patrizio Bekerle <patrizio@bekerle.com>
This commit is contained in:
Patrizio Bekerle 2025-06-24 20:41:36 +02:00
parent 349a31a1ac
commit cbf30b403c
No known key found for this signature in database
GPG key ID: 75960E6926556207
4 changed files with 134 additions and 0 deletions

View file

@ -108,6 +108,7 @@
#include "dialogs/storedattachmentsdialog.h"
#include "dialogs/storedimagesdialog.h"
#include "dialogs/tododialog.h"
#include "dialogs/versiondialog.h"
#include "entities/calendaritem.h"
#include "helpers/qownnotesmarkdownhighlighter.h"
#include "libraries/fakevim/fakevim/fakevimactions.h"
@ -6416,6 +6417,13 @@ void MainWindow::on_actionShow_versions_triggered() {
return;
}
auto versions = Utils::Git::getNoteVersions(currentNote);
qDebug() << __func__ << " - 'versions': " << Utils::Misc::jsValueToJsonString(versions);
// VersionDialog *dialog = new VersionDialog(versions);
// dialog->exec();
// return;
ui->actionShow_versions->setDisabled(true);
showStatusBarMessage(
Utils::Misc::replaceOwnCloudText(tr("Note versions are currently loaded from your ownCloud "

View file

@ -1261,6 +1261,8 @@ void OwnCloudService::handleVersionsLoading(QString data) {
}
#ifndef INTEGRATION_TESTS
qDebug() << __func__ << " - 'versions': " << Utils::Misc::jsValueToJsonString(versions);
VersionDialog *dialog = new VersionDialog(versions);
dialog->exec();
#endif

View file

@ -26,6 +26,10 @@
#ifdef USE_LIBGIT2
#include <git2.h>
#include <QJSEngine>
#include "diff_match_patch.h"
#endif
/**
@ -304,4 +308,117 @@ bool Utils::Git::commitAll(const QString &path, const QString &message) {
qDebug() << "Created commit in" << path;
return true;
}
/**
* Gets the note versions from the Git repository
*
* We want to get something like this:
* [
* {
* "timestamp": 1750925008,
* "humanReadableTimestamp": "2 minutes ago",
* "diffHtml": "Version test\n============\n\n- new<del>\n- new2</del>",
* "data": "Version test\n============\n\n- new"
* },
* {
* "timestamp": 1750924988,
* "humanReadableTimestamp": "2 minutes ago",
* "diffHtml": "Version test\n============\n\n<del>- new\n- new2</del>",
* "data": "Version test\n============\n\n"
* }
* ]
*
* @param note
* @return
*/
QJSValue Utils::Git::getNoteVersions(const Note &note) {
QJSEngine engine;
QJSValue versions = engine.newArray();
if (!note.exists()) {
// Return an empty array if note does not exist
return versions;
}
// Get the Git repository
git_repository *repo = nullptr;
QString noteFolderPath = NoteFolder::currentLocalPath();
if (git_repository_open(&repo, noteFolderPath.toUtf8().constData()) != 0) {
return versions;
}
// Get the file path relative to the repository root
QString relativePath = note.relativeNoteFilePath();
qDebug() << __func__ << " - 'relativePath': " << relativePath;
// Create a diff match patch instance for showing differences
diff_match_patch differ;
// Get all commits that modified this file
git_revwalk *walker;
git_revwalk_new(&walker, repo);
git_revwalk_push_head(walker);
git_oid oid;
QString previousContent;
bool isFirst = true;
int versionIndex = 0;
while (git_revwalk_next(&oid, walker) == 0) {
git_commit *commit;
if (git_commit_lookup(&commit, repo, &oid) == 0) {
git_tree *tree;
if (git_commit_tree(&tree, commit) == 0) {
git_tree_entry *entry = nullptr;
if (git_tree_entry_bypath(&entry, tree, relativePath.toUtf8().constData()) == 0) {
git_blob *blob = nullptr;
if (git_blob_lookup(&blob, repo, git_tree_entry_id(entry)) == 0) {
const char *content = (const char *)git_blob_rawcontent(blob);
QString currentContent = QString::fromUtf8(content);
QJSValue version = engine.newObject();
// Get commit timestamp
git_time_t timestamp = git_commit_time(commit);
QDateTime datetime = QDateTime::fromSecsSinceEpoch(timestamp);
qDebug() << __func__ << " - 'datetime': " << datetime;
version.setProperty("timestamp",
engine.toScriptValue(static_cast<qint64>(timestamp)));
version.setProperty("humanReadableTimestamp",
datetime.toString(QLocale::system().dateTimeFormat(
QLocale::ShortFormat)));
// Store the content
version.setProperty("data", currentContent);
// Generate diff HTML if not the first version
if (!isFirst) {
QList<Diff> diffs = differ.diff_main(currentContent, previousContent);
differ.diff_cleanupSemantic(diffs);
QString diffHtml = differ.diff_prettyHtml(diffs);
version.setProperty("diffHtml", diffHtml);
} else {
version.setProperty("diffHtml", "");
isFirst = false;
}
previousContent = currentContent;
versions.setProperty(versionIndex++, version);
// versionsArray.setProperty(versionsArray.property("length").toInt(),
// version);
git_blob_free(blob);
}
git_tree_entry_free(entry);
}
git_tree_free(tree);
}
git_commit_free(commit);
}
}
git_revwalk_free(walker);
git_repository_free(repo);
return versions;
}
#endif

View file

@ -17,6 +17,12 @@
#include <QProcess>
#include <QString>
#ifdef USE_LIBGIT2
#include <QJSValue>
#include "entities/note.h"
#endif
/* Git functions that can be useful */
namespace Utils {
@ -33,6 +39,7 @@ bool isCurrentNoteFolderUseGit();
#ifdef USE_LIBGIT2
bool initRepository(const QString& path);
bool commitAll(const QString& path, const QString& message);
QJSValue getNoteVersions(const Note& note);
#endif
} // namespace Git
} // namespace Utils