Skip to content

Commit

Permalink
Fix winget after a call to winget settings export (#2767)
Browse files Browse the repository at this point in the history
  • Loading branch information
msftrubengu authored Dec 15, 2022
1 parent 23f9942 commit 8a805cc
Show file tree
Hide file tree
Showing 15 changed files with 138 additions and 82 deletions.
8 changes: 5 additions & 3 deletions src/AppInstallerCLICore/Command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ namespace AppInstaller::CLI
std::string_view parent,
Command::Visibility visibility,
Settings::ExperimentalFeature::Feature feature,
Settings::TogglePolicy::Policy groupPolicy) :
m_name(name), m_aliases(std::move(aliases)), m_visibility(visibility), m_feature(feature), m_groupPolicy(groupPolicy)
Settings::TogglePolicy::Policy groupPolicy,
CommandOutputFlags outputFlags) :
m_name(name), m_aliases(std::move(aliases)), m_visibility(visibility), m_feature(feature), m_groupPolicy(groupPolicy), m_outputFlags(outputFlags)
{
if (!parent.empty())
{
Expand Down Expand Up @@ -933,7 +934,8 @@ namespace AppInstaller::CLI
{
try
{
if (!Settings::User().GetWarnings().empty())
if (!Settings::User().GetWarnings().empty() &&
!WI_IsFlagSet(command->GetOutputFlags(), CommandOutputFlags::IgnoreSettingsWarnings))
{
context.Reporter.Warn() << Resource::String::SettingsWarnings << std::endl;
}
Expand Down
37 changes: 29 additions & 8 deletions src/AppInstallerCLICore/Command.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ namespace AppInstaller::CLI
std::vector<Utility::LocIndString> m_params;
};

// Flags to control the behavior of the command output.
enum class CommandOutputFlags : int
{
None = 0x0,
IgnoreSettingsWarnings = 0x1,
};

DEFINE_ENUM_FLAG_OPERATORS(CommandOutputFlags);

struct Command
{
// Controls the visibility of the field.
Expand All @@ -57,17 +66,27 @@ namespace AppInstaller::CLI

Command(std::string_view name, std::string_view parent) :
Command(name, {}, parent) {}
Command(std::string_view name,std::vector<std::string_view> aliases, std::string_view parent) :
Command(std::string_view name, std::vector<std::string_view> aliases, std::string_view parent) :
Command(name, aliases, parent, Settings::ExperimentalFeature::Feature::None) {}
Command(std::string_view name,std::vector<std::string_view> aliases, std::string_view parent, Command::Visibility visibility) :
Command(std::string_view name, std::string_view parent, CommandOutputFlags outputFlags) :
Command(name, {}, parent, Command::Visibility::Show, Settings::ExperimentalFeature::Feature::None, Settings::TogglePolicy::Policy::None, outputFlags) {}
Command(std::string_view name, std::vector<std::string_view> aliases, std::string_view parent, Command::Visibility visibility) :
Command(name, aliases, parent, visibility, Settings::ExperimentalFeature::Feature::None) {}
Command(std::string_view name,std::vector<std::string_view> aliases, std::string_view parent, Settings::ExperimentalFeature::Feature feature) :
Command(std::string_view name, std::vector<std::string_view> aliases, std::string_view parent, Settings::ExperimentalFeature::Feature feature) :
Command(name, aliases, parent, Command::Visibility::Show, feature) {}
Command(std::string_view name,std::vector<std::string_view> aliases, std::string_view parent, Settings::TogglePolicy::Policy groupPolicy) :
Command(name, aliases, parent, Command::Visibility::Show, Settings::ExperimentalFeature::Feature::None, groupPolicy) {}
Command(std::string_view name,std::vector<std::string_view> aliases, std::string_view parent, Command::Visibility visibility, Settings::ExperimentalFeature::Feature feature) :
Command(name, aliases, parent, visibility, feature, Settings::TogglePolicy::Policy::None) {}
Command(std::string_view name,std::vector<std::string_view> aliases, std::string_view parent, Command::Visibility visibility, Settings::ExperimentalFeature::Feature feature, Settings::TogglePolicy::Policy groupPolicy);
Command(std::string_view name, std::vector<std::string_view> aliases, std::string_view parent, Settings::TogglePolicy::Policy groupPolicy) :
Command(name, aliases, parent, Command::Visibility::Show, Settings::ExperimentalFeature::Feature::None, groupPolicy, CommandOutputFlags::None) {}
Command(std::string_view name, std::vector<std::string_view> aliases, std::string_view parent, Command::Visibility visibility, Settings::ExperimentalFeature::Feature feature) :
Command(name, aliases, parent, visibility, feature, Settings::TogglePolicy::Policy::None, CommandOutputFlags::None) {}

Command(std::string_view name,
std::vector<std::string_view> aliases,
std::string_view parent,
Command::Visibility visibility,
Settings::ExperimentalFeature::Feature feature,
Settings::TogglePolicy::Policy groupPolicy,
CommandOutputFlags outputFlags);

virtual ~Command() = default;

Command(const Command&) = default;
Expand All @@ -85,6 +104,7 @@ namespace AppInstaller::CLI
Command::Visibility GetVisibility() const;
Settings::ExperimentalFeature::Feature Feature() const { return m_feature; }
Settings::TogglePolicy::Policy GroupPolicy() const { return m_groupPolicy; }
CommandOutputFlags GetOutputFlags() const { return m_outputFlags; }

virtual std::vector<std::unique_ptr<Command>> GetCommands() const { return {}; }
virtual std::vector<Argument> GetArguments() const { return {}; }
Expand Down Expand Up @@ -118,6 +138,7 @@ namespace AppInstaller::CLI
Command::Visibility m_visibility;
Settings::ExperimentalFeature::Feature m_feature;
Settings::TogglePolicy::Policy m_groupPolicy;
CommandOutputFlags m_outputFlags;
};

template <typename Container>
Expand Down
4 changes: 3 additions & 1 deletion src/AppInstallerCLICore/Commands/RootCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ using namespace AppInstaller::Utility::literals;

namespace AppInstaller::CLI
{
using namespace Settings;

namespace
{
void OutputGroupPolicySourceList(Execution::Context& context, const std::vector<Settings::SourceFromPolicy>& sources, Resource::StringId header)
Expand Down Expand Up @@ -193,7 +195,7 @@ namespace AppInstaller::CLI
};

info << std::endl << Resource::String::Logs << ": "_liv << Runtime::GetPathTo(Runtime::PathName::DefaultLogLocationForDisplay).u8string() << std::endl;
info << std::endl << Resource::String::UserSettings << ": "_liv << Runtime::GetPathTo(Runtime::PathName::UserSettingsFileLocationForDisplay).u8string() << std::endl;
info << std::endl << Resource::String::UserSettings << ": "_liv << UserSettings::SettingsFilePath(true).u8string() << std::endl;

info << std::endl;

Expand Down
2 changes: 1 addition & 1 deletion src/AppInstallerCLICore/Commands/SettingsCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace AppInstaller::CLI

struct SettingsExportCommand final : public Command
{
SettingsExportCommand(std::string_view parent) : Command("export", parent) {}
SettingsExportCommand(std::string_view parent) : Command("export", parent, CommandOutputFlags::IgnoreSettingsWarnings) {}

Resource::LocString ShortDescription() const override;
Resource::LocString LongDescription() const override;
Expand Down
2 changes: 1 addition & 1 deletion src/AppInstallerCLICore/Commands/SourceCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ namespace AppInstaller::CLI

struct SourceExportCommand final : public Command
{
SourceExportCommand(std::string_view parent) : Command("export", parent) {}
SourceExportCommand(std::string_view parent) : Command("export", parent, CommandOutputFlags::IgnoreSettingsWarnings) {}

std::vector<Argument> GetArguments() const override;

Expand Down
2 changes: 1 addition & 1 deletion src/AppInstallerCLICore/Workflows/SettingsFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace AppInstaller::CLI::Workflow
{
root["$schema"] = "https://aka.ms/winget-settings-export.schema.json";
root["adminSettings"] = Json::ValueType::objectValue;
root["userSettingsFile"] = Runtime::GetPathTo(Runtime::PathName::UserSettingsFileLocation).u8string();
root["userSettingsFile"] = UserSettings::SettingsFilePath().u8string();
}

void AddAdminSetting(AdminSetting setting)
Expand Down
3 changes: 3 additions & 0 deletions src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
Original file line number Diff line number Diff line change
Expand Up @@ -1541,4 +1541,7 @@ Please specify one of them using the --source option to proceed.</value>
<data name="UserSettings" xml:space="preserve">
<value>User Settings</value>
</data>
<data name="SettingsWarningUsingDefault" xml:space="preserve">
<value>Settings file couldn't load. Using default values.</value>
</data>
</root>
16 changes: 12 additions & 4 deletions src/AppInstallerCLITests/UserSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,12 +419,16 @@ TEST_CASE("SettingsPortablePackageUserRoot", "[settings]")
SECTION("Relative path")
{
DeleteUserSettingsFiles();
std::string_view json = R"({ "installBehavior": { "portablePackageUserRoot": %LOCALAPPDATA%/Portable/Root } })";
std::string_view json = R"({ "installBehavior": { "portablePackageUserRoot": "%LOCALAPPDATA%/Portable/Root" } })";
SetSetting(Stream::PrimaryUserSettings, json);
UserSettingsTest userSettingTest;

REQUIRE(userSettingTest.Get<Setting::PortablePackageUserRoot>().empty());
REQUIRE(userSettingTest.GetWarnings().size() == 1);

auto warnings = userSettingTest.GetWarnings();
REQUIRE(warnings.size() == 1);
REQUIRE(warnings[0].Message == AppInstaller::StringResource::String::SettingsWarningInvalidFieldValue);
REQUIRE(warnings[0].Path == ".installBehavior.portablePackageUserRoot");
}
SECTION("Valid path")
{
Expand All @@ -443,12 +447,16 @@ TEST_CASE("SettingsPortablePackageMachineRoot", "[settings]")
SECTION("Relative path")
{
DeleteUserSettingsFiles();
std::string_view json = R"({ "installBehavior": { "portablePackageMachineRoot": %LOCALAPPDATA%/Portable/Root } })";
std::string_view json = R"({ "installBehavior": { "portablePackageMachineRoot": "%LOCALAPPDATA%/Portable/Root" } })";
SetSetting(Stream::PrimaryUserSettings, json);
UserSettingsTest userSettingTest;

REQUIRE(userSettingTest.Get<Setting::PortablePackageMachineRoot>().empty());
REQUIRE(userSettingTest.GetWarnings().size() == 1);

auto warnings = userSettingTest.GetWarnings();
REQUIRE(warnings.size() == 1);
REQUIRE(warnings[0].Message == AppInstaller::StringResource::String::SettingsWarningInvalidFieldValue);
REQUIRE(warnings[0].Path == ".installBehavior.portablePackageMachineRoot");
}
SECTION("Valid path")
{
Expand Down
37 changes: 37 additions & 0 deletions src/AppInstallerCommonCore/Filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,41 @@ namespace AppInstaller::Filesystem
return path;
}
}

void ReplaceCommonPathPrefix(std::filesystem::path& source, const std::filesystem::path& prefix, std::string_view replacement)
{
auto prefixItr = prefix.begin();
auto sourceItr = source.begin();

while (prefixItr != prefix.end() && sourceItr != source.end())
{
if (*prefixItr != *sourceItr)
{
break;
}

++prefixItr;
++sourceItr;
}

// Only replace source if we found all of prefix
if (prefixItr == prefix.end())
{
std::filesystem::path temp{ replacement };

for (; sourceItr != source.end(); ++sourceItr)
{
temp /= *sourceItr;
}

source = std::move(temp);
}
}

std::filesystem::path GetKnownFolderPath(const KNOWNFOLDERID& id)
{
wil::unique_cotaskmem_string knownFolder = nullptr;
THROW_IF_FAILED(SHGetKnownFolderPath(id, KF_FLAG_NO_ALIAS | KF_FLAG_DONT_VERIFY | KF_FLAG_NO_PACKAGE_REDIRECTION, NULL, &knownFolder));
return knownFolder.get();
}
}
4 changes: 0 additions & 4 deletions src/AppInstallerCommonCore/Public/AppInstallerRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@ namespace AppInstaller::Runtime
PortableLinksUserLocation,
// The location where symlinks to portable packages are stored under machine scope.
PortableLinksMachineLocation,
// The location of the user settings json file.
UserSettingsFileLocation,
// The location of the user settings json file, anonymized using environment variables.
UserSettingsFileLocationForDisplay,
};

// The principal that an ACE applies to.
Expand Down
7 changes: 7 additions & 0 deletions src/AppInstallerCommonCore/Public/winget/Filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.
#pragma once
#include <filesystem>
#include <shtypes.h>

namespace AppInstaller::Filesystem
{
Expand Down Expand Up @@ -35,4 +36,10 @@ namespace AppInstaller::Filesystem

// Get expanded file system path.
std::filesystem::path GetExpandedPath(const std::string& path);

// If `source` begins with all of `prefix`, replace that with `replacement`.
void ReplaceCommonPathPrefix(std::filesystem::path& source, const std::filesystem::path& prefix, std::string_view replacement);

// Gets the path of a known folder.
std::filesystem::path GetKnownFolderPath(const KNOWNFOLDERID& id);
}
1 change: 1 addition & 0 deletions src/AppInstallerCommonCore/Public/winget/Resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ namespace AppInstaller
WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningInvalidValueFromPolicy);
WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningLoadedBackupSettings);
WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningParseError);
WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningUsingDefault);
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/AppInstallerCommonCore/Public/winget/UserSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ namespace AppInstaller::Settings

static UserSettings const& Instance(const std::optional<std::string>& content = std::nullopt);

static std::filesystem::path SettingsFilePath();
static std::filesystem::path SettingsFilePath(bool forDisplay = false);

UserSettings(const UserSettings&) = delete;
UserSettings& operator=(const UserSettings&) = delete;
Expand Down
53 changes: 1 addition & 52 deletions src/AppInstallerCommonCore/Runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace AppInstaller::Runtime
{
using namespace Utility;
using namespace Settings;
using namespace Filesystem;

namespace
{
Expand Down Expand Up @@ -96,13 +97,6 @@ namespace AppInstaller::Runtime
static std::map<PathName, PathDetails> s_Path_TestHook_Overrides;
#endif

std::filesystem::path GetKnownFolderPath(const KNOWNFOLDERID& id)
{
wil::unique_cotaskmem_string knownFolder = nullptr;
THROW_IF_FAILED(SHGetKnownFolderPath(id, KF_FLAG_NO_ALIAS | KF_FLAG_DONT_VERIFY | KF_FLAG_NO_PACKAGE_REDIRECTION, NULL, &knownFolder));
return knownFolder.get();
}

// Gets the user's temp path
std::filesystem::path GetPathToUserTemp()
{
Expand Down Expand Up @@ -166,37 +160,6 @@ namespace AppInstaller::Runtime
return result;
}

// If `source` begins with all of `prefix`, replace that with `replacement`.
void ReplaceCommonPathPrefix(std::filesystem::path& source, const std::filesystem::path& prefix, std::string_view replacement)
{
auto prefixItr = prefix.begin();
auto sourceItr = source.begin();

while (prefixItr != prefix.end() && sourceItr != source.end())
{
if (*prefixItr != *sourceItr)
{
break;
}

++prefixItr;
++sourceItr;
}

// Only replace source if we found all of prefix
if (prefixItr == prefix.end())
{
std::filesystem::path temp{ replacement };

for (; sourceItr != source.end(); ++sourceItr)
{
temp /= *sourceItr;
}

source = std::move(temp);
}
}

DWORD AccessPermissionsFrom(ACEPermissions permissions)
{
DWORD result = 0;
Expand Down Expand Up @@ -547,13 +510,6 @@ namespace AppInstaller::Runtime
case PathName::PortableLinksMachineLocation:
result = GetPathDetailsCommon(path);
break;
case PathName::UserSettingsFileLocation:
result.Path = UserSettings::SettingsFilePath();
break;
case PathName::UserSettingsFileLocationForDisplay:
result.Path = UserSettings::SettingsFilePath();
ReplaceCommonPathPrefix(result.Path, GetKnownFolderPath(FOLDERID_LocalAppData), "%LOCALAPPDATA%");
break;
default:
THROW_HR(E_UNEXPECTED);
}
Expand Down Expand Up @@ -624,13 +580,6 @@ namespace AppInstaller::Runtime
case PathName::PortableLinksMachineLocation:
result = GetPathDetailsCommon(path);
break;
case PathName::UserSettingsFileLocation:
result.Path = UserSettings::SettingsFilePath();
break;
case PathName::UserSettingsFileLocationForDisplay:
result.Path = UserSettings::SettingsFilePath();
ReplaceCommonPathPrefix(result.Path, GetKnownFolderPath(FOLDERID_LocalAppData), "%LOCALAPPDATA%");
break;
default:
THROW_HR(E_UNEXPECTED);
}
Expand Down
Loading

0 comments on commit 8a805cc

Please sign in to comment.