VCS: Refactor fileNameFromDiffSpecification

Use diff file pattern to match file name. Avoid duplication.

Include unit tests for Git

Change-Id: Ib68a08368270a27976a3e16bdd1cb219a52b8889
Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
Orgad Shaneh
2013-01-19 23:19:38 +02:00
committed by Orgad Shaneh
parent 57ee50d52f
commit 7b39f41c05
26 changed files with 256 additions and 244 deletions

View File

@@ -52,11 +52,13 @@ using namespace Bazaar;
BazaarEditor::BazaarEditor(const VcsBase::VcsBaseEditorParameters *type, QWidget *parent)
: VcsBase::VcsBaseEditorWidget(type, parent),
m_changesetId(QLatin1String(Constants::CHANGESET_ID)),
m_exactChangesetId(QLatin1String(Constants::CHANGESET_ID_EXACT)),
m_diffFileId(QLatin1String("^=== [a-z]+ [a-z]+ '(.*)'\\s*"))
m_exactChangesetId(QLatin1String(Constants::CHANGESET_ID_EXACT))
{
setAnnotateRevisionTextFormat(tr("Annotate %1"));
setAnnotatePreviousRevisionTextFormat(tr("Annotate parent revision %1"));
// Diff format:
// === <change> <file|dir> 'mainwindow.cpp'
setDiffFilePattern(QRegExp(QLatin1String("^=== [a-z]+ [a-z]+ '(.+)'\\s*")));
}
QSet<QString> BazaarEditor::annotationChanges() const
@@ -111,25 +113,8 @@ QString BazaarEditor::changeUnderCursor(const QTextCursor &cursorIn) const
return QString();
}
QRegExp BazaarEditor::diffFilePattern() const
{
return m_diffFileId;
}
VcsBase::BaseAnnotationHighlighter *BazaarEditor::createAnnotationHighlighter(const QSet<QString> &changes,
const QColor &bg) const
{
return new BazaarAnnotationHighlighter(changes, bg);
}
QString BazaarEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
{
// Check for:
// === <change> <file|dir> 'mainwindow.cpp'
for (QTextBlock block = inBlock; block.isValid(); block = block.previous()) {
const QString line = block.text();
if (m_diffFileId.indexIn(line) != -1)
return findDiffFile(m_diffFileId.cap(1));
}
return QString();
}

View File

@@ -46,13 +46,10 @@ public:
private:
QSet<QString> annotationChanges() const;
QString changeUnderCursor(const QTextCursor &cursor) const;
QRegExp diffFilePattern() const;
VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
QString fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const;
mutable QRegExp m_changesetId;
mutable QRegExp m_exactChangesetId;
mutable QRegExp m_diffFileId;
};
} // namespace Internal

View File

@@ -591,6 +591,41 @@ void BazaarPlugin::diffFromEditorSelected(const QStringList &files)
m_client->diff(m_submitRepository, files);
}
#ifdef WITH_TESTS
#include <QTest>
void BazaarPlugin::testDiffFileResolving_data()
{
QTest::addColumn<QByteArray>("header");
QTest::addColumn<QByteArray>("fileName");
QTest::newRow("New") << QByteArray(
"=== added file 'src/plugins/bazaar/bazaareditor.cpp'\n"
"--- src/plugins/bazaar/bazaareditor.cpp\t1970-01-01 00:00:00 +0000\n"
"+++ src/plugins/bazaar/bazaareditor.cpp\t2013-01-20 21:39:47 +0000\n"
"@@ -0,0 +1,121 @@\n\n")
<< QByteArray("src/plugins/bazaar/bazaareditor.cpp");
QTest::newRow("Deleted") << QByteArray(
"=== removed file 'src/plugins/bazaar/bazaareditor.cpp'\n"
"--- src/plugins/bazaar/bazaareditor.cpp\t2013-01-20 21:39:47 +0000\n"
"+++ src/plugins/bazaar/bazaareditor.cpp\t1970-01-01 00:00:00 +0000\n"
"@@ -1,121 +0,0 @@\n\n")
<< QByteArray("src/plugins/bazaar/bazaareditor.cpp");
QTest::newRow("Modified") << QByteArray(
"=== modified file 'src/plugins/bazaar/bazaareditor.cpp'\n"
"--- src/plugins/bazaar/bazaareditor.cpp\t2010-08-27 14:12:44 +0000\n"
"+++ src/plugins/bazaar/bazaareditor.cpp\t2011-02-28 21:24:19 +0000\n"
"@@ -727,6 +727,9 @@\n\n")
<< QByteArray("src/plugins/bazaar/bazaareditor.cpp");
}
void BazaarPlugin::testDiffFileResolving()
{
BazaarEditor editor(editorParameters + 3, 0);
VcsBase::VcsBaseEditorWidget::testDiffFileResolving(&editor);
}
#endif
void BazaarPlugin::commitFromEditor()
{
// Close the submit editor

View File

@@ -112,6 +112,10 @@ private slots:
void showCommitWidget(const QList<VcsBase::VcsBaseClient::StatusItem> &status);
void commitFromEditor();
void diffFromEditorSelected(const QStringList &files);
#ifdef WITH_TESTS
void testDiffFileResolving_data();
void testDiffFileResolving();
#endif
protected:
void updateActions(VcsBase::VcsBasePlugin::ActionState);

View File

@@ -51,6 +51,12 @@ ClearCaseEditor::ClearCaseEditor(const VcsBase::VcsBaseEditorParameters *type,
m_versionNumberPattern(QLatin1String("[\\\\/]main[\\\\/][^ \t\n\"]*"))
{
QTC_ASSERT(m_versionNumberPattern.isValid(), return);
// Diff formats:
// "+++ D:\depot\...\mainwindow.cpp@@\main\3" (versioned)
// "+++ D:\depot\...\mainwindow.cpp[TAB]Sun May 01 14:22:37 2011" (local)
QRegExp diffFilePattern(QLatin1String("^[-+]{3} ([^\\t]+)(?:@@|\\t)"));
diffFilePattern.setMinimal(true);
setDiffFilePattern(diffFilePattern);
setAnnotateRevisionTextFormat(tr("Annotate version \"%1\""));
}
@@ -87,41 +93,8 @@ QString ClearCaseEditor::changeUnderCursor(const QTextCursor &c) const
return QString();
}
/*
Diff header format (on Windows, native separators are used after the @@)
--- main.cpp@@\main\2
+++ main.cpp@@\main\1
@@ -6,6 +6,5 @@
*/
QRegExp ClearCaseEditor::diffFilePattern() const
{
return QRegExp(QLatin1String("^[-+][-+][-+] "));
}
VcsBase::BaseAnnotationHighlighter *ClearCaseEditor::createAnnotationHighlighter(const QSet<QString> &changes,
const QColor &bg) const
{
return new ClearCaseAnnotationHighlighter(changes, bg);
}
QString ClearCaseEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
{
// "+++ D:\depot\...\mainwindow.cpp@@\main\3"
// "+++ D:\depot\...\mainwindow.cpp[TAB]Sun May 01 14:22:37 2011"
// Go back chunks
const QString diffIndicator = QLatin1String("+++ ");
for (QTextBlock block = inBlock; block.isValid() ; block = block.previous()) {
QString diffFileName = block.text();
if (diffFileName.startsWith(diffIndicator)) {
diffFileName.remove(0, diffIndicator.size());
const int tabIndex = diffFileName.indexOf(QRegExp(QLatin1String("@@|\t")));
if (tabIndex != -1)
diffFileName.truncate(tabIndex);
const QString rc = findDiffFile(diffFileName);
if (ClearCase::Constants::debug)
qDebug() << Q_FUNC_INFO << diffFileName << rc << source();
return rc;
}
}
return QString();
}

View File

@@ -49,11 +49,9 @@ public:
private:
QSet<QString> annotationChanges() const;
QString changeUnderCursor(const QTextCursor &) const;
QRegExp diffFilePattern() const;
VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
QString fileNameFromDiffSpecification(const QTextBlock &diffFileName) const;
mutable QRegExp m_versionNumberPattern;
QRegExp m_versionNumberPattern;
};
} // namespace Internal

View File

@@ -96,7 +96,9 @@
#include <QVariant>
#include <QVBoxLayout>
#include <QXmlStreamReader>
#ifdef WITH_TESTS
#include <QTest>
#endif
namespace ClearCase {
namespace Internal {
@@ -1943,6 +1945,26 @@ void ClearCasePlugin::sync(QFutureInterface<void> &future, QString topLevel, QSt
ccSync.run(future, topLevel, files);
}
#ifdef WITH_TESTS
void ClearCasePlugin::testDiffFileResolving_data()
{
QTest::addColumn<QByteArray>("header");
QTest::addColumn<QByteArray>("fileName");
QTest::newRow("Modified") << QByteArray(
"--- src/plugins/clearcase/clearcaseeditor.cpp@@/main/1\t2013-01-20 23:45:48.549615210 +0200\n"
"+++ src/plugins/clearcase/clearcaseeditor.cpp@@/main/2\t2013-01-20 23:45:53.217604679 +0200\n"
"@@ -58,6 +58,10 @@\n\n")
<< QByteArray("src/plugins/clearcase/clearcaseeditor.cpp");
}
void ClearCasePlugin::testDiffFileResolving()
{
ClearCaseEditor editor(editorParameters + 3, 0);
VcsBase::VcsBaseEditorWidget::testDiffFileResolving(&editor);
}
#endif
} // namespace Internal
} // namespace ClearCase

View File

@@ -192,6 +192,10 @@ private slots:
void syncSlot();
void closing();
void updateStatusActions();
#ifdef WITH_TESTS
void testDiffFileResolving_data();
void testDiffFileResolving();
#endif
protected:
void updateActions(VcsBase::VcsBasePlugin::ActionState);

View File

@@ -55,6 +55,15 @@ CvsEditor::CvsEditor(const VcsBase::VcsBaseEditorParameters *type,
{
QTC_ASSERT(m_revisionAnnotationPattern.isValid(), return);
QTC_ASSERT(m_revisionLogPattern.isValid(), return);
/* Diff format:
\code
cvs diff -d -u -r1.1 -r1.2:
--- mainwindow.cpp<\t>13 Jul 2009 13:50:15 -0000<tab>1.1
+++ mainwindow.cpp<\t>14 Jul 2009 07:09:24 -0000<tab>1.2
@@ -6,6 +6,5 @@
\endcode
*/
setDiffFilePattern(QRegExp(QLatin1String("^[-+]{3} ([^\\t]+)")));
setAnnotateRevisionTextFormat(tr("Annotate revision \"%1\""));
}
@@ -113,42 +122,12 @@ QString CvsEditor::changeUnderCursor(const QTextCursor &c) const
return QString();
}
/* \code
cvs diff -d -u -r1.1 -r1.2:
--- mainwindow.cpp<\t>13 Jul 2009 13:50:15 -0000 <\t>1.1
+++ mainwindow.cpp<\t>14 Jul 2009 07:09:24 -0000<\t>1.2
@@ -6,6 +6,5 @@
\endcode
*/
QRegExp CvsEditor::diffFilePattern() const
{
return QRegExp(QLatin1String("^[-+][-+][-+] .*1\\.[\\d\\.]+$"));
}
VcsBase::BaseAnnotationHighlighter *CvsEditor::createAnnotationHighlighter(const QSet<QString> &changes,
const QColor &bg) const
{
return new CvsAnnotationHighlighter(changes, bg);
}
QString CvsEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
{
// "+++ mainwindow.cpp<\t>13 Jul 2009 13:50:15 -0000 1.1"
// Go back chunks
const QString diffIndicator = QLatin1String("+++ ");
for (QTextBlock block = inBlock; block.isValid() ; block = block.previous()) {
QString diffFileName = block.text();
if (diffFileName.startsWith(diffIndicator)) {
diffFileName.remove(0, diffIndicator.size());
const int tabIndex = diffFileName.indexOf(QLatin1Char('\t'));
if (tabIndex != -1)
diffFileName.truncate(tabIndex);
return findDiffFile(diffFileName);
}
}
return QString();
}
QStringList CvsEditor::annotationPreviousVersions(const QString &revision) const
{
if (isFirstRevision(revision))

View File

@@ -48,9 +48,7 @@ public:
private:
QSet<QString> annotationChanges() const;
QString changeUnderCursor(const QTextCursor &) const;
QRegExp diffFilePattern() const;
VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
QString fileNameFromDiffSpecification(const QTextBlock &diffFileName) const;
QStringList annotationPreviousVersions(const QString &revision) const;
mutable QRegExp m_revisionAnnotationPattern;

View File

@@ -66,6 +66,13 @@ GitEditor::GitEditor(const VcsBase::VcsBaseEditorParameters *type,
{
QTC_ASSERT(m_changeNumberPattern8.isValid(), return);
QTC_ASSERT(m_changeNumberPattern40.isValid(), return);
/* Diff format:
diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp
index 40997ff..4e49337 100644
--- a/src/plugins/git/giteditor.cpp
+++ b/src/plugins/git/giteditor.cpp
*/
setDiffFilePattern(QRegExp(QLatin1String("^(?:diff --git a/|index |[+-]{3} (?:/dev/null|[ab]/(.+$)))")));
setAnnotateRevisionTextFormat(tr("Blame %1"));
setAnnotatePreviousRevisionTextFormat(tr("Blame Parent Revision %1"));
}
@@ -107,46 +114,12 @@ QString GitEditor::changeUnderCursor(const QTextCursor &c) const
return QString();
}
QRegExp GitEditor::diffFilePattern() const
{
return QRegExp(QLatin1String("^(diff --git a/|index |[+-][+-][+-] [ab/]).*$"));
}
VcsBase::BaseAnnotationHighlighter *GitEditor::createAnnotationHighlighter(const QSet<QString> &changes,
const QColor &bg) const
{
return new GitAnnotationHighlighter(changes, bg);
}
QString GitEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
{
// Check for "+++ b/src/plugins/git/giteditor.cpp" (blame and diff)
// as well as "--- a/src/plugins/git/giteditor.cpp".
// Go back chunks.
bool checkForOld = false;
const QString oldFileIndicator = QLatin1String("--- a/");
const QString newFileIndicator = QLatin1String("+++ ");
for (QTextBlock block = inBlock; block.isValid(); block = block.previous()) {
QString diffFileName = block.text();
if (diffFileName.startsWith(oldFileIndicator) && checkForOld) {
diffFileName.remove(0, oldFileIndicator.size());
checkForOld = false;
return diffFileName;
} else if (diffFileName.startsWith(newFileIndicator)) {
diffFileName.remove(0, newFileIndicator.size());
if (diffFileName == QLatin1String("/dev/null")) {
checkForOld = true;
continue;
}
diffFileName.remove(0, 2); // remove "b/"
return findDiffFile(diffFileName);
}
checkForOld = false;
}
return QString();
}
/* Remove the date specification from annotation, which is tabular:
\code
8ca887aa (author YYYY-MM-DD HH:MM:SS <offset> <line>)<content>

View File

@@ -57,9 +57,7 @@ public slots:
private:
QSet<QString> annotationChanges() const;
QString changeUnderCursor(const QTextCursor &) const;
QRegExp diffFilePattern() const;
VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
QString fileNameFromDiffSpecification(const QTextBlock &diffFileName) const;
QString decorateVersion(const QString &revision) const;
QStringList annotationPreviousVersions(const QString &revision) const;
bool isValidRevision(const QString &revision) const;

View File

@@ -1253,8 +1253,14 @@ GitClient *GitPlugin::gitClient() const
}
#ifdef WITH_TESTS
#include "giteditor.h"
#include <QTest>
#include <QTextBlock>
#include <QTextDocument>
Q_DECLARE_METATYPE(FileStates)
void GitPlugin::testStatusParsing_data()
{
QTest::addColumn<FileStates>("first");
@@ -1301,6 +1307,42 @@ void GitPlugin::testStatusParsing()
else
QCOMPARE(data.files.at(1).first, second);
}
void GitPlugin::testDiffFileResolving_data()
{
QTest::addColumn<QByteArray>("header");
QTest::addColumn<QByteArray>("fileName");
QTest::newRow("New") << QByteArray(
"diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp\n"
"new file mode 100644\n"
"index 0000000..40997ff\n"
"--- /dev/null\n"
"+++ b/src/plugins/git/giteditor.cpp\n"
"@@ -0,0 +1,281 @@\n\n")
<< QByteArray("src/plugins/git/giteditor.cpp");
QTest::newRow("Deleted") << QByteArray(
"diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp\n"
"deleted file mode 100644\n"
"index 40997ff..0000000\n"
"--- a/src/plugins/git/giteditor.cpp\n"
"+++ /dev/null\n"
"@@ -1,281 +0,0 @@\n\n")
<< QByteArray("src/plugins/git/giteditor.cpp");
QTest::newRow("Normal") << QByteArray(
"diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp\n"
"index 69e0b52..8fc974d 100644\n"
"--- a/src/plugins/git/giteditor.cpp\n"
"+++ b/src/plugins/git/giteditor.cpp\n"
"@@ -49,6 +49,8 @@\n\n")
<< QByteArray("src/plugins/git/giteditor.cpp");
}
void GitPlugin::testDiffFileResolving()
{
GitEditor editor(editorParameters + 3, 0);
VcsBase::VcsBaseEditorWidget::testDiffFileResolving(&editor);
}
#endif
Q_EXPORT_PLUGIN(GitPlugin)

View File

@@ -144,6 +144,8 @@ private slots:
#ifdef WITH_TESTS
void testStatusParsing_data();
void testStatusParsing();
void testDiffFileResolving_data();
void testDiffFileResolving();
#endif
protected:
void updateActions(VcsBase::VcsBasePlugin::ActionState);

View File

@@ -42,7 +42,7 @@ const char CHANGESETID12[] = " ([a-f0-9]{12,12}) "; //match 12 hex chars and cap
const char CHANGESETID40[] = " ([a-f0-9]{40,40}) ";
const char CHANGEIDEXACT12[] = "[a-f0-9]{12,12}"; //match 12 hex chars a
const char CHANGEIDEXACT40[] = "[a-f0-9]{40,40}";
const char DIFFIDENTIFIER[] = "^[-+]{3,3} [ab]{1,1}.*"; // match e.g. +++ b/filename
const char DIFFIDENTIFIER[] = "^[-+]{3} [ab]/(.+)$"; // match e.g. +++ b/filename
// Base editor parameters
const char COMMANDLOG_ID[] = "Mercurial Command Log Editor";

View File

@@ -51,9 +51,9 @@ MercurialEditor::MercurialEditor(const VcsBase::VcsBaseEditorParameters *type, Q
exactIdentifier12(QLatin1String(Constants::CHANGEIDEXACT12)),
exactIdentifier40(QLatin1String(Constants::CHANGEIDEXACT40)),
changesetIdentifier12(QLatin1String(Constants::CHANGESETID12)),
changesetIdentifier40(QLatin1String(Constants::CHANGESETID40)),
diffIdentifier(QLatin1String(Constants::DIFFIDENTIFIER))
changesetIdentifier40(QLatin1String(Constants::CHANGESETID40))
{
setDiffFilePattern(QRegExp(QLatin1String(Constants::DIFFIDENTIFIER)));
setAnnotateRevisionTextFormat(tr("Annotate %1"));
setAnnotatePreviousRevisionTextFormat(tr("Annotate parent revision %1"));
}
@@ -88,33 +88,12 @@ QString MercurialEditor::changeUnderCursor(const QTextCursor &cursorIn) const
return QString();
}
QRegExp MercurialEditor::diffFilePattern() const
{
return diffIdentifier;
}
VcsBase::BaseAnnotationHighlighter *MercurialEditor::createAnnotationHighlighter(const QSet<QString> &changes,
const QColor &bg) const
{
return new MercurialAnnotationHighlighter(changes, bg);
}
QString MercurialEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
{
// git-compatible format: check for "+++ b/src/plugins/git/giteditor.cpp" (blame and diff)
// Go back chunks.
const QString newFileIndicator = QLatin1String("+++ b/");
for (QTextBlock block = inBlock; block.isValid(); block = block.previous()) {
QString diffFileName = block.text();
if (diffFileName.startsWith(newFileIndicator)) {
diffFileName.remove(0, newFileIndicator.size());
return findDiffFile(diffFileName);
}
}
return QString();
}
QString MercurialEditor::decorateVersion(const QString &revision) const
{
const QFileInfo fi(source());

View File

@@ -46,9 +46,7 @@ public:
private:
QSet<QString> annotationChanges() const;
QString changeUnderCursor(const QTextCursor &cursor) const;
QRegExp diffFilePattern() const;
VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
QString fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const;
QString decorateVersion(const QString &revision) const;
QStringList annotationPreviousVersions(const QString &revision) const;
@@ -56,7 +54,6 @@ private:
mutable QRegExp exactIdentifier40;
mutable QRegExp changesetIdentifier12;
const QRegExp changesetIdentifier40;
const QRegExp diffIdentifier;
};
} // namespace Internal

View File

@@ -63,6 +63,10 @@ PerforceEditor::PerforceEditor(const VcsBase::VcsBaseEditorParameters *type,
m_plugin(PerforcePlugin::perforcePluginInstance())
{
QTC_CHECK(m_changeNumberPattern.isValid());
// Diff format:
// 1) "==== //depot/.../mainwindow.cpp#2 - /depot/.../mainwindow.cpp ====" (created by p4 diff)
// 2) "==== //depot/.../mainwindow.cpp#15 (text) ====" (created by p4 describe)
setDiffFilePattern(QRegExp(QLatin1String("^==== (.+)#\\d")));
setAnnotateRevisionTextFormat(tr("Annotate change list \"%1\""));
if (Perforce::Constants::debug)
qDebug() << "PerforceEditor::PerforceEditor" << type->type << type->id;
@@ -103,57 +107,19 @@ QString PerforceEditor::changeUnderCursor(const QTextCursor &c) const
return m_changeNumberPattern.exactMatch(change) ? change : QString();
}
QRegExp PerforceEditor::diffFilePattern() const
{
return QRegExp(QLatin1String("^====.*"));
}
VcsBase::BaseAnnotationHighlighter *PerforceEditor::createAnnotationHighlighter(const QSet<QString> &changes,
const QColor &bg) const
{
return new PerforceAnnotationHighlighter(changes, bg);
}
QString PerforceEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
QString PerforceEditor::findDiffFile(const QString &f) const
{
QString errorMessage;
const QString diffIndicator = QLatin1String("==== ");
const QString diffEndIndicator = QLatin1String(" ====");
// Go back chunks. Note that for 'describe', an extra, empty line
// occurs.
for (QTextBlock block = inBlock; block.isValid(); block = block.previous()) {
QString diffFileName = block.text();
if (diffFileName.startsWith(diffIndicator) && diffFileName.endsWith(diffEndIndicator)) {
// Split:
// 1) "==== //depot/.../mainwindow.cpp#2 - /depot/.../mainwindow.cpp ===="
// (as created by p4 diff) or
// 2) "==== //depot/.../mainwindow.cpp#15 (text) ===="
// (as created by p4 describe).
diffFileName.remove(0, diffIndicator.size());
diffFileName.truncate(diffFileName.size() - diffEndIndicator.size());
const int separatorPos = diffFileName.indexOf(QLatin1String(" - "));
if (separatorPos == -1) {
// ==== depot path (text) ==== (p4 describe)
const int blankPos = diffFileName.indexOf(QLatin1Char(' '));
if (blankPos == -1)
return QString();
diffFileName.truncate(blankPos);
} else {
// ==== depot path - local path ==== (p4 diff)
diffFileName.truncate(separatorPos);
}
// Split off revision "#4"
const int revisionPos = diffFileName.lastIndexOf(QLatin1Char('#'));
if (revisionPos != -1 && revisionPos < diffFileName.length() - 1)
diffFileName.truncate(revisionPos);
// Ask plugin to map back
const QString fileName = m_plugin->fileNameFromPerforceName(diffFileName.trimmed(), false, &errorMessage);
if (fileName.isEmpty())
qWarning("%s", qPrintable(errorMessage));
return fileName;
}
}
return QString();
const QString fileName = m_plugin->fileNameFromPerforceName(f.trimmed(), false, &errorMessage);
if (fileName.isEmpty())
qWarning("%s", qPrintable(errorMessage));
return fileName;
}
QStringList PerforceEditor::annotationPreviousVersions(const QString &v) const

View File

@@ -50,9 +50,8 @@ public:
private:
QSet<QString> annotationChanges() const;
QString changeUnderCursor(const QTextCursor &) const;
QRegExp diffFilePattern() const;
VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
QString fileNameFromDiffSpecification(const QTextBlock &diffFileName) const;
QString findDiffFile(const QString &f) const;
QStringList annotationPreviousVersions(const QString &v) const;
mutable QRegExp m_changeNumberPattern;

View File

@@ -52,6 +52,16 @@ SubversionEditor::SubversionEditor(const VcsBase::VcsBaseEditorParameters *type,
{
QTC_ASSERT(m_changeNumberPattern.isValid(), return);
QTC_ASSERT(m_revisionNumberPattern.isValid(), return);
/* Diff pattern:
\code
Index: main.cpp
===================================================================
--- main.cpp<tab>(revision 2)
+++ main.cpp<tab>(working copy)
@@ -6,6 +6,5 @@
\endcode
*/
setDiffFilePattern(QRegExp(QLatin1String("^[-+]{3} ([^\\t]+)|^Index: .*|^=+$")));
setAnnotateRevisionTextFormat(tr("Annotate revision \"%1\""));
}
@@ -98,46 +108,12 @@ QString SubversionEditor::changeUnderCursor(const QTextCursor &c) const
return QString();
}
/* code:
Index: main.cpp
===================================================================
--- main.cpp (revision 2)
+++ main.cpp (working copy)
@@ -6,6 +6,5 @@
\endcode
*/
QRegExp SubversionEditor::diffFilePattern() const
{
return QRegExp(QLatin1String("^[-+][-+][-+] .*|^Index: .*|^==*$"));
}
VcsBase::BaseAnnotationHighlighter *SubversionEditor::createAnnotationHighlighter(const QSet<QString> &changes,
const QColor &bg) const
{
return new SubversionAnnotationHighlighter(changes, bg);
}
QString SubversionEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
{
// "+++ /depot/.../mainwindow.cpp<tab>(revision 3)"
// Go back chunks
const QString diffIndicator = QLatin1String("+++ ");
for (QTextBlock block = inBlock; block.isValid() ; block = block.previous()) {
QString diffFileName = block.text();
if (diffFileName.startsWith(diffIndicator)) {
diffFileName.remove(0, diffIndicator.size());
const int tabIndex = diffFileName.lastIndexOf(QLatin1Char('\t'));
if (tabIndex != -1)
diffFileName.truncate(tabIndex);
const QString rc = findDiffFile(diffFileName);
if (Subversion::Constants::debug)
qDebug() << Q_FUNC_INFO << diffFileName << rc << source();
return rc;
}
}
return QString();
}
QStringList SubversionEditor::annotationPreviousVersions(const QString &v) const
{
bool ok;

View File

@@ -48,9 +48,7 @@ public:
private:
QSet<QString> annotationChanges() const;
QString changeUnderCursor(const QTextCursor &) const;
QRegExp diffFilePattern() const;
VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
QString fileNameFromDiffSpecification(const QTextBlock &diffFileName) const;
QStringList annotationPreviousVersions(const QString &) const;
mutable QRegExp m_changeNumberPattern;

View File

@@ -77,6 +77,10 @@
#include <QInputDialog>
#include <limits.h>
#ifdef WITH_TESTS
#include <QTest>
#endif
namespace Subversion {
namespace Internal {
@@ -1389,6 +1393,42 @@ SubversionControl *SubversionPlugin::subVersionControl() const
return static_cast<SubversionControl *>(versionControl());
}
#ifdef WITH_TESTS
void SubversionPlugin::testDiffFileResolving_data()
{
QTest::addColumn<QByteArray>("header");
QTest::addColumn<QByteArray>("fileName");
QTest::newRow("New") << QByteArray(
"Index: src/plugins/subversion/subversioneditor.cpp\n"
"===================================================================\n"
"--- src/plugins/subversion/subversioneditor.cpp\t(revision 0)\n"
"+++ src/plugins/subversion/subversioneditor.cpp\t(revision 0)\n"
"@@ -0,0 +125 @@\n\n")
<< QByteArray("src/plugins/subversion/subversioneditor.cpp");
QTest::newRow("Deleted") << QByteArray(
"Index: src/plugins/subversion/subversioneditor.cpp\n"
"===================================================================\n"
"--- src/plugins/subversion/subversioneditor.cpp\t(revision 42)\n"
"+++ src/plugins/subversion/subversioneditor.cpp\t(working copy)\n"
"@@ -1,125 +0,0 @@\n\n")
<< QByteArray("src/plugins/subversion/subversioneditor.cpp");
QTest::newRow("Normal") << QByteArray(
"Index: src/plugins/subversion/subversioneditor.cpp\n"
"===================================================================\n"
"--- src/plugins/subversion/subversioneditor.cpp\t(revision 42)\n"
"+++ src/plugins/subversion/subversioneditor.cpp\t(working copy)\n"
"@@ -120,7 +120,7 @@\n\n")
<< QByteArray("src/plugins/subversion/subversioneditor.cpp");
}
void SubversionPlugin::testDiffFileResolving()
{
SubversionEditor editor(editorParameters + 3, 0);
VcsBase::VcsBaseEditorWidget::testDiffFileResolving(&editor);
}
#endif
} // Internal
} // Subversion

View File

@@ -136,6 +136,10 @@ private slots:
void diffRepository();
void statusRepository();
void updateRepository();
#ifdef WITH_TESTS
void testDiffFileResolving_data();
void testDiffFileResolving();
#endif
protected:
void updateActions(VcsBase::VcsBasePlugin::ActionState);

View File

@@ -116,7 +116,7 @@ DiffFormats DiffHighlighterPrivate::analyzeLine(const QString &text) const
{
// Do not match on git "--- a/" as a deleted line, check
// file first
if (m_filePattern.exactMatch(text))
if (m_filePattern.indexIn(text) == 0)
return DiffFileFormat;
if (text.startsWith(m_diffInIndicator))
return DiffInFormat;

View File

@@ -668,17 +668,23 @@ VcsBaseEditorWidget::VcsBaseEditorWidget(const VcsBaseEditorParameters *type, QW
setMimeType(QLatin1String(d->m_parameters->mimeType));
}
void VcsBaseEditorWidget::setDiffFilePattern(const QRegExp &pattern)
{
QTC_ASSERT(pattern.isValid() && pattern.captureCount() >= 1, return);
d->m_diffFilePattern = pattern;
}
void VcsBaseEditorWidget::init()
{
switch (d->m_parameters->type) {
case RegularCommandOutput:
case LogOutput:
break;
case AnnotateOutput:
// Annotation highlighting depends on contents, which is set later on
connect(this, SIGNAL(textChanged()), this, SLOT(slotActivateAnnotation()));
break;
case DiffOutput: {
d->m_diffFilePattern = diffFilePattern();
DiffHighlighter *dh = new DiffHighlighter(d->m_diffFilePattern);
setCodeFoldingSupported(true);
baseTextDocument()->setSyntaxHighlighter(dh);
@@ -1429,6 +1435,20 @@ bool VcsBaseEditorWidget::applyDiffChunk(const DiffChunk &dc, bool revert) const
return VcsBasePlugin::runPatch(dc.asPatch(), QString(), 0, revert);
}
QString VcsBaseEditorWidget::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
{
// Go back chunks
for (QTextBlock block = inBlock; block.isValid(); block = block.previous()) {
const QString line = block.text();
if (d->m_diffFilePattern.indexIn(line) != -1) {
QString cap = d->m_diffFilePattern.cap(1);
if (!cap.isEmpty())
return findDiffFile(cap);
}
}
return QString();
}
QString VcsBaseEditorWidget::decorateVersion(const QString &revision) const
{
return revision;
@@ -1502,4 +1522,18 @@ Core::IEditor* VcsBaseEditorWidget::locateEditorByTag(const QString &tag)
} // namespace VcsBase
#if WITH_TESTS
#include <QTest>
void VcsBase::VcsBaseEditorWidget::testDiffFileResolving(VcsBaseEditorWidget *editor)
{
QFETCH(QByteArray, header);
QFETCH(QByteArray, fileName);
QTextDocument doc(QString::fromLatin1(header));
editor->init();
QTextBlock block = doc.lastBlock();
QVERIFY(editor->fileNameFromDiffSpecification(block).endsWith(QString::fromLatin1(fileName)));
}
#endif
#include "vcsbaseeditor.moc"

View File

@@ -38,6 +38,7 @@
QT_BEGIN_NAMESPACE
class QAction;
class QRegExp;
class QTextCodec;
class QTextCursor;
QT_END_NAMESPACE
@@ -99,6 +100,9 @@ protected:
// virtual functions).
explicit VcsBaseEditorWidget(const VcsBaseEditorParameters *type,
QWidget *parent);
// Pattern for diff header. File name must be in the first capture group
void setDiffFilePattern(const QRegExp &pattern);
public:
void init();
@@ -180,6 +184,10 @@ public:
bool setConfigurationWidget(QWidget *w);
QWidget *configurationWidget() const;
// Returns a local file name from the diff file specification
// (text cursor at position above change hunk)
QString fileNameFromDiffSpecification(const QTextBlock &inBlock) const;
/* Tagging editors: Sometimes, an editor should be re-used, for example, when showing
* a diff of the same file with different diff-options. In order to be able to find
* the editor, they get a 'tag' containing type and parameters (dynamic property string). */
@@ -187,7 +195,6 @@ public:
static Core::IEditor* locateEditorByTag(const QString &tag);
static QString editorTag(EditorContentType t, const QString &workingDirectory, const QStringList &files,
const QString &revision = QString());
signals:
// These signals also exist in the opaque editable (IEditor) that is
// handled by the editor manager for convenience. They are emitted
@@ -227,25 +234,20 @@ protected:
/* A helper that can be used to locate a file in a diff in case it
* is relative. Tries to derive the directory from base directory,
* source and version control. */
QString findDiffFile(const QString &f) const;
virtual QString findDiffFile(const QString &f) const;
virtual bool canApplyDiffChunk(const DiffChunk &dc) const;
// Revert a patch chunk. Default implementation uses patch.exe
virtual bool applyDiffChunk(const DiffChunk &dc, bool revert = false) const;
private:
// Implement to return a set of change identifiers in
// annotation mode
virtual QSet<QString> annotationChanges() const = 0;
// Implement to identify a change number at the cursor position
virtual QString changeUnderCursor(const QTextCursor &) const = 0;
// Factory functions for highlighters
virtual QRegExp diffFilePattern() const = 0;
virtual BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes,
const QColor &bg) const = 0;
// Implement to return a local file name from the diff file specification
// (text cursor at position above change hunk)
virtual QString fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const = 0;
// Implement to return decorated annotation change for "Annotate version"
virtual QString decorateVersion(const QString &revision) const;
// Implement to return the previous version[s] of an annotation change
@@ -253,6 +255,8 @@ private:
virtual QStringList annotationPreviousVersions(const QString &revision) const;
// Implement to validate revisions
virtual bool isValidRevision(const QString &revision) const;
private:
// cut out chunk and determine file name.
DiffChunk diffChunk(QTextCursor cursor) const;
@@ -260,6 +264,11 @@ private:
friend class Internal::ChangeTextCursorHandler;
Internal::VcsBaseEditorWidgetPrivate *const d;
#if WITH_TESTS
public:
static void testDiffFileResolving(VcsBaseEditorWidget *editor);
#endif
};
} // namespace VcsBase