SVN: Escape files containing '@' characters

Append a '@' to files with a '@' in their name. The last '@' (and
everything following it) is cut off by SVN and treated as a revision.

Task-number: QTCREATORBUG-17229
Change-Id: Icab62345c18277c0327b1e548a45feda0906b3c3
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Tobias Hunger
2016-11-07 09:12:42 +01:00
parent 0dc87382e9
commit bc14dc223f
3 changed files with 28 additions and 16 deletions

View File

@@ -39,6 +39,7 @@
#include <diffeditor/diffutils.h> #include <diffeditor/diffutils.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <QDir> #include <QDir>
@@ -87,7 +88,7 @@ VcsCommand *SubversionClient::createCommitCmd(const QString &repositoryRoot,
VcsCommand *cmd = createCommand(repositoryRoot); VcsCommand *cmd = createCommand(repositoryRoot);
cmd->addFlags(VcsCommand::ShowStdOut); cmd->addFlags(VcsCommand::ShowStdOut);
QStringList args(vcsCommandString(CommitCommand)); QStringList args(vcsCommandString(CommitCommand));
cmd->addJob(vcsBinary(), args << svnExtraOptions << files); cmd->addJob(vcsBinary(), args << svnExtraOptions << escapeFiles(files));
return cmd; return cmd;
} }
@@ -154,6 +155,16 @@ QString SubversionClient::synchronousTopic(const QString &repository)
return result.stdOut().trimmed(); return result.stdOut().trimmed();
} }
QString SubversionClient::escapeFile(const QString &file)
{
return (file.contains('@') && !file.endsWith('@')) ? file + '@' : file;
}
QStringList SubversionClient::escapeFiles(const QStringList &files)
{
return Utils::transform(files, &SubversionClient::escapeFile);
}
class DiffController : public DiffEditorController class DiffController : public DiffEditorController
{ {
Q_OBJECT Q_OBJECT
@@ -198,7 +209,7 @@ void DiffController::setFilesList(const QStringList &filesList)
if (isReloading()) if (isReloading())
return; return;
m_filesList = filesList; m_filesList = SubversionClient::escapeFiles(filesList);
} }
void DiffController::setChangeNumber(int changeNumber) void DiffController::setChangeNumber(int changeNumber)
@@ -308,13 +319,9 @@ void SubversionClient::log(const QString &workingDir,
if (logCount > 0) if (logCount > 0)
svnExtraOptions << QLatin1String("-l") << QString::number(logCount); svnExtraOptions << QLatin1String("-l") << QString::number(logCount);
QStringList nativeFiles;
foreach (const QString& file, files)
nativeFiles.append(QDir::toNativeSeparators(file));
// 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, files, svnExtraOptions, enableAnnotationContextMenu); VcsBaseClient::log(workingDir, escapeFiles(files), svnExtraOptions, enableAnnotationContextMenu);
} }
void SubversionClient::describe(const QString &workingDirectory, int changeNumber, const QString &title) void SubversionClient::describe(const QString &workingDirectory, int changeNumber, const QString &title)

View File

@@ -71,6 +71,9 @@ public:
QString synchronousTopic(const QString &repository); QString synchronousTopic(const QString &repository);
static QString escapeFile(const QString &file);
static QStringList escapeFiles(const QStringList &files);
protected: protected:
Core::Id vcsEditorKind(VcsCommandTag cmd) const override; Core::Id vcsEditorKind(VcsCommandTag cmd) const override;

View File

@@ -559,7 +559,7 @@ void SubversionPlugin::revertCurrentFile()
QStringList args(QLatin1String("diff")); QStringList args(QLatin1String("diff"));
args << SubversionClient::addAuthenticationOptions(client()->settings()); args << SubversionClient::addAuthenticationOptions(client()->settings());
args.push_back(state.relativeCurrentFile()); args.push_back(SubversionClient::escapeFile(state.relativeCurrentFile()));
const SubversionResponse diffResponse const SubversionResponse diffResponse
= runSvn(state.currentFileTopLevel(), args, m_client->vcsTimeoutS(), 0); = runSvn(state.currentFileTopLevel(), args, m_client->vcsTimeoutS(), 0);
@@ -580,7 +580,7 @@ void SubversionPlugin::revertCurrentFile()
args.clear(); args.clear();
args << QLatin1String("revert"); args << QLatin1String("revert");
args << SubversionClient::addAuthenticationOptions(client()->settings()); args << SubversionClient::addAuthenticationOptions(client()->settings());
args << state.relativeCurrentFile(); args << SubversionClient::escapeFile(state.relativeCurrentFile());
const SubversionResponse revertResponse const SubversionResponse revertResponse
= runSvn(state.currentFileTopLevel(), args, m_client->vcsTimeoutS(), = runSvn(state.currentFileTopLevel(), args, m_client->vcsTimeoutS(),
@@ -643,7 +643,7 @@ void SubversionPlugin::startCommit(const QString &workingDir, const QStringList
QStringList args(QLatin1String("status")); QStringList args(QLatin1String("status"));
args << SubversionClient::addAuthenticationOptions(client()->settings()); args << SubversionClient::addAuthenticationOptions(client()->settings());
args += files; args += SubversionClient::escapeFiles(files);
const SubversionResponse response const SubversionResponse response
= runSvn(workingDir, args, m_client->vcsTimeoutS(), 0); = runSvn(workingDir, args, m_client->vcsTimeoutS(), 0);
@@ -724,7 +724,7 @@ void SubversionPlugin::svnStatus(const QString &workingDir, const QString &relat
QStringList args(QLatin1String("status")); QStringList args(QLatin1String("status"));
args << SubversionClient::addAuthenticationOptions(client()->settings()); args << SubversionClient::addAuthenticationOptions(client()->settings());
if (!relativePath.isEmpty()) if (!relativePath.isEmpty())
args.append(relativePath); args.append(SubversionClient::escapeFile(relativePath));
VcsOutputWindow::setRepository(workingDir); VcsOutputWindow::setRepository(workingDir);
runSvn(workingDir, args, m_client->vcsTimeoutS(), runSvn(workingDir, args, m_client->vcsTimeoutS(),
VcsCommand::ShowStdOut | VcsCommand::ShowSuccessMessage); VcsCommand::ShowStdOut | VcsCommand::ShowSuccessMessage);
@@ -789,7 +789,7 @@ void SubversionPlugin::vcsAnnotate(const QString &workingDir, const QString &fil
if (!revision.isEmpty()) if (!revision.isEmpty())
args << QLatin1String("-r") << revision; args << QLatin1String("-r") << revision;
args.push_back(QLatin1String("-v")); args.push_back(QLatin1String("-v"));
args.append(QDir::toNativeSeparators(file)); args.append(QDir::toNativeSeparators(SubversionClient::escapeFile(file)));
const SubversionResponse response const SubversionResponse response
= runSvn(workingDir, args, m_client->vcsTimeoutS(), = runSvn(workingDir, args, m_client->vcsTimeoutS(),
@@ -949,7 +949,7 @@ QString SubversionPlugin::synchronousTopic(const QString &repository) const
bool SubversionPlugin::vcsAdd(const QString &workingDir, const QString &rawFileName) bool SubversionPlugin::vcsAdd(const QString &workingDir, const QString &rawFileName)
{ {
const QString file = QDir::toNativeSeparators(rawFileName); const QString file = QDir::toNativeSeparators(SubversionClient::escapeFile(rawFileName));
QStringList args; QStringList args;
args << QLatin1String("add") args << QLatin1String("add")
<< SubversionClient::addAuthenticationOptions(client()->settings()) << SubversionClient::addAuthenticationOptions(client()->settings())
@@ -962,7 +962,7 @@ bool SubversionPlugin::vcsAdd(const QString &workingDir, const QString &rawFileN
bool SubversionPlugin::vcsDelete(const QString &workingDir, const QString &rawFileName) bool SubversionPlugin::vcsDelete(const QString &workingDir, const QString &rawFileName)
{ {
const QString file = QDir::toNativeSeparators(rawFileName); const QString file = QDir::toNativeSeparators(SubversionClient::escapeFile(rawFileName));
QStringList args; QStringList args;
args << QLatin1String("delete"); args << QLatin1String("delete");
@@ -979,7 +979,8 @@ bool SubversionPlugin::vcsMove(const QString &workingDir, const QString &from, c
{ {
QStringList args(QLatin1String("move")); QStringList args(QLatin1String("move"));
args << SubversionClient::addAuthenticationOptions(client()->settings()); args << SubversionClient::addAuthenticationOptions(client()->settings());
args << QDir::toNativeSeparators(from) << QDir::toNativeSeparators(to); args << QDir::toNativeSeparators(SubversionClient::escapeFile(from))
<< QDir::toNativeSeparators(SubversionClient::escapeFile(to));
const SubversionResponse response const SubversionResponse response
= runSvn(workingDir, args, m_client->vcsTimeoutS(), = runSvn(workingDir, args, m_client->vcsTimeoutS(),
VcsCommand::SshPasswordPrompt | VcsCommand::ShowStdOut VcsCommand::SshPasswordPrompt | VcsCommand::ShowStdOut
@@ -1042,7 +1043,8 @@ bool SubversionPlugin::managesFile(const QString &workingDirectory, const QStrin
{ {
QStringList args; QStringList args;
args << QLatin1String("status"); args << QLatin1String("status");
args << SubversionClient::addAuthenticationOptions(client()->settings()) << fileName; args << SubversionClient::addAuthenticationOptions(client()->settings())
<< QDir::toNativeSeparators(SubversionClient::escapeFile(fileName));
SubversionResponse response SubversionResponse response
= runSvn(workingDirectory, args, m_client->vcsTimeoutS(), 0); = runSvn(workingDirectory, args, m_client->vcsTimeoutS(), 0);
return response.stdOut.isEmpty() || response.stdOut.at(0) != QLatin1Char('?'); return response.stdOut.isEmpty() || response.stdOut.at(0) != QLatin1Char('?');