diff options
author | Tobias Hunger <tobias.hunger@theqtcompany.com> | 2015-04-23 17:48:32 +0200 |
---|---|---|
committer | Tobias Hunger <tobias.hunger@theqtcompany.com> | 2015-04-27 07:26:18 +0000 |
commit | ad9dc94eaefae9ab91e3a29f76a13d6e037547ca (patch) | |
tree | 1456396fe7e00ffb9cb789128e38d2b511f0fc18 /src/plugins/diffeditor/diffutils.cpp | |
parent | 3b0a75c9e05e8e4a9f48c6e6d6d28012612c2efa (diff) | |
download | qt-creator-ad9dc94eaefae9ab91e3a29f76a13d6e037547ca.tar.gz |
DiffEditor: Parse git diffs properly
Do not put filenames into a regular expression and then hope for
the best... any file with any character in its name that has a
special meaning for a regexp will break the parsing.
Task-number: QTCREATORBUG-14322
Change-Id: Ifab513d675168aff041f20d2b3f06a8d27919aa7
Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
Diffstat (limited to 'src/plugins/diffeditor/diffutils.cpp')
-rw-r--r-- | src/plugins/diffeditor/diffutils.cpp | 56 |
1 files changed, 27 insertions, 29 deletions
diff --git a/src/plugins/diffeditor/diffutils.cpp b/src/plugins/diffeditor/diffutils.cpp index 0e16becbdf..9bc5d3a75e 100644 --- a/src/plugins/diffeditor/diffutils.cpp +++ b/src/plugins/diffeditor/diffutils.cpp @@ -868,6 +868,11 @@ static QList<FileData> readDiffPatch(const QString &patch, return fileDataList; } +static bool fileNameEnd(const QChar &c) +{ + return c == QLatin1Char('\n') || c == QLatin1Char('\t'); +} + static FileData readGitHeaderAndChunks(const QString &headerAndChunks, const QString &fileName, bool *ok) @@ -909,34 +914,30 @@ static FileData readGitHeaderAndChunks(const QString &headerAndChunks, patch.remove(0, indexRegExp.matchedLength()); } - const QRegExp leftFileRegExp(QLatin1String("^-{3} ") // "--- " - + leftFileName // "a/fileName" or "/dev/null" - + QLatin1String("(?:\\t[^\\n]*)*\\n")); // optionally followed by: \t anything \t anything ...) - const QRegExp rightFileRegExp(QLatin1String("^\\+{3} ") // "+++ " - + rightFileName // "b/fileName" or "/dev/null" - + QLatin1String("(?:\\t[^\\n]*)*\\n")); // optionally followed by: \t anything \t anything ...) - const QRegExp binaryRegExp(QLatin1String("^Binary files ") - + leftFileName - + QLatin1String(" and ") - + rightFileName - + QLatin1String(" differ$")); + const QString binaryLine = QString::fromLatin1("Binary files ") + leftFileName + + QLatin1String(" and ") + rightFileName + QLatin1String(" differ"); + const QString leftStart = QString::fromLatin1("--- ") + leftFileName; + QChar leftFollow = patch.count() > leftStart.count() ? patch.at(leftStart.count()) : QLatin1Char('\n'); // empty or followed either by leftFileRegExp or by binaryRegExp if (patch.isEmpty() && (fileData.fileOperation == FileData::NewFile || fileData.fileOperation == FileData::DeleteFile)) { readOk = true; - } else if (leftFileRegExp.indexIn(patch) == 0) { - patch.remove(0, leftFileRegExp.matchedLength()); + } else if (patch.startsWith(leftStart) && fileNameEnd(leftFollow)) { + patch.remove(0, patch.indexOf(QLatin1Char('\n'), leftStart.count()) + 1); + + const QString rightStart = QString::fromLatin1("+++ ") + rightFileName; + QChar rightFollow = patch.count() > rightStart.count() ? patch.at(rightStart.count()) : QLatin1Char('\n'); // followed by rightFileRegExp - if (rightFileRegExp.indexIn(patch) == 0) { - patch.remove(0, rightFileRegExp.matchedLength()); + if (patch.startsWith(rightStart) && fileNameEnd(rightFollow)) { + patch.remove(0, patch.indexOf(QLatin1Char('\n'), rightStart.count()) + 1); fileData.chunks = readChunks(patch, &fileData.lastChunkAtTheEndOfFile, &readOk); } - } else if (binaryRegExp.indexIn(patch) == 0) { + } else if (patch == binaryLine) { readOk = true; fileData.binaryFiles = true; } @@ -966,9 +967,6 @@ static FileData readCopyRenameChunks(const QString ©RenameChunks, const QRegExp indexRegExp(QLatin1String("^index (\\w+)\\.{2}(\\w+)(?: \\d+)?(\\n|$)")); // index cap1..cap2(optionally: octal) - QString leftGitFileName = QLatin1String("a/") + leftFileName; - QString rightGitFileName = QLatin1String("b/") + rightFileName; - if (fileOperation == FileData::CopyFile || fileOperation == FileData::RenameFile) { if (indexRegExp.indexIn(patch) == 0) { fileData.leftFileInfo.typeInfo = indexRegExp.cap(1); @@ -976,20 +974,20 @@ static FileData readCopyRenameChunks(const QString ©RenameChunks, patch.remove(0, indexRegExp.matchedLength()); - const QRegExp leftFileRegExp(QLatin1String("^-{3} ") // "--- " - + leftGitFileName // "a/fileName" or "/dev/null" - + QLatin1String("(?:\\t[^\\n]*)*\\n")); // optionally followed by: \t anything \t anything ...) - const QRegExp rightFileRegExp(QLatin1String("^\\+{3} ") // "+++ " - + rightGitFileName // "b/fileName" or "/dev/null" - + QLatin1String("(?:\\t[^\\n]*)*\\n")); // optionally followed by: \t anything \t anything ...) + const QString leftStart = QString::fromLatin1("--- a/") + leftFileName; + QChar leftFollow = patch.count() > leftStart.count() ? patch.at(leftStart.count()) : QLatin1Char('\n'); // followed by leftFileRegExp - if (leftFileRegExp.indexIn(patch) == 0) { - patch.remove(0, leftFileRegExp.matchedLength()); + if (patch.startsWith(leftStart) && fileNameEnd(leftFollow)) { + patch.remove(0, patch.indexOf(QLatin1Char('\n'), leftStart.count()) + 1); + + // followed by rightFileRegExp + const QString rightStart = QString::fromLatin1("+++ b/") + rightFileName; + QChar rightFollow = patch.count() > rightStart.count() ? patch.at(rightStart.count()) : QLatin1Char('\n'); // followed by rightFileRegExp - if (rightFileRegExp.indexIn(patch) == 0) { - patch.remove(0, rightFileRegExp.matchedLength()); + if (patch.startsWith(rightStart) && fileNameEnd(rightFollow)) { + patch.remove(0, patch.indexOf(QLatin1Char('\n'), rightStart.count()) + 1); fileData.chunks = readChunks(patch, &fileData.lastChunkAtTheEndOfFile, |