Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow inheriting env vars from wt again and other env var changes too #15897

Merged
merged 17 commits into from
Sep 19, 2023

Conversation

zadjii-msft
Copy link
Member

@zadjii-msft zadjii-msft commented Aug 29, 2023

This PR is a few things:

  • part the first: Convert the compatibility.reloadEnvironmentVariables setting to a per-profile one.
    • The settings should migrate it from the user's old global place to the new one.
    • We also added it to "Profile>Advanced" while I was here.
  • Adds a new pair of commandline flags to new-tab and split-pane: --inheritEnvironment / --reloadEnvironment
    • On wt launch, bundle the entire environment that wt was spawned with, and put it into the Remoting.CommandlineArgs, and give them to the monarch (and ultimately, down to TerminalPage with the AppCommandlineArgs). DO THIS ALWAYS.
    • As a part of this, we’ll default to reloading if there’s no explicit commandline set, and inheriting if there is.
      • For example, wt -- cmd would inherit, and wt -p “Command Prompt” would reload.1
    • This is a little wacky, but we’re trying to separate out the intentions here:
      • wt -- cmd feels like “I want to run cmd.exe (in a terminal tab)”. That feels like the user would like environment variables from the calling process. They’re doing something more manual, so they get more refined control over it.
      • wt (or wt -p “Command Prompt”) is more like, “I want to run the Terminal (or, my Command Prompt profile) using whatever the Terminal would normally do”. So that feels more like a situation where it should just reload by default. (Of course, this will respect their settings here)

References and Relevant Issues

#15496 (comment) has more notes.

Detailed Description of the Pull Request / Additional comments

This is so VERY much plumbing. I'll try to leave comments in the interesting parts.

PR Checklist

Footnotes

  1. In both these cases, plus the environment setting, of course.

@@ -662,6 +668,13 @@ NewTerminalArgs AppCommandlineArgs::_getNewTerminalArgs(AppCommandlineArgs::NewT
args.AppendCommandLine(_appendCommandLineOption);
}

bool inheritEnv = hasCommandline;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of interest: default to inherit if we do have a commandline. If the user passed the arg in manually, then use the arg.

@@ -576,6 +577,12 @@ namespace winrt::TerminalApp::implementation
_WindowProperties.VirtualWorkingDirectory(originalVirtualCwd);
});

// Literally the same thing with env vars too
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this is exactly the same way VirtualWorkingDirectory (above this) works

environment,
settings.InitialRows(),
settings.InitialCols(),
winrt::guid(),
profile.Guid());

valueSet.Insert(L"passthroughMode", Windows::Foundation::PropertyValue::CreateBoolean(settings.VtPassthrough()));
valueSet.Insert(L"reloadEnvironmentVariables",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Promoted this to be a proper param to CreateSettings

@@ -286,6 +293,19 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
_reloadEnvironmentVariables = winrt::unbox_value_or<bool>(settings.TryLookup(L"reloadEnvironmentVariables").try_as<Windows::Foundation::IPropertyValue>(),
_reloadEnvironmentVariables);
_profileGuid = winrt::unbox_value_or<winrt::guid>(settings.TryLookup(L"profileGuid").try_as<Windows::Foundation::IPropertyValue>(), _profileGuid);

const auto& initialEnvironment{ winrt::unbox_value_or<winrt::hstring>(settings.TryLookup(L"initialEnvironment").try_as<Windows::Foundation::IPropertyValue>(), L"") };
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting: get the serialized env block here, and use it to make a til::env that this connection will use as it's basis.

@@ -450,6 +450,13 @@ bool SettingsLoader::FixupUserSettings()
}
}

if (!userSettings.globals->LegacyReloadEnvironmentVariables())
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

migration logic is here. This seemed like the right place?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM. @lhecker?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But wait, won't this set Reload to false when in globals it was set to true??

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for example, it's set to true in the constructor. doesn't that mean that everybody's base layer profile will get it set to false???

Copy link
Member

@lhecker lhecker Sep 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think we should put all our migration code into this place (if possible).
I think it should be if (globals->HasLegacyReloadEnvironmentVariables()) and then set it to base->ReloadEnvironmentVariables(globals->LegacyReloadEnvironmentVariables()) right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm see, I was thinking that the old setting defaulted to true, so the only thing we'd want to migrate is a false. Similarly, the _legacyReloadEnvironmentVariables defaults to true, so the only time we write a false in is if we found a false.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a SerializationTests::DontRoundtripNoReloadEnvVars for a test case 😜

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I see. since it's 2-state you're just checking the set value instead of Has. It's an unexpected technique, but it'll do. Thanks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I missed the ! i think

@@ -105,7 +106,9 @@ bool WindowEmperor::HandleCommandlineArgs()
GetStartupInfoW(&si);
const uint32_t showWindow = WI_IsFlagSet(si.dwFlags, STARTF_USESHOWWINDOW) ? si.wShowWindow : SW_SHOW;

Remoting::CommandlineArgs eventArgs{ { args }, { cwd }, showWindow };
const auto currentEnv{ til::env::from_current_environment() };
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, it's this easy to package up the calling wt's env vars into a string that we can move around easily.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this takes care of the embedded null bytes? wow

zadjii-msft added a commit that referenced this pull request Aug 29, 2023
@DHowett
Copy link
Member

DHowett commented Aug 29, 2023

How did this compile in the selfhost build but not in the CI build?

src/cascadia/TerminalApp/Resources/en-US/Resources.resw Outdated Show resolved Hide resolved
src/cascadia/TerminalApp/TerminalPage.idl Show resolved Hide resolved
src/cascadia/TerminalConnection/ConptyConnection.cpp Outdated Show resolved Hide resolved
@@ -246,20 +247,26 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
vs.Insert(L"commandline", Windows::Foundation::PropertyValue::CreateString(cmdline));
vs.Insert(L"startingDirectory", Windows::Foundation::PropertyValue::CreateString(startingDirectory));
vs.Insert(L"startingTitle", Windows::Foundation::PropertyValue::CreateString(startingTitle));
vs.Insert(L"reloadEnvironmentVariables", Windows::Foundation::PropertyValue::CreateBoolean(reloadEnvironmentVariables));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't figure out where this guy is used. The ValueSet is an internal contract between ConptyConnection and ConptyConnection, so I expected to see it in ConptyConnection.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's in ConptyConnection::Initialize. That isn't part of the diff because it was already there, I'm just moving the setting into ConptyConnection. Setting it outside, in TerminalPage, is wack.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good call thx

src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml Outdated Show resolved Hide resolved
@@ -450,6 +450,13 @@ bool SettingsLoader::FixupUserSettings()
}
}

if (!userSettings.globals->LegacyReloadEnvironmentVariables())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM. @lhecker?

@@ -450,6 +450,13 @@ bool SettingsLoader::FixupUserSettings()
}
}

if (!userSettings.globals->LegacyReloadEnvironmentVariables())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But wait, won't this set Reload to false when in globals it was set to true??

@@ -450,6 +450,13 @@ bool SettingsLoader::FixupUserSettings()
}
}

if (!userSettings.globals->LegacyReloadEnvironmentVariables())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for example, it's set to true in the constructor. doesn't that mean that everybody's base layer profile will get it set to false???

@@ -166,6 +166,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::TerminalSettings, bool, RightClickContextMenu, false);
INHERITABLE_SETTING(Model::TerminalSettings, bool, RepositionCursorWithMouse, false);

INHERITABLE_SETTING(Model::TerminalSettings, bool, ReloadEnvironmentVariables, true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qq: why does the control need to know about this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Control doesn't, but the page does. This is in the same weird case as Elevate. It's not a Control setting, but it is a per-control setting.

@@ -105,7 +106,9 @@ bool WindowEmperor::HandleCommandlineArgs()
GetStartupInfoW(&si);
const uint32_t showWindow = WI_IsFlagSet(si.dwFlags, STARTF_USESHOWWINDOW) ? si.wShowWindow : SW_SHOW;

Remoting::CommandlineArgs eventArgs{ { args }, { cwd }, showWindow };
const auto currentEnv{ til::env::from_current_environment() };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this takes care of the embedded null bytes? wow

@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Sep 6, 2023
@microsoft-github-policy-service microsoft-github-policy-service bot removed the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Sep 7, 2023
@github-actions

This comment has been minimized.

@zadjii-msft zadjii-msft requested a review from DHowett September 7, 2023 15:29
@github-actions

This comment has been minimized.

@zadjii-msft zadjii-msft assigned lhecker and unassigned DHowett Sep 18, 2023
@zadjii-msft zadjii-msft requested a review from lhecker September 19, 2023 16:43
Comment on lines +267 to +270
T unbox_prop_or(const Windows::Foundation::Collections::ValueSet& blob, std::wstring_view key, T defaultValue)
{
return winrt::unbox_value_or<T>(blob.TryLookup(key).try_as<Windows::Foundation::IPropertyValue>(), defaultValue);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat!

@zadjii-msft zadjii-msft merged commit 59248de into main Sep 19, 2023
17 checks passed
@zadjii-msft zadjii-msft deleted the dev/migrie/f/--inherit-env-vars branch September 19, 2023 20:03
DHowett pushed a commit that referenced this pull request Sep 22, 2023
…oo (#15897)

This PR is a few things:

* part the first: Convert the `compatibility.reloadEnvironmentVariables`
setting to a per-profile one.
* The settings should migrate it from the user's old global place to the
new one.
  * We also added it to "Profile>Advanced" while I was here.
* Adds a new pair of commandline flags to `new-tab` and `split-pane`:
`--inheritEnvironment` / `--reloadEnvironment`
* On `wt` launch, bundle the entire environment that `wt` was spawned
with, and put it into the `Remoting.CommandlineArgs`, and give them to
the monarch (and ultimately, down to `TerminalPage` with the
`AppCommandlineArgs`). DO THIS ALWAYS.
* As a part of this, we’ll default to _reloading_ if there’s no explicit
commandline set, and _inheriting_ if there is.
* For example, `wt -- cmd` would inherit, and `wt -p “Command Prompt”`
would reload.[^1]
* This is a little wacky, but we’re trying to separate out the
intentions here:
* `wt -- cmd` feels like “I want to run cmd.exe (in a terminal tab)”.
That feels like the user would _like_ environment variables from the
calling process. They’re doing something more manual, so they get more
refined control over it.
* `wt` (or `wt -p “Command Prompt”`) is more like, “I want to run the
Terminal (or, my Command Prompt profile) using whatever the Terminal
would normally do”. So that feels more like a situation where it should
just reload by default. (Of course, this will respect their settings
here)

#15496 (comment)
has more notes.

This is so VERY much plumbing. I'll try to leave comments in the
interesting parts.

- [x] This is not _all_ of #15496. We're also going to do a `-E foo=bar`
arg on top of this.
- [x] Tests added/passed
- [x] Schema updated

[^1]: In both these cases, plus the `environment` setting, of course.

(cherry picked from commit 59248de)
Service-Card-Id: 90383402
Service-Version: 1.18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

Terminal preview does not accept environment variables from parent process
3 participants