Subversion: Mask credentials in command line everywhere

Fixes: QTCREATORBUG-28413
Change-Id: I763c26944d89a8dcc7151e10b8eed5d9642fb982
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
Orgad Shaneh
2023-01-17 13:10:21 +02:00
committed by Orgad Shaneh
parent edd3c16382
commit 87e5ac7438
7 changed files with 150 additions and 95 deletions

View File

@@ -622,6 +622,18 @@ void ProcessArgs::addArgs(QString *args, const QStringList &inArgs)
addArg(args, arg); addArg(args, arg);
} }
CommandLine &CommandLine::operator<<(const QString &arg)
{
addArg(arg);
return *this;
}
CommandLine &CommandLine::operator<<(const QStringList &args)
{
addArgs(args);
return *this;
}
bool ProcessArgs::prepareCommand(const CommandLine &cmdLine, QString *outCmd, ProcessArgs *outArgs, bool ProcessArgs::prepareCommand(const CommandLine &cmdLine, QString *outCmd, ProcessArgs *outArgs,
const Environment *env, const FilePath *pwd) const Environment *env, const FilePath *pwd)
{ {
@@ -1432,7 +1444,7 @@ CommandLine CommandLine::fromUserInput(const QString &cmdline, MacroExpander *ex
void CommandLine::addArg(const QString &arg) void CommandLine::addArg(const QString &arg)
{ {
ProcessArgs::addArg(&m_arguments, arg, m_executable.osType()); addArg(arg, m_executable.osType());
} }
void CommandLine::addArg(const QString &arg, OsType osType) void CommandLine::addArg(const QString &arg, OsType osType)
@@ -1440,6 +1452,20 @@ void CommandLine::addArg(const QString &arg, OsType osType)
ProcessArgs::addArg(&m_arguments, arg, osType); ProcessArgs::addArg(&m_arguments, arg, osType);
} }
void CommandLine::addMaskedArg(const QString &arg)
{
addMaskedArg(arg, m_executable.osType());
}
void CommandLine::addMaskedArg(const QString &arg, OsType osType)
{
int start = m_arguments.size();
if (start > 0)
++start;
addArg(arg, osType);
m_masked.push_back({start, m_arguments.size() - start});
}
void CommandLine::addArgs(const QStringList &inArgs) void CommandLine::addArgs(const QStringList &inArgs)
{ {
for (const QString &arg : inArgs) for (const QString &arg : inArgs)
@@ -1509,8 +1535,12 @@ void CommandLine::prependArgs(const QString &inArgs, RawType)
QString CommandLine::toUserOutput() const QString CommandLine::toUserOutput() const
{ {
QString res = m_executable.toUserOutput(); QString res = m_executable.toUserOutput();
if (!m_arguments.isEmpty()) if (!m_arguments.isEmpty()) {
res += ' ' + m_arguments; QString args = m_arguments;
for (auto it = m_masked.crbegin(), end = m_masked.crend(); it != end; ++it)
args.replace(it->first, it->second, "*******");
res += ' ' + args;
}
return res; return res;
} }

View File

@@ -8,6 +8,8 @@
#include "filepath.h" #include "filepath.h"
#include "hostosinfo.h" #include "hostosinfo.h"
#include <QList>
#include <QPair>
#include <QStringList> #include <QStringList>
namespace Utils { namespace Utils {
@@ -126,9 +128,13 @@ public:
void addArg(const QString &arg); void addArg(const QString &arg);
void addArg(const QString &arg, OsType osType); void addArg(const QString &arg, OsType osType);
void addMaskedArg(const QString &arg);
void addMaskedArg(const QString &arg, OsType osType);
void addArgs(const QStringList &inArgs); void addArgs(const QStringList &inArgs);
void addArgs(const QStringList &inArgs, OsType osType); void addArgs(const QStringList &inArgs, OsType osType);
void addArgs(const QString &inArgs, RawType); void addArgs(const QString &inArgs, RawType);
CommandLine &operator<<(const QString &arg);
CommandLine &operator<<(const QStringList &arg);
void prependArgs(const QStringList &inArgs); void prependArgs(const QStringList &inArgs);
void prependArgs(const QString &inArgs, RawType); void prependArgs(const QString &inArgs, RawType);
@@ -158,6 +164,7 @@ private:
FilePath m_executable; FilePath m_executable;
QString m_arguments; QString m_arguments;
QList<QPair<int, int>> m_masked;
}; };
} // Utils } // Utils

View File

@@ -34,6 +34,8 @@ using namespace VcsBase;
namespace Subversion { namespace Subversion {
namespace Internal { namespace Internal {
static SubversionSettings *s_settings = nullptr;
class SubversionLogConfig : public VcsBaseEditorConfig class SubversionLogConfig : public VcsBaseEditorConfig
{ {
Q_OBJECT Q_OBJECT
@@ -49,6 +51,7 @@ public:
SubversionClient::SubversionClient(SubversionSettings *settings) : VcsBaseClient(settings) SubversionClient::SubversionClient(SubversionSettings *settings) : VcsBaseClient(settings)
{ {
s_settings = settings;
setLogConfigCreator([settings](QToolBar *toolBar) { setLogConfigCreator([settings](QToolBar *toolBar) {
return new SubversionLogConfig(*settings, toolBar); return new SubversionLogConfig(*settings, toolBar);
}); });
@@ -59,10 +62,10 @@ bool SubversionClient::doCommit(const FilePath &repositoryRoot,
const QString &commitMessageFile, const QString &commitMessageFile,
const QStringList &extraOptions) const const QStringList &extraOptions) const
{ {
QStringList args; CommandLine args{vcsBinary()};
args << vcsCommandString(CommitCommand) args << vcsCommandString(CommitCommand)
<< extraOptions << extraOptions
<< SubversionClient::addAuthenticationOptions(static_cast<SubversionSettings &>(settings())) << AddAuthOptions()
<< QLatin1String(Constants::NON_INTERACTIVE_OPTION) << QLatin1String(Constants::NON_INTERACTIVE_OPTION)
<< QLatin1String("--encoding") << QLatin1String("--encoding")
<< QLatin1String("UTF-8") << QLatin1String("UTF-8")
@@ -96,25 +99,23 @@ Id SubversionClient::vcsEditorKind(VcsCommandTag cmd) const
} }
// Add authorization options to the command line arguments. // Add authorization options to the command line arguments.
QStringList SubversionClient::addAuthenticationOptions(const SubversionSettings &settings) CommandLine &operator<<(Utils::CommandLine &command, const SubversionClient::AddAuthOptions &addAuth)
{ {
if (!settings.hasAuthentication()) if (!s_settings->hasAuthentication())
return QStringList(); return command;
const QString userName = settings.userName.value(); const QString userName = s_settings->userName.value();
const QString password = settings.password.value(); const QString password = s_settings->password.value();
if (userName.isEmpty()) if (userName.isEmpty())
return QStringList(); return command;
QStringList rc; command << "--username" << userName;
rc.push_back(QLatin1String("--username"));
rc.push_back(userName);
if (!password.isEmpty()) { if (!password.isEmpty()) {
rc.push_back(QLatin1String("--password")); command << "--password";
rc.push_back(password); command.addMaskedArg(password);
} }
return rc; return command;
} }
QString SubversionClient::synchronousTopic(const FilePath &repository) const QString SubversionClient::synchronousTopic(const FilePath &repository) const
@@ -149,7 +150,7 @@ class SubversionDiffEditorController : public VcsBaseDiffEditorController
{ {
Q_OBJECT Q_OBJECT
public: public:
SubversionDiffEditorController(IDocument *document, const QStringList &authOptions); SubversionDiffEditorController(IDocument *document);
void setFilesList(const QStringList &filesList); void setFilesList(const QStringList &filesList);
void setChangeNumber(int changeNumber); void setChangeNumber(int changeNumber);
@@ -159,8 +160,7 @@ private:
int m_changeNumber = 0; int m_changeNumber = 0;
}; };
SubversionDiffEditorController::SubversionDiffEditorController(IDocument *document, SubversionDiffEditorController::SubversionDiffEditorController(IDocument *document)
const QStringList &authOptions)
: VcsBaseDiffEditorController(document) : VcsBaseDiffEditorController(document)
{ {
setDisplayName("Svn Diff"); setDisplayName("Svn Diff");
@@ -176,10 +176,11 @@ SubversionDiffEditorController::SubversionDiffEditorController(IDocument *docume
return GroupConfig(); return GroupConfig();
}; };
const auto setupDescription = [this, authOptions](QtcProcess &process) { const auto setupDescription = [this](QtcProcess &process) {
const QStringList args = QStringList{"log"} << authOptions << "-r" setupCommand(process, {"log", "-r", QString::number(m_changeNumber)});
<< QString::number(m_changeNumber); CommandLine command = process.commandLine();
setupCommand(process, args); command << SubversionClient::AddAuthOptions();
process.setCommand(command);
setDescription(tr("Waiting for data...")); setDescription(tr("Waiting for data..."));
}; };
const auto onDescriptionDone = [this](const QtcProcess &process) { const auto onDescriptionDone = [this](const QtcProcess &process) {
@@ -189,8 +190,8 @@ SubversionDiffEditorController::SubversionDiffEditorController(IDocument *docume
setDescription({}); setDescription({});
}; };
const auto setupDiff = [this, authOptions](QtcProcess &process) { const auto setupDiff = [this](QtcProcess &process) {
QStringList args = QStringList{"diff"} << authOptions << "--internal-diff"; QStringList args = QStringList{"diff"} << "--internal-diff";
if (ignoreWhitespace()) if (ignoreWhitespace())
args << "-x" << "-uw"; args << "-x" << "-uw";
if (m_changeNumber) if (m_changeNumber)
@@ -199,6 +200,9 @@ SubversionDiffEditorController::SubversionDiffEditorController(IDocument *docume
args << m_filesList; args << m_filesList;
setupCommand(process, args); setupCommand(process, args);
CommandLine command = process.commandLine();
command << SubversionClient::AddAuthOptions();
process.setCommand(command);
}; };
const auto onDiffDone = [diffInputStorage](const QtcProcess &process) { const auto onDiffDone = [diffInputStorage](const QtcProcess &process) {
*diffInputStorage.activeStorage() = process.cleanedStdOut(); *diffInputStorage.activeStorage() = process.cleanedStdOut();
@@ -244,7 +248,7 @@ SubversionDiffEditorController *SubversionClient::findOrCreateDiffEditor(const Q
auto controller = qobject_cast<SubversionDiffEditorController *>( auto controller = qobject_cast<SubversionDiffEditorController *>(
DiffEditorController::controller(document)); DiffEditorController::controller(document));
if (!controller) { if (!controller) {
controller = new SubversionDiffEditorController(document, addAuthenticationOptions(settings)); controller = new SubversionDiffEditorController(document);
controller->setVcsBinary(settings.binaryPath.filePath()); controller->setVcsBinary(settings.binaryPath.filePath());
controller->setProcessEnvironment(processEnvironment()); controller->setProcessEnvironment(processEnvironment());
controller->setWorkingDirectory(workingDirectory); controller->setWorkingDirectory(workingDirectory);
@@ -270,19 +274,25 @@ void SubversionClient::diff(const FilePath &workingDirectory, const QStringList
controller->requestReload(); controller->requestReload();
} }
void SubversionClient::log(const FilePath &workingDir, const QStringList &files, void SubversionClient::log(const FilePath &workingDir,
const QStringList &extraOptions, bool enableAnnotationContextMenu) const QStringList &files,
const QStringList &extraOptions,
bool enableAnnotationContextMenu,
const std::function<void(Utils::CommandLine &)> &addAuthOptions)
{ {
auto &settings = static_cast<SubversionSettings &>(this->settings()); auto &settings = static_cast<SubversionSettings &>(this->settings());
const int logCount = settings.logCount.value(); const int logCount = settings.logCount.value();
QStringList svnExtraOptions = extraOptions; QStringList svnExtraOptions = extraOptions;
svnExtraOptions.append(SubversionClient::addAuthenticationOptions(settings));
if (logCount > 0) if (logCount > 0)
svnExtraOptions << QLatin1String("-l") << QString::number(logCount); svnExtraOptions << QLatin1String("-l") << QString::number(logCount);
// subversion stores log in UTF-8 and returns it back in user system locale. // subversion stores log in UTF-8 and returns it back in user system locale.
// So we do not need to encode it. // So we do not need to encode it.
VcsBaseClient::log(workingDir, escapeFiles(files), svnExtraOptions, enableAnnotationContextMenu); VcsBaseClient::log(workingDir,
escapeFiles(files),
svnExtraOptions,
enableAnnotationContextMenu,
addAuthOptions);
} }
void SubversionClient::describe(const FilePath &workingDirectory, int changeNumber, void SubversionClient::describe(const FilePath &workingDirectory, int changeNumber,

View File

@@ -36,12 +36,13 @@ public:
void log(const Utils::FilePath &workingDir, void log(const Utils::FilePath &workingDir,
const QStringList &files = {}, const QStringList &files = {},
const QStringList &extraOptions = {}, const QStringList &extraOptions = {},
bool enableAnnotationContextMenu = false) override; bool enableAnnotationContextMenu = false,
const std::function<void(Utils::CommandLine &)> &addAuthOptions = {}) override;
void describe(const Utils::FilePath &workingDirectory, int changeNumber, const QString &title); void describe(const Utils::FilePath &workingDirectory, int changeNumber, const QString &title);
// Add authorization options to the command line arguments. // Add authentication options to the command line arguments.
static QStringList addAuthenticationOptions(const SubversionSettings &settings); struct AddAuthOptions {};
QString synchronousTopic(const Utils::FilePath &repository) const; QString synchronousTopic(const Utils::FilePath &repository) const;
@@ -59,5 +60,8 @@ private:
mutable QString m_svnVersion; mutable QString m_svnVersion;
}; };
Utils::CommandLine &operator<<(Utils::CommandLine &command,
const SubversionClient::AddAuthOptions &addAuth);
} // namespace Internal } // namespace Internal
} // namespace Subversion } // namespace Subversion

View File

@@ -214,7 +214,7 @@ public:
QString monitorFile(const FilePath &repository) const; QString monitorFile(const FilePath &repository) const;
QString synchronousTopic(const FilePath &repository) const; QString synchronousTopic(const FilePath &repository) const;
CommandResult runSvn(const FilePath &workingDir, const QStringList &arguments, CommandResult runSvn(const FilePath &workingDir, const CommandLine &command,
RunFlags flags = RunFlags::None, QTextCodec *outputCodec = nullptr, RunFlags flags = RunFlags::None, QTextCodec *outputCodec = nullptr,
int timeoutMutiplier = 1) const; int timeoutMutiplier = 1) const;
void vcsAnnotateHelper(const FilePath &workingDir, const QString &file, void vcsAnnotateHelper(const FilePath &workingDir, const QString &file,
@@ -643,9 +643,8 @@ void SubversionPluginPrivate::revertAll()
QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
return; return;
// NoteL: Svn "revert ." doesn not work. // NoteL: Svn "revert ." doesn not work.
QStringList args; CommandLine args{m_settings.binaryPath.filePath(), {"revert"}};
args << QLatin1String("revert"); args << SubversionClient::AddAuthOptions();
args << SubversionClient::addAuthenticationOptions(m_settings);
args << QLatin1String("--recursive") << state.topLevel().toString(); args << QLatin1String("--recursive") << state.topLevel().toString();
const auto revertResponse = runSvn(state.topLevel(), args, RunFlags::ShowStdOut); const auto revertResponse = runSvn(state.topLevel(), args, RunFlags::ShowStdOut);
if (revertResponse.result() != ProcessResult::FinishedWithSuccess) { if (revertResponse.result() != ProcessResult::FinishedWithSuccess) {
@@ -661,11 +660,11 @@ void SubversionPluginPrivate::revertCurrentFile()
const VcsBasePluginState state = currentState(); const VcsBasePluginState state = currentState();
QTC_ASSERT(state.hasFile(), return); QTC_ASSERT(state.hasFile(), return);
QStringList args(QLatin1String("diff")); CommandLine diffArgs{m_settings.binaryPath.filePath(), {"diff"}};
args << SubversionClient::addAuthenticationOptions(m_settings); diffArgs << SubversionClient::AddAuthOptions();
args.push_back(SubversionClient::escapeFile(state.relativeCurrentFile())); diffArgs << SubversionClient::escapeFile(state.relativeCurrentFile());
const auto diffResponse = runSvn(state.currentFileTopLevel(), args); const auto diffResponse = runSvn(state.currentFileTopLevel(), diffArgs);
if (diffResponse.result() != ProcessResult::FinishedWithSuccess) if (diffResponse.result() != ProcessResult::FinishedWithSuccess)
return; return;
if (diffResponse.cleanedStdOut().isEmpty()) if (diffResponse.cleanedStdOut().isEmpty())
@@ -679,9 +678,8 @@ void SubversionPluginPrivate::revertCurrentFile()
FileChangeBlocker fcb(FilePath::fromString(state.currentFile())); FileChangeBlocker fcb(FilePath::fromString(state.currentFile()));
// revert // revert
args.clear(); CommandLine args{m_settings.binaryPath.filePath(), {"revert"}};
args << QLatin1String("revert"); args << SubversionClient::AddAuthOptions();
args << SubversionClient::addAuthenticationOptions(m_settings);
args << SubversionClient::escapeFile(state.relativeCurrentFile()); args << SubversionClient::escapeFile(state.relativeCurrentFile());
const auto revertResponse = runSvn(state.currentFileTopLevel(), args, RunFlags::ShowStdOut); const auto revertResponse = runSvn(state.currentFileTopLevel(), args, RunFlags::ShowStdOut);
@@ -741,9 +739,9 @@ void SubversionPluginPrivate::startCommit(const FilePath &workingDir, const QStr
return; return;
} }
QStringList args(QLatin1String("status")); CommandLine args{m_settings.binaryPath.filePath(), {"status"}};
args << SubversionClient::addAuthenticationOptions(m_settings); args << SubversionClient::AddAuthOptions();
args += SubversionClient::escapeFiles(files); args << SubversionClient::escapeFiles(files);
const auto response = runSvn(workingDir, args); const auto response = runSvn(workingDir, args);
if (response.result() != ProcessResult::FinishedWithSuccess) if (response.result() != ProcessResult::FinishedWithSuccess)
@@ -820,10 +818,10 @@ void SubversionPluginPrivate::svnStatus(const FilePath &workingDir, const QStrin
{ {
const VcsBasePluginState state = currentState(); const VcsBasePluginState state = currentState();
QTC_ASSERT(state.hasTopLevel(), return); QTC_ASSERT(state.hasTopLevel(), return);
QStringList args(QLatin1String("status")); CommandLine args{m_settings.binaryPath.filePath(), {"status"}};
args << SubversionClient::addAuthenticationOptions(m_settings); args << SubversionClient::AddAuthOptions();
if (!relativePath.isEmpty()) if (!relativePath.isEmpty())
args.append(SubversionClient::escapeFile(relativePath)); args << SubversionClient::escapeFile(relativePath);
VcsOutputWindow::setRepository(workingDir); VcsOutputWindow::setRepository(workingDir);
runSvn(workingDir, args, RunFlags::ShowStdOut | RunFlags::ShowSuccessMessage); runSvn(workingDir, args, RunFlags::ShowStdOut | RunFlags::ShowSuccessMessage);
VcsOutputWindow::clearRepository(); VcsOutputWindow::clearRepository();
@@ -833,7 +831,8 @@ void SubversionPluginPrivate::filelog(const FilePath &workingDir,
const QString &file, const QString &file,
bool enableAnnotationContextMenu) bool enableAnnotationContextMenu)
{ {
m_client->log(workingDir, QStringList(file), QStringList(), enableAnnotationContextMenu); m_client->log(workingDir, QStringList(file), QStringList(), enableAnnotationContextMenu,
[](CommandLine &command) { command << SubversionClient::AddAuthOptions(); });
} }
void SubversionPluginPrivate::updateProject() void SubversionPluginPrivate::updateProject()
@@ -845,11 +844,11 @@ void SubversionPluginPrivate::updateProject()
void SubversionPluginPrivate::svnUpdate(const FilePath &workingDir, const QString &relativePath) void SubversionPluginPrivate::svnUpdate(const FilePath &workingDir, const QString &relativePath)
{ {
QStringList args(QLatin1String("update")); CommandLine args{m_settings.binaryPath.filePath(), {"update"}};
args << SubversionClient::addAuthenticationOptions(m_settings); args << SubversionClient::AddAuthOptions();
args.push_back(QLatin1String(Constants::NON_INTERACTIVE_OPTION)); args << Constants::NON_INTERACTIVE_OPTION;
if (!relativePath.isEmpty()) if (!relativePath.isEmpty())
args.append(relativePath); args << relativePath;
const auto response = runSvn(workingDir, args, RunFlags::ShowStdOut, nullptr, 10); const auto response = runSvn(workingDir, args, RunFlags::ShowStdOut, nullptr, 10);
if (response.result() == ProcessResult::FinishedWithSuccess) if (response.result() == ProcessResult::FinishedWithSuccess)
emit repositoryChanged(workingDir); emit repositoryChanged(workingDir);
@@ -869,14 +868,13 @@ void SubversionPluginPrivate::vcsAnnotateHelper(const FilePath &workingDir, cons
const QString source = VcsBaseEditor::getSource(workingDir, file); const QString source = VcsBaseEditor::getSource(workingDir, file);
QTextCodec *codec = VcsBaseEditor::getCodec(source); QTextCodec *codec = VcsBaseEditor::getCodec(source);
QStringList args(QLatin1String("annotate")); CommandLine args{m_settings.binaryPath.filePath(), {"annotate"}};
args << SubversionClient::addAuthenticationOptions(m_settings); args << SubversionClient::AddAuthOptions();
if (m_settings.spaceIgnorantAnnotation.value()) if (m_settings.spaceIgnorantAnnotation.value())
args << QLatin1String("-x") << QLatin1String("-uw"); args << "-x" << "-uw";
if (!revision.isEmpty()) if (!revision.isEmpty())
args << QLatin1String("-r") << revision; args << "-r" << revision;
args.push_back(QLatin1String("-v")); args << "-v" << QDir::toNativeSeparators(SubversionClient::escapeFile(file));
args.append(QDir::toNativeSeparators(SubversionClient::escapeFile(file)));
const auto response = runSvn(workingDir, args, RunFlags::ForceCLocale, codec); const auto response = runSvn(workingDir, args, RunFlags::ForceCLocale, codec);
if (response.result() != ProcessResult::FinishedWithSuccess) if (response.result() != ProcessResult::FinishedWithSuccess)
@@ -951,14 +949,14 @@ void SubversionPluginPrivate::slotDescribe()
} }
CommandResult SubversionPluginPrivate::runSvn(const FilePath &workingDir, CommandResult SubversionPluginPrivate::runSvn(const FilePath &workingDir,
const QStringList &arguments, RunFlags flags, const CommandLine &command, RunFlags flags,
QTextCodec *outputCodec, int timeoutMutiplier) const QTextCodec *outputCodec, int timeoutMutiplier) const
{ {
if (m_settings.binaryPath.value().isEmpty()) if (m_settings.binaryPath.value().isEmpty())
return CommandResult(ProcessResult::StartFailed, tr("No subversion executable specified.")); return CommandResult(ProcessResult::StartFailed, tr("No subversion executable specified."));
const int timeoutS = m_settings.timeout.value() * timeoutMutiplier; const int timeoutS = m_settings.timeout.value() * timeoutMutiplier;
return m_client->vcsSynchronousExec(workingDir, arguments, flags, timeoutS, outputCodec); return m_client->vcsSynchronousExec(workingDir, command, flags, timeoutS, outputCodec);
} }
IEditor *SubversionPluginPrivate::showOutputInEditor(const QString &title, const QString &output, IEditor *SubversionPluginPrivate::showOutputInEditor(const QString &title, const QString &output,
@@ -1013,10 +1011,8 @@ QString SubversionPluginPrivate::synchronousTopic(const FilePath &repository) co
bool SubversionPluginPrivate::vcsAdd(const FilePath &workingDir, const QString &rawFileName) bool SubversionPluginPrivate::vcsAdd(const FilePath &workingDir, const QString &rawFileName)
{ {
const QString file = QDir::toNativeSeparators(SubversionClient::escapeFile(rawFileName)); const QString file = QDir::toNativeSeparators(SubversionClient::escapeFile(rawFileName));
QStringList args; CommandLine args{m_settings.binaryPath.filePath()};
args << QLatin1String("add") args << "add" << SubversionClient::AddAuthOptions() << "--parents" << file;
<< SubversionClient::addAuthenticationOptions(m_settings)
<< QLatin1String("--parents") << file;
return runSvn(workingDir, args, RunFlags::ShowStdOut).result() return runSvn(workingDir, args, RunFlags::ShowStdOut).result()
== ProcessResult::FinishedWithSuccess; == ProcessResult::FinishedWithSuccess;
} }
@@ -1025,10 +1021,8 @@ bool SubversionPluginPrivate::vcsDelete(const FilePath &workingDir, const QStrin
{ {
const QString file = QDir::toNativeSeparators(SubversionClient::escapeFile(rawFileName)); const QString file = QDir::toNativeSeparators(SubversionClient::escapeFile(rawFileName));
QStringList args; CommandLine args{m_settings.binaryPath.filePath()};
args << QLatin1String("delete"); args << "delete" << SubversionClient::AddAuthOptions() << "--force" << file;
args << SubversionClient::addAuthenticationOptions(m_settings)
<< QLatin1String("--force") << file;
return runSvn(workingDir, args, RunFlags::ShowStdOut).result() return runSvn(workingDir, args, RunFlags::ShowStdOut).result()
== ProcessResult::FinishedWithSuccess; == ProcessResult::FinishedWithSuccess;
@@ -1036,9 +1030,9 @@ bool SubversionPluginPrivate::vcsDelete(const FilePath &workingDir, const QStrin
bool SubversionPluginPrivate::vcsMove(const FilePath &workingDir, const QString &from, const QString &to) bool SubversionPluginPrivate::vcsMove(const FilePath &workingDir, const QString &from, const QString &to)
{ {
QStringList args(QLatin1String("move")); CommandLine args{m_settings.binaryPath.filePath(), {"move"}};
args << SubversionClient::addAuthenticationOptions(m_settings); args << SubversionClient::AddAuthOptions()
args << QDir::toNativeSeparators(SubversionClient::escapeFile(from)) << QDir::toNativeSeparators(SubversionClient::escapeFile(from))
<< QDir::toNativeSeparators(SubversionClient::escapeFile(to)); << QDir::toNativeSeparators(SubversionClient::escapeFile(to));
return runSvn(workingDir, args, RunFlags::ShowStdOut).result() return runSvn(workingDir, args, RunFlags::ShowStdOut).result()
== ProcessResult::FinishedWithSuccess; == ProcessResult::FinishedWithSuccess;
@@ -1049,8 +1043,8 @@ bool SubversionPluginPrivate::vcsCheckout(const FilePath &directory, const QByte
QUrl tempUrl = QUrl::fromEncoded(url); QUrl tempUrl = QUrl::fromEncoded(url);
const QString username = tempUrl.userName(); const QString username = tempUrl.userName();
const QString password = tempUrl.password(); const QString password = tempUrl.password();
QStringList args = QStringList(QLatin1String("checkout")); CommandLine args{m_settings.binaryPath.filePath(), {"checkout"}};
args << QLatin1String(Constants::NON_INTERACTIVE_OPTION) ; args << Constants::NON_INTERACTIVE_OPTION;
if (!username.isEmpty()) { if (!username.isEmpty()) {
// If url contains username and password we have to use separate username and password // If url contains username and password we have to use separate username and password
@@ -1059,12 +1053,13 @@ bool SubversionPluginPrivate::vcsCheckout(const FilePath &directory, const QByte
// if for example we are logging into a new host for the first time using svn. There seems to // if for example we are logging into a new host for the first time using svn. There seems to
// be a bug in subversion, so this might get fixed in the future. // be a bug in subversion, so this might get fixed in the future.
tempUrl.setUserInfo({}); tempUrl.setUserInfo({});
args << QLatin1String("--username") << username; args << "--username" << username;
if (!password.isEmpty()) if (!password.isEmpty())
args << QLatin1String("--password") << password; args << "--password";
args.addMaskedArg(password);
} }
args << QLatin1String(tempUrl.toEncoded()) << directory.toString(); args << QString::fromLatin1(tempUrl.toEncoded()) << directory.toString();
return runSvn(directory, args, RunFlags::None, nullptr, 10).result() return runSvn(directory, args, RunFlags::None, nullptr, 10).result()
== ProcessResult::FinishedWithSuccess; == ProcessResult::FinishedWithSuccess;
@@ -1095,9 +1090,8 @@ bool SubversionPluginPrivate::managesDirectory(const FilePath &directory, FilePa
bool SubversionPluginPrivate::managesFile(const FilePath &workingDirectory, const QString &fileName) const bool SubversionPluginPrivate::managesFile(const FilePath &workingDirectory, const QString &fileName) const
{ {
QStringList args; CommandLine args{m_settings.binaryPath.filePath()};
args << QLatin1String("status"); args << "status" << SubversionClient::AddAuthOptions()
args << SubversionClient::addAuthenticationOptions(m_settings)
<< QDir::toNativeSeparators(SubversionClient::escapeFile(fileName)); << QDir::toNativeSeparators(SubversionClient::escapeFile(fileName));
const QString output = runSvn(workingDirectory, args).cleanedStdOut(); const QString output = runSvn(workingDirectory, args).cleanedStdOut();
return output.isEmpty() || output.front() != QLatin1Char('?'); return output.isEmpty() || output.front() != QLatin1Char('?');
@@ -1198,14 +1192,13 @@ VcsCommand *SubversionPluginPrivate::createInitialCheckoutCommand(const QString
const QString &localName, const QString &localName,
const QStringList &extraArgs) const QStringList &extraArgs)
{ {
QStringList args; CommandLine args{m_settings.binaryPath.filePath()};
args << QLatin1String("checkout"); args << "checkout";
args << SubversionClient::addAuthenticationOptions(m_settings); args << SubversionClient::AddAuthOptions();
args << QLatin1String(Subversion::Constants::NON_INTERACTIVE_OPTION); args << Subversion::Constants::NON_INTERACTIVE_OPTION << extraArgs << url << localName;
args << extraArgs << url << localName;
auto command = VcsBaseClient::createVcsCommand(baseDirectory, m_client->processEnvironment()); auto command = VcsBaseClient::createVcsCommand(baseDirectory, m_client->processEnvironment());
command->addJob({m_settings.binaryPath.filePath(), args}, -1); command->addJob(args, -1);
return command; return command;
} }

View File

@@ -390,7 +390,8 @@ void VcsBaseClient::diff(const FilePath &workingDir, const QStringList &files,
void VcsBaseClient::log(const FilePath &workingDir, void VcsBaseClient::log(const FilePath &workingDir,
const QStringList &files, const QStringList &files,
const QStringList &extraOptions, const QStringList &extraOptions,
bool enableAnnotationContextMenu) bool enableAnnotationContextMenu,
const std::function<void(Utils::CommandLine &)> &addAuthOptions)
{ {
const QString vcsCmdString = vcsCommandString(LogCommand); const QString vcsCmdString = vcsCommandString(LogCommand);
const Id kind = vcsEditorKind(LogCommand); const Id kind = vcsEditorKind(LogCommand);
@@ -409,19 +410,28 @@ void VcsBaseClient::log(const FilePath &workingDir,
if (paramWidget) { if (paramWidget) {
paramWidget->setBaseArguments(extraOptions); paramWidget->setBaseArguments(extraOptions);
// editor has been just created, createVcsEditor() didn't set a configuration widget yet // editor has been just created, createVcsEditor() didn't set a configuration widget yet
connect(paramWidget, &VcsBaseEditorConfig::commandExecutionRequested, this, connect(paramWidget, &VcsBaseEditorConfig::commandExecutionRequested, this, [=] {
[=] { this->log(workingDir, files, extraOptions, enableAnnotationContextMenu); }); this->log(workingDir,
files,
extraOptions,
enableAnnotationContextMenu,
addAuthOptions);
});
editor->setEditorConfig(paramWidget); editor->setEditorConfig(paramWidget);
} }
} }
QStringList args = {vcsCmdString}; CommandLine args{vcsBinary(), {vcsCmdString}};
if (addAuthOptions)
addAuthOptions(args);
if (paramWidget) if (paramWidget)
args << paramWidget->arguments(); args << paramWidget->arguments();
else else
args << extraOptions; args << extraOptions;
args << files; args << files;
enqueueJob(createCommand(workingDir, editor), args); VcsCommand *cmd = createCommand(workingDir, editor);
cmd->addJob(args, vcsTimeoutS());
cmd->start();
} }
void VcsBaseClient::revertFile(const FilePath &workingDir, void VcsBaseClient::revertFile(const FilePath &workingDir,

View File

@@ -147,7 +147,8 @@ public:
virtual void log(const Utils::FilePath &workingDir, virtual void log(const Utils::FilePath &workingDir,
const QStringList &files = {}, const QStringList &files = {},
const QStringList &extraOptions = {}, const QStringList &extraOptions = {},
bool enableAnnotationContextMenu = false); bool enableAnnotationContextMenu = false,
const std::function<void(Utils::CommandLine &)> &addAuthOptions = {});
virtual void status(const Utils::FilePath &workingDir, virtual void status(const Utils::FilePath &workingDir,
const QString &file = {}, const QString &file = {},
const QStringList &extraOptions = {}); const QStringList &extraOptions = {});