Commit 989e1b5a authored by Brian McGillion's avatar Brian McGillion

Mercurial plugin, merge request with suggested fixes.

parent 0915342d
<plugin name="Mercurial" version="1.2.91" compatVersion="1.2.91">
<vendor>Brian McGillion</vendor>
<copyright>(C) 2008-2009 Brian McGillion</copyright>
<license>
Commercial Usage
Licensees holding valid Qt Commercial licenses may use this plugin in
accordance with the Qt Commercial License Agreement provided with the
Software or, alternatively, in accordance with the terms contained in
a written agreement between you and Nokia.
GNU Lesser General Public License Usage
Alternatively, this plugin may be used under the terms of the GNU Lesser
General Public License version 2.1 as published by the Free Software
Foundation. Please review the following information to
ensure the GNU Lesser General Public License version 2.1 requirements
will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.</license>
<description>Mercurial integration.</description>
<url>http://www.qtsoftware.com</url>
<dependencyList>
<dependency name="TextEditor" version="1.2.91"/>
<dependency name="ProjectExplorer" version="1.2.91"/>
<dependency name="Core" version="1.2.91"/>
<dependency name="VCSBase" version="1.2.91"/>
</dependencyList>
</plugin>
#include "annotationhighlighter.h"
#include "constants.h"
using namespace Mercurial::Internal;
using namespace Mercurial;
MercurialAnnotationHighlighter::MercurialAnnotationHighlighter(const ChangeNumbers &changeNumbers,
QTextDocument *document)
: VCSBase::BaseAnnotationHighlighter(changeNumbers, document),
changeset(Constants::CHANGESETID12)
{
}
QString MercurialAnnotationHighlighter::changeNumber(const QString &block) const
{
if (changeset.indexIn(block) != -1)
return changeset.cap(1);
return QString();
}
#ifndef ANNOTATIONHIGHLIGHTER_H
#define ANNOTATIONHIGHLIGHTER_H
#include <vcsbase/baseannotationhighlighter.h>
namespace Mercurial {
namespace Internal {
class MercurialAnnotationHighlighter : public VCSBase::BaseAnnotationHighlighter
{
public:
explicit MercurialAnnotationHighlighter(const ChangeNumbers &changeNumbers,
QTextDocument *document = 0);
private:
virtual QString changeNumber(const QString &block) const;
QRegExp changeset;
};
} //namespace Internal
}// namespace Mercurial
#endif // ANNOTATIONHIGHLIGHTER_H
#include "clonewizard.h"
#include "clonewizardpage.h"
#include "mercurialplugin.h"
#include "mercurialsettings.h"
#include <QtCore/QDebug>
using namespace Mercurial::Internal;
CloneWizard::CloneWizard(QObject *parent)
: VCSBase::BaseCheckoutWizard(parent),
m_icon(QIcon(":/mercurial/images/hg.png"))
{
}
QIcon CloneWizard::icon() const
{
return m_icon;
}
QString CloneWizard::description() const
{
return tr("Clone a Mercurial repository");
}
QString CloneWizard::name() const
{
return tr("Mercurial Clone");
}
QList<QWizardPage*> CloneWizard::createParameterPages(const QString &path)
{
QList<QWizardPage*> wizardPageList;
CloneWizardPage *page = new CloneWizardPage;
page->setPath(path);
wizardPageList.push_back(page);
return wizardPageList;
}
QSharedPointer<VCSBase::AbstractCheckoutJob> CloneWizard::createJob(const QList<QWizardPage *> &parameterPages,
QString *checkoutPath)
{
const CloneWizardPage *page = qobject_cast<const CloneWizardPage *>(parameterPages.front());
if (!page)
return QSharedPointer<VCSBase::AbstractCheckoutJob>();
MercurialSettings *settings = MercurialPlugin::instance()->settings();
QStringList args = settings->standardArguments();
QString path = page->path();
QString directory = page->directory();
args << "clone" << page->repository() << directory;
*checkoutPath = path + "/" + directory;
return QSharedPointer<VCSBase::AbstractCheckoutJob>(new VCSBase::ProcessCheckoutJob(settings->binary(),
args, path));
}
#ifndef CLONEWIZARD_H
#define CLONEWIZARD_H
#include <vcsbase/basecheckoutwizard.h>
#include <vcsbase/checkoutjobs.h>
#include <QtGui/QIcon>
namespace Mercurial {
namespace Internal {
class CloneWizard : public VCSBase::BaseCheckoutWizard
{
public:
CloneWizard(QObject *parent = 0);
QIcon icon() const;
QString description() const;
QString name() const;
protected:
QList<QWizardPage *> createParameterPages(const QString &path);
QSharedPointer<VCSBase::AbstractCheckoutJob> createJob(const QList<QWizardPage *> &parameterPages,
QString *checkoutPath);
private:
QIcon m_icon;
};
} //namespace Internal
} //namespace Mercurial
#endif // CLONEWIZARD_H
#include "clonewizardpage.h"
using namespace Mercurial::Internal;
CloneWizardPage::CloneWizardPage(QWidget *parent)
: VCSBase::BaseCheckoutWizardPage(parent)
{
setRepositoryLabel("Clone URL:");
}
QString CloneWizardPage::directoryFromRepository(const QString &repository) const
{
//mercruial repositories are generally of the form protocol://repositoryUrl/repository/
//we are just looking for repository.
QString repo = repository.trimmed();
if (repo.endsWith('/'))
repo = repo.remove(-1, 1);
//Take the basename or the repository url
return repo.mid(repo.lastIndexOf('/') + 1);
}
#ifndef CLONEWIZARDPAGE_H
#define CLONEWIZARDPAGE_H
#include <vcsbase/basecheckoutwizardpage.h>
namespace Mercurial {
namespace Internal {
class CloneWizardPage : public VCSBase::BaseCheckoutWizardPage
{
Q_OBJECT
public:
CloneWizardPage(QWidget *parent = 0);
protected:
QString directoryFromRepository(const QString &rrepository) const;
};
} //namespace Internal
} //namespace Mercurial
#endif // CLONEWIZARDPAGE_H
#include "commiteditor.h"
#include "mercurialcommitwidget.h"
#include <vcsbase/submitfilemodel.h>
#include <QtCore/QDebug>
#include <QDir> //TODO REMOVE WHEN BASE FILE CHANGES ARE PULLED
using namespace Mercurial::Internal;
CommitEditor::CommitEditor(const VCSBase::VCSBaseSubmitEditorParameters *parameters, QWidget *parent)
: VCSBase::VCSBaseSubmitEditor(parameters, new MercurialCommitWidget(parent)),
fileModel(0)
{
setDisplayName(tr("Commit Editor"));
}
MercurialCommitWidget *CommitEditor::commitWidget()
{
return static_cast<MercurialCommitWidget *>(widget());
}
void CommitEditor::setFields(const QFileInfo &repositoryRoot, const QString &branch,
const QString &userName, const QString &email,
const QList<QPair<QString, QString> > &repoStatus)
{
MercurialCommitWidget *mercurialWidget = commitWidget();
if (!mercurialWidget)
return;
mercurialWidget->setFields(repositoryRoot.absoluteFilePath(), branch, userName, email);
fileModel = new VCSBase::SubmitFileModel(this);
//TODO Messy tidy this up
typedef QPair<QString, QString> PAIR;
QStringList shouldTrack;
foreach (PAIR status, repoStatus) {
if (status.first == "Untracked")
shouldTrack.append(status.second);
else
fileModel->addFile(status.second, status.first, false);
}
VCSBase::VCSBaseSubmitEditor::filterUntrackedFilesOfProject(repositoryRoot.absoluteFilePath(),
&shouldTrack);
foreach (QString track, shouldTrack) {
foreach (PAIR status, repoStatus) {
if (status.second == track)
fileModel->addFile(status.second, status.first, false);
}
}
setFileModel(fileModel);
}
QString CommitEditor::committerInfo()
{
return commitWidget()->committer();
}
QString CommitEditor::repoRoot()
{
return commitWidget()->repoRoot();
}
#ifndef COMMITEDITOR_H
#define COMMITEDITOR_H
#include <vcsbase/vcsbasesubmiteditor.h>
#include <QtCore/QFileInfo>
namespace VCSBase {
class SubmitFileModel;
}
namespace Mercurial {
namespace Internal {
class MercurialCommitWidget;
class CommitEditor : public VCSBase::VCSBaseSubmitEditor
{
Q_OBJECT
public:
explicit CommitEditor(const VCSBase::VCSBaseSubmitEditorParameters *parameters,
QWidget *parent);
void setFields(const QFileInfo &repositoryRoot, const QString &branch,
const QString &userName, const QString &email,
const QList<QPair<QString, QString> > &repoStatus);
QString committerInfo();
QString repoRoot();
private:
inline MercurialCommitWidget *commitWidget();
VCSBase::SubmitFileModel *fileModel;
};
}
}
#endif // COMMITEDITOR_H
#ifndef CONSTANTS_H
#define CONSTANTS_H
namespace Mercurial {
namespace Constants {
enum { debug = 1 };
const char * const MERCURIAL = "mercurial";
const char * const MECURIALREPO = ".hg";
const char * const MERCURIALDEFAULT = "hg";
//options page items
const char * const MERCURIALPATH = "Mercurial_Path";
const char * const MERCURIALUSERNAME = "Mercurial_Username";
const char * const MERCURIALEMAIL = "Mercurial_Email";
const char * const MERCURIALLOGCOUNT = "Mercurial_LogCount";
const char * const MERCURIALTIMEOUT = "Mercurial_Timeout";
const char * const MERCURIALPROMPTSUBMIT = "Mercurial_PromptOnSubmit";
//changeset identifiers
const char * const CHANGESETID12 = " ([a-f0-9]{12,12}) "; //match 12 hex chars and capture
const char * const CHANGESETID40 = " ([a-f0-9]{40,40}) ";
const char * const CHANGEIDEXACT12 = "[a-f0-9]{12,12}"; //match 12 hex chars a
const char * const CHANGEIDEXACT40 = "[a-f0-9]{40,40}";
const char * const DIFFIDENTIFIER = "^[-+]{3,3} [ab]{1,1}.*"; // match e.g. +++ b/filename
//Errors
const char * const ERRORSTARTING = "Unable to start Mercurial Process";
const char * const TIMEDOUT = "Timed out waiting for Mercurail Process to Finish";
//BaseEditorParameters
const char * const COMMANDLOG = "Mercurial Command Log Editor";
const char * const COMMANDAPP = "application/vnd.nokia.text.scs_mercurial_commandlog";
const char * const COMMANDEXT = "vcsMercurialCommand";
const char * const FILELOG = "Mercurial File Log Editor";
const char * const LOGAPP = "application/vnd.nokia.text.scs_mercurial_log";
const char * const LOGEXT = "vcsMercurialLog";
const char * const ANNOTATELOG = "Mercurial Annotation Editor";
const char * const ANNOTATEAPP = "application/vnd.nokia.text.scs_mercurial_annotatelog";
const char * const ANNOTATEEXT = "vcsMercurialAnnotate";
const char * const DIFFLOG = "Mercurial Diff Editor";
const char * const DIFFAPP = "text/x-patch";
const char * const DIFFEXT = "diff";
//SubmitEditorParameters
const char * const COMMITKIND = "Mercurial Commit Log Editor";
const char * const COMMITMIMETYPE = "application/vnd.nokia.text.scs_mercurial_commitlog";
#ifndef Q_WS_MAC
const char * const MODIFIER = "Alt+";
const char * const MENUKEY = "Alt+H, ";
#else
const char * const MODIFIER = "Meta+";
const char * const MENUKEY = "Meta+H, ";
#endif
//menu items
//File menu actions
const char * const ANNOTATE = "Mercurial.Annotate";
const char * const DIFF = "Mercurial.DiffSingleFile";
const char * const LOG = "Mercurial.LogSingleFile";
const char * const REVERT = "Mercurial.RevertSingleFile";
const char * const STATUS = "Mercurial.Status";
//directory menu Actions
const char * const DIFFMULTI = "Mercurial.Action.DiffMulti";
const char * const REVERTMULTI = "Mercurial.Action.RevertMulti";
const char * const STATUSMULTI = "Mercurial.Action.StatusMulti";
const char * const LOGMULTI = "Mercurial.Action.Logmulti";
//repository menu actions
const char * const PULL = "Mercurial.Action.Pull";
const char * const PUSH = "Mercurial.Action.Push";
const char * const UPDATE = "Mercurial.Action.Update";
const char * const IMPORT = "Mercurial.Action.Import";
const char * const INCOMING = "Mercurial.Action.Incoming";
const char * const OUTGOING = "Mercurial.Action.Outgoing";
const char * const COMMIT = "Mercurial.Action.Commit";
//Repository Management
const char * const MERGE = "Mercurial.Action.Merge";
const char * const BRANCH = "Mercurial.Action.Branch";
const char * const HEADS = "Mercurial.Action.Heads";
const char * const PARENTS = "Mercurial.Action.Parents";
const char * const TAGS = "Mercurial.Action.Tags";
const char * const TIP = "Mercurial.Action.TIP";
const char * const PATHS = "Mercurial.Action.Paths";
//Less commonly used menu actions
const char * const CLONE = "Mercurial.Action.Clone";
const char * const INIT = "Mercurial.Action.Init";
const char * const SERVE = "Mercurial.Action.Serve";
//submit editor actions
const char * const COMMITEDITOR = "Mercurial.Action.Editor.Commit";
const char * const DIFFEDITOR = "Mercurial.Action.Editor.Diff";
} // namespace Constants
} // namespace mercurial
#endif // CONSTANTS_H
TARGET = Mercurial
TEMPLATE = lib
include(../../qtcreatorplugin.pri)
include(mercurial_dependencies.pri)
SOURCES += mercurialplugin.cpp \
optionspage.cpp \
mercurialoutputwindow.cpp \
mercurialcontrol.cpp \
mercurialclient.cpp \
mercurialjobrunner.cpp \
annotationhighlighter.cpp \
mercurialeditor.cpp \
revertdialog.cpp \
srcdestdialog.cpp \
mercurialcommitwidget.cpp \
commiteditor.cpp \
clonewizardpage.cpp \
clonewizard.cpp \
mercurialsettings.cpp
HEADERS += mercurialplugin.h \
constants.h \
optionspage.h \
mercurialoutputwindow.h \
mercurialcontrol.h \
mercurialclient.h \
mercurialjobrunner.h \
annotationhighlighter.h \
mercurialeditor.h \
revertdialog.h \
srcdestdialog.h \
mercurialcommitwidget.h \
commiteditor.h \
clonewizardpage.h \
clonewizard.h \
mercurialsettings.h
OTHER_FILES += Mercurial.pluginspec
FORMS += optionspage.ui \
revertdialog.ui \
srcdestdialog.ui \
mercurialcommitpanel.ui
RESOURCES += mercurial.qrc
<RCC>
<qresource prefix="/mercurial" >
<file>images/hg.png</file>
</qresource>
</RCC>
include(../../plugins/projectexplorer/projectexplorer.pri)
include(../../plugins/texteditor/texteditor.pri)
include(../../plugins/coreplugin/coreplugin.pri)
include(../../plugins/vcsbase/vcsbase.pri)
include(../../libs/utils/utils.pri)
This diff is collapsed.
#ifndef MERCURIALCLIENT_H
#define MERCURIALCLIENT_H
#include <QtCore/QObject>
#include <QtCore/QFileInfo>
#include <QtCore/QByteArray>
#include <QtCore/QPair>
namespace Core {
class ICore;
}
namespace VCSBase{
class VCSBaseEditor;
}
namespace Mercurial {
namespace Internal {
class MercurialJobRunner;
class MercurialClient : public QObject
{
Q_OBJECT
public:
MercurialClient();
~MercurialClient();
bool add(const QString &fileName);
bool remove(const QString &fileName);
bool manifestSync(const QString &filename);
QString branchQuerySync(const QFileInfo &repositoryRoot);
void annotate(const QFileInfo &file);
void diff(const QFileInfo &fileOrDir);
void log(const QFileInfo &fileOrDir);
void import(const QFileInfo &repositoryRoot, const QStringList &files);
void pull(const QFileInfo &repositoryRoot, const QString &repository);
void push(const QFileInfo &repositoryRoot, const QString &repository);
void incoming(const QFileInfo &repositoryRoot, const QString &repository);
void outgoing(const QFileInfo &repositoryRoot);
void status(const QFileInfo &fileOrDir);
void statusWithSignal(const QFileInfo &fileOrDir);
void revert(const QFileInfo &fileOrDir, const QString &revision);
void update(const QFileInfo &repositoryRoot, const QString &revision);
void commit(const QFileInfo &repositoryRoot, const QStringList &files,
const QString &commiterInfo, const QString &commitMessageFile);
static QString findTopLevelForFile(const QFileInfo &file);
signals:
void parsedStatus(const QList<QPair<QString, QString> > &statusList);
public slots:
void view(const QString &source, const QString &id);
void settingsChanged();
private slots:
void statusParser(const QByteArray &data);
private:
bool hgProcessSync(const QFileInfo &file, const QStringList &args,
QByteArray *output=0) const;
MercurialJobRunner *jobManager;
Core::ICore *core;
VCSBase::VCSBaseEditor *createVCSEditor(const QString &kind, QString title,
const QString &source, bool setSourceCodec,
const char *registerDynamicProperty,
const QString &dynamicPropertyValue) const;
};
} //namespace Internal
} //namespace Mercurial
#endif // MERCURIALCLIENT_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Mercurial::Internal::MercurialCommitPanel</class>
<widget class="QWidget" name="Mercurial::Internal::MercurialCommitPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>374</width>
<height>229</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="infoGroup">
<property name="title">
<string>General Information</string>
</property>
<layout class="QFormLayout" name="infoFormLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="repositoryLabelLabel">
<property name="text">
<string>Repository:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="repositoryLabel">
<property name="text">
<string>repository</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="branchLabelLabel">
<property name="text">
<string>Branch:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="branchLabel">
<property name="text">
<string>branch</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="editGroup">
<property name="title">