Utils: Add a way to provide fall-back entries in an environment

These are used if a (presumably fully-expanded) environment does
not have a value for a certain key. Currently this works only for
fully-known environments, but this can at least be delayed until
the environment is needed, not when it is set up.

Change-Id: I9baaa2d23002ddd574101741a91d5f872e6b0314
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
hjk
2023-03-24 10:59:30 +01:00
parent a0924caea2
commit 6e276b0a00
3 changed files with 31 additions and 7 deletions

View File

@@ -494,6 +494,12 @@ void Environment::set(const QString &key, const QString &value, bool enabled)
std::tuple<QString, QString, bool>{key, value, enabled}}); std::tuple<QString, QString, bool>{key, value, enabled}});
} }
void Environment::setFallback(const QString &key, const QString &value)
{
addItem(Item{std::in_place_index_t<SetFallbackValue>(),
std::tuple<QString, QString>{key, value}});
}
void Environment::unset(const QString &key) void Environment::unset(const QString &key)
{ {
addItem(Item{std::in_place_index_t<UnsetValue>(), key}); addItem(Item{std::in_place_index_t<UnsetValue>(), key});
@@ -536,19 +542,33 @@ const NameValueDictionary &Environment::resolved() const
if (m_dict.size() != 0) if (m_dict.size() != 0)
return m_dict; return m_dict;
m_fullDict = false;
for (const Item &item : m_changeItems) { for (const Item &item : m_changeItems) {
switch (item.index()) { switch (item.index()) {
case SetSystemEnvironment: case SetSystemEnvironment:
m_dict = Environment::systemEnvironment().toDictionary(); m_dict = Environment::systemEnvironment().toDictionary();
m_fullDict = true;
break; break;
case SetFixedDictionary: case SetFixedDictionary:
m_dict = std::get<SetFixedDictionary>(item); m_dict = std::get<SetFixedDictionary>(item);
m_fullDict = true;
break; break;
case SetValue: { case SetValue: {
auto [key, value, enabled] = std::get<SetValue>(item); auto [key, value, enabled] = std::get<SetValue>(item);
m_dict.set(key, value, enabled); m_dict.set(key, value, enabled);
break; break;
} }
case SetFallbackValue: {
auto [key, value] = std::get<SetFallbackValue>(item);
if (m_fullDict) {
if (m_dict.value(key).isEmpty())
m_dict.set(key, value, true);
} else {
QTC_ASSERT(false, qDebug() << "operating on partial dictionary");
m_dict.set(key, value, true);
}
break;
}
case UnsetValue: case UnsetValue:
m_dict.unset(std::get<UnsetValue>(item)); m_dict.unset(std::get<UnsetValue>(item));
break; break;

View File

@@ -33,6 +33,7 @@ public:
bool hasKey(const QString &key) const; bool hasKey(const QString &key) const;
void set(const QString &key, const QString &value, bool enabled = true); void set(const QString &key, const QString &value, bool enabled = true);
void setFallback(const QString &key, const QString &value);
void unset(const QString &key); void unset(const QString &key);
void modify(const NameValueItems &items); void modify(const NameValueItems &items);
@@ -55,6 +56,7 @@ public:
void appendToPath(const FilePaths &values); void appendToPath(const FilePaths &values);
void setupEnglishOutput(); void setupEnglishOutput();
void setupSudoAskPass(const FilePath &askPass);
FilePath searchInPath(const QString &executable, FilePath searchInPath(const QString &executable,
const FilePaths &additionalDirs = FilePaths(), const FilePaths &additionalDirs = FilePaths(),
@@ -95,22 +97,25 @@ public:
SetSystemEnvironment, SetSystemEnvironment,
SetFixedDictionary, SetFixedDictionary,
SetValue, SetValue,
SetFallbackValue,
UnsetValue, UnsetValue,
PrependOrSet, PrependOrSet,
AppendOrSet, AppendOrSet,
Modify, Modify,
SetupEnglishOutput, SetupEnglishOutput
}; };
using Item = std::variant< using Item = std::variant<
std::monostate, // SetSystemEnvironment dummy std::monostate, // SetSystemEnvironment dummy
NameValueDictionary, // SetFixedDictionary NameValueDictionary, // SetFixedDictionary
std::tuple<QString, QString, bool>, // SetValue (key, value, enabled) std::tuple<QString, QString, bool>, // SetValue (key, value, enabled)
std::tuple<QString, QString>, // SetFallbackValue (key, value)
QString, // UnsetValue (key) QString, // UnsetValue (key)
std::tuple<QString, QString, QString>, // PrependOrSet (key, value, separator) std::tuple<QString, QString, QString>, // PrependOrSet (key, value, separator)
std::tuple<QString, QString, QString>, // AppendOrSet (key, value, separator) std::tuple<QString, QString, QString>, // AppendOrSet (key, value, separator)
NameValueItems, // Modify NameValueItems, // Modify
std::monostate // SetupEnglishOutput std::monostate, // SetupEnglishOutput
FilePath // SetupSudoAskPass (file path of qtc-askpass or ssh-askpass)
>; >;
void addItem(const Item &item); void addItem(const Item &item);
@@ -122,6 +127,7 @@ public:
private: private:
mutable QList<Item> m_changeItems; mutable QList<Item> m_changeItems;
mutable NameValueDictionary m_dict; // Latest resolved. mutable NameValueDictionary m_dict; // Latest resolved.
mutable bool m_fullDict = false;
}; };
using EnviromentChange = Environment; using EnviromentChange = Environment;

View File

@@ -1069,11 +1069,9 @@ bool RunControl::showPromptToStopDialog(const QString &title,
void RunControl::provideAskPassEntry(Environment &env) void RunControl::provideAskPassEntry(Environment &env)
{ {
if (env.value("SUDO_ASKPASS").isEmpty()) { const FilePath askpass = SshSettings::askpassFilePath();
const FilePath askpass = SshSettings::askpassFilePath(); if (askpass.exists())
if (askpass.exists()) env.setFallback("SUDO_ASKPASS", askpass.toUserOutput());
env.set("SUDO_ASKPASS", askpass.toUserOutput());
}
} }
bool RunControlPrivate::isAllowedTransition(RunControlState from, RunControlState to) bool RunControlPrivate::isAllowedTransition(RunControlState from, RunControlState to)