forked from qt-creator/qt-creator
Utils: Make Environment has-a NameValueDictory instead of is-a
We need a somewhat more wholistic approach on how to communicate environment data and changes in the code, a single fixed map doesn't cut it. Change-Id: Ifbed254e7e0f4a76f8627e77030889c326f551d4 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -40,10 +40,15 @@ Q_GLOBAL_STATIC_WITH_ARGS(Environment, staticSystemEnvironment,
|
|||||||
|
|
||||||
Q_GLOBAL_STATIC(QVector<EnvironmentProvider>, environmentProviders)
|
Q_GLOBAL_STATIC(QVector<EnvironmentProvider>, environmentProviders)
|
||||||
|
|
||||||
|
NameValueItems Environment::diff(const Environment &other, bool checkAppendPrepend) const
|
||||||
|
{
|
||||||
|
return m_dict.diff(other.m_dict, checkAppendPrepend);
|
||||||
|
}
|
||||||
|
|
||||||
QProcessEnvironment Environment::toProcessEnvironment() const
|
QProcessEnvironment Environment::toProcessEnvironment() const
|
||||||
{
|
{
|
||||||
QProcessEnvironment result;
|
QProcessEnvironment result;
|
||||||
for (auto it = m_values.constBegin(); it != m_values.constEnd(); ++it) {
|
for (auto it = m_dict.m_values.constBegin(); it != m_dict.m_values.constEnd(); ++it) {
|
||||||
if (it.value().second)
|
if (it.value().second)
|
||||||
result.insert(it.key().name, expandedValueForKey(key(it)));
|
result.insert(it.key().name, expandedValueForKey(key(it)));
|
||||||
}
|
}
|
||||||
@@ -52,28 +57,28 @@ QProcessEnvironment Environment::toProcessEnvironment() const
|
|||||||
|
|
||||||
void Environment::appendOrSetPath(const FilePath &value)
|
void Environment::appendOrSetPath(const FilePath &value)
|
||||||
{
|
{
|
||||||
QTC_CHECK(value.osType() == m_osType);
|
QTC_CHECK(value.osType() == osType());
|
||||||
if (value.isEmpty())
|
if (value.isEmpty())
|
||||||
return;
|
return;
|
||||||
appendOrSet("PATH", value.nativePath(),
|
appendOrSet("PATH", value.nativePath(),
|
||||||
QString(OsSpecificAspects::pathListSeparator(m_osType)));
|
QString(OsSpecificAspects::pathListSeparator(osType())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Environment::prependOrSetPath(const FilePath &value)
|
void Environment::prependOrSetPath(const FilePath &value)
|
||||||
{
|
{
|
||||||
QTC_CHECK(value.osType() == m_osType);
|
QTC_CHECK(value.osType() == osType());
|
||||||
if (value.isEmpty())
|
if (value.isEmpty())
|
||||||
return;
|
return;
|
||||||
prependOrSet("PATH", value.nativePath(),
|
prependOrSet("PATH", value.nativePath(),
|
||||||
QString(OsSpecificAspects::pathListSeparator(m_osType)));
|
QString(OsSpecificAspects::pathListSeparator(osType())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Environment::appendOrSet(const QString &key, const QString &value, const QString &sep)
|
void Environment::appendOrSet(const QString &key, const QString &value, const QString &sep)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!key.contains('='), return );
|
QTC_ASSERT(!key.contains('='), return );
|
||||||
const auto it = findKey(key);
|
const auto it = m_dict.findKey(key);
|
||||||
if (it == m_values.end()) {
|
if (it == m_dict.m_values.end()) {
|
||||||
m_values.insert(DictKey(key, nameCaseSensitivity()), qMakePair(value, true));
|
m_dict.m_values.insert(DictKey(key, m_dict.nameCaseSensitivity()), qMakePair(value, true));
|
||||||
} else {
|
} else {
|
||||||
// Append unless it is already there
|
// Append unless it is already there
|
||||||
const QString toAppend = sep + value;
|
const QString toAppend = sep + value;
|
||||||
@@ -85,9 +90,9 @@ void Environment::appendOrSet(const QString &key, const QString &value, const QS
|
|||||||
void Environment::prependOrSet(const QString &key, const QString &value, const QString &sep)
|
void Environment::prependOrSet(const QString &key, const QString &value, const QString &sep)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!key.contains('='), return );
|
QTC_ASSERT(!key.contains('='), return );
|
||||||
const auto it = findKey(key);
|
const auto it = m_dict.findKey(key);
|
||||||
if (it == m_values.end()) {
|
if (it == m_dict.m_values.end()) {
|
||||||
m_values.insert(DictKey(key, nameCaseSensitivity()), qMakePair(value, true));
|
m_dict.m_values.insert(DictKey(key, m_dict.nameCaseSensitivity()), qMakePair(value, true));
|
||||||
} else {
|
} else {
|
||||||
// Prepend unless it is already there
|
// Prepend unless it is already there
|
||||||
const QString toPrepend = value + sep;
|
const QString toPrepend = value + sep;
|
||||||
@@ -98,8 +103,8 @@ void Environment::prependOrSet(const QString &key, const QString &value, const Q
|
|||||||
|
|
||||||
void Environment::prependOrSetLibrarySearchPath(const FilePath &value)
|
void Environment::prependOrSetLibrarySearchPath(const FilePath &value)
|
||||||
{
|
{
|
||||||
QTC_CHECK(value.osType() == m_osType);
|
QTC_CHECK(value.osType() == osType());
|
||||||
switch (m_osType) {
|
switch (osType()) {
|
||||||
case OsTypeWindows: {
|
case OsTypeWindows: {
|
||||||
const QChar sep = ';';
|
const QChar sep = ';';
|
||||||
prependOrSet("PATH", value.nativePath(), QString(sep));
|
prependOrSet("PATH", value.nativePath(), QString(sep));
|
||||||
@@ -137,8 +142,8 @@ Environment Environment::systemEnvironment()
|
|||||||
|
|
||||||
void Environment::setupEnglishOutput()
|
void Environment::setupEnglishOutput()
|
||||||
{
|
{
|
||||||
set("LC_MESSAGES", "en_US.utf8");
|
m_dict.set("LC_MESSAGES", "en_US.utf8");
|
||||||
set("LANGUAGE", "en_US:en");
|
m_dict.set("LANGUAGE", "en_US:en");
|
||||||
}
|
}
|
||||||
|
|
||||||
static FilePath searchInDirectory(const QStringList &execs,
|
static FilePath searchInDirectory(const QStringList &execs,
|
||||||
@@ -166,7 +171,7 @@ QStringList Environment::appendExeExtensions(const QString &executable) const
|
|||||||
{
|
{
|
||||||
QStringList execs(executable);
|
QStringList execs(executable);
|
||||||
const QFileInfo fi(executable);
|
const QFileInfo fi(executable);
|
||||||
if (m_osType == OsTypeWindows) {
|
if (osType() == OsTypeWindows) {
|
||||||
// Check all the executable extensions on windows:
|
// Check all the executable extensions on windows:
|
||||||
// PATHEXT is only used if the executable has no extension
|
// PATHEXT is only used if the executable has no extension
|
||||||
if (fi.suffix().isEmpty()) {
|
if (fi.suffix().isEmpty()) {
|
||||||
@@ -202,7 +207,7 @@ bool Environment::isSameExecutable(const QString &exe1, const QString &exe2) con
|
|||||||
|
|
||||||
QString Environment::expandedValueForKey(const QString &key) const
|
QString Environment::expandedValueForKey(const QString &key) const
|
||||||
{
|
{
|
||||||
return expandVariables(value(key));
|
return expandVariables(m_dict.value(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
static FilePath searchInDirectoriesHelper(const Environment &env,
|
static FilePath searchInDirectoriesHelper(const Environment &env,
|
||||||
@@ -308,7 +313,7 @@ FilePaths Environment::path() const
|
|||||||
FilePaths Environment::pathListValue(const QString &varName) const
|
FilePaths Environment::pathListValue(const QString &varName) const
|
||||||
{
|
{
|
||||||
const QStringList pathComponents = expandedValueForKey(varName).split(
|
const QStringList pathComponents = expandedValueForKey(varName).split(
|
||||||
OsSpecificAspects::pathListSeparator(m_osType), Qt::SkipEmptyParts);
|
OsSpecificAspects::pathListSeparator(osType()), Qt::SkipEmptyParts);
|
||||||
return transform(pathComponents, &FilePath::fromUserInput);
|
return transform(pathComponents, &FilePath::fromUserInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,12 +338,12 @@ QString Environment::expandVariables(const QString &input) const
|
|||||||
{
|
{
|
||||||
QString result = input;
|
QString result = input;
|
||||||
|
|
||||||
if (m_osType == OsTypeWindows) {
|
if (osType() == OsTypeWindows) {
|
||||||
for (int vStart = -1, i = 0; i < result.length(); ) {
|
for (int vStart = -1, i = 0; i < result.length(); ) {
|
||||||
if (result.at(i++) == '%') {
|
if (result.at(i++) == '%') {
|
||||||
if (vStart > 0) {
|
if (vStart > 0) {
|
||||||
const auto it = findKey(result.mid(vStart, i - vStart - 1));
|
const auto it = m_dict.findKey(result.mid(vStart, i - vStart - 1));
|
||||||
if (it != m_values.constEnd()) {
|
if (it != m_dict.m_values.constEnd()) {
|
||||||
result.replace(vStart - 1, i - vStart + 1, it->first);
|
result.replace(vStart - 1, i - vStart + 1, it->first);
|
||||||
i = vStart - 1 + it->first.length();
|
i = vStart - 1 + it->first.length();
|
||||||
vStart = -1;
|
vStart = -1;
|
||||||
|
@@ -40,13 +40,27 @@ QT_END_NAMESPACE
|
|||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT Environment final : public NameValueDictionary
|
class QTCREATOR_UTILS_EXPORT Environment final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using NameValueDictionary::NameValueDictionary;
|
Environment() : m_dict(HostOsInfo::hostOs()) {}
|
||||||
|
explicit Environment(OsType osType) : m_dict(osType) {}
|
||||||
|
explicit Environment(const QStringList &env, OsType osType = HostOsInfo::hostOs())
|
||||||
|
: m_dict(env, osType) {}
|
||||||
|
explicit Environment(const NameValuePairs &nameValues) : m_dict(nameValues) {}
|
||||||
|
explicit Environment(const NameValueDictionary &dict) : m_dict(dict) {}
|
||||||
|
|
||||||
static Environment systemEnvironment();
|
QString value(const QString &key) const { return m_dict.value(key); }
|
||||||
|
bool hasKey(const QString &key) const { return m_dict.hasKey(key); }
|
||||||
|
|
||||||
|
void set(const QString &key, const QString &value, bool enabled = true) { m_dict.set(key, value, enabled); }
|
||||||
|
void unset(const QString &key) { m_dict.unset(key); }
|
||||||
|
void modify(const NameValueItems &items) { m_dict.modify(items); }
|
||||||
|
|
||||||
|
int size() const { return m_dict.size(); }
|
||||||
|
void clear() { return m_dict.clear(); }
|
||||||
|
|
||||||
|
QStringList toStringList() const { return m_dict.toStringList(); }
|
||||||
QProcessEnvironment toProcessEnvironment() const;
|
QProcessEnvironment toProcessEnvironment() const;
|
||||||
|
|
||||||
void appendOrSet(const QString &key, const QString &value, const QString &sep = QString());
|
void appendOrSet(const QString &key, const QString &value, const QString &sep = QString());
|
||||||
@@ -81,8 +95,38 @@ public:
|
|||||||
FilePath expandVariables(const FilePath &input) const;
|
FilePath expandVariables(const FilePath &input) const;
|
||||||
QStringList expandVariables(const QStringList &input) const;
|
QStringList expandVariables(const QStringList &input) const;
|
||||||
|
|
||||||
|
OsType osType() const { return m_dict.osType(); }
|
||||||
|
QString userName() const;
|
||||||
|
|
||||||
|
using const_iterator = NameValueMap::const_iterator; // FIXME: avoid
|
||||||
|
NameValueDictionary toDictionary() const { return m_dict; } // FIXME: avoid
|
||||||
|
NameValueItems diff(const Environment &other, bool checkAppendPrepend = false) const; // FIXME: avoid
|
||||||
|
|
||||||
|
QString key(const_iterator it) const { return m_dict.key(it); } // FIXME: avoid
|
||||||
|
QString value(const_iterator it) const { return m_dict.value(it); } // FIXME: avoid
|
||||||
|
bool isEnabled(const_iterator it) const { return m_dict.isEnabled(it); } // FIXME: avoid
|
||||||
|
|
||||||
|
const_iterator constBegin() const { return m_dict.constBegin(); } // FIXME: avoid
|
||||||
|
const_iterator constEnd() const { return m_dict.constEnd(); } // FIXME: avoid
|
||||||
|
const_iterator constFind(const QString &name) const { return m_dict.constFind(name); } // FIXME: avoid
|
||||||
|
|
||||||
|
friend bool operator!=(const Environment &first, const Environment &second)
|
||||||
|
{
|
||||||
|
return first.m_dict != second.m_dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator==(const Environment &first, const Environment &second)
|
||||||
|
{
|
||||||
|
return first.m_dict == second.m_dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Environment systemEnvironment();
|
||||||
|
|
||||||
static void modifySystemEnvironment(const EnvironmentItems &list); // use with care!!!
|
static void modifySystemEnvironment(const EnvironmentItems &list); // use with care!!!
|
||||||
static void setSystemEnvironment(const Environment &environment); // don't use at all!!!
|
static void setSystemEnvironment(const Environment &environment); // don't use at all!!!
|
||||||
|
|
||||||
|
private:
|
||||||
|
NameValueDictionary m_dict;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT EnvironmentChange final
|
class QTCREATOR_UTILS_EXPORT EnvironmentChange final
|
||||||
|
@@ -28,12 +28,15 @@
|
|||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
const Environment &EnvironmentModel::baseEnvironment() const
|
|
||||||
|
Environment EnvironmentModel::baseEnvironment() const
|
||||||
{
|
{
|
||||||
return static_cast<const Environment &>(baseNameValueDictionary());
|
return Environment(baseNameValueDictionary());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnvironmentModel::setBaseEnvironment(const Environment &env)
|
void EnvironmentModel::setBaseEnvironment(const Environment &env)
|
||||||
{
|
{
|
||||||
setBaseNameValueDictionary(env);
|
setBaseNameValueDictionary(env.toDictionary());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -36,7 +36,7 @@ class QTCREATOR_UTILS_EXPORT EnvironmentModel : public NameValueModel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const Environment &baseEnvironment() const;
|
Environment baseEnvironment() const;
|
||||||
void setBaseEnvironment(const Environment &env);
|
void setBaseEnvironment(const Environment &env);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -101,6 +101,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
friend class Environment;
|
||||||
NameValueMap::iterator findKey(const QString &key);
|
NameValueMap::iterator findKey(const QString &key);
|
||||||
const_iterator findKey(const QString &key) const;
|
const_iterator findKey(const QString &key) const;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user