# # # patch "src/model/ContentDiff.cpp" # from [d5f9c1f13e38f6aee86944e9a30cc70ed4aa07dd] # to [35d7dcc334afc2c001d65aa230a17e3ea42986a3] # # patch "src/model/ContentDiff.h" # from [90b48b45b61ac9e9d29d606df9203c8acbf5c3be] # to [1f974e237ab07595838d0cc47680ef11242a1474] # # patch "src/util/DiffParser.cpp" # from [8a0894d240cf052d59fb7355194bb9c38857568e] # to [5bdcb3f592048ca903f4ad916b70fe441cb24256] # # patch "src/util/DiffParser.h" # from [733f86a15e4818ad2712a1652c91252fbeabaf1b] # to [831ad2e4c4bffd650540219fedd91deb5c6945be] # ============================================================ --- src/model/ContentDiff.cpp d5f9c1f13e38f6aee86944e9a30cc70ed4aa07dd +++ src/model/ContentDiff.cpp 35d7dcc334afc2c001d65aa230a17e3ea42986a3 @@ -43,8 +43,10 @@ void ContentDiff::readDatabaseDiff(const void ContentDiff::readDatabaseDiff(const DatabaseFile & db, const QString & fileName, const QString & base, const QString & target, - const QString & encoding) + const QString & enc) { + encoding = enc; + QStringList cmd; cmd << "content_diff"; @@ -70,19 +72,15 @@ void ContentDiff::readDatabaseDiff(const } MonotoneTask task(cmd, opts); - - if (!encoding.isEmpty()) - { - task.setOutputEncoding(encoding); - } - AutomateCommand::enqueueDatabaseTask(db, task); } void ContentDiff::readWorkspaceDiff(const WorkspacePath & ws, const QString & fileName, const QString & base, const QString & target, - const QString & encoding) + const QString & enc) { + encoding = enc; + QStringList cmd; cmd << "content_diff"; @@ -116,16 +114,10 @@ void ContentDiff::readWorkspaceDiff(cons } MonotoneTask task(cmd, opts); - - if (!encoding.isEmpty()) - { - task.setOutputEncoding(encoding); - } - AutomateCommand::enqueueWorkspaceTask(ws, task); } -void ContentDiff::switchOutputEncoding(const QString & codec) +void ContentDiff::switchOutputEncoding(const QString & enc) { if (!lastTask.isFinished()) { @@ -133,11 +125,12 @@ void ContentDiff::switchOutputEncoding(c return; } - cleanup(); + encoding = enc; - loadOutputIntoModel(lastTask.getDecodedOutput(codec)); + cleanup(); + loadOutputIntoModel(lastTask.getOutput(), enc); - emit encodingChanged(codec); + emit encodingChanged(enc); } void ContentDiff::processTaskResult(const MonotoneTask & task) @@ -152,15 +145,15 @@ void ContentDiff::processTaskResult(cons cleanup(); lastTask = task; - loadOutputIntoModel(task.getDecodedOutput()); + loadOutputIntoModel(task.getOutput(), encoding); emit diffRead(); } -void ContentDiff::loadOutputIntoModel(const QString & output) +void ContentDiff::loadOutputIntoModel(const QByteArray & output, const QString & codec) { I(!diffParser); - diffParser = new DiffParser(output); + diffParser = new DiffParser(output, codec); // flatten the data for the current view FileDiffs fileDiffs = diffParser->getAllDiffs(); ============================================================ --- src/model/ContentDiff.h 90b48b45b61ac9e9d29d606df9203c8acbf5c3be +++ src/model/ContentDiff.h 1f974e237ab07595838d0cc47680ef11242a1474 @@ -116,12 +116,13 @@ private: private: void processTaskResult(const MonotoneTask &); - void loadOutputIntoModel(const QString &); + void loadOutputIntoModel(const QByteArray &, const QString &); void cleanup(); DiffParser * diffParser; ListLines lines; MonotoneTask lastTask; + QString encoding; }; #endif ============================================================ --- src/util/DiffParser.cpp 8a0894d240cf052d59fb7355194bb9c38857568e +++ src/util/DiffParser.cpp 5bdcb3f592048ca903f4ad916b70fe441cb24256 @@ -22,8 +22,13 @@ #include #include -DiffParser::DiffParser(const QString & input) +DiffParser::DiffParser(const QByteArray & input, const QString & enc) + : codec(0) { + // QTextCodec implements codecForName as factory and caches multiple + // requests, so we don't need to do that ourselves + codec = QTextCodec::codecForName(enc.toLatin1()); + I(codec); parse(input); } @@ -33,7 +38,7 @@ DiffParser::~DiffParser() fileDiffs.clear(); } -void DiffParser::parse(const QString & input) +void DiffParser::parse(const QByteArray & input) { if (input.length() == 0) { @@ -42,11 +47,11 @@ void DiffParser::parse(const QString & i } // remove last newline character - QString in(input); + QByteArray in(input); in.chop(1); // split the output into lines - QStringList lines = in.split(QChar('\n')); + ByteArrayList lines = in.split('\n'); QString curFile; @@ -55,9 +60,9 @@ void DiffParser::parse(const QString & i for (int i=0, s=lines.size(); i 0); - QChar curChar = line.at(0); + char curChar = line.at(0); // // parse file diff separators, setup new DiffFile object @@ -67,28 +72,30 @@ void DiffParser::parse(const QString & i I(i < (s-1)); // straightly go to the next line - QString nextGroup(lines.at(++i)); + QByteArray nextLine(lines.at(++i)); // create a new diff curDiff = new Diff(); - // check if this is a binary - QRegExp rx = QRegExp("^#\\s(.+)\\sis binary"); - if (rx.indexIn(nextGroup) != -1) + // `# path/to/file is binary' + int isBinaryPos = nextLine.indexOf(" is binary"); + if (isBinaryPos != -1) { curDiff->is_binary = true; - curFile = rx.cap(1); + I(in.length() > isBinaryPos); + curFile = nextLine.mid(2, isBinaryPos - 2); } else { - // then this should be a normal file diff - rx = QRegExp("^---\\s([^\\t]+)\\t\\w{40}"); - I(rx.indexIn(nextGroup) > -1); - curFile = rx.cap(1); + // `--- path/to/file 123456789abcdef...' + int tabPos = nextLine.indexOf('\t'); + I(tabPos != -1); + curFile = nextLine.mid(4, tabPos - 4); curDiff->is_binary = false; // skip the next line as we don't care about renames - // yet and if we care about them, we get this info from - // the cset + // yet and if we would care about them, we would get this + // info from the cset (which we should fetch and process + // sometime...) i++; } @@ -103,8 +110,13 @@ void DiffParser::parse(const QString & i // if (curChar == '@') { + // this line is far easier to parse with a regex and it should not + // contain any non-ascii character + QString str(line); + I(str.length() == line.length()); + QRegExp rx = QRegExp("^@@\\s+\\-(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@"); - I(rx.indexIn(line) > -1); + I(rx.indexIn(str) > -1); QStringList list = rx.capturedTexts(); I(list.size() >= 2); @@ -139,7 +151,7 @@ void DiffParser::parse(const QString & i { // if we have a "no newline at the end of the file" line we // also always have an ancestor line which has missing this - // particular \n characterkate + // particular \n character I(curHunk->lines.size() > 0); DiffLine * lastLine = curHunk->lines.last(); @@ -164,7 +176,7 @@ void DiffParser::parse(const QString & i DiffLine * diffLine = new DiffLine(); curHunk->lines.push_back(diffLine); - diffLine->content = line.mid(1); + diffLine->content = codec->toUnicode(line.mid(1)); diffLine->state = state; } } ============================================================ --- src/util/DiffParser.h 733f86a15e4818ad2712a1652c91252fbeabaf1b +++ src/util/DiffParser.h 831ad2e4c4bffd650540219fedd91deb5c6945be @@ -24,6 +24,7 @@ #include #include #include +#include struct DiffLine { @@ -68,14 +69,16 @@ public: { Q_OBJECT public: - DiffParser(const QString &); + DiffParser(const QByteArray &, const QString &); ~DiffParser(); Diff * getDiff(const QString &); inline FileDiffs getAllDiffs() const { return fileDiffs; } private: - void parse(const QString &); + void parse(const QByteArray &); + FileDiffs fileDiffs; + QTextCodec * codec; }; #endif