#include "gitdiff.h" #include #include #include #include #include GitDiff::GitDiff(git_commit* a, git_commit* b, GitRepository *repository) : QObject() ,m_repository(repository) { Q_ASSERT_X(m_repository, "GitDiff", "Repository of NULL"); connect(m_repository, &GitRepository::destroyed, this, &GitDiff::deleteLater); readBody(a, b); } GitDiff::~GitDiff() { reset(); } void GitDiff::readBody(git_commit *a, git_commit *b) { git_diff *diff = nullptr; git_tree *aTree = nullptr; git_tree *bTree = nullptr; git_diff_find_options similarityOpts; if(a != nullptr) { git_commit_tree(&aTree, a); } if(b != nullptr) { git_commit_tree(&bTree, b); } git_diff_tree_to_tree(&diff, m_repository->raw(), aTree, bTree, nullptr); git_diff_find_init_options(&similarityOpts, GIT_DIFF_FIND_OPTIONS_VERSION); git_diff_find_similar(diff, &similarityOpts); git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, [](const git_diff_delta *delta, const git_diff_hunk *hunk, const git_diff_line *line, void *payload) -> int { Q_UNUSED(hunk) QString prefix("%2"); QString suffix("
"); GitDiff* diff = static_cast(payload); QString newFileName(delta->new_file.path); QString oldFileName(delta->old_file.path); QString diffData; switch(line->origin) { case GIT_DIFF_LINE_ADDITION: prefix = prefix.arg("#00ff00"); break; case GIT_DIFF_LINE_DELETION: prefix = prefix.arg("#ff0000"); break; case GIT_DIFF_LINE_HUNK_HDR: prefix = "
"; suffix = "
"; break; default: prefix = prefix.arg("#000000").arg(" "); break; } if ( line->origin == GIT_DIFF_LINE_ADDITION || line->origin == GIT_DIFF_LINE_DELETION) { prefix = prefix.arg(line->origin); } if(!diff->m_diffList.contains(newFileName)) { diff->m_diffList.insert(newFileName, QPointer(new DiffModel(newFileName, diff))); } if(line->origin != GIT_DIFF_LINE_FILE_HDR) { //Add line only in case if origin is not file header diffData = QString::fromUtf8(line->content, line->content_len); } else if(delta->status == GIT_DELTA_RENAMED){ //else check the similarity if(delta->similarity == 100) { diffData = QString(oldFileName + " -> " + newFileName); } diff->m_diffList[newFileName]->setSimilarity(delta->similarity); } if(!diffData.isEmpty()) { diff->m_diffList[newFileName]->append(prefix); diff->m_diffList[newFileName]->append(diffData.toHtmlEscaped().replace(" ", " ")); diff->m_diffList[newFileName]->append(suffix); } diff->m_diffList[newFileName]->setType(delta->status); return 0; }, this); git_diff_free(diff); git_tree_free(aTree); git_tree_free(bTree); } void GitDiff::reset() { foreach (QPointer model, m_diffList) { model.clear(); } m_diffList.clear(); } QStringList GitDiff::files() { return m_diffList.keys(); } DiffModel* GitDiff::model(const QString& file) { DiffModel* model = m_diffList.value(file).data(); return model; }