# # # patch "NEWS" # from [194df88efeddf0057ea21fd65b59753b94c18f99] # to [8f7f5dbff999f8c3bc5d19cd99d0c79cd206ec3d] # # patch "notes/TODO" # from [ea5eaa751fa11645c142bca08911a145ef87d4a5] # to [d75ffed20b8388cb8c037695c7de3bd5c7be45e4] # # patch "src/model/ContentDiff.cpp" # from [ff1f36cc79508208262bac9b577edfa4bdb8bad0] # to [25b9c4272115c9105bc95a0e126731e098d76a06] # # patch "src/model/GetFile.cpp" # from [c7c56add3d7c44df2b73a16c1884f5b73d232aba] # to [71eb299484ec7ad15dea21b6f5604a947b58778b] # # patch "src/model/GetFile.h" # from [7a964370cd74cd5aa333751d9966fb72c1fc44c1] # to [0c796e32b16d6fb12567629e72940f551cba74f5] # # patch "src/model/GetFileProxyModel.cpp" # from [350edfa9110debc88a3367d786fee0f7c080806a] # to [65152d1d360f0c5ca3b1a15efea8c5a055a9601d] # # patch "src/util/DiffParser.cpp" # from [18c023e886b912e9d2f388beeb1bc3cd9e4e6d23] # to [8a0894d240cf052d59fb7355194bb9c38857568e] # # patch "src/util/DiffParser.h" # from [8b5c78064a94791d05ee43b384fcaa36afa628d4] # to [733f86a15e4818ad2712a1652c91252fbeabaf1b] # ============================================================ --- NEWS 194df88efeddf0057ea21fd65b59753b94c18f99 +++ NEWS 8f7f5dbff999f8c3bc5d19cd99d0c79cd206ec3d @@ -31,6 +31,11 @@ - improved: the file history dialog now reads and displays the changes ad-hoc, so you don't need to wait until the complete history of a particular long- living file is read + - improved: the diff dialogs are now more aware of diffs which change the + line ending at the end of the file: the revision diff dialog shows + "missing \n" after the type of the line, the detailed diff dialog you get + this information in a tooltip when hovering over the particular line. + This needs a monotone installation >= 0.40 - bugfix: a running mtn instance for a workspace is now properly re-used if needed for a database-only task - bugfix: fixed a crash which occured when an internal thread was deleted @@ -39,6 +44,8 @@ reading data - bugfix: on export and checkout, the mtn:execute attribute is now honored, i.e. an exported executable file is made user-executable. (closes FS#12) + - bugfix: fixed a crash when the detailed file diff dialog should display + a diff where the left side (the original file) was completly empty - bugfix: if a not supported mtn version is found and the user hits cancel in the preferences dialog, guitone is now closed properly and does not sit in the background doing nothing ============================================================ --- notes/TODO ea5eaa751fa11645c142bca08911a145ef87d4a5 +++ notes/TODO d75ffed20b8388cb8c037695c7de3bd5c7be45e4 @@ -1,2 +1,7 @@ Current TODO, for "long-term" stuff see Current TODO, for "long-term" stuff see IDEAS. +* make previous / next group buttons work again in detailed diff dialog +* expand the root workspace node in the inventory view again +* decide what to do with the inventory watcher and incremental updates +* code rendering for graph view in the changeset dialog (and think about + a nice way to include this view in the per-file history as well) ============================================================ --- src/model/ContentDiff.cpp ff1f36cc79508208262bac9b577edfa4bdb8bad0 +++ src/model/ContentDiff.cpp 25b9c4272115c9105bc95a0e126731e098d76a06 @@ -135,20 +135,32 @@ void ContentDiff::processTaskResult(cons ListLine * hunkLine = new ListLine(ListLine::HunkLine); fileLine->addChild(hunkLine); - if (line->state == DiffLine::Unchanged) + switch (line->state) { - oldLineNumber++; - hunkLine->lineMarker = QString::number(oldLineNumber); + case DiffLine::Unchanged: + oldLineNumber++; + hunkLine->lineMarker = QString::number(oldLineNumber); + break; + case DiffLine::UnchangedMissingNewline: + oldLineNumber++; + hunkLine->lineMarker = QString("%1 (%2)").arg(oldLineNumber).arg(tr("missing \\n")); + break; + case DiffLine::Added: + hunkLine->lineMarker = QString("+"); + break; + case DiffLine::AddedMissingNewline: + hunkLine->lineMarker = QString("+ (%1)").arg(tr("missing \\n")); + break; + case DiffLine::Removed: + oldLineNumber++; + hunkLine->lineMarker = QString("-"); + break; + case DiffLine::RemovedMissingNewline: + oldLineNumber++; + hunkLine->lineMarker = QString("- (%1)").arg(tr("missing \\n")); + break; + default: I(false); } - else if (line->state == DiffLine::Added) - { - hunkLine->lineMarker = QString("+"); - } - else - { - oldLineNumber++; - hunkLine->lineMarker = QString("-"); - } hunkLine->lineContent = line->content; } @@ -216,12 +228,12 @@ QVariant ContentDiff::data(const QModelI { if (line->type != ListLine::HunkLine) return QVariant(); - if (line->lineMarker.compare("-") == 0) + if (line->lineMarker.startsWith("-")) { return QVariant(QBrush(Qt::red)); } - if (line->lineMarker.compare("+") == 0) + if (line->lineMarker.startsWith("+")) { return QVariant(QBrush(Qt::green)); } ============================================================ --- src/model/GetFile.cpp c7c56add3d7c44df2b73a16c1884f5b73d232aba +++ src/model/GetFile.cpp 71eb299484ec7ad15dea21b6f5604a947b58778b @@ -82,7 +82,7 @@ void GetFile::processTaskResult(const Mo for (int i=0, s=lines.size() - 1; ihunks.size(); ihunks.at(i); - int lineStart = hunk->leftStart + lineOffset; + int lineStart = hunk->leftStart + addedLines; + if (lineStart == 0) + { + lineStart = 1; + } + for (int j=0, t=hunk->lines.size(); jlines.at(j); - // skip unchanged lines - if (line->state == DiffLine::Unchanged) + switch (line->state) { - lineStart++; - continue; - } + case DiffLine::Unchanged: + break; - if (line->state == DiffLine::Removed) - { - fileContents.value(lineStart-1)->marker = ContentLine::Removed; - lineStart++; - continue; - } + case DiffLine::UnchangedMissingNewline: + case DiffLine::Removed: + case DiffLine::RemovedMissingNewline: + I(lineStart - 1 >= 0); + fileContents.value(lineStart - 1)->state = line->state; + break; - I(line->state == DiffLine::Added); + case DiffLine::Added: + case DiffLine::AddedMissingNewline: + I(lineStart - 1 >= 0); + fileContents.insert( + lineStart - 1, + new ContentLine(line->content, line->state) + ); + addedLines++; + break; - fileContents.insert( - lineStart - 1, - new ContentLine(line->content, ContentLine::Added) - ); - lineOffset++; + default: I(false); + } lineStart++; } } @@ -135,21 +143,25 @@ QModelIndex GetFile::getNextGroup(const QModelIndex GetFile::getNextGroup(const QModelIndex & base, bool recurse) { int startRow = 0; - ContentLine::Marker lastMarker = ContentLine::Unchanged; + DiffLine::State lastState = DiffLine::Unchanged; if (base.isValid() && base.row() < fileContents.size()) { startRow = base.row(); - lastMarker = fileContents.at(startRow)->marker; + lastState = fileContents.at(startRow)->state; } for (int i=startRow, j=fileContents.size(); imarker != lastMarker && line->marker != ContentLine::Unchanged) + if ( line->state == DiffLine::Unchanged || + line->state == DiffLine::UnchangedMissingNewline || + (line->state == DiffLine::AddedMissingNewline && lastState == DiffLine::Added) || + (line->state == DiffLine::RemovedMissingNewline && lastState == DiffLine::Removed)) { - return index(i, 0, QModelIndex()); + lastState = line->state; + continue; } - lastMarker = line->marker; + return index(i, 0, QModelIndex()); } // if we already recursed, stop here @@ -161,11 +173,11 @@ QModelIndex GetFile::getPrevGroup(const QModelIndex GetFile::getPrevGroup(const QModelIndex & base, bool recurse) { int startRow = fileContents.size() - 1; - ContentLine::Marker lastMarker = ContentLine::Unchanged; + DiffLine::State lastState = DiffLine::Unchanged; if (base.isValid() && base.row() < fileContents.size()) { startRow = base.row(); - lastMarker = fileContents.at(startRow)->marker; + lastState = fileContents.at(startRow)->state; } bool foundLast = false; @@ -176,19 +188,22 @@ QModelIndex GetFile::getPrevGroup(const // did we already found the last line of a group of similar lines? if (!foundLast) { - if (line->marker != lastMarker && line->marker != ContentLine::Unchanged) + if (line->state == DiffLine::Unchanged || + line->state == DiffLine::UnchangedMissingNewline || + (line->state == DiffLine::Added && lastState == DiffLine::AddedMissingNewline) || + (line->state == DiffLine::Removed && lastState == DiffLine::RemovedMissingNewline)) { - foundLast = true; + lastState = line->state; + continue; } - lastMarker = line->marker; - continue; + foundLast = true; } if (foundLast) { // if the marker just changed, the previous line was our // first line - if (line->marker != lastMarker) + if (line->state != lastState) { return index(i + 1, 0, QModelIndex()); } @@ -231,14 +246,31 @@ QVariant GetFile::data(const QModelIndex else if (role == Qt::BackgroundRole) { - switch (line->marker) + switch (line->state) { - case ContentLine::Added: return QVariant(QBrush(Qt::green)); - case ContentLine::Removed: return QVariant(QBrush(Qt::red)); + case DiffLine::Added: + case DiffLine::AddedMissingNewline: + return QVariant(QBrush(Qt::green)); + case DiffLine::Removed: + case DiffLine::RemovedMissingNewline: + return QVariant(QBrush(Qt::red)); default: return QVariant(); } } else + if (role == Qt::ToolTipRole) + { + // FIXME: do people want to see this more prominently? + switch (line->state) + { + case DiffLine::AddedMissingNewline: + case DiffLine::RemovedMissingNewline: + case DiffLine::UnchangedMissingNewline: + return QVariant(tr("No newline at the end of this line")); + default: return QVariant(); + } + } + else if (role == Qt::FontRole && index.column() == 1) { QFont font; ============================================================ --- src/model/GetFile.h 7a964370cd74cd5aa333751d9966fb72c1fc44c1 +++ src/model/GetFile.h 0c796e32b16d6fb12567629e72940f551cba74f5 @@ -24,11 +24,14 @@ #include +// FIXME: theoretically we could now just use the DiffLine struct which has +// the same fields, however a content line might not always keep a diff line +// forever... struct ContentLine { QString content; - enum Marker {Unchanged, Added, Removed} marker; + DiffLine::State state; ContentLine() {} - ContentLine(QString c, Marker m) : content(c), marker(m) {} + ContentLine(QString c, DiffLine::State s) : content(c), state(s) {} }; typedef QVector Content; ============================================================ --- src/model/GetFileProxyModel.cpp 350edfa9110debc88a3367d786fee0f7c080806a +++ src/model/GetFileProxyModel.cpp 65152d1d360f0c5ca3b1a15efea8c5a055a9601d @@ -30,9 +30,9 @@ bool GetFileProxyModel::filterAcceptsRow QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); ContentLine * line = static_cast(index.internalPointer()); - if (line->marker == ContentLine::Added && version == Left) + if ((line->state == DiffLine::Added || line->state == DiffLine::AddedMissingNewline) && version == Left) return false; - if (line->marker == ContentLine::Removed && version == Right) + if ((line->state == DiffLine::Removed || line->state == DiffLine::RemovedMissingNewline) && version == Right) return false; return true; } @@ -48,4 +48,3 @@ GetFileProxyModel::FileVersion GetFilePr { return version; } - ============================================================ --- src/util/DiffParser.cpp 18c023e886b912e9d2f388beeb1bc3cd9e4e6d23 +++ src/util/DiffParser.cpp 8a0894d240cf052d59fb7355194bb9c38857568e @@ -130,14 +130,42 @@ void DiffParser::parse(const QString & i I(curHunk); + DiffLine::State state; + + if (curChar == '+') state = DiffLine::Added; + else if (curChar == '-') state = DiffLine::Removed; + else if (curChar == ' ') state = DiffLine::Unchanged; + else if (curChar == '\\') + { + // 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 + I(curHunk->lines.size() > 0); + + DiffLine * lastLine = curHunk->lines.last(); + switch (lastLine->state) + { + case DiffLine::Added: + lastLine->state = DiffLine::AddedMissingNewline; + break; + case DiffLine::Removed: + lastLine->state = DiffLine::RemovedMissingNewline; + break; + case DiffLine::Unchanged: + lastLine->state = DiffLine::UnchangedMissingNewline; + break; + default: I(false); + } + + // we do not create a new diff line for this pseudo line + continue; + } + else I(false); + DiffLine * diffLine = new DiffLine(); curHunk->lines.push_back(diffLine); diffLine->content = line.mid(1); - - if (curChar == '+') diffLine->state = DiffLine::Added; - else if (curChar == '-') diffLine->state = DiffLine::Removed; - else if (curChar == ' ') diffLine->state = DiffLine::Unchanged; - else I(false); + diffLine->state = state; } } ============================================================ --- src/util/DiffParser.h 8b5c78064a94791d05ee43b384fcaa36afa628d4 +++ src/util/DiffParser.h 733f86a15e4818ad2712a1652c91252fbeabaf1b @@ -27,7 +27,13 @@ struct DiffLine struct DiffLine { - enum State {Added, Removed, Unchanged} state; + enum State { Added, + Removed, + Unchanged, + AddedMissingNewline, + RemovedMissingNewline, + UnchangedMissingNewline + } state; QString content; };