forked from qt-creator/qt-creator
Git: Auto stash for branches
Allow user to handle local changes when switching branches. Task-number: QTCREATORBUG-8417 Change-Id: I62d615aadfbd81c8ae03f3cd292b98773a36e1e7 Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
committed by
Tobias Hunger
parent
7df112b687
commit
81bf2ec154
88
src/plugins/git/branchcheckoutdialog.cpp
Normal file
88
src/plugins/git/branchcheckoutdialog.cpp
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#include "branchcheckoutdialog.h"
|
||||||
|
#include "ui_branchcheckoutdialog.h"
|
||||||
|
|
||||||
|
namespace Git {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
BranchCheckoutDialog::BranchCheckoutDialog(QWidget *parent,
|
||||||
|
const QString& currentBranch,
|
||||||
|
const QString& nextBranch) :
|
||||||
|
QDialog(parent),
|
||||||
|
m_ui(new Ui::BranchCheckoutDialog),
|
||||||
|
m_foundStashForNextBranch(false),
|
||||||
|
m_hasLocalChanges(true)
|
||||||
|
{
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
|
setWindowTitle(tr("Checkout branch \"%1\"").arg(nextBranch));
|
||||||
|
m_ui->moveChangesRadioButton->setText(tr("Move Local Changes to \"%1\"").arg(nextBranch));
|
||||||
|
m_ui->popStashCheckBox->setText(tr("Pop Stash of \"%1\"").arg(nextBranch));
|
||||||
|
|
||||||
|
if (!currentBranch.isEmpty()) {
|
||||||
|
m_ui->makeStashRadioButton->setText(tr("Create Branch Stash for \"%1\"").arg(currentBranch));
|
||||||
|
} else {
|
||||||
|
m_ui->makeStashRadioButton->setText(tr("Create Branch Stash for Current Branch"));
|
||||||
|
foundNoLocalChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(m_ui->moveChangesRadioButton, SIGNAL(toggled(bool)), this, SLOT(updatePopStashCheckBox(bool)));
|
||||||
|
}
|
||||||
|
|
||||||
|
BranchCheckoutDialog::~BranchCheckoutDialog()
|
||||||
|
{
|
||||||
|
delete m_ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BranchCheckoutDialog::foundNoLocalChanges()
|
||||||
|
{
|
||||||
|
m_ui->discardChangesRadioButton->setChecked(true);
|
||||||
|
m_ui->localChangesGroupBox->setEnabled(false);
|
||||||
|
m_hasLocalChanges = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BranchCheckoutDialog::foundStashForNextBranch()
|
||||||
|
{
|
||||||
|
m_ui->popStashCheckBox->setChecked(true);
|
||||||
|
m_ui->popStashCheckBox->setEnabled(true);
|
||||||
|
m_foundStashForNextBranch = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BranchCheckoutDialog::makeStashOfCurrentBranch()
|
||||||
|
{
|
||||||
|
return m_ui->makeStashRadioButton->isChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BranchCheckoutDialog::moveLocalChangesToNextBranch()
|
||||||
|
{
|
||||||
|
return m_ui->moveChangesRadioButton->isChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BranchCheckoutDialog::discardLocalChanges()
|
||||||
|
{
|
||||||
|
return m_ui->discardChangesRadioButton->isChecked() && m_ui->localChangesGroupBox->isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BranchCheckoutDialog::popStashOfNextBranch()
|
||||||
|
{
|
||||||
|
return m_ui->popStashCheckBox->isChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BranchCheckoutDialog::hasStashForNextBranch()
|
||||||
|
{
|
||||||
|
return m_foundStashForNextBranch;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BranchCheckoutDialog::hasLocalChanges()
|
||||||
|
{
|
||||||
|
return m_hasLocalChanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BranchCheckoutDialog::updatePopStashCheckBox(bool moveChangesChecked)
|
||||||
|
{
|
||||||
|
m_ui->popStashCheckBox->setChecked(!moveChangesChecked && m_foundStashForNextBranch);
|
||||||
|
m_ui->popStashCheckBox->setEnabled(!moveChangesChecked && m_foundStashForNextBranch);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Git
|
||||||
|
|
||||||
45
src/plugins/git/branchcheckoutdialog.h
Normal file
45
src/plugins/git/branchcheckoutdialog.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#ifndef BRANCHCHECKOUTDIALOG_H
|
||||||
|
#define BRANCHCHECKOUTDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
namespace Git {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class BranchCheckoutDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BranchCheckoutDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BranchCheckoutDialog(QWidget *parent, const QString& currentBranch,
|
||||||
|
const QString& nextBranch);
|
||||||
|
~BranchCheckoutDialog();
|
||||||
|
|
||||||
|
void foundNoLocalChanges();
|
||||||
|
void foundStashForNextBranch();
|
||||||
|
|
||||||
|
bool makeStashOfCurrentBranch();
|
||||||
|
bool moveLocalChangesToNextBranch();
|
||||||
|
bool discardLocalChanges();
|
||||||
|
bool popStashOfNextBranch();
|
||||||
|
|
||||||
|
bool hasStashForNextBranch();
|
||||||
|
bool hasLocalChanges();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updatePopStashCheckBox(bool moveChangesChecked);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::BranchCheckoutDialog *m_ui;
|
||||||
|
bool m_foundStashForNextBranch;
|
||||||
|
bool m_hasLocalChanges;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Git
|
||||||
|
|
||||||
|
#endif // BRANCHCHECKOUTDIALOG_H
|
||||||
133
src/plugins/git/branchcheckoutdialog.ui
Normal file
133
src/plugins/git/branchcheckoutdialog.ui
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Git::Internal::BranchCheckoutDialog</class>
|
||||||
|
<widget class="QDialog" name="Git::Internal::BranchCheckoutDialog">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::WindowModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>394</width>
|
||||||
|
<height>199</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<property name="modal">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="localChangesGroupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Local Changes Found. Choose Action:</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="makeStashRadioButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>RadioButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="moveChangesRadioButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>RadioButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="discardChangesRadioButton">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Discard Local Changes</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="popStashCheckBox">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>CheckBox</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>discardChangesRadioButton</tabstop>
|
||||||
|
<tabstop>buttonBox</tabstop>
|
||||||
|
</tabstops>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>Git::Internal::BranchCheckoutDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>227</x>
|
||||||
|
<y>219</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>179</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>Git::Internal::BranchCheckoutDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>295</x>
|
||||||
|
<y>219</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>179</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
||||||
@@ -29,9 +29,11 @@
|
|||||||
|
|
||||||
#include "branchdialog.h"
|
#include "branchdialog.h"
|
||||||
#include "branchadddialog.h"
|
#include "branchadddialog.h"
|
||||||
|
#include "branchcheckoutdialog.h"
|
||||||
#include "branchmodel.h"
|
#include "branchmodel.h"
|
||||||
#include "gitclient.h"
|
#include "gitclient.h"
|
||||||
#include "gitplugin.h"
|
#include "gitplugin.h"
|
||||||
|
#include "gitutils.h"
|
||||||
#include "ui_branchdialog.h"
|
#include "ui_branchdialog.h"
|
||||||
#include "stashdialog.h" // Label helpers
|
#include "stashdialog.h" // Label helpers
|
||||||
|
|
||||||
@@ -42,6 +44,7 @@
|
|||||||
#include <QItemSelectionModel>
|
#include <QItemSelectionModel>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
@@ -159,7 +162,59 @@ void BranchDialog::checkout()
|
|||||||
QModelIndex idx = selectedIndex();
|
QModelIndex idx = selectedIndex();
|
||||||
QTC_CHECK(m_model->isLocal(idx));
|
QTC_CHECK(m_model->isLocal(idx));
|
||||||
|
|
||||||
m_model->checkoutBranch(idx);
|
const QString currentBranch = m_model->branchName(m_model->currentBranch());
|
||||||
|
const QString nextBranch = m_model->branchName(idx);
|
||||||
|
const QString popMessageStart = QCoreApplication::applicationName() +
|
||||||
|
QLatin1String(" ") + nextBranch + QLatin1String("-AutoStash ");
|
||||||
|
|
||||||
|
BranchCheckoutDialog branchCheckoutDialog(this, currentBranch, nextBranch);
|
||||||
|
GitClient *gitClient = GitPlugin::instance()->gitClient();
|
||||||
|
|
||||||
|
if (gitClient->gitStatus(m_repository, StatusMode(NoUntracked | NoSubmodules)) != GitClient::StatusChanged)
|
||||||
|
branchCheckoutDialog.foundNoLocalChanges();
|
||||||
|
|
||||||
|
QList<Stash> stashes;
|
||||||
|
gitClient->synchronousStashList(m_repository, &stashes);
|
||||||
|
foreach (const Stash &stash, stashes) {
|
||||||
|
if (stash.message.startsWith(popMessageStart)) {
|
||||||
|
branchCheckoutDialog.foundStashForNextBranch();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!branchCheckoutDialog.hasLocalChanges() &&
|
||||||
|
!branchCheckoutDialog.hasStashForNextBranch()) {
|
||||||
|
// No local changes and no Auto Stash - no need to open dialog
|
||||||
|
m_model->checkoutBranch(idx);
|
||||||
|
} else if (branchCheckoutDialog.exec() == QDialog::Accepted && m_model) {
|
||||||
|
|
||||||
|
QString stashMessage;
|
||||||
|
if (branchCheckoutDialog.makeStashOfCurrentBranch()
|
||||||
|
|| branchCheckoutDialog.moveLocalChangesToNextBranch()) {
|
||||||
|
stashMessage = gitClient->synchronousStash(m_repository, currentBranch + QLatin1String("-AutoStash"));
|
||||||
|
} else if (branchCheckoutDialog.discardLocalChanges()) {
|
||||||
|
gitClient->synchronousReset(m_repository);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_model->checkoutBranch(idx);
|
||||||
|
|
||||||
|
QString stashName;
|
||||||
|
gitClient->synchronousStashList(m_repository, &stashes);
|
||||||
|
foreach (const Stash &stash, stashes) {
|
||||||
|
if (stash.message.startsWith(popMessageStart)) {
|
||||||
|
stashName = stash.name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stashMessage.isEmpty() && branchCheckoutDialog.moveLocalChangesToNextBranch())
|
||||||
|
gitClient->stashPop(m_repository);
|
||||||
|
else if (branchCheckoutDialog.popStashOfNextBranch())
|
||||||
|
gitClient->synchronousStashRestore(m_repository, stashName);
|
||||||
|
|
||||||
|
if (branchCheckoutDialog.hasStashForNextBranch())
|
||||||
|
gitClient->synchronousStashRemove(m_repository, stashName);
|
||||||
|
}
|
||||||
enableButtons();
|
enableButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ HEADERS += gitplugin.h \
|
|||||||
remotedialog.h \
|
remotedialog.h \
|
||||||
branchadddialog.h \
|
branchadddialog.h \
|
||||||
resetdialog.h \
|
resetdialog.h \
|
||||||
mergetool.h
|
mergetool.h \
|
||||||
|
branchcheckoutdialog.h
|
||||||
|
|
||||||
SOURCES += gitplugin.cpp \
|
SOURCES += gitplugin.cpp \
|
||||||
gitclient.cpp \
|
gitclient.cpp \
|
||||||
@@ -52,7 +53,8 @@ SOURCES += gitplugin.cpp \
|
|||||||
remotedialog.cpp \
|
remotedialog.cpp \
|
||||||
branchadddialog.cpp \
|
branchadddialog.cpp \
|
||||||
resetdialog.cpp \
|
resetdialog.cpp \
|
||||||
mergetool.cpp
|
mergetool.cpp \
|
||||||
|
branchcheckoutdialog.cpp
|
||||||
|
|
||||||
FORMS += changeselectiondialog.ui \
|
FORMS += changeselectiondialog.ui \
|
||||||
settingspage.ui \
|
settingspage.ui \
|
||||||
@@ -61,7 +63,8 @@ FORMS += changeselectiondialog.ui \
|
|||||||
stashdialog.ui \
|
stashdialog.ui \
|
||||||
remotedialog.ui \
|
remotedialog.ui \
|
||||||
remoteadditiondialog.ui \
|
remoteadditiondialog.ui \
|
||||||
branchadddialog.ui
|
branchadddialog.ui \
|
||||||
|
branchcheckoutdialog.ui
|
||||||
|
|
||||||
include(gitorious/gitorious.pri)
|
include(gitorious/gitorious.pri)
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ QtcPlugin {
|
|||||||
"branchadddialog.cpp",
|
"branchadddialog.cpp",
|
||||||
"branchadddialog.h",
|
"branchadddialog.h",
|
||||||
"branchadddialog.ui",
|
"branchadddialog.ui",
|
||||||
|
"branchcheckoutdialog.cpp",
|
||||||
|
"branchcheckoutdialog.h",
|
||||||
|
"branchcheckoutdialog.ui",
|
||||||
"branchdialog.cpp",
|
"branchdialog.cpp",
|
||||||
"branchdialog.h",
|
"branchdialog.h",
|
||||||
"branchdialog.ui",
|
"branchdialog.ui",
|
||||||
|
|||||||
Reference in New Issue
Block a user