Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 31 additions & 55 deletions src/codex/DiffViewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,31 +241,6 @@ QStringList stringListSetting(const QString &key) {
return result;
}

QByteArray fingerprint(const GitDiffSnapshot &snapshot) {
QByteArray value = snapshot.repositoryRoot.toUtf8();
value += '\0';
value += snapshot.error.toUtf8();
value += static_cast<char>(snapshot.scope);
value += static_cast<char>(snapshot.context);
value += snapshot.repository ? '\1' : '\0';
value += snapshot.truncated ? '\1' : '\0';
for (const GitDiffFile &file : snapshot.files) {
value += '\0';
value += file.repositoryRoot.toUtf8();
value += '\0';
value += file.path.toUtf8();
value += '\0';
value += file.absolutePath.toUtf8();
value += '\0';
value += file.previousPath.toUtf8();
value += '\0';
value += file.status.toUtf8();
value += '\0';
value += file.patch.toUtf8();
}
return QCryptographicHash::hash(value, QCryptographicHash::Sha256);
}

struct SideBySideText {
QString left;
QString right;
Expand Down Expand Up @@ -439,7 +414,7 @@ class GitDiffReviewWindow final : public QDialog {
reload();
});
connect(provider, &GitDiffProvider::loadingChanged, this, [this](bool value) {
if (value && snapshot.files.empty())
if (value && (!snapshot || snapshot->files.empty()))
subtitle->setText(QStringLiteral("Loading repository changes…"));
});
connect(provider, &GitDiffProvider::snapshotReady, this,
Expand Down Expand Up @@ -494,10 +469,8 @@ class GitDiffReviewWindow final : public QDialog {
}

void apply(const GitDiffSnapshot &value) {
const QByteArray nextFingerprint = fingerprint(value);
if (nextFingerprint == snapshotFingerprint)
if (snapshot && *snapshot == value)
return;
snapshotFingerprint = nextFingerprint;
snapshot = value;
subtitle->setText(value.error.isEmpty()
? QStringLiteral("%1 | %2")
Expand Down Expand Up @@ -532,11 +505,12 @@ class GitDiffReviewWindow final : public QDialog {

void renderSelected() {
const int index = reviewFiles->currentRow();
if (index < 0 || static_cast<std::size_t>(index) >= snapshot.files.size())
if (!snapshot || index < 0 ||
static_cast<std::size_t>(index) >= snapshot->files.size())
return;
const GitDiffFile &file = snapshot.files[static_cast<std::size_t>(index)];
const GitDiffFile &file = snapshot->files[static_cast<std::size_t>(index)];
requestedPath = file.absolutePath;
title->setText(fileTitle(file, snapshot.repositoryRoots.size() > 1));
title->setText(fileTitle(file, snapshot->repositoryRoots.size() > 1));
const QString content = file.patch.isEmpty()
? QStringLiteral("No textual patch is available for this file.")
: file.patch;
Expand All @@ -550,7 +524,7 @@ class GitDiffReviewWindow final : public QDialog {
}

GitDiffProvider *provider = nullptr;
GitDiffSnapshot snapshot;
std::optional<GitDiffSnapshot> snapshot;
QString workspace;
QStringList commandDirectories;
QStringList changedPaths;
Expand All @@ -559,7 +533,6 @@ class GitDiffReviewWindow final : public QDialog {
QString requestedPath;
GitDiffScope scope = GitDiffScope::Unstaged;
GitDiffContext context = GitDiffContext::Compact;
QByteArray snapshotFingerprint;
QLabel *title = nullptr;
QLabel *subtitle = nullptr;
QListWidget *reviewFiles = nullptr;
Expand Down Expand Up @@ -681,7 +654,9 @@ DiffViewer::DiffViewer(QWidget *parent) : QWidget(parent) {
scopeValue(scope), GitDiffContext::Compact);
});
connect(provider, &GitDiffProvider::loadingChanged, this, [this](bool loading) {
if (loading && snapshot.files.empty() && snapshot.error.isEmpty()) {
if (loading &&
(!snapshot ||
(snapshot->files.empty() && snapshot->error.isEmpty()))) {
summary->setText(QStringLiteral("Loading changes…"));
}
});
Expand Down Expand Up @@ -754,16 +729,16 @@ void DiffViewer::setRepositoryContext(QString nextThreadId,
selectedRepository =
QSettings().value(base + QStringLiteral("/selected")).toString();
}
snapshot = {};
snapshot.reset();
updateFileWatches();
snapshotFingerprint.clear();
files->clear();
diff->clear();
refreshRepository();
}

const GitDiffSnapshot &DiffViewer::currentSnapshot() const noexcept {
return snapshot;
static const GitDiffSnapshot empty;
return snapshot ? *snapshot : empty;
}

void DiffViewer::refreshRepository() {
Expand All @@ -784,19 +759,17 @@ QStringList DiffViewer::repositoryCandidates() const {

QString DiffViewer::selectedPath() const {
const int index = files->currentRow();
return index >= 0 && static_cast<std::size_t>(index) < snapshot.files.size()
? snapshot.files[static_cast<std::size_t>(index)].absolutePath
: QString{};
if (!snapshot || index < 0 ||
static_cast<std::size_t>(index) >= snapshot->files.size())
return {};
return snapshot->files[static_cast<std::size_t>(index)].absolutePath;
}

void DiffViewer::applySnapshot(const GitDiffSnapshot &value) {
const QByteArray nextFingerprint = fingerprint(value);
if (nextFingerprint == snapshotFingerprint) {
snapshot = value;
if (snapshot && *snapshot == value) {
updateFileWatches();
return;
}
snapshotFingerprint = nextFingerprint;
const QString previous = selectedPath();
const int previousScroll = diff->verticalScrollBar()->value();
snapshot = value;
Expand Down Expand Up @@ -882,13 +855,15 @@ void DiffViewer::applySnapshot(const GitDiffSnapshot &value) {

void DiffViewer::updateFileWatches() {
QStringList desired;
for (const GitDiffFile &file : snapshot.files) {
const QFileInfo info(file.absolutePath);
if (info.exists())
desired.push_back(info.absoluteFilePath());
const QString parent = info.absolutePath();
if (!parent.isEmpty() && QFileInfo(parent).isDir())
desired.push_back(parent);
if (snapshot) {
for (const GitDiffFile &file : snapshot->files) {
const QFileInfo info(file.absolutePath);
if (info.exists())
desired.push_back(info.absoluteFilePath());
const QString parent = info.absolutePath();
if (!parent.isEmpty() && QFileInfo(parent).isDir())
desired.push_back(parent);
}
}
desired.removeDuplicates();
const QStringList existing = fileWatcher->files() + fileWatcher->directories();
Expand All @@ -910,14 +885,15 @@ void DiffViewer::updateFileWatches() {

void DiffViewer::showSelectedFile() {
const int index = files->currentRow();
if (index < 0 || static_cast<std::size_t>(index) >= snapshot.files.size()) {
if (!snapshot || index < 0 ||
static_cast<std::size_t>(index) >= snapshot->files.size()) {
selectedFile->setText(QStringLiteral("Select a changed file"));
diff->clear();
return;
}
const GitDiffFile &file = snapshot.files[static_cast<std::size_t>(index)];
const GitDiffFile &file = snapshot->files[static_cast<std::size_t>(index)];
selectedFile->setText(
fileTitle(file, snapshot.repositoryRoots.size() > 1));
fileTitle(file, snapshot->repositoryRoots.size() > 1));
diff->setPlainText(file.patch.isEmpty()
? QStringLiteral("No textual patch is available for this file.")
: file.patch);
Expand Down
5 changes: 3 additions & 2 deletions src/codex/DiffViewer.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <QStringList>
#include <QWidget>

#include <optional>

class QComboBox;
class QFileSystemWatcher;
class QLabel;
Expand Down Expand Up @@ -49,8 +51,7 @@ class DiffViewer final : public QWidget {
QStringList changedPaths;
QStringList persistedRepositoryRoots;
QString selectedRepository;
GitDiffSnapshot snapshot;
QByteArray snapshotFingerprint;
std::optional<GitDiffSnapshot> snapshot;
QComboBox *scope = nullptr;
QComboBox *repositories = nullptr;
QPushButton *hiddenRepositories = nullptr;
Expand Down
4 changes: 4 additions & 0 deletions src/codex/GitDiffProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ struct GitDiffFile {
int additions = 0;
int deletions = 0;
bool binary = false;

bool operator==(const GitDiffFile &) const = default;
};

struct GitDiffSnapshot {
Expand All @@ -39,6 +41,8 @@ struct GitDiffSnapshot {
std::vector<GitDiffFile> files;
bool repository = false;
bool truncated = false;

bool operator==(const GitDiffSnapshot &) const = default;
};

class GitDiffProvider final : public QObject {
Expand Down
Loading