diff --git a/gitplusplus.cpp b/gitplusplus.cpp index 85879b2..3073f51 100644 --- a/gitplusplus.cpp +++ b/gitplusplus.cpp @@ -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::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::of(&QProcess::finished),