forked from qt-creator/qt-creator
Refactored the Mercurial plugin
Refactored the mercurial plugin which led to new vcsbase common tools (VCSBaseClient, VCSBaseClientSettings and VCSJobRunner) Merge-request: 229 Reviewed-by: Tobias Hunger <tobias.hunger@nokia.com>
This commit is contained in:
@@ -32,81 +32,25 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "mercurialclient.h"
|
||||
#include "mercurialjobrunner.h"
|
||||
#include "constants.h"
|
||||
#include "mercurialsettings.h"
|
||||
#include "mercurialplugin.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/synchronousprocess.h>
|
||||
#include <vcsbase/vcsbaseeditor.h>
|
||||
#include <vcsbase/vcsbaseoutputwindow.h>
|
||||
#include <vcsbase/vcsbaseplugin.h>
|
||||
#include <vcsbase/vcsjobrunner.h>
|
||||
#include <utils/synchronousprocess.h>
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QTextCodec>
|
||||
#include <QtCore/QtDebug>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QMetaType>
|
||||
|
||||
Q_DECLARE_METATYPE(QVariant)
|
||||
|
||||
inline Core::IEditor* locateEditor(const Core::ICore *core, const char *property, const QString &entry)
|
||||
{
|
||||
foreach (Core::IEditor *ed, core->editorManager()->openedEditors())
|
||||
if (ed->file()->property(property).toString() == entry)
|
||||
return ed;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char nonInteractiveOptionC[] = "--noninteractive";
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QTextCodec>
|
||||
#include <QTextStream>
|
||||
#include <QVariant>
|
||||
|
||||
namespace Mercurial {
|
||||
namespace Internal {
|
||||
|
||||
MercurialClient::MercurialClient() :
|
||||
jobManager(0),
|
||||
core(Core::ICore::instance())
|
||||
MercurialClient::MercurialClient(const VCSBase::VCSBaseClientSettings &settings) :
|
||||
VCSBase::VCSBaseClient(settings)
|
||||
{
|
||||
qRegisterMetaType<QVariant>();
|
||||
}
|
||||
|
||||
MercurialClient::~MercurialClient()
|
||||
{
|
||||
if (jobManager) {
|
||||
delete jobManager;
|
||||
jobManager = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool MercurialClient::add(const QString &workingDir, const QString &filename)
|
||||
{
|
||||
QStringList args;
|
||||
args << QLatin1String("add") << filename;
|
||||
QByteArray stdOut;
|
||||
return executeHgFullySynchronously(workingDir, args, &stdOut);
|
||||
}
|
||||
|
||||
bool MercurialClient::remove(const QString &workingDir, const QString &filename)
|
||||
{
|
||||
QStringList args;
|
||||
args << QLatin1String("remove") << filename;
|
||||
QByteArray stdOut;
|
||||
return executeHgFullySynchronously(workingDir, args, &stdOut);
|
||||
}
|
||||
|
||||
bool MercurialClient::move(const QString &workingDir, const QString &from, const QString &to)
|
||||
{
|
||||
QStringList args;
|
||||
args << QLatin1String("rename") << from << to;
|
||||
QByteArray stdOut;
|
||||
return executeHgFullySynchronously(workingDir, args, &stdOut);
|
||||
}
|
||||
|
||||
bool MercurialClient::manifestSync(const QString &repository, const QString &relativeFilename)
|
||||
@@ -115,7 +59,7 @@ bool MercurialClient::manifestSync(const QString &repository, const QString &rel
|
||||
const QStringList args(QLatin1String("manifest"));
|
||||
|
||||
QByteArray output;
|
||||
executeHgFullySynchronously(repository, args, &output);
|
||||
vcsFullySynchronousExec(repository, args, &output);
|
||||
const QDir repositoryDir(repository);
|
||||
const QFileInfo needle = QFileInfo(repositoryDir, relativeFilename);
|
||||
|
||||
@@ -128,62 +72,62 @@ bool MercurialClient::manifestSync(const QString &repository, const QString &rel
|
||||
return false;
|
||||
}
|
||||
|
||||
Utils::SynchronousProcessResponse
|
||||
MercurialClient::executeHgSynchronously(const QString &workingDirectory,
|
||||
const QStringList &hgArgs,
|
||||
unsigned flags,
|
||||
QTextCodec *outputCodec)
|
||||
//bool MercurialClient::clone(const QString &directory, const QString &url)
|
||||
bool MercurialClient::synchronousClone(const QString &workingDir,
|
||||
const QString &srcLocation,
|
||||
const QString &dstLocation,
|
||||
const ExtraCommandOptions &extraOptions)
|
||||
{
|
||||
const MercurialSettings &settings = MercurialPlugin::instance()->settings();
|
||||
const QString binary = settings.binary();
|
||||
const QStringList arguments = settings.standardArguments() + hgArgs;
|
||||
return VCSBase::VCSBasePlugin::runVCS(workingDirectory, binary, arguments,
|
||||
settings.timeoutMilliSeconds(),
|
||||
flags, outputCodec);
|
||||
}
|
||||
Q_UNUSED(workingDir);
|
||||
Q_UNUSED(extraOptions);
|
||||
QDir workingDirectory(srcLocation);
|
||||
QByteArray output;
|
||||
const unsigned flags = VCSBase::VCSBasePlugin::SshPasswordPrompt |
|
||||
VCSBase::VCSBasePlugin::ShowStdOutInLogWindow |
|
||||
VCSBase::VCSBasePlugin::ShowSuccessMessage;
|
||||
|
||||
bool MercurialClient::executeHgFullySynchronously(const QString &workingDir,
|
||||
const QStringList &args,
|
||||
QByteArray *output) const
|
||||
{
|
||||
QProcess hgProcess;
|
||||
if (!workingDir.isEmpty())
|
||||
hgProcess.setWorkingDirectory(workingDir);
|
||||
MercurialJobRunner::setProcessEnvironment(hgProcess);
|
||||
if (workingDirectory.exists()) {
|
||||
// Let's make first init
|
||||
QStringList arguments(QLatin1String("init"));
|
||||
if (!vcsFullySynchronousExec(workingDirectory.path(), arguments, &output)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const MercurialSettings &settings = MercurialPlugin::instance()->settings();
|
||||
const QString binary = settings.binary();
|
||||
const QStringList arguments = settings.standardArguments() + args;
|
||||
// Then pull remote repository
|
||||
arguments.clear();
|
||||
arguments << QLatin1String("pull") << dstLocation;
|
||||
const Utils::SynchronousProcessResponse resp1 =
|
||||
vcsSynchronousExec(workingDirectory.path(), arguments, flags);
|
||||
if (resp1.result != Utils::SynchronousProcessResponse::Finished) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance();
|
||||
outputWindow->appendCommand(workingDir, binary, args);
|
||||
// By now, there is no hgrc file -> create it
|
||||
QFile hgrc(workingDirectory.path()+"/.hg/hgrc");
|
||||
hgrc.open(QIODevice::WriteOnly);
|
||||
hgrc.write(QString("[paths]\ndefault = %1\n").arg(dstLocation).toUtf8());
|
||||
hgrc.close();
|
||||
|
||||
hgProcess.start(binary, arguments);
|
||||
|
||||
if (!hgProcess.waitForStarted()) {
|
||||
outputWindow->appendError(MercurialJobRunner::msgStartFailed(binary, hgProcess.errorString()));
|
||||
return false;
|
||||
// And last update repository
|
||||
arguments.clear();
|
||||
arguments << QLatin1String("update");
|
||||
const Utils::SynchronousProcessResponse resp2 =
|
||||
vcsSynchronousExec(workingDirectory.path(), arguments, flags);
|
||||
return resp2.result == Utils::SynchronousProcessResponse::Finished;
|
||||
} else {
|
||||
QStringList arguments(QLatin1String("clone"));
|
||||
arguments << dstLocation << workingDirectory.dirName();
|
||||
workingDirectory.cdUp();
|
||||
const Utils::SynchronousProcessResponse resp =
|
||||
vcsSynchronousExec(workingDirectory.path(), arguments, flags);
|
||||
return resp.result == Utils::SynchronousProcessResponse::Finished;
|
||||
}
|
||||
|
||||
hgProcess.closeWriteChannel();
|
||||
|
||||
QByteArray stdErr;
|
||||
if (!Utils::SynchronousProcess::readDataFromProcess(hgProcess, settings.timeoutMilliSeconds(),
|
||||
output, &stdErr, true)) {
|
||||
Utils::SynchronousProcess::stopProcess(hgProcess);
|
||||
outputWindow->appendError(MercurialJobRunner::msgTimeout(settings.timeoutSeconds()));
|
||||
return false;
|
||||
}
|
||||
if (!stdErr.isEmpty())
|
||||
outputWindow->append(QString::fromLocal8Bit(stdErr));
|
||||
|
||||
return hgProcess.exitStatus() == QProcess::NormalExit && hgProcess.exitCode() == 0;
|
||||
}
|
||||
|
||||
QString MercurialClient::branchQuerySync(const QString &repositoryRoot)
|
||||
{
|
||||
QByteArray output;
|
||||
if (executeHgFullySynchronously(repositoryRoot, QStringList(QLatin1String("branch")), &output))
|
||||
if (vcsFullySynchronousExec(repositoryRoot, QStringList(QLatin1String("branch")), &output))
|
||||
return QTextCodec::codecForLocale()->toUnicode(output).trimmed();
|
||||
|
||||
return QLatin1String("Unknown Branch");
|
||||
@@ -213,7 +157,7 @@ bool MercurialClient::parentRevisionsSync(const QString &workingDirectory,
|
||||
if (!file.isEmpty())
|
||||
args << file;
|
||||
QByteArray outputData;
|
||||
if (!executeHgFullySynchronously(workingDirectory, args, &outputData))
|
||||
if (!vcsFullySynchronousExec(workingDirectory, args, &outputData))
|
||||
return false;
|
||||
QString output = QString::fromLocal8Bit(outputData);
|
||||
output.remove(QLatin1Char('\r'));
|
||||
@@ -257,7 +201,7 @@ bool MercurialClient::shortDescriptionSync(const QString &workingDirectory,
|
||||
if (!format.isEmpty())
|
||||
args << QLatin1String("--template") << format;
|
||||
QByteArray outputData;
|
||||
if (!executeHgFullySynchronously(workingDirectory, args, &outputData))
|
||||
if (!vcsFullySynchronousExec(workingDirectory, args, &outputData))
|
||||
return false;
|
||||
*description = QString::fromLocal8Bit(outputData);
|
||||
description->remove(QLatin1Char('\r'));
|
||||
@@ -293,260 +237,6 @@ bool MercurialClient::shortDescriptionsSync(const QString &workingDirectory, con
|
||||
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);
|
||||
}
|
||||
|
||||
void MercurialClient::annotate(const QString &workingDir, const QString &file,
|
||||
const QString revision /* = QString() */,
|
||||
int lineNumber /* = -1 */)
|
||||
{
|
||||
Q_UNUSED(lineNumber)
|
||||
QStringList args;
|
||||
args << QLatin1String("annotate") << QLatin1String("-u") << QLatin1String("-c") << QLatin1String("-d");
|
||||
if (!revision.isEmpty())
|
||||
args << QLatin1String("-r") << revision;
|
||||
args << file;
|
||||
const QString kind = QLatin1String(Constants::ANNOTATELOG);
|
||||
const QString id = VCSBase::VCSBaseEditorWidget::getSource(workingDir, QStringList(file));
|
||||
const QString title = tr("Hg Annotate %1").arg(id);
|
||||
const QString source = VCSBase::VCSBaseEditorWidget::getSource(workingDir, file);
|
||||
|
||||
VCSBase::VCSBaseEditorWidget *editor = createVCSEditor(kind, title, source, true,
|
||||
"annotate", id);
|
||||
|
||||
QSharedPointer<HgTask> job(new HgTask(workingDir, args, editor));
|
||||
enqueueJob(job);
|
||||
}
|
||||
|
||||
void MercurialClient::diff(const QString &workingDir, const QStringList &files)
|
||||
{
|
||||
QStringList args;
|
||||
args << QLatin1String("diff") << QLatin1String("-g") << QLatin1String("-p")
|
||||
<< QLatin1String("-U 8");
|
||||
if (!files.isEmpty())
|
||||
args.append(files);
|
||||
|
||||
const QString kind = QLatin1String(Constants::DIFFLOG);
|
||||
const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(workingDir,files);
|
||||
const QString title = tr("Hg diff %1").arg(id);
|
||||
const QString source = VCSBase::VCSBaseEditorWidget::getSource(workingDir, files);
|
||||
VCSBase::VCSBaseEditorWidget *editor = createVCSEditor(kind, title, source, true,
|
||||
"diff", id);
|
||||
editor->setDiffBaseDirectory(workingDir);
|
||||
|
||||
QSharedPointer<HgTask> job(new HgTask(workingDir, args, editor));
|
||||
enqueueJob(job);
|
||||
}
|
||||
|
||||
|
||||
void MercurialClient::log(const QString &workingDir, const QStringList &files,
|
||||
bool enableAnnotationContextMenu)
|
||||
{
|
||||
QStringList args(QLatin1String("log"));
|
||||
if (!files.empty())
|
||||
args.append(files);
|
||||
|
||||
const QString kind = QLatin1String(Constants::FILELOG);
|
||||
const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(workingDir,files);
|
||||
const QString title = tr("Hg log %1").arg(id);
|
||||
const QString source = VCSBase::VCSBaseEditorWidget::getSource(workingDir, files);
|
||||
|
||||
VCSBase::VCSBaseEditorWidget *editor = createVCSEditor(kind, title, workingDir, true,
|
||||
"log", id);
|
||||
editor->setFileLogAnnotateEnabled(enableAnnotationContextMenu);
|
||||
|
||||
QSharedPointer<HgTask> job(new HgTask(workingDir, args, editor));
|
||||
enqueueJob(job);
|
||||
}
|
||||
|
||||
void MercurialClient::revertFile(const QString &workingDir,
|
||||
const QString &file,
|
||||
const QString &revision)
|
||||
{
|
||||
const QStringList cookieList(workingDir + QLatin1Char('/') + file);
|
||||
revert(workingDir, file, revision, QVariant(cookieList));
|
||||
}
|
||||
|
||||
void MercurialClient::revertRepository(const QString &workingDir,
|
||||
const QString &revision)
|
||||
{
|
||||
revert(workingDir, QLatin1String("--all"), revision, QVariant(workingDir));
|
||||
}
|
||||
|
||||
void MercurialClient::revert(const QString &workingDir,
|
||||
const QString &argument,
|
||||
const QString &revision,
|
||||
const QVariant &cookie)
|
||||
{
|
||||
QStringList args(QLatin1String("revert"));
|
||||
if (!revision.isEmpty())
|
||||
args << QLatin1String("-r") << revision;
|
||||
args.append(argument);
|
||||
|
||||
// Indicate repository change or file list
|
||||
QSharedPointer<HgTask> job(new HgTask(workingDir, args, false, cookie));
|
||||
connect(job.data(), SIGNAL(succeeded(QVariant)), this, SIGNAL(changed(QVariant)), Qt::QueuedConnection);
|
||||
enqueueJob(job);
|
||||
}
|
||||
|
||||
bool MercurialClient::createRepositorySync(const QString &workingDirectory)
|
||||
{
|
||||
const QStringList args(QLatin1String("init"));
|
||||
QByteArray outputData;
|
||||
if (!executeHgFullySynchronously(workingDirectory, args, &outputData))
|
||||
return false;
|
||||
QString output = QString::fromLocal8Bit(outputData);
|
||||
output.remove(QLatin1Char('\r'));
|
||||
VCSBase::VCSBaseOutputWindow::instance()->append(output);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MercurialClient::status(const QString &workingDir, const QString &file)
|
||||
{
|
||||
QStringList args(QLatin1String("status"));
|
||||
if (!file.isEmpty())
|
||||
args.append(file);
|
||||
VCSBase::VCSBaseOutputWindow *outwin = VCSBase::VCSBaseOutputWindow::instance();
|
||||
outwin->setRepository(workingDir);
|
||||
QSharedPointer<HgTask> job(new HgTask(workingDir, args, false));
|
||||
connect(job.data(), SIGNAL(succeeded(QVariant)), outwin, SLOT(clearRepository()),
|
||||
Qt::QueuedConnection);
|
||||
enqueueJob(job);
|
||||
}
|
||||
|
||||
void MercurialClient::statusWithSignal(const QString &repositoryRoot)
|
||||
{
|
||||
const QStringList args(QLatin1String("status"));
|
||||
QSharedPointer<HgTask> job(new HgTask(repositoryRoot, args, true));
|
||||
connect(job.data(), SIGNAL(rawData(QByteArray)),
|
||||
this, SLOT(statusParser(QByteArray)));
|
||||
enqueueJob(job);
|
||||
}
|
||||
|
||||
void MercurialClient::statusParser(const QByteArray &data)
|
||||
{
|
||||
QList<QPair<QString, QString> > statusList;
|
||||
|
||||
QStringList rawStatusList = QTextCodec::codecForLocale()->toUnicode(data).split(QLatin1Char('\n'));
|
||||
|
||||
foreach (const QString &string, rawStatusList) {
|
||||
QPair<QString, QString> status;
|
||||
|
||||
if (string.startsWith(QLatin1Char('M')))
|
||||
status.first = QLatin1String("Modified");
|
||||
else if (string.startsWith(QLatin1Char('A')))
|
||||
status.first = QLatin1String("Added");
|
||||
else if (string.startsWith(QLatin1Char('R')))
|
||||
status.first = QLatin1String("Removed");
|
||||
else if (string.startsWith(QLatin1Char('!')))
|
||||
status.first = QLatin1String("Deleted");
|
||||
else if (string.startsWith(QLatin1Char('?')))
|
||||
status.first = QLatin1String("Untracked");
|
||||
else
|
||||
continue;
|
||||
|
||||
//the status string should be similar to "M file_with_Changes"
|
||||
//so just should take the file name part and store it
|
||||
status.second = string.mid(2);
|
||||
statusList.append(status);
|
||||
}
|
||||
|
||||
emit parsedStatus(statusList);
|
||||
}
|
||||
|
||||
void MercurialClient::import(const QString &repositoryRoot, const QStringList &files)
|
||||
{
|
||||
QStringList args;
|
||||
args << QLatin1String("import") << QLatin1String("--no-commit");
|
||||
args += files;
|
||||
|
||||
QSharedPointer<HgTask> job(new HgTask(repositoryRoot, args, false));
|
||||
enqueueJob(job);
|
||||
}
|
||||
|
||||
bool MercurialClient::pullSync(const QString &repositoryRoot, const QString &repository)
|
||||
{
|
||||
QStringList args(QLatin1String("pull"));
|
||||
if (!repository.isEmpty())
|
||||
args.append(repository);
|
||||
// Disable UNIX terminals to suppress SSH prompting.
|
||||
const unsigned flags = VCSBase::VCSBasePlugin::SshPasswordPrompt|VCSBase::VCSBasePlugin::ShowStdOutInLogWindow
|
||||
|VCSBase::VCSBasePlugin::ShowSuccessMessage;
|
||||
const Utils::SynchronousProcessResponse resp =
|
||||
executeHgSynchronously(repositoryRoot, args, flags);
|
||||
const bool ok = resp.result == Utils::SynchronousProcessResponse::Finished;
|
||||
if (ok)
|
||||
emit changed(QVariant(repositoryRoot));
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool MercurialClient::pushSync(const QString &repositoryRoot, const QString &repository)
|
||||
{
|
||||
QStringList args(QLatin1String("push"));
|
||||
if (!repository.isEmpty())
|
||||
args.append(repository);
|
||||
// Disable UNIX terminals to suppress SSH prompting.
|
||||
const unsigned flags = VCSBase::VCSBasePlugin::SshPasswordPrompt|VCSBase::VCSBasePlugin::ShowStdOutInLogWindow
|
||||
|VCSBase::VCSBasePlugin::ShowSuccessMessage;
|
||||
const Utils::SynchronousProcessResponse resp =
|
||||
executeHgSynchronously(repositoryRoot, args, flags);
|
||||
return resp.result == Utils::SynchronousProcessResponse::Finished;
|
||||
}
|
||||
|
||||
bool MercurialClient::clone(const QString &directory, const QString &url)
|
||||
{
|
||||
QDir workingDirectory(directory);
|
||||
QByteArray output;
|
||||
const unsigned flags = VCSBase::VCSBasePlugin::SshPasswordPrompt |
|
||||
VCSBase::VCSBasePlugin::ShowStdOutInLogWindow |
|
||||
VCSBase::VCSBasePlugin::ShowSuccessMessage;
|
||||
|
||||
if (workingDirectory.exists()) {
|
||||
// Let's make first init
|
||||
QStringList arguments(QLatin1String("init"));
|
||||
if (!executeHgFullySynchronously(workingDirectory.path(), arguments, &output)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Then pull remote repository
|
||||
arguments.clear();
|
||||
arguments << QLatin1String("pull") << url;
|
||||
const Utils::SynchronousProcessResponse resp1 =
|
||||
executeHgSynchronously(workingDirectory.path(), arguments, flags);
|
||||
if (resp1.result != Utils::SynchronousProcessResponse::Finished) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// By now, there is no hgrc file -> create it
|
||||
QFile hgrc(workingDirectory.path()+"/.hg/hgrc");
|
||||
hgrc.open(QIODevice::WriteOnly);
|
||||
hgrc.write(QString("[paths]\ndefault = %1\n").arg(QString(url)).toUtf8());
|
||||
hgrc.close();
|
||||
|
||||
// And last update repository
|
||||
arguments.clear();
|
||||
arguments << QLatin1String("update");
|
||||
const Utils::SynchronousProcessResponse resp2 =
|
||||
executeHgSynchronously(workingDirectory.path(), arguments, flags);
|
||||
return resp2.result == Utils::SynchronousProcessResponse::Finished;
|
||||
} else {
|
||||
QStringList arguments(QLatin1String("clone"));
|
||||
arguments << url << workingDirectory.dirName();
|
||||
workingDirectory.cdUp();
|
||||
const Utils::SynchronousProcessResponse resp =
|
||||
executeHgSynchronously(workingDirectory.path(), arguments, flags);
|
||||
return resp.result == Utils::SynchronousProcessResponse::Finished;
|
||||
}
|
||||
}
|
||||
|
||||
QString MercurialClient::vcsGetRepositoryURL(const QString &directory)
|
||||
{
|
||||
QByteArray output;
|
||||
@@ -554,8 +244,8 @@ QString MercurialClient::vcsGetRepositoryURL(const QString &directory)
|
||||
QStringList arguments(QLatin1String("showconfig"));
|
||||
arguments << QLatin1String("paths.default");
|
||||
|
||||
if (executeHgFullySynchronously(directory, arguments, &output))
|
||||
return QString::fromLocal8Bit(output);;
|
||||
if (vcsFullySynchronousExec(directory, arguments, &output))
|
||||
return QString::fromLocal8Bit(output);
|
||||
return QString();
|
||||
}
|
||||
|
||||
@@ -578,10 +268,10 @@ void MercurialClient::incoming(const QString &repositoryRoot, const QString &rep
|
||||
VCSBase::VCSBaseEditorWidget *editor = createVCSEditor(kind, title, repositoryRoot,
|
||||
true, "incoming", id);
|
||||
|
||||
QSharedPointer<HgTask> job(new HgTask(repositoryRoot, args, editor));
|
||||
QSharedPointer<VCSBase::VCSJob> job(new VCSBase::VCSJob(repositoryRoot, args, editor));
|
||||
// Suppress SSH prompting.
|
||||
if (!repository.isEmpty() && VCSBase::VCSBasePlugin::isSshPromptConfigured())
|
||||
job->setUnixTerminalDisabled(true);
|
||||
job->setUnixTerminalDisabled(true);
|
||||
enqueueJob(job);
|
||||
}
|
||||
|
||||
@@ -592,116 +282,209 @@ void MercurialClient::outgoing(const QString &repositoryRoot)
|
||||
|
||||
const QString kind = QLatin1String(Constants::DIFFLOG);
|
||||
const QString title = tr("Hg outgoing %1").
|
||||
arg(QDir::toNativeSeparators(repositoryRoot));
|
||||
arg(QDir::toNativeSeparators(repositoryRoot));
|
||||
|
||||
VCSBase::VCSBaseEditorWidget *editor = createVCSEditor(kind, title, repositoryRoot, true,
|
||||
"outgoing", repositoryRoot);
|
||||
|
||||
QSharedPointer<HgTask> job(new HgTask(repositoryRoot, args, editor));
|
||||
QSharedPointer<VCSBase::VCSJob> job(new VCSBase::VCSJob(repositoryRoot, args, editor));
|
||||
// Suppress SSH prompting
|
||||
job->setUnixTerminalDisabled(VCSBase::VCSBasePlugin::isSshPromptConfigured());
|
||||
enqueueJob(job);
|
||||
}
|
||||
|
||||
void MercurialClient::view(const QString &source, const QString &id)
|
||||
{
|
||||
QStringList args;
|
||||
args << QLatin1String("log") << QLatin1String("-p") << QLatin1String("-g")
|
||||
<< QLatin1String("-r") << id;
|
||||
|
||||
const QString kind = QLatin1String(Constants::DIFFLOG);
|
||||
const QString title = tr("Hg log %1").arg(id);
|
||||
|
||||
VCSBase::VCSBaseEditorWidget *editor = createVCSEditor(kind, title, source,
|
||||
true, "view", id);
|
||||
|
||||
QSharedPointer<HgTask> job(new HgTask(source, args, editor));
|
||||
enqueueJob(job);
|
||||
}
|
||||
|
||||
void MercurialClient::update(const QString &repositoryRoot, const QString &revision)
|
||||
{
|
||||
QStringList args(QLatin1String("update"));
|
||||
if (!revision.isEmpty())
|
||||
args << revision;
|
||||
|
||||
QSharedPointer<HgTask> job(new HgTask(repositoryRoot, args, false, QVariant(repositoryRoot)));
|
||||
// Suppress SSH prompting
|
||||
job->setUnixTerminalDisabled(VCSBase::VCSBasePlugin::isSshPromptConfigured());
|
||||
connect(job.data(), SIGNAL(succeeded(QVariant)), this, SIGNAL(changed(QVariant)), Qt::QueuedConnection);
|
||||
enqueueJob(job);
|
||||
}
|
||||
|
||||
void MercurialClient::commit(const QString &repositoryRoot, const QStringList &files,
|
||||
const QString &committerInfo, const QString &commitMessageFile,
|
||||
bool autoAddRemove)
|
||||
{
|
||||
// refuse to do "autoadd" on a commit with working directory only, as this will
|
||||
// add all the untracked stuff.
|
||||
QTC_ASSERT(!(autoAddRemove && files.isEmpty()), return)
|
||||
QStringList args = QStringList(QLatin1String(nonInteractiveOptionC));
|
||||
args.append(QLatin1String("commit"));
|
||||
if (!committerInfo.isEmpty())
|
||||
args << QLatin1String("-u") << committerInfo;
|
||||
args << QLatin1String("-l") << commitMessageFile;
|
||||
if (autoAddRemove)
|
||||
args << QLatin1String("-A");
|
||||
args << files;
|
||||
QSharedPointer<HgTask> job(new HgTask(repositoryRoot, args, false));
|
||||
enqueueJob(job);
|
||||
}
|
||||
|
||||
QString MercurialClient::findTopLevelForFile(const QFileInfo &file)
|
||||
QString MercurialClient::findTopLevelForFile(const QFileInfo &file) const
|
||||
{
|
||||
const QString repositoryCheckFile = QLatin1String(Constants::MECURIALREPO) + QLatin1String("/requires");
|
||||
return file.isDir() ?
|
||||
VCSBase::VCSBasePlugin::findRepositoryForDirectory(file.absoluteFilePath(), repositoryCheckFile) :
|
||||
VCSBase::VCSBasePlugin::findRepositoryForDirectory(file.absolutePath(), repositoryCheckFile);
|
||||
VCSBase::VCSBasePlugin::findRepositoryForDirectory(file.absoluteFilePath(), repositoryCheckFile) :
|
||||
VCSBase::VCSBasePlugin::findRepositoryForDirectory(file.absolutePath(), repositoryCheckFile);
|
||||
}
|
||||
|
||||
void MercurialClient::settingsChanged()
|
||||
QString MercurialClient::vcsEditorKind(VCSCommand cmd) const
|
||||
{
|
||||
if (jobManager)
|
||||
jobManager->restart();
|
||||
}
|
||||
|
||||
VCSBase::VCSBaseEditorWidget *MercurialClient::createVCSEditor(const QString &kind, QString title,
|
||||
const QString &source, bool setSourceCodec,
|
||||
const char *registerDynamicProperty,
|
||||
const QString &dynamicPropertyValue) const
|
||||
{
|
||||
VCSBase::VCSBaseEditorWidget *baseEditor = 0;
|
||||
Core::IEditor* outputEditor = locateEditor(core, registerDynamicProperty, dynamicPropertyValue);
|
||||
const QString progressMsg = tr("Working...");
|
||||
if (outputEditor) {
|
||||
// Exists already
|
||||
outputEditor->createNew(progressMsg);
|
||||
baseEditor = VCSBase::VCSBaseEditorWidget::getVcsBaseEditor(outputEditor);
|
||||
QTC_ASSERT(baseEditor, return 0);
|
||||
} else {
|
||||
outputEditor = core->editorManager()->openEditorWithContents(kind, &title, progressMsg);
|
||||
outputEditor->file()->setProperty(registerDynamicProperty, dynamicPropertyValue);
|
||||
baseEditor = VCSBase::VCSBaseEditorWidget::getVcsBaseEditor(outputEditor);
|
||||
connect(baseEditor, SIGNAL(annotateRevisionRequested(QString,QString,int)),
|
||||
this, SLOT(slotAnnotateRevisionRequested(QString,QString,int)));
|
||||
QTC_ASSERT(baseEditor, return 0);
|
||||
baseEditor->setSource(source);
|
||||
if (setSourceCodec)
|
||||
baseEditor->setCodec(VCSBase::VCSBaseEditorWidget::getCodec(source));
|
||||
switch(cmd)
|
||||
{
|
||||
case AnnotateCommand : return QLatin1String(Constants::ANNOTATELOG);
|
||||
case DiffCommand : return QLatin1String(Constants::DIFFLOG);
|
||||
case LogCommand : return QLatin1String(Constants::FILELOG);
|
||||
default : return QLatin1String("");
|
||||
}
|
||||
|
||||
core->editorManager()->activateEditor(outputEditor, Core::EditorManager::ModeSwitch);
|
||||
baseEditor->setForceReadOnly(true);
|
||||
return baseEditor;
|
||||
return QLatin1String("");
|
||||
}
|
||||
|
||||
void MercurialClient::enqueueJob(const QSharedPointer<HgTask> &job)
|
||||
QStringList MercurialClient::cloneArguments(const QString &srcLocation,
|
||||
const QString &dstLocation,
|
||||
const ExtraCommandOptions &extraOptions) const
|
||||
{
|
||||
if (!jobManager) {
|
||||
jobManager = new MercurialJobRunner();
|
||||
jobManager->start();
|
||||
Q_UNUSED(srcLocation);
|
||||
Q_UNUSED(dstLocation);
|
||||
Q_UNUSED(extraOptions);
|
||||
QStringList args;
|
||||
return args;
|
||||
}
|
||||
|
||||
QStringList MercurialClient::pullArguments(const QString &srcLocation,
|
||||
const ExtraCommandOptions &extraOptions) const
|
||||
{
|
||||
Q_UNUSED(extraOptions);
|
||||
QStringList args;
|
||||
// Add arguments for common options
|
||||
if (!srcLocation.isEmpty())
|
||||
args << srcLocation;
|
||||
return args;
|
||||
}
|
||||
|
||||
QStringList MercurialClient::pushArguments(const QString &dstLocation,
|
||||
const ExtraCommandOptions &extraOptions) const
|
||||
{
|
||||
Q_UNUSED(extraOptions);
|
||||
QStringList args;
|
||||
// Add arguments for common options
|
||||
if (!dstLocation.isEmpty())
|
||||
args << dstLocation;
|
||||
return args;
|
||||
}
|
||||
|
||||
QStringList MercurialClient::commitArguments(const QStringList &files,
|
||||
const QString &commitMessageFile,
|
||||
const ExtraCommandOptions &extraOptions) const
|
||||
{
|
||||
QStringList args(QLatin1String("--noninteractive"));
|
||||
// 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 << QLatin1String("-u") << committerInfo;
|
||||
break;
|
||||
}
|
||||
case AutoAddRemoveCommitOptionId :
|
||||
{
|
||||
Q_ASSERT(iOptValue.canConvert(QVariant::Bool));
|
||||
const bool autoAddRemove = iOptValue.toBool();
|
||||
if (autoAddRemove)
|
||||
args << QLatin1String("-A");
|
||||
break;
|
||||
}
|
||||
default :
|
||||
Q_ASSERT(false); // Invalid option !
|
||||
}
|
||||
} // end foreach ()
|
||||
// Add arguments for common options
|
||||
args << QLatin1String("-l") << commitMessageFile;
|
||||
args << files;
|
||||
return args;
|
||||
}
|
||||
|
||||
QStringList MercurialClient::importArguments(const QStringList &files) const
|
||||
{
|
||||
QStringList args(QLatin1String("--no-commit"));
|
||||
if (!files.isEmpty())
|
||||
args.append(files);
|
||||
return args;
|
||||
}
|
||||
|
||||
QStringList MercurialClient::updateArguments(const QString &revision) const
|
||||
{
|
||||
QStringList args;
|
||||
if (!revision.isEmpty())
|
||||
args << QLatin1String("-r") << revision;
|
||||
return args;
|
||||
}
|
||||
|
||||
QStringList MercurialClient::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 MercurialClient::revertAllArguments(const QString &revision) const
|
||||
{
|
||||
QStringList args;
|
||||
if (!revision.isEmpty())
|
||||
args << QLatin1String("-r") << revision;
|
||||
return args << QLatin1String("--all");
|
||||
}
|
||||
|
||||
QStringList MercurialClient::annotateArguments(const QString &file,
|
||||
const QString &revision,
|
||||
int /*lineNumber*/) const
|
||||
{
|
||||
QStringList args;
|
||||
args << QLatin1String("-u") << QLatin1String("-c") << QLatin1String("-d");
|
||||
if (!revision.isEmpty())
|
||||
args << QLatin1String("-r") << revision;
|
||||
return args << file;
|
||||
}
|
||||
|
||||
QStringList MercurialClient::diffArguments(const QStringList &files) const
|
||||
{
|
||||
QStringList args;
|
||||
args << QLatin1String("-g") << QLatin1String("-p") << QLatin1String("-U 8");
|
||||
if (!files.isEmpty())
|
||||
args.append(files);
|
||||
return args;
|
||||
}
|
||||
|
||||
QStringList MercurialClient::logArguments(const QStringList &files) const
|
||||
{
|
||||
QStringList args;
|
||||
if (!files.empty())
|
||||
args.append(files);
|
||||
return args;
|
||||
}
|
||||
|
||||
QStringList MercurialClient::statusArguments(const QString &file) const
|
||||
{
|
||||
QStringList args;
|
||||
if (!file.isEmpty())
|
||||
args.append(file);
|
||||
return args;
|
||||
}
|
||||
|
||||
QStringList MercurialClient::viewArguments(const QString &revision) const
|
||||
{
|
||||
QStringList args;
|
||||
args << QLatin1String("log") << QLatin1String("-p") << QLatin1String("-g")
|
||||
<< QLatin1String("-r") << revision;
|
||||
return args;
|
||||
}
|
||||
|
||||
QPair<QString, QString> MercurialClient::parseStatusLine(const QString &line) const
|
||||
{
|
||||
QPair<QString, QString> status;
|
||||
if (!line.isEmpty())
|
||||
{
|
||||
if (line.startsWith(QLatin1Char('M')))
|
||||
status.first = QLatin1String("Modified");
|
||||
else if (line.startsWith(QLatin1Char('A')))
|
||||
status.first = QLatin1String("Added");
|
||||
else if (line.startsWith(QLatin1Char('R')))
|
||||
status.first = QLatin1String("Removed");
|
||||
else if (line.startsWith(QLatin1Char('!')))
|
||||
status.first = QLatin1String("Deleted");
|
||||
else if (line.startsWith(QLatin1Char('?')))
|
||||
status.first = QLatin1String("Untracked");
|
||||
else
|
||||
return status;
|
||||
|
||||
//the status line should be similar to "M file_with_changes"
|
||||
//so just should take the file name part and store it
|
||||
status.second = line.mid(2);
|
||||
}
|
||||
jobManager->enqueueJob(job);
|
||||
return status;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
Reference in New Issue
Block a user