Support deleting remote branches via the delete button
The delete button and context menu action now detect whether the selected branch is remote (tracked via Qt::UserRole on list items). Remote branches are deleted with `git push --delete <remote> <branch>` with an appropriate confirmation dialog warning about server-side removal. Local branches continue using `git branch -D`.
This commit is contained in:
parent
3642f8b743
commit
7dabd4b9e6
|
|
@ -836,6 +836,7 @@ void GitPlusPlusView::onBranchFinished(int exitCode, QProcess::ExitStatus)
|
||||||
if (exitCode == 0) {
|
if (exitCode == 0) {
|
||||||
QByteArray output = proc->readAllStandardOutput();
|
QByteArray output = proc->readAllStandardOutput();
|
||||||
m_allBranches.clear();
|
m_allBranches.clear();
|
||||||
|
m_remoteBranches.clear();
|
||||||
QString current;
|
QString current;
|
||||||
|
|
||||||
const auto lines = output.split('\n');
|
const auto lines = output.split('\n');
|
||||||
|
|
@ -849,17 +850,25 @@ void GitPlusPlusView::onBranchFinished(int exitCode, QProcess::ExitStatus)
|
||||||
// Skip HEAD pointer in remotes
|
// Skip HEAD pointer in remotes
|
||||||
if (branch.contains(QStringLiteral(" -> "))) continue;
|
if (branch.contains(QStringLiteral(" -> "))) continue;
|
||||||
// Strip "remotes/" prefix for display (show as origin/foo)
|
// Strip "remotes/" prefix for display (show as origin/foo)
|
||||||
if (branch.startsWith(QStringLiteral("remotes/")))
|
bool isRemote = false;
|
||||||
|
if (branch.startsWith(QStringLiteral("remotes/"))) {
|
||||||
branch = branch.mid(8); // len("remotes/") == 8
|
branch = branch.mid(8); // len("remotes/") == 8
|
||||||
|
isRemote = true;
|
||||||
|
}
|
||||||
// Deduplicate: if local branch matches a remote, skip the remote
|
// Deduplicate: if local branch matches a remote, skip the remote
|
||||||
if (!m_allBranches.contains(branch))
|
if (!m_allBranches.contains(branch)) {
|
||||||
m_allBranches.append(branch);
|
m_allBranches.append(branch);
|
||||||
|
if (isRemote)
|
||||||
|
m_remoteBranches.append(branch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update branch list widget
|
// Update branch list widget
|
||||||
m_branchList->clear();
|
m_branchList->clear();
|
||||||
for (const auto &b : m_allBranches) {
|
for (const auto &b : m_allBranches) {
|
||||||
auto *item = new QListWidgetItem(b, m_branchList);
|
auto *item = new QListWidgetItem(b, m_branchList);
|
||||||
|
// Mark remote branches (those that came from remotes/ prefix)
|
||||||
|
item->setData(Qt::UserRole, m_remoteBranches.contains(b));
|
||||||
if (b == current) {
|
if (b == current) {
|
||||||
item->setText(QStringLiteral("* ") + b);
|
item->setText(QStringLiteral("* ") + b);
|
||||||
QFont f = item->font();
|
QFont f = item->font();
|
||||||
|
|
@ -1202,26 +1211,62 @@ void GitPlusPlusView::deleteBranch()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (QMessageBox::question(m_toolView, QStringLiteral("Delete Branch"),
|
// Detect if this is a remote branch via the UserRole flag
|
||||||
QStringLiteral("Delete branch '%1'?").arg(branch),
|
auto *item = m_branchList->currentItem();
|
||||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
|
bool isRemote = item && item->data(Qt::UserRole).toBool();
|
||||||
return;
|
|
||||||
|
|
||||||
// Use -D for force delete (handles unmerged branches)
|
if (isRemote) {
|
||||||
auto *proc = gitProcess({QStringLiteral("branch"), QStringLiteral("-D"), branch});
|
// Remote branch: extract remote name and branch name (e.g. "origin/feature" -> "origin", "feature")
|
||||||
if (!proc) return;
|
int sep = branch.indexOf(QLatin1Char('/'));
|
||||||
connect(proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
if (sep <= 0) {
|
||||||
this, [this, proc, branch](int exitCode, QProcess::ExitStatus) {
|
setMessage(QStringLiteral("Cannot determine remote for branch: ") + branch, true);
|
||||||
if (exitCode == 0) {
|
return;
|
||||||
setMessage(QStringLiteral("Deleted branch: ") + branch);
|
|
||||||
} else {
|
|
||||||
QString err = QString::fromUtf8(proc->readAllStandardError()).trimmed();
|
|
||||||
setMessage(QStringLiteral("Delete failed: ") + err, true);
|
|
||||||
}
|
}
|
||||||
proc->deleteLater();
|
QString remote = branch.left(sep);
|
||||||
refreshAll();
|
QString remoteBranch = branch.mid(sep + 1);
|
||||||
});
|
|
||||||
proc->start();
|
if (QMessageBox::question(m_toolView, QStringLiteral("Delete Remote Branch"),
|
||||||
|
QStringLiteral("Delete remote branch '%1' from '%2'?\n\nThis will remove it from the remote server.").arg(remoteBranch, remote),
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto *proc = gitProcess({QStringLiteral("push"), QStringLiteral("--delete"), remote, remoteBranch});
|
||||||
|
if (!proc) return;
|
||||||
|
connect(proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
||||||
|
this, [this, proc, branch](int exitCode, QProcess::ExitStatus) {
|
||||||
|
if (exitCode == 0) {
|
||||||
|
setMessage(QStringLiteral("Deleted remote branch: ") + branch);
|
||||||
|
} else {
|
||||||
|
QString err = QString::fromUtf8(proc->readAllStandardError()).trimmed();
|
||||||
|
setMessage(QStringLiteral("Delete failed: ") + err, true);
|
||||||
|
}
|
||||||
|
proc->deleteLater();
|
||||||
|
refreshAll();
|
||||||
|
});
|
||||||
|
proc->start();
|
||||||
|
} else {
|
||||||
|
// Local branch
|
||||||
|
if (QMessageBox::question(m_toolView, QStringLiteral("Delete Branch"),
|
||||||
|
QStringLiteral("Delete local branch '%1'?").arg(branch),
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Use -D for force delete (handles unmerged branches)
|
||||||
|
auto *proc = gitProcess({QStringLiteral("branch"), QStringLiteral("-D"), branch});
|
||||||
|
if (!proc) return;
|
||||||
|
connect(proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
||||||
|
this, [this, proc, branch](int exitCode, QProcess::ExitStatus) {
|
||||||
|
if (exitCode == 0) {
|
||||||
|
setMessage(QStringLiteral("Deleted branch: ") + branch);
|
||||||
|
} else {
|
||||||
|
QString err = QString::fromUtf8(proc->readAllStandardError()).trimmed();
|
||||||
|
setMessage(QStringLiteral("Delete failed: ") + err, true);
|
||||||
|
}
|
||||||
|
proc->deleteLater();
|
||||||
|
refreshAll();
|
||||||
|
});
|
||||||
|
proc->start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GitPlusPlusView::compareBranch()
|
void GitPlusPlusView::compareBranch()
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,7 @@ private:
|
||||||
QString m_gitDir;
|
QString m_gitDir;
|
||||||
QString m_currentBranch;
|
QString m_currentBranch;
|
||||||
QStringList m_allBranches;
|
QStringList m_allBranches;
|
||||||
|
QStringList m_remoteBranches;
|
||||||
bool m_isDirty = false;
|
bool m_isDirty = false;
|
||||||
QPointer<QProcess> m_remoteProc;
|
QPointer<QProcess> m_remoteProc;
|
||||||
int m_spinnerFrame = 0;
|
int m_spinnerFrame = 0;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue