// Copyright (C) 2016 Brian McGillion // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "mercurialclient.h" #include "constants.h" #include "mercurialtr.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Core; using namespace DiffEditor; using namespace Utils; using namespace VcsBase; namespace Mercurial::Internal { class MercurialDiffEditorController : public VcsBaseDiffEditorController { public: MercurialDiffEditorController(IDocument *document, const QStringList &args); private: QStringList addConfigurationArguments(const QStringList &args) const; }; MercurialDiffEditorController::MercurialDiffEditorController(IDocument *document, const QStringList &args) : VcsBaseDiffEditorController(document) { setDisplayName("Hg Diff"); using namespace Tasking; const Storage diffInputStorage; const auto onDiffSetup = [this, args](Process &process) { setupCommand(process, {addConfigurationArguments(args)}); VcsOutputWindow::appendCommand(process.workingDirectory(), process.commandLine()); }; const auto onDiffDone = [diffInputStorage](const Process &process) { *diffInputStorage = process.cleanedStdOut(); }; const Group root { diffInputStorage, ProcessTask(onDiffSetup, onDiffDone, CallDoneIf::Success), postProcessTask(diffInputStorage) }; setReloadRecipe(root); } QStringList MercurialDiffEditorController::addConfigurationArguments(const QStringList &args) const { QStringList configArgs{"-g", "-p", "-U", QString::number(contextLineCount())}; if (ignoreWhitespace()) configArgs << "-w" << "-b" << "-B" << "-Z"; return args + configArgs; } ///////////////////////////////////////////////////////////// MercurialClient::MercurialClient() : VcsBaseClient(&Internal::settings()) { } bool MercurialClient::manifestSync(const FilePath &repository, const QString &relativeFilename) { // This only works when called from the repo and outputs paths relative to it. const QStringList args(QLatin1String("manifest")); const CommandResult result = vcsSynchronousExec(repository, args); const QDir repositoryDir(repository.toString()); const QFileInfo needle = QFileInfo(repositoryDir, relativeFilename); const QStringList files = result.cleanedStdOut().split(QLatin1Char('\n')); for (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 FilePath &workingDirectory, const QString &srcLocation, const QString &dstLocation, const QStringList &extraOptions) { Q_UNUSED(srcLocation) Q_UNUSED(extraOptions) const RunFlags flags = RunFlags::ShowStdOut | RunFlags::ShowSuccessMessage; if (workingDirectory.exists()) { // Let's make first init if (vcsSynchronousExec(workingDirectory, QStringList{"init"}).result() != ProcessResult::FinishedWithSuccess) { return false; } // Then pull remote repository if (vcsSynchronousExec(workingDirectory, {"pull", dstLocation}, flags).result() != ProcessResult::FinishedWithSuccess) { return false; } // By now, there is no hgrc file -> create it FileSaver saver(workingDirectory.pathAppended(".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 return vcsSynchronousExec(workingDirectory, QStringList{"update"}, flags).result() == ProcessResult::FinishedWithSuccess; } else { const QStringList arguments{"clone", dstLocation, workingDirectory.parentDir().toString()}; return vcsSynchronousExec(workingDirectory.parentDir(), arguments, flags).result() == ProcessResult::FinishedWithSuccess; } } bool MercurialClient::synchronousPull(const FilePath &workingDir, const QString &srcLocation, const QStringList &extraOptions) { QStringList args; args << vcsCommandString(PullCommand) << extraOptions << srcLocation; const CommandResult result = vcsSynchronousExec(workingDir, args, RunFlags::ShowStdOut | RunFlags::ShowSuccessMessage | RunFlags::ForceCLocale); parsePullOutput(result.cleanedStdOut().trimmed()); return result.result() == ProcessResult::FinishedWithSuccess; } 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 QString msgParentRevisionFailed(const FilePath &workingDirectory, const QString &revision, const QString &why) { return Tr::tr("Unable to find parent revisions of %1 in %2: %3"). arg(revision, workingDirectory.toUserOutput(), why); } static inline QString msgParseParentsOutputFailed(const QString &output) { return Tr::tr("Cannot parse output: %1").arg(output); } QStringList MercurialClient::parentRevisionsSync(const FilePath &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 FilePath &workingDirectory, const QString &revision, const QString &format) { QStringList args; args << QLatin1String("log") << QLatin1String("-r") <setVcsBinary(settings().binaryPath()); controller->setWorkingDirectory(workingDirectory); VcsBase::setSource(document, sourceCopy); EditorManager::activateEditorForDocument(document); controller->requestReload(); } void MercurialClient::parsePullOutput(const QString &output) { if (output.endsWith(QLatin1String("no changes found"))) return; if (output.endsWith(QLatin1String("(run 'hg update' to get a working copy)"))) { emit needUpdate(); return; } if (output.endsWith(QLatin1String("'hg merge' to merge)"))) emit needMerge(); } MercurialClient &mercurialClient() { static MercurialClient theMercurialClient; return theMercurialClient; } } // Mercurial::Internal