forked from qt-creator/qt-creator
Replace QRegExp with QRegularExpression
Use QStringRef where possible. Speedup readGitPatch() approximately 2 times. Change-Id: I7bd09d7ac768331b0600456e48c44cfc72b7001d Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
@@ -1298,6 +1298,53 @@ void DiffEditor::Internal::DiffEditorPlugin::testReadPatch_data()
|
|||||||
QTest::newRow("Dirty submodule") << patch
|
QTest::newRow("Dirty submodule") << patch
|
||||||
<< fileDataList7;
|
<< fileDataList7;
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
patch = _("diff --git a/demos/arthurplugin/arthurplugin.pro b/demos/arthurplugin/arthurplugin.pro\n"
|
||||||
|
"new file mode 100644\n"
|
||||||
|
"index 0000000..c5132b4\n"
|
||||||
|
"--- /dev/null\n"
|
||||||
|
"+++ b/demos/arthurplugin/arthurplugin.pro\n"
|
||||||
|
"@@ -0,0 +1 @@\n"
|
||||||
|
"+XXX\n"
|
||||||
|
"diff --git a/demos/arthurplugin/bg1.jpg b/demos/arthurplugin/bg1.jpg\n"
|
||||||
|
"new file mode 100644\n"
|
||||||
|
"index 0000000..dfc7cee\n"
|
||||||
|
"Binary files /dev/null and b/demos/arthurplugin/bg1.jpg differ\n"
|
||||||
|
"diff --git a/demos/arthurplugin/flower.jpg b/demos/arthurplugin/flower.jpg\n"
|
||||||
|
"new file mode 100644\n"
|
||||||
|
"index 0000000..f8e022c\n"
|
||||||
|
"Binary files /dev/null and b/demos/arthurplugin/flower.jpg differ\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
fileData1 = FileData();
|
||||||
|
fileData1.leftFileInfo = DiffFileInfo(_("demos/arthurplugin/arthurplugin.pro"), _("0000000"));
|
||||||
|
fileData1.rightFileInfo = DiffFileInfo(_("demos/arthurplugin/arthurplugin.pro"), _("c5132b4"));
|
||||||
|
fileData1.fileOperation = FileData::NewFile;
|
||||||
|
chunkData1 = ChunkData();
|
||||||
|
chunkData1.leftStartingLineNumber = -1;
|
||||||
|
chunkData1.rightStartingLineNumber = 0;
|
||||||
|
rows1.clear();
|
||||||
|
rows1 << RowData(TextLineData::Separator, _("XXX"));
|
||||||
|
rows1 << RowData(TextLineData::Separator, TextLineData(TextLineData::TextLine));
|
||||||
|
chunkData1.rows = rows1;
|
||||||
|
fileData1.chunks << chunkData1;
|
||||||
|
fileData2 = FileData();
|
||||||
|
fileData2.leftFileInfo = DiffFileInfo(_("demos/arthurplugin/bg1.jpg"), _("0000000"));
|
||||||
|
fileData2.rightFileInfo = DiffFileInfo(_("demos/arthurplugin/bg1.jpg"), _("dfc7cee"));
|
||||||
|
fileData2.fileOperation = FileData::NewFile;
|
||||||
|
fileData2.binaryFiles = true;
|
||||||
|
fileData3 = FileData();
|
||||||
|
fileData3.leftFileInfo = DiffFileInfo(_("demos/arthurplugin/flower.jpg"), _("0000000"));
|
||||||
|
fileData3.rightFileInfo = DiffFileInfo(_("demos/arthurplugin/flower.jpg"), _("f8e022c"));
|
||||||
|
fileData3.fileOperation = FileData::NewFile;
|
||||||
|
fileData3.binaryFiles = true;
|
||||||
|
|
||||||
|
QList<FileData> fileDataList8;
|
||||||
|
fileDataList8 << fileData1 << fileData2 << fileData3;
|
||||||
|
|
||||||
|
QTest::newRow("Binary files") << patch
|
||||||
|
<< fileDataList8;
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
|
|
||||||
// Subversion New
|
// Subversion New
|
||||||
@@ -1313,10 +1360,10 @@ void DiffEditor::Internal::DiffEditorPlugin::testReadPatch_data()
|
|||||||
chunkData1.leftStartingLineNumber = -1;
|
chunkData1.leftStartingLineNumber = -1;
|
||||||
chunkData1.rightStartingLineNumber = 124;
|
chunkData1.rightStartingLineNumber = 124;
|
||||||
fileData1.chunks << chunkData1;
|
fileData1.chunks << chunkData1;
|
||||||
QList<FileData> fileDataList8;
|
QList<FileData> fileDataList9;
|
||||||
fileDataList8 << fileData1;
|
fileDataList9 << fileData1;
|
||||||
QTest::newRow("Subversion New") << patch
|
QTest::newRow("Subversion New") << patch
|
||||||
<< fileDataList8;
|
<< fileDataList9;
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
|
|
||||||
@@ -1333,10 +1380,10 @@ void DiffEditor::Internal::DiffEditorPlugin::testReadPatch_data()
|
|||||||
chunkData1.leftStartingLineNumber = 0;
|
chunkData1.leftStartingLineNumber = 0;
|
||||||
chunkData1.rightStartingLineNumber = -1;
|
chunkData1.rightStartingLineNumber = -1;
|
||||||
fileData1.chunks << chunkData1;
|
fileData1.chunks << chunkData1;
|
||||||
QList<FileData> fileDataList9;
|
QList<FileData> fileDataList10;
|
||||||
fileDataList9 << fileData1;
|
fileDataList10 << fileData1;
|
||||||
QTest::newRow("Subversion Deleted") << patch
|
QTest::newRow("Subversion Deleted") << patch
|
||||||
<< fileDataList9;
|
<< fileDataList10;
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
|
|
||||||
@@ -1353,10 +1400,10 @@ void DiffEditor::Internal::DiffEditorPlugin::testReadPatch_data()
|
|||||||
chunkData1.leftStartingLineNumber = 119;
|
chunkData1.leftStartingLineNumber = 119;
|
||||||
chunkData1.rightStartingLineNumber = 119;
|
chunkData1.rightStartingLineNumber = 119;
|
||||||
fileData1.chunks << chunkData1;
|
fileData1.chunks << chunkData1;
|
||||||
QList<FileData> fileDataList10;
|
QList<FileData> fileDataList11;
|
||||||
fileDataList10 << fileData1;
|
fileDataList11 << fileData1;
|
||||||
QTest::newRow("Subversion Normal") << patch
|
QTest::newRow("Subversion Normal") << patch
|
||||||
<< fileDataList10;
|
<< fileDataList11;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiffEditor::Internal::DiffEditorPlugin::testReadPatch()
|
void DiffEditor::Internal::DiffEditorPlugin::testReadPatch()
|
||||||
@@ -1365,10 +1412,10 @@ void DiffEditor::Internal::DiffEditorPlugin::testReadPatch()
|
|||||||
QFETCH(QList<FileData>, fileDataList);
|
QFETCH(QList<FileData>, fileDataList);
|
||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
QList<FileData> result = DiffUtils::readPatch(sourcePatch, &ok);
|
const QList<FileData> &result = DiffUtils::readPatch(sourcePatch, &ok);
|
||||||
|
|
||||||
QVERIFY(ok);
|
QVERIFY(ok);
|
||||||
QCOMPARE(fileDataList.count(), result.count());
|
QCOMPARE(result.count(), fileDataList.count());
|
||||||
for (int i = 0; i < fileDataList.count(); i++) {
|
for (int i = 0; i < fileDataList.count(); i++) {
|
||||||
const FileData &origFileData = fileDataList.at(i);
|
const FileData &origFileData = fileDataList.at(i);
|
||||||
const FileData &resultFileData = result.at(i);
|
const FileData &resultFileData = result.at(i);
|
||||||
|
@@ -34,7 +34,7 @@ publication by Neil Fraser: http://neil.fraser.name/writing/diff/
|
|||||||
#include "differ.h"
|
#include "differ.h"
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
@@ -204,9 +204,9 @@ static QList<Diff> cleanupOverlaps(const QList<Diff> &diffList)
|
|||||||
|
|
||||||
static int cleanupSemanticsScore(const QString &text1, const QString &text2)
|
static int cleanupSemanticsScore(const QString &text1, const QString &text2)
|
||||||
{
|
{
|
||||||
const QRegExp blankLineEnd = QRegExp(QLatin1String("\\n\\r?\\n$"));
|
const QRegularExpression blankLineEnd("\\n\\r?\\n$");
|
||||||
const QRegExp blankLineStart = QRegExp(QLatin1String("^\\r?\\n\\r?\\n"));
|
const QRegularExpression blankLineStart("^\\r?\\n\\r?\\n");
|
||||||
const QRegExp sentenceEnd = QRegExp(QLatin1String("\\. $"));
|
const QRegularExpression sentenceEnd("\\. $");
|
||||||
|
|
||||||
if (!text1.count() || !text2.count()) // Edges
|
if (!text1.count() || !text2.count()) // Edges
|
||||||
return 6;
|
return 6;
|
||||||
@@ -219,14 +219,14 @@ static int cleanupSemanticsScore(const QString &text1, const QString &text2)
|
|||||||
const bool whitespace2 = nonAlphaNumeric2 && char2.isSpace();
|
const bool whitespace2 = nonAlphaNumeric2 && char2.isSpace();
|
||||||
const bool lineBreak1 = whitespace1 && char1.category() == QChar::Other_Control;
|
const bool lineBreak1 = whitespace1 && char1.category() == QChar::Other_Control;
|
||||||
const bool lineBreak2 = whitespace2 && char2.category() == QChar::Other_Control;
|
const bool lineBreak2 = whitespace2 && char2.category() == QChar::Other_Control;
|
||||||
const bool blankLine1 = lineBreak1 && blankLineEnd.indexIn(text1) != -1;
|
const bool blankLine1 = lineBreak1 && blankLineEnd.match(text1).hasMatch();
|
||||||
const bool blankLine2 = lineBreak2 && blankLineStart.indexIn(text2) != -1;
|
const bool blankLine2 = lineBreak2 && blankLineStart.match(text2).hasMatch();
|
||||||
|
|
||||||
if (blankLine1 || blankLine2) // Blank lines
|
if (blankLine1 || blankLine2) // Blank lines
|
||||||
return 5;
|
return 5;
|
||||||
if (lineBreak1 || lineBreak2) // Line breaks
|
if (lineBreak1 || lineBreak2) // Line breaks
|
||||||
return 4;
|
return 4;
|
||||||
if (sentenceEnd.indexIn(text1) != -1) // End of sentence
|
if (sentenceEnd.match(text1).hasMatch()) // End of sentence
|
||||||
return 3;
|
return 3;
|
||||||
if (whitespace1 || whitespace2) // Whitespaces
|
if (whitespace1 || whitespace2) // Whitespaces
|
||||||
return 2;
|
return 2;
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include "diffutils.h"
|
#include "diffutils.h"
|
||||||
#include "differ.h"
|
#include "differ.h"
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include "texteditor/fontsettings.h"
|
#include "texteditor/fontsettings.h"
|
||||||
@@ -519,14 +519,11 @@ QString DiffUtils::makePatch(const QList<FileData> &fileDataList, unsigned forma
|
|||||||
return diffText;
|
return diffText;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QList<RowData> readLines(const QString &patch,
|
static QList<RowData> readLines(QStringRef patch,
|
||||||
bool lastChunk,
|
bool lastChunk,
|
||||||
bool *lastChunkAtTheEndOfFile,
|
bool *lastChunkAtTheEndOfFile,
|
||||||
bool *ok)
|
bool *ok)
|
||||||
{
|
{
|
||||||
// const QRegExp lineRegExp(QLatin1String("(?:\\n)" // beginning of the line
|
|
||||||
// "([ -\\+\\\\])([^\\n]*)" // -, +, \\ or space, followed by any no-newline character
|
|
||||||
// "(?:\\n|$)")); // end of line or file
|
|
||||||
QList<Diff> diffList;
|
QList<Diff> diffList;
|
||||||
|
|
||||||
const QChar newLine = QLatin1Char('\n');
|
const QChar newLine = QLatin1Char('\n');
|
||||||
@@ -539,16 +536,16 @@ static QList<RowData> readLines(const QString &patch,
|
|||||||
int noNewLineInDelete = -1;
|
int noNewLineInDelete = -1;
|
||||||
int noNewLineInInsert = -1;
|
int noNewLineInInsert = -1;
|
||||||
|
|
||||||
const QStringList lines = patch.split(newLine);
|
const QVector<QStringRef> lines = patch.split(newLine);
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < lines.count(); i++) {
|
for (i = 0; i < lines.count(); i++) {
|
||||||
const QString line = lines.at(i);
|
QStringRef line = lines.at(i);
|
||||||
if (line.isEmpty()) { // need to have at least one character (1 column)
|
if (line.isEmpty()) { // need to have at least one character (1 column)
|
||||||
if (lastChunk)
|
if (lastChunk)
|
||||||
i = lines.count(); // pretend as we've read all the lines (we just ignore the rest)
|
i = lines.count(); // pretend as we've read all the lines (we just ignore the rest)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
QChar firstCharacter = line.at(0);
|
const QChar firstCharacter = line.at(0);
|
||||||
if (firstCharacter == QLatin1Char('\\')) { // no new line marker
|
if (firstCharacter == QLatin1Char('\\')) { // no new line marker
|
||||||
if (!lastChunk) // can only appear in last chunk of the file
|
if (!lastChunk) // can only appear in last chunk of the file
|
||||||
break;
|
break;
|
||||||
@@ -695,34 +692,35 @@ static QList<RowData> readLines(const QString &patch,
|
|||||||
outputRightDiffList).rows;
|
outputRightDiffList).rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QList<ChunkData> readChunks(const QString &patch,
|
static QList<ChunkData> readChunks(QStringRef patch,
|
||||||
bool *lastChunkAtTheEndOfFile,
|
bool *lastChunkAtTheEndOfFile,
|
||||||
bool *ok)
|
bool *ok)
|
||||||
{
|
{
|
||||||
const QRegExp chunkRegExp(QLatin1String(
|
const QRegularExpression chunkRegExp(
|
||||||
// beginning of the line
|
// beginning of the line
|
||||||
"(?:\\n|^)"
|
"(?:\\n|^)"
|
||||||
// @@ -leftPos[,leftCount] +rightPos[,rightCount] @@
|
// @@ -leftPos[,leftCount] +rightPos[,rightCount] @@
|
||||||
"@@ -(\\d+)(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@"
|
"@@ -(\\d+)(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@"
|
||||||
// optional hint (e.g. function name)
|
// optional hint (e.g. function name)
|
||||||
"(\\ +[^\\n]*)?"
|
"(\\ +[^\\n]*)?"
|
||||||
// end of line (need to be followed by text line)
|
// end of line (need to be followed by text line)
|
||||||
"\\n"));
|
"\\n");
|
||||||
|
|
||||||
bool readOk = false;
|
bool readOk = false;
|
||||||
|
|
||||||
QList<ChunkData> chunkDataList;
|
QList<ChunkData> chunkDataList;
|
||||||
|
|
||||||
int pos = chunkRegExp.indexIn(patch);
|
QRegularExpressionMatch match = chunkRegExp.match(patch);
|
||||||
if (pos == 0) {
|
if (match.hasMatch() && match.capturedStart() == 0) {
|
||||||
int endOfLastChunk = 0;
|
int endOfLastChunk = 0;
|
||||||
do {
|
do {
|
||||||
const int leftStartingPos = chunkRegExp.cap(1).toInt();
|
const int pos = match.capturedStart();
|
||||||
const int rightStartingPos = chunkRegExp.cap(2).toInt();
|
const int leftStartingPos = match.capturedRef(1).toInt();
|
||||||
const QString contextInfo = chunkRegExp.cap(3);
|
const int rightStartingPos = match.capturedRef(2).toInt();
|
||||||
|
const QString contextInfo = match.captured(3);
|
||||||
if (endOfLastChunk > 0) {
|
if (endOfLastChunk > 0) {
|
||||||
const QString lines = patch.mid(endOfLastChunk,
|
QStringRef lines = patch.mid(endOfLastChunk,
|
||||||
pos - endOfLastChunk);
|
pos - endOfLastChunk);
|
||||||
chunkDataList.last().rows = readLines(lines,
|
chunkDataList.last().rows = readLines(lines,
|
||||||
false,
|
false,
|
||||||
lastChunkAtTheEndOfFile,
|
lastChunkAtTheEndOfFile,
|
||||||
@@ -730,17 +728,17 @@ static QList<ChunkData> readChunks(const QString &patch,
|
|||||||
if (!readOk)
|
if (!readOk)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pos += chunkRegExp.matchedLength();
|
endOfLastChunk = match.capturedEnd();
|
||||||
endOfLastChunk = pos;
|
|
||||||
ChunkData chunkData;
|
ChunkData chunkData;
|
||||||
chunkData.leftStartingLineNumber = leftStartingPos - 1;
|
chunkData.leftStartingLineNumber = leftStartingPos - 1;
|
||||||
chunkData.rightStartingLineNumber = rightStartingPos - 1;
|
chunkData.rightStartingLineNumber = rightStartingPos - 1;
|
||||||
chunkData.contextInfo = contextInfo;
|
chunkData.contextInfo = contextInfo;
|
||||||
chunkDataList.append(chunkData);
|
chunkDataList.append(chunkData);
|
||||||
} while ((pos = chunkRegExp.indexIn(patch, pos, QRegExp::CaretAtOffset)) != -1);
|
match = chunkRegExp.match(patch, endOfLastChunk);
|
||||||
|
} while (match.hasMatch());
|
||||||
|
|
||||||
if (endOfLastChunk > 0) {
|
if (endOfLastChunk > 0) {
|
||||||
const QString lines = patch.mid(endOfLastChunk);
|
QStringRef lines = patch.mid(endOfLastChunk);
|
||||||
chunkDataList.last().rows = readLines(lines,
|
chunkDataList.last().rows = readLines(lines,
|
||||||
true,
|
true,
|
||||||
lastChunkAtTheEndOfFile,
|
lastChunkAtTheEndOfFile,
|
||||||
@@ -754,42 +752,49 @@ static QList<ChunkData> readChunks(const QString &patch,
|
|||||||
return chunkDataList;
|
return chunkDataList;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FileData readDiffHeaderAndChunks(const QString &headerAndChunks,
|
static FileData readDiffHeaderAndChunks(QStringRef headerAndChunks,
|
||||||
bool *ok)
|
bool *ok)
|
||||||
{
|
{
|
||||||
QString patch = headerAndChunks;
|
QStringRef patch = headerAndChunks;
|
||||||
FileData fileData;
|
FileData fileData;
|
||||||
bool readOk = false;
|
bool readOk = false;
|
||||||
|
|
||||||
const QRegExp leftFileRegExp(QLatin1String(
|
const QRegularExpression leftFileRegExp(
|
||||||
"(?:\\n|^)-{3} " // "--- "
|
"(?:\\n|^)-{3} " // "--- "
|
||||||
"([^\\t\\n]+)" // "fileName1"
|
"([^\\t\\n]+)" // "fileName1"
|
||||||
"(?:\\t[^\\n]*)*\\n")); // optionally followed by: \t anything \t anything ...)
|
"(?:\\t[^\\n]*)*\\n"); // optionally followed by: \t anything \t anything ...)
|
||||||
const QRegExp rightFileRegExp(QLatin1String(
|
const QRegularExpression rightFileRegExp(
|
||||||
"^\\+{3} " // "+++ "
|
"^\\+{3} " // "+++ "
|
||||||
"([^\\t\\n]+)" // "fileName2"
|
"([^\\t\\n]+)" // "fileName2"
|
||||||
"(?:\\t[^\\n]*)*\\n")); // optionally followed by: \t anything \t anything ...)
|
"(?:\\t[^\\n]*)*\\n"); // optionally followed by: \t anything \t anything ...)
|
||||||
const QRegExp binaryRegExp(QLatin1String("^Binary files ([^\\t\\n]+) and ([^\\t\\n]+) differ$"));
|
const QRegularExpression binaryRegExp(
|
||||||
|
"^Binary files ([^\\t\\n]+) and ([^\\t\\n]+) differ$");
|
||||||
|
|
||||||
// followed either by leftFileRegExp or by binaryRegExp
|
// followed either by leftFileRegExp
|
||||||
if (leftFileRegExp.indexIn(patch) == 0) {
|
const QRegularExpressionMatch leftMatch = leftFileRegExp.match(patch);
|
||||||
patch.remove(0, leftFileRegExp.matchedLength());
|
if (leftMatch.hasMatch() && leftMatch.capturedStart() == 0) {
|
||||||
fileData.leftFileInfo.fileName = leftFileRegExp.cap(1);
|
patch = patch.mid(leftMatch.capturedEnd());
|
||||||
|
fileData.leftFileInfo.fileName = leftMatch.captured(1);
|
||||||
|
|
||||||
// followed by rightFileRegExp
|
// followed by rightFileRegExp
|
||||||
if (rightFileRegExp.indexIn(patch) == 0) {
|
const QRegularExpressionMatch rightMatch = rightFileRegExp.match(patch);
|
||||||
patch.remove(0, rightFileRegExp.matchedLength());
|
if (rightMatch.hasMatch() && rightMatch.capturedStart() == 0) {
|
||||||
fileData.rightFileInfo.fileName = rightFileRegExp.cap(1);
|
patch = patch.mid(rightMatch.capturedEnd());
|
||||||
|
fileData.rightFileInfo.fileName = rightMatch.captured(1);
|
||||||
|
|
||||||
fileData.chunks = readChunks(patch,
|
fileData.chunks = readChunks(patch,
|
||||||
&fileData.lastChunkAtTheEndOfFile,
|
&fileData.lastChunkAtTheEndOfFile,
|
||||||
&readOk);
|
&readOk);
|
||||||
}
|
}
|
||||||
} else if (binaryRegExp.indexIn(patch) == 0) {
|
} else {
|
||||||
fileData.leftFileInfo.fileName = binaryRegExp.cap(1);
|
// or by binaryRegExp
|
||||||
fileData.rightFileInfo.fileName = binaryRegExp.cap(2);
|
const QRegularExpressionMatch binaryMatch = binaryRegExp.match(patch);
|
||||||
fileData.binaryFiles = true;
|
if (binaryMatch.hasMatch() && binaryMatch.capturedStart() == 0) {
|
||||||
readOk = true;
|
fileData.leftFileInfo.fileName = binaryMatch.captured(1);
|
||||||
|
fileData.rightFileInfo.fileName = binaryMatch.captured(2);
|
||||||
|
fileData.binaryFiles = true;
|
||||||
|
readOk = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
@@ -802,37 +807,38 @@ static FileData readDiffHeaderAndChunks(const QString &headerAndChunks,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static QList<FileData> readDiffPatch(const QString &patch,
|
static QList<FileData> readDiffPatch(QStringRef patch,
|
||||||
bool *ok)
|
bool *ok)
|
||||||
{
|
{
|
||||||
const QRegExp diffRegExp(QLatin1String("(?:\\n|^)" // new line of the beginning of a patch
|
const QRegularExpression diffRegExp("(?:\\n|^)" // new line of the beginning of a patch
|
||||||
"(" // either
|
"(" // either
|
||||||
"-{3} " // ---
|
"-{3} " // ---
|
||||||
"[^\\t\\n]+" // filename1
|
"[^\\t\\n]+" // filename1
|
||||||
"(?:\\t[^\\n]*)*\\n" // optionally followed by: \t anything \t anything ...
|
"(?:\\t[^\\n]*)*\\n" // optionally followed by: \t anything \t anything ...
|
||||||
"\\+{3} " // +++
|
"\\+{3} " // +++
|
||||||
"[^\\t\\n]+" // filename2
|
"[^\\t\\n]+" // filename2
|
||||||
"(?:\\t[^\\n]*)*\\n" // optionally followed by: \t anything \t anything ...
|
"(?:\\t[^\\n]*)*\\n" // optionally followed by: \t anything \t anything ...
|
||||||
"|" // or
|
"|" // or
|
||||||
"Binary files "
|
"Binary files "
|
||||||
"[^\\t\\n]+" // filename1
|
"[^\\t\\n]+" // filename1
|
||||||
" and "
|
" and "
|
||||||
"[^\\t\\n]+" // filename2
|
"[^\\t\\n]+" // filename2
|
||||||
" differ"
|
" differ"
|
||||||
")")); // end of or
|
")"); // end of or
|
||||||
|
|
||||||
bool readOk = false;
|
bool readOk = false;
|
||||||
|
|
||||||
QList<FileData> fileDataList;
|
QList<FileData> fileDataList;
|
||||||
|
|
||||||
int pos = diffRegExp.indexIn(patch);
|
QRegularExpressionMatch diffMatch = diffRegExp.match(patch);
|
||||||
if (pos >= 0) { // git style patch
|
if (diffMatch.hasMatch()) {
|
||||||
readOk = true;
|
readOk = true;
|
||||||
int lastPos = -1;
|
int lastPos = -1;
|
||||||
do {
|
do {
|
||||||
|
int pos = diffMatch.capturedStart();
|
||||||
if (lastPos >= 0) {
|
if (lastPos >= 0) {
|
||||||
const QString headerAndChunks = patch.mid(lastPos,
|
QStringRef headerAndChunks = patch.mid(lastPos,
|
||||||
pos - lastPos);
|
pos - lastPos);
|
||||||
|
|
||||||
const FileData fileData = readDiffHeaderAndChunks(headerAndChunks,
|
const FileData fileData = readDiffHeaderAndChunks(headerAndChunks,
|
||||||
&readOk);
|
&readOk);
|
||||||
@@ -843,12 +849,13 @@ static QList<FileData> readDiffPatch(const QString &patch,
|
|||||||
fileDataList.append(fileData);
|
fileDataList.append(fileData);
|
||||||
}
|
}
|
||||||
lastPos = pos;
|
lastPos = pos;
|
||||||
pos += diffRegExp.matchedLength();
|
pos = diffMatch.capturedEnd();
|
||||||
} while ((pos = diffRegExp.indexIn(patch, pos)) != -1);
|
diffMatch = diffRegExp.match(patch, pos);
|
||||||
|
} while (diffMatch.hasMatch());
|
||||||
|
|
||||||
if (lastPos >= 0 && readOk) {
|
if (readOk) {
|
||||||
const QString headerAndChunks = patch.mid(lastPos,
|
QStringRef headerAndChunks = patch.mid(lastPos,
|
||||||
patch.count() - lastPos - 1);
|
patch.count() - lastPos - 1);
|
||||||
|
|
||||||
const FileData fileData = readDiffHeaderAndChunks(headerAndChunks,
|
const FileData fileData = readDiffHeaderAndChunks(headerAndChunks,
|
||||||
&readOk);
|
&readOk);
|
||||||
@@ -872,7 +879,7 @@ static bool fileNameEnd(const QChar &c)
|
|||||||
return c == QLatin1Char('\n') || c == QLatin1Char('\t');
|
return c == QLatin1Char('\n') || c == QLatin1Char('\t');
|
||||||
}
|
}
|
||||||
|
|
||||||
static FileData readGitHeaderAndChunks(const QString &headerAndChunks,
|
static FileData readGitHeaderAndChunks(QStringRef headerAndChunks,
|
||||||
const QString &fileName,
|
const QString &fileName,
|
||||||
bool *ok)
|
bool *ok)
|
||||||
{
|
{
|
||||||
@@ -880,41 +887,52 @@ static FileData readGitHeaderAndChunks(const QString &headerAndChunks,
|
|||||||
fileData.leftFileInfo.fileName = fileName;
|
fileData.leftFileInfo.fileName = fileName;
|
||||||
fileData.rightFileInfo.fileName = fileName;
|
fileData.rightFileInfo.fileName = fileName;
|
||||||
|
|
||||||
QString patch = headerAndChunks;
|
QStringRef patch = headerAndChunks;
|
||||||
bool readOk = false;
|
bool readOk = false;
|
||||||
|
|
||||||
const QString devNull(QLatin1String("/dev/null"));
|
const QString devNull(QLatin1String("/dev/null"));
|
||||||
|
|
||||||
// will be followed by: index 0000000..shasha, file "a" replaced by "/dev/null", @@ -0,0 +m,n @@
|
// will be followed by: index 0000000..shasha, file "a" replaced by "/dev/null", @@ -0,0 +m,n @@
|
||||||
const QRegExp newFileMode(QLatin1String("^new file mode \\d+\\n")); // new file mode octal
|
// new file mode octal
|
||||||
|
const QRegularExpression newFileMode("^new file mode \\d+\\n");
|
||||||
|
|
||||||
// will be followed by: index shasha..0000000, file "b" replaced by "/dev/null", @@ -m,n +0,0 @@
|
// will be followed by: index shasha..0000000, file "b" replaced by "/dev/null", @@ -m,n +0,0 @@
|
||||||
const QRegExp deletedFileMode(QLatin1String("^deleted file mode \\d+\\n")); // deleted file mode octal
|
// deleted file mode octal
|
||||||
|
const QRegularExpression deletedFileMode("^deleted file mode \\d+\\n");
|
||||||
|
|
||||||
const QRegExp modeChangeRegExp(QLatin1String("^old mode \\d+\\nnew mode \\d+\\n"));
|
const QRegularExpression modeChangeRegExp("^old mode \\d+\\nnew mode \\d+\\n");
|
||||||
|
|
||||||
const QRegExp indexRegExp(QLatin1String("^index (\\w+)\\.{2}(\\w+)(?: \\d+)?(\\n|$)")); // index cap1..cap2(optionally: octal)
|
// index cap1..cap2(optionally: octal)
|
||||||
|
const QRegularExpression indexRegExp("^index (\\w+)\\.{2}(\\w+)(?: \\d+)?(\\n|$)");
|
||||||
|
|
||||||
QString leftFileName = QLatin1String("a/") + fileName;
|
QString leftFileName = QLatin1String("a/") + fileName;
|
||||||
QString rightFileName = QLatin1String("b/") + fileName;
|
QString rightFileName = QLatin1String("b/") + fileName;
|
||||||
|
|
||||||
if (newFileMode.indexIn(patch) == 0) {
|
const QRegularExpressionMatch newFileMatch = newFileMode.match(patch);
|
||||||
|
if (newFileMatch.hasMatch() && newFileMatch.capturedStart() == 0) {
|
||||||
fileData.fileOperation = FileData::NewFile;
|
fileData.fileOperation = FileData::NewFile;
|
||||||
leftFileName = devNull;
|
leftFileName = devNull;
|
||||||
patch.remove(0, newFileMode.matchedLength());
|
patch = patch.mid(newFileMatch.capturedEnd());
|
||||||
} else if (deletedFileMode.indexIn(patch) == 0) {
|
} else {
|
||||||
fileData.fileOperation = FileData::DeleteFile;
|
const QRegularExpressionMatch deletedFileMatch = deletedFileMode.match(patch);
|
||||||
rightFileName = devNull;
|
if (deletedFileMatch.hasMatch() && deletedFileMatch.capturedStart() == 0) {
|
||||||
patch.remove(0, deletedFileMode.matchedLength());
|
fileData.fileOperation = FileData::DeleteFile;
|
||||||
} else if (modeChangeRegExp.indexIn(patch) == 0) {
|
rightFileName = devNull;
|
||||||
patch.remove(0, modeChangeRegExp.matchedLength());
|
patch = patch.mid(deletedFileMatch.capturedEnd());
|
||||||
|
} else {
|
||||||
|
const QRegularExpressionMatch modeChangeMatch = modeChangeRegExp.match(patch);
|
||||||
|
if (modeChangeMatch.hasMatch() && modeChangeMatch.capturedStart() == 0) {
|
||||||
|
patch = patch.mid(modeChangeMatch.capturedEnd());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indexRegExp.indexIn(patch) == 0) {
|
const QRegularExpressionMatch indexMatch = indexRegExp.match(patch);
|
||||||
fileData.leftFileInfo.typeInfo = indexRegExp.cap(1);
|
if (indexMatch.hasMatch() && indexMatch.capturedStart() == 0) {
|
||||||
fileData.rightFileInfo.typeInfo = indexRegExp.cap(2);
|
fileData.leftFileInfo.typeInfo = indexMatch.captured(1);
|
||||||
|
fileData.rightFileInfo.typeInfo = indexMatch.captured(2);
|
||||||
|
|
||||||
patch.remove(0, indexRegExp.matchedLength());
|
patch = patch.mid(indexMatch.capturedEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString binaryLine = QString::fromLatin1("Binary files ") + leftFileName
|
const QString binaryLine = QString::fromLatin1("Binary files ") + leftFileName
|
||||||
@@ -927,14 +945,14 @@ static FileData readGitHeaderAndChunks(const QString &headerAndChunks,
|
|||||||
|| fileData.fileOperation == FileData::DeleteFile)) {
|
|| fileData.fileOperation == FileData::DeleteFile)) {
|
||||||
readOk = true;
|
readOk = true;
|
||||||
} else if (patch.startsWith(leftStart) && fileNameEnd(leftFollow)) {
|
} else if (patch.startsWith(leftStart) && fileNameEnd(leftFollow)) {
|
||||||
patch.remove(0, patch.indexOf(QLatin1Char('\n'), leftStart.count()) + 1);
|
patch = patch.mid(patch.indexOf(QLatin1Char('\n'), leftStart.count()) + 1);
|
||||||
|
|
||||||
const QString rightStart = QString::fromLatin1("+++ ") + rightFileName;
|
const QString rightStart = QString::fromLatin1("+++ ") + rightFileName;
|
||||||
QChar rightFollow = patch.count() > rightStart.count() ? patch.at(rightStart.count()) : QLatin1Char('\n');
|
QChar rightFollow = patch.count() > rightStart.count() ? patch.at(rightStart.count()) : QLatin1Char('\n');
|
||||||
|
|
||||||
// followed by rightFileRegExp
|
// followed by rightFileRegExp
|
||||||
if (patch.startsWith(rightStart) && fileNameEnd(rightFollow)) {
|
if (patch.startsWith(rightStart) && fileNameEnd(rightFollow)) {
|
||||||
patch.remove(0, patch.indexOf(QLatin1Char('\n'), rightStart.count()) + 1);
|
patch = patch.mid(patch.indexOf(QLatin1Char('\n'), rightStart.count()) + 1);
|
||||||
|
|
||||||
fileData.chunks = readChunks(patch,
|
fileData.chunks = readChunks(patch,
|
||||||
&fileData.lastChunkAtTheEndOfFile,
|
&fileData.lastChunkAtTheEndOfFile,
|
||||||
@@ -954,7 +972,7 @@ static FileData readGitHeaderAndChunks(const QString &headerAndChunks,
|
|||||||
return fileData;
|
return fileData;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FileData readCopyRenameChunks(const QString ©RenameChunks,
|
static FileData readCopyRenameChunks(QStringRef copyRenameChunks,
|
||||||
FileData::FileOperation fileOperation,
|
FileData::FileOperation fileOperation,
|
||||||
const QString &leftFileName,
|
const QString &leftFileName,
|
||||||
const QString &rightFileName,
|
const QString &rightFileName,
|
||||||
@@ -965,24 +983,26 @@ static FileData readCopyRenameChunks(const QString ©RenameChunks,
|
|||||||
fileData.leftFileInfo.fileName = leftFileName;
|
fileData.leftFileInfo.fileName = leftFileName;
|
||||||
fileData.rightFileInfo.fileName = rightFileName;
|
fileData.rightFileInfo.fileName = rightFileName;
|
||||||
|
|
||||||
QString patch = copyRenameChunks;
|
QStringRef patch = copyRenameChunks;
|
||||||
bool readOk = false;
|
bool readOk = false;
|
||||||
|
|
||||||
const QRegExp indexRegExp(QLatin1String("^index (\\w+)\\.{2}(\\w+)(?: \\d+)?(\\n|$)")); // index cap1..cap2(optionally: octal)
|
// index cap1..cap2(optionally: octal)
|
||||||
|
const QRegularExpression indexRegExp("^index (\\w+)\\.{2}(\\w+)(?: \\d+)?(\\n|$)");
|
||||||
|
|
||||||
if (fileOperation == FileData::CopyFile || fileOperation == FileData::RenameFile) {
|
if (fileOperation == FileData::CopyFile || fileOperation == FileData::RenameFile) {
|
||||||
if (indexRegExp.indexIn(patch) == 0) {
|
const QRegularExpressionMatch indexMatch = indexRegExp.match(patch);
|
||||||
fileData.leftFileInfo.typeInfo = indexRegExp.cap(1);
|
if (indexMatch.hasMatch() && indexMatch.capturedStart() == 0) {
|
||||||
fileData.rightFileInfo.typeInfo = indexRegExp.cap(2);
|
fileData.leftFileInfo.typeInfo = indexMatch.captured(1);
|
||||||
|
fileData.rightFileInfo.typeInfo = indexMatch.captured(2);
|
||||||
|
|
||||||
patch.remove(0, indexRegExp.matchedLength());
|
patch = patch.mid(indexMatch.capturedEnd());
|
||||||
|
|
||||||
const QString leftStart = QString::fromLatin1("--- a/") + leftFileName;
|
const QString leftStart = QString::fromLatin1("--- a/") + leftFileName;
|
||||||
QChar leftFollow = patch.count() > leftStart.count() ? patch.at(leftStart.count()) : QLatin1Char('\n');
|
QChar leftFollow = patch.count() > leftStart.count() ? patch.at(leftStart.count()) : QLatin1Char('\n');
|
||||||
|
|
||||||
// followed by leftFileRegExp
|
// followed by leftFileRegExp
|
||||||
if (patch.startsWith(leftStart) && fileNameEnd(leftFollow)) {
|
if (patch.startsWith(leftStart) && fileNameEnd(leftFollow)) {
|
||||||
patch.remove(0, patch.indexOf(QLatin1Char('\n'), leftStart.count()) + 1);
|
patch = patch.mid(patch.indexOf(QLatin1Char('\n'), leftStart.count()) + 1);
|
||||||
|
|
||||||
// followed by rightFileRegExp
|
// followed by rightFileRegExp
|
||||||
const QString rightStart = QString::fromLatin1("+++ b/") + rightFileName;
|
const QString rightStart = QString::fromLatin1("+++ b/") + rightFileName;
|
||||||
@@ -990,7 +1010,7 @@ static FileData readCopyRenameChunks(const QString ©RenameChunks,
|
|||||||
|
|
||||||
// followed by rightFileRegExp
|
// followed by rightFileRegExp
|
||||||
if (patch.startsWith(rightStart) && fileNameEnd(rightFollow)) {
|
if (patch.startsWith(rightStart) && fileNameEnd(rightFollow)) {
|
||||||
patch.remove(0, patch.indexOf(QLatin1Char('\n'), rightStart.count()) + 1);
|
patch = patch.mid(patch.indexOf(QLatin1Char('\n'), rightStart.count()) + 1);
|
||||||
|
|
||||||
fileData.chunks = readChunks(patch,
|
fileData.chunks = readChunks(patch,
|
||||||
&fileData.lastChunkAtTheEndOfFile,
|
&fileData.lastChunkAtTheEndOfFile,
|
||||||
@@ -1011,15 +1031,19 @@ static FileData readCopyRenameChunks(const QString ©RenameChunks,
|
|||||||
return fileData;
|
return fileData;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QList<FileData> readGitPatch(const QString &patch, bool *ok)
|
static QList<FileData> readGitPatch(QStringRef patch, bool *ok)
|
||||||
{
|
{
|
||||||
const QRegExp simpleGitRegExp(QLatin1String("(?:\\n|^)diff --git a/([^\\n]+) b/\\1\\n")); // diff --git a/cap1 b/cap1
|
|
||||||
|
|
||||||
const QRegExp similarityRegExp(QLatin1String(
|
const QRegularExpression simpleGitRegExp(
|
||||||
"(?:\\n|^)diff --git a/([^\\n]+) b/([^\\n]+)\\n" // diff --git a/cap1 b/cap2
|
"^diff --git a/([^\\n]+) b/\\1\\n" // diff --git a/cap1 b/cap1
|
||||||
"(?:dis)?similarity index \\d{1,3}%\\n" // similarity / dissimilarity index xxx% (100% max)
|
, QRegularExpression::MultilineOption);
|
||||||
"(copy|rename) from \\1\\n" // copy / rename from cap1
|
|
||||||
"\\3 to \\2\\n")); // copy / rename (cap3) to cap2
|
const QRegularExpression similarityRegExp(
|
||||||
|
"^diff --git a/([^\\n]+) b/([^\\n]+)\\n" // diff --git a/cap1 b/cap2
|
||||||
|
"(?:dis)?similarity index \\d{1,3}%\\n" // similarity / dissimilarity index xxx% (100% max)
|
||||||
|
"(copy|rename) from \\1\\n" // copy / rename from cap1
|
||||||
|
"\\3 to \\2\\n" // copy / rename (cap3) to cap2
|
||||||
|
, QRegularExpression::MultilineOption);
|
||||||
|
|
||||||
bool readOk = false;
|
bool readOk = false;
|
||||||
|
|
||||||
@@ -1027,20 +1051,46 @@ static QList<FileData> readGitPatch(const QString &patch, bool *ok)
|
|||||||
|
|
||||||
bool simpleGitMatched;
|
bool simpleGitMatched;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
QRegularExpressionMatch simpleGitMatch = simpleGitRegExp.match(patch);
|
||||||
|
QRegularExpressionMatch similarityMatch = similarityRegExp.match(patch);
|
||||||
auto calculateGitMatchAndPosition = [&]() {
|
auto calculateGitMatchAndPosition = [&]() {
|
||||||
const int simpleGitPos = simpleGitRegExp.indexIn(patch, pos, QRegExp::CaretAtOffset);
|
if (pos > 0) { // don't advance in the initial call
|
||||||
const int similarityPos = similarityRegExp.indexIn(patch, pos, QRegExp::CaretAtOffset);
|
if (simpleGitMatch.hasMatch() && similarityMatch.hasMatch()) {
|
||||||
if (simpleGitPos < 0) {
|
const int simpleGitPos = simpleGitMatch.capturedStart();
|
||||||
pos = similarityPos;
|
const int similarityPos = similarityMatch.capturedStart();
|
||||||
simpleGitMatched = false;
|
if (simpleGitPos <= similarityPos)
|
||||||
|
simpleGitMatch = simpleGitRegExp.match(patch, simpleGitMatch.capturedEnd() - 1); // advance only simpleGit
|
||||||
|
else
|
||||||
|
similarityMatch = similarityRegExp.match(patch, similarityMatch.capturedEnd() - 1); // advance only similarity
|
||||||
|
} else if (simpleGitMatch.hasMatch()) {
|
||||||
|
simpleGitMatch = simpleGitRegExp.match(patch, simpleGitMatch.capturedEnd() - 1);
|
||||||
|
} else if (similarityMatch.hasMatch()) {
|
||||||
|
similarityMatch = similarityRegExp.match(patch, similarityMatch.capturedEnd() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (simpleGitMatch.hasMatch() && similarityMatch.hasMatch()) {
|
||||||
|
const int simpleGitPos = simpleGitMatch.capturedStart();
|
||||||
|
const int similarityPos = similarityMatch.capturedStart();
|
||||||
|
pos = qMin(simpleGitPos, similarityPos);
|
||||||
|
simpleGitMatched = (pos == simpleGitPos);
|
||||||
return;
|
return;
|
||||||
} else if (similarityPos < 0) {
|
}
|
||||||
pos = simpleGitPos;
|
|
||||||
|
if (simpleGitMatch.hasMatch()) {
|
||||||
|
pos = simpleGitMatch.capturedStart();
|
||||||
simpleGitMatched = true;
|
simpleGitMatched = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pos = qMin(simpleGitPos, similarityPos);
|
|
||||||
simpleGitMatched = (pos == simpleGitPos);
|
if (similarityMatch.hasMatch()) {
|
||||||
|
pos = similarityMatch.capturedStart();
|
||||||
|
simpleGitMatched = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = -1;
|
||||||
|
simpleGitMatched = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set both pos and simpleGitMatched according to the first match:
|
// Set both pos and simpleGitMatched according to the first match:
|
||||||
@@ -1052,10 +1102,12 @@ static QList<FileData> readGitPatch(const QString &patch, bool *ok)
|
|||||||
QString lastLeftFileName;
|
QString lastLeftFileName;
|
||||||
QString lastRightFileName;
|
QString lastRightFileName;
|
||||||
FileData::FileOperation lastOperation = FileData::ChangeFile;
|
FileData::FileOperation lastOperation = FileData::ChangeFile;
|
||||||
do {
|
|
||||||
if (endOfLastHeader > 0) {
|
auto collectFileData = [&]() {
|
||||||
const QString headerAndChunks = patch.mid(endOfLastHeader,
|
if (endOfLastHeader > 0 && readOk) {
|
||||||
pos - endOfLastHeader);
|
const int end = pos < 0 ? patch.count() : pos;
|
||||||
|
QStringRef headerAndChunks = patch.mid(endOfLastHeader,
|
||||||
|
qMax(end - endOfLastHeader - 1, 0));
|
||||||
|
|
||||||
FileData fileData;
|
FileData fileData;
|
||||||
if (lastOperation == FileData::ChangeFile) {
|
if (lastOperation == FileData::ChangeFile) {
|
||||||
@@ -1069,25 +1121,27 @@ static QList<FileData> readGitPatch(const QString &patch, bool *ok)
|
|||||||
lastRightFileName,
|
lastRightFileName,
|
||||||
&readOk);
|
&readOk);
|
||||||
}
|
}
|
||||||
if (!readOk)
|
if (readOk)
|
||||||
break;
|
fileDataList.append(fileData);
|
||||||
|
|
||||||
fileDataList.append(fileData);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
do {
|
||||||
|
collectFileData();
|
||||||
|
if (!readOk)
|
||||||
|
break;
|
||||||
|
|
||||||
if (simpleGitMatched) {
|
if (simpleGitMatched) {
|
||||||
const QString fileName = simpleGitRegExp.cap(1);
|
const QString fileName = simpleGitMatch.captured(1);
|
||||||
pos += simpleGitRegExp.matchedLength();
|
pos = simpleGitMatch.capturedEnd();
|
||||||
endOfLastHeader = pos;
|
|
||||||
lastLeftFileName = fileName;
|
lastLeftFileName = fileName;
|
||||||
lastRightFileName = fileName;
|
lastRightFileName = fileName;
|
||||||
lastOperation = FileData::ChangeFile;
|
lastOperation = FileData::ChangeFile;
|
||||||
} else {
|
} else {
|
||||||
lastLeftFileName = similarityRegExp.cap(1);
|
lastLeftFileName = similarityMatch.captured(1);
|
||||||
lastRightFileName = similarityRegExp.cap(2);
|
lastRightFileName = similarityMatch.captured(2);
|
||||||
const QString operation = similarityRegExp.cap(3);
|
const QString operation = similarityMatch.captured(3);
|
||||||
pos += similarityRegExp.matchedLength();
|
pos = similarityMatch.capturedEnd();
|
||||||
endOfLastHeader = pos;
|
|
||||||
if (operation == QLatin1String("copy"))
|
if (operation == QLatin1String("copy"))
|
||||||
lastOperation = FileData::CopyFile;
|
lastOperation = FileData::CopyFile;
|
||||||
else if (operation == QLatin1String("rename"))
|
else if (operation == QLatin1String("rename"))
|
||||||
@@ -1095,31 +1149,14 @@ static QList<FileData> readGitPatch(const QString &patch, bool *ok)
|
|||||||
else
|
else
|
||||||
break; // either copy or rename, otherwise broken
|
break; // either copy or rename, otherwise broken
|
||||||
}
|
}
|
||||||
|
endOfLastHeader = pos;
|
||||||
|
|
||||||
// give both pos and simpleGitMatched a new value for the next match
|
// give both pos and simpleGitMatched a new value for the next match
|
||||||
calculateGitMatchAndPosition();
|
calculateGitMatchAndPosition();
|
||||||
} while (pos != -1);
|
} while (pos != -1);
|
||||||
|
|
||||||
if (endOfLastHeader > 0 && readOk) {
|
if (readOk)
|
||||||
const QString headerAndChunks = patch.mid(endOfLastHeader,
|
collectFileData();
|
||||||
patch.count() - endOfLastHeader - 1);
|
|
||||||
|
|
||||||
FileData fileData;
|
|
||||||
if (lastOperation == FileData::ChangeFile) {
|
|
||||||
|
|
||||||
fileData = readGitHeaderAndChunks(headerAndChunks,
|
|
||||||
lastLeftFileName,
|
|
||||||
&readOk);
|
|
||||||
} else {
|
|
||||||
fileData = readCopyRenameChunks(headerAndChunks,
|
|
||||||
lastOperation,
|
|
||||||
lastLeftFileName,
|
|
||||||
lastRightFileName,
|
|
||||||
&readOk);
|
|
||||||
}
|
|
||||||
if (readOk)
|
|
||||||
fileDataList.append(fileData);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
@@ -1137,12 +1174,12 @@ QList<FileData> DiffUtils::readPatch(const QString &patch, bool *ok)
|
|||||||
|
|
||||||
QList<FileData> fileDataList;
|
QList<FileData> fileDataList;
|
||||||
|
|
||||||
QString croppedPatch = patch;
|
QStringRef croppedPatch(&patch);
|
||||||
// Crop e.g. "-- \n2.10.2.windows.1\n\n" at end of file
|
// Crop e.g. "-- \n2.10.2.windows.1\n\n" at end of file
|
||||||
const QRegExp formatPatchEndingRegExp(QLatin1String("(\\n-- \\n\\S*\\n\\n$)"));
|
const QRegularExpression formatPatchEndingRegExp("(\\n-- \\n\\S*\\n\\n$)");
|
||||||
const int pos = formatPatchEndingRegExp.indexIn(patch);
|
const QRegularExpressionMatch match = formatPatchEndingRegExp.match(croppedPatch);
|
||||||
if (pos != -1)
|
if (match.hasMatch())
|
||||||
croppedPatch = patch.left(pos + 1); // crop the ending for git format-patch
|
croppedPatch = croppedPatch.left(match.capturedStart() + 1);
|
||||||
|
|
||||||
fileDataList = readGitPatch(croppedPatch, &readOk);
|
fileDataList = readGitPatch(croppedPatch, &readOk);
|
||||||
if (!readOk)
|
if (!readOk)
|
||||||
|
Reference in New Issue
Block a user