forked from qt-creator/qt-creator
Gerrit: added ability to save path for applying patches
Change-Id: I3cc8f1d19784145a7fbf19c321ccbc079847fbc2 Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: Petar Perisin <petar.perisin@gmail.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com> Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
#include "gerritparameters.h"
|
||||
|
||||
#include <utils/filterlineedit.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
@@ -103,7 +104,9 @@ GerritDialog::GerritDialog(const QSharedPointer<GerritParameters> &p,
|
||||
, m_detailsBrowser(new QTextBrowser)
|
||||
, m_queryLineEdit(new QueryValidatingLineEdit)
|
||||
, m_filterLineEdit(new Utils::FilterLineEdit)
|
||||
, m_repositoryChooser(new Utils::PathChooser)
|
||||
, m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Close))
|
||||
, m_repositoryChooserLabel(new QLabel(tr("Apply in: "), this))
|
||||
, m_fetchRunning(false)
|
||||
{
|
||||
setWindowTitle(tr("Gerrit %1@%2").arg(p->user, p->host));
|
||||
@@ -157,9 +160,15 @@ GerritDialog::GerritDialog(const QSharedPointer<GerritParameters> &p,
|
||||
m_detailsBrowser->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
detailsLayout->addWidget(m_detailsBrowser);
|
||||
|
||||
m_displayButton = addActionButton(tr("Diff..."), SLOT(slotFetchDisplay()));
|
||||
m_applyButton = addActionButton(tr("Apply..."), SLOT(slotFetchApply()));
|
||||
m_checkoutButton = addActionButton(tr("Checkout..."), SLOT(slotFetchCheckout()));
|
||||
m_repositoryChooser->setExpectedKind(Utils::PathChooser::Directory);
|
||||
QHBoxLayout *repoPathLayout = new QHBoxLayout;
|
||||
repoPathLayout->addWidget(m_repositoryChooserLabel);
|
||||
repoPathLayout->addWidget(m_repositoryChooser);
|
||||
detailsLayout->addLayout(repoPathLayout);
|
||||
|
||||
m_displayButton = addActionButton(QString(), SLOT(slotFetchDisplay()));
|
||||
m_applyButton = addActionButton(QString(), SLOT(slotFetchApply()));
|
||||
m_checkoutButton = addActionButton(QString(), SLOT(slotFetchCheckout()));
|
||||
m_refreshButton = addActionButton(tr("Refresh"), SLOT(slotRefresh()));
|
||||
|
||||
connect(m_model, SIGNAL(refreshStateChanged(bool)),
|
||||
@@ -185,6 +194,35 @@ GerritDialog::GerritDialog(const QSharedPointer<GerritParameters> &p,
|
||||
m_treeView->setFocus();
|
||||
}
|
||||
|
||||
QString GerritDialog::repositoryPath() const
|
||||
{
|
||||
return m_repositoryChooser->path();
|
||||
}
|
||||
|
||||
void GerritDialog::displayRepositoryPath()
|
||||
{
|
||||
QTC_ASSERT(m_parameters, return);
|
||||
m_repositoryChooser->setVisible(!m_parameters->promptPath);
|
||||
m_repositoryChooserLabel->setVisible(!m_parameters->promptPath);
|
||||
if (m_repositoryChooser->path().isEmpty())
|
||||
m_repositoryChooser->setPath(m_parameters->repositoryPath);
|
||||
if (m_parameters->promptPath) {
|
||||
m_displayButton->setText(tr("Diff..."));
|
||||
m_applyButton->setText(tr("Apply..."));
|
||||
m_checkoutButton->setText(tr("Checkout..."));
|
||||
} else {
|
||||
m_displayButton->setText(tr("Diff"));
|
||||
m_applyButton->setText(tr("Apply"));
|
||||
m_checkoutButton->setText(tr("Checkout"));
|
||||
}
|
||||
}
|
||||
|
||||
void GerritDialog::showEvent(QShowEvent *event)
|
||||
{
|
||||
displayRepositoryPath();
|
||||
QDialog::showEvent(event);
|
||||
}
|
||||
|
||||
QPushButton *GerritDialog::addActionButton(const QString &text, const char *buttonSlot)
|
||||
{
|
||||
QPushButton *button = m_buttonBox->addButton(text, QDialogButtonBox::ActionRole);
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#define GERRIT_INTERNAL_GERRITDIALOG_H
|
||||
|
||||
#include <utils/filterlineedit.h>
|
||||
#include <utils/pathchooser.h>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QSharedPointer>
|
||||
@@ -78,6 +79,7 @@ public:
|
||||
explicit GerritDialog(const QSharedPointer<GerritParameters> &p,
|
||||
QWidget *parent = 0);
|
||||
~GerritDialog();
|
||||
QString repositoryPath() const;
|
||||
|
||||
signals:
|
||||
void fetchDisplay(const QSharedPointer<Gerrit::Internal::GerritChange> &);
|
||||
@@ -88,6 +90,9 @@ public slots:
|
||||
void fetchStarted(const QSharedPointer<Gerrit::Internal::GerritChange> &change);
|
||||
void fetchFinished();
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *event);
|
||||
|
||||
private slots:
|
||||
void slotCurrentChanged();
|
||||
void slotDoubleClicked(const QModelIndex &);
|
||||
@@ -96,6 +101,7 @@ private slots:
|
||||
void slotFetchApply();
|
||||
void slotFetchCheckout();
|
||||
void slotRefresh();
|
||||
void displayRepositoryPath();
|
||||
|
||||
private:
|
||||
const QStandardItem *itemAt(const QModelIndex &i, int column = 0) const;
|
||||
@@ -112,11 +118,13 @@ private:
|
||||
QTextBrowser *m_detailsBrowser;
|
||||
QueryValidatingLineEdit *m_queryLineEdit;
|
||||
Utils::FilterLineEdit *m_filterLineEdit;
|
||||
Utils::PathChooser *m_repositoryChooser;
|
||||
QDialogButtonBox *m_buttonBox;
|
||||
QPushButton *m_displayButton;
|
||||
QPushButton *m_applyButton;
|
||||
QPushButton *m_checkoutButton;
|
||||
QPushButton *m_refreshButton;
|
||||
QLabel *m_repositoryChooserLabel;
|
||||
bool m_fetchRunning;
|
||||
};
|
||||
|
||||
|
@@ -84,8 +84,10 @@ GerritOptionsWidget::GerritOptionsWidget(QWidget *parent)
|
||||
, m_hostLineEdit(new QLineEdit(this))
|
||||
, m_userLineEdit(new QLineEdit(this))
|
||||
, m_sshChooser(new Utils::PathChooser)
|
||||
, m_repositoryChooser(new Utils::PathChooser)
|
||||
, m_portSpinBox(new QSpinBox(this))
|
||||
, m_httpsCheckBox(new QCheckBox(tr("HTTPS")))
|
||||
, m_promptPathCheckBox(new QCheckBox(tr("Always prompt for repository folder")))
|
||||
{
|
||||
QFormLayout *formLayout = new QFormLayout(this);
|
||||
formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
||||
@@ -94,6 +96,11 @@ GerritOptionsWidget::GerritOptionsWidget(QWidget *parent)
|
||||
m_sshChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
||||
m_sshChooser->setCommandVersionArguments(QStringList(QLatin1String("-V")));
|
||||
formLayout->addRow(tr("&ssh:"), m_sshChooser);
|
||||
formLayout->addRow(tr("&Repository:"), m_repositoryChooser);
|
||||
m_repositoryChooser->setToolTip(tr("Default repository where patches will be applied."));
|
||||
formLayout->addRow(tr("Pr&ompt:"), m_promptPathCheckBox);
|
||||
m_promptPathCheckBox->setToolTip(tr("If checked, user will always be\n"
|
||||
"asked to confirm the repository path."));
|
||||
m_portSpinBox->setMinimum(1);
|
||||
m_portSpinBox->setMaximum(65535);
|
||||
formLayout->addRow(tr("&Port:"), m_portSpinBox);
|
||||
@@ -110,8 +117,10 @@ GerritParameters GerritOptionsWidget::parameters() const
|
||||
result.host = m_hostLineEdit->text().trimmed();
|
||||
result.user = m_userLineEdit->text().trimmed();
|
||||
result.ssh = m_sshChooser->path();
|
||||
result.repositoryPath = m_repositoryChooser->path();
|
||||
result.port = m_portSpinBox->value();
|
||||
result.https = m_httpsCheckBox->isChecked();
|
||||
result.promptPath = m_promptPathCheckBox->isChecked();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -120,8 +129,10 @@ void GerritOptionsWidget::setParameters(const GerritParameters &p)
|
||||
m_hostLineEdit->setText(p.host);
|
||||
m_userLineEdit->setText(p.user);
|
||||
m_sshChooser->setPath(p.ssh);
|
||||
m_repositoryChooser->setPath(p.repositoryPath);
|
||||
m_portSpinBox->setValue(p.port);
|
||||
m_httpsCheckBox->setChecked(p.https);
|
||||
m_promptPathCheckBox->setChecked(p.promptPath);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -63,8 +63,10 @@ private:
|
||||
QLineEdit *m_hostLineEdit;
|
||||
QLineEdit *m_userLineEdit;
|
||||
Utils::PathChooser *m_sshChooser;
|
||||
Utils::PathChooser *m_repositoryChooser;
|
||||
QSpinBox *m_portSpinBox;
|
||||
QCheckBox *m_httpsCheckBox;
|
||||
QCheckBox *m_promptPathCheckBox;
|
||||
};
|
||||
|
||||
class GerritOptionsPage : public VcsBase::VcsBaseOptionsPage
|
||||
|
@@ -50,7 +50,9 @@ static const char userKeyC[] = "User";
|
||||
static const char portKeyC[] = "Port";
|
||||
static const char portFlagKeyC[] = "PortFlag";
|
||||
static const char sshKeyC[] = "Ssh";
|
||||
static const char repositoryKeyC[] = "RepoPath";
|
||||
static const char httpsKeyC[] = "Https";
|
||||
static const char promptPathKeyC[] = "PromptPath";
|
||||
static const char defaultHostC[] = "codereview.qt-project.org";
|
||||
static const char defaultSshC[] = "ssh";
|
||||
static const char savedQueriesKeyC[] = "SavedQueries";
|
||||
@@ -99,6 +101,7 @@ GerritParameters::GerritParameters()
|
||||
: host(QLatin1String(defaultHostC))
|
||||
, port(defaultPort)
|
||||
, https(true)
|
||||
, promptPath(true)
|
||||
, portFlag(QLatin1String(defaultPortFlag))
|
||||
{
|
||||
}
|
||||
@@ -118,8 +121,8 @@ QString GerritParameters::sshHostArgument() const
|
||||
|
||||
bool GerritParameters::equals(const GerritParameters &rhs) const
|
||||
{
|
||||
return port == rhs.port && host == rhs.host && user == rhs.user
|
||||
&& ssh == rhs.ssh && https == rhs.https;
|
||||
return port == rhs.port && host == rhs.host && user == rhs.user && promptPath == rhs.promptPath
|
||||
&& ssh == rhs.ssh && https == rhs.https && repositoryPath == rhs.repositoryPath;
|
||||
}
|
||||
|
||||
void GerritParameters::toSettings(QSettings *s) const
|
||||
@@ -130,7 +133,9 @@ void GerritParameters::toSettings(QSettings *s) const
|
||||
s->setValue(QLatin1String(portKeyC), port);
|
||||
s->setValue(QLatin1String(portFlagKeyC), portFlag);
|
||||
s->setValue(QLatin1String(sshKeyC), ssh);
|
||||
s->setValue(QLatin1String(repositoryKeyC), repositoryPath);
|
||||
s->setValue(QLatin1String(httpsKeyC), https);
|
||||
s->setValue(QLatin1String(promptPathKeyC), promptPath);
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
@@ -147,11 +152,13 @@ void GerritParameters::fromSettings(const QSettings *s)
|
||||
host = s->value(rootKey + QLatin1String(hostKeyC), QLatin1String(defaultHostC)).toString();
|
||||
user = s->value(rootKey + QLatin1String(userKeyC), QString()).toString();
|
||||
ssh = s->value(rootKey + QLatin1String(sshKeyC), QString()).toString();
|
||||
repositoryPath = s->value(rootKey + QLatin1String(repositoryKeyC), QString()).toString();
|
||||
port = s->value(rootKey + QLatin1String(portKeyC), QVariant(int(defaultPort))).toInt();
|
||||
portFlag = s->value(rootKey + QLatin1String(portFlagKeyC), QLatin1String(defaultPortFlag)).toString();
|
||||
savedQueries = s->value(rootKey + QLatin1String(savedQueriesKeyC), QString()).toString()
|
||||
.split(QLatin1String(","));
|
||||
https = s->value(rootKey + QLatin1String(httpsKeyC), QVariant(true)).toBool();
|
||||
promptPath = s->value(rootKey + QLatin1String(promptPathKeyC), QVariant(true)).toBool();
|
||||
if (ssh.isEmpty())
|
||||
ssh = detectSsh();
|
||||
}
|
||||
|
@@ -55,8 +55,10 @@ public:
|
||||
unsigned short port;
|
||||
QString user;
|
||||
QString ssh;
|
||||
QString repositoryPath;
|
||||
QStringList savedQueries;
|
||||
bool https;
|
||||
bool promptPath;
|
||||
QString portFlag;
|
||||
};
|
||||
|
||||
|
@@ -60,8 +60,10 @@
|
||||
#include <QRegExp>
|
||||
#include <QAction>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QTemporaryFile>
|
||||
#include <QDir>
|
||||
#include <QMap>
|
||||
|
||||
enum { debug = 0 };
|
||||
|
||||
@@ -411,14 +413,79 @@ void GerritPlugin::fetch(const QSharedPointer<Gerrit::Internal::GerritChange> &c
|
||||
if (git.isEmpty())
|
||||
return;
|
||||
|
||||
Git::Internal::GitClient* gitClient = Git::Internal::GitPlugin::instance()->gitClient();
|
||||
|
||||
QString repository;
|
||||
bool verifiedRepository = false;
|
||||
if (!m_dialog.isNull() && !m_parameters.isNull() && !m_parameters->promptPath
|
||||
&& QFile::exists(m_dialog->repositoryPath())) {
|
||||
repository = gitClient->findRepositoryForDirectory(m_dialog->repositoryPath());
|
||||
}
|
||||
if (!repository.isEmpty()) {
|
||||
// Check if remote from a working dir is the same as remote from patch
|
||||
QMap<QString, QString> remotesList = gitClient->synchronousRemotesList(repository);
|
||||
if (!remotesList.isEmpty()) {
|
||||
QStringList remotes = remotesList.values();
|
||||
foreach (QString remote, remotes) {
|
||||
if (remote.endsWith(QLatin1String(".git")))
|
||||
remote.chop(4);
|
||||
if (remote.contains(m_parameters->host) && remote.endsWith(change->project)) {
|
||||
verifiedRepository = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!verifiedRepository && QFile::exists(repository + QLatin1String("/.gitmodules"))) {
|
||||
QMap<QString,QString> submodules = gitClient->synchronousSubmoduleList(repository);
|
||||
|
||||
QMap<QString,QString>::const_iterator i = submodules.constBegin();
|
||||
while (i != submodules.constEnd()) {
|
||||
QString remote = i.value();
|
||||
if (remote.endsWith(QLatin1String(".git")))
|
||||
remote.chop(4);
|
||||
if (remote.contains(m_parameters->host) && remote.endsWith(change->project)
|
||||
&& QFile::exists(repository + QLatin1Char('/') + i.key())) {
|
||||
repository = QDir::cleanPath(repository + QLatin1Char('/') + i.key());
|
||||
verifiedRepository = true;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!verifiedRepository){
|
||||
QMessageBox::StandardButton answer = QMessageBox::question(
|
||||
Core::ICore::mainWindow(), tr("Remote not Verified"),
|
||||
tr("Change host: %1\nand project: %2\n\nwere not verified among remotes"
|
||||
" in %3. Select different folder?")
|
||||
.arg(m_parameters->host,
|
||||
change->project,
|
||||
QDir::toNativeSeparators(repository)),
|
||||
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
|
||||
QMessageBox::Yes);
|
||||
switch (answer) {
|
||||
case QMessageBox::Cancel:
|
||||
return;
|
||||
case QMessageBox::No:
|
||||
verifiedRepository = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!verifiedRepository) {
|
||||
// Ask the user for a repository to retrieve the change.
|
||||
const QString title =
|
||||
tr("Enter Local Repository for '%1' (%2)").arg(change->project, change->branch);
|
||||
const QString suggestedRespository =
|
||||
findLocalRepository(change->project, change->branch);
|
||||
const QString repository =
|
||||
QFileDialog::getExistingDirectory(m_dialog.data(),
|
||||
repository = QFileDialog::getExistingDirectory(m_dialog.data(),
|
||||
title, suggestedRespository);
|
||||
}
|
||||
|
||||
if (repository.isEmpty())
|
||||
return;
|
||||
|
||||
|
@@ -1504,6 +1504,67 @@ bool GitClient::synchronousRemoteCmd(const QString &workingDirectory, QStringLis
|
||||
return true;
|
||||
}
|
||||
|
||||
QMap<QString,QString> GitClient::synchronousRemotesList(const QString &workingDirectory,
|
||||
QString *errorMessage)
|
||||
{
|
||||
QMap<QString,QString> result;
|
||||
QString output;
|
||||
QString error;
|
||||
QStringList args(QLatin1String("-v"));
|
||||
if (!synchronousRemoteCmd(workingDirectory, args, &output, &error)) {
|
||||
if (errorMessage)
|
||||
*errorMessage = error;
|
||||
else
|
||||
outputWindow()->append(error);
|
||||
return result;
|
||||
}
|
||||
QStringList remotes = output.split(QLatin1String("\n"));
|
||||
|
||||
foreach (const QString &remote, remotes) {
|
||||
if (!remote.endsWith(QLatin1String(" (fetch)")))
|
||||
continue;
|
||||
|
||||
QStringList tokens = remote.split(QRegExp(QLatin1String("\\s")),
|
||||
QString::SkipEmptyParts);
|
||||
if (tokens.count() != 3)
|
||||
continue;
|
||||
|
||||
result.insert(tokens.at(0), tokens.at(1));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QMap<QString,QString> GitClient::synchronousSubmoduleList(const QString &workingDirectory,
|
||||
QString *errorMessage)
|
||||
{
|
||||
QStringList args;
|
||||
QMap<QString,QString> result;
|
||||
args << QLatin1String("config") << QLatin1String("-l");
|
||||
QByteArray outputText;
|
||||
QByteArray errorText;
|
||||
const bool rc = fullySynchronousGit(workingDirectory, args, &outputText, &errorText);
|
||||
if (!rc) {
|
||||
QString message = tr("Cannot run \"git config -l\" in \"%1\": %2").
|
||||
arg(QDir::toNativeSeparators(workingDirectory), commandOutputFromLocal8Bit(errorText));
|
||||
|
||||
if (errorMessage)
|
||||
*errorMessage = message;
|
||||
else
|
||||
outputWindow()->append(message);
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList outputList = commandOutputLinesFromLocal8Bit(outputText);
|
||||
QString urlKey = QLatin1String(".url=");
|
||||
foreach (const QString& line, outputList) {
|
||||
if (line.startsWith(QLatin1String("submodule."))) {
|
||||
result.insertMulti(line.mid(10, line.indexOf(urlKey) - 10),
|
||||
line.mid(line.indexOf(urlKey, 10) + 5));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GitClient::synchronousShow(const QString &workingDirectory, const QString &id,
|
||||
QString *output, QString *errorMessage)
|
||||
{
|
||||
|
@@ -182,6 +182,11 @@ public:
|
||||
QString *output, QString *errorMessage);
|
||||
bool synchronousRemoteCmd(const QString &workingDirectory, QStringList remoteArgs,
|
||||
QString *output, QString *errorMessage);
|
||||
|
||||
QMap<QString,QString> synchronousRemotesList(const QString &workingDirectory,
|
||||
QString *errorMessage = 0);
|
||||
QMap<QString,QString> synchronousSubmoduleList(const QString &workingDirectory,
|
||||
QString *errorMessage = 0);
|
||||
bool synchronousShow(const QString &workingDirectory, const QString &id,
|
||||
QString *output, QString *errorMessage);
|
||||
bool synchronousParentRevisions(const QString &workingDirectory,
|
||||
|
@@ -33,21 +33,6 @@
|
||||
namespace Git {
|
||||
namespace Internal {
|
||||
|
||||
// Parse a branch line: " *name sha description".
|
||||
bool RemoteModel::Remote::parse(const QString &line)
|
||||
{
|
||||
if (!line.endsWith(QLatin1String(" (fetch)")))
|
||||
return false;
|
||||
|
||||
QStringList tokens = line.split(QRegExp(QLatin1String("\\s")), QString::SkipEmptyParts);
|
||||
if (tokens.count() != 3)
|
||||
return false;
|
||||
|
||||
name = tokens.at(0);
|
||||
url = tokens.at(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------ RemoteModel
|
||||
RemoteModel::RemoteModel(GitClient *client, QObject *parent) :
|
||||
QAbstractTableModel(parent),
|
||||
@@ -192,20 +177,20 @@ void RemoteModel::clear()
|
||||
|
||||
bool RemoteModel::refresh(const QString &workingDirectory, QString *errorMessage)
|
||||
{
|
||||
// Run branch command with verbose.
|
||||
QStringList remoteArgs;
|
||||
remoteArgs << QLatin1String("-v");
|
||||
QString output;
|
||||
if (!m_client->synchronousRemoteCmd(workingDirectory, remoteArgs, &output, errorMessage))
|
||||
// get list of remotes.
|
||||
QMap<QString,QString> remotesList =
|
||||
m_client->synchronousRemotesList(workingDirectory, errorMessage);
|
||||
|
||||
if (remotesList.isEmpty())
|
||||
return false;
|
||||
// Parse output
|
||||
|
||||
m_workingDirectory = workingDirectory;
|
||||
beginResetModel();
|
||||
m_remotes.clear();
|
||||
const QStringList lines = output.split(QLatin1Char('\n'));
|
||||
for (int r = 0; r < lines.count(); ++r) {
|
||||
foreach (const QString &remoteName, remotesList.keys()) {
|
||||
Remote newRemote;
|
||||
if (newRemote.parse(lines.at(r)))
|
||||
newRemote.name = remoteName;
|
||||
newRemote.url = remotesList.value(remoteName);
|
||||
m_remotes.push_back(newRemote);
|
||||
}
|
||||
endResetModel();
|
||||
|
@@ -70,8 +70,6 @@ public:
|
||||
|
||||
protected:
|
||||
struct Remote {
|
||||
bool parse(const QString &line);
|
||||
|
||||
QString name;
|
||||
QString url;
|
||||
};
|
||||
|
Reference in New Issue
Block a user