|
|
|
|
@@ -53,7 +53,7 @@
|
|
|
|
|
#include <utils/qtcprocess.h>
|
|
|
|
|
#include <utils/synchronousprocess.h>
|
|
|
|
|
#include <utils/fileutils.h>
|
|
|
|
|
#include <vcsbase/command.h>
|
|
|
|
|
#include <vcsbase/vcscommand.h>
|
|
|
|
|
#include <vcsbase/vcsbaseeditor.h>
|
|
|
|
|
#include <vcsbase/vcsbaseeditorparameterwidget.h>
|
|
|
|
|
#include <vcsbase/vcsoutputwindow.h>
|
|
|
|
|
@@ -87,19 +87,18 @@ static const char noColorOption[] = "--no-color";
|
|
|
|
|
static const char decorateOption[] = "--decorate";
|
|
|
|
|
|
|
|
|
|
using namespace Core;
|
|
|
|
|
using namespace Utils;
|
|
|
|
|
using namespace VcsBase;
|
|
|
|
|
|
|
|
|
|
namespace Git {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
|
|
|
|
// Suppress git diff warnings about "LF will be replaced by CRLF..." on Windows.
|
|
|
|
|
static inline unsigned diffExecutionFlags()
|
|
|
|
|
static unsigned diffExecutionFlags()
|
|
|
|
|
{
|
|
|
|
|
return Utils::HostOsInfo::isWindowsHost() ? unsigned(VcsBase::VcsBasePlugin::SuppressStdErrInLogWindow) : 0u;
|
|
|
|
|
return HostOsInfo::isWindowsHost() ? unsigned(VcsBasePlugin::SuppressStdErrInLogWindow) : 0u;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using VcsBase::VcsBasePlugin;
|
|
|
|
|
|
|
|
|
|
class GitDiffHandler : public QObject
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
@@ -134,13 +133,13 @@ private:
|
|
|
|
|
void postCollectTextualDiffOutputUsingShowCommand(const QStringList &arguments);
|
|
|
|
|
void postCollectTextualDiffOutput(const QString &gitCommand,
|
|
|
|
|
const QList<QStringList> &argumentsList);
|
|
|
|
|
void addJob(VcsBase::Command *command,
|
|
|
|
|
void addJob(VcsCommand *command,
|
|
|
|
|
const QString &gitCommand,
|
|
|
|
|
const QStringList &arguments);
|
|
|
|
|
QStringList addHeadWhenCommandInProgress() const;
|
|
|
|
|
int timeout() const;
|
|
|
|
|
QProcessEnvironment processEnvironment() const;
|
|
|
|
|
Utils::FileName gitPath() const;
|
|
|
|
|
FileName gitPath() const;
|
|
|
|
|
|
|
|
|
|
QPointer<DiffEditor::DiffEditorController> m_controller;
|
|
|
|
|
const QString m_workingDirectory;
|
|
|
|
|
@@ -220,9 +219,7 @@ void GitDiffHandler::postCollectShowDescription(const QString &id)
|
|
|
|
|
|
|
|
|
|
m_controller->requestSaveState();
|
|
|
|
|
m_controller->clear(m_waitMessage);
|
|
|
|
|
VcsBase::Command *command = new VcsBase::Command(gitPath(),
|
|
|
|
|
m_workingDirectory,
|
|
|
|
|
processEnvironment());
|
|
|
|
|
VcsCommand *command = new VcsCommand(gitPath(), m_workingDirectory, processEnvironment());
|
|
|
|
|
command->setCodec(m_gitClient->encoding(m_workingDirectory,
|
|
|
|
|
"i18n.commitEncoding"));
|
|
|
|
|
connect(command, SIGNAL(output(QString)),
|
|
|
|
|
@@ -256,7 +253,7 @@ void GitDiffHandler::slotShowDescriptionReceived(const QString &description)
|
|
|
|
|
description));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GitDiffHandler::addJob(VcsBase::Command *command,
|
|
|
|
|
void GitDiffHandler::addJob(VcsCommand *command,
|
|
|
|
|
const QString &gitCommand,
|
|
|
|
|
const QStringList &arguments)
|
|
|
|
|
{
|
|
|
|
|
@@ -308,9 +305,7 @@ void GitDiffHandler::postCollectTextualDiffOutput(const QString &gitCommand, con
|
|
|
|
|
|
|
|
|
|
m_controller->requestSaveState();
|
|
|
|
|
m_controller->clear(m_waitMessage);
|
|
|
|
|
VcsBase::Command *command = new VcsBase::Command(gitPath(),
|
|
|
|
|
m_workingDirectory,
|
|
|
|
|
processEnvironment());
|
|
|
|
|
VcsCommand *command = new VcsCommand(gitPath(), m_workingDirectory, processEnvironment());
|
|
|
|
|
command->setCodec(EditorManager::defaultTextCodec());
|
|
|
|
|
connect(command, SIGNAL(output(QString)),
|
|
|
|
|
this, SLOT(slotTextualDiffOutputReceived(QString)));
|
|
|
|
|
@@ -348,7 +343,7 @@ QProcessEnvironment GitDiffHandler::processEnvironment() const
|
|
|
|
|
return m_gitClient->processEnvironment();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Utils::FileName GitDiffHandler::gitPath() const
|
|
|
|
|
FileName GitDiffHandler::gitPath() const
|
|
|
|
|
{
|
|
|
|
|
return m_gitClient->gitExecutable();
|
|
|
|
|
}
|
|
|
|
|
@@ -446,7 +441,7 @@ void GitDiffEditorReloader::reload()
|
|
|
|
|
|
|
|
|
|
///////////////////////////////
|
|
|
|
|
|
|
|
|
|
class BaseGitDiffArgumentsWidget : public VcsBase::VcsBaseEditorParameterWidget
|
|
|
|
|
class BaseGitDiffArgumentsWidget : public VcsBaseEditorParameterWidget
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
@@ -481,7 +476,7 @@ protected:
|
|
|
|
|
QToolButton *m_ignoreWSButton;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class GitBlameArgumentsWidget : public VcsBase::VcsBaseEditorParameterWidget
|
|
|
|
|
class GitBlameArgumentsWidget : public VcsBaseEditorParameterWidget
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
@@ -506,7 +501,7 @@ public:
|
|
|
|
|
setBaseArguments(args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setEditor(VcsBase::VcsBaseEditorWidget *editor)
|
|
|
|
|
void setEditor(VcsBaseEditorWidget *editor)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(editor, return);
|
|
|
|
|
m_editor = editor;
|
|
|
|
|
@@ -514,12 +509,12 @@ public:
|
|
|
|
|
|
|
|
|
|
void executeCommand()
|
|
|
|
|
{
|
|
|
|
|
int line = VcsBase::VcsBaseEditor::lineNumberOfCurrentEditor();
|
|
|
|
|
int line = VcsBaseEditor::lineNumberOfCurrentEditor();
|
|
|
|
|
m_client->blame(m_workingDirectory, baseArguments(), m_fileName, m_revision, line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
VcsBase::VcsBaseEditorWidget *m_editor;
|
|
|
|
|
VcsBaseEditorWidget *m_editor;
|
|
|
|
|
GitClient *m_client;
|
|
|
|
|
QString m_workingDirectory;
|
|
|
|
|
QString m_revision;
|
|
|
|
|
@@ -579,7 +574,7 @@ class ConflictHandler : public QObject
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
public:
|
|
|
|
|
ConflictHandler(VcsBase::Command *parentCommand,
|
|
|
|
|
ConflictHandler(VcsCommand *parentCommand,
|
|
|
|
|
const QString &workingDirectory,
|
|
|
|
|
const QString &command = QString())
|
|
|
|
|
: QObject(parentCommand),
|
|
|
|
|
@@ -634,10 +629,10 @@ private:
|
|
|
|
|
QStringList m_files;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class ProgressParser : public VcsBase::ProgressParser
|
|
|
|
|
class GitProgressParser : public ProgressParser
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
ProgressParser() :
|
|
|
|
|
GitProgressParser() :
|
|
|
|
|
m_progressExp(QLatin1String("\\((\\d+)/(\\d+)\\)")) // e.g. Rebasing (7/42)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
@@ -666,7 +661,7 @@ IEditor *locateEditor(const char *property, const QString &entry)
|
|
|
|
|
// Return converted command output, remove '\r' read on Windows
|
|
|
|
|
static inline QString commandOutputFromLocal8Bit(const QByteArray &a)
|
|
|
|
|
{
|
|
|
|
|
return Utils::SynchronousProcess::normalizeNewlines(QString::fromLocal8Bit(a));
|
|
|
|
|
return SynchronousProcess::normalizeNewlines(QString::fromLocal8Bit(a));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return converted command output split into lines
|
|
|
|
|
@@ -796,10 +791,10 @@ bool GitClient::managesFile(const QString &workingDirectory, const QString &file
|
|
|
|
|
VcsBasePlugin::SuppressCommandLogging);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VcsBase::VcsBaseEditorWidget *GitClient::findExistingVCSEditor(const char *registerDynamicProperty,
|
|
|
|
|
const QString &dynamicPropertyValue) const
|
|
|
|
|
VcsBaseEditorWidget *GitClient::findExistingVCSEditor(const char *registerDynamicProperty,
|
|
|
|
|
const QString &dynamicPropertyValue) const
|
|
|
|
|
{
|
|
|
|
|
VcsBase::VcsBaseEditorWidget *rc = 0;
|
|
|
|
|
VcsBaseEditorWidget *rc = 0;
|
|
|
|
|
IEditor *outputEditor = locateEditor(registerDynamicProperty, dynamicPropertyValue);
|
|
|
|
|
if (!outputEditor)
|
|
|
|
|
return 0;
|
|
|
|
|
@@ -937,16 +932,16 @@ void GitClient::stage(const QString &patch, bool revert)
|
|
|
|
|
* (using the file's codec). Makes use of a dynamic property to find an
|
|
|
|
|
* existing instance and to reuse it (in case, say, 'git diff foo' is
|
|
|
|
|
* already open). */
|
|
|
|
|
VcsBase::VcsBaseEditorWidget *GitClient::createVcsEditor(
|
|
|
|
|
VcsBaseEditorWidget *GitClient::createVcsEditor(
|
|
|
|
|
Id id,
|
|
|
|
|
QString title,
|
|
|
|
|
const QString &source, // Source file or directory
|
|
|
|
|
CodecType codecType,
|
|
|
|
|
const char *registerDynamicProperty, // Dynamic property and value to identify that editor
|
|
|
|
|
const QString &dynamicPropertyValue,
|
|
|
|
|
VcsBase::VcsBaseEditorParameterWidget *configWidget) const
|
|
|
|
|
VcsBaseEditorParameterWidget *configWidget) const
|
|
|
|
|
{
|
|
|
|
|
VcsBase::VcsBaseEditorWidget *rc = 0;
|
|
|
|
|
VcsBaseEditorWidget *rc = 0;
|
|
|
|
|
QTC_CHECK(!findExistingVCSEditor(registerDynamicProperty, dynamicPropertyValue));
|
|
|
|
|
|
|
|
|
|
// Create new, set wait message, set up with source and codec
|
|
|
|
|
@@ -1024,8 +1019,7 @@ void GitClient::diff(const QString &workingDirectory,
|
|
|
|
|
void GitClient::diff(const QString &workingDirectory, const QString &fileName) const
|
|
|
|
|
{
|
|
|
|
|
const QString title = tr("Git Diff \"%1\"").arg(fileName);
|
|
|
|
|
const QString sourceFile = VcsBase::VcsBaseEditor::getSource(
|
|
|
|
|
workingDirectory, fileName);
|
|
|
|
|
const QString sourceFile = VcsBaseEditor::getSource(workingDirectory, fileName);
|
|
|
|
|
const QString documentId = QLatin1String("File:") + sourceFile;
|
|
|
|
|
DiffEditor::DiffEditorDocument *diffEditorDocument =
|
|
|
|
|
DiffEditor::DiffEditorManager::find(documentId);
|
|
|
|
|
@@ -1083,7 +1077,7 @@ void GitClient::status(const QString &workingDirectory)
|
|
|
|
|
QStringList statusArgs = statusArguments();
|
|
|
|
|
statusArgs << QLatin1String("-u");
|
|
|
|
|
VcsOutputWindow::setRepository(workingDirectory);
|
|
|
|
|
VcsBase::Command *command = executeGit(workingDirectory, statusArgs, 0, true);
|
|
|
|
|
VcsCommand *command = executeGit(workingDirectory, statusArgs, 0, true);
|
|
|
|
|
connect(command, SIGNAL(finished(bool,int,QVariant)), VcsOutputWindow::instance(), SLOT(clearRepository()),
|
|
|
|
|
Qt::QueuedConnection);
|
|
|
|
|
}
|
|
|
|
|
@@ -1095,7 +1089,7 @@ void GitClient::log(const QString &workingDirectory, const QString &fileName,
|
|
|
|
|
const QString title = tr("Git Log \"%1\"").arg(msgArg);
|
|
|
|
|
const Id editorId = Git::Constants::GIT_LOG_EDITOR_ID;
|
|
|
|
|
const QString sourceFile = VcsBaseEditor::getSource(workingDirectory, fileName);
|
|
|
|
|
VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("logFileName", sourceFile);
|
|
|
|
|
VcsBaseEditorWidget *editor = findExistingVCSEditor("logFileName", sourceFile);
|
|
|
|
|
if (!editor)
|
|
|
|
|
editor = createVcsEditor(editorId, title, sourceFile, CodecLogOutput, "logFileName", sourceFile,
|
|
|
|
|
new GitLogArgumentsWidget(this, workingDirectory,
|
|
|
|
|
@@ -1129,7 +1123,7 @@ void GitClient::reflog(const QString &workingDirectory)
|
|
|
|
|
{
|
|
|
|
|
const QString title = tr("Git Reflog \"%1\"").arg(workingDirectory);
|
|
|
|
|
const Id editorId = Git::Constants::GIT_LOG_EDITOR_ID;
|
|
|
|
|
VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("reflogRepository", workingDirectory);
|
|
|
|
|
VcsBaseEditorWidget *editor = findExistingVCSEditor("reflogRepository", workingDirectory);
|
|
|
|
|
if (!editor) {
|
|
|
|
|
editor = createVcsEditor(editorId, title, workingDirectory, CodecLogOutput,
|
|
|
|
|
"reflogRepository", workingDirectory, 0);
|
|
|
|
|
@@ -1220,7 +1214,7 @@ void GitClient::slotBlameRevisionRequested(const QString &workingDirectory, cons
|
|
|
|
|
|
|
|
|
|
QTextCodec *GitClient::getSourceCodec(const QString &file) const
|
|
|
|
|
{
|
|
|
|
|
return QFileInfo(file).isFile() ? VcsBase::VcsBaseEditor::getCodec(file)
|
|
|
|
|
return QFileInfo(file).isFile() ? VcsBaseEditor::getCodec(file)
|
|
|
|
|
: encoding(file, "gui.encoding");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1231,11 +1225,11 @@ void GitClient::blame(const QString &workingDirectory,
|
|
|
|
|
int lineNumber)
|
|
|
|
|
{
|
|
|
|
|
const Id editorId = Git::Constants::GIT_BLAME_EDITOR_ID;
|
|
|
|
|
const QString id = VcsBase::VcsBaseEditor::getTitleId(workingDirectory, QStringList(fileName), revision);
|
|
|
|
|
const QString id = VcsBaseEditor::getTitleId(workingDirectory, QStringList(fileName), revision);
|
|
|
|
|
const QString title = tr("Git Blame \"%1\"").arg(id);
|
|
|
|
|
const QString sourceFile = VcsBase::VcsBaseEditor::getSource(workingDirectory, fileName);
|
|
|
|
|
const QString sourceFile = VcsBaseEditor::getSource(workingDirectory, fileName);
|
|
|
|
|
|
|
|
|
|
VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("blameFileName", id);
|
|
|
|
|
VcsBaseEditorWidget *editor = findExistingVCSEditor("blameFileName", id);
|
|
|
|
|
if (!editor) {
|
|
|
|
|
GitBlameArgumentsWidget *argWidget =
|
|
|
|
|
new GitBlameArgumentsWidget(this, workingDirectory, args,
|
|
|
|
|
@@ -1793,8 +1787,7 @@ void GitClient::branchesForCommit(const QString &revision)
|
|
|
|
|
DiffEditor::DiffEditorController *controller
|
|
|
|
|
= qobject_cast<DiffEditor::DiffEditorController *>(sender());
|
|
|
|
|
QString workingDirectory = controller->workingDirectory();
|
|
|
|
|
VcsBase::Command *command = new VcsBase::Command(gitExecutable(), workingDirectory,
|
|
|
|
|
processEnvironment());
|
|
|
|
|
VcsCommand *command = new VcsCommand(gitExecutable(), workingDirectory, processEnvironment());
|
|
|
|
|
command->setCodec(getSourceCodec(currentDocumentPath()));
|
|
|
|
|
|
|
|
|
|
connect(command, SIGNAL(output(QString)), controller,
|
|
|
|
|
@@ -1991,7 +1984,7 @@ bool GitClient::synchronousForEachRefCmd(const QString &workingDirectory, QStrin
|
|
|
|
|
QByteArray errorText;
|
|
|
|
|
const bool rc = fullySynchronousGit(workingDirectory, args, &outputText, &errorText,
|
|
|
|
|
VcsBasePlugin::SuppressCommandLogging);
|
|
|
|
|
*output = Utils::SynchronousProcess::normalizeNewlines(QString::fromUtf8(outputText));
|
|
|
|
|
*output = SynchronousProcess::normalizeNewlines(QString::fromUtf8(outputText));
|
|
|
|
|
if (!rc)
|
|
|
|
|
msgCannotRun(args, workingDirectory, errorText, errorMessage);
|
|
|
|
|
|
|
|
|
|
@@ -2191,12 +2184,12 @@ bool GitClient::synchronousApplyPatch(const QString &workingDirectory,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Factory function to create an asynchronous command
|
|
|
|
|
VcsBase::Command *GitClient::createCommand(const QString &workingDirectory,
|
|
|
|
|
VcsBase::VcsBaseEditorWidget* editor,
|
|
|
|
|
bool useOutputToWindow,
|
|
|
|
|
int editorLineNumber)
|
|
|
|
|
VcsCommand *GitClient::createCommand(const QString &workingDirectory,
|
|
|
|
|
VcsBaseEditorWidget* editor,
|
|
|
|
|
bool useOutputToWindow,
|
|
|
|
|
int editorLineNumber)
|
|
|
|
|
{
|
|
|
|
|
VcsBase::Command *command = new VcsBase::Command(gitExecutable(), workingDirectory, processEnvironment());
|
|
|
|
|
VcsCommand *command = new VcsCommand(gitExecutable(), workingDirectory, processEnvironment());
|
|
|
|
|
command->setCodec(getSourceCodec(currentDocumentPath()));
|
|
|
|
|
command->setCookie(QVariant(editorLineNumber));
|
|
|
|
|
if (editor) {
|
|
|
|
|
@@ -2217,17 +2210,17 @@ VcsBase::Command *GitClient::createCommand(const QString &workingDirectory,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Execute a single command
|
|
|
|
|
VcsBase::Command *GitClient::executeGit(const QString &workingDirectory,
|
|
|
|
|
const QStringList &arguments,
|
|
|
|
|
VcsBase::VcsBaseEditorWidget* editor,
|
|
|
|
|
bool useOutputToWindow,
|
|
|
|
|
unsigned additionalFlags,
|
|
|
|
|
int editorLineNumber)
|
|
|
|
|
VcsCommand *GitClient::executeGit(const QString &workingDirectory,
|
|
|
|
|
const QStringList &arguments,
|
|
|
|
|
VcsBaseEditorWidget* editor,
|
|
|
|
|
bool useOutputToWindow,
|
|
|
|
|
unsigned additionalFlags,
|
|
|
|
|
int editorLineNumber)
|
|
|
|
|
{
|
|
|
|
|
VcsOutputWindow::appendCommand(workingDirectory,
|
|
|
|
|
Utils::FileName::fromUserInput(settings()->stringValue(GitSettings::binaryPathKey)),
|
|
|
|
|
arguments);
|
|
|
|
|
VcsBase::Command *command = createCommand(workingDirectory, editor, useOutputToWindow, editorLineNumber);
|
|
|
|
|
FileName::fromUserInput(settings()->stringValue(GitSettings::binaryPathKey)),
|
|
|
|
|
arguments);
|
|
|
|
|
VcsCommand *command = createCommand(workingDirectory, editor, useOutputToWindow, editorLineNumber);
|
|
|
|
|
command->addJob(arguments, settings()->intValue(GitSettings::timeoutKey));
|
|
|
|
|
command->addFlags(additionalFlags);
|
|
|
|
|
command->execute();
|
|
|
|
|
@@ -2239,11 +2232,11 @@ QProcessEnvironment GitClient::processEnvironment() const
|
|
|
|
|
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
|
|
|
|
|
QString gitPath = settings()->stringValue(GitSettings::pathKey);
|
|
|
|
|
if (!gitPath.isEmpty()) {
|
|
|
|
|
gitPath += Utils::HostOsInfo::pathListSeparator();
|
|
|
|
|
gitPath += HostOsInfo::pathListSeparator();
|
|
|
|
|
gitPath += environment.value(QLatin1String("PATH"));
|
|
|
|
|
environment.insert(QLatin1String("PATH"), gitPath);
|
|
|
|
|
}
|
|
|
|
|
if (Utils::HostOsInfo::isWindowsHost()
|
|
|
|
|
if (HostOsInfo::isWindowsHost()
|
|
|
|
|
&& settings()->boolValue(GitSettings::winSetHomeEnvironmentKey)) {
|
|
|
|
|
environment.insert(QLatin1String("HOME"), QDir::toNativeSeparators(QDir::homePath()));
|
|
|
|
|
}
|
|
|
|
|
@@ -2289,10 +2282,10 @@ bool GitClient::isValidRevision(const QString &revision) const
|
|
|
|
|
|
|
|
|
|
// Synchronous git execution using Utils::SynchronousProcess, with
|
|
|
|
|
// log windows updating.
|
|
|
|
|
Utils::SynchronousProcessResponse GitClient::synchronousGit(const QString &workingDirectory,
|
|
|
|
|
const QStringList &gitArguments,
|
|
|
|
|
unsigned flags,
|
|
|
|
|
QTextCodec *outputCodec) const
|
|
|
|
|
SynchronousProcessResponse GitClient::synchronousGit(const QString &workingDirectory,
|
|
|
|
|
const QStringList &gitArguments,
|
|
|
|
|
unsigned flags,
|
|
|
|
|
QTextCodec *outputCodec) const
|
|
|
|
|
{
|
|
|
|
|
return VcsBasePlugin::runVcs(workingDirectory, gitExecutable(), gitArguments,
|
|
|
|
|
settings()->intValue(GitSettings::timeoutKey) * 1000,
|
|
|
|
|
@@ -2305,7 +2298,7 @@ bool GitClient::fullySynchronousGit(const QString &workingDirectory,
|
|
|
|
|
QByteArray* errorText,
|
|
|
|
|
unsigned flags) const
|
|
|
|
|
{
|
|
|
|
|
VcsBase::Command command(gitExecutable(), workingDirectory, processEnvironment());
|
|
|
|
|
VcsCommand command(gitExecutable(), workingDirectory, processEnvironment());
|
|
|
|
|
command.addFlags(flags);
|
|
|
|
|
return command.runFullySynchronous(gitArguments,
|
|
|
|
|
settings()->intValue(GitSettings::timeoutKey) * 1000,
|
|
|
|
|
@@ -2360,8 +2353,8 @@ void GitClient::updateSubmodulesIfNeeded(const QString &workingDirectory, bool p
|
|
|
|
|
QStringList arguments;
|
|
|
|
|
arguments << QLatin1String("submodule") << QLatin1String("update");
|
|
|
|
|
|
|
|
|
|
VcsBase::Command *cmd = executeGit(workingDirectory, arguments, 0, true,
|
|
|
|
|
VcsBasePlugin::ExpectRepoChanges);
|
|
|
|
|
VcsCommand *cmd = executeGit(workingDirectory, arguments, 0, true,
|
|
|
|
|
VcsBasePlugin::ExpectRepoChanges);
|
|
|
|
|
connect(cmd, SIGNAL(finished(bool,int,QVariant)), this, SLOT(finishSubmoduleUpdate()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2555,7 +2548,7 @@ QStringList GitClient::synchronousRepositoryBranches(const QString &repositoryUR
|
|
|
|
|
const unsigned flags = VcsBasePlugin::SshPasswordPrompt
|
|
|
|
|
| VcsBasePlugin::SuppressStdErrInLogWindow
|
|
|
|
|
| VcsBasePlugin::SuppressFailMessageInLogWindow;
|
|
|
|
|
const Utils::SynchronousProcessResponse resp = synchronousGit(QString(), arguments, flags);
|
|
|
|
|
const SynchronousProcessResponse resp = synchronousGit(QString(), arguments, flags);
|
|
|
|
|
QStringList branches;
|
|
|
|
|
branches << tr("<Detached HEAD>");
|
|
|
|
|
QString headSha;
|
|
|
|
|
@@ -2605,8 +2598,8 @@ void GitClient::launchGitK(const QString &workingDirectory, const QString &fileN
|
|
|
|
|
VcsOutputWindow::appendSilently(msgCannotLaunch(gitkPath));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Utils::Environment sysEnv = Utils::Environment::systemEnvironment();
|
|
|
|
|
const Utils::FileName exec = sysEnv.searchInPath(QLatin1String("gitk"));
|
|
|
|
|
Environment sysEnv = Environment::systemEnvironment();
|
|
|
|
|
const FileName exec = sysEnv.searchInPath(QLatin1String("gitk"));
|
|
|
|
|
|
|
|
|
|
if (!exec.isEmpty() && tryLauchingGitK(env, workingDirectory, fileName,
|
|
|
|
|
exec.parentDir().toString())) {
|
|
|
|
|
@@ -2630,7 +2623,7 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env,
|
|
|
|
|
{
|
|
|
|
|
QString binary = gitBinDirectory + QLatin1String("/gitk");
|
|
|
|
|
QStringList arguments;
|
|
|
|
|
if (Utils::HostOsInfo::isWindowsHost()) {
|
|
|
|
|
if (HostOsInfo::isWindowsHost()) {
|
|
|
|
|
// If git/bin is in path, use 'wish' shell to run. Otherwise (git/cmd), directly run gitk
|
|
|
|
|
QString wish = gitBinDirectory + QLatin1String("/wish");
|
|
|
|
|
if (QFileInfo(wish + QLatin1String(".exe")).exists()) {
|
|
|
|
|
@@ -2640,10 +2633,10 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env,
|
|
|
|
|
}
|
|
|
|
|
const QString gitkOpts = settings()->stringValue(GitSettings::gitkOptionsKey);
|
|
|
|
|
if (!gitkOpts.isEmpty())
|
|
|
|
|
arguments.append(Utils::QtcProcess::splitArgs(gitkOpts, Utils::HostOsInfo::hostOs()));
|
|
|
|
|
arguments.append(QtcProcess::splitArgs(gitkOpts, HostOsInfo::hostOs()));
|
|
|
|
|
if (!fileName.isEmpty())
|
|
|
|
|
arguments << QLatin1String("--") << fileName;
|
|
|
|
|
VcsOutputWindow::appendCommand(workingDirectory, Utils::FileName::fromString(binary), arguments);
|
|
|
|
|
VcsOutputWindow::appendCommand(workingDirectory, FileName::fromString(binary), arguments);
|
|
|
|
|
// This should always use QProcess::startDetached (as not to kill
|
|
|
|
|
// the child), but that does not have an environment parameter.
|
|
|
|
|
bool success = false;
|
|
|
|
|
@@ -2666,7 +2659,7 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env,
|
|
|
|
|
|
|
|
|
|
bool GitClient::launchGitGui(const QString &workingDirectory) {
|
|
|
|
|
bool success;
|
|
|
|
|
Utils::FileName gitBinary = gitExecutable(&success);
|
|
|
|
|
FileName gitBinary = gitExecutable(&success);
|
|
|
|
|
if (success) {
|
|
|
|
|
success = QProcess::startDetached(gitBinary.toString(), QStringList(QLatin1String("gui")),
|
|
|
|
|
workingDirectory);
|
|
|
|
|
@@ -2678,25 +2671,25 @@ bool GitClient::launchGitGui(const QString &workingDirectory) {
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Utils::FileName GitClient::gitBinDirectory()
|
|
|
|
|
FileName GitClient::gitBinDirectory()
|
|
|
|
|
{
|
|
|
|
|
const QString git = gitExecutable().toString();
|
|
|
|
|
if (git.isEmpty())
|
|
|
|
|
return Utils::FileName();
|
|
|
|
|
return FileName();
|
|
|
|
|
|
|
|
|
|
// Is 'git\cmd' in the path (folder containing .bats)?
|
|
|
|
|
QString path = QFileInfo(git).absolutePath();
|
|
|
|
|
// Git for Windows (msysGit) has git and gitk redirect executables in {setup dir}/cmd
|
|
|
|
|
// and the real binaries are in {setup dir}/bin. If cmd is configured in PATH
|
|
|
|
|
// or in Git settings, return bin instead.
|
|
|
|
|
if (Utils::HostOsInfo::isWindowsHost()
|
|
|
|
|
&& path.endsWith(QLatin1String("/cmd"), Utils::HostOsInfo::fileNameCaseSensitivity())) {
|
|
|
|
|
if (HostOsInfo::isWindowsHost()
|
|
|
|
|
&& path.endsWith(QLatin1String("/cmd"), HostOsInfo::fileNameCaseSensitivity())) {
|
|
|
|
|
path.replace(path.size() - 3, 3, QLatin1String("bin"));
|
|
|
|
|
}
|
|
|
|
|
return Utils::FileName::fromString(path);
|
|
|
|
|
return FileName::fromString(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Utils::FileName GitClient::gitExecutable(bool *ok, QString *errorMessage) const
|
|
|
|
|
FileName GitClient::gitExecutable(bool *ok, QString *errorMessage) const
|
|
|
|
|
{
|
|
|
|
|
return settings()->gitExecutable(ok, errorMessage);
|
|
|
|
|
}
|
|
|
|
|
@@ -2735,7 +2728,7 @@ bool GitClient::readDataFromCommit(const QString &repoDirectory, const QString &
|
|
|
|
|
*errorMessage = tr("Cannot retrieve last commit data of repository \"%1\".").arg(repoDirectory);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
QTextCodec *authorCodec = Utils::HostOsInfo::isWindowsHost()
|
|
|
|
|
QTextCodec *authorCodec = HostOsInfo::isWindowsHost()
|
|
|
|
|
? QTextCodec::codecForName("UTF-8")
|
|
|
|
|
: commitData.commitEncoding;
|
|
|
|
|
commitData.amendSHA1 = QString::fromLatin1(shiftLogLine(outputText));
|
|
|
|
|
@@ -2809,7 +2802,7 @@ bool GitClient::getCommitData(const QString &workingDirectory,
|
|
|
|
|
// Filter out untracked files that are not part of the project
|
|
|
|
|
QStringList untrackedFiles = commitData.filterFiles(UntrackedFile);
|
|
|
|
|
|
|
|
|
|
VcsBase::VcsBaseSubmitEditor::filterUntrackedFilesOfProject(repoDirectory, &untrackedFiles);
|
|
|
|
|
VcsBaseSubmitEditor::filterUntrackedFilesOfProject(repoDirectory, &untrackedFiles);
|
|
|
|
|
QList<CommitData::StateFilePair> filteredFiles;
|
|
|
|
|
QList<CommitData::StateFilePair>::const_iterator it = commitData.files.constBegin();
|
|
|
|
|
for ( ; it != commitData.files.constEnd(); ++it) {
|
|
|
|
|
@@ -2855,7 +2848,7 @@ bool GitClient::getCommitData(const QString &workingDirectory,
|
|
|
|
|
if (!QFile::exists(templateFilename))
|
|
|
|
|
templateFilename = gitDirectory.absoluteFilePath(QLatin1String("SQUASH_MSG"));
|
|
|
|
|
if (!QFile::exists(templateFilename)) {
|
|
|
|
|
Utils::FileName templateName = Utils::FileName::fromUserInput(
|
|
|
|
|
FileName templateName = FileName::fromUserInput(
|
|
|
|
|
readConfigValue(workingDirectory, QLatin1String("commit.template")));
|
|
|
|
|
templateFilename = templateName.toString();
|
|
|
|
|
}
|
|
|
|
|
@@ -2864,7 +2857,7 @@ bool GitClient::getCommitData(const QString &workingDirectory,
|
|
|
|
|
const QFileInfo templateFileInfo(templateFilename);
|
|
|
|
|
if (templateFileInfo.isRelative())
|
|
|
|
|
templateFilename = repoDirectory + QLatin1Char('/') + templateFilename;
|
|
|
|
|
Utils::FileReader reader;
|
|
|
|
|
FileReader reader;
|
|
|
|
|
if (!reader.fetch(templateFilename, QIODevice::Text, errorMessage))
|
|
|
|
|
return false;
|
|
|
|
|
*commitTemplate = QString::fromLocal8Bit(reader.data());
|
|
|
|
|
@@ -2900,7 +2893,7 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory,
|
|
|
|
|
CommitType commitType,
|
|
|
|
|
const QString &amendSHA1,
|
|
|
|
|
const QString &messageFile,
|
|
|
|
|
VcsBase::SubmitFileModel *model)
|
|
|
|
|
SubmitFileModel *model)
|
|
|
|
|
{
|
|
|
|
|
const QString renameSeparator = QLatin1String(" -> ");
|
|
|
|
|
|
|
|
|
|
@@ -3102,7 +3095,7 @@ void GitClient::fetch(const QString &workingDirectory, const QString &remote)
|
|
|
|
|
{
|
|
|
|
|
QStringList arguments(QLatin1String("fetch"));
|
|
|
|
|
arguments << (remote.isEmpty() ? QLatin1String("--all") : remote);
|
|
|
|
|
VcsBase::Command *command = executeGit(workingDirectory, arguments, 0, true);
|
|
|
|
|
VcsCommand *command = executeGit(workingDirectory, arguments, 0, true);
|
|
|
|
|
command->setCookie(workingDirectory);
|
|
|
|
|
connect(command, SIGNAL(success(QVariant)), this, SLOT(fetchFinished(QVariant)));
|
|
|
|
|
}
|
|
|
|
|
@@ -3115,10 +3108,10 @@ bool GitClient::executeAndHandleConflicts(const QString &workingDirectory,
|
|
|
|
|
const unsigned flags = VcsBasePlugin::SshPasswordPrompt
|
|
|
|
|
| VcsBasePlugin::ShowStdOutInLogWindow
|
|
|
|
|
| VcsBasePlugin::ExpectRepoChanges;
|
|
|
|
|
const Utils::SynchronousProcessResponse resp = synchronousGit(workingDirectory, arguments, flags);
|
|
|
|
|
const SynchronousProcessResponse resp = synchronousGit(workingDirectory, arguments, flags);
|
|
|
|
|
ConflictHandler conflictHandler(0, workingDirectory, abortCommand);
|
|
|
|
|
// Notify about changed files or abort the rebase.
|
|
|
|
|
const bool ok = resp.result == Utils::SynchronousProcessResponse::Finished;
|
|
|
|
|
const bool ok = resp.result == SynchronousProcessResponse::Finished;
|
|
|
|
|
if (!ok) {
|
|
|
|
|
conflictHandler.readStdOut(resp.stdOut);
|
|
|
|
|
conflictHandler.readStdErr(resp.stdErr);
|
|
|
|
|
@@ -3264,8 +3257,8 @@ void GitClient::subversionLog(const QString &workingDirectory)
|
|
|
|
|
// Create a command editor, no highlighting or interaction.
|
|
|
|
|
const QString title = tr("Git SVN Log");
|
|
|
|
|
const Id editorId = Git::Constants::C_GIT_COMMAND_LOG_EDITOR;
|
|
|
|
|
const QString sourceFile = VcsBase::VcsBaseEditor::getSource(workingDirectory, QStringList());
|
|
|
|
|
VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("svnLog", sourceFile);
|
|
|
|
|
const QString sourceFile = VcsBaseEditor::getSource(workingDirectory, QStringList());
|
|
|
|
|
VcsBaseEditorWidget *editor = findExistingVCSEditor("svnLog", sourceFile);
|
|
|
|
|
if (!editor)
|
|
|
|
|
editor = createVcsEditor(editorId, title, sourceFile, CodecNone, "svnLog", sourceFile, 0);
|
|
|
|
|
editor->setWorkingDirectory(workingDirectory);
|
|
|
|
|
@@ -3329,10 +3322,10 @@ void GitClient::asyncCommand(const QString &workingDirectory, const QStringList
|
|
|
|
|
// and without timeout
|
|
|
|
|
QString gitCommand = arguments.first();
|
|
|
|
|
VcsOutputWindow::appendCommand(workingDirectory, settings()->binaryPath(), arguments);
|
|
|
|
|
VcsBase::Command *command = createCommand(workingDirectory, 0, true);
|
|
|
|
|
VcsCommand *command = createCommand(workingDirectory, 0, true);
|
|
|
|
|
new ConflictHandler(command, workingDirectory, gitCommand);
|
|
|
|
|
if (hasProgress)
|
|
|
|
|
command->setProgressParser(new ProgressParser);
|
|
|
|
|
command->setProgressParser(new GitProgressParser);
|
|
|
|
|
command->addJob(arguments, -1);
|
|
|
|
|
command->execute();
|
|
|
|
|
command->setCookie(workingDirectory);
|
|
|
|
|
@@ -3398,8 +3391,8 @@ void GitClient::stashPop(const QString &workingDirectory, const QString &stash)
|
|
|
|
|
arguments << QLatin1String("pop");
|
|
|
|
|
if (!stash.isEmpty())
|
|
|
|
|
arguments << stash;
|
|
|
|
|
VcsBase::Command *cmd = executeGit(workingDirectory, arguments, 0, true,
|
|
|
|
|
VcsBasePlugin::ExpectRepoChanges);
|
|
|
|
|
VcsCommand *cmd = executeGit(workingDirectory, arguments, 0, true,
|
|
|
|
|
VcsBasePlugin::ExpectRepoChanges);
|
|
|
|
|
new ConflictHandler(cmd, workingDirectory);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -3474,7 +3467,7 @@ QByteArray GitClient::readConfigBytes(const QString &workingDirectory, const QSt
|
|
|
|
|
if (!fullySynchronousGit(workingDirectory, arguments, &outputText, &errorText,
|
|
|
|
|
VcsBasePlugin::SuppressCommandLogging))
|
|
|
|
|
return QByteArray();
|
|
|
|
|
if (Utils::HostOsInfo::isWindowsHost())
|
|
|
|
|
if (HostOsInfo::isWindowsHost())
|
|
|
|
|
outputText.replace("\r\n", "\n");
|
|
|
|
|
return outputText;
|
|
|
|
|
}
|
|
|
|
|
@@ -3484,11 +3477,11 @@ QString GitClient::readConfigValue(const QString &workingDirectory, const QStrin
|
|
|
|
|
{
|
|
|
|
|
// msysGit always uses UTF-8 for configuration:
|
|
|
|
|
// https://github.com/msysgit/msysgit/wiki/Git-for-Windows-Unicode-Support#convert-config-files
|
|
|
|
|
static QTextCodec *codec = Utils::HostOsInfo::isWindowsHost()
|
|
|
|
|
static QTextCodec *codec = HostOsInfo::isWindowsHost()
|
|
|
|
|
? QTextCodec::codecForName("UTF-8")
|
|
|
|
|
: QTextCodec::codecForLocale();
|
|
|
|
|
const QByteArray value = readConfigBytes(workingDirectory, configVar).trimmed();
|
|
|
|
|
return Utils::SynchronousProcess::normalizeNewlines(codec->toUnicode(value));
|
|
|
|
|
return SynchronousProcess::normalizeNewlines(codec->toUnicode(value));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GitClient::cloneRepository(const QString &directory,const QByteArray &url)
|
|
|
|
|
@@ -3509,9 +3502,9 @@ bool GitClient::cloneRepository(const QString &directory,const QByteArray &url)
|
|
|
|
|
|
|
|
|
|
arguments.clear();
|
|
|
|
|
arguments << QLatin1String("fetch");
|
|
|
|
|
const Utils::SynchronousProcessResponse resp =
|
|
|
|
|
const SynchronousProcessResponse resp =
|
|
|
|
|
synchronousGit(workingDirectory.path(), arguments, flags);
|
|
|
|
|
if (resp.result != Utils::SynchronousProcessResponse::Finished)
|
|
|
|
|
if (resp.result != SynchronousProcessResponse::Finished)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
arguments.clear();
|
|
|
|
|
@@ -3533,11 +3526,11 @@ bool GitClient::cloneRepository(const QString &directory,const QByteArray &url)
|
|
|
|
|
QStringList arguments(QLatin1String("clone"));
|
|
|
|
|
arguments << QLatin1String(url) << workingDirectory.dirName();
|
|
|
|
|
workingDirectory.cdUp();
|
|
|
|
|
const Utils::SynchronousProcessResponse resp =
|
|
|
|
|
const SynchronousProcessResponse resp =
|
|
|
|
|
synchronousGit(workingDirectory.path(), arguments, flags);
|
|
|
|
|
// TODO: Turn this into a VcsBaseClient and use resetCachedVcsInfo(...)
|
|
|
|
|
VcsManager::resetVersionControlForDirectory(workingDirectory.absolutePath());
|
|
|
|
|
return (resp.result == Utils::SynchronousProcessResponse::Finished);
|
|
|
|
|
return (resp.result == SynchronousProcessResponse::Finished);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -3563,7 +3556,7 @@ GitSettings *GitClient::settings() const
|
|
|
|
|
// determine version as '(major << 16) + (minor << 8) + patch' or 0.
|
|
|
|
|
unsigned GitClient::gitVersion(QString *errorMessage) const
|
|
|
|
|
{
|
|
|
|
|
const Utils::FileName newGitBinary = gitExecutable();
|
|
|
|
|
const FileName newGitBinary = gitExecutable();
|
|
|
|
|
if (m_gitVersionForBinary != newGitBinary && !newGitBinary.isEmpty()) {
|
|
|
|
|
// Do not execute repeatedly if that fails (due to git
|
|
|
|
|
// not being installed) until settings are changed.
|
|
|
|
|
|