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

@@ -110,8 +110,8 @@ bool BazaarClient::synchronousSetUserId()
args << QLatin1String("whoami")
<< (settings().stringValue(BazaarSettings::userNameKey) + QLatin1String(" <")
+ settings().stringValue(BazaarSettings::userEmailKey) + QLatin1Char('>'));
QByteArray stdOut;
return vcsFullySynchronousExec(QDir::currentPath(), args, &stdOut);
return vcsFullySynchronousExec(QDir::currentPath(), args).result
== SynchronousProcessResponse::Finished;
}
BranchInfo BazaarClient::synchronousBranchQuery(const QString &repositoryRoot) const
@@ -150,11 +150,10 @@ bool BazaarClient::synchronousUncommit(const QString &workingDir,
<< QLatin1String("--verbose") // Will print out what is being removed
<< revisionSpec(revision)
<< extraOptions;
QByteArray stdOut;
const bool success = vcsFullySynchronousExec(workingDir, args, &stdOut);
if (!stdOut.isEmpty())
VcsOutputWindow::append(QString::fromUtf8(stdOut));
return success;
const SynchronousProcessResponse result = vcsFullySynchronousExec(workingDir, args);
VcsOutputWindow::append(result.stdOut());
return result.result == SynchronousProcessResponse::Finished;
}
void BazaarClient::commit(const QString &repositoryRoot, const QStringList &files,
@@ -187,10 +186,11 @@ bool BazaarClient::managesFile(const QString &workingDirectory, const QString &f
{
QStringList args(QLatin1String("status"));
args << fileName;
QByteArray stdOut;
if (!vcsFullySynchronousExec(workingDirectory, args, &stdOut))
const SynchronousProcessResponse result = vcsFullySynchronousExec(workingDirectory, args);
if (result.result != SynchronousProcessResponse::Finished)
return false;
return !stdOut.startsWith("unknown");
return result.rawStdOut.startsWith("unknown");
}
void BazaarClient::view(const QString &source, const QString &id, const QStringList &extraOptions)

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,
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, args,
silentFlags);
*output = SynchronousProcess::normalizeNewlines(QString::fromUtf8(outputText));
if (!rc)
msgCannotRun(args, workingDirectory, errorText, errorMessage);
return rc;
*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);

View File

@@ -73,12 +73,12 @@ bool MercurialClient::manifestSync(const QString &repository, const QString &rel
// This only works when called from the repo and outputs paths relative to it.
const QStringList args(QLatin1String("manifest"));
QByteArray output;
vcsFullySynchronousExec(repository, args, &output);
const SynchronousProcessResponse result = vcsFullySynchronousExec(repository, args);
const QDir repositoryDir(repository);
const QFileInfo needle = QFileInfo(repositoryDir, relativeFilename);
const QStringList files = QString::fromLocal8Bit(output).split(QLatin1Char('\n'));
const QStringList files = result.stdOut().split(QLatin1Char('\n'));
foreach (const QString &fileName, files) {
const QFileInfo managedFile(repositoryDir, fileName);
if (needle == managedFile)
@@ -96,7 +96,6 @@ bool MercurialClient::synchronousClone(const QString &workingDir,
Q_UNUSED(workingDir);
Q_UNUSED(extraOptions);
QDir workingDirectory(srcLocation);
QByteArray output;
const unsigned flags = VcsCommand::SshPasswordPrompt |
VcsCommand::ShowStdOut |
VcsCommand::ShowSuccessMessage;
@@ -104,14 +103,16 @@ bool MercurialClient::synchronousClone(const QString &workingDir,
if (workingDirectory.exists()) {
// Let's make first init
QStringList arguments(QLatin1String("init"));
if (!vcsFullySynchronousExec(workingDirectory.path(), arguments, &output))
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
workingDirectory.path(), arguments);
if (resp.result != SynchronousProcessResponse::Finished)
return false;
// Then pull remote repository
arguments.clear();
arguments << QLatin1String("pull") << dstLocation;
const SynchronousProcessResponse resp1 =
vcsSynchronousExec(workingDirectory.path(), arguments, flags);
const SynchronousProcessResponse resp1 = vcsSynchronousExec(
workingDirectory.path(), arguments, flags);
if (resp1.result != SynchronousProcessResponse::Finished)
return false;
@@ -127,15 +128,15 @@ bool MercurialClient::synchronousClone(const QString &workingDir,
// And last update repository
arguments.clear();
arguments << QLatin1String("update");
const SynchronousProcessResponse resp2 =
vcsSynchronousExec(workingDirectory.path(), arguments, flags);
const SynchronousProcessResponse resp2 = vcsSynchronousExec(
workingDirectory.path(), arguments, flags);
return resp2.result == SynchronousProcessResponse::Finished;
} else {
QStringList arguments(QLatin1String("clone"));
arguments << dstLocation << workingDirectory.dirName();
workingDirectory.cdUp();
const SynchronousProcessResponse resp =
vcsSynchronousExec(workingDirectory.path(), arguments, flags);
const SynchronousProcessResponse resp = vcsSynchronousExec(
workingDirectory.path(), arguments, flags);
return resp.result == SynchronousProcessResponse::Finished;
}
}
@@ -194,24 +195,22 @@ QStringList MercurialClient::parentRevisionsSync(const QString &workingDirectory
args << QLatin1String("parents") << QLatin1String("-r") <<revision;
if (!file.isEmpty())
args << file;
QByteArray outputData;
if (!vcsFullySynchronousExec(workingDirectory, args, &outputData))
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, args);
if (resp.result != SynchronousProcessResponse::Finished)
return QStringList();
const QString output = SynchronousProcess::normalizeNewlines(
QString::fromLocal8Bit(outputData));
/* Looks like: \code
changeset: 0:031a48610fba
user: ...
\endcode */
// Obtain first line and split by blank-delimited tokens
const QStringList lines = output.split(QLatin1Char('\n'));
const QStringList lines = resp.stdOut().split(QLatin1Char('\n'));
if (lines.size() < 1) {
VcsOutputWindow::appendSilently(msgParentRevisionFailed(workingDirectory, revision, msgParseParentsOutputFailed(output)));
VcsOutputWindow::appendSilently(msgParentRevisionFailed(workingDirectory, revision, msgParseParentsOutputFailed(resp.stdOut())));
return QStringList();
}
QStringList changeSets = lines.front().simplified().split(QLatin1Char(' '));
if (changeSets.size() < 2) {
VcsOutputWindow::appendSilently(msgParentRevisionFailed(workingDirectory, revision, msgParseParentsOutputFailed(output)));
VcsOutputWindow::appendSilently(msgParentRevisionFailed(workingDirectory, revision, msgParseParentsOutputFailed(resp.stdOut())));
return QStringList();
}
// Remove revision numbers
@@ -231,18 +230,15 @@ QString MercurialClient::shortDescriptionSync(const QString &workingDirectory,
const QString &revision,
const QString &format)
{
QString description;
QStringList args;
args << QLatin1String("log") << QLatin1String("-r") <<revision;
if (!format.isEmpty())
args << QLatin1String("--template") << format;
QByteArray outputData;
if (!vcsFullySynchronousExec(workingDirectory, args, &outputData))
const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, args);
if (resp.result != SynchronousProcessResponse::Finished)
return revision;
description = commandOutputFromLocal8Bit(outputData);
if (description.endsWith(QLatin1Char('\n')))
description.truncate(description.size() - 1);
return description;
return stripLastNewline(resp.stdOut());
}
// Default format: "SHA1 (author summmary)"
@@ -258,9 +254,7 @@ bool MercurialClient::managesFile(const QString &workingDirectory, const QString
{
QStringList args;
args << QLatin1String("status") << QLatin1String("--unknown") << fileName;
QByteArray output;
vcsFullySynchronousExec(workingDirectory, args, &output);
return output.isEmpty();
return vcsFullySynchronousExec(workingDirectory, args).stdOut().isEmpty();
}
void MercurialClient::incoming(const QString &repositoryRoot, const QString &repository)

View File

@@ -138,14 +138,13 @@ QString SubversionClient::synchronousTopic(const QString &repository)
QStringList args;
args << QLatin1String("info");
QByteArray stdOut;
if (!vcsFullySynchronousExec(repository, args, &stdOut))
const SynchronousProcessResponse result = vcsFullySynchronousExec(repository, args);
if (result.result != SynchronousProcessResponse::Finished)
return QString();
const QString revisionString = QLatin1String("Revision: ");
// stdOut is ASCII only (at least in those areas we care about).
QString output = commandOutputFromLocal8Bit(stdOut);
foreach (const QString &line, output.split(QLatin1Char('\n'))) {
foreach (const QString &line, result.stdOut().split(QLatin1Char('\n'))) {
if (line.startsWith(revisionString))
return QString::fromLatin1("r") + line.mid(revisionString.count());
}

View File

@@ -877,21 +877,19 @@ SubversionResponse SubversionPlugin::runSvn(const QString &workingDir,
int timeOutS, unsigned flags,
QTextCodec *outputCodec) const
{
const FileName executable = client()->vcsBinary();
SubversionResponse response;
if (executable.isEmpty()) {
if (client()->vcsBinary().isEmpty()) {
response.error = true;
response.message =tr("No subversion executable specified.");
return response;
}
const SynchronousProcessResponse sp_resp =
VcsBasePlugin::runVcs(workingDir, executable, arguments, timeOutS,
flags, outputCodec);
const SynchronousProcessResponse sp_resp
= client()->vcsFullySynchronousExec(workingDir, arguments, flags, timeOutS, outputCodec);
response.error = sp_resp.result != SynchronousProcessResponse::Finished;
if (response.error)
response.message = sp_resp.exitMessage(executable.toString(), timeOutS);
response.message = sp_resp.exitMessage(client()->vcsBinary().toString(), timeOutS);
response.stdErr = sp_resp.stdErr();
response.stdOut = sp_resp.stdOut();
return response;

View File

@@ -155,8 +155,13 @@ QString VcsBaseClientImpl::commandOutputFromLocal8Bit(const QByteArray &a)
QStringList VcsBaseClientImpl::commandOutputLinesFromLocal8Bit(const QByteArray &a)
{
QString output = commandOutputFromLocal8Bit(a);
return splitLines(commandOutputFromLocal8Bit(a));
}
QStringList VcsBaseClientImpl::splitLines(const QString &s)
{
const QChar newLine = QLatin1Char('\n');
QString output = s;
if (output.endsWith(newLine))
output.truncate(output.size() - 1);
if (output.isEmpty())
@@ -164,6 +169,13 @@ QStringList VcsBaseClientImpl::commandOutputLinesFromLocal8Bit(const QByteArray
return output.split(newLine);
}
QString VcsBaseClientImpl::stripLastNewline(const QString &in)
{
if (in.endsWith('\n'))
return in.left(in.count() - 1);
return in;
}
void VcsBaseClientImpl::resetCachedVcsInfo(const QString &workingDir)
{
Core::VcsManager::resetVersionControlForDirectory(workingDir);
@@ -182,18 +194,15 @@ void VcsBaseClientImpl::annotateRevisionRequested(const QString &workingDirector
annotate(workingDirectory, file, changeCopy, line);
}
bool VcsBaseClientImpl::vcsFullySynchronousExec(const QString &workingDir, const QStringList &args,
QByteArray *outputData, QByteArray *errorData,
unsigned flags) const
Utils::SynchronousProcessResponse
VcsBaseClientImpl::vcsFullySynchronousExec(const QString &workingDir, const QStringList &args,
unsigned flags, int timeoutS, QTextCodec *codec) const
{
QByteArray internalErrorData;
QScopedPointer<VcsCommand> command(createCommand(workingDir));
command->addFlags(flags);
bool result = command->runFullySynchronous(vcsBinary(), args, vcsTimeoutS(), outputData,
errorData ? errorData : &internalErrorData);
if (!internalErrorData.isEmpty() && !(flags & VcsCommand::SuppressStdErr))
VcsOutputWindow::appendError(commandOutputFromLocal8Bit(internalErrorData));
return result;
VcsCommand command(workingDir, processEnvironment());
command.addFlags(flags);
if (codec)
command.setCodec(codec);
return command.runCommand(vcsBinary(), args, (timeoutS > 0) ? timeoutS : vcsTimeoutS());
}
VcsCommand *VcsBaseClientImpl::vcsExec(const QString &workingDirectory, const QStringList &arguments,
@@ -300,10 +309,10 @@ bool VcsBaseClient::synchronousCreateRepository(const QString &workingDirectory,
{
QStringList args(vcsCommandString(CreateRepositoryCommand));
args << extraOptions;
QByteArray outputData;
if (!vcsFullySynchronousExec(workingDirectory, args, &outputData))
Utils::SynchronousProcessResponse result = vcsFullySynchronousExec(workingDirectory, args);
if (result.result != Utils::SynchronousProcessResponse::Finished)
return false;
VcsOutputWindow::append(commandOutputFromLocal8Bit(outputData));
VcsOutputWindow::append(result.stdOut());
resetCachedVcsInfo(workingDirectory);
@@ -318,10 +327,10 @@ bool VcsBaseClient::synchronousClone(const QString &workingDir,
QStringList args;
args << vcsCommandString(CloneCommand)
<< extraOptions << srcLocation << dstLocation;
QByteArray stdOut;
const bool cloneOk = vcsFullySynchronousExec(workingDir, args, &stdOut);
Utils::SynchronousProcessResponse result = vcsFullySynchronousExec(workingDir, args);
resetCachedVcsInfo(workingDir);
return cloneOk;
return result.result == Utils::SynchronousProcessResponse::Finished;
}
bool VcsBaseClient::synchronousAdd(const QString &workingDir, const QString &filename,
@@ -329,8 +338,7 @@ bool VcsBaseClient::synchronousAdd(const QString &workingDir, const QString &fil
{
QStringList args;
args << vcsCommandString(AddCommand) << extraOptions << filename;
QByteArray stdOut;
return vcsFullySynchronousExec(workingDir, args, &stdOut);
return vcsFullySynchronousExec(workingDir, args).result == Utils::SynchronousProcessResponse::Finished;
}
bool VcsBaseClient::synchronousRemove(const QString &workingDir, const QString &filename,
@@ -338,8 +346,7 @@ bool VcsBaseClient::synchronousRemove(const QString &workingDir, const QString &
{
QStringList args;
args << vcsCommandString(RemoveCommand) << extraOptions << filename;
QByteArray stdOut;
return vcsFullySynchronousExec(workingDir, args, &stdOut);
return vcsFullySynchronousExec(workingDir, args).result == Utils::SynchronousProcessResponse::Finished;
}
bool VcsBaseClient::synchronousMove(const QString &workingDir,
@@ -348,8 +355,7 @@ bool VcsBaseClient::synchronousMove(const QString &workingDir,
{
QStringList args;
args << vcsCommandString(MoveCommand) << extraOptions << from << to;
QByteArray stdOut;
return vcsFullySynchronousExec(workingDir, args, &stdOut);
return vcsFullySynchronousExec(workingDir, args).result == Utils::SynchronousProcessResponse::Finished;
}
bool VcsBaseClient::synchronousPull(const QString &workingDir,

View File

@@ -95,28 +95,31 @@ public:
static QString commandOutputFromLocal8Bit(const QByteArray &a);
// Return converted command output split into lines
static QStringList commandOutputLinesFromLocal8Bit(const QByteArray &a);
static QStringList splitLines(const QString &s);
static QString stripLastNewline(const QString &in);
// Fully synchronous VCS execution (QProcess-based)
Utils::SynchronousProcessResponse
vcsFullySynchronousExec(const QString &workingDir, const QStringList &args,
unsigned flags = 0, int timeoutS = -1, QTextCodec *codec = nullptr) const;
// Simple helper to execute a single command using createCommand and enqueueJob.
VcsCommand *vcsExec(const QString &workingDirectory, const QStringList &arguments,
VcsBaseEditorWidget *editor = nullptr, bool useOutputToWindow = false,
unsigned additionalFlags = 0, const QVariant &cookie = QVariant()) const;
protected:
void resetCachedVcsInfo(const QString &workingDir);
virtual void annotateRevisionRequested(const QString &workingDirectory, const QString &file,
const QString &change, int line);
// Fully synchronous VCS execution (QProcess-based)
bool vcsFullySynchronousExec(const QString &workingDir, const QStringList &args,
QByteArray *outputData, QByteArray *errorData = 0,
unsigned flags = 0) const;
// Simple helper to execute a single command using createCommand and enqueueJob.
VcsCommand *vcsExec(const QString &workingDirectory, const QStringList &arguments,
VcsBaseEditorWidget *editor = 0, bool useOutputToWindow = false,
unsigned additionalFlags = 0, const QVariant &cookie = QVariant()) const;
// Synchronous VCS execution using Utils::SynchronousProcess, with
// log windows updating (using VcsBasePlugin::runVcs with flags)
Utils::SynchronousProcessResponse vcsSynchronousExec(const QString &workingDir,
const QStringList &args,
unsigned flags = 0,
QTextCodec *outputCodec = 0) const;
QTextCodec *outputCodec = nullptr) const;
private:
void saveSettings();