summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@nokia.com>2010-01-08 09:44:07 +0100
committerFriedemann Kleint <Friedemann.Kleint@nokia.com>2010-01-08 09:44:07 +0100
commitda6463ee2f856cea6086f8a4938a371a81f75fdf (patch)
tree2de603f6abed02adf7d3562c6f75091d6714e6b1 /src
parente8195c0766d6b9bde3f529ff670765304f0ae104 (diff)
downloadqt-creator-da6463ee2f856cea6086f8a4938a371a81f75fdf.tar.gz
VCS[Mercurial]: Implement annotate previous as for git.
Task-number: QTCREATORBUG-503
Diffstat (limited to 'src')
-rw-r--r--src/plugins/mercurial/mercurialclient.cpp110
-rw-r--r--src/plugins/mercurial/mercurialclient.h12
-rw-r--r--src/plugins/mercurial/mercurialeditor.cpp20
-rw-r--r--src/plugins/mercurial/mercurialeditor.h1
-rw-r--r--src/plugins/mercurial/mercurialplugin.cpp60
-rw-r--r--src/plugins/mercurial/mercurialplugin.h3
6 files changed, 173 insertions, 33 deletions
diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp
index 2f5ba8ff58..2e15c6a8cd 100644
--- a/src/plugins/mercurial/mercurialclient.cpp
+++ b/src/plugins/mercurial/mercurialclient.cpp
@@ -159,8 +159,116 @@ QString MercurialClient::branchQuerySync(const QString &repositoryRoot)
return QLatin1String("Unknown Branch");
}
-void MercurialClient::slotAnnotateRevisionRequested(const QString &source, const QString &change, int lineNumber)
+static inline QString msgParentRevisionFailed(const QString &workingDirectory,
+ const QString &revision,
+ const QString &why)
{
+ return MercurialClient::tr("Unable to find parent revisions of %1 in %2: %3").arg(revision, workingDirectory, why);
+}
+
+static inline QString msgParseParentsOutputFailed(const QString &output)
+{
+ return MercurialClient::tr("Cannot parse output: %1").arg(output);
+}
+
+bool MercurialClient::parentRevisionsSync(const QString &workingDirectory,
+ const QString &file /* = QString() */,
+ const QString &revision,
+ QStringList *parents)
+{
+ parents->clear();
+ QStringList args;
+ args << QLatin1String("parents") << QLatin1String("-r") <<revision;
+ if (!file.isEmpty())
+ args << file;
+ QByteArray outputData;
+ if (!executeHgSynchronously(workingDirectory, args, &outputData))
+ return false;
+ QString output = QString::fromLocal8Bit(outputData);
+ output.remove(QLatin1Char('\r'));
+ /* Looks like: \code
+changeset: 0:031a48610fba
+user: ...
+\endcode */
+ // Obtain first line and split by blank-delimited tokens
+ VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance();
+ const QStringList lines = output.split(QLatin1Char('\n'));
+ if (lines.size() < 1) {
+ outputWindow->appendSilently(msgParentRevisionFailed(workingDirectory, revision, msgParseParentsOutputFailed(output)));
+ return false;
+ }
+ QStringList changeSets = lines.front().simplified().split(QLatin1Char(' '));
+ if (changeSets.size() < 2) {
+ outputWindow->appendSilently(msgParentRevisionFailed(workingDirectory, revision, msgParseParentsOutputFailed(output)));
+ return false;
+ }
+ // Remove revision numbers
+ const QChar colon = QLatin1Char(':');
+ const QStringList::iterator end = changeSets.end();
+ QStringList::iterator it = changeSets.begin();
+ for (++it; it != end; ++it) {
+ const int colonIndex = it->indexOf(colon);
+ if (colonIndex != -1)
+ parents->push_back(it->mid(colonIndex + 1));
+ }
+ return true;
+}
+
+// Describe a change using an optional format
+bool MercurialClient::shortDescriptionSync(const QString &workingDirectory,
+ const QString &revision,
+ const QString &format,
+ QString *description)
+{
+ description->clear();
+ QStringList args;
+ args << QLatin1String("log") << QLatin1String("-r") <<revision;
+ if (!format.isEmpty())
+ args << QLatin1String("--template") << format;
+ QByteArray outputData;
+ if (!executeHgSynchronously(workingDirectory, args, &outputData))
+ return false;
+ *description = QString::fromLocal8Bit(outputData);
+ description->remove(QLatin1Char('\r'));
+ if (description->endsWith(QLatin1Char('\n')))
+ description->truncate(description->size() - 1);
+ return true;
+}
+
+// Default format: "SHA1 (author summmary)"
+static const char defaultFormatC[] = "{node} ({author|person} {desc|firstline})";
+
+bool MercurialClient::shortDescriptionSync(const QString &workingDirectory,
+ const QString &revision,
+ QString *description)
+{
+ if (!shortDescriptionSync(workingDirectory, revision, QLatin1String(defaultFormatC), description))
+ return false;
+ description->remove(QLatin1Char('\n'));
+ return true;
+}
+
+// Convenience to format a list of changes
+bool MercurialClient::shortDescriptionsSync(const QString &workingDirectory, const QStringList &revisions,
+ QStringList *descriptions)
+{
+ descriptions->clear();
+ foreach(const QString &revision, revisions) {
+ QString description;
+ if (!shortDescriptionSync(workingDirectory, revision, &description))
+ return false;
+ descriptions->push_back(description);
+ }
+ return true;
+}
+
+void MercurialClient::slotAnnotateRevisionRequested(const QString &source, QString change, int lineNumber)
+{
+ // This might be invoked with a verbose revision description
+ // "SHA1 author subject" from the annotation context menu. Strip the rest.
+ const int blankPos = change.indexOf(QLatin1Char(' '));
+ if (blankPos != -1)
+ change.truncate(blankPos);
const QFileInfo fi(source);
annotate(fi.absolutePath(), fi.fileName(), change, lineNumber);
}
diff --git a/src/plugins/mercurial/mercurialclient.h b/src/plugins/mercurial/mercurialclient.h
index 0a59b83a1d..53fc0e58d0 100644
--- a/src/plugins/mercurial/mercurialclient.h
+++ b/src/plugins/mercurial/mercurialclient.h
@@ -64,6 +64,16 @@ public:
bool remove(const QString &workingDir, const QString &fileName);
bool manifestSync(const QString &repository, const QString &filename);
QString branchQuerySync(const QString &repositoryRoot);
+ bool parentRevisionsSync(const QString &workingDirectory,
+ const QString &file /* = QString() */,
+ const QString &revision,
+ QStringList *parents);
+ bool shortDescriptionSync(const QString &workingDirectory, const QString &revision,
+ const QString &format /* = QString() */, QString *description);
+ bool shortDescriptionSync(const QString &workingDirectory, const QString &revision,
+ QString *description);
+ bool shortDescriptionsSync(const QString &workingDirectory, const QStringList &revisions,
+ QStringList *descriptions);
void annotate(const QString &workingDir, const QString &files,
const QString revision = QString(), int lineNumber = -1);
void diff(const QString &workingDir, const QStringList &files = QStringList());
@@ -95,7 +105,7 @@ public slots:
private slots:
void statusParser(const QByteArray &data);
- void slotAnnotateRevisionRequested(const QString &source, const QString &change, int lineNumber);
+ void slotAnnotateRevisionRequested(const QString &source, QString change, int lineNumber);
private:
bool executeHgSynchronously(const QString &workingDir,
diff --git a/src/plugins/mercurial/mercurialeditor.cpp b/src/plugins/mercurial/mercurialeditor.cpp
index 9315c3dad2..e38d30b886 100644
--- a/src/plugins/mercurial/mercurialeditor.cpp
+++ b/src/plugins/mercurial/mercurialeditor.cpp
@@ -31,6 +31,7 @@
#include "annotationhighlighter.h"
#include "constants.h"
#include "mercurialplugin.h"
+#include "mercurialclient.h"
#include <coreplugin/editormanager/editormanager.h>
#include <vcsbase/diffhighlighter.h>
@@ -53,6 +54,7 @@ MercurialEditor::MercurialEditor(const VCSBase::VCSBaseEditorParameters *type, Q
changesetIdentifier40(QLatin1String(Constants::CHANGESETID40)),
diffIdentifier(QLatin1String(Constants::DIFFIDENTIFIER))
{
+ setAnnotateRevisionTextFormat(tr("Annotate %1"));
}
QSet<QString> MercurialEditor::annotationChanges() const
@@ -110,3 +112,21 @@ QString MercurialEditor::fileNameFromDiffSpecification(const QTextBlock &diffFil
}
return QString();
}
+
+QStringList MercurialEditor::annotationPreviousVersions(const QString &revision) const
+{
+ MercurialClient *client = MercurialPlugin::instance()->client();
+ QStringList parents;
+ const QFileInfo fi(source());
+ const QString workingDirectory = fi.absolutePath();
+ // Retrieve parent revisions
+ QStringList revisions;
+ if (!client->parentRevisionsSync(workingDirectory, fi.fileName(), revision, &revisions))
+ return QStringList();
+ // Format with short summary
+ QStringList descriptions;
+ if (!client->shortDescriptionsSync(workingDirectory, revisions, &descriptions))
+ return QStringList();
+ return descriptions;
+}
+
diff --git a/src/plugins/mercurial/mercurialeditor.h b/src/plugins/mercurial/mercurialeditor.h
index ac5c357338..c74e6e48c8 100644
--- a/src/plugins/mercurial/mercurialeditor.h
+++ b/src/plugins/mercurial/mercurialeditor.h
@@ -48,6 +48,7 @@ private:
virtual VCSBase::DiffHighlighter *createDiffHighlighter() const;
virtual VCSBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes) const;
virtual QString fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const;
+ virtual QStringList annotationPreviousVersions(const QString &revision) const;
const QRegExp exactIdentifier12;
const QRegExp exactIdentifier40;
diff --git a/src/plugins/mercurial/mercurialplugin.cpp b/src/plugins/mercurial/mercurialplugin.cpp
index c9eb4ba344..29c9f0f8d2 100644
--- a/src/plugins/mercurial/mercurialplugin.cpp
+++ b/src/plugins/mercurial/mercurialplugin.cpp
@@ -117,7 +117,7 @@ MercurialPlugin *MercurialPlugin::m_instance = 0;
MercurialPlugin::MercurialPlugin() :
VCSBase::VCSBasePlugin(QLatin1String(Constants::COMMITKIND)),
optionsPage(0),
- client(0),
+ m_client(0),
changeLog(0),
m_menuAction(0)
{
@@ -126,9 +126,9 @@ MercurialPlugin::MercurialPlugin() :
MercurialPlugin::~MercurialPlugin()
{
- if (client) {
- delete client;
- client = 0;
+ if (m_client) {
+ delete m_client;
+ m_client = 0;
}
deleteCommitLog();
@@ -140,7 +140,7 @@ bool MercurialPlugin::initialize(const QStringList & /* arguments */, QString *
{
typedef VCSBase::VCSEditorFactory<MercurialEditor> MercurialEditorFactory;
- VCSBase::VCSBasePlugin::initialize(new MercurialControl(client));
+ VCSBase::VCSBasePlugin::initialize(new MercurialControl(m_client));
core = Core::ICore::instance();
actionManager = core->actionManager();
@@ -149,15 +149,15 @@ bool MercurialPlugin::initialize(const QStringList & /* arguments */, QString *
addAutoReleasedObject(optionsPage);
mercurialSettings.readSettings(core->settings());
- client = new MercurialClient();
- connect(optionsPage, SIGNAL(settingsChanged()), client, SLOT(settingsChanged()));
+ m_client = new MercurialClient();
+ connect(optionsPage, SIGNAL(settingsChanged()), m_client, SLOT(settingsChanged()));
- connect(client, SIGNAL(changed(QVariant)), versionControl(), SLOT(changed(QVariant)));
+ connect(m_client, SIGNAL(changed(QVariant)), versionControl(), SLOT(changed(QVariant)));
static const char *describeSlot = SLOT(view(QString,QString));
const int editorCount = sizeof(editorParameters)/sizeof(VCSBase::VCSBaseEditorParameters);
for (int i = 0; i < editorCount; i++)
- addAutoReleasedObject(new MercurialEditorFactory(editorParameters + i, client, describeSlot));
+ addAutoReleasedObject(new MercurialEditorFactory(editorParameters + i, m_client, describeSlot));
addAutoReleasedObject(new VCSBase::VCSSubmitEditorFactory<CommitEditor>(&submitEditorParameters));
@@ -258,21 +258,21 @@ void MercurialPlugin::annotateCurrentFile()
{
const VCSBase::VCSBasePluginState state = currentState();
QTC_ASSERT(state.hasFile(), return)
- client->annotate(state.currentFileTopLevel(), state.relativeCurrentFile());
+ m_client->annotate(state.currentFileTopLevel(), state.relativeCurrentFile());
}
void MercurialPlugin::diffCurrentFile()
{
const VCSBase::VCSBasePluginState state = currentState();
QTC_ASSERT(state.hasFile(), return)
- client->diff(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile()));
+ m_client->diff(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile()));
}
void MercurialPlugin::logCurrentFile()
{
const VCSBase::VCSBasePluginState state = currentState();
QTC_ASSERT(state.hasFile(), return)
- client->log(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile()), true);
+ m_client->log(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile()), true);
}
void MercurialPlugin::revertCurrentFile()
@@ -283,14 +283,14 @@ void MercurialPlugin::revertCurrentFile()
RevertDialog reverter;
if (reverter.exec() != QDialog::Accepted)
return;
- client->revertFile(state.currentFileTopLevel(), state.relativeCurrentFile(), reverter.revision());
+ m_client->revertFile(state.currentFileTopLevel(), state.relativeCurrentFile(), reverter.revision());
}
void MercurialPlugin::statusCurrentFile()
{
const VCSBase::VCSBasePluginState state = currentState();
QTC_ASSERT(state.hasFile(), return)
- client->status(state.currentFileTopLevel(), state.relativeCurrentFile());
+ m_client->status(state.currentFileTopLevel(), state.relativeCurrentFile());
}
void MercurialPlugin::createDirectoryActions(const QList<int> &context)
@@ -327,14 +327,14 @@ void MercurialPlugin::diffRepository()
{
const VCSBase::VCSBasePluginState state = currentState();
QTC_ASSERT(state.hasTopLevel(), return)
- client->diff(state.topLevel());
+ m_client->diff(state.topLevel());
}
void MercurialPlugin::logRepository()
{
const VCSBase::VCSBasePluginState state = currentState();
QTC_ASSERT(state.hasTopLevel(), return)
- client->log(state.topLevel());
+ m_client->log(state.topLevel());
}
void MercurialPlugin::revertMulti()
@@ -345,7 +345,7 @@ void MercurialPlugin::revertMulti()
RevertDialog reverter;
if (reverter.exec() != QDialog::Accepted)
return;
- client->revertRepository(state.topLevel(), reverter.revision());
+ m_client->revertRepository(state.topLevel(), reverter.revision());
}
void MercurialPlugin::statusMulti()
@@ -353,7 +353,7 @@ void MercurialPlugin::statusMulti()
const VCSBase::VCSBasePluginState state = currentState();
QTC_ASSERT(state.hasTopLevel(), return)
- client->status(state.topLevel());
+ m_client->status(state.topLevel());
}
void MercurialPlugin::createRepositoryActions(const QList<int> &context)
@@ -411,7 +411,7 @@ void MercurialPlugin::pull()
dialog.setWindowTitle(tr("Pull Source"));
if (dialog.exec() != QDialog::Accepted)
return;
- client->pull(state.topLevel(), dialog.getRepositoryString());
+ m_client->pull(state.topLevel(), dialog.getRepositoryString());
}
void MercurialPlugin::push()
@@ -423,7 +423,7 @@ void MercurialPlugin::push()
dialog.setWindowTitle(tr("Push Destination"));
if (dialog.exec() != QDialog::Accepted)
return;
- client->push(state.topLevel(), dialog.getRepositoryString());
+ m_client->push(state.topLevel(), dialog.getRepositoryString());
}
void MercurialPlugin::update()
@@ -435,7 +435,7 @@ void MercurialPlugin::update()
updateDialog.setWindowTitle(tr("Update"));
if (updateDialog.exec() != QDialog::Accepted)
return;
- client->update(state.topLevel(), updateDialog.revision());
+ m_client->update(state.topLevel(), updateDialog.revision());
}
void MercurialPlugin::import()
@@ -451,7 +451,7 @@ void MercurialPlugin::import()
return;
const QStringList fileNames = importDialog.selectedFiles();
- client->import(state.topLevel(), fileNames);
+ m_client->import(state.topLevel(), fileNames);
}
void MercurialPlugin::incoming()
@@ -463,14 +463,14 @@ void MercurialPlugin::incoming()
dialog.setWindowTitle(tr("Incoming Source"));
if (dialog.exec() != QDialog::Accepted)
return;
- client->incoming(state.topLevel(), dialog.getRepositoryString());
+ m_client->incoming(state.topLevel(), dialog.getRepositoryString());
}
void MercurialPlugin::outgoing()
{
const VCSBase::VCSBasePluginState state = currentState();
QTC_ASSERT(state.hasTopLevel(), return)
- client->outgoing(state.topLevel());
+ m_client->outgoing(state.topLevel());
}
void MercurialPlugin::createSubmitEditorActions()
@@ -502,9 +502,9 @@ void MercurialPlugin::commit()
m_submitRepository = state.topLevel();
- connect(client, SIGNAL(parsedStatus(QList<QPair<QString,QString> >)),
+ connect(m_client, SIGNAL(parsedStatus(QList<QPair<QString,QString> >)),
this, SLOT(showCommitWidget(QList<QPair<QString,QString> >)));
- client->statusWithSignal(m_submitRepository);
+ m_client->statusWithSignal(m_submitRepository);
}
void MercurialPlugin::showCommitWidget(const QList<QPair<QString, QString> > &status)
@@ -512,7 +512,7 @@ void MercurialPlugin::showCommitWidget(const QList<QPair<QString, QString> > &st
VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance();
//Once we receive our data release the connection so it can be reused elsewhere
- disconnect(client, SIGNAL(parsedStatus(QList<QPair<QString,QString> >)),
+ disconnect(m_client, SIGNAL(parsedStatus(QList<QPair<QString,QString> >)),
this, SLOT(showCommitWidget(QList<QPair<QString,QString> >)));
if (status.isEmpty()) {
@@ -547,7 +547,7 @@ void MercurialPlugin::showCommitWidget(const QList<QPair<QString, QString> > &st
const QString msg = tr("Commit changes for \"%1\".").arg(m_submitRepository);
commitEditor->setDisplayName(msg);
- QString branch = client->branchQuerySync(m_submitRepository);
+ QString branch = m_client->branchQuerySync(m_submitRepository);
commitEditor->setFields(m_submitRepository, branch, mercurialSettings.userName(),
mercurialSettings.email(), status);
@@ -560,7 +560,7 @@ void MercurialPlugin::showCommitWidget(const QList<QPair<QString, QString> > &st
void MercurialPlugin::diffFromEditorSelected(const QStringList &files)
{
- client->diff(m_submitRepository, files);
+ m_client->diff(m_submitRepository, files);
}
void MercurialPlugin::commitFromEditor()
@@ -604,7 +604,7 @@ bool MercurialPlugin::submitEditorAboutToClose(VCSBase::VCSBaseSubmitEditor *sub
editorFile->save();
core->fileManager()->unblockFileChange(editorFile);
- client->commit(commitEditor->repoRoot(), files, commitEditor->committerInfo(),
+ m_client->commit(commitEditor->repoRoot(), files, commitEditor->committerInfo(),
editorFile->fileName());
}
return true;
diff --git a/src/plugins/mercurial/mercurialplugin.h b/src/plugins/mercurial/mercurialplugin.h
index c11d5590a0..6b6e9f5071 100644
--- a/src/plugins/mercurial/mercurialplugin.h
+++ b/src/plugins/mercurial/mercurialplugin.h
@@ -79,6 +79,7 @@ public:
bool initialize(const QStringList &arguments, QString *error_message);
void extensionsInitialized();
static MercurialPlugin *instance() { return m_instance; }
+ MercurialClient *client() const { return m_client; }
QStringList standardArguments() const;
@@ -145,7 +146,7 @@ private:
static MercurialPlugin *m_instance;
MercurialSettings mercurialSettings;
OptionsPage *optionsPage;
- MercurialClient *client;
+ MercurialClient *m_client;
Core::ICore *core;
Core::ActionManager *actionManager;