aboutsummaryrefslogtreecommitdiffstats
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.cpp343
1 files changed, 226 insertions, 117 deletions
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 369dc06708..70f34604ae 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -38,7 +38,6 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
-#include <coreplugin/id.h>
#include <coreplugin/idocument.h>
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h>
@@ -49,6 +48,7 @@
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
+#include <utils/stringutils.h>
#include <utils/synchronousprocess.h>
#include <utils/temporaryfile.h>
#include <utils/theme/theme.h>
@@ -84,12 +84,14 @@
#include <QTextCodec>
const char GIT_DIRECTORY[] = ".git";
-const char graphLogFormatC[] = "%h %d %an %s %ci";
const char HEAD[] = "HEAD";
const char CHERRY_PICK_HEAD[] = "CHERRY_PICK_HEAD";
const char BRANCHES_PREFIX[] = "Branches: ";
const char stashNamePrefix[] = "stash@{";
const char noColorOption[] = "--no-color";
+const char colorOption[] = "--color=always";
+const char patchOption[] = "--patch";
+const char graphOption[] = "--graph";
const char decorateOption[] = "--decorate";
const char showFormatC[] =
"--pretty=format:commit %H%d%n"
@@ -265,37 +267,74 @@ void DescriptionWidgetDecorator::removeWatch(TextEditor::TextEditorWidget *widge
///////////////////////////////
-class GitDiffEditorController : public VcsBaseDiffEditorController
+class GitBaseDiffEditorController : public VcsBaseDiffEditorController
{
Q_OBJECT
-public:
- explicit GitDiffEditorController(IDocument *document);
-
protected:
+ explicit GitBaseDiffEditorController(IDocument *document,
+ const QString &leftCommit,
+ const QString &rightCommit);
+
void runCommand(const QList<QStringList> &args, QTextCodec *codec = nullptr);
QStringList addConfigurationArguments(const QStringList &args) const;
- QStringList addHeadWhenCommandInProgress() const;
+ QStringList baseArguments() const;
+
+public:
+ void initialize();
private:
void updateBranchList();
DescriptionWidgetWatcher m_watcher;
DescriptionWidgetDecorator m_decorator;
+ QString m_leftCommit;
+ QString m_rightCommit;
+};
+
+class GitDiffEditorController : public GitBaseDiffEditorController
+{
+public:
+ explicit GitDiffEditorController(IDocument *document,
+ const QString &leftCommit,
+ const QString &rightCommit,
+ const QStringList &extraArgs)
+ : GitBaseDiffEditorController(document, leftCommit, rightCommit)
+ {
+ setReloader([this, extraArgs] {
+ runCommand({addConfigurationArguments(baseArguments() << extraArgs)});
+ });
+ }
};
-GitDiffEditorController::GitDiffEditorController(IDocument *document) :
+GitBaseDiffEditorController::GitBaseDiffEditorController(IDocument *document,
+ const QString &leftCommit,
+ const QString &rightCommit) :
VcsBaseDiffEditorController(document),
m_watcher(this),
- m_decorator(&m_watcher)
+ m_decorator(&m_watcher),
+ m_leftCommit(leftCommit),
+ m_rightCommit(rightCommit)
{
connect(&m_decorator, &DescriptionWidgetDecorator::branchListRequested,
- this, &GitDiffEditorController::updateBranchList);
+ this, &GitBaseDiffEditorController::updateBranchList);
setDisplayName("Git Diff");
}
-void GitDiffEditorController::updateBranchList()
+void GitBaseDiffEditorController::initialize()
+{
+ if (m_rightCommit.isEmpty()) {
+ // This is workaround for lack of support for merge commits and resolving conflicts,
+ // we compare the current state of working tree to the HEAD of current branch
+ // instead of showing unsupported combined diff format.
+ GitClient::CommandInProgress commandInProgress = m_instance->checkCommandInProgress(workingDirectory());
+ if (commandInProgress != GitClient::NoCommand)
+ m_rightCommit = HEAD;
+ }
+}
+
+void GitBaseDiffEditorController::updateBranchList()
{
const QString revision = description().mid(7, 12);
if (revision.isEmpty())
@@ -347,12 +386,12 @@ void GitDiffEditorController::updateBranchList()
///////////////////////////////
-void GitDiffEditorController::runCommand(const QList<QStringList> &args, QTextCodec *codec)
+void GitBaseDiffEditorController::runCommand(const QList<QStringList> &args, QTextCodec *codec)
{
VcsBaseDiffEditorController::runCommand(args, diffExecutionFlags(), codec);
}
-QStringList GitDiffEditorController::addConfigurationArguments(const QStringList &args) const
+QStringList GitBaseDiffEditorController::addConfigurationArguments(const QStringList &args) const
{
QTC_ASSERT(!args.isEmpty(), return args);
@@ -372,66 +411,32 @@ QStringList GitDiffEditorController::addConfigurationArguments(const QStringList
return realArgs;
}
-QStringList GitDiffEditorController::addHeadWhenCommandInProgress() const
+QStringList GitBaseDiffEditorController::baseArguments() const
{
- // This is workaround for lack of support for merge commits and resolving conflicts,
- // we compare the current state of working tree to the HEAD of current branch
- // instead of showing unsupported combined diff format.
- GitClient::CommandInProgress commandInProgress = m_instance->checkCommandInProgress(workingDirectory());
- if (commandInProgress != GitClient::NoCommand)
- return {HEAD};
- return QStringList();
+ QStringList res = {"diff"};
+ if (!m_leftCommit.isEmpty())
+ res << m_leftCommit;
+ if (!m_rightCommit.isEmpty())
+ res << m_rightCommit;
+ return res;
}
-class RepositoryDiffController : public GitDiffEditorController
-{
-public:
- explicit RepositoryDiffController(IDocument *document) :
- GitDiffEditorController(document)
- {
- setReloader([this] {
- QStringList args = {"diff"};
- args.append(addHeadWhenCommandInProgress());
- runCommand({addConfigurationArguments(args)});
- });
- }
-};
-
-class FileDiffController : public GitDiffEditorController
-{
-public:
- FileDiffController(IDocument *document, const QString &fileName) :
- GitDiffEditorController(document)
- {
- setReloader([this, fileName] {
- QStringList args = {"diff"};
- args.append(addHeadWhenCommandInProgress());
- args << "--" << fileName;
- runCommand({addConfigurationArguments(args)});
- });
- }
-};
-
-class FileListDiffController : public GitDiffEditorController
+class FileListDiffController : public GitBaseDiffEditorController
{
public:
FileListDiffController(IDocument *document,
const QStringList &stagedFiles, const QStringList &unstagedFiles) :
- GitDiffEditorController(document)
+ GitBaseDiffEditorController(document, {}, {})
{
setReloader([this, stagedFiles, unstagedFiles] {
QList<QStringList> argLists;
if (!stagedFiles.isEmpty()) {
- QStringList stagedArgs = {"diff", "--cached", "--"};
- stagedArgs << stagedFiles;
+ QStringList stagedArgs = QStringList({"diff", "--cached", "--"}) << stagedFiles;
argLists << addConfigurationArguments(stagedArgs);
}
- if (!unstagedFiles.isEmpty()) {
- QStringList unstagedArgs = {"diff"};
- unstagedArgs << addHeadWhenCommandInProgress() << "--" << unstagedFiles;
- argLists << addConfigurationArguments(unstagedArgs);
- }
+ if (!unstagedFiles.isEmpty())
+ argLists << addConfigurationArguments(baseArguments() << "--" << unstagedFiles);
if (!argLists.isEmpty())
runCommand(argLists);
@@ -439,40 +444,12 @@ public:
}
};
-class ProjectDiffController : public GitDiffEditorController
-{
-public:
- ProjectDiffController(IDocument *document, const QStringList &projectPaths) :
- GitDiffEditorController(document)
- {
- setReloader([this, projectPaths] {
- QStringList args = {"diff"};
- args << addHeadWhenCommandInProgress() << "--" << projectPaths;
- runCommand({addConfigurationArguments(args)});
- });
- }
-};
-
-class BranchDiffController : public GitDiffEditorController
-{
-public:
- BranchDiffController(IDocument *document, const QString &branch) :
- GitDiffEditorController(document)
- {
- setReloader([this, branch] {
- QStringList args = {"diff"};
- args << addHeadWhenCommandInProgress() << branch;
- runCommand({addConfigurationArguments(args)});
- });
- }
-};
-
-class ShowController : public GitDiffEditorController
+class ShowController : public GitBaseDiffEditorController
{
Q_OBJECT
public:
ShowController(IDocument *document, const QString &id) :
- GitDiffEditorController(document),
+ GitBaseDiffEditorController(document, {}, {}),
m_id(id),
m_state(Idle)
{
@@ -505,7 +482,7 @@ void ShowController::processCommandOutput(const QString &output)
runCommand(QList<QStringList>() << addConfigurationArguments(args));
} else if (m_state == GettingDiff) {
m_state = Idle;
- GitDiffEditorController::processCommandOutput(output);
+ GitBaseDiffEditorController::processCommandOutput(output);
}
}
@@ -571,7 +548,7 @@ public:
BaseGitDiffArgumentsWidget(settings, editor->toolBar())
{
QToolBar *toolBar = editor->toolBar();
- QAction *diffButton = addToggleButton("--patch", tr("Diff"),
+ QAction *diffButton = addToggleButton(patchOption, tr("Diff"),
tr("Show difference."));
mapSetting(diffButton, settings.boolPointer(GitSettings::logDiffKey));
connect(diffButton, &QAction::toggled, m_patienceButton, &QAction::setVisible);
@@ -586,6 +563,23 @@ public:
}
};
+static bool gitHasRgbColors()
+{
+ const unsigned gitVersion = GitClient::instance()->gitVersion();
+ return gitVersion >= 0x020300U;
+}
+
+static QString logColorName(TextEditor::TextStyle style)
+{
+ using namespace TextEditor;
+
+ const ColorScheme &scheme = TextEditorSettings::fontSettings().colorScheme();
+ QColor color = scheme.formatFor(style).foreground();
+ if (!color.isValid())
+ color = scheme.formatFor(C_TEXT).foreground();
+ return color.name();
+};
+
class GitLogArgumentsWidget : public BaseGitLogArgumentsWidget
{
Q_OBJECT
@@ -599,14 +593,14 @@ public:
tr("First Parent"),
tr("Follow only the first parent on merge commits."));
mapSetting(firstParentButton, settings.boolPointer(GitSettings::firstParentKey));
- const QStringList graphArguments = {
- "--graph", "--oneline", "--topo-order",
- QLatin1String("--pretty=format:") + graphLogFormatC
- };
- QAction *graphButton = addToggleButton(graphArguments, tr("Graph"),
+ QAction *graphButton = addToggleButton(graphArguments(), tr("Graph"),
tr("Show textual graph log."));
mapSetting(graphButton, settings.boolPointer(GitSettings::graphLogKey));
+ QAction *colorButton = addToggleButton(QStringList{colorOption},
+ tr("Color"), tr("Use colors in log."));
+ mapSetting(colorButton, settings.boolPointer(GitSettings::colorLogKey));
+
if (fileRelated) {
QAction *followButton = addToggleButton(
"--follow", tr("Follow"),
@@ -616,6 +610,33 @@ public:
addReloadButton();
}
+
+ QStringList graphArguments() const
+ {
+ const QString authorName = logColorName(TextEditor::C_LOG_AUTHOR_NAME);
+ const QString commitDate = logColorName(TextEditor::C_LOG_COMMIT_DATE);
+ const QString commitHash = logColorName(TextEditor::C_LOG_COMMIT_HASH);
+ const QString commitSubject = logColorName(TextEditor::C_LOG_COMMIT_SUBJECT);
+ const QString decoration = logColorName(TextEditor::C_LOG_DECORATION);
+
+ const QString formatArg = QStringLiteral(
+ "--pretty=format:"
+ "%C(%1)%h%Creset "
+ "%C(%2)%d%Creset "
+ "%C(%3)%an%Creset "
+ "%C(%4)%s%Creset "
+ "%C(%5)%ci%Creset"
+ ).arg(commitHash, decoration, authorName, commitSubject, commitDate);
+
+ QStringList graphArgs = {graphOption, "--oneline", "--topo-order"};
+
+ if (gitHasRgbColors())
+ graphArgs << formatArg;
+ else
+ graphArgs << "--pretty=format:%h %d %an %s %ci";
+
+ return graphArgs;
+ }
};
class GitRefLogArgumentsWidget : public BaseGitLogArgumentsWidget
@@ -827,7 +848,7 @@ QStringList GitClient::unmanagedFiles(const QString &workingDirectory,
if (response.result != SynchronousProcessResponse::Finished)
return filePaths;
const QStringList managedFilePaths
- = transform(response.stdOut().split('\0', QString::SkipEmptyParts),
+ = transform(response.stdOut().split('\0', Utils::SkipEmptyParts),
[&wd](const QString &fp) { return wd.absoluteFilePath(fp); });
return filtered(filePaths, [&managedFilePaths](const QString &fp) {
return !managedFilePaths.contains(fp);
@@ -936,19 +957,20 @@ void GitClient::stage(DiffEditor::DiffEditorController *diffController,
void GitClient::requestReload(const QString &documentId, const QString &source,
const QString &title, const QString &workingDirectory,
- std::function<VcsBaseDiffEditorController *(IDocument *)> factory) const
+ std::function<GitBaseDiffEditorController *(IDocument *)> factory) const
{
// Creating document might change the referenced source. Store a copy and use it.
const QString sourceCopy = source;
IDocument *document = DiffEditorController::findOrCreateDocument(documentId, title);
QTC_ASSERT(document, return);
- VcsBaseDiffEditorController *controller = factory(document);
+ GitBaseDiffEditorController *controller = factory(document);
QTC_ASSERT(controller, return);
controller->setVcsBinary(settings().binaryPath());
controller->setVcsTimeoutS(settings().vcsTimeoutS());
controller->setProcessEnvironment(processEnvironment());
controller->setWorkingDirectory(workingDirectory);
+ controller->initialize();
connect(controller, &DiffEditorController::chunkActionsRequested,
this, &GitClient::chunkActionsRequested, Qt::DirectConnection);
@@ -978,17 +1000,20 @@ void GitClient::diffProject(const QString &workingDirectory, const QString &proj
requestReload(documentId,
workingDirectory, tr("Git Diff Project"), workingDirectory,
[projectDirectory](IDocument *doc){
- return new ProjectDiffController(doc, {projectDirectory});
+ return new GitDiffEditorController(doc, {}, {}, {"--", projectDirectory});
});
}
-void GitClient::diffRepository(const QString &workingDirectory)
+void GitClient::diffRepository(const QString &workingDirectory,
+ const QString &leftCommit,
+ const QString &rightCommit) const
{
const QString documentId = QLatin1String(Constants::GIT_PLUGIN)
+ QLatin1String(".DiffRepository.") + workingDirectory;
- requestReload(documentId,
- workingDirectory, tr("Git Diff Repository"), workingDirectory,
- [](IDocument *doc) { return new RepositoryDiffController(doc); });
+ requestReload(documentId, workingDirectory, tr("Git Diff Repository"), workingDirectory,
+ [&leftCommit, &rightCommit](IDocument *doc) {
+ return new GitDiffEditorController(doc, leftCommit, rightCommit, {});
+ });
}
void GitClient::diffFile(const QString &workingDirectory, const QString &fileName) const
@@ -998,7 +1023,9 @@ void GitClient::diffFile(const QString &workingDirectory, const QString &fileNam
const QString documentId = QLatin1String(Constants::GIT_PLUGIN)
+ QLatin1String(".DifFile.") + sourceFile;
requestReload(documentId, sourceFile, title, workingDirectory,
- [fileName](IDocument *doc) { return new FileDiffController(doc, fileName); });
+ [&fileName](IDocument *doc) {
+ return new GitDiffEditorController(doc, {}, {}, {"--", fileName});
+ });
}
void GitClient::diffBranch(const QString &workingDirectory, const QString &branchName) const
@@ -1007,7 +1034,9 @@ void GitClient::diffBranch(const QString &workingDirectory, const QString &branc
const QString documentId = QLatin1String(Constants::GIT_PLUGIN)
+ QLatin1String(".DiffBranch.") + branchName;
requestReload(documentId, workingDirectory, title, workingDirectory,
- [branchName](IDocument *doc) { return new BranchDiffController(doc, branchName); });
+ [branchName](IDocument *doc) {
+ return new GitDiffEditorController(doc, branchName, {}, {});
+ });
}
void GitClient::merge(const QString &workingDirectory,
@@ -1018,7 +1047,7 @@ void GitClient::merge(const QString &workingDirectory,
delete mergeTool;
}
-void GitClient::status(const QString &workingDirectory)
+void GitClient::status(const QString &workingDirectory) const
{
VcsOutputWindow::setRepository(workingDirectory);
VcsCommand *command = vcsExec(workingDirectory, {"status", "-u"}, nullptr, true);
@@ -1026,6 +1055,28 @@ void GitClient::status(const QString &workingDirectory)
Qt::QueuedConnection);
}
+static QStringList normalLogArguments()
+{
+ if (!gitHasRgbColors())
+ return {};
+
+ const QString authorName = logColorName(TextEditor::C_LOG_AUTHOR_NAME);
+ const QString commitDate = logColorName(TextEditor::C_LOG_COMMIT_DATE);
+ const QString commitHash = logColorName(TextEditor::C_LOG_COMMIT_HASH);
+ const QString commitSubject = logColorName(TextEditor::C_LOG_COMMIT_SUBJECT);
+ const QString decoration = logColorName(TextEditor::C_LOG_DECORATION);
+
+ const QString logArgs = QStringLiteral(
+ "--pretty=format:"
+ "commit %C(%1)%H%Creset %C(%2)%d%Creset%n"
+ "Author: %C(%3)%an <%ae>%Creset%n"
+ "Date: %C(%4)%cD%Creset%n%n"
+ "%C(%5)%w(0,4,4)%s%Creset%n%n%b"
+ ).arg(commitHash, decoration, authorName, commitDate, commitSubject);
+
+ return {logArgs};
+}
+
void GitClient::log(const QString &workingDirectory, const QString &fileName,
bool enableAnnotationContextMenu, const QStringList &args)
{
@@ -1055,12 +1106,21 @@ void GitClient::log(const QString &workingDirectory, const QString &fileName,
editor->setFileLogAnnotateEnabled(enableAnnotationContextMenu);
editor->setWorkingDirectory(workingDir);
- QStringList arguments = {"log", noColorOption, decorateOption};
+ QStringList arguments = {"log", decorateOption};
int logCount = settings().intValue(GitSettings::logCountKey);
if (logCount > 0)
arguments << "-n" << QString::number(logCount);
arguments << argWidget->arguments();
+ if (arguments.contains(patchOption)) {
+ arguments.removeAll(colorOption);
+ editor->setHighlightingEnabled(true);
+ } else if (gitHasRgbColors()) {
+ editor->setHighlightingEnabled(false);
+ }
+ if (!arguments.contains(graphOption) && !arguments.contains(patchOption))
+ arguments << normalLogArguments();
+
const QString grepValue = editor->grepValue();
if (!grepValue.isEmpty())
arguments << "--grep=" + grepValue;
@@ -1285,7 +1345,9 @@ QStringList GitClient::setupCheckoutArguments(const QString &workingDirectory,
}
}
+ const QString suggestedName = suggestedLocalBranchName(localBranches, remoteBranch);
BranchAddDialog branchAddDialog(localBranches, BranchAddDialog::Type::AddBranch, ICore::dialogParent());
+ branchAddDialog.setBranchName(suggestedName);
branchAddDialog.setTrackedBranchName(remoteBranch, true);
if (branchAddDialog.exec() != QDialog::Accepted)
@@ -2431,7 +2493,7 @@ QStringList GitClient::synchronousRepositoryBranches(const QString &repositoryUR
return branches;
}
-void GitClient::launchGitK(const QString &workingDirectory, const QString &fileName)
+void GitClient::launchGitK(const QString &workingDirectory, const QString &fileName) const
{
const QFileInfo binaryInfo = vcsBinary().toFileInfo();
QDir foundBinDir(binaryInfo.dir());
@@ -2467,7 +2529,7 @@ void GitClient::launchGitK(const QString &workingDirectory, const QString &fileN
VcsOutputWindow::appendError(msgCannotLaunch("gitk"));
}
-void GitClient::launchRepositoryBrowser(const QString &workingDirectory)
+void GitClient::launchRepositoryBrowser(const QString &workingDirectory) const
{
const QString repBrowserBinary = settings().stringValue(GitSettings::repositoryBrowserCmd);
if (!repBrowserBinary.isEmpty())
@@ -2477,7 +2539,7 @@ void GitClient::launchRepositoryBrowser(const QString &workingDirectory)
bool GitClient::tryLauchingGitK(const QProcessEnvironment &env,
const QString &workingDirectory,
const QString &fileName,
- const QString &gitBinDirectory)
+ const QString &gitBinDirectory) const
{
QString binary = gitBinDirectory + "/gitk";
QStringList arguments;
@@ -2499,7 +2561,7 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env,
// the child), but that does not have an environment parameter.
bool success = false;
if (!settings().stringValue(GitSettings::pathKey).isEmpty()) {
- auto process = new QProcess(this);
+ auto process = new QProcess;
process->setWorkingDirectory(workingDirectory);
process->setProcessEnvironment(env);
process->start(binary, arguments);
@@ -2559,6 +2621,24 @@ FilePath GitClient::gitBinDirectory() const
return FilePath::fromString(path);
}
+bool GitClient::launchGitBash(const QString &workingDirectory)
+{
+ bool success = true;
+ const QString git = vcsBinary().toString();
+
+ if (git.isEmpty()) {
+ success = false;
+ } else {
+ const QString gitBash = QFileInfo(git).absolutePath() + "/../git-bash.exe";
+ success = QProcess::startDetached(gitBash, {}, workingDirectory);
+ }
+
+ if (!success)
+ VcsOutputWindow::appendError(msgCannotLaunch("git-bash"));
+
+ return success;
+}
+
FilePath GitClient::vcsBinary() const
{
bool ok;
@@ -3116,7 +3196,7 @@ void GitClient::addFuture(const QFuture<void> &future)
}
// Subversion: git svn
-void GitClient::synchronousSubversionFetch(const QString &workingDirectory)
+void GitClient::synchronousSubversionFetch(const QString &workingDirectory) const
{
// Disable UNIX terminals to suppress SSH prompting.
const unsigned flags = VcsCommand::SshPasswordPrompt
@@ -3125,7 +3205,7 @@ void GitClient::synchronousSubversionFetch(const QString &workingDirectory)
vcsSynchronousExec(workingDirectory, {"svn", "fetch"}, flags);
}
-void GitClient::subversionLog(const QString &workingDirectory)
+void GitClient::subversionLog(const QString &workingDirectory) const
{
QStringList arguments = {"svn", "log"};
int logCount = settings().intValue(GitSettings::logCountKey);
@@ -3142,7 +3222,7 @@ void GitClient::subversionLog(const QString &workingDirectory)
vcsExec(workingDirectory, arguments, editor);
}
-void GitClient::subversionDeltaCommit(const QString &workingDirectory)
+void GitClient::subversionDeltaCommit(const QString &workingDirectory) const
{
vcsExec(workingDirectory, {"svn", "dcommit"}, nullptr, true,
VcsCommand::ShowSuccessMessage);
@@ -3160,7 +3240,7 @@ void GitClient::push(const QString &workingDirectory, const QStringList &pushArg
command->setCookie(NoRemoteBranch);
if (command->cookie().toInt() == NoRemoteBranch) {
- const QStringList lines = text.split('\n', QString::SkipEmptyParts);
+ const QStringList lines = text.split('\n', Utils::SkipEmptyParts);
for (const QString &line : lines) {
/* Extract the suggested command from the git output which
* should be similar to the following:
@@ -3210,7 +3290,7 @@ void GitClient::push(const QString &workingDirectory, const QStringList &pushArg
QMessageBox::No) == QMessageBox::Yes) {
const QStringList fallbackCommandParts =
- m_pushFallbackCommand.split(' ', QString::SkipEmptyParts);
+ m_pushFallbackCommand.split(' ', Utils::SkipEmptyParts);
VcsCommand *rePushCommand = vcsExec(workingDirectory,
fallbackCommandParts.mid(1),
nullptr, true, VcsCommand::ShowSuccessMessage);
@@ -3596,6 +3676,20 @@ GitRemote::GitRemote(const QString &location) : Core::IVersionControl::RepoUrl(l
isValid = QDir(path).exists() || QDir(path + ".git").exists();
}
+QString GitClient::suggestedLocalBranchName(const QStringList localNames,
+ const QString trackedBranch)
+{
+ const QString suggestedNameBase = trackedBranch.mid(trackedBranch.lastIndexOf('/') + 1);
+ QString suggestedName = suggestedNameBase;
+ int i = 2;
+ while (localNames.contains(suggestedName)) {
+ suggestedName = suggestedNameBase + QString::number(i);
+ ++i;
+ }
+
+ return suggestedName;
+}
+
void GitClient::addChangeActions(QMenu *menu, const QString &workingDir, const QString &change)
{
QTC_ASSERT(!change.isEmpty(), return);
@@ -3646,6 +3740,21 @@ void GitClient::addChangeActions(QMenu *menu, const QString &workingDir, const Q
resetMenu->addAction(tr("&Mixed"), std::bind(resetChange, "mixed"));
resetMenu->addAction(tr("&Soft"), std::bind(resetChange, "soft"));
menu->addMenu(resetMenu);
+
+ menu->addAction(tr("Di&ff Against %1").arg(change),
+ [workingDir, change] {
+ m_instance->diffRepository(workingDir, change, {});
+ });
+ if (!m_instance->m_diffCommit.isEmpty()) {
+ menu->addAction(tr("Diff &Against Saved %1").arg(m_instance->m_diffCommit),
+ [workingDir, change] {
+ m_instance->diffRepository(workingDir, m_instance->m_diffCommit, change);
+ m_instance->m_diffCommit.clear();
+ });
+ }
+ menu->addAction(tr("&Save for Diff"), [change] {
+ m_instance->m_diffCommit = change;
+ });
}
} // namespace Internal