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

Configure export command #4434

Merged
merged 16 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ GRPICONDIR
GRPICONDIRENTRY
guiddef
Hackathon
hashtables
helplib
helplibrary
hhx
Expand Down Expand Up @@ -217,6 +218,7 @@ JToken
JValue
Kaido
KNOWNFOLDERID
kool
ktf
ldcase
learnxinyminutes
Expand Down
17 changes: 14 additions & 3 deletions doc/Settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,15 +332,26 @@ Currently, this means that properly attributed configuration units (and only tho
"experimentalFeatures": {
"configureSelfElevate": true
},
```
```

### storeDownload

This feature enables packages to be downloaded from the Microsoft Store.
This feature enables packages to be downloaded from the Microsoft Store.
You can enable the feature as shown below.

```json
"experimentalFeatures": {
"storeDownload": true
},
```

### configureExport

This feature enables exporting a configuration file.
You can enable the feature as shown below.

```json
"experimentalFeatures": {
"configureExport": true
},
```
4 changes: 4 additions & 0 deletions doc/windows/package-manager/winget/returnCodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ Installation failed. Restart your PC then try again. |
| 0x8A15C00C | -1978286068 | WINGET_CONFIG_ERROR_SET_DEPENDENCY_CYCLE | The dependency graph contains a cycle which cannot be resolved. |
| 0x8A15C00D | -1978286067 | WINGET_CONFIG_ERROR_INVALID_FIELD_VALUE | The configuration has an invalid field value. |
| 0x8A15C00E | -1978286066 | WINGET_CONFIG_ERROR_MISSING_FIELD | The configuration is missing a field. |
| 0x8A15C00F | -1978286065 | WINGET_CONFIG_ERROR_TEST_FAILED | Some of the configuration units failed while testing their state. |
| 0x8A15C010 | -1978286064 | WINGET_CONFIG_ERROR_TEST_NOT_RUN | Configuration state was not tested. |
| 0x8A15C011 | -1978286063 | WINGET_CONFIG_ERROR_GET_FAILED | The configuration unit failed getting its properties. |

## Configuration Processor Errors

Expand All @@ -211,3 +214,4 @@ Installation failed. Restart your PC then try again. |
| 0x8A15C109 | -1978285815 | WINGET_CONFIG_ERROR_UNIT_INVOKE_INVALID_RESULT | The configuration unit returned an unexpected result during execution. |
| 0x8A15C110 | -1978285814 | WINGET_CONFIG_ERROR_UNIT_SETTING_CONFIG_ROOT | A unit contains a setting that requires the config root. |
| 0x8A15C111 | -1978285813 | WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE_ADMIN | Loading the module for the configuration unit failed because it requires administrator privileges to run. |
| 0x8A15C112 | -1978285812 | WINGET_CONFIG_ERROR_NOT_SUPPORTED_BY_PROCESSOR | Operation is not supported by the configuration processor. |
5 changes: 5 additions & 0 deletions schemas/JSON/settings/settings.schema.0.2.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,11 @@
"description": "Enable support for downloading packages from the Microsoft Store",
"type": "boolean",
"default": false
},
"configureExport": {
"description": "Enable support for the configure export command",
"type": "boolean",
"default": false
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/AppInstallerCLICore/AppInstallerCLICore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@
<ClInclude Include="ConfigurationCommon.h" />
<ClInclude Include="ConfigurationContext.h" />
<ClInclude Include="ConfigurationWingetDscModuleUnitValidation.h" />
<ClInclude Include="ConfigureExportCommand.h" />
<ClInclude Include="ContextOrchestrator.h" />
<ClInclude Include="COMContext.h" />
<ClInclude Include="Public\ConfigurationSetProcessorFactoryRemoting.h" />
Expand Down Expand Up @@ -446,6 +447,7 @@
<ClCompile Include="ConfigurationDynamicRuntimeFactory.cpp" />
<ClCompile Include="ConfigurationSetProcessorFactoryRemoting.cpp" />
<ClCompile Include="ConfigurationWingetDscModuleUnitValidation.cpp" />
<ClCompile Include="ConfigureExportCommand.cpp" />
<ClCompile Include="ContextOrchestrator.cpp" />
<ClCompile Include="Workflows\ConfigurationFlow.cpp" />
<ClCompile Include="Workflows\DependenciesFlow.cpp" />
Expand Down
6 changes: 6 additions & 0 deletions src/AppInstallerCLICore/AppInstallerCLICore.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@
<ClInclude Include="ConfigurationWingetDscModuleUnitValidation.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ConfigureExportCommand.h">
<Filter>Commands</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
Expand Down Expand Up @@ -472,6 +475,9 @@
<ClCompile Include="ConfigurationDynamicRuntimeFactory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ConfigureExportCommand.cpp">
<Filter>Commands</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="PropertySheet.props" />
Expand Down
10 changes: 8 additions & 2 deletions src/AppInstallerCLICore/Argument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,6 @@ namespace AppInstaller::CLI
return { type, "position"_liv };

// Export Command
case Execution::Args::Type::OutputFile:
return { type, "output"_liv, 'o' };
case Execution::Args::Type::IncludeVersions:
return { type, "include-versions"_liv };

Expand Down Expand Up @@ -211,6 +209,12 @@ namespace AppInstaller::CLI
return { type, "disable"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::StubType };
case Execution::Args::Type::ConfigurationModulePath:
return { type, "module-path"_liv };
case Execution::Args::Type::ConfigurationExportPackageId:
return { type, "package-id"_liv };
case Execution::Args::Type::ConfigurationExportModule:
return { type, "module"_liv };
case Execution::Args::Type::ConfigurationExportResource:
return { type, "resource"_liv };

// Download command
case Execution::Args::Type::DownloadDirectory:
Expand All @@ -237,6 +241,8 @@ namespace AppInstaller::CLI
return { type, "open-logs"_liv, "logs"_liv };
case Execution::Args::Type::Force:
return { type, "force"_liv, ArgTypeCategory::CopyFlagToSubContext };
case Execution::Args::Type::OutputFile:
return { type, "output"_liv, 'o' };

case Execution::Args::Type::DependencySource:
return { type, "dependency-source"_liv, ArgTypeCategory::ExtendedSource };
Expand Down
2 changes: 2 additions & 0 deletions src/AppInstallerCLICore/Command.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ namespace AppInstaller::CLI
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::string_view parent, Settings::ExperimentalFeature::Feature feature) :
Command(name, {}, parent, Command::Visibility::Show, 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) :
Expand Down
3 changes: 2 additions & 1 deletion src/AppInstallerCLICore/Commands/ConfigureCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "ConfigureShowCommand.h"
#include "ConfigureTestCommand.h"
#include "ConfigureValidateCommand.h"
#include "ConfigureExportCommand.h"
#include "Workflows/ConfigurationFlow.h"
#include "Workflows/MSStoreInstallerHandler.h"
#include "ConfigurationCommon.h"
Expand All @@ -25,6 +26,7 @@ namespace AppInstaller::CLI
std::make_unique<ConfigureShowCommand>(FullName()),
std::make_unique<ConfigureTestCommand>(FullName()),
std::make_unique<ConfigureValidateCommand>(FullName()),
std::make_unique<ConfigureExportCommand>(FullName()),
});
}

Expand All @@ -51,7 +53,6 @@ namespace AppInstaller::CLI

Utility::LocIndView ConfigureCommand::HelpLink() const
{
// TODO: Make this exist
return "https://aka.ms/winget-command-configure"_liv;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ namespace AppInstaller::CLI

Utility::LocIndView ConfigureShowCommand::HelpLink() const
{
// TODO: Make this exist
return "https://aka.ms/winget-command-configure#show"_liv;
}

void ConfigureShowCommand::ExecuteInternal(Execution::Context& context) const
{
context <<
VerifyIsFullPackage <<
VerifyFileOrUri(Execution::Args::Type::ConfigurationFile) <<
CreateConfigurationProcessor <<
OpenConfigurationSet <<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ namespace AppInstaller::CLI

Utility::LocIndView ConfigureTestCommand::HelpLink() const
{
// TODO: Make this exist
return "https://aka.ms/winget-command-configure#test"_liv;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ namespace AppInstaller::CLI

Utility::LocIndView ConfigureValidateCommand::HelpLink() const
{
// TODO: Make this exist
return "https://aka.ms/winget-command-configure#validate"_liv;
}

Expand Down
64 changes: 64 additions & 0 deletions src/AppInstallerCLICore/ConfigureExportCommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "pch.h"
#include "ConfigureExportCommand.h"
#include "Workflows/ConfigurationFlow.h"
#include "ConfigurationCommon.h"

using namespace AppInstaller::CLI::Workflow;

namespace AppInstaller::CLI
{
std::vector<Argument> ConfigureExportCommand::GetArguments() const
{
return {
Argument{ Execution::Args::Type::OutputFile, Resource::String::OutputFileArgumentDescription, true },
Argument{ Execution::Args::Type::ConfigurationExportPackageId, Resource::String::ConfigureExportPackageId },
Argument{ Execution::Args::Type::ConfigurationExportModule, Resource::String::ConfigureExportModule },
Argument{ Execution::Args::Type::ConfigurationExportResource, Resource::String::ConfigureExportResource },
Argument{ Execution::Args::Type::ConfigurationModulePath, Resource::String::ConfigurationModulePath },
};
}

Resource::LocString ConfigureExportCommand::ShortDescription() const
{
return { Resource::String::ConfigureExportCommandShortDescription };
}

Resource::LocString ConfigureExportCommand::LongDescription() const
{
return { Resource::String::ConfigureExportCommandLongDescription };
}

Utility::LocIndView ConfigureExportCommand::HelpLink() const
{
return "https://aka.ms/winget-command-configure#export"_liv;
}

void ConfigureExportCommand::ExecuteInternal(Execution::Context& context) const
{
context <<
VerifyIsFullPackage <<
CreateConfigurationProcessor <<
CreateOrOpenConfigurationSet <<
AddWinGetPackageAndResource <<
WriteConfigFile;
}

void ConfigureExportCommand::ValidateArgumentsInternal(Execution::Args& execArgs) const
{
Configuration::ValidateCommonArguments(execArgs);

bool validInputArgs = false;
if (execArgs.Contains(Execution::Args::Type::ConfigurationExportModule, Execution::Args::Type::ConfigurationExportResource) ||
execArgs.Contains(Execution::Args::Type::ConfigurationExportPackageId))
{
validInputArgs = true;
}

if (!validInputArgs)
{
throw CommandException(Resource::String::ConfigureExportArgumentError);
}
}
}
23 changes: 23 additions & 0 deletions src/AppInstallerCLICore/ConfigureExportCommand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include "Command.h"

namespace AppInstaller::CLI
{
struct ConfigureExportCommand final : public Command
Copy link
Contributor

Choose a reason for hiding this comment

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

Just curious if there is a design preference here. The subcommands for other areas like pinning are contained within the parent file. For example, PinRemoveCommand is contained in PinCommand.h and SettingsExportCommand is contained in SettingsCommand.h. Is there a reason that all the configuration sub commands wouldn't be included in ConfigureCommand.h ?

Copy link
Member

Choose a reason for hiding this comment

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

My 2🪙: This isn't large enough to warrant a new file, which is to say that if a subcommand were itself rather complex I think it would be ok to break it out (or if it had its own subcommands, etc.)

{
ConfigureExportCommand(std::string_view parent) : Command("export", parent, Settings::ExperimentalFeature::Feature::ConfigureExport) {}

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

Resource::LocString ShortDescription() const override;
Resource::LocString LongDescription() const override;

Utility::LocIndView HelpLink() const override;

protected:
void ExecuteInternal(Execution::Context& context) const override;
void ValidateArgumentsInternal(Execution::Args& execArgs) const override;
};
}
11 changes: 9 additions & 2 deletions src/AppInstallerCLICore/ExecutionArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ namespace AppInstaller::CLI::Execution
Position,

// Export Command
OutputFile,
IncludeVersions,

// Import Command
Expand Down Expand Up @@ -126,6 +125,9 @@ namespace AppInstaller::CLI::Execution
ConfigurationEnable,
ConfigurationDisable,
ConfigurationModulePath,
ConfigurationExportPackageId,
ConfigurationExportModule,
ConfigurationExportResource,

// Common arguments
NoVT, // Disable VirtualTerminal outputs
Expand All @@ -138,6 +140,7 @@ namespace AppInstaller::CLI::Execution
Wait, // Prompts the user to press any key before exiting
OpenLogs, // Opens the default logs directory after executing the command
Force, // Forces the execution of the workflow with non security related issues
OutputFile,

DependencySource, // Index source to be queried against for finding dependencies
CustomHeader, // Optional Rest source header
Expand All @@ -159,7 +162,11 @@ namespace AppInstaller::CLI::Execution
Max
};

bool Contains(Type arg) const { return (m_parsedArgs.count(arg) != 0); }
template<typename... T, std::enable_if_t<(... && std::is_same_v<T, Args::Type>), bool> = true>
Copy link
Member

Choose a reason for hiding this comment

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

Pretty sure you can just do:

Suggested change
template<typename... T, std::enable_if_t<(... && std::is_same_v<T, Args::Type>), bool> = true>
template<Args::Type... T>

bool Contains(T... arg) const
Copy link
Member

Choose a reason for hiding this comment

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

You could also use a std::initializer_list with the low cost of putting {} around your parameter list. But it definitely wouldn't be as fun as figuring out this.

{
return (... && (m_parsedArgs.count(arg) != 0));
}

const std::vector<std::string>* GetArgs(Type arg) const
{
Expand Down
16 changes: 14 additions & 2 deletions src/AppInstallerCLICore/Resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationEnabledMessage);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationEnableMessage);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationEnablingMessage);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationExportAddingToFile);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationExportFailed);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationExportSuccessful);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationFailedToApply);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationFailedToGetDetails);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationFailedToTest);
Expand All @@ -79,6 +82,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationFileInvalidYAML);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationFileVersionUnknown);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationGettingDetails);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationGettingResourceSettings);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationInDesiredState);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationInform);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationInitializing);
Expand Down Expand Up @@ -132,6 +136,14 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationWarningValueTruncated);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureExportArgumentError);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureExportCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureExportCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureExportModule);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureExportPackageId);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureExportResource);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureExportUnitDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureExportUnitInstallDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureShowCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureShowCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigureTestCommandLongDescription);
Expand Down Expand Up @@ -535,6 +547,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(SourceArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SourceCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SourceCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SourceExplicitArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SourceExportCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SourceExportCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListAdditionalSource);
Expand All @@ -543,12 +556,12 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(SourceListCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListData);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListExplicit);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListField);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListIdentifier);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListName);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListNoneFound);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListNoSources);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListExplicit);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListTrustLevel);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListType);
WINGET_DEFINE_RESOURCE_STRINGID(SourceListUpdated);
Expand All @@ -563,7 +576,6 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(SourceRemoveCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SourceRemoveOne);
WINGET_DEFINE_RESOURCE_STRINGID(SourceRequiresAuthentication);
WINGET_DEFINE_RESOURCE_STRINGID(SourceExplicitArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SourceResetAll);
WINGET_DEFINE_RESOURCE_STRINGID(SourceResetCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SourceResetCommandShortDescription);
Expand Down
Loading
Loading