summaryrefslogtreecommitdiff
path: root/src/plugins/git/gitclient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/git/gitclient.cpp')
-rw-r--r--src/plugins/git/gitclient.cpp1034
1 files changed, 700 insertions, 334 deletions
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 949705242c..124a0d63a4 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -44,6 +44,7 @@
#include <coreplugin/vcsmanager.h>
#include <coreplugin/id.h>
#include <coreplugin/iversioncontrol.h>
+#include <coreplugin/coreconstants.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
@@ -84,6 +85,100 @@ namespace Internal {
using VcsBase::VcsBasePlugin;
+class GitDiffSwitcher : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum DiffType {
+ DiffRepository,
+ DiffFile,
+ DiffFileList,
+ DiffProjectList,
+ DiffBranch,
+ DiffShow
+ };
+
+ GitDiffSwitcher(Core::IEditor *parentEditor, GitClient *gitClient)
+ : QObject(parentEditor),
+ m_editor(parentEditor),
+ m_gitClient(gitClient)
+ {
+ m_usingDiffEditor = gitClient->settings()->boolValue(GitSettings::useDiffEditorKey);
+ QIcon actionIcon = m_usingDiffEditor
+ ? QIcon(QLatin1String(Core::Constants::ICON_TEXT_DIFF))
+ : QIcon(QLatin1String(Core::Constants::ICON_SIDE_BY_SIDE_DIFF));
+
+ const QString actionToolTip = m_usingDiffEditor
+ ? tr("Switch to Text Diff Editor")
+ : tr("Switch to Side By Side Diff Editor");
+
+ QAction *switchAction = new QAction(actionIcon, actionToolTip, parentEditor);
+ parentEditor->toolBar()->addAction(switchAction);
+ connect(switchAction, SIGNAL(triggered()), this, SLOT(execute()));
+ }
+
+ void setWorkingDirectory(const QString &workingDir) { m_workingDirectory = workingDir; }
+ void setDiffType(DiffType type) { m_diffType = type; }
+ void setFileName(const QString &fileName) { m_fileName = fileName; }
+ void setFileList(const QStringList &stagedFiles, const QStringList &unstagedFiles)
+ {
+ m_stagedFiles = stagedFiles;
+ m_unstagedFiles = unstagedFiles;
+ }
+ void setProjectList(const QStringList &projectFiles) { m_projectFiles = projectFiles; }
+ void setBranchName(const QString &branchName) { m_branchName = branchName; }
+ void setId(const QString &id) { m_id = id; }
+ void setDisplayName(const QString &displayName) { m_displayName = displayName; }
+ void setBaseArguments(const QStringList &args) { m_baseArguments = args; }
+
+public slots:
+ void execute();
+
+private:
+ Core::IEditor *m_editor;
+ GitClient *m_gitClient;
+ QString m_workingDirectory;
+ DiffType m_diffType;
+ bool m_usingDiffEditor;
+ QString m_fileName;
+ QStringList m_stagedFiles;
+ QStringList m_unstagedFiles;
+ QStringList m_projectFiles;
+ QString m_branchName;
+ QString m_id;
+ QString m_displayName;
+ QStringList m_baseArguments;
+};
+
+void GitDiffSwitcher::execute()
+{
+ m_gitClient->settings()->setValue(GitSettings::useDiffEditorKey, !m_usingDiffEditor);
+ switch (m_diffType) {
+ case DiffRepository:
+ m_gitClient->diff(m_workingDirectory, QStringList(), QStringList());
+ break;
+ case DiffFile:
+ m_gitClient->diff(m_workingDirectory, m_fileName);
+ break;
+ case DiffFileList:
+ m_gitClient->diff(m_workingDirectory, m_unstagedFiles, m_stagedFiles);
+ break;
+ case DiffProjectList:
+ m_gitClient->diff(m_workingDirectory, m_projectFiles, QStringList());
+ break;
+ case DiffBranch:
+ m_gitClient->diffBranch(m_workingDirectory, m_baseArguments, m_branchName);
+ break;
+ case DiffShow:
+ m_gitClient->show(m_fileName, m_id, m_baseArguments, m_displayName);
+ break;
+ default:
+ break;
+ }
+ Core::EditorManager::closeEditor(m_editor, false);
+}
+
class GitDiffHandler : public QObject
{
Q_OBJECT
@@ -132,9 +227,9 @@ public:
void show(const QString &id);
private slots:
- void slotShowDescriptionReceived(const QByteArray &data);
- void slotFileListReceived(const QByteArray &data);
- void slotFileContentsReceived(const QByteArray &data);
+ void slotShowDescriptionReceived(const QString &data);
+ void slotFileListReceived(const QString &fileList);
+ void slotFileContentsReceived(const QString &contents);
private:
void collectShowDescription(const QString &id);
@@ -259,23 +354,24 @@ void GitDiffHandler::collectShowDescription(const QString &id)
return;
m_editor->clear(m_waitMessage);
VcsBase::Command *command = new VcsBase::Command(m_gitPath, m_workingDirectory, m_processEnvironment);
- connect(command, SIGNAL(outputData(QByteArray)), this, SLOT(slotShowDescriptionReceived(QByteArray)));
+ command->setCodec(m_editor->editorWidget()->codec());
+ connect(command, SIGNAL(output(QString)), this, SLOT(slotShowDescriptionReceived(QString)));
QStringList arguments;
- arguments << QLatin1String("show") << QLatin1String("-s") << QLatin1String("--format=fuller")
+ arguments << QLatin1String("show") << QLatin1String("-s")
<< QLatin1String(noColorOption) << QLatin1String(decorateOption) << id;
command->addJob(arguments, m_timeout);
command->execute();
}
-void GitDiffHandler::slotShowDescriptionReceived(const QByteArray &data)
+void GitDiffHandler::slotShowDescriptionReceived(const QString &description)
{
if (m_editor.isNull())
return;
- const QString description = m_editor->editorWidget()->codec()->toUnicode(data).remove(QLatin1Char('\r'));
-
DiffEditor::DiffShowEditor *editor = qobject_cast<DiffEditor::DiffShowEditor *>(m_editor);
- if (editor)
- editor->setDescription(description);
+ if (editor) {
+ editor->setDescription(GitPlugin::instance()->gitClient()->
+ extendedShowDescription(m_workingDirectory, description));
+ }
collectFilesList(QStringList()
<< m_requestedRevisionRange.begin.id
@@ -288,19 +384,19 @@ void GitDiffHandler::collectFilesList(const QStringList &additionalArguments)
return;
m_editor->clear(m_waitMessage);
VcsBase::Command *command = new VcsBase::Command(m_gitPath, m_workingDirectory, m_processEnvironment);
- connect(command, SIGNAL(outputData(QByteArray)), this, SLOT(slotFileListReceived(QByteArray)));
+ command->setCodec(m_editor->editorWidget()->codec());
+ connect(command, SIGNAL(output(QString)), this, SLOT(slotFileListReceived(QString)));
QStringList arguments;
arguments << QLatin1String("diff") << QLatin1String("--name-only") << additionalArguments;
command->addJob(arguments, m_timeout);
command->execute();
}
-void GitDiffHandler::slotFileListReceived(const QByteArray &data)
+void GitDiffHandler::slotFileListReceived(const QString &fileList)
{
if (m_editor.isNull())
return;
- const QString fileList = m_editor->editorWidget()->codec()->toUnicode(data).remove(QLatin1Char('\r'));
QStringList fileNames = fileList.split(QLatin1Char('\n'), QString::SkipEmptyParts);
fileNames.removeDuplicates();
@@ -355,11 +451,13 @@ void GitDiffHandler::collectFilesContents()
// prepare job here
VcsBase::Command *command = new VcsBase::Command(m_gitPath, m_workingDirectory, m_processEnvironment);
- connect(command, SIGNAL(outputData(QByteArray)), this, SLOT(slotFileContentsReceived(QByteArray)));
+ if (m_editor)
+ command->setCodec(m_editor->editorWidget()->codec());
+ connect(command, SIGNAL(output(QString)), this, SLOT(slotFileContentsReceived(QString)));
QString revisionArgument = (revision.type == Other)
? revision.id : QString();
- revisionArgument += QLatin1String(":./");
+ revisionArgument += QLatin1Char(':');
QStringList arguments;
arguments << QLatin1String("show") << revisionArgument + fileName;
command->addJob(arguments, m_timeout);
@@ -375,7 +473,7 @@ void GitDiffHandler::collectFilesContents()
feedEditor();
}
-void GitDiffHandler::slotFileContentsReceived(const QByteArray &data)
+void GitDiffHandler::slotFileContentsReceived(const QString &contents)
{
if (m_editor.isNull())
return;
@@ -392,7 +490,6 @@ void GitDiffHandler::slotFileContentsReceived(const QByteArray &data)
QMap<Revision, bool>::iterator itRevEnd
= revisions.end();
if (itRev != itRevEnd) {
- const QString contents = m_editor->editorWidget()->codec()->toUnicode(data).remove(QLatin1Char('\r'));
m_collectedRevisions[fileName][itRev.key()] = contents;
itRev = revisions.erase(itRev);
@@ -484,21 +581,26 @@ class GitCommitDiffArgumentsWidget : public BaseGitDiffArgumentsWidget
public:
GitCommitDiffArgumentsWidget(Git::Internal::GitClient *client, const QString &directory,
- const QStringList &args, const QStringList &unstaged,
- const QStringList &staged) :
- BaseGitDiffArgumentsWidget(client, directory, args),
- m_unstagedFileNames(unstaged),
- m_stagedFileNames(staged)
- { }
+ const QStringList &unstaged, const QStringList &staged) :
+ BaseGitDiffArgumentsWidget(client, directory, QStringList())
+ {
+ setFileNames(unstaged, staged);
+ }
+
+ void setFileNames(const QStringList &unstaged, const QStringList &staged)
+ {
+ m_unstagedFileNames = unstaged;
+ m_stagedFileNames = staged;
+ }
void executeCommand()
{
- m_client->diff(m_workingDirectory, arguments(), m_unstagedFileNames, m_stagedFileNames);
+ m_client->diff(m_workingDirectory, m_unstagedFileNames, m_stagedFileNames);
}
private:
- const QStringList m_unstagedFileNames;
- const QStringList m_stagedFileNames;
+ QStringList m_unstagedFileNames;
+ QStringList m_stagedFileNames;
};
class GitFileDiffArgumentsWidget : public BaseGitDiffArgumentsWidget
@@ -506,14 +608,14 @@ class GitFileDiffArgumentsWidget : public BaseGitDiffArgumentsWidget
Q_OBJECT
public:
GitFileDiffArgumentsWidget(Git::Internal::GitClient *client, const QString &directory,
- const QStringList &args, const QString &file) :
- BaseGitDiffArgumentsWidget(client, directory, args),
+ const QString &file) :
+ BaseGitDiffArgumentsWidget(client, directory, QStringList()),
m_fileName(file)
{ }
void executeCommand()
{
- m_client->diff(m_workingDirectory, arguments(), m_fileName);
+ m_client->diff(m_workingDirectory, m_fileName);
}
private:
@@ -532,7 +634,7 @@ public:
void executeCommand()
{
- m_client->diffBranch(m_workingDirectory, arguments(), m_branchName);
+ m_client->diffBranch(m_workingDirectory, baseArguments(), m_branchName);
}
private:
@@ -567,7 +669,7 @@ public:
void executeCommand()
{
- m_client->show(m_workingDirectory, m_id, arguments());
+ m_client->show(m_workingDirectory, m_id, baseArguments());
}
private:
@@ -612,7 +714,7 @@ public:
int line = -1;
if (m_editor)
line = m_editor->lineNumberOfCurrentEditor();
- m_client->blame(m_workingDirectory, arguments(), m_fileName, m_revision, line);
+ m_client->blame(m_workingDirectory, baseArguments(), m_fileName, m_revision, line);
}
private:
@@ -632,12 +734,11 @@ public:
const QString &directory,
bool enableAnnotationContextMenu,
const QStringList &args,
- const QStringList &fileNames) :
+ const QString &fileName) :
BaseGitDiffArgumentsWidget(client, directory, args),
m_client(client),
m_workingDirectory(directory),
- m_enableAnnotationContextMenu(enableAnnotationContextMenu),
- m_fileNames(fileNames)
+ m_enableAnnotationContextMenu(enableAnnotationContextMenu)
{
QTC_ASSERT(!directory.isEmpty(), return);
QToolButton *diffButton = addToggleButton(QLatin1String("--patch"), tr("Show Diff"),
@@ -653,18 +754,24 @@ public:
QToolButton *graphButton = addToggleButton(graphArguments, tr("Graph"),
tr("Show textual graph log."));
mapSetting(graphButton, m_client->settings()->boolPointer(GitSettings::graphLogKey));
+ setFileName(fileName);
+ }
+
+ void setFileName(const QString &fileNames)
+ {
+ m_fileName = fileNames;
}
void executeCommand()
{
- m_client->log(m_workingDirectory, m_fileNames, m_enableAnnotationContextMenu, arguments());
+ m_client->log(m_workingDirectory, m_fileName, m_enableAnnotationContextMenu, baseArguments());
}
private:
GitClient *m_client;
QString m_workingDirectory;
bool m_enableAnnotationContextMenu;
- QStringList m_fileNames;
+ QString m_fileName;
};
class ConflictHandler : public QObject
@@ -679,8 +786,8 @@ public:
m_command(command)
{
if (parentCommand) {
- parentCommand->setExpectChanges(true);
- connect(parentCommand, SIGNAL(outputData(QByteArray)), this, SLOT(readStdOut(QByteArray)));
+ parentCommand->addFlags(VcsBasePlugin::ExpectRepoChanges);
+ connect(parentCommand, SIGNAL(output(QString)), this, SLOT(readStdOut(QString)));
connect(parentCommand, SIGNAL(errorText(QString)), this, SLOT(readStdErr(QString)));
}
}
@@ -700,7 +807,8 @@ public:
}
}
- void readStdOutString(const QString &data)
+public slots:
+ void readStdOut(const QString &data)
{
static QRegExp patchFailedRE(QLatin1String("Patch failed at ([^\\n]*)"));
static QRegExp conflictedFilesRE(QLatin1String("Merge conflict in ([^\\n]*)"));
@@ -711,11 +819,6 @@ public:
m_files.append(conflictedFilesRE.cap(1));
}
}
-public slots:
- void readStdOut(const QByteArray &data)
- {
- readStdOutString(QString::fromUtf8(data));
- }
void readStdErr(const QString &data)
{
@@ -730,21 +833,39 @@ private:
QStringList m_files;
};
+class ProgressParser : public VcsBase::ProgressParser
+{
+public:
+ ProgressParser() :
+ m_progressExp(QLatin1String("\\((\\d+)/(\\d+)\\)")) // e.g. Rebasing (7/42)
+ {
+ }
+
+protected:
+ void parseProgress(const QString &text)
+ {
+ if (m_progressExp.lastIndexIn(text) != -1)
+ setProgressAndMaximum(m_progressExp.cap(1).toInt(), m_progressExp.cap(2).toInt());
+ }
+
+private:
+ QRegExp m_progressExp;
+};
+
+
Core::IEditor *locateEditor(const char *property, const QString &entry)
{
- foreach (Core::IEditor *ed, Core::ICore::editorManager()->openedEditors())
- if (ed->document()->property(property).toString() == entry)
- return ed;
+ foreach (Core::IDocument *document, Core::EditorManager::documentModel()->openedDocuments())
+ if (document->property(property).toString() == entry)
+ return Core::EditorManager::documentModel()->editorsForDocument(document).first();
return 0;
}
// Return converted command output, remove '\r' read on Windows
static inline QString commandOutputFromLocal8Bit(const QByteArray &a)
{
- QString output = QString::fromLocal8Bit(a);
- output.remove(QLatin1Char('\r'));
- return output;
+ return Utils::SynchronousProcess::normalizeNewlines(QString::fromLocal8Bit(a));
}
// Return converted command output split into lines
@@ -774,13 +895,24 @@ static inline QString msgParseFilesFailed()
return GitClient::tr("Cannot parse the file output.");
}
+static inline QString msgCannotLaunch(const QString &binary)
+{
+ return GitClient::tr("Cannot launch \"%1\".").arg(QDir::toNativeSeparators(binary));
+}
+
static inline QString currentDocumentPath()
{
- if (Core::IEditor *editor = Core::EditorManager::currentEditor())
- return QFileInfo(editor->document()->fileName()).path();
+ if (Core::IDocument *document= Core::EditorManager::currentDocument())
+ return QFileInfo(document->filePath()).path();
return QString();
}
+static inline QStringList statusArguments()
+{
+ return QStringList() << QLatin1String("-c") << QLatin1String("color.status=false")
+ << QLatin1String("status");
+}
+
// ---------------- GitClient
const char *GitClient::stashNamePrefix = "stash@{";
@@ -850,53 +982,60 @@ VcsBase::VcsBaseEditorWidget *GitClient::findExistingVCSEditor(const char *regis
// Exists already
Core::EditorManager::activateEditor(outputEditor);
- outputEditor->createNew(m_msgWait);
+ outputEditor->document()->setContents(m_msgWait.toUtf8());
rc = VcsBase::VcsBaseEditorWidget::getVcsBaseEditor(outputEditor);
return rc;
}
-DiffEditor::DiffEditor *GitClient::findExistingOrOpenNewDiffEditor(const char *registerDynamicProperty,
- const QString &dynamicPropertyValue, const QString &titlePattern, const Core::Id editorId) const
+DiffEditor::DiffEditor *GitClient::findExistingDiffEditor(const char *registerDynamicProperty,
+ const QString &dynamicPropertyValue) const
{
- Core::IEditor *outputEditor = locateEditor(registerDynamicProperty, dynamicPropertyValue);
- if (outputEditor) {
- // Exists already
- Core::EditorManager::activateEditor(outputEditor);
- outputEditor->createNew(m_msgWait);
- }
-
- DiffEditor::DiffEditor *editor = qobject_cast<DiffEditor::DiffEditor *>(outputEditor);
- if (!editor) {
- QString title = titlePattern;
- editor = qobject_cast<DiffEditor::DiffEditor *>(
- Core::EditorManager::openEditorWithContents(editorId, &title, m_msgWait));
- editor->document()->setProperty(registerDynamicProperty, dynamicPropertyValue);
- Core::EditorManager::activateEditor(editor);
+ DiffEditor::DiffEditor *diffEditor = qobject_cast<DiffEditor::DiffEditor *>(
+ locateEditor(registerDynamicProperty, dynamicPropertyValue));
+ if (diffEditor) {
+ diffEditor->document()->setContents(m_msgWait.toUtf8());
+ Core::EditorManager::activateEditor(diffEditor);
}
- return editor;
+ return diffEditor;
}
+DiffEditor::DiffEditor *GitClient::createDiffEditor(const char *registerDynamicProperty,
+ const QString &dynamicPropertyValue,
+ const QString &source,
+ const QString &titlePattern,
+ const Core::Id editorId) const
+{
+ QString title = titlePattern;
+ DiffEditor::DiffEditor *diffEditor = qobject_cast<DiffEditor::DiffEditor *>(
+ Core::EditorManager::openEditorWithContents(editorId, &title, m_msgWait.toUtf8()));
+ QTC_ASSERT(diffEditor, return 0);
+ diffEditor->document()->setProperty(registerDynamicProperty, dynamicPropertyValue);
+ diffEditor->editorWidget()->setSource(source);
+
+ Core::EditorManager::activateEditor(diffEditor);
+ return diffEditor;
+}
/* Create an editor associated to VCS output of a source file/directory
* (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(const Core::Id &id,
- QString title,
- // Source file or directory
- const QString &source,
- CodecType codecType,
- // Dynamic property and value to identify that editor
- const char *registerDynamicProperty,
- const QString &dynamicPropertyValue,
- QWidget *configWidget) const
+VcsBase::VcsBaseEditorWidget *GitClient::createVcsEditor(
+ const Core::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
{
VcsBase::VcsBaseEditorWidget *rc = 0;
QTC_CHECK(!findExistingVCSEditor(registerDynamicProperty, dynamicPropertyValue));
// Create new, set wait message, set up with source and codec
- Core::IEditor *outputEditor = Core::EditorManager::openEditorWithContents(id, &title, m_msgWait);
+ Core::IEditor *outputEditor = Core::EditorManager::openEditorWithContents(id, &title,
+ m_msgWait.toUtf8());
outputEditor->document()->setProperty(registerDynamicProperty, dynamicPropertyValue);
rc = VcsBase::VcsBaseEditorWidget::getVcsBaseEditor(outputEditor);
connect(rc, SIGNAL(annotateRevisionRequested(QString,QString,int)),
@@ -922,21 +1061,28 @@ VcsBase::VcsBaseEditorWidget *GitClient::createVcsEditor(const Core::Id &id,
}
void GitClient::diff(const QString &workingDirectory,
- const QStringList &diffArgs,
const QStringList &unstagedFileNames,
const QStringList &stagedFileNames)
{
const QString title = tr("Git Diff");
const int timeout = settings()->intValue(GitSettings::timeoutKey);
-
+ Core::IEditor *newEditor = 0;
if (settings()->boolValue(GitSettings::useDiffEditorKey)) {
- DiffEditor::DiffEditor *editor = findExistingOrOpenNewDiffEditor(
- "originalFileName",
- workingDirectory,
- title,
- DiffEditor::Constants::DIFF_EDITOR_ID);
+ const char *propertyName = "sideBySideOriginalFileName";
+ DiffEditor::DiffEditor *diffEditor = findExistingDiffEditor(propertyName, workingDirectory);
+ if (!diffEditor) {
+ newEditor = diffEditor = createDiffEditor(propertyName,
+ workingDirectory,
+ workingDirectory,
+ title,
+ DiffEditor::Constants::DIFF_EDITOR_ID);
+ }
- GitDiffHandler *handler = new GitDiffHandler(editor, gitBinaryPath(), workingDirectory, processEnvironment(), timeout);
+ GitDiffHandler *handler = new GitDiffHandler(diffEditor,
+ gitBinaryPath(),
+ workingDirectory,
+ processEnvironment(),
+ timeout);
if (unstagedFileNames.empty() && stagedFileNames.empty()) {
// local repository diff
@@ -950,31 +1096,43 @@ void GitClient::diff(const QString &workingDirectory,
}
} else {
const QString binary = settings()->stringValue(GitSettings::binaryPathKey);
- const Core::Id editorId = Git::Constants::GIT_DIFF_EDITOR_ID;
-
- VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("originalFileName", workingDirectory);
- if (!editor) {
+ const char *propertyName = "originalFileName";
+ VcsBase::VcsBaseEditorWidget *vcsEditor = findExistingVCSEditor(propertyName, workingDirectory);
+ if (!vcsEditor) {
GitCommitDiffArgumentsWidget *argWidget =
- new GitCommitDiffArgumentsWidget(this, workingDirectory, diffArgs,
- unstagedFileNames, stagedFileNames);
-
- editor = createVcsEditor(editorId, title,
- workingDirectory, CodecSource, "originalFileName", workingDirectory, argWidget);
- connect(editor, SIGNAL(diffChunkReverted(VcsBase::DiffChunk)), argWidget, SLOT(executeCommand()));
+ new GitCommitDiffArgumentsWidget(this,
+ workingDirectory,
+ unstagedFileNames,
+ stagedFileNames);
+ vcsEditor = createVcsEditor(Git::Constants::GIT_DIFF_EDITOR_ID,
+ title,
+ workingDirectory,
+ CodecSource,
+ propertyName,
+ workingDirectory,
+ argWidget);
+ newEditor = vcsEditor->editor();
+ connect(vcsEditor, SIGNAL(diffChunkApplied(VcsBase::DiffChunk)),
+ argWidget, SLOT(executeCommand()));
+ connect(vcsEditor, SIGNAL(diffChunkReverted(VcsBase::DiffChunk)),
+ argWidget, SLOT(executeCommand()));
}
- GitCommitDiffArgumentsWidget *argWidget = qobject_cast<GitCommitDiffArgumentsWidget *>(editor->configurationWidget());
+ GitCommitDiffArgumentsWidget *argWidget = qobject_cast<GitCommitDiffArgumentsWidget *>(
+ vcsEditor->configurationWidget());
+ argWidget->setFileNames(unstagedFileNames, stagedFileNames);
QStringList userDiffArgs = argWidget->arguments();
- editor->setDiffBaseDirectory(workingDirectory);
+ vcsEditor->setDiffBaseDirectory(workingDirectory);
// Create a batch of 2 commands to be run after each other in case
// we have a mixture of staged/unstaged files as is the case
// when using the submit dialog.
- VcsBase::Command *command = createCommand(workingDirectory, editor);
+ VcsBase::Command *command = createCommand(workingDirectory, vcsEditor);
// Directory diff?
QStringList cmdArgs;
- cmdArgs << QLatin1String("diff") << QLatin1String(noColorOption);
+ cmdArgs << QLatin1String("diff")
+ << QLatin1String(noColorOption);
if (unstagedFileNames.empty() && stagedFileNames.empty()) {
QStringList arguments(cmdArgs);
@@ -985,65 +1143,99 @@ void GitClient::diff(const QString &workingDirectory,
// Files diff.
if (!unstagedFileNames.empty()) {
QStringList arguments(cmdArgs);
- arguments << userDiffArgs;
- arguments << QLatin1String("--") << unstagedFileNames;
+ arguments << userDiffArgs
+ << QLatin1String("--")
+ << unstagedFileNames;
outputWindow()->appendCommand(workingDirectory, binary, arguments);
command->addJob(arguments, timeout);
}
if (!stagedFileNames.empty()) {
QStringList arguments(cmdArgs);
- arguments << userDiffArgs;
- arguments << QLatin1String("--cached") << diffArgs << QLatin1String("--") << stagedFileNames;
+ arguments << userDiffArgs
+ << QLatin1String("--cached")
+ << QLatin1String("--")
+ << stagedFileNames;
outputWindow()->appendCommand(workingDirectory, binary, arguments);
command->addJob(arguments, timeout);
}
}
command->execute();
}
+ if (newEditor) {
+ GitDiffSwitcher *switcher = new GitDiffSwitcher(newEditor, this);
+ switcher->setWorkingDirectory(workingDirectory);
+ if (unstagedFileNames.empty() && stagedFileNames.empty()) {
+ // local repository diff
+ switcher->setDiffType(GitDiffSwitcher::DiffRepository);
+ } else if (!stagedFileNames.empty()) {
+ // diff of selected files only with --cached option, used in commit editor
+ switcher->setDiffType(GitDiffSwitcher::DiffFileList);
+ switcher->setFileList(stagedFileNames, unstagedFileNames);
+ } else {
+ // current project diff
+ switcher->setDiffType(GitDiffSwitcher::DiffProjectList);
+ switcher->setProjectList(unstagedFileNames);
+ }
+ }
}
-void GitClient::diff(const QString &workingDirectory,
- const QStringList &diffArgs,
- const QString &fileName)
+void GitClient::diff(const QString &workingDirectory, const QString &fileName)
{
const QString title = tr("Git Diff \"%1\"").arg(fileName);
+ const QString sourceFile = VcsBase::VcsBaseEditorWidget::getSource(workingDirectory, fileName);
+ Core::IEditor *newEditor = 0;
if (settings()->boolValue(GitSettings::useDiffEditorKey)) {
- const QString sourceFile = VcsBase::VcsBaseEditorWidget::getSource(workingDirectory, fileName);
- DiffEditor::DiffEditor *editor = findExistingOrOpenNewDiffEditor(
- "originalFileName",
- sourceFile,
- title,
- DiffEditor::Constants::DIFF_EDITOR_ID);
-
- if (!fileName.isEmpty()) {
- int timeout = settings()->intValue(GitSettings::timeoutKey);
- GitDiffHandler *handler = new GitDiffHandler(editor, gitBinaryPath(), workingDirectory, processEnvironment(), timeout);
- handler->diffFile(fileName);
+ const char *propertyName = "sideBySideOriginalFileName";
+ DiffEditor::DiffEditor *diffEditor = findExistingDiffEditor(propertyName, sourceFile);
+ if (!diffEditor) {
+ newEditor = diffEditor = createDiffEditor(propertyName,
+ sourceFile,
+ sourceFile,
+ title,
+ DiffEditor::Constants::DIFF_EDITOR_ID);
}
+ GitDiffHandler *handler = new GitDiffHandler(diffEditor,
+ gitBinaryPath(),
+ workingDirectory,
+ processEnvironment(),
+ settings()->intValue(GitSettings::timeoutKey));
+ handler->diffFile(fileName);
} else {
- const Core::Id editorId = Git::Constants::GIT_DIFF_EDITOR_ID;
- const QString sourceFile = VcsBase::VcsBaseEditorWidget::getSource(workingDirectory, fileName);
-
- VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("originalFileName", sourceFile);
- if (!editor) {
+ const char *propertyName = "originalFileName";
+ VcsBase::VcsBaseEditorWidget *vcsEditor = findExistingVCSEditor(propertyName, sourceFile);
+ if (!vcsEditor) {
GitFileDiffArgumentsWidget *argWidget =
- new GitFileDiffArgumentsWidget(this, workingDirectory, diffArgs, fileName);
-
- editor = createVcsEditor(editorId, title, sourceFile, CodecSource, "originalFileName", sourceFile, argWidget);
- connect(editor, SIGNAL(diffChunkReverted(VcsBase::DiffChunk)), argWidget, SLOT(executeCommand()));
+ new GitFileDiffArgumentsWidget(this, workingDirectory, fileName);
+
+ vcsEditor = createVcsEditor(Git::Constants::GIT_DIFF_EDITOR_ID,
+ title,
+ sourceFile,
+ CodecSource,
+ propertyName,
+ sourceFile,
+ argWidget);
+ newEditor = vcsEditor->editor();
+ connect(vcsEditor, SIGNAL(diffChunkApplied(VcsBase::DiffChunk)),
+ argWidget, SLOT(executeCommand()));
+ connect(vcsEditor, SIGNAL(diffChunkReverted(VcsBase::DiffChunk)),
+ argWidget, SLOT(executeCommand()));
}
- editor->setDiffBaseDirectory(workingDirectory);
-
- GitFileDiffArgumentsWidget *argWidget = qobject_cast<GitFileDiffArgumentsWidget *>(editor->configurationWidget());
- QStringList userDiffArgs = argWidget->arguments();
+ vcsEditor->setDiffBaseDirectory(workingDirectory);
QStringList cmdArgs;
- cmdArgs << QLatin1String("diff") << QLatin1String(noColorOption)
- << userDiffArgs;
+ cmdArgs << QLatin1String("diff")
+ << QLatin1String(noColorOption)
+ << vcsEditor->configurationWidget()->arguments();
if (!fileName.isEmpty())
cmdArgs << QLatin1String("--") << fileName;
- executeGit(workingDirectory, cmdArgs, editor);
+ executeGit(workingDirectory, cmdArgs, vcsEditor);
+ }
+ if (newEditor) {
+ GitDiffSwitcher *switcher = new GitDiffSwitcher(newEditor, this);
+ switcher->setWorkingDirectory(workingDirectory);
+ switcher->setDiffType(GitDiffSwitcher::DiffFile);
+ switcher->setFileName(fileName);
}
}
@@ -1052,35 +1244,58 @@ void GitClient::diffBranch(const QString &workingDirectory,
const QString &branchName)
{
const QString title = tr("Git Diff Branch \"%1\"").arg(branchName);
+ Core::IEditor *newEditor = 0;
if (settings()->boolValue(GitSettings::useDiffEditorKey)) {
- DiffEditor::DiffEditor *editor = findExistingOrOpenNewDiffEditor(
- "BranchName",
- branchName,
- title,
- DiffEditor::Constants::DIFF_EDITOR_ID);
-
- int timeout = settings()->intValue(GitSettings::timeoutKey);
- GitDiffHandler *handler = new GitDiffHandler(editor, gitBinaryPath(), workingDirectory, processEnvironment(), timeout);
+ const char *propertyName = "sideBySideBranchName";
+ DiffEditor::DiffEditor *diffEditor = findExistingDiffEditor(propertyName, branchName);
+ if (!diffEditor) {
+ newEditor = diffEditor = createDiffEditor(propertyName,
+ branchName,
+ workingDirectory,
+ title,
+ DiffEditor::Constants::DIFF_EDITOR_ID);
+ }
+
+ GitDiffHandler *handler = new GitDiffHandler(diffEditor,
+ gitBinaryPath(),
+ workingDirectory,
+ processEnvironment(),
+ settings()->intValue(GitSettings::timeoutKey));
handler->diffBranch(branchName);
} else {
- const Core::Id editorId = Git::Constants::GIT_DIFF_EDITOR_ID;
+ const char *propertyName = "BranchName";
const QString sourceFile = VcsBase::VcsBaseEditorWidget::getSource(workingDirectory, QStringList());
- VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("BranchName", branchName);
- if (!editor)
- editor = createVcsEditor(editorId, title, sourceFile, CodecSource, "BranchName", branchName,
- new GitBranchDiffArgumentsWidget(this, workingDirectory,
- diffArgs, branchName));
- editor->setDiffBaseDirectory(workingDirectory);
-
- GitBranchDiffArgumentsWidget *argWidget = qobject_cast<GitBranchDiffArgumentsWidget *>(editor->configurationWidget());
- QStringList userDiffArgs = argWidget->arguments();
+ VcsBase::VcsBaseEditorWidget *vcsEditor = findExistingVCSEditor(propertyName, branchName);
+ if (!vcsEditor) {
+ vcsEditor = createVcsEditor(Git::Constants::GIT_DIFF_EDITOR_ID,
+ title,
+ sourceFile,
+ CodecSource,
+ propertyName,
+ branchName,
+ new GitBranchDiffArgumentsWidget(this,
+ workingDirectory,
+ diffArgs,
+ branchName));
+ newEditor = vcsEditor->editor();
+ }
+ vcsEditor->setDiffBaseDirectory(workingDirectory);
QStringList cmdArgs;
- cmdArgs << QLatin1String("diff") << QLatin1String(noColorOption)
- << userDiffArgs << branchName;
+ cmdArgs << QLatin1String("diff")
+ << QLatin1String(noColorOption)
+ << vcsEditor->configurationWidget()->arguments()
+ << branchName;
- executeGit(workingDirectory, cmdArgs, editor);
+ executeGit(workingDirectory, cmdArgs, vcsEditor);
+ }
+ if (newEditor) {
+ GitDiffSwitcher *switcher = new GitDiffSwitcher(newEditor, this);
+ switcher->setWorkingDirectory(workingDirectory);
+ switcher->setDiffType(GitDiffSwitcher::DiffBranch);
+ switcher->setBaseArguments(diffArgs);
+ switcher->setBranchName(branchName);
}
}
@@ -1093,8 +1308,7 @@ void GitClient::merge(const QString &workingDirectory, const QStringList &unmerg
void GitClient::status(const QString &workingDirectory)
{
- // @TODO: Use "--no-color" once it is supported
- QStringList statusArgs(QLatin1String("status"));
+ QStringList statusArgs = statusArguments();
statusArgs << QLatin1String("-u");
VcsBase::VcsBaseOutputWindow *outwin = outputWindow();
outwin->setRepository(workingDirectory);
@@ -1103,20 +1317,19 @@ void GitClient::status(const QString &workingDirectory)
Qt::QueuedConnection);
}
-void GitClient::log(const QString &workingDirectory, const QStringList &fileNames,
+void GitClient::log(const QString &workingDirectory, const QString &fileName,
bool enableAnnotationContextMenu, const QStringList &args)
{
- const QString msgArg = fileNames.empty() ? workingDirectory :
- fileNames.join(QLatin1String(", "));
+ const QString msgArg = fileName.isEmpty() ? workingDirectory : fileName;
const QString title = tr("Git Log \"%1\"").arg(msgArg);
const Core::Id editorId = Git::Constants::GIT_LOG_EDITOR_ID;
- const QString sourceFile = VcsBase::VcsBaseEditorWidget::getSource(workingDirectory, fileNames);
+ const QString sourceFile = VcsBase::VcsBaseEditorWidget::getSource(workingDirectory, fileName);
VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("logFileName", sourceFile);
if (!editor)
editor = createVcsEditor(editorId, title, sourceFile, CodecLogOutput, "logFileName", sourceFile,
new GitLogArgumentsWidget(this, workingDirectory,
enableAnnotationContextMenu,
- args, fileNames));
+ args, fileName));
editor->setFileLogAnnotateEnabled(enableAnnotationContextMenu);
editor->setDiffBaseDirectory(workingDirectory);
@@ -1129,12 +1342,35 @@ void GitClient::log(const QString &workingDirectory, const QStringList &fileName
arguments << QLatin1String("-n") << QString::number(logCount);
GitLogArgumentsWidget *argWidget = qobject_cast<GitLogArgumentsWidget *>(editor->configurationWidget());
+ argWidget->setBaseArguments(args);
+ argWidget->setFileName(fileName);
QStringList userArgs = argWidget->arguments();
arguments.append(userArgs);
- if (!fileNames.isEmpty())
- arguments << QLatin1String("--") << fileNames;
+ if (!fileName.isEmpty())
+ arguments << QLatin1String("--follow") << QLatin1String("--") << fileName;
+
+ executeGit(workingDirectory, arguments, editor);
+}
+
+void GitClient::reflog(const QString &workingDirectory)
+{
+ const QString title = tr("Git Reflog \"%1\"").arg(workingDirectory);
+ const Core::Id editorId = Git::Constants::GIT_LOG_EDITOR_ID;
+ VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("reflogRepository", workingDirectory);
+ if (!editor) {
+ editor = createVcsEditor(editorId, title, workingDirectory, CodecLogOutput,
+ "reflogRepository", workingDirectory, 0);
+ }
+
+ QStringList arguments;
+ arguments << QLatin1String("reflog") << QLatin1String(noColorOption)
+ << QLatin1String(decorateOption);
+
+ int logCount = settings()->intValue(GitSettings::logCountKey);
+ if (logCount > 0)
+ arguments << QLatin1String("-n") << QString::number(logCount);
executeGit(workingDirectory, arguments, editor);
}
@@ -1158,43 +1394,65 @@ void GitClient::show(const QString &source, const QString &id,
const QStringList &args, const QString &name)
{
if (!canShow(id)) {
- outputWindow()->append(msgCannotShow(id));
+ outputWindow()->appendError(msgCannotShow(id));
return;
}
const QString title = tr("Git Show \"%1\"").arg(name.isEmpty() ? id : name);
const QFileInfo sourceFi(source);
- const QString workDir = sourceFi.isDir() ? sourceFi.absoluteFilePath() : sourceFi.absolutePath();
+ const QString workingDirectory = sourceFi.isDir() ? sourceFi.absoluteFilePath() : sourceFi.absolutePath();
+ Core::IEditor *newEditor = 0;
if (settings()->boolValue(GitSettings::useDiffEditorKey)) {
- DiffEditor::DiffEditor *editor = findExistingOrOpenNewDiffEditor(
- "show",
- id,
- title,
- DiffEditor::Constants::DIFF_SHOW_EDITOR_ID);
-
- int timeout = settings()->intValue(GitSettings::timeoutKey);
- GitDiffHandler *handler = new GitDiffHandler(editor, gitBinaryPath(),
- findRepositoryForDirectory(workDir),
- processEnvironment(), timeout);
+ const char *propertyName = "sideBySideShow";
+ DiffEditor::DiffEditor *diffEditor = findExistingDiffEditor(propertyName, id);
+ if (!diffEditor) {
+ newEditor = diffEditor = createDiffEditor(propertyName,
+ id,
+ source,
+ title,
+ DiffEditor::Constants::DIFF_SHOW_EDITOR_ID);
+ }
+
+ GitDiffHandler *handler = new GitDiffHandler(diffEditor,
+ gitBinaryPath(),
+ workingDirectory,
+ processEnvironment(),
+ settings()->intValue(GitSettings::timeoutKey));
handler->show(id);
} else {
+ const char *propertyName = "show";
const Core::Id editorId = Git::Constants::GIT_DIFF_EDITOR_ID;
- VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("show", id);
- if (!editor)
- editor = createVcsEditor(editorId, title, source, CodecSource, "show", id,
- new GitShowArgumentsWidget(this, source, args, id));
-
- GitShowArgumentsWidget *argWidget = qobject_cast<GitShowArgumentsWidget *>(editor->configurationWidget());
- QStringList userArgs = argWidget->arguments();
+ VcsBase::VcsBaseEditorWidget *vcsEditor = findExistingVCSEditor(propertyName, id);
+ if (!vcsEditor) {
+ vcsEditor = createVcsEditor(editorId,
+ title,
+ source,
+ CodecSource,
+ propertyName,
+ id,
+ new GitShowArgumentsWidget(this,
+ source,
+ args,
+ id));
+ newEditor = vcsEditor->editor();
+ }
QStringList arguments;
- arguments << QLatin1String("show") << QLatin1String(noColorOption);
- arguments << QLatin1String(decorateOption);
- arguments.append(userArgs);
- arguments << id;
+ arguments << QLatin1String("show")
+ << QLatin1String(noColorOption)
+ << QLatin1String(decorateOption)
+ << vcsEditor->configurationWidget()->arguments()
+ << id;
- editor->setDiffBaseDirectory(workDir);
- executeGit(workDir, arguments, editor);
+ vcsEditor->setDiffBaseDirectory(workingDirectory);
+ executeGit(workingDirectory, arguments, vcsEditor);
+ }
+ if (newEditor) {
+ GitDiffSwitcher *switcher = new GitDiffSwitcher(newEditor, this);
+ switcher->setDiffType(GitDiffSwitcher::DiffShow);
+ switcher->setFileName(source);
+ switcher->setBaseArguments(args);
+ switcher->setId(id);
}
}
@@ -1214,18 +1472,6 @@ void GitClient::slotBlameRevisionRequested(const QString &source, QString change
blame(fi.absolutePath(), QStringList(), fi.fileName(), change, lineNumber);
}
-void GitClient::appendOutputData(const QByteArray &data) const
-{
- const QTextCodec *codec = getSourceCodec(currentDocumentPath());
- outputWindow()->appendData(codec->toUnicode(data).toLocal8Bit());
-}
-
-void GitClient::appendOutputDataSilently(const QByteArray &data) const
-{
- const QTextCodec *codec = getSourceCodec(currentDocumentPath());
- outputWindow()->appendDataSilently(codec->toUnicode(data).toLocal8Bit());
-}
-
QTextCodec *GitClient::getSourceCodec(const QString &file) const
{
if (QFileInfo(file).isFile())
@@ -1256,12 +1502,9 @@ void GitClient::blame(const QString &workingDirectory,
argWidget->setEditor(editor);
}
- GitBlameArgumentsWidget *argWidget = qobject_cast<GitBlameArgumentsWidget *>(editor->configurationWidget());
- QStringList userBlameArgs = argWidget->arguments();
-
QStringList arguments(QLatin1String("blame"));
arguments << QLatin1String("--root");
- arguments.append(userBlameArgs);
+ arguments.append(editor->configurationWidget()->arguments());
arguments << QLatin1String("--") << fileName;
if (!revision.isEmpty())
arguments << revision;
@@ -1446,11 +1689,11 @@ bool GitClient::synchronousInit(const QString &workingDirectory)
const bool rc = fullySynchronousGit(workingDirectory, arguments, &outputText, &errorText);
// '[Re]Initialized...'
outputWindow()->append(commandOutputFromLocal8Bit(outputText));
- if (!rc)
+ if (!rc) {
outputWindow()->appendError(commandOutputFromLocal8Bit(errorText));
- else {
+ } else {
// TODO: Turn this into a VcsBaseClient and use resetCachedVcsInfo(...)
- Core::ICore::vcsManager()->resetVersionControlForDirectory(workingDirectory);
+ Core::VcsManager::resetVersionControlForDirectory(workingDirectory);
}
return rc;
}
@@ -1540,9 +1783,9 @@ bool GitClient::synchronousRevListCmd(const QString &workingDirectory, const QSt
if (errorMessage)
*errorMessage = commandOutputFromLocal8Bit(errorText);
else
- outputWindow()->append(tr("Cannot execute \"git %1\" in \"%2\": %3").arg(
- args.join(QLatin1String(" ")), workingDirectory,
- commandOutputFromLocal8Bit(errorText)));
+ outputWindow()->appendError(tr("Cannot execute \"git %1\" in \"%2\": %3").arg(
+ args.join(QLatin1String(" ")), workingDirectory,
+ commandOutputFromLocal8Bit(errorText)));
return false;
}
*output = commandOutputFromLocal8Bit(outputTextData);
@@ -1620,11 +1863,6 @@ QString GitClient::synchronousCurrentLocalBranch(const QString &workingDirectory
return QString();
}
-static inline QString msgCannotDetermineBranch(const QString &workingDirectory, const QString &why)
-{
- return GitClient::tr("Cannot retrieve branch of \"%1\": %2").arg(QDir::toNativeSeparators(workingDirectory), why);
-}
-
static inline QString msgCannotRun(const QString &command, const QString &workingDirectory, const QString &why)
{
return GitClient::tr("Cannot run \"%1\" in \"%2\": %3")
@@ -1646,7 +1884,7 @@ bool GitClient::synchronousHeadRefs(const QString &workingDirectory, QStringList
if (errorMessage)
*errorMessage = message;
else
- outputWindow()->append(message);
+ outputWindow()->appendError(message);
return false;
}
@@ -1690,20 +1928,6 @@ QString GitClient::synchronousTopic(const QString &workingDirectory)
if (!branch.isEmpty())
return data.topic = branch;
- switch (checkCommandInProgressInGitDir(gitDir)) {
- case Rebase:
- case RebaseMerge:
- return data.topic = tr("REBASING");
- case Revert:
- return data.topic = tr("REVERTING");
- case CherryPick:
- return data.topic = tr("CHERRY-PICKING");
- case Merge:
- return data.topic = tr("MERGING");
- default:
- break;
- }
-
// Detached HEAD, try a tag or remote branch
QStringList references;
if (!synchronousHeadRefs(workingDirectory, &references))
@@ -1757,17 +1981,19 @@ QString GitClient::synchronousTopRevision(const QString &workingDirectory, QStri
}
void GitClient::synchronousTagsForCommit(const QString &workingDirectory, const QString &revision,
- QByteArray &precedes, QByteArray &follows)
+ QString &precedes, QString &follows)
{
+ QByteArray pr;
QStringList arguments;
arguments << QLatin1String("describe") << QLatin1String("--contains") << revision;
- fullySynchronousGit(workingDirectory, arguments, &precedes, 0,
+ fullySynchronousGit(workingDirectory, arguments, &pr, 0,
VcsBasePlugin::SuppressCommandLogging);
- int tilde = precedes.indexOf('~');
+ int tilde = pr.indexOf('~');
if (tilde != -1)
- precedes.truncate(tilde);
+ pr.truncate(tilde);
else
- precedes = precedes.trimmed();
+ pr = pr.trimmed();
+ precedes = QString::fromLocal8Bit(pr);
QStringList parents;
QString errorMessage;
@@ -1782,12 +2008,42 @@ void GitClient::synchronousTagsForCommit(const QString &workingDirectory, const
pf.truncate(pf.lastIndexOf('\n'));
if (!pf.isEmpty()) {
if (!follows.isEmpty())
- follows += ", ";
- follows += pf;
+ follows += QLatin1String(", ");
+ follows += QString::fromLocal8Bit(pf);
}
}
}
+QStringList GitClient::synchronousBranchesForCommit(const QString &workingDirectory, const QString &revision)
+{
+ QByteArray outputData;
+ QString output;
+ QStringList arguments;
+ arguments << QLatin1String("branch") << QLatin1String(noColorOption)
+ << QLatin1String("-a") << QLatin1String("--contains") << revision;
+ fullySynchronousGit(workingDirectory, arguments, &outputData, 0,
+ VcsBasePlugin::SuppressCommandLogging);
+ output = commandOutputFromLocal8Bit(outputData);
+ QStringList res;
+ foreach (const QString &branch, output.split(QLatin1Char('\n'))) {
+ const QString b = branch.mid(2).trimmed();
+ if (!b.isEmpty())
+ res << b;
+ }
+ return res;
+}
+
+bool GitClient::isRemoteCommit(const QString &workingDirectory, const QString &commit)
+{
+ QStringList arguments;
+ QByteArray outputText;
+ arguments << QLatin1String("branch") << QLatin1String("-r")
+ << QLatin1String("--contains") << commit;
+ fullySynchronousGit(workingDirectory, arguments, &outputText, 0,
+ VcsBasePlugin::SuppressCommandLogging);
+ return !outputText.isEmpty();
+}
+
// Format an entry in a one-liner for selection list using git log.
QString GitClient::synchronousShortDescription(const QString &workingDirectory, const QString &revision,
const QString &format)
@@ -1862,10 +2118,10 @@ QString GitClient::synchronousStash(const QString &workingDirectory, const QStri
if (unchanged)
*unchanged = true;
if (!(flags & StashIgnoreUnchanged))
- outputWindow()->append(msgNoChangedFiles());
+ outputWindow()->appendWarning(msgNoChangedFiles());
break;
case StatusFailed:
- outputWindow()->append(errorMessage);
+ outputWindow()->appendError(errorMessage);
break;
}
if (!success)
@@ -1923,7 +2179,7 @@ bool GitClient::stashNameFromMessage(const QString &workingDirectory,
if (errorMessage)
*errorMessage = msg;
else
- outputWindow()->append(msg);
+ outputWindow()->appendError(msg);
return false;
}
@@ -1935,8 +2191,23 @@ bool GitClient::synchronousBranchCmd(const QString &workingDirectory, QStringLis
QByteArray errorText;
const bool rc = fullySynchronousGit(workingDirectory, branchArgs, &outputText, &errorText);
*output = commandOutputFromLocal8Bit(outputText);
+ if (!rc && errorMessage) {
+ *errorMessage = msgCannotRun(QLatin1String("git branch"), workingDirectory,
+ commandOutputFromLocal8Bit(errorText));
+ }
+ return rc;
+}
+
+bool GitClient::synchronousTagCmd(const QString &workingDirectory, QStringList tagArgs, QString *output, QString *errorMessage)
+{
+ tagArgs.push_front(QLatin1String("tag"));
+ QByteArray outputText;
+ QByteArray errorText;
+ const bool rc = fullySynchronousGit(workingDirectory, tagArgs, &outputText, &errorText);
+ *output = commandOutputFromLocal8Bit(outputText);
if (!rc) {
- *errorMessage = msgCannotRun(QLatin1String("git branch"), workingDirectory, commandOutputFromLocal8Bit(errorText));
+ *errorMessage = msgCannotRun(QLatin1String("git tag"), workingDirectory,
+ commandOutputFromLocal8Bit(errorText));
return false;
}
return true;
@@ -1951,8 +2222,12 @@ bool GitClient::synchronousForEachRefCmd(const QString &workingDirectory, QStrin
const bool rc = fullySynchronousGit(workingDirectory, args, &outputText, &errorText);
*output = commandOutputFromLocal8Bit(outputText);
if (!rc) {
- *errorMessage = msgCannotRun(QLatin1String("git for-each-ref"), workingDirectory,
+ QString error = msgCannotRun(QLatin1String("git for-each-ref"), workingDirectory,
commandOutputFromLocal8Bit(errorText));
+ if (errorMessage)
+ *errorMessage = error;
+ else
+ outputWindow()->appendError(error);
return false;
}
@@ -1985,7 +2260,7 @@ QMap<QString,QString> GitClient::synchronousRemotesList(const QString &workingDi
if (errorMessage)
*errorMessage = error;
else
- outputWindow()->append(error);
+ outputWindow()->appendError(error);
return result;
}
QStringList remotes = output.split(QLatin1String("\n"));
@@ -1994,12 +2269,11 @@ QMap<QString,QString> GitClient::synchronousRemotesList(const QString &workingDi
if (!remote.endsWith(QLatin1String(" (push)")))
continue;
- QStringList tokens = remote.split(QRegExp(QLatin1String("\\s")),
- QString::SkipEmptyParts);
- if (tokens.count() != 3)
+ int tabIndex = remote.indexOf(QLatin1Char('\t'));
+ if (tabIndex == -1)
continue;
-
- result.insert(tokens.at(0), tokens.at(1));
+ QString url = remote.mid(tabIndex + 1, remote.length() - tabIndex - 8);
+ result.insert(remote.left(tabIndex), url);
}
return result;
}
@@ -2021,7 +2295,7 @@ QStringList GitClient::synchronousSubmoduleStatus(const QString &workingDirector
if (errorMessage)
*errorMessage = error;
else
- outputWindow()->append(error);
+ outputWindow()->appendError(error);
return QStringList();
}
@@ -2143,10 +2417,11 @@ bool GitClient::synchronousCleanList(const QString &workingDirectory, QStringLis
}
bool GitClient::synchronousApplyPatch(const QString &workingDirectory,
- const QString &file, QString *errorMessage)
+ const QString &file, QString *errorMessage,
+ const QStringList &arguments)
{
QStringList args;
- args << QLatin1String("apply") << QLatin1String("--whitespace=fix") << file;
+ args << QLatin1String("apply") << QLatin1String("--whitespace=fix") << arguments << file;
QByteArray outputText;
QByteArray errorText;
const bool rc = fullySynchronousGit(workingDirectory, args, &outputText, &errorText);
@@ -2167,20 +2442,22 @@ VcsBase::Command *GitClient::createCommand(const QString &workingDirectory,
int editorLineNumber)
{
VcsBase::Command *command = new VcsBase::Command(gitBinaryPath(), workingDirectory, processEnvironment());
+ command->setCodec(getSourceCodec(currentDocumentPath()));
command->setCookie(QVariant(editorLineNumber));
- if (editor)
- connect(command, SIGNAL(finished(bool,int,QVariant)), editor, SLOT(commandFinishedGotoLine(bool,int,QVariant)));
+ if (editor) {
+ editor->setCommand(command);
+ connect(command, SIGNAL(finished(bool,int,QVariant)),
+ editor, SLOT(commandFinishedGotoLine(bool,int,QVariant)));
+ }
if (useOutputToWindow) {
+ command->addFlags(VcsBasePlugin::ShowStdOutInLogWindow);
+ command->addFlags(VcsBasePlugin::ShowSuccessMessage);
if (editor) // assume that the commands output is the important thing
- connect(command, SIGNAL(outputData(QByteArray)), this, SLOT(appendOutputDataSilently(QByteArray)));
- else
- connect(command, SIGNAL(outputData(QByteArray)), this, SLOT(appendOutputData(QByteArray)));
- } else {
- if (editor)
- connect(command, SIGNAL(outputData(QByteArray)), editor, SLOT(setPlainTextDataFiltered(QByteArray)));
+ command->addFlags(VcsBasePlugin::SilentOutput);
+ } else if (editor) {
+ connect(command, SIGNAL(output(QString)), editor, SLOT(setPlainTextFiltered(QString)));
}
- connect(command, SIGNAL(errorText(QString)), outputWindow(), SLOT(appendError(QString)));
return command;
}
@@ -2195,9 +2472,8 @@ VcsBase::Command *GitClient::executeGit(const QString &workingDirectory,
outputWindow()->appendCommand(workingDirectory, settings()->stringValue(GitSettings::binaryPathKey), arguments);
VcsBase::Command *command = createCommand(workingDirectory, editor, useOutputToWindow, editorLineNumber);
command->addJob(arguments, settings()->intValue(GitSettings::timeoutKey));
- command->setTerminationReportMode(VcsBase::Command::NoReport);
- command->setUnixTerminalDisabled(false);
- command->setExpectChanges(expectChanges);
+ if (expectChanges)
+ command->addFlags(VcsBasePlugin::ExpectRepoChanges);
command->execute();
return command;
}
@@ -2221,12 +2497,12 @@ QProcessEnvironment GitClient::processEnvironment() const
return environment;
}
-bool GitClient::beginStashScope(const QString &workingDirectory, const QString &keyword, StashFlag flag)
+bool GitClient::beginStashScope(const QString &workingDirectory, const QString &command, StashFlag flag)
{
const QString repoDirectory = findRepositoryForDirectory(workingDirectory);
QTC_ASSERT(!repoDirectory.isEmpty(), return false);
StashInfo &stashInfo = m_stashInfo[repoDirectory];
- return stashInfo.init(repoDirectory, keyword, flag);
+ return stashInfo.init(repoDirectory, command, flag);
}
GitClient::StashInfo &GitClient::stashInfo(const QString &workingDirectory)
@@ -2258,12 +2534,11 @@ bool GitClient::isValidRevision(const QString &revision) const
Utils::SynchronousProcessResponse GitClient::synchronousGit(const QString &workingDirectory,
const QStringList &gitArguments,
unsigned flags,
- QTextCodec *stdOutCodec)
+ QTextCodec *outputCodec)
{
return VcsBasePlugin::runVcs(workingDirectory, gitBinaryPath(), gitArguments,
settings()->intValue(GitSettings::timeoutKey) * 1000,
- processEnvironment(),
- flags, stdOutCodec);
+ flags, outputCodec, processEnvironment());
}
bool GitClient::fullySynchronousGit(const QString &workingDirectory,
@@ -2272,10 +2547,11 @@ bool GitClient::fullySynchronousGit(const QString &workingDirectory,
QByteArray* errorText,
unsigned flags) const
{
- return VcsBasePlugin::runFullySynchronous(workingDirectory, gitBinaryPath(), gitArguments,
- processEnvironment(), outputText, errorText,
- settings()->intValue(GitSettings::timeoutKey) * 1000,
- flags);
+ VcsBase::Command command(gitBinaryPath(), workingDirectory, processEnvironment());
+ command.addFlags(flags);
+ return command.runFullySynchronous(gitArguments,
+ settings()->intValue(GitSettings::timeoutKey) * 1000,
+ outputText, errorText);
}
void GitClient::updateSubmodulesIfNeeded(const QString &workingDirectory, bool prompt)
@@ -2342,21 +2618,6 @@ void GitClient::fetchFinished(const QVariant &cookie)
GitPlugin::instance()->updateBranches(cookie.toString());
}
-// Trim a git status file spec: "modified: foo .cpp" -> "modified: foo .cpp"
-static inline QString trimFileSpecification(QString fileSpec)
-{
- const int colonIndex = fileSpec.indexOf(QLatin1Char(':'));
- if (colonIndex != -1) {
- // Collapse the sequence of spaces
- const int filePos = colonIndex + 2;
- int nonBlankPos = filePos;
- for ( ; fileSpec.at(nonBlankPos).isSpace(); nonBlankPos++) ;
- if (nonBlankPos > filePos)
- fileSpec.remove(filePos, nonBlankPos - filePos);
- }
- return fileSpec;
-}
-
GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory, StatusMode mode,
QString *output, QString *errorMessage)
{
@@ -2364,7 +2625,7 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory, St
QByteArray outputText;
QByteArray errorText;
- QStringList statusArgs(QLatin1String("status"));
+ QStringList statusArgs = statusArguments();
if (mode & NoUntracked)
statusArgs << QLatin1String("--untracked-files=no");
else
@@ -2397,8 +2658,27 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory, St
return StatusUnchanged;
}
-GitClient::CommandInProgress GitClient::checkCommandInProgressInGitDir(const QString &gitDir)
+QString GitClient::commandInProgressDescription(const QString &workingDirectory)
+{
+ switch (checkCommandInProgress(workingDirectory)) {
+ case NoCommand:
+ break;
+ case Rebase:
+ case RebaseMerge:
+ return tr("REBASING");
+ case Revert:
+ return tr("REVERTING");
+ case CherryPick:
+ return tr("CHERRY-PICKING");
+ case Merge:
+ return tr("MERGING");
+ }
+ return QString();
+}
+
+GitClient::CommandInProgress GitClient::checkCommandInProgress(const QString &workingDirectory)
{
+ const QString gitDir = findGitDirForRepository(workingDirectory);
if (QFile::exists(gitDir + QLatin1String("/MERGE_HEAD")))
return Merge;
else if (QFile::exists(gitDir + QLatin1String("/rebase-apply/rebasing")))
@@ -2413,15 +2693,15 @@ GitClient::CommandInProgress GitClient::checkCommandInProgressInGitDir(const QSt
return NoCommand;
}
-GitClient::CommandInProgress GitClient::checkCommandInProgress(const QString &workingDirectory)
-{
- return checkCommandInProgressInGitDir(findGitDirForRepository(workingDirectory));
-}
-
void GitClient::continueCommandIfNeeded(const QString &workingDirectory)
{
CommandInProgress command = checkCommandInProgress(workingDirectory);
switch (command) {
+ case Merge:
+ continuePreviousGitCommand(workingDirectory, tr("Continue Merge"),
+ tr("Merge is in progress. What do you want to do?"),
+ tr("Continue"), QLatin1String("merge"));
+ break;
case Rebase:
case RebaseMerge:
continuePreviousGitCommand(workingDirectory, tr("Continue Rebase"),
@@ -2479,6 +2759,37 @@ void GitClient::continuePreviousGitCommand(const QString &workingDirectory,
}
}
+QString GitClient::extendedShowDescription(const QString &workingDirectory, const QString &text)
+{
+ if (!text.startsWith(QLatin1String("commit ")))
+ return text;
+ QString modText = text;
+ QString precedes, follows;
+ int lastHeaderLine = modText.indexOf(QLatin1String("\n\n")) + 1;
+ const QString commit = modText.mid(7, 8);
+ synchronousTagsForCommit(workingDirectory, commit, precedes, follows);
+ if (!precedes.isEmpty())
+ modText.insert(lastHeaderLine, QLatin1String("Precedes: ") + precedes + QLatin1Char('\n'));
+ if (!follows.isEmpty())
+ modText.insert(lastHeaderLine, QLatin1String("Follows: ") + follows + QLatin1Char('\n'));
+ QString moreBranches;
+ QStringList branches = synchronousBranchesForCommit(workingDirectory, commit);
+ const int branchCount = branches.count();
+ // If there are more than 20 branches, list first 10 followed by a hint
+ if (branchCount > 20) {
+ const int leave = 10;
+ //: Displayed after the untranslated message "Branches: branch1, branch2 'and %n more'" in git show.
+ moreBranches = tr(" and %n more", 0, branchCount - leave);
+ branches.erase(branches.begin() + leave, branches.end());
+ }
+ if (!branches.isEmpty()) {
+ modText.insert(lastHeaderLine, QLatin1String("Branches: ")
+ + branches.join(QLatin1String(", ")) + moreBranches
+ + QLatin1Char('\n'));
+ }
+ return modText;
+}
+
// Quietly retrieve branch list of remote repository URL
//
// The branch HEAD is pointing to is always returned first.
@@ -2578,15 +2889,27 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env,
success = QProcess::startDetached(binary, arguments, workingDirectory);
}
if (!success) {
- const QString error = tr("Cannot launch \"%1\".").arg(binary);
if (silent)
- outwin->appendSilently(error);
+ outwin->appendSilently(msgCannotLaunch(binary));
else
- outwin->appendError(error);
+ outwin->appendError(msgCannotLaunch(binary));
}
return success;
}
+bool GitClient::launchGitGui(const QString &workingDirectory) {
+ bool success;
+ QString gitBinary = gitBinaryPath(&success);
+ if (success)
+ success = QProcess::startDetached(gitBinary, QStringList(QLatin1String("gui")),
+ workingDirectory);
+
+ if (!success)
+ outputWindow()->appendError(msgCannotLaunch(QLatin1String("git gui")));
+
+ return success;
+}
+
QString GitClient::gitBinaryPath(bool *ok, QString *errorMessage) const
{
return settings()->gitBinaryPath(ok, errorMessage);
@@ -2721,6 +3044,8 @@ bool GitClient::getCommitData(const QString &workingDirectory,
case FixupCommit:
break;
}
+
+ commitData.panelData.hasRemotes = !synchronousRemotesList(repoDirectory).isEmpty();
return true;
}
@@ -2819,7 +3144,7 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory,
const bool rc = fullySynchronousGit(repositoryDirectory, args, &outputText, &errorText);
const QString stdErr = commandOutputFromLocal8Bit(errorText);
if (rc) {
- outputWindow()->append(msgCommitted(amendSHA1, commitCount));
+ outputWindow()->appendMessage(msgCommitted(amendSHA1, commitCount));
outputWindow()->appendError(stdErr);
} else {
outputWindow()->appendError(tr("Cannot commit %n file(s): %1\n", 0, commitCount).arg(stdErr));
@@ -2928,11 +3253,11 @@ void GitClient::revert(const QStringList &files, bool revertStaging)
break;
case RevertUnchanged: {
const QString msg = (isDirectory || files.size() > 1) ? msgNoChangedFiles() : tr("The file is not modified.");
- outputWindow()->append(msg);
+ outputWindow()->appendWarning(msg);
}
break;
case RevertFailed:
- outputWindow()->append(errorMessage);
+ outputWindow()->appendError(errorMessage);
break;
}
}
@@ -2959,7 +3284,7 @@ bool GitClient::executeAndHandleConflicts(const QString &workingDirectory,
// Notify about changed files or abort the rebase.
const bool ok = resp.result == Utils::SynchronousProcessResponse::Finished;
if (!ok) {
- conflictHandler.readStdOutString(resp.stdOut);
+ conflictHandler.readStdOut(resp.stdOut);
conflictHandler.readStdErr(resp.stdErr);
}
return ok;
@@ -3021,13 +3346,36 @@ QString GitClient::synchronousTrackingBranch(const QString &workingDirectory, co
return remote + QLatin1Char('/') + rBranch;
}
+bool GitClient::synchronousSetTrackingBranch(const QString &workingDirectory,
+ const QString &branch, const QString &tracking)
+{
+ QByteArray outputText;
+ QByteArray errorText;
+ QStringList arguments;
+ arguments << QLatin1String("branch");
+ if (gitVersion() >= 0x010800)
+ arguments << (QLatin1String("--set-upstream-to=") + tracking) << branch;
+ else
+ arguments << QLatin1String("--set-upstream") << branch << tracking;
+ const bool rc = fullySynchronousGit(workingDirectory, arguments, &outputText, &errorText);
+ if (!rc) {
+ const QString errorMessage = tr("Cannot set tracking branch: %1")
+ .arg(commandOutputFromLocal8Bit(errorText));
+ outputWindow()->appendError(errorMessage);
+ }
+ return rc;
+}
+
void GitClient::handleMergeConflicts(const QString &workingDir, const QString &commit,
const QStringList &files, const QString &abortCommand)
{
- Q_UNUSED(files);
-
- QString message = commit.isEmpty() ? tr("Conflicts detected")
- : tr("Conflicts detected with commit %1").arg(commit);
+ QString message;
+ if (!commit.isEmpty())
+ message = tr("Conflicts detected with commit %1.").arg(commit);
+ else if (!files.isEmpty())
+ message = tr("Conflicts detected with files:\n%1").arg(files.join(QLatin1String("\n")));
+ else
+ message = tr("Conflicts detected.");
QMessageBox mergeOrAbort(QMessageBox::Question, tr("Conflicts Detected"), message,
QMessageBox::NoButton, Core::ICore::mainWindow());
QPushButton *mergeToolButton = mergeOrAbort.addButton(tr("Run &Merge Tool"),
@@ -3125,6 +3473,7 @@ void GitClient::rebase(const QString &workingDirectory, const QString &baseBranc
arguments);
VcsBase::Command *command = createCommand(workingDirectory, 0, true);
new ConflictHandler(command, workingDirectory, gitCommand);
+ command->setProgressParser(new ProgressParser);
command->addJob(arguments, -1);
command->execute();
}
@@ -3132,7 +3481,11 @@ void GitClient::rebase(const QString &workingDirectory, const QString &baseBranc
bool GitClient::synchronousRevert(const QString &workingDirectory, const QString &commit)
{
QStringList arguments;
- QString command = QLatin1String("revert");
+ const QString command = QLatin1String("revert");
+ // Do not stash if --continue or --abort is given as the commit
+ if (!commit.startsWith(QLatin1Char('-')) && !beginStashScope(workingDirectory, command))
+ return false;
+
arguments << command << QLatin1String("--no-edit") << commit;
return executeAndHandleConflicts(workingDirectory, arguments, command);
@@ -3140,9 +3493,16 @@ bool GitClient::synchronousRevert(const QString &workingDirectory, const QString
bool GitClient::synchronousCherryPick(const QString &workingDirectory, const QString &commit)
{
- QStringList arguments;
- QString command = QLatin1String("cherry-pick");
- arguments << command << commit;
+ const QString command = QLatin1String("cherry-pick");
+ // "commit" might be --continue or --abort
+ const bool isRealCommit = !commit.startsWith(QLatin1Char('-'));
+ if (isRealCommit && !beginStashScope(workingDirectory, command))
+ return false;
+
+ QStringList arguments(command);
+ if (isRealCommit && isRemoteCommit(workingDirectory, commit))
+ arguments << QLatin1String("-x");
+ arguments << commit;
return executeAndHandleConflicts(workingDirectory, arguments, command);
}
@@ -3159,6 +3519,7 @@ void GitClient::interactiveRebase(const QString &workingDirectory, const QString
m_disableEditor = true;
VcsBase::Command *command = createCommand(workingDirectory, 0, true);
new ConflictHandler(command, workingDirectory, QLatin1String("rebase"));
+ command->setProgressParser(new ProgressParser);
command->addJob(arguments, -1);
command->execute();
command->setCookie(workingDirectory);
@@ -3217,7 +3578,7 @@ bool GitClient::synchronousStashRestore(const QString &workingDirectory,
if (errorMessage)
*errorMessage = msg;
else
- outputWindow()->append(msg);
+ outputWindow()->appendError(msg);
return false;
}
QString output = commandOutputFromLocal8Bit(outputText);
@@ -3249,7 +3610,7 @@ bool GitClient::synchronousStashRemove(const QString &workingDirectory,
if (errorMessage)
*errorMessage = msg;
else
- outputWindow()->append(msg);
+ outputWindow()->appendError(msg);
return false;
}
QString output = commandOutputFromLocal8Bit(outputText);
@@ -3289,7 +3650,7 @@ bool GitClient::synchronousStashList(const QString &workingDirectory,
if (errorMessage)
*errorMessage = msg;
else
- outputWindow()->append(msg);
+ outputWindow()->appendError(msg);
return false;
}
Stash stash;
@@ -3310,7 +3671,7 @@ QString GitClient::readConfig(const QString &workingDirectory, const QStringList
VcsBasePlugin::SuppressCommandLogging))
return QString();
if (Utils::HostOsInfo::isWindowsHost())
- return QString::fromUtf8(outputText).remove(QLatin1Char('\r'));
+ return Utils::SynchronousProcess::normalizeNewlines(QString::fromUtf8(outputText));
return commandOutputFromLocal8Bit(outputText);
}
@@ -3365,7 +3726,7 @@ bool GitClient::cloneRepository(const QString &directory,const QByteArray &url)
const Utils::SynchronousProcessResponse resp =
synchronousGit(workingDirectory.path(), arguments, flags);
// TODO: Turn this into a VcsBaseClient and use resetCachedVcsInfo(...)
- Core::ICore::vcsManager()->resetVersionControlForDirectory(workingDirectory.absolutePath());
+ Core::VcsManager::resetVersionControlForDirectory(workingDirectory.absolutePath());
return (resp.result == Utils::SynchronousProcessResponse::Finished);
}
}
@@ -3419,7 +3780,7 @@ unsigned GitClient::synchronousGitVersion(QString *errorMessage) const
if (errorMessage)
*errorMessage = msg;
else
- outputWindow()->append(msg);
+ outputWindow()->appendError(msg);
return 0;
}
// cut 'git version 1.6.5.1.sha'
@@ -3438,7 +3799,7 @@ GitClient::StashInfo::StashInfo() :
{
}
-bool GitClient::StashInfo::init(const QString &workingDirectory, const QString &keyword,
+bool GitClient::StashInfo::init(const QString &workingDirectory, const QString &command,
StashFlag flag)
{
m_workingDir = workingDirectory;
@@ -3449,9 +3810,9 @@ bool GitClient::StashInfo::init(const QString &workingDirectory, const QString &
&statusOutput, &errorMessage)) {
case GitClient::StatusChanged:
if (m_flags & NoPrompt)
- executeStash(keyword, &errorMessage);
+ executeStash(command, &errorMessage);
else
- stashPrompt(keyword, statusOutput, &errorMessage);
+ stashPrompt(command, statusOutput, &errorMessage);
break;
case GitClient::StatusUnchanged:
m_stashResult = StashUnchanged;
@@ -3466,7 +3827,7 @@ bool GitClient::StashInfo::init(const QString &workingDirectory, const QString &
return !stashingFailed();
}
-void GitClient::StashInfo::stashPrompt(const QString &keyword, const QString &statusOutput,
+void GitClient::StashInfo::stashPrompt(const QString &command, const QString &statusOutput,
QString *errorMessage)
{
QMessageBox msgBox(QMessageBox::Question, tr("Uncommitted Changes Found"),
@@ -3476,40 +3837,45 @@ void GitClient::StashInfo::stashPrompt(const QString &keyword, const QString &st
msgBox.setDetailedText(statusOutput);
+ QPushButton *stashAndPopButton = msgBox.addButton(tr("Stash && Pop"), QMessageBox::AcceptRole);
+ stashAndPopButton->setToolTip(tr("Stash local changes and pop when %1 finishes.").arg(command));
+
QPushButton *stashButton = msgBox.addButton(tr("Stash"), QMessageBox::AcceptRole);
- stashButton->setToolTip(tr("Stash local changes and continue."));
+ stashButton->setToolTip(tr("Stash local changes and execute %1.").arg(command));
QPushButton *discardButton = msgBox.addButton(tr("Discard"), QMessageBox::AcceptRole);
- discardButton->setToolTip(tr("Discard (reset) local changes and continue."));
+ discardButton->setToolTip(tr("Discard (reset) local changes and execute %1.").arg(command));
QPushButton *ignoreButton = 0;
if (m_flags & AllowUnstashed) {
ignoreButton = msgBox.addButton(QMessageBox::Ignore);
- ignoreButton->setToolTip(tr("Continue with local changes in working directory."));
+ ignoreButton->setToolTip(tr("Execute %1 with local changes in working directory.")
+ .arg(command));
}
QPushButton *cancelButton = msgBox.addButton(QMessageBox::Cancel);
- cancelButton->setToolTip(tr("Cancel current command."));
+ cancelButton->setToolTip(tr("Cancel %1.").arg(command));
msgBox.exec();
if (msgBox.clickedButton() == discardButton) {
- if (!m_client->synchronousReset(m_workingDir, QStringList(), errorMessage))
- m_stashResult = StashFailed;
- else
- m_stashResult = StashUnchanged;
+ m_stashResult = m_client->synchronousReset(m_workingDir, QStringList(), errorMessage) ?
+ StashUnchanged : StashFailed;
} else if (msgBox.clickedButton() == ignoreButton) { // At your own risk, so.
m_stashResult = NotStashed;
} else if (msgBox.clickedButton() == cancelButton) {
m_stashResult = StashCanceled;
} else if (msgBox.clickedButton() == stashButton) {
- executeStash(keyword, errorMessage);
+ m_stashResult = m_client->executeSynchronousStash(m_workingDir,
+ creatorStashMessage(command), errorMessage) ? StashUnchanged : StashFailed;
+ } else if (msgBox.clickedButton() == stashAndPopButton) {
+ executeStash(command, errorMessage);
}
}
-void GitClient::StashInfo::executeStash(const QString &keyword, QString *errorMessage)
+void GitClient::StashInfo::executeStash(const QString &command, QString *errorMessage)
{
- m_message = creatorStashMessage(keyword);
+ m_message = creatorStashMessage(command);
if (!m_client->executeSynchronousStash(m_workingDir, m_message, errorMessage))
m_stashResult = StashFailed;
else