VCS: VcsBaseClient::vcsFullySynchronousExec returns a SynchronousProcessResponse

Change-Id: Ic155da2ed1fd36f1f91327ac90f34a5cad3c210e
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Tobias Hunger
2016-07-05 10:34:41 +02:00
parent 5efd82468b
commit ca7a924a06
7 changed files with 320 additions and 343 deletions

View File

@@ -103,7 +103,8 @@ static unsigned diffExecutionFlags()
}
const unsigned silentFlags = unsigned(VcsCommand::SuppressCommandLogging
| VcsCommand::SuppressStdErr);
| VcsCommand::SuppressStdErr
| VcsCommand::SuppressFailMessage);
/////////////////////////////////////
@@ -567,12 +568,12 @@ static inline void msgCannotRun(const QString &message, QString *errorMessage)
}
static inline void msgCannotRun(const QStringList &args, const QString &workingDirectory,
const QByteArray &error, QString *errorMessage)
const QString &error, QString *errorMessage)
{
const QString message = GitClient::tr("Cannot run \"%1\" in \"%2\": %3")
.arg("git " + args.join(' '),
QDir::toNativeSeparators(workingDirectory),
GitClient::commandOutputFromLocal8Bit(error));
error);
msgCannotRun(message, errorMessage);
}
@@ -625,9 +626,8 @@ QString GitClient::findGitDirForRepository(const QString &repositoryDir) const
bool GitClient::managesFile(const QString &workingDirectory, const QString &fileName) const
{
QByteArray output;
const QStringList arguments = { "ls-files", "--error-unmatch", fileName };
return vcsFullySynchronousExec(workingDirectory, arguments, &output, 0, silentFlags);
return vcsFullySynchronousExec(workingDirectory, { "ls-files", "--error-unmatch", fileName }).result
== SynchronousProcessResponse::Finished;
}
QTextCodec *GitClient::codecFor(GitClient::CodecType codecType, const QString &source) const
@@ -938,17 +938,17 @@ bool GitClient::synchronousCheckout(const QString &workingDirectory,
const QString &ref,
QString *errorMessage)
{
QByteArray outputText;
QByteArray errorText;
QStringList arguments = setupCheckoutArguments(workingDirectory, ref);
const bool rc = vcsFullySynchronousExec(workingDirectory, arguments, &outputText, 0,
VcsCommand::ExpectRepoChanges);
VcsOutputWindow::append(commandOutputFromLocal8Bit(outputText));
if (rc)
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory, arguments, VcsCommand::ExpectRepoChanges);
VcsOutputWindow::append(resp.stdOut());
if (resp.result == SynchronousProcessResponse::Finished) {
updateSubmodulesIfNeeded(workingDirectory, true);
else
msgCannotRun(arguments, workingDirectory, errorText, errorMessage);
return rc;
return true;
} else {
msgCannotRun(arguments, workingDirectory, resp.stdErr(), errorMessage);
return false;
}
}
/* method used to setup arguments for checkout, in case user wants to create local branch */
@@ -1044,76 +1044,72 @@ void GitClient::addFile(const QString &workingDirectory, const QString &fileName
bool GitClient::synchronousLog(const QString &workingDirectory, const QStringList &arguments,
QString *output, QString *errorMessageIn, unsigned flags)
{
QByteArray outputData;
QByteArray errorData;
QStringList allArguments = { "log", noColorOption };
allArguments.append(arguments);
const bool rc = vcsFullySynchronousExec(workingDirectory, allArguments, &outputData, &errorData, flags);
if (rc) {
if (QTextCodec *codec = encoding(workingDirectory, "i18n.logOutputEncoding"))
*output = codec->toUnicode(outputData);
else
*output = commandOutputFromLocal8Bit(outputData);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory, allArguments, flags, vcsTimeoutS(),
encoding(workingDirectory, "i18n.logOutputEncoding"));
if (resp.result == SynchronousProcessResponse::Finished) {
*output = resp.stdOut();
return true;
} else {
msgCannotRun(tr("Cannot obtain log of \"%1\": %2")
.arg(QDir::toNativeSeparators(workingDirectory),
commandOutputFromLocal8Bit(errorData)), errorMessageIn);
.arg(QDir::toNativeSeparators(workingDirectory), resp.stdErr()), errorMessageIn);
return false;
}
return rc;
}
bool GitClient::synchronousAdd(const QString &workingDirectory, const QStringList &files)
{
QByteArray outputText;
return vcsFullySynchronousExec(workingDirectory, QStringList({ "add" }) + files, &outputText);
return vcsFullySynchronousExec(workingDirectory, QStringList({ "add" }) + files).result
== SynchronousProcessResponse::Finished;
}
bool GitClient::synchronousDelete(const QString &workingDirectory,
bool force,
const QStringList &files)
{
QByteArray outputText;
QStringList arguments = { "rm" };
if (force)
arguments << "--force";
arguments.append(files);
return vcsFullySynchronousExec(workingDirectory, arguments, &outputText);
return vcsFullySynchronousExec(workingDirectory, arguments).result
== SynchronousProcessResponse::Finished;
}
bool GitClient::synchronousMove(const QString &workingDirectory,
const QString &from,
const QString &to)
{
QByteArray outputText;
return vcsFullySynchronousExec(workingDirectory, { "mv", from, to }, &outputText);
return vcsFullySynchronousExec(workingDirectory, { "mv", from, to }).result
== SynchronousProcessResponse::Finished;
}
bool GitClient::synchronousReset(const QString &workingDirectory,
const QStringList &files,
QString *errorMessage)
{
QByteArray outputText;
QByteArray errorText;
QStringList arguments = { "reset" };
if (files.isEmpty())
arguments << "--hard";
else
arguments << HEAD << "--" << files;
const bool rc = vcsFullySynchronousExec(workingDirectory, arguments, &outputText, &errorText);
const QString output = commandOutputFromLocal8Bit(outputText);
VcsOutputWindow::append(output);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, arguments);
const QString stdOut = resp.stdOut();
VcsOutputWindow::append(stdOut);
// Note that git exits with 1 even if the operation is successful
// Assume real failure if the output does not contain "foo.cpp modified"
// or "Unstaged changes after reset" (git 1.7.0).
if (!rc && (!output.contains("modified") && !output.contains("Unstaged changes after reset"))) {
if (resp.result == SynchronousProcessResponse::Finished
&& (!stdOut.contains("modified") && !stdOut.contains("Unstaged changes after reset"))) {
if (files.isEmpty()) {
msgCannotRun(arguments, workingDirectory, errorText, errorMessage);
msgCannotRun(arguments, workingDirectory, resp.stdErr(), errorMessage);
} else {
msgCannotRun(tr("Cannot reset %n file(s) in \"%1\": %2", 0, files.size())
.arg(QDir::toNativeSeparators(workingDirectory),
commandOutputFromLocal8Bit(errorText)),
.arg(QDir::toNativeSeparators(workingDirectory), resp.stdErr()),
errorMessage);
}
return false;
@@ -1124,13 +1120,15 @@ bool GitClient::synchronousReset(const QString &workingDirectory,
// Initialize repository
bool GitClient::synchronousInit(const QString &workingDirectory)
{
QByteArray outputText;
const bool rc = vcsFullySynchronousExec(workingDirectory, { "init" }, &outputText);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, { "init" });
// '[Re]Initialized...'
VcsOutputWindow::append(commandOutputFromLocal8Bit(outputText));
if (rc)
VcsOutputWindow::append(resp.stdOut());
if (resp.result == SynchronousProcessResponse::Finished) {
resetCachedVcsInfo(workingDirectory);
return rc;
return true;
} else {
return false;
}
}
/* Checkout, supports:
@@ -1145,21 +1143,18 @@ bool GitClient::synchronousCheckoutFiles(const QString &workingDirectory, QStrin
revision = HEAD;
if (files.isEmpty())
files = QStringList(".");
QByteArray outputText;
QByteArray errorText;
QStringList arguments = { "checkout" };
if (revertStaging)
arguments << revision;
arguments << "--" << files;
const bool rc = vcsFullySynchronousExec(workingDirectory, arguments, &outputText, &errorText,
VcsCommand::ExpectRepoChanges);
if (!rc) {
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory, arguments, VcsCommand::ExpectRepoChanges);
if (resp.result != SynchronousProcessResponse::Finished) {
const QString fileArg = files.join(", ");
//: Meaning of the arguments: %1: revision, %2: files, %3: repository,
//: %4: Error message
msgCannotRun(tr("Cannot checkout \"%1\" of %2 in \"%3\": %4")
.arg(revision, fileArg, workingDirectory,
commandOutputFromLocal8Bit(errorText)),
.arg(revision, fileArg, workingDirectory, resp.stdErr()),
errorMessage);
return false;
}
@@ -1212,16 +1207,14 @@ static inline bool splitCommitParents(const QString &line,
bool GitClient::synchronousRevListCmd(const QString &workingDirectory, const QStringList &extraArguments,
QString *output, QString *errorMessage) const
{
QByteArray outputTextData;
QByteArray errorText;
const QStringList arguments = QStringList({ "rev-list", noColorOption }) + extraArguments;
const bool rc = vcsFullySynchronousExec(workingDirectory, arguments, &outputTextData,
&errorText, silentFlags);
if (!rc) {
msgCannotRun(arguments, workingDirectory, errorText, errorMessage);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory, arguments, silentFlags);
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(arguments, workingDirectory, resp.stdErr(), errorMessage);
return false;
}
*output = commandOutputFromLocal8Bit(outputTextData);
*output = resp.stdOut();
return true;
}
@@ -1273,11 +1266,11 @@ QString GitClient::synchronousShortDescription(const QString &workingDirectory,
QString GitClient::synchronousCurrentLocalBranch(const QString &workingDirectory) const
{
QByteArray outputTextData;
QString branch;
if (vcsFullySynchronousExec(workingDirectory, { "symbolic-ref", HEAD }, &outputTextData, 0,
silentFlags)) {
branch = commandOutputFromLocal8Bit(outputTextData.trimmed());
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory, { "symbolic-ref", HEAD }, silentFlags);
if (resp.result == SynchronousProcessResponse::Finished) {
branch = resp.stdOut().trimmed();
} else {
const QString gitDir = findGitDirForRepository(workingDirectory);
const QString rebaseHead = gitDir + "/rebase-merge/head-name";
@@ -1299,27 +1292,25 @@ bool GitClient::synchronousHeadRefs(const QString &workingDirectory, QStringList
QString *errorMessage) const
{
const QStringList arguments = { "show-ref", "--head", "--abbrev=10", "--dereference" };
QByteArray outputText;
QByteArray errorText;
const bool rc = vcsFullySynchronousExec(workingDirectory, arguments, &outputText, &errorText,
silentFlags);
if (!rc) {
msgCannotRun(arguments, workingDirectory, errorText, errorMessage);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory, arguments, silentFlags);
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(arguments, workingDirectory, resp.stdErr(), errorMessage);
return false;
}
QByteArray headSha = outputText.left(10);
QByteArray newLine("\n");
const QString stdOut = resp.stdOut();
const QString headSha = stdOut.left(10);
const QChar newLine('\n');
int currentIndex = 15;
while (true) {
currentIndex = outputText.indexOf(headSha, currentIndex);
currentIndex = stdOut.indexOf(headSha, currentIndex);
if (currentIndex < 0)
break;
currentIndex += 11;
output->append(QString::fromLocal8Bit(outputText.mid(currentIndex,
outputText.indexOf(newLine, currentIndex) - currentIndex)));
output->append(stdOut.mid(currentIndex, stdOut.indexOf(newLine, currentIndex) - currentIndex));
}
return true;
@@ -1356,11 +1347,12 @@ QString GitClient::synchronousTopic(const QString &workingDirectory) const
return remoteBranch;
// No tag or remote branch - try git describe
QByteArray output;
if (vcsFullySynchronousExec(workingDirectory, { "describe" }, &output, 0, VcsCommand::NoOutput)) {
const QString describeOutput = commandOutputFromLocal8Bit(output.trimmed());
if (!describeOutput.isEmpty())
return describeOutput;
const SynchronousProcessResponse resp =
vcsFullySynchronousExec(workingDirectory, { "describe" }, VcsCommand::NoOutput);
if (resp.result == SynchronousProcessResponse::Finished) {
const QString stdOut = resp.stdOut().trimmed();
if (!stdOut.isEmpty())
return stdOut;
}
return tr("Detached HEAD");
}
@@ -1369,15 +1361,15 @@ bool GitClient::synchronousRevParseCmd(const QString &workingDirectory, const QS
QString *output, QString *errorMessage) const
{
const QStringList arguments = { "rev-parse", ref };
QByteArray outputText;
QByteArray errorText;
const bool rc = vcsFullySynchronousExec(workingDirectory, arguments, &outputText, &errorText,
silentFlags);
*output = commandOutputFromLocal8Bit(outputText.trimmed());
if (!rc)
msgCannotRun(arguments, workingDirectory, errorText, errorMessage);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory, arguments, silentFlags);
*output = resp.stdOut().trimmed();
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(arguments, workingDirectory, resp.stdErr(), errorMessage);
return false;
}
return rc;
return true;
}
// Retrieve head revision
@@ -1393,28 +1385,27 @@ QString GitClient::synchronousTopRevision(const QString &workingDirectory, QStri
void GitClient::synchronousTagsForCommit(const QString &workingDirectory, const QString &revision,
QString &precedes, QString &follows) const
{
QByteArray pr;
vcsFullySynchronousExec(workingDirectory, { "describe", "--contains", revision },
&pr, 0, silentFlags);
int tilde = pr.indexOf('~');
const SynchronousProcessResponse resp1 = vcsFullySynchronousExec(
workingDirectory, { "describe", "--contains", revision }, silentFlags);
precedes = resp1.stdOut();
int tilde = precedes.indexOf('~');
if (tilde != -1)
pr.truncate(tilde);
precedes.truncate(tilde);
else
pr = pr.trimmed();
precedes = QString::fromLocal8Bit(pr);
precedes = precedes.trimmed();
QStringList parents;
QString errorMessage;
synchronousParentRevisions(workingDirectory, revision, &parents, &errorMessage);
foreach (const QString &p, parents) {
QByteArray pf;
vcsFullySynchronousExec(workingDirectory, { "describe", "--tags", "--abbrev=0", p },
&pf, 0, silentFlags);
const SynchronousProcessResponse resp2 = vcsFullySynchronousExec(
workingDirectory, { "describe", "--tags", "--abbrev=0", p }, silentFlags);
QString pf = resp2.stdOut();
pf.truncate(pf.lastIndexOf('\n'));
if (!pf.isEmpty()) {
if (!follows.isEmpty())
follows += ", ";
follows += QString::fromLocal8Bit(pf);
follows += pf;
}
}
}
@@ -1432,41 +1423,31 @@ void GitClient::branchesForCommit(const QString &revision)
bool GitClient::isRemoteCommit(const QString &workingDirectory, const QString &commit)
{
QByteArray outputText;
vcsFullySynchronousExec(workingDirectory, { "branch", "-r", "--contains", commit },
&outputText, 0, silentFlags);
return !outputText.isEmpty();
return !vcsFullySynchronousExec(
workingDirectory, { "branch", "-r", "--contains", commit }, silentFlags).rawStdOut.isEmpty();
}
bool GitClient::isFastForwardMerge(const QString &workingDirectory, const QString &branch)
{
QByteArray outputText;
vcsFullySynchronousExec(workingDirectory, { "merge-base", HEAD, branch },
&outputText, 0, silentFlags);
return commandOutputFromLocal8Bit(outputText).trimmed()
== synchronousTopRevision(workingDirectory);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory, { "merge-base", HEAD, branch }, silentFlags);
return resp.stdOut().trimmed() == synchronousTopRevision(workingDirectory);
}
// 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) const
{
QString description;
QByteArray outputTextData;
QByteArray errorText;
const QStringList arguments = { "log", noColorOption, ("--pretty=format:" + format),
"--max-count=1", revision };
const bool rc = vcsFullySynchronousExec(workingDirectory, arguments, &outputTextData, &errorText,
silentFlags);
if (!rc) {
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory, arguments, silentFlags);
if (resp.result != SynchronousProcessResponse::Finished) {
VcsOutputWindow::appendSilently(tr("Cannot describe revision \"%1\" in \"%2\": %3")
.arg(revision, workingDirectory, commandOutputFromLocal8Bit(errorText)));
.arg(revision, workingDirectory, resp.stdErr()));
return revision;
}
description = commandOutputFromLocal8Bit(outputTextData);
if (description.endsWith('\n'))
description.truncate(description.size() - 1);
return description;
return stripLastNewline(resp.stdOut());
}
// Create a default message to be used for describing stashes
@@ -1540,12 +1521,13 @@ bool GitClient::executeSynchronousStash(const QString &workingDirectory,
const unsigned flags = VcsCommand::ShowStdOut
| VcsCommand::ExpectRepoChanges
| VcsCommand::ShowSuccessMessage;
const SynchronousProcessResponse response = vcsSynchronousExec(workingDirectory, arguments, flags);
const bool rc = response.result == SynchronousProcessResponse::Finished;
if (!rc)
msgCannotRun(arguments, workingDirectory, response.rawStdErr, errorMessage);
const SynchronousProcessResponse resp = vcsSynchronousExec(workingDirectory, arguments, flags);
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(arguments, workingDirectory, resp.stdErr(), errorMessage);
return false;
}
return rc;
return true;
}
// Resolve a stash name from message
@@ -1578,43 +1560,40 @@ bool GitClient::synchronousBranchCmd(const QString &workingDirectory, QStringLis
QString *output, QString *errorMessage) const
{
branchArgs.push_front("branch");
QByteArray outputText;
QByteArray errorText;
const bool rc = vcsFullySynchronousExec(workingDirectory, branchArgs, &outputText, &errorText);
*output = commandOutputFromLocal8Bit(outputText);
if (!rc)
msgCannotRun(branchArgs, workingDirectory, errorText, errorMessage);
return rc;
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, branchArgs);
*output = resp.stdOut();
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(branchArgs, workingDirectory, resp.stdErr(), errorMessage);
return false;
}
return true;
}
bool GitClient::synchronousTagCmd(const QString &workingDirectory, QStringList tagArgs,
QString *output, QString *errorMessage) const
{
tagArgs.push_front("tag");
QByteArray outputText;
QByteArray errorText;
const bool rc = vcsFullySynchronousExec(workingDirectory, tagArgs, &outputText, &errorText);
*output = commandOutputFromLocal8Bit(outputText);
if (!rc)
msgCannotRun(tagArgs, workingDirectory, errorText, errorMessage);
return rc;
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, tagArgs);
*output = resp.stdOut();
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(tagArgs, workingDirectory, resp.stdErr(), errorMessage);
return false;
}
return true;
}
bool GitClient::synchronousForEachRefCmd(const QString &workingDirectory, QStringList args,
QString *output, QString *errorMessage) const
{
args.push_front("for-each-ref");
QByteArray outputText;
QByteArray errorText;
const bool rc = vcsFullySynchronousExec(workingDirectory, args, &outputText, &errorText,
silentFlags);
*output = SynchronousProcess::normalizeNewlines(QString::fromUtf8(outputText));
if (!rc)
msgCannotRun(args, workingDirectory, errorText, errorMessage);
return rc;
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, args,
silentFlags);
*output = resp.stdOut();
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(args, workingDirectory, resp.stdErr(), errorMessage);
return false;
}
return true;
}
VcsCommand *GitClient::asyncForEachRefCmd(const QString &workingDirectory, QStringList args) const
@@ -1627,15 +1606,17 @@ bool GitClient::synchronousRemoteCmd(const QString &workingDirectory, QStringLis
QString *output, QString *errorMessage, bool silent) const
{
remoteArgs.push_front("remote");
QByteArray outputText;
QByteArray errorText;
if (!vcsFullySynchronousExec(workingDirectory, remoteArgs, &outputText, &errorText,
silent ? silentFlags : 0)) {
msgCannotRun(remoteArgs, workingDirectory, errorText, errorMessage);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, remoteArgs,
silent ? silentFlags : 0);
const QString stdErr = resp.stdErr();
*errorMessage = stdErr;
*output = resp.stdOut();
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(remoteArgs, workingDirectory, stdErr, errorMessage);
return false;
}
if (output)
*output = commandOutputFromLocal8Bit(outputText);
return true;
}
@@ -1643,6 +1624,7 @@ QMap<QString,QString> GitClient::synchronousRemotesList(const QString &workingDi
QString *errorMessage) const
{
QMap<QString,QString> result;
QString output;
QString error;
if (!synchronousRemoteCmd(workingDirectory, { "-v" }, &output, &error, true)) {
@@ -1658,7 +1640,7 @@ QMap<QString,QString> GitClient::synchronousRemotesList(const QString &workingDi
const int tabIndex = remote.indexOf('\t');
if (tabIndex == -1)
continue;
QString url = remote.mid(tabIndex + 1, remote.length() - tabIndex - 8);
const QString url = remote.mid(tabIndex + 1, remote.length() - tabIndex - 8);
result.insert(remote.left(tabIndex), url);
}
return result;
@@ -1667,17 +1649,16 @@ QMap<QString,QString> GitClient::synchronousRemotesList(const QString &workingDi
QStringList GitClient::synchronousSubmoduleStatus(const QString &workingDirectory,
QString *errorMessage) const
{
QByteArray outputTextData;
QByteArray errorText;
// get submodule status
if (!vcsFullySynchronousExec(workingDirectory, { "submodule", "status" },
&outputTextData, &errorText, silentFlags)) {
const SynchronousProcessResponse resp =
vcsFullySynchronousExec(workingDirectory, { "submodule", "status" }, silentFlags);
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(tr("Cannot retrieve submodule status of \"%1\": %2")
.arg(QDir::toNativeSeparators(workingDirectory),
commandOutputFromLocal8Bit(errorText)), errorMessage);
.arg(QDir::toNativeSeparators(workingDirectory), resp.stdErr()), errorMessage);
return QStringList();
}
return commandOutputLinesFromLocal8Bit(outputTextData);
return splitLines(resp.stdOut());
}
SubmoduleDataMap GitClient::submoduleList(const QString &workingDirectory) const
@@ -1750,11 +1731,13 @@ bool GitClient::synchronousShow(const QString &workingDirectory, const QString &
return false;
}
const QStringList arguments = { "show", decorateOption, noColorOption, id };
QByteArray errorText;
const bool rc = vcsFullySynchronousExec(workingDirectory, arguments, output, &errorText);
if (!rc)
msgCannotRun(arguments, workingDirectory, errorText, errorMessage);
return rc;
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, arguments);
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(arguments, workingDirectory, resp.stdErr(), errorMessage);
return false;
}
*output = resp.rawStdOut;
return true;
}
// Retrieve list of files to be cleaned
@@ -1763,17 +1746,17 @@ bool GitClient::cleanList(const QString &workingDirectory, const QString &module
{
const QString directory = workingDirectory + '/' + modulePath;
const QStringList arguments = { "clean", "--dry-run", flag };
QByteArray outputText;
QByteArray errorText;
const bool rc = vcsFullySynchronousExec(directory, arguments, &outputText, &errorText);
if (!rc) {
msgCannotRun(arguments, directory, errorText, errorMessage);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(directory, arguments);
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(arguments, directory, resp.stdErr(), errorMessage);
return false;
}
// Filter files that git would remove
const QString relativeBase = modulePath.isEmpty() ? QString() : modulePath + '/';
const QString prefix = "Would remove ";
foreach (const QString &line, commandOutputLinesFromLocal8Bit(outputText)) {
foreach (const QString &line, resp.stdOut()) {
if (line.startsWith(prefix))
files->push_back(relativeBase + line.mid(prefix.size()));
}
@@ -1806,19 +1789,19 @@ bool GitClient::synchronousApplyPatch(const QString &workingDirectory,
{
QStringList arguments = { "apply", "--whitespace=fix" };
arguments << extraArguments << file;
QByteArray outputText;
QByteArray errorText;
const bool rc = vcsFullySynchronousExec(workingDirectory, arguments, &outputText, &errorText);
if (rc) {
if (!errorText.isEmpty())
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, arguments);
const QString stdErr = resp.stdErr();
if (resp.result == SynchronousProcessResponse::Finished) {
if (!stdErr.isEmpty())
*errorMessage = tr("There were warnings while applying \"%1\" to \"%2\":\n%3")
.arg(file, workingDirectory, commandOutputFromLocal8Bit(errorText));
.arg(file, workingDirectory, stdErr);
return true;
} else {
*errorMessage = tr("Cannot apply patch \"%1\" to \"%2\": %3")
.arg(file, workingDirectory, commandOutputFromLocal8Bit(errorText));
.arg(QDir::toNativeSeparators(file), workingDirectory, stdErr);
return false;
}
return true;
}
QProcessEnvironment GitClient::processEnvironment() const
@@ -1932,8 +1915,6 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory, St
QString *output, QString *errorMessage) const
{
// Run 'status'. Note that git returns exitcode 1 if there are no added files.
QByteArray outputText;
QByteArray errorText;
QStringList arguments = { "status" };
if (mode & NoUntracked)
arguments << "--untracked-files=no";
@@ -1943,27 +1924,28 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory, St
arguments << "--ignore-submodules=all";
arguments << "--porcelain" << "-b";
const bool statusRc = vcsFullySynchronousExec(workingDirectory, arguments,
&outputText, &errorText, silentFlags);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory, arguments, silentFlags);
const QString stdOut = resp.stdOut();
if (output)
*output = commandOutputFromLocal8Bit(outputText);
*output = stdOut;
static const char * NO_BRANCH = "## HEAD (no branch)\n";
const bool branchKnown = !outputText.startsWith(NO_BRANCH);
const bool statusRc = resp.result == SynchronousProcessResponse::Finished;
const bool branchKnown = !stdOut.startsWith("## HEAD (no branch)\n");
// Is it something really fatal?
if (!statusRc && !branchKnown) {
if (errorMessage) {
const QString error = commandOutputFromLocal8Bit(errorText);
*errorMessage = tr("Cannot obtain status: %1").arg(error);
*errorMessage = tr("Cannot obtain status: %1").arg(resp.stdErr());
}
return StatusFailed;
}
// Unchanged (output text depending on whether -u was passed)
QList<QByteArray> lines = outputText.split('\n');
foreach (const QByteArray &line, lines)
QList<QString> lines = resp.stdOut().split('\n');
foreach (const QString &line, lines) {
if (!line.isEmpty() && !line.startsWith('#'))
return StatusChanged;
}
return StatusUnchanged;
}
@@ -2291,20 +2273,25 @@ bool GitClient::readDataFromCommit(const QString &repoDirectory, const QString &
{
// Get commit data as "SHA1<lf>author<lf>email<lf>message".
const QStringList arguments = { "log", "--max-count=1", "--pretty=format:%h\n%an\n%ae\n%B", commit };
QByteArray outputText;
if (!vcsFullySynchronousExec(repoDirectory, arguments, &outputText, 0, silentFlags)) {
if (errorMessage)
*errorMessage = tr("Cannot retrieve last commit data of repository \"%1\".").arg(repoDirectory);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(repoDirectory, arguments, silentFlags);
if (resp.result != SynchronousProcessResponse::Finished) {
if (errorMessage) {
*errorMessage = tr("Cannot retrieve last commit data of repository \"%1\".")
.arg(QDir::toNativeSeparators(repoDirectory));
}
return false;
}
QTextCodec *authorCodec = HostOsInfo::isWindowsHost()
? QTextCodec::codecForName("UTF-8")
: commitData.commitEncoding;
commitData.amendSHA1 = QLatin1String(shiftLogLine(outputText));
commitData.panelData.author = authorCodec->toUnicode(shiftLogLine(outputText));
commitData.panelData.email = authorCodec->toUnicode(shiftLogLine(outputText));
QByteArray stdOut = resp.rawStdOut;
commitData.amendSHA1 = QLatin1String(shiftLogLine(stdOut));
commitData.panelData.author = authorCodec->toUnicode(shiftLogLine(stdOut));
commitData.panelData.email = authorCodec->toUnicode(shiftLogLine(stdOut));
if (commitTemplate)
*commitTemplate = commitData.commitEncoding->toUnicode(outputText);
*commitTemplate = commitData.commitEncoding->toUnicode(stdOut);
return true;
}
@@ -2539,19 +2526,16 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory,
arguments << "--no-verify";
}
QByteArray outputText;
QByteArray errorText;
const bool rc = vcsFullySynchronousExec(repositoryDirectory, arguments, &outputText, &errorText);
const QString stdErr = commandOutputFromLocal8Bit(errorText);
if (rc) {
const SynchronousProcessResponse resp = vcsFullySynchronousExec(repositoryDirectory, arguments);
const QString stdErr = resp.stdErr();
if (resp.result == SynchronousProcessResponse::Finished) {
VcsOutputWindow::appendMessage(msgCommitted(amendSHA1, commitCount));
VcsOutputWindow::appendError(stdErr);
return true;
} else {
VcsOutputWindow::appendError(tr("Cannot commit %n file(s): %1\n", 0, commitCount).arg(stdErr));
return false;
}
return rc;
}
/* Revert: This function can be called with a file list (to revert single
@@ -2715,10 +2699,10 @@ void GitClient::synchronousAbortCommand(const QString &workingDir, const QString
QStringList(), QString(), nullptr, false);
return;
}
QByteArray stdOut;
vcsFullySynchronousExec(workingDir, { abortCommand, "--abort" }, &stdOut, nullptr,
VcsCommand::ExpectRepoChanges);
VcsOutputWindow::append(commandOutputFromLocal8Bit(stdOut));
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDir, { abortCommand, "--abort" }, VcsCommand::ExpectRepoChanges);
VcsOutputWindow::append(resp.stdOut());
}
QString GitClient::synchronousTrackingBranch(const QString &workingDirectory, const QString &branch)
@@ -2741,9 +2725,9 @@ QString GitClient::synchronousTrackingBranch(const QString &workingDirectory, co
bool GitClient::synchronousSetTrackingBranch(const QString &workingDirectory,
const QString &branch, const QString &tracking)
{
QByteArray outputText;
return vcsFullySynchronousExec(
workingDirectory, { "branch", "--set-upstream-to=" + tracking, branch }, &outputText);
workingDirectory, { "branch", "--set-upstream-to=" + tracking, branch }).result
== SynchronousProcessResponse::Finished;
}
void GitClient::handleMergeConflicts(const QString &workingDir, const QString &commit,
@@ -2962,35 +2946,35 @@ bool GitClient::synchronousStashRemove(const QString &workingDirectory, const QS
arguments << "clear";
else
arguments << "drop" << stash;
QByteArray outputText;
QByteArray errorText;
const bool rc = vcsFullySynchronousExec(workingDirectory, arguments, &outputText, &errorText);
if (rc) {
const QString output = commandOutputFromLocal8Bit(outputText);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, arguments);
if (resp.result == SynchronousProcessResponse::Finished) {
const QString output = resp.stdOut();
if (!output.isEmpty())
VcsOutputWindow::append(output);
return true;
} else {
msgCannotRun(arguments, workingDirectory, errorText, errorMessage);
msgCannotRun(arguments, workingDirectory, resp.stdErr(), errorMessage);
return false;
}
return rc;
}
bool GitClient::synchronousStashList(const QString &workingDirectory, QList<Stash> *stashes,
QString *errorMessage) const
{
stashes->clear();
QByteArray outputText;
QByteArray errorText;
const QStringList arguments = { "stash", "list", noColorOption };
const bool rc = vcsFullySynchronousExec(workingDirectory, arguments, &outputText, &errorText);
if (!rc) {
msgCannotRun(arguments, workingDirectory, errorText, errorMessage);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, arguments);
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(arguments, workingDirectory, resp.stdErr(), errorMessage);
return false;
}
Stash stash;
foreach (const QString &line, commandOutputLinesFromLocal8Bit(outputText))
foreach (const QString &line, splitLines(resp.stdOut())) {
if (stash.parseStashLine(line))
stashes->push_back(stash);
}
return true;
}
@@ -3013,13 +2997,11 @@ QString GitClient::readOneLine(const QString &workingDirectory, const QStringLis
? QTextCodec::codecForName("UTF-8")
: QTextCodec::codecForLocale();
QByteArray outputText;
if (!vcsFullySynchronousExec(workingDirectory, arguments, &outputText, 0, silentFlags))
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory, arguments, silentFlags, vcsTimeoutS(), codec);
if (resp.result != SynchronousProcessResponse::Finished)
return QString();
if (HostOsInfo::isWindowsHost())
outputText.replace("\r\n", "\n");
return SynchronousProcess::normalizeNewlines(codec->toUnicode(outputText.trimmed()));
return resp.stdOut().trimmed();
}
bool GitClient::cloneRepository(const QString &directory,const QByteArray &url)
@@ -3032,27 +3014,25 @@ bool GitClient::cloneRepository(const QString &directory,const QByteArray &url)
if (!synchronousInit(workingDirectory.path()))
return false;
if (!vcsFullySynchronousExec(workingDirectory.path(),
{ "remote", "add", "origin", QString::fromUtf8(url) }, nullptr)) {
return false;
}
const SynchronousProcessResponse resp
= vcsSynchronousExec(workingDirectory.path(), { "fetch" }, flags);
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory.path(), { "remote", "add", "origin", QString::fromUtf8(url) });
if (resp.result != SynchronousProcessResponse::Finished)
return false;
if (!vcsFullySynchronousExec(workingDirectory.path(),
{ "config", "branch.master.remote", "origin" }, nullptr)) {
const SynchronousProcessResponse resp1 = vcsSynchronousExec(
workingDirectory.path(), { "fetch" }, flags);
if (resp1.result != SynchronousProcessResponse::Finished)
return false;
}
if (!vcsFullySynchronousExec(workingDirectory.path(),
{ "config", "branch.master.merge", "refs/heads/master" }, nullptr)) {
const SynchronousProcessResponse resp2 = vcsSynchronousExec(
workingDirectory.path(), { "config", "branch.master.remote", "origin" }, flags);
if (resp2.result != SynchronousProcessResponse::Finished)
return false;
}
return true;
const SynchronousProcessResponse resp3 = vcsSynchronousExec(
workingDirectory.path(),
{ "config", "branch.master.merge", "refs/heads/master" }, flags);
return resp3.result == SynchronousProcessResponse::Finished;
} else {
workingDirectory.cdUp();
const SynchronousProcessResponse resp = vcsSynchronousExec(
@@ -3083,19 +3063,16 @@ unsigned GitClient::synchronousGitVersion(QString *errorMessage) const
return 0;
// run git --version
QByteArray outputText;
QByteArray errorText;
const bool rc = vcsFullySynchronousExec(QString(), { "--version" },
&outputText, &errorText, silentFlags);
if (!rc) {
msgCannotRun(tr("Cannot determine Git version: %1")
.arg(commandOutputFromLocal8Bit(errorText)),
errorMessage);
const SynchronousProcessResponse resp = vcsSynchronousExec(
QString(), { "--version" }, silentFlags);
if (resp.result != SynchronousProcessResponse::Finished) {
msgCannotRun(tr("Cannot determine Git version: %1").arg(resp.stdErr()), errorMessage);
return 0;
}
// cut 'git version 1.6.5.1.sha'
// another form: 'git version 1.9.rc1'
const QString output = commandOutputFromLocal8Bit(outputText);
const QString output = resp.stdOut();
QRegExp versionPattern("^[^\\d]+(\\d+)\\.(\\d+)\\.(\\d+|rc\\d).*$");
QTC_ASSERT(versionPattern.isValid(), return 0);
QTC_ASSERT(versionPattern.exactMatch(output), return 0);