From 7b012dc3036b8c3a3a509e83d166185f837aa4f1 Mon Sep 17 00:00:00 2001 From: Thomas Zander Date: Wed, 22 Jul 2009 19:22:16 +0300 Subject: [PATCH] Update readGitDiff to work for rename and move patches --- src/hunks/ChangeSet.cpp | 83 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/src/hunks/ChangeSet.cpp b/src/hunks/ChangeSet.cpp index 276a3ab..4eb89be 100644 --- a/src/hunks/ChangeSet.cpp +++ b/src/hunks/ChangeSet.cpp @@ -356,12 +356,29 @@ QList ChangeSet::readGitDiff(QIODevice &git, File *fileToDiff) // parse the output and create objects for each hunk. (note how that can be made multi-threading) // we have to have the filename in the hunk too to allow skipping a whole hunk char buf[10240]; - bool inPatch = false; + enum State { + InPatch, + Empty, + InHeader + }; // a diff can be multiple files, or just the one fileToDiff. Lets keep one File object to point to the current file. + State state = Empty; File file; Hunk hunk; while(true) { qint64 lineLength = Vng::readLine(&git, buf, sizeof(buf)); + if (lineLength == -1 || state == Empty) { + file.addHunk(hunk); + hunk = Hunk(); + if (file.isValid()) + filesInDiff << file; + if (fileToDiff) + file = File(*fileToDiff); + else + file = File(); + state = Empty; + } + if (lineLength == -1) break; QString line = QString::fromLocal8Bit(buf, lineLength); @@ -369,29 +386,21 @@ QList ChangeSet::readGitDiff(QIODevice &git, File *fileToDiff) const bool newfile = line.startsWith("--- /dev/null"); if (line.length() > 6 && (newfile || line.startsWith("--- a/") || line.startsWith("--- \"a/"))) { - file.addHunk(hunk); - hunk = Hunk(); - if (file.isValid()) - filesInDiff << file; - if (fileToDiff) { - file = File(*fileToDiff); - } else { - file = File(); - if (!newfile) { - if (line[4].unicode() == '"') { // git-encoding... - QByteArray array(buf + 7, strlen(buf) - 8); - array.prepend('"'); - file.setOldFileName(File::escapeGitFilename(array)); - } else { - QByteArray array(buf + 6, strlen(buf) - 7); - file.setOldFileName(File::escapeGitFilename(array)); - } + if (!newfile) { + if (line[4].unicode() == '"') { // git-encoding... + QByteArray array(buf + 7, strlen(buf) - 8); + array.prepend('"'); + file.setOldFileName(File::escapeGitFilename(array)); + } else { + QByteArray array(buf + 6, strlen(buf) - 7); + file.setOldFileName(File::escapeGitFilename(array)); } } - inPatch = false; + state = state == InPatch ? Empty : InHeader; } else if (fileToDiff == 0 && line.length() > 6 && (line.startsWith("+++ b/") || line.startsWith("+++ \"b"))) { + state = InHeader; if (line[4].unicode() == '"') { // git-encoding... QByteArray array(buf + 7, strlen(buf) - 8); array.prepend('"'); @@ -403,25 +412,45 @@ QList ChangeSet::readGitDiff(QIODevice &git, File *fileToDiff) else if (line.length() > 5 && line.startsWith("@@ -")) { file.addHunk(hunk); hunk = Hunk(); - inPatch = true; + state = InPatch; } - else if (inPatch && line.startsWith("diff --git ")) { - inPatch = false; + else if (line.startsWith("diff --git ")) { + state = state == InPatch ? Empty : InHeader; + continue; } - else if (line.startsWith("Binary files a/") && line.indexOf(" differ") > 0) { // TODO does git do translations? + else if (line.startsWith("Binary files a/") && line.indexOf(" differ") > 0) { Q_ASSERT(fileToDiff); fileToDiff->setBinary(true); git.close(); return filesInDiff; } - if (inPatch) { + else if (line.startsWith("index ")) { + int dot = line.indexOf(QLatin1Char('.'), 6); + if (dot > 0 && line.length() > dot+3) { + file.setOldSha1(line.mid(6, dot-6)); + int space = line.indexOf(QLatin1Char(' '), dot); + if (space == -1) { + space = line.length()-1; // cut off the linefeed + } else { + file.setProtection(line.mid(space+1).trimmed()); + } + file.setSha1(line.mid(dot+2, space - dot - 2)); + } + state = state == InPatch ? Empty : InHeader; + } + else if (line.startsWith("deleted file mode ")) { + file.setProtection(line.mid(18).trimmed()); + state = state == InPatch ? Empty : InHeader; + } + else if (line.startsWith("new file mode ")) { + file.setProtection(line.mid(13).trimmed()); + state = state == InPatch ? Empty : InHeader; + } + if (state == InPatch) { QByteArray array(buf, lineLength); hunk.addLine(array); } } - file.addHunk(hunk); - if (fileToDiff == 0 && file.isValid()) - filesInDiff << file; git.close(); return filesInDiff; } -- 2.11.4.GIT