2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
2008-12-02 16:19:05 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "environment.h"
|
|
|
|
|
|
2017-04-19 14:47:48 +02:00
|
|
|
#include "algorithm.h"
|
2022-05-24 00:40:44 +02:00
|
|
|
#include "fileutils.h"
|
2017-06-20 11:30:21 +03:00
|
|
|
#include "qtcassert.h"
|
2017-04-19 14:47:48 +02:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDir>
|
2013-01-11 12:37:38 +01:00
|
|
|
#include <QProcessEnvironment>
|
2014-03-05 11:17:10 +01:00
|
|
|
#include <QSet>
|
2012-04-30 19:01:26 +02:00
|
|
|
|
2022-05-24 00:40:44 +02:00
|
|
|
namespace Utils {
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2022-05-24 00:40:44 +02:00
|
|
|
Q_GLOBAL_STATIC_WITH_ARGS(Environment, staticSystemEnvironment,
|
|
|
|
|
(QProcessEnvironment::systemEnvironment().toStringList()))
|
2018-09-25 13:56:46 +02:00
|
|
|
|
2022-05-24 00:40:44 +02:00
|
|
|
Q_GLOBAL_STATIC(QVector<EnvironmentProvider>, environmentProviders)
|
2019-05-07 16:51:22 +02:00
|
|
|
|
2022-06-01 12:34:08 +02:00
|
|
|
NameValueItems Environment::diff(const Environment &other, bool checkAppendPrepend) const
|
|
|
|
|
{
|
|
|
|
|
return m_dict.diff(other.m_dict, checkAppendPrepend);
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-01 15:19:31 +02:00
|
|
|
int Environment::isValid() const
|
|
|
|
|
{
|
|
|
|
|
return m_dict.size() != 0;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-15 13:45:46 +01:00
|
|
|
QProcessEnvironment Environment::toProcessEnvironment() const
|
|
|
|
|
{
|
|
|
|
|
QProcessEnvironment result;
|
2022-06-01 12:34:08 +02:00
|
|
|
for (auto it = m_dict.m_values.constBegin(); it != m_dict.m_values.constEnd(); ++it) {
|
2019-07-09 17:41:30 +02:00
|
|
|
if (it.value().second)
|
2019-08-16 16:42:14 +02:00
|
|
|
result.insert(it.key().name, expandedValueForKey(key(it)));
|
2019-07-09 17:41:30 +02:00
|
|
|
}
|
2013-01-15 13:45:46 +01:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-09 18:20:14 +01:00
|
|
|
void Environment::appendOrSetPath(const FilePath &value)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2022-06-01 12:34:08 +02:00
|
|
|
QTC_CHECK(value.osType() == osType());
|
2021-11-09 18:20:14 +01:00
|
|
|
if (value.isEmpty())
|
|
|
|
|
return;
|
2021-11-10 16:19:25 +01:00
|
|
|
appendOrSet("PATH", value.nativePath(),
|
2022-06-01 12:34:08 +02:00
|
|
|
QString(OsSpecificAspects::pathListSeparator(osType())));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2021-11-09 18:20:14 +01:00
|
|
|
void Environment::prependOrSetPath(const FilePath &value)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2022-06-01 12:34:08 +02:00
|
|
|
QTC_CHECK(value.osType() == osType());
|
2021-11-09 18:20:14 +01:00
|
|
|
if (value.isEmpty())
|
|
|
|
|
return;
|
2021-11-10 16:19:25 +01:00
|
|
|
prependOrSet("PATH", value.nativePath(),
|
2022-06-01 12:34:08 +02:00
|
|
|
QString(OsSpecificAspects::pathListSeparator(osType())));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Environment::appendOrSet(const QString &key, const QString &value, const QString &sep)
|
|
|
|
|
{
|
2019-05-07 16:51:22 +02:00
|
|
|
QTC_ASSERT(!key.contains('='), return );
|
2022-06-01 12:34:08 +02:00
|
|
|
const auto it = m_dict.findKey(key);
|
|
|
|
|
if (it == m_dict.m_values.end()) {
|
2022-09-30 11:40:32 +02:00
|
|
|
m_dict.m_values.insert(DictKey(key, m_dict.nameCaseSensitivity()), {value, true});
|
2008-12-02 12:01:29 +01:00
|
|
|
} else {
|
2010-02-17 17:38:48 +01:00
|
|
|
// Append unless it is already there
|
|
|
|
|
const QString toAppend = sep + value;
|
2019-07-09 17:41:30 +02:00
|
|
|
if (!it.value().first.endsWith(toAppend))
|
|
|
|
|
it.value().first.append(toAppend);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-07 16:51:22 +02:00
|
|
|
void Environment::prependOrSet(const QString &key, const QString &value, const QString &sep)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2019-05-07 16:51:22 +02:00
|
|
|
QTC_ASSERT(!key.contains('='), return );
|
2022-06-01 12:34:08 +02:00
|
|
|
const auto it = m_dict.findKey(key);
|
|
|
|
|
if (it == m_dict.m_values.end()) {
|
2022-09-30 11:40:32 +02:00
|
|
|
m_dict.m_values.insert(DictKey(key, m_dict.nameCaseSensitivity()), {value, true});
|
2008-12-02 12:01:29 +01:00
|
|
|
} else {
|
2010-02-17 17:38:48 +01:00
|
|
|
// Prepend unless it is already there
|
|
|
|
|
const QString toPrepend = value + sep;
|
2019-07-09 17:41:30 +02:00
|
|
|
if (!it.value().first.startsWith(toPrepend))
|
|
|
|
|
it.value().first.prepend(toPrepend);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-09 18:20:14 +01:00
|
|
|
void Environment::prependOrSetLibrarySearchPath(const FilePath &value)
|
2011-04-29 13:25:25 +02:00
|
|
|
{
|
2022-06-01 12:34:08 +02:00
|
|
|
QTC_CHECK(value.osType() == osType());
|
|
|
|
|
switch (osType()) {
|
2013-08-15 16:08:16 +02:00
|
|
|
case OsTypeWindows: {
|
2017-04-19 14:26:54 +02:00
|
|
|
const QChar sep = ';';
|
2021-11-10 16:19:25 +01:00
|
|
|
prependOrSet("PATH", value.nativePath(), QString(sep));
|
2012-08-23 15:53:58 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2015-09-02 17:06:58 +02:00
|
|
|
case OsTypeMac: {
|
2017-04-19 14:26:54 +02:00
|
|
|
const QString sep = ":";
|
2021-11-10 16:19:25 +01:00
|
|
|
const QString nativeValue = value.nativePath();
|
2017-04-19 14:26:54 +02:00
|
|
|
prependOrSet("DYLD_LIBRARY_PATH", nativeValue, sep);
|
|
|
|
|
prependOrSet("DYLD_FRAMEWORK_PATH", nativeValue, sep);
|
2015-09-02 17:06:58 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2013-08-15 16:08:16 +02:00
|
|
|
case OsTypeLinux:
|
|
|
|
|
case OsTypeOtherUnix: {
|
2017-04-19 14:26:54 +02:00
|
|
|
const QChar sep = ':';
|
2021-11-10 16:19:25 +01:00
|
|
|
prependOrSet("LD_LIBRARY_PATH", value.nativePath(), QString(sep));
|
2012-08-23 15:53:58 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2015-09-02 17:06:58 +02:00
|
|
|
default:
|
2012-08-23 15:53:58 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2011-04-29 13:25:25 +02:00
|
|
|
}
|
|
|
|
|
|
2021-11-09 18:20:14 +01:00
|
|
|
void Environment::prependOrSetLibrarySearchPaths(const FilePaths &values)
|
2018-01-08 22:46:54 +02:00
|
|
|
{
|
2022-05-24 00:40:44 +02:00
|
|
|
reverseForeach(values, [this](const FilePath &value) {
|
2018-01-08 22:46:54 +02:00
|
|
|
prependOrSetLibrarySearchPath(value);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
Environment Environment::systemEnvironment()
|
|
|
|
|
{
|
2012-04-30 19:01:26 +02:00
|
|
|
return *staticSystemEnvironment();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2021-05-20 11:57:21 +02:00
|
|
|
void Environment::setupEnglishOutput()
|
2016-04-07 13:06:01 +02:00
|
|
|
{
|
2022-06-01 12:34:08 +02:00
|
|
|
m_dict.set("LC_MESSAGES", "en_US.utf8");
|
|
|
|
|
m_dict.set("LANGUAGE", "en_US:en");
|
2016-04-07 13:06:01 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-06 16:47:48 +02:00
|
|
|
static FilePath searchInDirectory(const QStringList &execs,
|
2021-10-04 10:59:41 +02:00
|
|
|
const FilePath &directory,
|
|
|
|
|
QSet<FilePath> &alreadyChecked)
|
2012-09-11 13:56:08 +02:00
|
|
|
{
|
2017-09-20 12:53:30 +02:00
|
|
|
const int checkedCount = alreadyChecked.count();
|
|
|
|
|
alreadyChecked.insert(directory);
|
2012-09-11 13:56:08 +02:00
|
|
|
|
2017-09-20 12:53:30 +02:00
|
|
|
if (directory.isEmpty() || alreadyChecked.count() == checkedCount)
|
2019-05-28 13:49:26 +02:00
|
|
|
return FilePath();
|
2017-04-19 14:47:48 +02:00
|
|
|
|
2017-09-20 12:53:30 +02:00
|
|
|
const QString dir = directory.toString();
|
2017-04-19 14:47:48 +02:00
|
|
|
|
2017-09-20 12:53:30 +02:00
|
|
|
QFileInfo fi;
|
2017-04-19 14:47:48 +02:00
|
|
|
for (const QString &exec : execs) {
|
2017-09-20 12:53:30 +02:00
|
|
|
fi.setFile(dir, exec);
|
2017-04-19 14:47:48 +02:00
|
|
|
if (fi.isFile() && fi.isExecutable())
|
2019-05-28 13:49:26 +02:00
|
|
|
return FilePath::fromString(fi.absoluteFilePath());
|
2012-09-11 13:56:08 +02:00
|
|
|
}
|
2019-05-28 13:49:26 +02:00
|
|
|
return FilePath();
|
2012-09-11 13:56:08 +02:00
|
|
|
}
|
|
|
|
|
|
2015-07-15 14:21:45 +02:00
|
|
|
QStringList Environment::appendExeExtensions(const QString &executable) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2015-07-15 14:21:45 +02:00
|
|
|
QStringList execs(executable);
|
2017-04-19 14:50:38 +02:00
|
|
|
const QFileInfo fi(executable);
|
2022-06-01 12:34:08 +02:00
|
|
|
if (osType() == OsTypeWindows) {
|
2012-08-23 15:53:58 +02:00
|
|
|
// Check all the executable extensions on windows:
|
2012-09-12 17:27:37 +02:00
|
|
|
// PATHEXT is only used if the executable has no extension
|
|
|
|
|
if (fi.suffix().isEmpty()) {
|
2019-08-19 14:29:14 +02:00
|
|
|
const QStringList extensions = expandedValueForKey("PATHEXT").split(';');
|
2012-08-23 15:53:58 +02:00
|
|
|
|
2017-04-19 14:50:38 +02:00
|
|
|
for (const QString &ext : extensions)
|
2015-07-15 14:21:45 +02:00
|
|
|
execs << executable + ext.toLower();
|
2012-09-12 17:27:37 +02:00
|
|
|
}
|
2012-08-23 15:53:58 +02:00
|
|
|
}
|
2015-07-15 14:21:45 +02:00
|
|
|
return execs;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-23 17:17:58 +01:00
|
|
|
bool Environment::isSameExecutable(const QString &exe1, const QString &exe2) const
|
|
|
|
|
{
|
|
|
|
|
const QStringList exe1List = appendExeExtensions(exe1);
|
|
|
|
|
const QStringList exe2List = appendExeExtensions(exe2);
|
|
|
|
|
for (const QString &i1 : exe1List) {
|
|
|
|
|
for (const QString &i2 : exe2List) {
|
2019-05-28 13:49:26 +02:00
|
|
|
const FilePath f1 = FilePath::fromString(i1);
|
|
|
|
|
const FilePath f2 = FilePath::fromString(i2);
|
2022-10-13 11:11:29 +02:00
|
|
|
if (f1.isSameFile(f2))
|
2019-04-04 16:18:20 +02:00
|
|
|
return true;
|
2017-03-23 17:17:58 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-19 14:29:14 +02:00
|
|
|
QString Environment::expandedValueForKey(const QString &key) const
|
|
|
|
|
{
|
2022-06-01 12:34:08 +02:00
|
|
|
return expandVariables(m_dict.value(key));
|
2019-08-19 14:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-04 10:59:41 +02:00
|
|
|
static FilePath searchInDirectoriesHelper(const Environment &env,
|
|
|
|
|
const QString &executable,
|
|
|
|
|
const FilePaths &dirs,
|
|
|
|
|
const Environment::PathFilter &func,
|
|
|
|
|
bool usePath)
|
2015-07-15 14:21:45 +02:00
|
|
|
{
|
|
|
|
|
if (executable.isEmpty())
|
2019-05-28 13:49:26 +02:00
|
|
|
return FilePath();
|
2010-09-23 13:08:03 +02:00
|
|
|
|
2021-10-04 10:59:41 +02:00
|
|
|
const QString exec = QDir::cleanPath(env.expandVariables(executable));
|
2017-04-19 14:47:48 +02:00
|
|
|
const QFileInfo fi(exec);
|
2015-07-15 14:21:45 +02:00
|
|
|
|
2021-10-04 10:59:41 +02:00
|
|
|
const QStringList execs = env.appendExeExtensions(exec);
|
2015-07-15 14:21:45 +02:00
|
|
|
|
|
|
|
|
if (fi.isAbsolute()) {
|
2017-04-19 14:47:48 +02:00
|
|
|
for (const QString &path : execs) {
|
|
|
|
|
QFileInfo pfi = QFileInfo(path);
|
|
|
|
|
if (pfi.isFile() && pfi.isExecutable())
|
2019-05-28 13:49:26 +02:00
|
|
|
return FilePath::fromString(path);
|
2017-04-19 14:47:48 +02:00
|
|
|
}
|
2019-05-28 13:49:26 +02:00
|
|
|
return FilePath::fromString(exec);
|
2015-07-15 14:21:45 +02:00
|
|
|
}
|
2013-05-17 08:17:43 +03:00
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
QSet<FilePath> alreadyChecked;
|
2021-10-04 10:59:41 +02:00
|
|
|
for (const FilePath &dir : dirs) {
|
2021-10-06 16:47:48 +02:00
|
|
|
FilePath tmp = searchInDirectory(execs, dir, alreadyChecked);
|
2017-09-20 12:53:30 +02:00
|
|
|
if (!tmp.isEmpty() && (!func || func(tmp)))
|
2012-09-11 13:56:08 +02:00
|
|
|
return tmp;
|
|
|
|
|
}
|
2010-09-23 13:08:03 +02:00
|
|
|
|
2021-10-04 10:59:41 +02:00
|
|
|
if (usePath) {
|
|
|
|
|
if (executable.contains('/'))
|
|
|
|
|
return FilePath();
|
2012-09-11 13:56:08 +02:00
|
|
|
|
2021-10-04 10:59:41 +02:00
|
|
|
for (const FilePath &p : env.path()) {
|
2021-10-06 16:47:48 +02:00
|
|
|
FilePath tmp = searchInDirectory(execs, p, alreadyChecked);
|
2021-10-04 10:59:41 +02:00
|
|
|
if (!tmp.isEmpty() && (!func || func(tmp)))
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
2010-09-23 13:08:03 +02:00
|
|
|
}
|
2019-05-28 13:49:26 +02:00
|
|
|
return FilePath();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2021-10-04 10:59:41 +02:00
|
|
|
FilePath Environment::searchInDirectories(const QString &executable,
|
|
|
|
|
const FilePaths &dirs) const
|
|
|
|
|
{
|
|
|
|
|
return searchInDirectoriesHelper(*this, executable, dirs, {}, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FilePath Environment::searchInPath(const QString &executable,
|
|
|
|
|
const FilePaths &additionalDirs,
|
|
|
|
|
const PathFilter &func) const
|
|
|
|
|
{
|
|
|
|
|
return searchInDirectoriesHelper(*this, executable, additionalDirs, func, true);
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-17 14:07:53 +01:00
|
|
|
FilePaths Environment::findAllInPath(const QString &executable,
|
|
|
|
|
const FilePaths &additionalDirs,
|
2019-07-09 09:02:02 +02:00
|
|
|
const Environment::PathFilter &func) const
|
|
|
|
|
{
|
|
|
|
|
if (executable.isEmpty())
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
const QString exec = QDir::cleanPath(expandVariables(executable));
|
|
|
|
|
const QFileInfo fi(exec);
|
|
|
|
|
|
|
|
|
|
const QStringList execs = appendExeExtensions(exec);
|
|
|
|
|
|
|
|
|
|
if (fi.isAbsolute()) {
|
|
|
|
|
for (const QString &path : execs) {
|
|
|
|
|
QFileInfo pfi = QFileInfo(path);
|
|
|
|
|
if (pfi.isFile() && pfi.isExecutable())
|
|
|
|
|
return {FilePath::fromString(path)};
|
|
|
|
|
}
|
|
|
|
|
return {FilePath::fromString(exec)};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QSet<FilePath> result;
|
|
|
|
|
QSet<FilePath> alreadyChecked;
|
|
|
|
|
for (const FilePath &dir : additionalDirs) {
|
2021-10-06 16:47:48 +02:00
|
|
|
FilePath tmp = searchInDirectory(execs, dir, alreadyChecked);
|
2019-07-09 09:02:02 +02:00
|
|
|
if (!tmp.isEmpty() && (!func || func(tmp)))
|
|
|
|
|
result << tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!executable.contains('/')) {
|
|
|
|
|
for (const FilePath &p : path()) {
|
2021-10-06 16:47:48 +02:00
|
|
|
FilePath tmp = searchInDirectory(execs, p, alreadyChecked);
|
2019-07-09 09:02:02 +02:00
|
|
|
if (!tmp.isEmpty() && (!func || func(tmp)))
|
|
|
|
|
result << tmp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result.values();
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-17 14:07:53 +01:00
|
|
|
FilePaths Environment::path() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2019-07-05 16:58:07 +02:00
|
|
|
return pathListValue("PATH");
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-17 14:07:53 +01:00
|
|
|
FilePaths Environment::pathListValue(const QString &varName) const
|
2019-07-05 16:58:07 +02:00
|
|
|
{
|
2020-08-18 13:55:38 +02:00
|
|
|
const QStringList pathComponents = expandedValueForKey(varName).split(
|
2022-06-01 12:34:08 +02:00
|
|
|
OsSpecificAspects::pathListSeparator(osType()), Qt::SkipEmptyParts);
|
2019-07-05 16:58:07 +02:00
|
|
|
return transform(pathComponents, &FilePath::fromUserInput);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2019-05-07 16:51:22 +02:00
|
|
|
void Environment::modifySystemEnvironment(const EnvironmentItems &list)
|
2018-08-09 11:31:41 +02:00
|
|
|
{
|
|
|
|
|
staticSystemEnvironment->modify(list);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-16 16:40:12 +01:00
|
|
|
void Environment::setSystemEnvironment(const Environment &environment)
|
|
|
|
|
{
|
|
|
|
|
*staticSystemEnvironment = environment;
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-22 15:10:20 +02:00
|
|
|
/** Expand environment variables in a string.
|
|
|
|
|
*
|
|
|
|
|
* Environment variables are accepted in the following forms:
|
2010-10-19 11:10:58 +02:00
|
|
|
* $SOMEVAR, ${SOMEVAR} on Unix and %SOMEVAR% on Windows.
|
|
|
|
|
* No escapes and quoting are supported.
|
|
|
|
|
* If a variable is not found, it is not substituted.
|
2010-09-22 15:10:20 +02:00
|
|
|
*/
|
|
|
|
|
QString Environment::expandVariables(const QString &input) const
|
|
|
|
|
{
|
2010-10-19 11:10:58 +02:00
|
|
|
QString result = input;
|
|
|
|
|
|
2022-06-01 12:34:08 +02:00
|
|
|
if (osType() == OsTypeWindows) {
|
2012-08-23 15:53:58 +02:00
|
|
|
for (int vStart = -1, i = 0; i < result.length(); ) {
|
2017-04-19 14:26:54 +02:00
|
|
|
if (result.at(i++) == '%') {
|
2012-08-23 15:53:58 +02:00
|
|
|
if (vStart > 0) {
|
2022-06-01 12:34:08 +02:00
|
|
|
const auto it = m_dict.findKey(result.mid(vStart, i - vStart - 1));
|
|
|
|
|
if (it != m_dict.m_values.constEnd()) {
|
2019-07-09 17:41:30 +02:00
|
|
|
result.replace(vStart - 1, i - vStart + 1, it->first);
|
|
|
|
|
i = vStart - 1 + it->first.length();
|
2012-08-23 15:53:58 +02:00
|
|
|
vStart = -1;
|
|
|
|
|
} else {
|
|
|
|
|
vStart = i;
|
|
|
|
|
}
|
2010-10-19 11:10:58 +02:00
|
|
|
} else {
|
|
|
|
|
vStart = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-08-23 15:53:58 +02:00
|
|
|
} else {
|
|
|
|
|
enum { BASE, OPTIONALVARIABLEBRACE, VARIABLE, BRACEDVARIABLE } state = BASE;
|
|
|
|
|
int vStart = -1;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < result.length();) {
|
|
|
|
|
QChar c = result.at(i++);
|
|
|
|
|
if (state == BASE) {
|
2017-04-19 14:26:54 +02:00
|
|
|
if (c == '$')
|
2012-08-23 15:53:58 +02:00
|
|
|
state = OPTIONALVARIABLEBRACE;
|
|
|
|
|
} else if (state == OPTIONALVARIABLEBRACE) {
|
2017-04-19 14:26:54 +02:00
|
|
|
if (c == '{') {
|
2012-08-23 15:53:58 +02:00
|
|
|
state = BRACEDVARIABLE;
|
|
|
|
|
vStart = i;
|
2017-04-19 14:26:54 +02:00
|
|
|
} else if (c.isLetterOrNumber() || c == '_') {
|
2012-08-23 15:53:58 +02:00
|
|
|
state = VARIABLE;
|
|
|
|
|
vStart = i - 1;
|
|
|
|
|
} else {
|
|
|
|
|
state = BASE;
|
2010-10-19 11:10:58 +02:00
|
|
|
}
|
2012-08-23 15:53:58 +02:00
|
|
|
} else if (state == BRACEDVARIABLE) {
|
2017-04-19 14:26:54 +02:00
|
|
|
if (c == '}') {
|
2019-08-16 16:42:14 +02:00
|
|
|
const_iterator it = constFind(result.mid(vStart, i - 1 - vStart));
|
2012-08-23 15:53:58 +02:00
|
|
|
if (it != constEnd()) {
|
2019-07-09 17:41:30 +02:00
|
|
|
result.replace(vStart - 2, i - vStart + 2, it->first);
|
|
|
|
|
i = vStart - 2 + it->first.length();
|
2012-08-23 15:53:58 +02:00
|
|
|
}
|
|
|
|
|
state = BASE;
|
|
|
|
|
}
|
|
|
|
|
} else if (state == VARIABLE) {
|
2017-04-19 14:26:54 +02:00
|
|
|
if (!c.isLetterOrNumber() && c != '_') {
|
2019-08-16 16:42:14 +02:00
|
|
|
const_iterator it = constFind(result.mid(vStart, i - vStart - 1));
|
2012-08-23 15:53:58 +02:00
|
|
|
if (it != constEnd()) {
|
2019-07-09 17:41:30 +02:00
|
|
|
result.replace(vStart - 1, i - vStart, it->first);
|
|
|
|
|
i = vStart - 1 + it->first.length();
|
2012-08-23 15:53:58 +02:00
|
|
|
}
|
|
|
|
|
state = BASE;
|
2010-10-19 11:10:58 +02:00
|
|
|
}
|
2010-09-22 15:10:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
2012-08-23 15:53:58 +02:00
|
|
|
if (state == VARIABLE) {
|
2019-08-16 16:42:14 +02:00
|
|
|
const_iterator it = constFind(result.mid(vStart));
|
2012-08-23 15:53:58 +02:00
|
|
|
if (it != constEnd())
|
2019-07-09 17:41:30 +02:00
|
|
|
result.replace(vStart - 1, result.length() - vStart + 1, it->first);
|
2012-08-23 15:53:58 +02:00
|
|
|
}
|
2010-09-22 15:10:20 +02:00
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2010-09-23 13:08:03 +02:00
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
FilePath Environment::expandVariables(const FilePath &variables) const
|
2019-05-15 13:59:43 +02:00
|
|
|
{
|
2019-05-28 13:49:26 +02:00
|
|
|
return FilePath::fromString(expandVariables(variables.toString()));
|
2019-05-15 13:59:43 +02:00
|
|
|
}
|
|
|
|
|
|
2010-09-23 13:08:03 +02:00
|
|
|
QStringList Environment::expandVariables(const QStringList &variables) const
|
|
|
|
|
{
|
2022-05-24 00:40:44 +02:00
|
|
|
return transform(variables, [this](const QString &i) { return expandVariables(i); });
|
2010-09-23 13:08:03 +02:00
|
|
|
}
|
2011-05-24 12:04:24 +02:00
|
|
|
|
2018-09-25 13:56:46 +02:00
|
|
|
void EnvironmentProvider::addProvider(EnvironmentProvider &&provider)
|
|
|
|
|
{
|
|
|
|
|
environmentProviders->append(std::move(provider));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QVector<EnvironmentProvider> EnvironmentProvider::providers()
|
|
|
|
|
{
|
|
|
|
|
return *environmentProviders;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-26 10:30:00 +02:00
|
|
|
std::optional<EnvironmentProvider> EnvironmentProvider::provider(const QByteArray &id)
|
2018-09-25 13:56:46 +02:00
|
|
|
{
|
|
|
|
|
const int index = indexOf(*environmentProviders, equal(&EnvironmentProvider::id, id));
|
|
|
|
|
if (index >= 0)
|
2022-08-26 10:30:00 +02:00
|
|
|
return std::make_optional(environmentProviders->at(index));
|
|
|
|
|
return std::nullopt;
|
2018-09-25 13:56:46 +02:00
|
|
|
}
|
|
|
|
|
|
2021-05-25 15:25:37 +02:00
|
|
|
void EnvironmentChange::addSetValue(const QString &key, const QString &value)
|
|
|
|
|
{
|
2022-06-01 13:04:57 +02:00
|
|
|
m_changeItems.append({Item::SetValue, QVariant::fromValue(QPair<QString, QString>(key, value))});
|
2021-05-25 15:25:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EnvironmentChange::addUnsetValue(const QString &key)
|
|
|
|
|
{
|
2022-06-01 13:04:57 +02:00
|
|
|
m_changeItems.append({Item::UnsetValue, key});
|
2021-05-25 15:25:37 +02:00
|
|
|
}
|
|
|
|
|
|
2021-11-09 18:20:14 +01:00
|
|
|
void EnvironmentChange::addPrependToPath(const FilePaths &values)
|
2021-05-25 15:25:37 +02:00
|
|
|
{
|
2021-08-03 15:12:24 +02:00
|
|
|
for (int i = values.size(); --i >= 0; ) {
|
2021-11-09 18:20:14 +01:00
|
|
|
const FilePath value = values.at(i);
|
2022-06-01 13:04:57 +02:00
|
|
|
m_changeItems.append({Item::PrependToPath, value.toVariant()});
|
2021-08-03 15:12:24 +02:00
|
|
|
}
|
2021-05-25 15:25:37 +02:00
|
|
|
}
|
|
|
|
|
|
2021-11-09 18:20:14 +01:00
|
|
|
void EnvironmentChange::addAppendToPath(const FilePaths &values)
|
2021-05-25 15:25:37 +02:00
|
|
|
{
|
2021-11-09 18:20:14 +01:00
|
|
|
for (const FilePath &value : values)
|
2022-06-01 13:04:57 +02:00
|
|
|
m_changeItems.append({Item::AppendToPath, value.toVariant()});
|
2021-05-25 15:25:37 +02:00
|
|
|
}
|
|
|
|
|
|
2021-08-03 15:12:24 +02:00
|
|
|
EnvironmentChange EnvironmentChange::fromFixedEnvironment(const Environment &fixedEnv)
|
|
|
|
|
{
|
|
|
|
|
EnvironmentChange change;
|
2022-06-01 13:04:57 +02:00
|
|
|
change.m_changeItems.append({Item::SetFixedEnvironment, QVariant::fromValue(fixedEnv)});
|
2021-08-03 15:12:24 +02:00
|
|
|
return change;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-25 15:25:37 +02:00
|
|
|
void EnvironmentChange::applyToEnvironment(Environment &env) const
|
|
|
|
|
{
|
2022-06-01 13:04:57 +02:00
|
|
|
for (const Item &item : m_changeItems) {
|
|
|
|
|
switch (item.type) {
|
|
|
|
|
case Item::SetSystemEnvironment:
|
|
|
|
|
env = Environment::systemEnvironment();
|
|
|
|
|
break;
|
|
|
|
|
case Item::SetFixedEnvironment:
|
|
|
|
|
env = item.data.value<Environment>();
|
|
|
|
|
break;
|
|
|
|
|
case Item::SetValue: {
|
|
|
|
|
auto data = item.data.value<QPair<QString, QString>>();
|
|
|
|
|
env.set(data.first, data.second);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case Item::UnsetValue:
|
|
|
|
|
env.unset(item.data.toString());
|
|
|
|
|
break;
|
|
|
|
|
case Item::PrependToPath:
|
|
|
|
|
env.prependOrSetPath(FilePath::fromVariant(item.data));
|
|
|
|
|
break;
|
|
|
|
|
case Item::AppendToPath:
|
|
|
|
|
env.appendOrSetPath(FilePath::fromVariant(item.data));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-25 15:25:37 +02:00
|
|
|
}
|
|
|
|
|
|
2022-08-23 15:42:37 +02:00
|
|
|
/*!
|
|
|
|
|
Returns the value of \a key in \QC's modified system environment.
|
|
|
|
|
\sa Utils::Environment::systemEnvironment
|
|
|
|
|
\sa qEnvironmentVariable
|
|
|
|
|
*/
|
|
|
|
|
QString qtcEnvironmentVariable(const QString &key)
|
|
|
|
|
{
|
|
|
|
|
return Environment::systemEnvironment().value(key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Returns the value of \a key in \QC's modified system environment if it is set,
|
|
|
|
|
or otherwise \a defaultValue.
|
|
|
|
|
\sa Utils::Environment::systemEnvironment
|
|
|
|
|
\sa qEnvironmentVariable
|
|
|
|
|
*/
|
|
|
|
|
QString qtcEnvironmentVariable(const QString &key, const QString &defaultValue)
|
|
|
|
|
{
|
|
|
|
|
if (Environment::systemEnvironment().hasKey(key))
|
|
|
|
|
return Environment::systemEnvironment().value(key);
|
|
|
|
|
return defaultValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Returns if the environment variable \a key is set \QC's modified system environment.
|
|
|
|
|
\sa Utils::Environment::systemEnvironment
|
|
|
|
|
\sa qEnvironmentVariableIsSet
|
|
|
|
|
*/
|
|
|
|
|
bool qtcEnvironmentVariableIsSet(const QString &key)
|
|
|
|
|
{
|
|
|
|
|
return Environment::systemEnvironment().hasKey(key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Returns if the environment variable \a key is not set or empty in \QC's modified system
|
|
|
|
|
environment.
|
|
|
|
|
\sa Utils::Environment::systemEnvironment
|
|
|
|
|
\sa qEnvironmentVariableIsEmpty
|
|
|
|
|
*/
|
|
|
|
|
bool qtcEnvironmentVariableIsEmpty(const QString &key)
|
|
|
|
|
{
|
|
|
|
|
return Environment::systemEnvironment().value(key).isEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Returns the value of \a key in \QC's modified system environment, converted to an int.
|
|
|
|
|
If \a ok is not null, sets \c{*ok} to true or false depending on the success of the conversion
|
|
|
|
|
\sa Utils::Environment::systemEnvironment
|
|
|
|
|
\sa qEnvironmentVariableIntValue
|
|
|
|
|
*/
|
|
|
|
|
int qtcEnvironmentVariableIntValue(const QString &key, bool *ok)
|
|
|
|
|
{
|
|
|
|
|
return Environment::systemEnvironment().value(key).toInt(ok);
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-24 12:04:24 +02:00
|
|
|
} // namespace Utils
|