Commit f9bb4c59 authored by cerf's avatar cerf Committed by Tobias Hunger
Browse files

Added new Bazaar plugin



Merge-request: 229
Reviewed-by: default avatarTobias Hunger <tobias.hunger@nokia.com>
parent 6c1dd96f
<plugin name=\"Bazaar\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
<vendor>Hugues Delorme</vendor>
<copyright>(C) 2010-2011 Hugues Delorme</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>
<category>Version Control</category>
<description>Bazaar integration.</description>
<url>http://qt.nokia.com</url>
<dependencyList>
<dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
<dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
<dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
<dependency name=\"VCSBase\" version=\"$$QTCREATOR_VERSION\"/>
</dependencyList>
</plugin>
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Hugues Delorme
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "annotationhighlighter.h"
#include "constants.h"
using namespace Bazaar::Internal;
using namespace Bazaar;
BazaarAnnotationHighlighter::BazaarAnnotationHighlighter(const ChangeNumbers &changeNumbers,
QTextDocument *document)
: VCSBase::BaseAnnotationHighlighter(changeNumbers, document),
m_changeset(QLatin1String(Constants::CHANGESETID12))
{
}
QString BazaarAnnotationHighlighter::changeNumber(const QString &block) const
{
if (m_changeset.indexIn(block) != -1)
return m_changeset.cap(1);
return QString();
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Hugues Delorme
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#ifndef ANNOTATIONHIGHLIGHTER_H
#define ANNOTATIONHIGHLIGHTER_H
#include <vcsbase/baseannotationhighlighter.h>
#include <QtCore/QRegExp>
namespace Bazaar {
namespace Internal {
class BazaarAnnotationHighlighter : public VCSBase::BaseAnnotationHighlighter
{
public:
explicit BazaarAnnotationHighlighter(const ChangeNumbers &changeNumbers,
QTextDocument *document = 0);
private:
virtual QString changeNumber(const QString &block) const;
QRegExp m_changeset;
};
} //namespace Internal
}// namespace Bazaar
#endif // ANNOTATIONHIGHLIGHTER_H
TARGET = Bazaar
TEMPLATE = lib
include(../../qtcreatorplugin.pri)
include(bazaar_dependencies.pri)
SOURCES += \
bazaarclient.cpp \
bazaarcontrol.cpp \
bazaarplugin.cpp \
optionspage.cpp \
bazaarsettings.cpp \
commiteditor.cpp \
bazaarcommitwidget.cpp \
bazaareditor.cpp \
annotationhighlighter.cpp \
pullorpushdialog.cpp \
branchinfo.cpp \
clonewizardpage.cpp \
clonewizard.cpp \
cloneoptionspanel.cpp
HEADERS += \
bazaarclient.h \
constants.h \
bazaarcontrol.h \
bazaarplugin.h \
optionspage.h \
bazaarsettings.h \
commiteditor.h \
bazaarcommitwidget.h \
bazaareditor.h \
annotationhighlighter.h \
pullorpushdialog.h \
branchinfo.h \
clonewizard.h \
clonewizardpage.h \
cloneoptionspanel.h
FORMS += \
optionspage.ui \
revertdialog.ui \
bazaarcommitpanel.ui \
pullorpushdialog.ui \
cloneoptionspanel.ui
RESOURCES += bazaar.qrc
<RCC>
<qresource prefix="/bazaar" >
<file>images/bazaar.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 file is part of Qt Creator
**
** Copyright (c) 2010 Hugues Delorme
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "bazaarclient.h"
#include "constants.h"
#include <vcsbase/vcsbaseplugin.h>
#include <QDir>
#include <QFileInfo>
#include <QTextStream>
#include <QtDebug>
namespace {
void addBoolArgument(const QVariant &optionValue,
const QString &optionName,
QStringList *arguments)
{
if (arguments == 0)
return;
Q_ASSERT(optionValue.canConvert(QVariant::Bool));
if (optionValue.toBool())
arguments->append(optionName);
}
void addRevisionArgument(const QVariant &optionValue, QStringList *arguments)
{
if (arguments == 0)
return;
Q_ASSERT(optionValue.canConvert(QVariant::String));
const QString revision = optionValue.toString();
if (!revision.isEmpty())
(*arguments) << QLatin1String("-r") << revision;
}
} // Anonymous namespace
namespace Bazaar {
namespace Internal {
BazaarClient::BazaarClient(const VCSBase::VCSBaseClientSettings &settings) :
VCSBase::VCSBaseClient(settings)
{
}
BranchInfo BazaarClient::synchronousBranchQuery(const QString &repositoryRoot) const
{
QFile branchConfFile(repositoryRoot + QDir::separator() +
QLatin1String(Constants::BAZAARREPO) +
QLatin1String("/branch/branch.conf"));
if (!branchConfFile.open(QIODevice::ReadOnly))
return BranchInfo(QString(), false);
QTextStream ts(&branchConfFile);
QString branchLocation;
QString isBranchBound;
const QRegExp branchLocationRx("bound_location\\s*=\\s*(.+)$");
const QRegExp isBranchBoundRx("bound\\s*=\\s*(.+)$");
while (!ts.atEnd() && (branchLocation.isEmpty() || isBranchBound.isEmpty())) {
const QString line = ts.readLine();
if (branchLocationRx.indexIn(line) != -1)
branchLocation = branchLocationRx.cap(1);
else if (isBranchBoundRx.indexIn(line) != -1)
isBranchBound = isBranchBoundRx.cap(1);
}
if (isBranchBound.simplified().toLower() == QLatin1String("true"))
return BranchInfo(branchLocation, true);
return BranchInfo(repositoryRoot, false);
}
QString BazaarClient::findTopLevelForFile(const QFileInfo &file) const
{
const QString repositoryCheckFile =
QLatin1String(Constants::BAZAARREPO) + QLatin1String("/branch-format");
return file.isDir() ?
VCSBase::VCSBasePlugin::findRepositoryForDirectory(file.absoluteFilePath(),
repositoryCheckFile) :
VCSBase::VCSBasePlugin::findRepositoryForDirectory(file.absolutePath(),
repositoryCheckFile);
}
QString BazaarClient::vcsEditorKind(VCSCommand cmd) const
{
switch(cmd) {
case AnnotateCommand : return QLatin1String(Constants::ANNOTATELOG);
case DiffCommand : return QLatin1String(Constants::DIFFLOG);
case LogCommand : return QLatin1String(Constants::FILELOG);
default : return QLatin1String("");
}
return QLatin1String("");
}
QStringList BazaarClient::cloneArguments(const QString &srcLocation,
const QString &dstLocation,
const ExtraCommandOptions &extraOptions) const
{
QStringList args;
// Fetch extra options
foreach (int iOption, extraOptions.keys()) {
const QVariant iOptValue = extraOptions[iOption];
switch (iOption) {
case UseExistingDirCloneOptionId :
::addBoolArgument(iOptValue, QLatin1String("--use-existing-dir"), &args);
break;
case StackedCloneOptionId :
::addBoolArgument(iOptValue, QLatin1String("--stacked"), &args);
break;
case StandAloneCloneOptionId :
::addBoolArgument(iOptValue, QLatin1String("--standalone"), &args);
break;
case BindCloneOptionId :
::addBoolArgument(iOptValue, QLatin1String("--bind"), &args);
break;
case SwitchCloneOptionId :
::addBoolArgument(iOptValue, QLatin1String("--switch"), &args);
break;
case HardLinkCloneOptionId :
::addBoolArgument(iOptValue, QLatin1String("--hardlink"), &args);
break;
case NoTreeCloneOptionId :
::addBoolArgument(iOptValue, QLatin1String("--no-tree"), &args);
break;
case RevisionCloneOptionId :
::addRevisionArgument(iOptValue, &args);
break;
default :
Q_ASSERT(false); // Invalid option !
}
} // end foreach ()
// Add arguments for common options
args << srcLocation;
if (!dstLocation.isEmpty())
args << dstLocation;
return args;
}
QStringList BazaarClient::pullArguments(const QString &srcLocation,
const ExtraCommandOptions &extraOptions) const
{
// Fetch extra options
QStringList args(commonPullOrPushArguments(extraOptions));
foreach (int iOption, extraOptions.keys()) {
const QVariant iOptValue = extraOptions[iOption];
switch (iOption) {
case RememberPullOrPushOptionId : break;
case OverwritePullOrPushOptionId : break;
case RevisionPullOrPushOptionId : break;
case LocalPullOptionId :
::addBoolArgument(iOptValue, QLatin1String("--local"), &args);
break;
default :
Q_ASSERT(false); // Invalid option !
}
} // end foreach ()
// Add arguments for common options
if (!srcLocation.isEmpty())
args << srcLocation;
return args;
}
QStringList BazaarClient::pushArguments(const QString &dstLocation,
const ExtraCommandOptions &extraOptions) const
{
// Fetch extra options
QStringList args(commonPullOrPushArguments(extraOptions));
foreach (int iOption, extraOptions.keys()) {
const QVariant iOptValue = extraOptions[iOption];
switch (iOption) {
case RememberPullOrPushOptionId : break;
case OverwritePullOrPushOptionId : break;
case RevisionPullOrPushOptionId : break;
case UseExistingDirPushOptionId :
::addBoolArgument(iOptValue, QLatin1String("--use-existing-dir"), &args);
break;
case CreatePrefixPushOptionId :
::addBoolArgument(iOptValue, QLatin1String("--create-prefix"), &args);
break;
default :
Q_ASSERT(false); // Invalid option !
}
} // end foreach ()
// Add arguments for common options
if (!dstLocation.isEmpty())
args << dstLocation;
return args;
}
QStringList BazaarClient::commitArguments(const QStringList &files,
const QString &commitMessageFile,
const ExtraCommandOptions &extraOptions) const
{
QStringList args;
// Fetch extra options
foreach (int iOption, extraOptions.keys()) {
const QVariant iOptValue = extraOptions[iOption];
switch (iOption) {
case AuthorCommitOptionId :
{
Q_ASSERT(iOptValue.canConvert(QVariant::String));
const QString committerInfo = iOptValue.toString();
if (!committerInfo.isEmpty())
args << QString("--author=%1").arg(committerInfo);
break;
}
case FixesCommitOptionId :
{
Q_ASSERT(iOptValue.canConvert(QVariant::StringList));
foreach (const QString& iFix, iOptValue.toStringList()) {
if (!iFix.isEmpty())
args << QLatin1String("--fixes") << iFix;
}
break;
}
case LocalCommitOptionId :
::addBoolArgument(iOptValue, QLatin1String("--local"), &args);
break;
default :
Q_ASSERT(false); // Invalid option !
}
} // end foreach ()
// Add arguments for common options
args << QLatin1String("-F") << commitMessageFile;
args << files;
return args;
}
QStringList BazaarClient::importArguments(const QStringList &files) const
{
QStringList args;
if (!files.isEmpty())
args.append(files);
return args;
}
QStringList BazaarClient::updateArguments(const QString &revision) const
{
QStringList args;
if (!revision.isEmpty())
args << QLatin1String("-r") << revision;
return args;
}
QStringList BazaarClient::revertArguments(const QString &file,
const QString &revision) const
{
QStringList args;
if (!revision.isEmpty())
args << QLatin1String("-r") << revision;
if (!file.isEmpty())
args << file;
return args;
}
QStringList BazaarClient::revertAllArguments(const QString &revision) const
{
QStringList args;
if (!revision.isEmpty())
args << QLatin1String("-r") << revision;
return args;
}
QStringList BazaarClient::annotateArguments(const QString &file,
const QString &revision,
int lineNumber) const
{
Q_UNUSED(lineNumber);
QStringList args(QLatin1String("--long"));
if (!revision.isEmpty())
args << QLatin1String("-r") << revision;
return args << file;
}
QStringList BazaarClient::diffArguments(const QStringList &files) const
{
QStringList args;
if (!files.isEmpty())
args.append(files);
return args;
}
QStringList BazaarClient::logArguments(const QStringList &files) const
{
return diffArguments(files);
}
QStringList BazaarClient::statusArguments(const QString &file) const
{
QStringList args;
args.append(QLatin1String("--short"));
if (!file.isEmpty())
args.append(file);
return args;
}
QStringList BazaarClient::viewArguments(const QString &revision) const
{
QStringList args(QLatin1String("log"));
args << QLatin1String("-p") << QLatin1String("--gnu-changelog")
<< QLatin1String("-r") << revision;
return args;
}
QPair<QString, QString> BazaarClient::parseStatusLine(const QString &line) const
{
QPair<QString, QString> status;
if (!line.isEmpty()) {
const QChar flagVersion = line[0];
if (flagVersion == QLatin1Char('+'))
status.first = QLatin1String("Versioned");
else if (flagVersion == QLatin1Char('-'))
status.first = QLatin1String("Unversioned");
else if (flagVersion == QLatin1Char('R'))
status.first = QLatin1String("Renamed");
else if (flagVersion == QLatin1Char('?'))
status.first = QLatin1String("Unknown");
else if (flagVersion == QLatin1Char('X'))
status.first = QLatin1String("Nonexistent");
else if (flagVersion == QLatin1Char('C'))
status.first = QLatin1String("Conflict");
else if (flagVersion == QLatin1Char('P'))
status.first = QLatin1String("PendingMerge");
const int lineLength = line.length();
if (lineLength >= 2) {
const QChar flagContents = line[1];
if (flagContents == QLatin1Char('N'))
status.first = QLatin1String("Created");
else if (flagContents == QLatin1Char('D'))
status.first = QLatin1String("Deleted");
else if (flagContents == QLatin1Char('K'))
status.first = QLatin1String("KindChanged");
else if (flagContents == QLatin1Char('M'))
status.first = QLatin1String("Modified");
}
if (lineLength >= 3) {
const QChar flagExec = line[2];
if (flagExec == QLatin1Char('*'))
status.first = QLatin1String("ExecuteBitChanged");
}
// The status string should be similar to "xxx file_with_changes"
// so just should take the file name part and store it
status.second = line.mid(4);
}
return status;
}
QStringList BazaarClient::commonPullOrPushArguments(const ExtraCommandOptions &extraOptions) const
{
QStringList args;
foreach (int iOption, extraOptions.keys()) {
const QVariant iOptValue = extraOptions[iOption];
switch (iOption) {
case RememberPullOrPushOptionId :
::addBoolArgument(iOptValue, QLatin1String("--remember"), &args);
break;
case OverwritePullOrPushOptionId :
::addBoolArgument(iOptValue, QLatin1String("--overwrite"), &args);
break;
case RevisionPullOrPushOptionId :
::addRevisionArgument(iOptValue, &args);
break;
default :
break; // Unknown option, do nothing
}
} // end foreach ()
return args;
}
} //namespace Internal
} // namespace Bazaar
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Hugues Delorme
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.