void CMakeTool::fetchFromCapabilities() const { Utils::SynchronousProcessResponse response = run({ "-E", "capabilities" }, true); if (response.result != Utils::SynchronousProcessResponse::Finished) return; auto doc = QJsonDocument::fromJson(response.stdOut().toUtf8()); if (!doc.isObject()) return; const QVariantMap data = doc.object().toVariantMap(); m_hasServerMode = data.value("serverMode").toBool(); const QVariantList generatorList = data.value("generators").toList(); for (const QVariant &v : generatorList) { const QVariantMap gen = v.toMap(); m_generators.append(Generator(gen.value("name").toString(), gen.value("extraGenerators").toStringList(), gen.value("platformSupport").toBool(), gen.value("toolsetSupport").toBool())); } const QVariantMap versionInfo = data.value("version").toMap(); m_version.major = versionInfo.value("major").toInt(); m_version.minor = versionInfo.value("minor").toInt(); m_version.patch = versionInfo.value("patch").toInt(); m_version.fullVersion = versionInfo.value("string").toByteArray(); }
TextEditor::Keywords CMakeTool::keywords() { if (m_functions.isEmpty()) { Utils::SynchronousProcessResponse response; response = run({ "--help-command-list" }); if (response.result == Utils::SynchronousProcessResponse::Finished) m_functions = response.stdOut().split('\n'); response = run({ "--help-commands" }); if (response.result == Utils::SynchronousProcessResponse::Finished) parseFunctionDetailsOutput(response.stdOut()); response = run({ "--help-property-list" }); if (response.result == Utils::SynchronousProcessResponse::Finished) m_variables = parseVariableOutput(response.stdOut()); response = run({ "--help-variable-list" }); if (response.result == Utils::SynchronousProcessResponse::Finished) { m_variables.append(parseVariableOutput(response.stdOut())); m_variables = Utils::filteredUnique(m_variables); Utils::sort(m_variables); } } return TextEditor::Keywords(m_variables, m_functions, m_functionArgs); }
bool AndroidRunnerWorkerBase::runAdb(const QStringList &args, int timeoutS) { Utils::SynchronousProcess adb; adb.setTimeoutS(timeoutS); Utils::SynchronousProcessResponse response = adb.run(m_adb, selector() + args); m_lastRunAdbError = response.exitMessage(m_adb, timeoutS); m_lastRunAdbRawOutput = response.allRawOutput(); return response.result == Utils::SynchronousProcessResponse::Finished; }
void CMakeTool::fetchGeneratorsFromHelp() const { Utils::SynchronousProcessResponse response = run({ "--help" }); if (response.result != Utils::SynchronousProcessResponse::Finished) return; bool inGeneratorSection = false; QHash<QString, QStringList> generatorInfo; const QStringList lines = response.stdOut().split('\n'); foreach (const QString &line, lines) { if (line.isEmpty()) continue; if (line == "Generators") { inGeneratorSection = true; continue; } if (!inGeneratorSection) continue; if (line.startsWith(" ") && line.at(3) != ' ') { int pos = line.indexOf('='); if (pos < 0) pos = line.length(); if (pos >= 0) { --pos; while (pos > 2 && line.at(pos).isSpace()) --pos; } if (pos > 2) { const QString fullName = line.mid(2, pos - 1); const int dashPos = fullName.indexOf(" - "); QString generator; QString extra; if (dashPos < 0) { generator = fullName; } else { extra = fullName.mid(0, dashPos); generator = fullName.mid(dashPos + 3); } QStringList value = generatorInfo.value(generator); if (!extra.isEmpty()) value.append(extra); generatorInfo.insert(generator, value); } } } // Populate genertor list: for (auto it = generatorInfo.constBegin(); it != generatorInfo.constEnd(); ++it) m_generators.append(Generator(it.key(), it.value())); }
static int updateVersionHelper(const QString &command) { Utils::SynchronousProcess process; Utils::SynchronousProcessResponse response = process.runBlocking(command, QStringList() << QLatin1String("--version")); if (response.result != Utils::SynchronousProcessResponse::Finished) return 0; // Astyle prints the version on stdout or stderr, depending on platform const int version = parseVersion(response.stdOut().trimmed()); if (version != 0) return version; return parseVersion(response.stdErr().trimmed()); }
ClangExecutableVersion clangExecutableVersion(const QString &executable) { const ClangExecutableVersion invalidVersion; // Sanity checks const QFileInfo fileInfo(executable); const bool isExecutableFile = fileInfo.isFile() && fileInfo.isExecutable(); if (!isExecutableFile) return invalidVersion; // Get version output Utils::Environment environment = Utils::Environment::systemEnvironment(); Utils::Environment::setupEnglishOutput(&environment); Utils::SynchronousProcess runner; runner.setEnvironment(environment.toStringList()); runner.setTimeoutS(10); // We would prefer "-dumpversion", but that one returns some old version number. const QStringList arguments(QLatin1String(("--version"))); const Utils::SynchronousProcessResponse response = runner.runBlocking(executable, arguments); if (response.result != Utils::SynchronousProcessResponse::Finished) return invalidVersion; const QString output = response.stdOut(); // Parse version output const QRegularExpression re(QLatin1String("clang version (\\d+)\\.(\\d+)\\.(\\d+)")); const QRegularExpressionMatch reMatch = re.match(output); if (re.captureCount() != 3) return invalidVersion; const QString majorString = reMatch.captured(1); bool convertedSuccessfully = false; const int major = majorString.toInt(&convertedSuccessfully); if (!convertedSuccessfully) return invalidVersion; const QString minorString = reMatch.captured(2); const int minor = minorString.toInt(&convertedSuccessfully); if (!convertedSuccessfully) return invalidVersion; const QString patchString = reMatch.captured(3); const int patch = patchString.toInt(&convertedSuccessfully); if (!convertedSuccessfully) return invalidVersion; return ClangExecutableVersion(major, minor, patch); }
void IosProbe::detectDeveloperPaths() { QString program = QLatin1String("/usr/bin/xcode-select"); QStringList arguments(QLatin1String("--print-path")); Utils::SynchronousProcess selectedXcode; selectedXcode.setTimeoutS(5); Utils::SynchronousProcessResponse response = selectedXcode.run(program, arguments); if (response.result != Utils::SynchronousProcessResponse::Finished) { qCWarning(probeLog) << QString::fromLatin1("Could not detect selected xcode with /usr/bin/xcode-select"); } else { QString path = response.stdOut(); path.chop(1); addDeveloperPath(path); } addDeveloperPath(QLatin1String("/Applications/Xcode.app/Contents/Developer")); }
void AndroidCreateKeystoreCertificate::on_buttonBox_accepted() { if (!validateUserInput()) return; m_keystoreFilePath = Utils::FileName::fromString(QFileDialog::getSaveFileName(this, tr("Keystore file name"), QDir::homePath() + QLatin1String("/android_release.keystore"), tr("Keystore files (*.keystore *.jks)"))); if (m_keystoreFilePath.isEmpty()) return; QString distinguishedNames(QString::fromLatin1("CN=%1, O=%2, L=%3, C=%4") .arg(ui->commonNameLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,"))) .arg(ui->organizationNameLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,"))) .arg(ui->localityNameLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,"))) .arg(ui->countryLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,")))); if (ui->organizationUnitLineEdit->text().length()) distinguishedNames += QLatin1String(", OU=") + ui->organizationUnitLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,")); if (ui->stateNameLineEdit->text().length()) distinguishedNames += QLatin1String(", S=") + ui->stateNameLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,")); const QString command = AndroidConfigurations::currentConfig().keytoolPath().toString(); QStringList params; params << QLatin1String("-genkey") << QLatin1String("-keyalg") << QLatin1String("RSA") << QLatin1String("-keystore") << m_keystoreFilePath.toString() << QLatin1String("-storepass") << keystorePassword() << QLatin1String("-alias") << certificateAlias() << QLatin1String("-keysize") << ui->keySizeSpinBox->text() << QLatin1String("-validity") << ui->validitySpinBox->text() << QLatin1String("-keypass") << certificatePassword() << QLatin1String("-dname") << distinguishedNames; Utils::SynchronousProcess genKeyCertProc; genKeyCertProc.setTimeoutS(15); Utils::SynchronousProcessResponse response = genKeyCertProc.run(command, params); if (response.result != Utils::SynchronousProcessResponse::Finished || response.exitCode != 0) { QMessageBox::critical(this, tr("Error"), response.exitMessage(command, 15) + QLatin1Char('\n') + response.allOutput()); return; } accept(); }
void CMakeTool::fetchVersionFromVersionOutput() const { Utils::SynchronousProcessResponse response = run({ "--version" }); if (response.result != Utils::SynchronousProcessResponse::Finished) return; QRegularExpression versionLine("^cmake version ((\\d+).(\\d+).(\\d+).*)$"); const QString responseText = response.stdOut(); for (const QStringRef &line : responseText.splitRef(QLatin1Char('\n'))) { QRegularExpressionMatch match = versionLine.match(line); if (!match.hasMatch()) continue; m_version.major = match.captured(2).toInt(); m_version.minor = match.captured(3).toInt(); m_version.patch = match.captured(4).toInt(); m_version.fullVersion = match.captured(1).toUtf8(); break; } }
bool AndroidRunnerWorkerBase::adbShellAmNeedsQuotes() { // Between Android SDK Tools version 24.3.1 and 24.3.4 the quoting // needs for the 'adb shell am start ...' parameters changed. // Run a test to find out on what side of the fence we live. // The command will fail with a complaint about the "--dummy" // option on newer SDKs, and with "No intent supplied" on older ones. // In case the test itself fails assume a new SDK. Utils::SynchronousProcess adb; adb.setTimeoutS(10); Utils::SynchronousProcessResponse response = adb.run(m_adb, selector() << "shell" << "am" << "start" << "-e" << "dummy" << "dummy --dummy"); if (response.result == Utils::SynchronousProcessResponse::StartFailed || response.result != Utils::SynchronousProcessResponse::Finished) return true; const QString output = response.allOutput(); const bool oldSdk = output.contains("Error: No intent supplied"); return !oldSdk; }
void ArtisticStyleSettings::createDocumentationFile() const { Utils::SynchronousProcess process; process.setTimeoutS(2); Utils::SynchronousProcessResponse response = process.runBlocking(command(), QStringList() << QLatin1String("-h")); if (response.result != Utils::SynchronousProcessResponse::Finished) return; QFile file(documentationFilePath()); const QFileInfo fi(file); if (!fi.exists()) fi.dir().mkpath(fi.absolutePath()); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) return; bool contextWritten = false; QXmlStreamWriter stream(&file); stream.setAutoFormatting(true); stream.writeStartDocument("1.0", true); stream.writeComment("Created " + QDateTime::currentDateTime().toString(Qt::ISODate)); stream.writeStartElement(Constants::DOCUMENTATION_XMLROOT); // astyle writes its output to 'error'... const QStringList lines = response.stdErr().split(QLatin1Char('\n')); QStringList keys; QStringList docu; for (QString line : lines) { line = line.trimmed(); if ((line.startsWith("--") && !line.startsWith("---")) || line.startsWith("OR ")) { const QStringList rawKeys = line.split(" OR ", QString::SkipEmptyParts); for (QString k : rawKeys) { k = k.trimmed(); k.remove('#'); keys << k; if (k.startsWith("--")) keys << k.right(k.size() - 2); } } else { if (line.isEmpty()) { if (!keys.isEmpty()) { // Write entry stream.writeStartElement(Constants::DOCUMENTATION_XMLENTRY); stream.writeStartElement(Constants::DOCUMENTATION_XMLKEYS); for (const QString &key : keys) stream.writeTextElement(Constants::DOCUMENTATION_XMLKEY, key); stream.writeEndElement(); const QString text = "<p><span class=\"option\">" + keys.filter(QRegExp("^\\-")).join(", ") + "</span></p><p>" + (docu.join(' ').toHtmlEscaped()) + "</p>"; stream.writeTextElement(Constants::DOCUMENTATION_XMLDOC, text); stream.writeEndElement(); contextWritten = true; } keys.clear(); docu.clear(); } else if (!keys.isEmpty()) { docu << line; } } } stream.writeEndElement(); stream.writeEndDocument(); // An empty file causes error messages and a contextless file preventing this function to run // again in order to generate the documentation successfully. Thus delete the file. if (!contextWritten) { file.close(); file.remove(); } }
void UncrustifySettings::createDocumentationFile() const { Utils::SynchronousProcess process; process.setTimeoutS(2); Utils::SynchronousProcessResponse response = process.run(command(), QStringList() << QLatin1String("--show-config")); if (response.result != Utils::SynchronousProcessResponse::Finished) return; QFile file(documentationFilePath()); const QFileInfo fi(file); if (!fi.exists()) fi.dir().mkpath(fi.absolutePath()); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) return; bool contextWritten = false; QXmlStreamWriter stream(&file); stream.setAutoFormatting(true); stream.writeStartDocument("1.0", true); stream.writeComment("Created " + QDateTime::currentDateTime().toString(Qt::ISODate)); stream.writeStartElement(Constants::DOCUMENTATION_XMLROOT); const QStringList lines = response.allOutput().split(QLatin1Char('\n')); const int totalLines = lines.count(); for (int i = 0; i < totalLines; ++i) { const QString &line = lines.at(i); if (line.startsWith('#') || line.trimmed().isEmpty()) continue; const int firstSpace = line.indexOf(' '); const QString keyword = line.left(firstSpace); const QString options = line.right(line.size() - firstSpace).trimmed(); QStringList docu; while (++i < totalLines) { const QString &subline = lines.at(i); if (line.startsWith('#') || subline.trimmed().isEmpty()) { const QString text = "<p><span class=\"option\">" + keyword + "</span> <span class=\"param\">" + options + "</span></p><p>" + docu.join(' ').toHtmlEscaped() + "</p>"; stream.writeStartElement(Constants::DOCUMENTATION_XMLENTRY); stream.writeTextElement(Constants::DOCUMENTATION_XMLKEY, keyword); stream.writeTextElement(Constants::DOCUMENTATION_XMLDOC, text); stream.writeEndElement(); contextWritten = true; break; } else { docu << subline; } } } stream.writeEndElement(); stream.writeEndDocument(); // An empty file causes error messages and a contextless file preventing this function to run // again in order to generate the documentation successfully. Thus delete the file. if (!contextWritten) { file.close(); file.remove(); } }
Utils::SynchronousProcessResponse VcsCommand::runVcs(const QStringList &arguments, int timeoutMS, Utils::ExitCodeInterpreter *interpreter) { Utils::SynchronousProcessResponse response; OutputProxy outputProxy; if (d->m_binaryPath.isEmpty()) { response.result = Utils::SynchronousProcessResponse::StartFailed; return response; } if (!(d->m_flags & VcsBasePlugin::SuppressCommandLogging)) emit outputProxy.appendCommand(d->m_workingDirectory, d->m_binaryPath, arguments); const bool sshPromptConfigured = !d->m_sshPasswordPrompt.isEmpty(); if (debugExecution) { QDebug nsp = qDebug().nospace(); nsp << "Command::runVcs" << d->m_workingDirectory << d->m_binaryPath << arguments << timeoutMS; if (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow) nsp << "stdout"; if (d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow) nsp << "suppress_stderr"; if (d->m_flags & VcsBasePlugin::SuppressFailMessageInLogWindow) nsp << "suppress_fail_msg"; if (d->m_flags & VcsBasePlugin::MergeOutputChannels) nsp << "merge_channels"; if (d->m_flags & VcsBasePlugin::SshPasswordPrompt) nsp << "ssh (" << sshPromptConfigured << ')'; if (d->m_flags & VcsBasePlugin::SuppressCommandLogging) nsp << "suppress_log"; if (d->m_flags & VcsBasePlugin::ForceCLocale) nsp << "c_locale"; if (d->m_flags & VcsBasePlugin::FullySynchronously) nsp << "fully_synchronously"; if (d->m_flags & VcsBasePlugin::ExpectRepoChanges) nsp << "expect_repo_changes"; if (d->m_codec) nsp << " Codec: " << d->m_codec->name(); } // TODO tell the document manager about expected repository changes // if (d->m_flags & ExpectRepoChanges) // Core::DocumentManager::expectDirectoryChange(d->m_workingDirectory); if (d->m_flags & VcsBasePlugin::FullySynchronously) { response = runSynchronous(arguments, timeoutMS, interpreter); } else { Utils::SynchronousProcess process; process.setExitCodeInterpreter(interpreter); connect(this, &VcsCommand::terminate, &process, &Utils::SynchronousProcess::terminate); if (!d->m_workingDirectory.isEmpty()) process.setWorkingDirectory(d->m_workingDirectory); QProcessEnvironment env = d->m_environment; VcsBasePlugin::setProcessEnvironment(&env, (d->m_flags & VcsBasePlugin::ForceCLocale), d->m_sshPasswordPrompt); process.setProcessEnvironment(env); process.setTimeout(timeoutMS); if (d->m_codec) process.setCodec(d->m_codec); // Suppress terminal on UNIX for ssh prompts if it is configured. if (sshPromptConfigured && (d->m_flags & VcsBasePlugin::SshPasswordPrompt)) process.setFlags(Utils::SynchronousProcess::UnixTerminalDisabled); // connect stderr to the output window if desired if (d->m_flags & VcsBasePlugin::MergeOutputChannels) { process.setProcessChannelMode(QProcess::MergedChannels); } else if (d->m_progressiveOutput || !(d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow)) { process.setStdErrBufferedSignalsEnabled(true); connect(&process, &Utils::SynchronousProcess::stdErrBuffered, this, &VcsCommand::bufferedError); } // connect stdout to the output window if desired if (d->m_progressParser || d->m_progressiveOutput || (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow)) { process.setStdOutBufferedSignalsEnabled(true); connect(&process, &Utils::SynchronousProcess::stdOutBuffered, this, &VcsCommand::bufferedOutput); } process.setTimeOutMessageBoxEnabled(true); // Run! response = process.run(d->m_binaryPath.toString(), arguments); } if (!d->m_aborted) { // Success/Fail message in appropriate window? if (response.result == Utils::SynchronousProcessResponse::Finished) { if (d->m_flags & VcsBasePlugin::ShowSuccessMessage) { emit outputProxy.appendMessage(response.exitMessage(d->m_binaryPath.toUserOutput(), timeoutMS)); } } else if (!(d->m_flags & VcsBasePlugin::SuppressFailMessageInLogWindow)) { emit outputProxy.appendError(response.exitMessage(d->m_binaryPath.toUserOutput(), timeoutMS)); } } emitRepositoryChanged(); return response; }