VcsCommand: Limit the usage of setCookie()

Don't use setCookie() for setting the push failure status.
Introduce a PushHandler helper that keeps the data collected
when stdErrText() signal is emitted and reuse it when
finished() is being called. Move m_pushFallbackCommand
field into the helper, as its value is meaningful only
in context of the invoked command.

Hide PushFailure enum inside PushHandler.

Change-Id: Id21457734f32e06bb130c3c07c24cb2b7af6e466
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Jarek Kobus
2022-08-02 09:08:16 +02:00
parent 7b8c053c25
commit 09fb9f3973
2 changed files with 74 additions and 73 deletions

View File

@@ -3290,89 +3290,97 @@ void GitClient::subversionDeltaCommit(const FilePath &workingDirectory) const
vcsExec(workingDirectory, {"svn", "dcommit"}, nullptr, true, VcsCommand::ShowSuccessMessage); vcsExec(workingDirectory, {"svn", "dcommit"}, nullptr, true, VcsCommand::ShowSuccessMessage);
} }
void GitClient::push(const FilePath &workingDirectory, const QStringList &pushArgs) class PushHandler : public QObject
{ {
VcsCommand *command = vcsExec(workingDirectory, QStringList({"push"}) + pushArgs, nullptr, true, public:
VcsCommand::ShowSuccessMessage); PushHandler(GitClient *gitClient, const FilePath &workingDir, const QStringList &pushArgs)
connect(command, &VcsCommand::stdErrText, this, [this, command](const QString &text) { : m_gitClient(gitClient)
PushFailure failure = Unknown; {
if (text.contains("non-fast-forward")) VcsCommand *command = gitClient->vcsExec(workingDir, QStringList({"push"}) + pushArgs,
failure = NonFastForward; nullptr, true, VcsCommand::ShowSuccessMessage);
else if (text.contains("has no upstream branch")) // Make command a parent of this in order to delete this when command is deleted
failure = NoRemoteBranch; setParent(command);
if (failure != Unknown) connect(command, &VcsCommand::stdErrText, this, [this](const QString &text) {
command->setCookie(failure); if (text.contains("non-fast-forward")) {
m_pushFailure = NonFastForward;
if (failure == NoRemoteBranch) { } else if (text.contains("has no upstream branch")) {
const QStringList lines = text.split('\n', Qt::SkipEmptyParts); m_pushFailure = NoRemoteBranch;
for (const QString &line : lines) { const QStringList lines = text.split('\n', Qt::SkipEmptyParts);
/* Extract the suggested command from the git output which for (const QString &line : lines) {
* should be similar to the following: /* Extract the suggested command from the git output which
* * should be similar to the following:
* git push --set-upstream origin add_set_upstream_dialog *
*/ * git push --set-upstream origin add_set_upstream_dialog
const QString trimmedLine = line.trimmed(); */
if (trimmedLine.startsWith("git push")) { const QString trimmedLine = line.trimmed();
m_pushFallbackCommand = trimmedLine; if (trimmedLine.startsWith("git push")) {
break; m_pushFallbackCommand = trimmedLine;
break;
}
} }
} }
} });
});
connect(command, &VcsCommand::finished, this, connect(command, &VcsCommand::finished, this, [this, workingDir, pushArgs](bool success) {
[this, workingDirectory, pushArgs](bool success, const QVariant &cookie) { if (success) {
if (success) { GitPlugin::updateCurrentBranch();
GitPlugin::updateCurrentBranch(); return;
return; }
} if (m_pushFailure == Unknown || !m_gitClient)
switch (static_cast<PushFailure>(cookie.toInt())) { return;
case Unknown:
break; if (m_pushFailure == NonFastForward) {
case NonFastForward: { const QColor warnColor = Utils::creatorTheme()->color(Theme::TextColorError);
const QColor warnColor = Utils::creatorTheme()->color(Theme::TextColorError); if (QMessageBox::question(
if (QMessageBox::question( Core::ICore::dialogParent(), tr("Force Push"),
Core::ICore::dialogParent(), tr("Force Push"), tr("Push failed. Would you like to force-push <span style=\"color:#%1\">"
tr("Push failed. Would you like to force-push <span style=\"color:#%1\">" "(rewrites remote history)</span>?")
"(rewrites remote history)</span>?") .arg(QString::number(warnColor.rgba(), 16)),
.arg(QString::number(warnColor.rgba(), 16)), QMessageBox::Yes | QMessageBox::No,
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) {
QMessageBox::No) == QMessageBox::Yes) { return;
VcsCommand *rePushCommand = vcsExec(workingDirectory, }
QStringList({"push", "--force-with-lease"}) + pushArgs, VcsCommand *rePushCommand = m_gitClient->vcsExec(workingDir,
nullptr, true, VcsCommand::ShowSuccessMessage); QStringList({"push", "--force-with-lease"}) + pushArgs,
nullptr, true, VcsCommand::ShowSuccessMessage);
connect(rePushCommand, &VcsCommand::finished, this, [](bool success) { connect(rePushCommand, &VcsCommand::finished, this, [](bool success) {
if (success) if (success)
GitPlugin::updateCurrentBranch(); GitPlugin::updateCurrentBranch();
}); });
return;
} }
break; // NoRemoteBranch case
}
case NoRemoteBranch:
if (QMessageBox::question( if (QMessageBox::question(
Core::ICore::dialogParent(), tr("No Upstream Branch"), Core::ICore::dialogParent(), tr("No Upstream Branch"),
tr("Push failed because the local branch \"%1\" " tr("Push failed because the local branch \"%1\" "
"does not have an upstream branch on the remote.\n\n" "does not have an upstream branch on the remote.\n\n"
"Would you like to create the branch \"%1\" on the " "Would you like to create the branch \"%1\" on the "
"remote and set it as upstream?") "remote and set it as upstream?")
.arg(synchronousCurrentLocalBranch(workingDirectory)), .arg(m_gitClient->synchronousCurrentLocalBranch(workingDir)),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes | QMessageBox::No,
QMessageBox::No) == QMessageBox::Yes) { QMessageBox::No) != QMessageBox::Yes) {
return;
const QStringList fallbackCommandParts =
m_pushFallbackCommand.split(' ', Qt::SkipEmptyParts);
VcsCommand *rePushCommand = vcsExec(workingDirectory,
fallbackCommandParts.mid(1), nullptr, true,
VcsCommand::ShowSuccessMessage);
connect(rePushCommand, &VcsCommand::finished, this,
[workingDirectory](bool success) {
if (success)
GitPlugin::updateBranches(workingDirectory);
});
} }
break; const QStringList fallbackCommandParts =
} m_pushFallbackCommand.split(' ', Qt::SkipEmptyParts);
}); VcsCommand *rePushCommand = m_gitClient->vcsExec(workingDir,
fallbackCommandParts.mid(1), nullptr, true, VcsCommand::ShowSuccessMessage);
connect(rePushCommand, &VcsCommand::finished, this, [workingDir](bool success) {
if (success)
GitPlugin::updateBranches(workingDir);
});
});
}
private:
enum PushFailure { Unknown, NonFastForward, NoRemoteBranch } m_pushFailure = Unknown;
QPointer<GitClient> m_gitClient;
QString m_pushFallbackCommand;
};
void GitClient::push(const FilePath &workingDirectory, const QStringList &pushArgs)
{
new PushHandler(this, workingDirectory, pushArgs);
} }
bool GitClient::synchronousMerge(const FilePath &workingDirectory, const QString &branch, bool GitClient::synchronousMerge(const FilePath &workingDirectory, const QString &branch,

View File

@@ -80,12 +80,6 @@ enum StashFlag {
NoPrompt = 0x02 NoPrompt = 0x02
}; };
enum PushFailure {
Unknown,
NonFastForward,
NoRemoteBranch
};
class SubmoduleData class SubmoduleData
{ {
public: public:
@@ -425,7 +419,6 @@ private:
QString m_gitQtcEditor; QString m_gitQtcEditor;
QMap<Utils::FilePath, StashInfo> m_stashInfo; QMap<Utils::FilePath, StashInfo> m_stashInfo;
QString m_pushFallbackCommand;
QString m_diffCommit; QString m_diffCommit;
Utils::FilePaths m_updatedSubmodules; Utils::FilePaths m_updatedSubmodules;
bool m_disableEditor = false; bool m_disableEditor = false;