Skip to content

Commit 7a426b4

Browse files
committed
Introduce PowerShell installer stub
1 parent cb04e7f commit 7a426b4

21 files changed

+475
-291
lines changed
Loading

src/cascadia/TerminalSettingsEditor/Extensions.xaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@
156156
x:Uid="Extensions_NavigateToProfileButton"
157157
Click="NavigateToProfile_Click"
158158
Style="{StaticResource SettingContainerResetButtonStyle}"
159-
Tag="{x:Bind Profile.Guid}">
159+
Tag="{x:Bind Profile.Guid}"
160+
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(Profile.Deleted)}">
160161
<FontIcon Glyph="&#xE8A7;"
161162
Style="{StaticResource SettingContainerFontIconStyle}" />
162163
</Button>

src/cascadia/TerminalSettingsModel/AzureCloudShellGenerator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ std::wstring_view AzureCloudShellGenerator::GetDisplayName() const noexcept
3131
// - <none>
3232
// Return Value:
3333
// - a vector with the Azure Cloud Shell connection profile, if available.
34-
void AzureCloudShellGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const
34+
void AzureCloudShellGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles)
3535
{
3636
if (AzureConnection::IsAzureConnectionAvailable())
3737
{

src/cascadia/TerminalSettingsModel/AzureCloudShellGenerator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model
2727
std::wstring_view GetNamespace() const noexcept override;
2828
std::wstring_view GetDisplayName() const noexcept override;
2929
std::wstring_view GetIcon() const noexcept override { return {}; };
30-
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const override;
30+
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) override;
3131
};
3232
};

src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ Model::CascadiaSettings CascadiaSettings::Copy() const
144144

145145
Model::FragmentSettings FragmentSettings::Copy() const
146146
{
147-
auto fragment{ winrt::make_self<FragmentSettings>(_source, _json, _jsonSource) };
147+
auto fragment{ winrt::make_self<FragmentSettings>(_source, _Json, _jsonSource) };
148148

149149
std::vector<Model::FragmentProfileEntry> modifiedProfiles;
150150
modifiedProfiles.reserve(_modifiedProfiles.Size());

src/cascadia/TerminalSettingsModel/CascadiaSettings.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
123123
void _appendProfile(winrt::com_ptr<Profile>&& profile, const winrt::guid& guid, ParsedSettings& settings);
124124
void _addUserProfileParent(const winrt::com_ptr<implementation::Profile>& profile);
125125
bool _addOrMergeUserColorScheme(const winrt::com_ptr<implementation::ColorScheme>& colorScheme);
126-
void _executeGenerator(const IDynamicProfileGenerator& generator);
126+
void _executeGenerator(IDynamicProfileGenerator& generator);
127+
void _cleanupPowerShellInstaller(bool isPowerShellInstalled);
127128
winrt::com_ptr<implementation::ExtensionPackage> _registerFragment(const winrt::Microsoft::Terminal::Settings::Model::FragmentSettings& fragment, FragmentScope scope);
128129

129130
std::unordered_set<winrt::hstring, til::transparent_hstring_hash, til::transparent_hstring_equal_to> _ignoredNamespaces;
@@ -237,14 +238,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
237238
public:
238239
FragmentProfileEntry(winrt::guid profileGuid, hstring json) :
239240
_profileGuid{ profileGuid },
240-
_json{ json } {}
241+
_Json{ json } {}
241242

242243
winrt::guid ProfileGuid() const noexcept { return _profileGuid; }
243-
hstring Json() const noexcept { return _json; }
244+
WINRT_PROPERTY(hstring, Json);
244245

245246
private:
246247
winrt::guid _profileGuid;
247-
hstring _json;
248248
};
249249

250250
struct FragmentColorSchemeEntry : FragmentColorSchemeEntryT<FragmentColorSchemeEntry>
@@ -268,7 +268,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
268268
public:
269269
FragmentSettings(hstring source, hstring json, hstring jsonSource) :
270270
_source{ source },
271-
_json{ json },
271+
_Json{ json },
272272
_jsonSource{ jsonSource },
273273
_modifiedProfiles{ winrt::single_threaded_vector<Model::FragmentProfileEntry>() },
274274
_newProfiles{ winrt::single_threaded_vector<Model::FragmentProfileEntry>() },
@@ -277,20 +277,20 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
277277
Model::FragmentSettings Copy() const;
278278

279279
hstring Source() const noexcept { return _source; }
280-
hstring Json() const noexcept { return _json; }
281280
hstring JsonSource() const noexcept { return _jsonSource; }
282281
Windows::Foundation::Collections::IVector<Model::FragmentProfileEntry> ModifiedProfiles() const noexcept { return _modifiedProfiles; }
283282
Windows::Foundation::Collections::IVector<Model::FragmentProfileEntry> NewProfiles() const noexcept { return _newProfiles; }
284283
Windows::Foundation::Collections::IVector<Model::FragmentColorSchemeEntry> ColorSchemes() const noexcept { return _colorSchemes; }
284+
WINRT_PROPERTY(hstring, Json);
285285

286+
public:
286287
// views
287288
Windows::Foundation::Collections::IVectorView<Model::FragmentProfileEntry> ModifiedProfilesView() const noexcept { return _modifiedProfiles.GetView(); }
288289
Windows::Foundation::Collections::IVectorView<Model::FragmentProfileEntry> NewProfilesView() const noexcept { return _newProfiles.GetView(); }
289290
Windows::Foundation::Collections::IVectorView<Model::FragmentColorSchemeEntry> ColorSchemesView() const noexcept { return _colorSchemes.GetView(); }
290291

291292
private:
292293
hstring _source;
293-
hstring _json;
294294
hstring _jsonSource;
295295
Windows::Foundation::Collections::IVector<Model::FragmentProfileEntry> _modifiedProfiles;
296296
Windows::Foundation::Collections::IVector<Model::FragmentProfileEntry> _newProfiles;

src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#if TIL_FEATURE_DYNAMICSSHPROFILES_ENABLED
2020
#include "SshHostGenerator.h"
2121
#endif
22+
#include "PowershellInstallationProfileGenerator.h"
2223

2324
#include "ApplicationState.h"
2425
#include "DefaultTerminal.h"
@@ -178,13 +179,77 @@ SettingsLoader::SettingsLoader(const std::string_view& userJSON, const std::stri
178179
// (meaning profiles specified by the application rather by the user).
179180
void SettingsLoader::GenerateProfiles()
180181
{
181-
_executeGenerator(PowershellCoreProfileGenerator{});
182-
_executeGenerator(WslDistroGenerator{});
183-
_executeGenerator(AzureCloudShellGenerator{});
184-
_executeGenerator(VisualStudioGenerator{});
182+
PowershellCoreProfileGenerator powerShellGenerator{};
183+
_executeGenerator(powerShellGenerator);
184+
185+
WslDistroGenerator wslGenerator{};
186+
_executeGenerator(wslGenerator);
187+
188+
AzureCloudShellGenerator acsGenerator{};
189+
_executeGenerator(acsGenerator);
190+
191+
VisualStudioGenerator vsGenerator{};
192+
_executeGenerator(vsGenerator);
193+
185194
#if TIL_FEATURE_DYNAMICSSHPROFILES_ENABLED
186-
_executeGenerator(SshHostGenerator{});
195+
SshHostGenerator sshGenerator{};
196+
_executeGenerator(sshGenerator);
187197
#endif
198+
199+
PowershellInstallationProfileGenerator pwshInstallationGenerator{};
200+
_executeGenerator(pwshInstallationGenerator);
201+
202+
_cleanupPowerShellInstaller(!powerShellGenerator.GetPowerShellInstances().empty());
203+
}
204+
205+
// Retrieve the "Install Latest PowerShell" profile and...
206+
// - add a comment to the JSON to indicate it's conditionally applied
207+
// - (if PowerShell is installed) mark it for deletion
208+
void SettingsLoader::_cleanupPowerShellInstaller(bool isPowerShellInstalled)
209+
{
210+
const hstring pwshInstallerNamespace{ PowershellInstallationProfileGenerator::Namespace };
211+
if (extensionPackageMap.contains(pwshInstallerNamespace))
212+
{
213+
if (const auto& fragExtList = extensionPackageMap[pwshInstallerNamespace]->Fragments(); fragExtList.Size() > 0)
214+
{
215+
Json::StreamWriterBuilder styledWriter;
216+
styledWriter["indentation"] = " ";
217+
styledWriter["commentStyle"] = "All";
218+
219+
auto fragExt = get_self<FragmentSettings>(fragExtList.GetAt(0));
220+
221+
// We want the comment to be the first thing in the object,
222+
// "closeOnExit" is the first property, so target that.
223+
auto fragExtJson = _parseJSON(til::u16u8(fragExt->Json()));
224+
fragExtJson[JsonKey(ProfilesKey)][0]["closeOnExit"].setComment(til::u16u8(fmt::format(FMT_COMPILE(L"// {}"), RS_(L"PowerShellInstallationProfileJsonComment"))), Json::CommentPlacement::commentBefore);
225+
fragExt->Json(hstring{ til::u8u16(Json::writeString(styledWriter, fragExtJson)) });
226+
227+
if (const auto& profileEntryList = fragExt->NewProfilesView(); profileEntryList.Size() > 0)
228+
{
229+
auto profileEntry = get_self<FragmentProfileEntry>(profileEntryList.GetAt(0));
230+
231+
// We want the comment to be the first thing in the object,
232+
// "closeOnExit" is the first property, so target that.
233+
auto profileJson = _parseJSON(til::u16u8(profileEntry->Json()));
234+
profileJson["closeOnExit"].setComment(til::u16u8(fmt::format(FMT_COMPILE(L"// {}"), RS_(L"PowerShellInstallationProfileJsonComment"))), Json::CommentPlacement::commentBefore);
235+
profileEntry->Json(hstring{ til::u8u16(Json::writeString(styledWriter, profileJson)) });
236+
237+
// If PowerShell is installed, mark the installer profile for deletion
238+
if (isPowerShellInstalled)
239+
{
240+
const auto profileGuid = profileEntryList.GetAt(0).ProfileGuid();
241+
for (const auto& profile : userSettings.profiles)
242+
{
243+
if (profile->Guid() == profileGuid)
244+
{
245+
profile->Deleted(true);
246+
break;
247+
}
248+
}
249+
}
250+
}
251+
}
252+
}
188253
}
189254

190255
// A new settings.json gets a special treatment:
@@ -993,7 +1058,7 @@ bool SettingsLoader::_addOrMergeUserColorScheme(const winrt::com_ptr<implementat
9931058

9941059
// As the name implies it executes a generator.
9951060
// Generated profiles are added to .inboxSettings. Used by GenerateProfiles().
996-
void SettingsLoader::_executeGenerator(const IDynamicProfileGenerator& generator)
1061+
void SettingsLoader::_executeGenerator(IDynamicProfileGenerator& generator)
9971062
{
9981063
const auto generatorNamespace = generator.GetNamespace();
9991064
std::vector<winrt::com_ptr<implementation::Profile>> generatedProfiles;
@@ -1590,7 +1655,11 @@ void CascadiaSettings::_resolveNewTabMenuProfiles() const
15901655
auto activeProfileCount = gsl::narrow_cast<int>(_activeProfiles.Size());
15911656
for (auto profileIndex = 0; profileIndex < activeProfileCount; profileIndex++)
15921657
{
1593-
remainingProfilesMap.emplace(profileIndex, _activeProfiles.GetAt(profileIndex));
1658+
const auto& profile = _activeProfiles.GetAt(profileIndex);
1659+
if (!profile.Deleted())
1660+
{
1661+
remainingProfilesMap.emplace(profileIndex, _activeProfiles.GetAt(profileIndex));
1662+
}
15941663
}
15951664

15961665
// We keep track of the "remaining profiles" - those that have not yet been resolved

src/cascadia/TerminalSettingsModel/IDynamicProfileGenerator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model
3232
virtual std::wstring_view GetNamespace() const noexcept = 0;
3333
virtual std::wstring_view GetDisplayName() const noexcept = 0;
3434
virtual std::wstring_view GetIcon() const noexcept = 0;
35-
virtual void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const = 0;
35+
virtual void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) = 0;
3636
};
3737
};

src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
<DependentUpon>KeyChordSerialization.idl</DependentUpon>
9191
</ClInclude>
9292
<ClInclude Include="PowershellCoreProfileGenerator.h" />
93+
<ClInclude Include="PowershellInstallationProfileGenerator.h" />
9394
<ClInclude Include="Profile.h">
9495
<DependentUpon>Profile.idl</DependentUpon>
9596
</ClInclude>
@@ -167,6 +168,7 @@
167168
<DependentUpon>KeyChordSerialization.idl</DependentUpon>
168169
</ClCompile>
169170
<ClCompile Include="PowershellCoreProfileGenerator.cpp" />
171+
<ClCompile Include="PowershellInstallationProfileGenerator.cpp" />
170172
<ClCompile Include="Profile.cpp">
171173
<DependentUpon>Profile.idl</DependentUpon>
172174
</ClCompile>

src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
<ClCompile Include="PowershellCoreProfileGenerator.cpp">
1616
<Filter>profileGeneration</Filter>
1717
</ClCompile>
18+
<ClCompile Include="PowershellInstallationProfileGenerator.cpp">
19+
<Filter>profileGeneration</Filter>
20+
</ClCompile>
1821
<ClCompile Include="WslDistroGenerator.cpp">
1922
<Filter>profileGeneration</Filter>
2023
</ClCompile>
@@ -57,6 +60,9 @@
5760
<ClInclude Include="PowershellCoreProfileGenerator.h">
5861
<Filter>profileGeneration</Filter>
5962
</ClInclude>
63+
<ClInclude Include="PowershellInstallationProfileGenerator.h">
64+
<Filter>profileGeneration</Filter>
65+
</ClInclude>
6066
<ClInclude Include="WslDistroGenerator.h">
6167
<Filter>profileGeneration</Filter>
6268
</ClInclude>

0 commit comments

Comments
 (0)