Fix branch context menu using wrong branch for Create Worktree

Capture the right-clicked branch in lambdas at menu-build time instead
of relying on currentItem() at action execution time, which could shift
due to auto-refresh or filter interactions.
This commit is contained in:
Levi Neely 2026-07-16 11:25:45 +02:00
parent cbbb06bd53
commit 7098d70b40
1 changed files with 47 additions and 9 deletions

View File

@ -1514,19 +1514,57 @@ void GitPlusPlusView::branchContextMenu(const QPoint &pos)
m_branchList->setCurrentItem(item);
QString branch = selectedBranch();
if (branch.isEmpty()) return;
QMenu menu;
menu.addAction(QStringLiteral("Copy branch name"), this, [this]() {
QString branch = selectedBranch();
if (!branch.isEmpty())
QApplication::clipboard()->setText(branch);
menu.addAction(QStringLiteral("Copy branch name"), this, [branch]() {
QApplication::clipboard()->setText(branch);
});
menu.addSeparator();
menu.addAction(QStringLiteral("Checkout"), this, &GitPlusPlusView::checkoutBranch);
menu.addAction(QStringLiteral("Compare with %1").arg(m_currentBranch), this, &GitPlusPlusView::compareBranch);
menu.addAction(QStringLiteral("Create worktree"), this, &GitPlusPlusView::createWorktree);
menu.addAction(QStringLiteral("Checkout"), this, [this]() { checkoutBranch(); });
menu.addAction(QStringLiteral("Compare with %1").arg(m_currentBranch), this, [this]() { compareBranch(); });
menu.addAction(QStringLiteral("Create worktree"), this, [this, branch]() {
// Use the captured branch directly — don't rely on currentItem()
if (branch.isEmpty()) return;
QDir repoDir(m_gitDir);
QString repoName = repoDir.dirName();
QDir parentDir(m_gitDir);
parentDir.cdUp();
QString branchDir = branch;
branchDir.replace(QLatin1Char('/'), QLatin1Char('-'));
QString worktreePath = parentDir.absoluteFilePath(repoName + QLatin1Char('.') + branchDir);
if (QFileInfo::exists(worktreePath)) {
setMessage(QStringLiteral("Directory already exists: ") + worktreePath, true);
return;
}
auto *proc = gitProcess({QStringLiteral("worktree"), QStringLiteral("add"), worktreePath, branch});
if (!proc) return;
connect(proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, [this, proc, worktreePath](int exitCode, QProcess::ExitStatus) {
if (exitCode == 0) {
QFile kateProject(worktreePath + QStringLiteral("/.kateproject"));
if (!QFileInfo::exists(kateProject.fileName())) {
if (kateProject.open(QIODevice::WriteOnly | QIODevice::Text)) {
kateProject.write("{\n \"name\": \"" + QFileInfo(worktreePath).fileName().toUtf8() + "\",\n \"files\": [ { \"git\": true } ]\n}\n");
kateProject.close();
}
}
setMessage(QStringLiteral("Worktree created: ") + worktreePath);
} else {
QString err = QString::fromUtf8(proc->readAllStandardError()).trimmed();
setMessage(QStringLiteral("Worktree failed: ") + err, true);
}
proc->deleteLater();
refreshAll();
});
proc->start();
});
if (branch != m_currentBranch)
menu.addAction(QStringLiteral("Delete"), this, &GitPlusPlusView::deleteBranch);
menu.addAction(QStringLiteral("Delete"), this, [this]() { deleteBranch(); });
// "Soft Reset to Merge Base" — available when the selected branch is an ancestor of HEAD
// (i.e., current branch was forked from the selected branch)
@ -1539,7 +1577,7 @@ void GitPlusPlusView::branchContextMenu(const QPoint &pos)
QString head = QString::fromUtf8(headHash).trimmed();
if (mergeBaseHash != head) {
menu.addSeparator();
menu.addAction(QStringLiteral("Soft Reset to Merge Base"), this, [this, branch, mergeBaseHash]() {
menu.addAction(QStringLiteral("Soft Reset to Merge Base"), this, [this, mergeBaseHash]() {
auto *proc = gitProcess({QStringLiteral("reset"), QStringLiteral("--soft"), mergeBaseHash});
if (!proc) return;
connect(proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),