forked from qt-creator/qt-creator
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:
committed by
Orgad Shaneh
parent
57ee50d52f
commit
7b39f41c05
@@ -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();
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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))
|
||||
|
@@ -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;
|
||||
|
@@ -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>
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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";
|
||||
|
@@ -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());
|
||||
|
@@ -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
|
||||
|
@@ -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,58 +107,20 @@ 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);
|
||||
const QString fileName = m_plugin->fileNameFromPerforceName(f.trimmed(), false, &errorMessage);
|
||||
if (fileName.isEmpty())
|
||||
qWarning("%s", qPrintable(errorMessage));
|
||||
return fileName;
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QStringList PerforceEditor::annotationPreviousVersions(const QString &v) const
|
||||
{
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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"
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user