forked from qt-creator/qt-creator
Use QtcProcess in MergeTool
Change-Id: I9d08c455404a75a29874883dbdc4855a183a58e3 Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
@@ -1971,9 +1971,9 @@ void GitPlugin::emitFilesChanged(const QStringList &l)
|
|||||||
emit dd->filesChanged(l);
|
emit dd->filesChanged(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GitPlugin::emitRepositoryChanged(const QString &r)
|
void GitPlugin::emitRepositoryChanged(const FilePath &r)
|
||||||
{
|
{
|
||||||
emit dd->repositoryChanged(FilePath::fromString(r));
|
emit dd->repositoryChanged(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GitPlugin::startRebaseFromCommit(const FilePath &workingDirectory, const QString &commit)
|
void GitPlugin::startRebaseFromCommit(const FilePath &workingDirectory, const QString &commit)
|
||||||
|
@@ -66,7 +66,7 @@ public:
|
|||||||
static bool isCommitEditorOpen();
|
static bool isCommitEditorOpen();
|
||||||
|
|
||||||
static void emitFilesChanged(const QStringList &);
|
static void emitFilesChanged(const QStringList &);
|
||||||
static void emitRepositoryChanged(const QString &);
|
static void emitRepositoryChanged(const Utils::FilePath &);
|
||||||
static void startRebaseFromCommit(const Utils::FilePath &workingDirectory, const QString &commit);
|
static void startRebaseFromCommit(const Utils::FilePath &workingDirectory, const QString &commit);
|
||||||
static void manageRemotes();
|
static void manageRemotes();
|
||||||
static void initRepository();
|
static void initRepository();
|
||||||
|
@@ -29,11 +29,12 @@
|
|||||||
|
|
||||||
#include <coreplugin/documentmanager.h>
|
#include <coreplugin/documentmanager.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <vcsbase/vcsoutputwindow.h>
|
|
||||||
#include <coreplugin/messagebox.h>
|
#include <coreplugin/messagebox.h>
|
||||||
|
#include <utils/commandline.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
#include <vcsbase/vcsoutputwindow.h>
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QProcess>
|
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
@@ -54,20 +55,21 @@ bool MergeTool::start(const FilePath &workingDirectory, const QStringList &files
|
|||||||
{
|
{
|
||||||
QStringList arguments;
|
QStringList arguments;
|
||||||
arguments << "mergetool" << "-y" << files;
|
arguments << "mergetool" << "-y" << files;
|
||||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
Environment env = Environment::systemEnvironment();
|
||||||
env.insert("LANG", "C");
|
env.set("LANG", "C");
|
||||||
env.insert("LANGUAGE", "C");
|
env.set("LANGUAGE", "C");
|
||||||
m_process = new QProcess(this);
|
m_process = new QtcProcess(ProcessMode::Writer);
|
||||||
m_process->setWorkingDirectory(workingDirectory.toString());
|
m_process->setWorkingDirectory(workingDirectory.toString());
|
||||||
m_process->setProcessEnvironment(env);
|
m_process->setEnvironment(env);
|
||||||
m_process->setProcessChannelMode(QProcess::MergedChannels);
|
m_process->setProcessChannelMode(QProcess::MergedChannels);
|
||||||
const Utils::FilePath binary = GitClient::instance()->vcsBinary();
|
const Utils::FilePath binary = GitClient::instance()->vcsBinary();
|
||||||
VcsOutputWindow::appendCommand(workingDirectory, {binary, arguments});
|
const CommandLine cmd = {binary, arguments};
|
||||||
m_process->start(binary.toString(), arguments);
|
VcsOutputWindow::appendCommand(workingDirectory, cmd);
|
||||||
|
m_process->setCommand(cmd);
|
||||||
|
m_process->start();
|
||||||
if (m_process->waitForStarted()) {
|
if (m_process->waitForStarted()) {
|
||||||
connect(m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
connect(m_process, &QtcProcess::finished, this, &MergeTool::done);
|
||||||
this, &MergeTool::done);
|
connect(m_process, &QtcProcess::readyReadStandardOutput, this, &MergeTool::readData);
|
||||||
connect(m_process, &QIODevice::readyRead, this, &MergeTool::readData);
|
|
||||||
} else {
|
} else {
|
||||||
delete m_process;
|
delete m_process;
|
||||||
m_process = nullptr;
|
m_process = nullptr;
|
||||||
@@ -76,9 +78,9 @@ bool MergeTool::start(const FilePath &workingDirectory, const QStringList &files
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MergeTool::FileState MergeTool::parseStatus(const QByteArray &line, QString &extraInfo)
|
MergeTool::FileState MergeTool::parseStatus(const QString &line, QString &extraInfo)
|
||||||
{
|
{
|
||||||
QByteArray state = line.trimmed();
|
QString state = line.trimmed();
|
||||||
// " {local}: modified file"
|
// " {local}: modified file"
|
||||||
// " {remote}: deleted"
|
// " {remote}: deleted"
|
||||||
if (!state.isEmpty()) {
|
if (!state.isEmpty()) {
|
||||||
@@ -89,16 +91,16 @@ MergeTool::FileState MergeTool::parseStatus(const QByteArray &line, QString &ext
|
|||||||
return ModifiedState;
|
return ModifiedState;
|
||||||
if (state.startsWith("created"))
|
if (state.startsWith("created"))
|
||||||
return CreatedState;
|
return CreatedState;
|
||||||
QByteArray submodulePrefix("submodule commit ");
|
const QString submodulePrefix("submodule commit ");
|
||||||
// " {local}: submodule commit <hash>"
|
// " {local}: submodule commit <hash>"
|
||||||
if (state.startsWith(submodulePrefix)) {
|
if (state.startsWith(submodulePrefix)) {
|
||||||
extraInfo = QString::fromLocal8Bit(state.mid(submodulePrefix.size()));
|
extraInfo = state.mid(submodulePrefix.size());
|
||||||
return SubmoduleState;
|
return SubmoduleState;
|
||||||
}
|
}
|
||||||
// " {local}: a symbolic link -> 'foo.cpp'"
|
// " {local}: a symbolic link -> 'foo.cpp'"
|
||||||
QByteArray symlinkPrefix("a symbolic link -> '");
|
const QString symlinkPrefix("a symbolic link -> '");
|
||||||
if (state.startsWith(symlinkPrefix)) {
|
if (state.startsWith(symlinkPrefix)) {
|
||||||
extraInfo = QString::fromLocal8Bit(state.mid(symlinkPrefix.size()));
|
extraInfo = state.mid(symlinkPrefix.size());
|
||||||
extraInfo.chop(1); // remove last quote
|
extraInfo.chop(1); // remove last quote
|
||||||
return SymbolicLinkState;
|
return SymbolicLinkState;
|
||||||
}
|
}
|
||||||
@@ -106,7 +108,7 @@ MergeTool::FileState MergeTool::parseStatus(const QByteArray &line, QString &ext
|
|||||||
return UnknownState;
|
return UnknownState;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MergeTool::MergeType mergeType(const QByteArray &type)
|
static MergeTool::MergeType mergeType(const QString &type)
|
||||||
{
|
{
|
||||||
if (type == "Normal")
|
if (type == "Normal")
|
||||||
return MergeTool::NormalMerge;
|
return MergeTool::NormalMerge;
|
||||||
@@ -206,57 +208,52 @@ void MergeTool::prompt(const QString &title, const QString &question)
|
|||||||
|
|
||||||
void MergeTool::readData()
|
void MergeTool::readData()
|
||||||
{
|
{
|
||||||
bool waitForFurtherInput = false;
|
QString newData = QString::fromLocal8Bit(m_process->readAllStandardOutput());
|
||||||
while (m_process->bytesAvailable()) {
|
newData.remove('\r');
|
||||||
const bool hasLine = m_process->canReadLine();
|
VcsOutputWindow::append(newData);
|
||||||
const QByteArray line = hasLine ? m_process->readLine() : m_process->readAllStandardOutput();
|
QString data = m_unfinishedLine + newData;
|
||||||
VcsOutputWindow::append(QString::fromLocal8Bit(line));
|
m_unfinishedLine.clear();
|
||||||
m_line += line;
|
while (const int index = data.indexOf('\n') != -1) {
|
||||||
// {Normal|Deleted|Submodule|Symbolic link} merge conflict for 'foo.cpp'
|
const QString line = data.left(index + 1);
|
||||||
const int index = m_line.indexOf(" merge conflict for ");
|
readLine(line);
|
||||||
if (index != -1) {
|
data = data.mid(index + 1);
|
||||||
m_mergeType = mergeType(m_line.left(index));
|
}
|
||||||
int quote = m_line.indexOf('\'');
|
if (data.startsWith("Was the merge successful")) {
|
||||||
m_fileName = QString::fromLocal8Bit(m_line.mid(quote + 1, m_line.lastIndexOf('\'') - quote - 1));
|
prompt(tr("Unchanged File"), tr("Was the merge successful?"));
|
||||||
m_line.clear();
|
} else if (data.startsWith("Continue merging")) {
|
||||||
} else if (m_line.startsWith(" {local}")) {
|
prompt(tr("Continue Merging"), tr("Continue merging other unresolved paths?"));
|
||||||
waitForFurtherInput = !hasLine;
|
} else if (data.startsWith("Hit return")) {
|
||||||
if (waitForFurtherInput)
|
QMessageBox::warning(
|
||||||
continue;
|
Core::ICore::dialogParent(), tr("Merge Tool"),
|
||||||
m_localState = parseStatus(m_line, m_localInfo);
|
QString("<html><body><p>%1</p>\n<p>%2</p></body></html>").arg(
|
||||||
m_line.clear();
|
tr("Merge tool is not configured."),
|
||||||
} else if (m_line.startsWith(" {remote}")) {
|
tr("Run git config --global merge.tool <tool> "
|
||||||
waitForFurtherInput = !hasLine;
|
"to configure it, then try again.")));
|
||||||
if (waitForFurtherInput)
|
m_process->kill();
|
||||||
continue;
|
} else {
|
||||||
m_remoteState = parseStatus(m_line, m_remoteInfo);
|
m_unfinishedLine = data;
|
||||||
m_line.clear();
|
}
|
||||||
chooseAction();
|
}
|
||||||
} else if (m_line.startsWith("Was the merge successful")) {
|
|
||||||
prompt(tr("Unchanged File"), tr("Was the merge successful?"));
|
void MergeTool::readLine(const QString &line)
|
||||||
} else if (m_line.startsWith("Continue merging")) {
|
{
|
||||||
prompt(tr("Continue Merging"), tr("Continue merging other unresolved paths?"));
|
// {Normal|Deleted|Submodule|Symbolic link} merge conflict for 'foo.cpp'
|
||||||
} else if (m_line.startsWith("Hit return")) {
|
const int index = line.indexOf(" merge conflict for ");
|
||||||
QMessageBox::warning(
|
if (index != -1) {
|
||||||
Core::ICore::dialogParent(), tr("Merge Tool"),
|
m_mergeType = mergeType(line.left(index));
|
||||||
QString("<html><body><p>%1</p>\n<p>%2</p></body></html>").arg(
|
const int quote = line.indexOf('\'');
|
||||||
tr("Merge tool is not configured."),
|
m_fileName = line.mid(quote + 1, line.lastIndexOf('\'') - quote - 1);
|
||||||
tr("Run git config --global merge.tool <tool> "
|
} else if (line.startsWith(" {local}")) {
|
||||||
"to configure it, then try again.")));
|
m_localState = parseStatus(line, m_localInfo);
|
||||||
m_process->kill();
|
} else if (line.startsWith(" {remote}")) {
|
||||||
} else if (m_line.endsWith('\n')) {
|
m_remoteState = parseStatus(line, m_remoteInfo);
|
||||||
// Skip unidentified lines
|
chooseAction();
|
||||||
m_line.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if (!waitForFurtherInput)
|
|
||||||
m_line.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MergeTool::done()
|
void MergeTool::done()
|
||||||
{
|
{
|
||||||
const QString workingDirectory = m_process->workingDirectory();
|
const FilePath workingDirectory = m_process->workingDirectory();
|
||||||
int exitCode = m_process->exitCode();
|
int exitCode = m_process->exitCode();
|
||||||
if (!exitCode) {
|
if (!exitCode) {
|
||||||
VcsOutputWindow::appendMessage(tr("Merge tool process finished successfully."));
|
VcsOutputWindow::appendMessage(tr("Merge tool process finished successfully."));
|
||||||
@@ -264,7 +261,7 @@ void MergeTool::done()
|
|||||||
VcsOutputWindow::appendError(tr("Merge tool process terminated with exit code %1")
|
VcsOutputWindow::appendError(tr("Merge tool process terminated with exit code %1")
|
||||||
.arg(exitCode));
|
.arg(exitCode));
|
||||||
}
|
}
|
||||||
GitClient::instance()->continueCommandIfNeeded(FilePath::fromString(workingDirectory), exitCode == 0);
|
GitClient::instance()->continueCommandIfNeeded(workingDirectory, exitCode == 0);
|
||||||
GitPlugin::emitRepositoryChanged(workingDirectory);
|
GitPlugin::emitRepositoryChanged(workingDirectory);
|
||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
@@ -272,7 +269,6 @@ void MergeTool::done()
|
|||||||
void MergeTool::write(const QByteArray &bytes)
|
void MergeTool::write(const QByteArray &bytes)
|
||||||
{
|
{
|
||||||
m_process->write(bytes);
|
m_process->write(bytes);
|
||||||
m_process->waitForBytesWritten();
|
|
||||||
VcsOutputWindow::append(QString::fromLocal8Bit(bytes));
|
VcsOutputWindow::append(QString::fromLocal8Bit(bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,10 +30,13 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QMessageBox;
|
class QMessageBox;
|
||||||
class QProcess;
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Utils { class FilePath; }
|
namespace Utils
|
||||||
|
{
|
||||||
|
class FilePath;
|
||||||
|
class QtcProcess;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Git {
|
namespace Git {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -66,23 +69,24 @@ public:
|
|||||||
private:
|
private:
|
||||||
void prompt(const QString &title, const QString &question);
|
void prompt(const QString &title, const QString &question);
|
||||||
void readData();
|
void readData();
|
||||||
|
void readLine(const QString &line);
|
||||||
void done();
|
void done();
|
||||||
void write(const QByteArray &bytes);
|
void write(const QByteArray &bytes);
|
||||||
|
|
||||||
FileState parseStatus(const QByteArray &line, QString &extraInfo);
|
FileState parseStatus(const QString &line, QString &extraInfo);
|
||||||
QString mergeTypeName();
|
QString mergeTypeName();
|
||||||
QString stateName(FileState state, const QString &extraInfo);
|
QString stateName(FileState state, const QString &extraInfo);
|
||||||
void chooseAction();
|
void chooseAction();
|
||||||
void addButton(QMessageBox *msgBox, const QString &text, char key);
|
void addButton(QMessageBox *msgBox, const QString &text, char key);
|
||||||
|
|
||||||
QProcess *m_process = nullptr;
|
Utils::QtcProcess *m_process = nullptr;
|
||||||
MergeType m_mergeType = NormalMerge;
|
MergeType m_mergeType = NormalMerge;
|
||||||
QString m_fileName;
|
QString m_fileName;
|
||||||
FileState m_localState = UnknownState;
|
FileState m_localState = UnknownState;
|
||||||
QString m_localInfo;
|
QString m_localInfo;
|
||||||
FileState m_remoteState = UnknownState;
|
FileState m_remoteState = UnknownState;
|
||||||
QString m_remoteInfo;
|
QString m_remoteInfo;
|
||||||
QByteArray m_line;
|
QString m_unfinishedLine;
|
||||||
bool m_merging = false;
|
bool m_merging = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user