-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Implement V1 manifest and schema validation #740
Conversation
!Runtime::IsCurrentOSVersionGreaterThanOrEqual(Version(manifest.MinOSVersion))) | ||
{ | ||
context.Reporter.Error() << Resource::String::InstallationRequiresHigherWindows << ' ' << manifest.MinOSVersion << std::endl; | ||
AICLI_TERMINATE_CONTEXT(HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the motivation to remove this, but it does mean that we will not message the reason for failure to the user (or ourselves for the failure code). Maybe it is upcoming in my reading of the PR, but we need a way to message the failure state of no applicable installers. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the MinOSVersion check is moved to installer selection logic since in the new world each installer has its own MinOSVersion. It will be part of the No_Applicable_Installer error
#Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I think we need to do a better job of messaging the reason that there are not applicable installers. Some of that burden could be placed on search to filter them out before we even attempt to install, but I prefer to show everything and have the user be informed that we don't have their flavor of installer rather than we don't even know what they are talking about.
It might be more complex, and thus not piled on to this PR, but I think we should attempt to give some reason as to why there are no applicable installers. Imagine:
for each installer
reason[i] = GetAllReasonsWhyNotApplicable(installer)
if (AndAllReasons() != 0)
ReportReasons(AndAllReasons())
So if all installers require a newer OS, we say that. If they are all ARM, we can say that they are for a different processor architecture. If one required a newer OS and one is ARM, we say both somehow.
In reply to: 571311595 [](ancestors = 571311595)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add a todo for better message regarding installer selection
In reply to: 571318031 [](ancestors = 571318031,571311595)
if (isOSVersionSatisfied1 && !isOSVersionSatisfied2) | ||
{ | ||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's re-write the loop to check IsInstallerApplicable
first before ever calling IsInstallerBetterMatch
. That way we don't need to duplicate these kinds of boolean checks. It ends up making this function just the arch > arch comparison. Not sure why I didn't think of it when I rewrote this a while back. #Resolved
@@ -77,8 +80,34 @@ namespace AppInstaller::CLI::Workflow | |||
{ | |||
const auto& manifest = context.Get<Execution::Data::Manifest>(); | |||
|
|||
// Channel is moved to installer level, get all channels from all installers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Channel is moved to installer level, get all channels from all installers [](start = 8, length = 76)
Channel is not an installer level item. It is a part of the version. If the schema has this change, I obviously missed it in review. #Resolved
void GetManifestFromArg(Execution::Context& context) | ||
{ | ||
Logging::Telemetry().LogIsManifestLocal(true); | ||
|
||
context << | ||
VerifyFile(Execution::Args::Type::Manifest) << | ||
VerifyPath(Execution::Args::Type::Manifest) << |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VerifyPath [](start = 12, length = 10)
This one does not seem like it should have changed, winget install -m a_directory
will now work? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will work if the directory contains only one manifest(either split manifest files or a singleton inside). The input will be checked in ValidateInput method in manifest parsing
In reply to: 571315313 [](ancestors = 571315313)
@@ -39,7 +39,7 @@ public void HashFileNotFound() | |||
{ | |||
var result = TestCommon.RunAICLICommand("hash", TestCommon.GetTestDataFile("DoesNot.Exist")); | |||
Assert.AreEqual(Constants.ErrorCode.ERROR_FILE_NOT_FOUND, result.ExitCode); | |||
Assert.True(result.StdOut.Contains("File does not exist")); | |||
Assert.True(result.StdOut.Contains("Path does not exist")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Path [](start = 48, length = 4)
This one should not have changed. #Resolved
@@ -0,0 +1,23 @@ | |||
PackageIdentifier: microsoft.msixsdk |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These split manifests should be in a directory for organization and testing. Was it complicating the copy on build? #Resolved
} | ||
} | ||
|
||
std::string LoadResourceAsString(PCWSTR resourceModuleName, PCWSTR resourceName, PCWSTR resourceType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PCWSTR [](start = 37, length = 6)
std::wstring_view #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although I suppose that doesn't require null termination, so it is suspect. We should probably add a utility type that can handle this for us.
In reply to: 571321711 [](ancestors = 571321711)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
per offline chat, we decided to remove the resourceModuleName parameter, leave the other 2 PCWSTR as they are because that's what MAKEINTRESOURCE produces and later consumed by resource related apis
In reply to: 571322386 [](ancestors = 571322386,571321711)
|
||
std::string LoadResourceAsString(PCWSTR resourceModuleName, PCWSTR resourceName, PCWSTR resourceType) | ||
{ | ||
HMODULE resourceModule = GetModuleHandle(resourceModuleName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GetModuleHandle [](start = 33, length = 15)
If you are going to allow arbitrary modules here, you should use the proper, thread safe GetModuleHandleEx and a wil::unique_hmodule to hold it. #Resolved
// - DefaultLocale matches in version manifest and defaultLocale manifest | ||
// - Validate manifest type correctness | ||
// - Allowed file type in multi file manifest: version, installer, defaultLocale, locale | ||
// - Allowed file type in multi file manifest: preview manifest, merged and singleton |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
multi [](start = 36, length = 5)
single #Resolved
template <Localization L> | ||
struct LocalizationMapping | ||
{ | ||
// value_t type specifies the type of this data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// value_t type specifies the type of this data [](start = 12, length = 47)
Since almost everything is going to be string_t, you could define it here in the unspecialized definition. Then one only needs to specify the very few exceptions to the rule (1 right now). #Resolved
// fullValidation: Bool to set if manifest creation should perform extra validation that client does not need. | ||
// e.g. Channel should be null. Client code does not need this check to work properly. | ||
// throwOnWarning: Bool to indicate if an exception should be thrown with only warnings detected in the manifest. | ||
// resourceDll: Binary where schemas are embedded, or nullptr if they are embedded in the binary that created the process |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// resourceDll: Binary where schemas are embedded, or nullptr if they are embedded in the binary that created the process [](start = 4, length = 124)
This seems like it is only marginally useful for some negative test case. Isn't it possible to determine the module that the current code is executing in? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's mainly for WinGetUtil.dll, I cannot find a simple way to detect the code is being called by wingetutil(or you prefer a bool like isFromWinGetUtil)?
In reply to: 571327922 [](ancestors = 571327922)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either use GetModuleHandleEx or https://devblogs.microsoft.com/oldnewthing/20041025-00
In reply to: 571330356 [](ancestors = 571330356,571327922)
src/WinGetUtil/WinGetUtil.h
Outdated
@@ -76,9 +76,11 @@ extern "C" | |||
// Validates a given manifest. Returns a bool for validation result and | |||
// a string representing validation errors if validation failed. | |||
WINGET_UTIL_API WinGetValidateManifest( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WinGetValidateManifest [](start = 20, length = 22)
This will need to be a new function and the old one will need to continue to work with it's existing signature. #Resolved
src/WinGetUtil/Exports.cpp
Outdated
WINGET_STRING_OUT* message) try | ||
WINGET_STRING_OUT* message, | ||
WINGET_STRING mergedManifestPath, | ||
BOOL isPartialManifest) try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isPartialManifest [](start = 13, length = 17)
We need to know the expected type, or return it, or the service code will need to parse the manifest enough to answer the question of "Does this file name pattern match the type in the manifest?".
Rather than a BOOL here, we should take in an enum with values for single file, split, sub-component of a split. It could even be an in-out where we also let them give us "don't know" and we give them back the answer. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🕐
Misspellings found, please review:
To accept these changes, run the following commands from this repository on this branch
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change
Validation
Note: After this change, we might need to revisit and relax restrictions in some of v1 manifest schemas as I found around 300+ manifests in current winget-pkgs will fail in new restrictions imposed by V1 manifest schemas
Microsoft Reviewers: Open in CodeFlow