Skip to content
Snippets Groups Projects
Commit da6463ee authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

VCS[Mercurial]: Implement annotate previous as for git.

Task-number:   QTCREATORBUG-503
parent e8195c07
No related branches found
No related tags found
No related merge requests found
......@@ -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);
}
......
......@@ -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,
......
......@@ -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;
}
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment