/**************************************************************************** ** ** Copyright (C) 2016 Brian McGillion ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include "mercurialclient.h" #include "constants.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Utils; using namespace VcsBase; namespace Mercurial { namespace Internal { // Parameter widget controlling whitespace diff mode, associated with a parameter class MercurialDiffConfig : public VcsBaseEditorConfig { Q_OBJECT public: MercurialDiffConfig(VcsBaseClientSettings &settings, QToolBar *toolBar) : VcsBaseEditorConfig(toolBar) { mapSetting(addToggleButton(QLatin1String("-w"), tr("Ignore Whitespace")), settings.boolPointer(MercurialSettings::diffIgnoreWhiteSpaceKey)); mapSetting(addToggleButton(QLatin1String("-B"), tr("Ignore Blank Lines")), settings.boolPointer(MercurialSettings::diffIgnoreBlankLinesKey)); } }; MercurialClient::MercurialClient() : VcsBaseClient(new MercurialSettings) { setDiffConfigCreator([this](QToolBar *toolBar) { return new MercurialDiffConfig(settings(), toolBar); }); } bool MercurialClient::manifestSync(const QString &repository, const QString &relativeFilename) { // This only works when called from the repo and outputs paths relative to it. const QStringList args(QLatin1String("manifest")); const SynchronousProcessResponse result = vcsFullySynchronousExec(repository, args); const QDir repositoryDir(repository); const QFileInfo needle = QFileInfo(repositoryDir, relativeFilename); const QStringList files = result.stdOut().split(QLatin1Char('\n')); foreach (const QString &fileName, files) { const QFileInfo managedFile(repositoryDir, fileName); if (needle == managedFile) return true; } return false; } //bool MercurialClient::clone(const QString &directory, const QString &url) bool MercurialClient::synchronousClone(const QString &workingDir, const QString &srcLocation, const QString &dstLocation, const QStringList &extraOptions) { Q_UNUSED(workingDir); Q_UNUSED(extraOptions); QDir workingDirectory(srcLocation); const unsigned flags = VcsCommand::SshPasswordPrompt | VcsCommand::ShowStdOut | VcsCommand::ShowSuccessMessage; if (workingDirectory.exists()) { // Let's make first init QStringList arguments(QLatin1String("init")); const SynchronousProcessResponse resp = vcsFullySynchronousExec( workingDirectory.path(), arguments); if (resp.result != SynchronousProcessResponse::Finished) return false; // Then pull remote repository arguments.clear(); arguments << QLatin1String("pull") << dstLocation; const SynchronousProcessResponse resp1 = vcsSynchronousExec( workingDirectory.path(), arguments, flags); if (resp1.result != SynchronousProcessResponse::Finished) return false; // By now, there is no hgrc file -> create it FileSaver saver(workingDirectory.path() + QLatin1String("/.hg/hgrc")); const QString hgrc = QLatin1String("[paths]\ndefault = ") + dstLocation + QLatin1Char('\n'); saver.write(hgrc.toUtf8()); if (!saver.finalize()) { VcsOutputWindow::appendError(saver.errorString()); return false; } // And last update repository arguments.clear(); arguments << QLatin1String("update"); const SynchronousProcessResponse resp2 = vcsSynchronousExec( workingDirectory.path(), arguments, flags); return resp2.result == SynchronousProcessResponse::Finished; } else { QStringList arguments(QLatin1String("clone")); arguments << dstLocation << workingDirectory.dirName(); workingDirectory.cdUp(); const SynchronousProcessResponse resp = vcsSynchronousExec( workingDirectory.path(), arguments, flags); return resp.result == SynchronousProcessResponse::Finished; } } bool MercurialClient::synchronousPull(const QString &workingDir, const QString &srcLocation, const QStringList &extraOptions) { QStringList args; args << vcsCommandString(PullCommand) << extraOptions << srcLocation; // Disable UNIX terminals to suppress SSH prompting const unsigned flags = VcsCommand::SshPasswordPrompt | VcsCommand::ShowStdOut | VcsCommand::ShowSuccessMessage; // cause mercurial doesn`t understand LANG QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(QLatin1String("LANGUAGE"), QLatin1String("C")); const SynchronousProcessResponse resp = VcsBasePlugin::runVcs( workingDir, vcsBinary(), args, vcsTimeoutS(), flags, 0, env); const bool ok = resp.result == SynchronousProcessResponse::Finished; parsePullOutput(resp.stdOut().trimmed()); return ok; } QString MercurialClient::branchQuerySync(const QString &repositoryRoot) { QFile branchFile(repositoryRoot + QLatin1String("/.hg/branch")); if (branchFile.open(QFile::ReadOnly)) { const QByteArray branch = branchFile.readAll().trimmed(); if (!branch.isEmpty()) return QString::fromLocal8Bit(branch); } return QLatin1String("Unknown Branch"); } 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, QDir::toNativeSeparators(workingDirectory), why); } static inline QString msgParseParentsOutputFailed(const QString &output) { return MercurialClient::tr("Cannot parse output: %1").arg(output); } QStringList MercurialClient::parentRevisionsSync(const QString &workingDirectory, const QString &file /* = QString() */, const QString &revision) { QStringList parents; QStringList args; args << QLatin1String("parents") << QLatin1String("-r") <indexOf(colon); if (colonIndex != -1) parents.push_back(it->mid(colonIndex + 1)); } return parents; } // Describe a change using an optional format QString MercurialClient::shortDescriptionSync(const QString &workingDirectory, const QString &revision, const QString &format) { QStringList args; args << QLatin1String("log") << QLatin1String("-r") <