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

Implementation for Zip Install (Non-Portable) #2320

Merged
merged 8 commits into from
Jul 13, 2022
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
13 changes: 13 additions & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ fintimes
Fixfor
flargle
flexera
FOF
foldc
foldcase
FOLDERID
Expand Down Expand Up @@ -166,7 +167,9 @@ IAttachment
IARP
IConfiguration
idx
IEnum
IFACEMETHODIMP
IFile
IGlobal
IHelp
IHost
Expand All @@ -186,6 +189,7 @@ IPersist
IRead
IService
ISettings
IShell
ishelp
ISQ
issuecomment
Expand Down Expand Up @@ -222,6 +226,7 @@ localhost
localizationpriority
LPBYTE
LPDWORD
LPITEMIDLIST
LPWSTR
LSTATUS
LTDA
Expand Down Expand Up @@ -259,11 +264,13 @@ mylog
mysilent
mysilentwithprogress
mytool
NESTEDINSTALLER
NETFX
netlify
Newtonsoft
NOEXPAND
nonetwork
NONFOLDERS
nonterminated
normer
NOSEPARATOR
Expand Down Expand Up @@ -293,6 +300,8 @@ PEGI
pfn
pfxpath
Pherson
pidl
PIDLIST
pkgmgr
pkindex
PMS
Expand Down Expand Up @@ -346,6 +355,8 @@ seof
serializer
setmetadatabymanifestid
SETTINGMAPPING
SHCONTF
SHGDN
Shlobj
sid
SIGNATUREHASH
Expand All @@ -360,6 +371,7 @@ srs
standalone
startswith
streambuf
STRRET
strtoull
subdir
subkey
Expand Down Expand Up @@ -453,4 +465,5 @@ yamlcreateps
yao
ype
Zanollo
ZIPHASH
zy
2 changes: 2 additions & 0 deletions src/AppInstallerCLICore/AppInstallerCLICore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@
<ClInclude Include="TableOutput.h" />
<ClInclude Include="VTSupport.h" />
<ClInclude Include="PackageCollection.h" />
<ClInclude Include="Workflows\ArchiveFlow.h" />
<ClInclude Include="Workflows\CompletionFlow.h" />
<ClInclude Include="Workflows\DependencyNodeProcessor.h" />
<ClInclude Include="Workflows\DownloadFlow.h" />
Expand Down Expand Up @@ -327,6 +328,7 @@
</ClCompile>
<ClCompile Include="Resources.cpp" />
<ClCompile Include="VTSupport.cpp" />
<ClCompile Include="Workflows\ArchiveFlow.cpp" />
<ClCompile Include="Workflows\CompletionFlow.cpp" />
<ClCompile Include="Workflows\DependencyNodeProcessor.cpp" />
<ClCompile Include="Workflows\DownloadFlow.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 @@ -179,6 +179,9 @@
<ClInclude Include="Workflows\PortableFlow.h">
<Filter>Workflows</Filter>
</ClInclude>
<ClInclude Include="Workflows\ArchiveFlow.h">
<Filter>Workflows</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
Expand Down Expand Up @@ -325,6 +328,9 @@
<ClCompile Include="Workflows\PortableFlow.cpp">
<Filter>Workflows</Filter>
</ClCompile>
<ClCompile Include="Workflows\ArchiveFlow.cpp">
<Filter>Workflows</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="PropertySheet.props" />
Expand Down
3 changes: 3 additions & 0 deletions src/AppInstallerCLICore/Resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(ExportIncludeVersionsArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ExportSourceArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ExternalDependencies);
WINGET_DEFINE_RESOURCE_STRINGID(ExtractArchiveFailed);
WINGET_DEFINE_RESOURCE_STRINGID(ExtraPositionalError);
WINGET_DEFINE_RESOURCE_STRINGID(FeatureDisabledByAdminSettingMessage);
WINGET_DEFINE_RESOURCE_STRINGID(FeatureDisabledMessage);
Expand Down Expand Up @@ -188,6 +189,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(MultipleInstalledPackagesFound);
WINGET_DEFINE_RESOURCE_STRINGID(MultiplePackagesFound);
WINGET_DEFINE_RESOURCE_STRINGID(NameArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(NestedInstallerNotFound);
WINGET_DEFINE_RESOURCE_STRINGID(NoApplicableInstallers);
WINGET_DEFINE_RESOURCE_STRINGID(NoExperimentalFeaturesMessage);
WINGET_DEFINE_RESOURCE_STRINGID(NoInstalledPackageFound);
Expand Down Expand Up @@ -216,6 +218,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(PortableHashMismatchOverridden);
WINGET_DEFINE_RESOURCE_STRINGID(PortableHashMismatchOverrideRequired);
WINGET_DEFINE_RESOURCE_STRINGID(PortableInstallFailed);
WINGET_DEFINE_RESOURCE_STRINGID(PortableInstallFromArchiveNotSupported);
WINGET_DEFINE_RESOURCE_STRINGID(PortableRegistryCollisionOverridden);
WINGET_DEFINE_RESOURCE_STRINGID(PositionArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(PreserveArgumentDescription);
Expand Down
59 changes: 59 additions & 0 deletions src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "pch.h"
#include "ArchiveFlow.h"
#include "winget/Archive.h"

namespace AppInstaller::CLI::Workflow
{
void ExtractFilesFromArchive(Execution::Context& context)
{
const auto& installerPath = context.Get<Execution::Data::InstallerPath>();
const auto& installerParentPath = installerPath.parent_path();

// TODO: For portables, extract portables to final install location and log to local database.
HRESULT hr = AppInstaller::Archive::TryExtractArchive(installerPath, installerParentPath);
AICLI_LOG(CLI, Info, << "Extracting archive to: " << installerParentPath);

if (SUCCEEDED(hr))
{
AICLI_LOG(CLI, Info, << "Successfully extracted archive");
ryfu-msft marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
AICLI_LOG(CLI, Info, << "Failed to extract archive with code " << hr);
context.Reporter.Error() << Resource::String::ExtractArchiveFailed << std::endl;
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_EXTRACT_ARCHIVE_FAILED);
}
}

void VerifyAndSetNestedInstaller(Execution::Context& context)
{
const auto& installer = context.Get<Execution::Data::Installer>().value();
if (installer.NestedInstallerFiles.empty())
{
// Manifest validation should prevent this from happening
AICLI_LOG(CLI, Error, << "No entries specified for NestedInstallerFiles");
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_INVALID_MANIFEST);
}

const auto& installerPath = context.Get<Execution::Data::InstallerPath>();
const auto& installerParentPath = installerPath.parent_path();

const auto& relativeFilePath = ConvertToUTF16(installer.NestedInstallerFiles[0].RelativeFilePath);
ryfu-msft marked this conversation as resolved.
Show resolved Hide resolved

std::filesystem::path nestedInstallerPath = installerParentPath / relativeFilePath;

if (!std::filesystem::exists(nestedInstallerPath))
{
AICLI_LOG(CLI, Error, << "Unable to locate nested installer at: " << nestedInstallerPath);
context.Reporter.Error() << Resource::String::NestedInstallerNotFound << ' ' << nestedInstallerPath << std::endl;
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_NESTEDINSTALLER_NOT_FOUND);
}
else
{
AICLI_LOG(CLI, Info, << "Setting installerPath to: " << nestedInstallerPath);
context.Add<Execution::Data::InstallerPath>(nestedInstallerPath);
}
}
}
19 changes: 19 additions & 0 deletions src/AppInstallerCLICore/Workflows/ArchiveFlow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include "ExecutionContext.h"

namespace AppInstaller::CLI::Workflow
{
// Extracts the files from an archive
// Required Args: None
// Inputs: InstallerPath
// Outputs: None
void ExtractFilesFromArchive(Execution::Context& context);

// Verifies that the NestedInstaller exists and sets the InstallerPath
// Required Args: None
// Inputs: Installer, InstallerPath
// Outputs: None
void VerifyAndSetNestedInstaller(Execution::Context& context);
}
1 change: 1 addition & 0 deletions src/AppInstallerCLICore/Workflows/DownloadFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ namespace AppInstaller::CLI::Workflow
case InstallerTypeEnum::Nullsoft:
case InstallerTypeEnum::Portable:
case InstallerTypeEnum::Wix:
case InstallerTypeEnum::Zip:
context << DownloadInstallerFile;
break;
case InstallerTypeEnum::Msix:
Expand Down
34 changes: 26 additions & 8 deletions src/AppInstallerCLICore/Workflows/InstallFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
#include "ShellExecuteInstallerHandler.h"
#include "MSStoreInstallerHandler.h"
#include "MsiInstallFlow.h"
#include "ArchiveFlow.h"
#include "PortableFlow.h"
#include "WorkflowBase.h"
#include "Workflows/DependenciesFlow.h"
#include <AppInstallerDeployment.h>
#include <winget/ARPCorrelation.h>
#include <winget/Archive.h>
#include <Argument.h>
#include <Command.h>

Expand Down Expand Up @@ -316,28 +318,27 @@ namespace AppInstaller::CLI::Workflow
}
}

void ExecuteInstaller(Execution::Context& context)
void ExecuteInstallerForType::operator()(Execution::Context& context) const
{
const auto& installer = context.Get<Execution::Data::Installer>().value();

bool isUpdate = WI_IsFlagSet(context.GetFlags(), Execution::ContextFlag::InstallerExecutionUseUpdate);
UpdateBehaviorEnum updateBehavior = context.Get<Execution::Data::Installer>().value().UpdateBehavior;

switch (installer.InstallerType)
switch (m_installerType)
{
case InstallerTypeEnum::Exe:
case InstallerTypeEnum::Burn:
case InstallerTypeEnum::Inno:
case InstallerTypeEnum::Msi:
case InstallerTypeEnum::Nullsoft:
case InstallerTypeEnum::Wix:
if (isUpdate && installer.UpdateBehavior == UpdateBehaviorEnum::UninstallPrevious)
if (isUpdate && updateBehavior == UpdateBehaviorEnum::UninstallPrevious)
{
context <<
GetUninstallInfo <<
ExecuteUninstaller;
context.ClearFlags(Execution::ContextFlag::InstallerExecutionUseUpdate);
}
if (ShouldUseDirectMSIInstall(installer.InstallerType, context.Args.Contains(Execution::Args::Type::Silent)))
if (ShouldUseDirectMSIInstall(m_installerType, context.Args.Contains(Execution::Args::Type::Silent)))
{
context << DirectMSIInstall;
}
Expand All @@ -355,7 +356,7 @@ namespace AppInstaller::CLI::Workflow
(isUpdate ? MSStoreUpdate : MSStoreInstall);
break;
case InstallerTypeEnum::Portable:
if (isUpdate && installer.UpdateBehavior == UpdateBehaviorEnum::UninstallPrevious)
if (isUpdate && updateBehavior == UpdateBehaviorEnum::UninstallPrevious)
{
context <<
GetUninstallInfo <<
Expand All @@ -364,11 +365,27 @@ namespace AppInstaller::CLI::Workflow
}
context << PortableInstall;
break;
case InstallerTypeEnum::Zip:
context << ArchiveInstall;
break;
default:
THROW_HR(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED));
}
}

void ExecuteInstaller(Execution::Context& context)
{
context << Workflow::ExecuteInstallerForType(context.Get<Execution::Data::Installer>().value().InstallerType);
}

void ArchiveInstall(Execution::Context& context)
{
context <<
ExtractFilesFromArchive <<
VerifyAndSetNestedInstaller <<
ExecuteInstallerForType(context.Get<Execution::Data::Installer>().value().NestedInstallerType);
}

void ShellExecuteInstall(Execution::Context& context)
{
context <<
Expand Down Expand Up @@ -524,7 +541,8 @@ namespace AppInstaller::CLI::Workflow
void EnsureSupportForInstall(Execution::Context& context)
{
context <<
Workflow::EnsureSupportForPortableInstall;
Workflow::EnsureSupportForPortableInstall <<
Workflow::EnsureNonPortableTypeForArchiveInstall;
}

void InstallMultiplePackages::operator()(Execution::Context& context) const
Expand Down
22 changes: 21 additions & 1 deletion src/AppInstallerCLICore/Workflows/InstallFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,26 @@ namespace AppInstaller::CLI::Workflow
// Outputs: None
void EnsurePackageAgreementsAcceptanceForMultipleInstallers(Execution::Context& context);

// Composite flow that chooses what to do based on the installer type.
// Starts execution of the installer.
// Required Args: None
// Inputs: Installer, InstallerPath
// Outputs: None
void ExecuteInstaller(Execution::Context& context);

// Composite flow that chooses what to do based on the installer type.
// Required Args: None
// Inputs: Installer, InstallerPath
// Outputs: None
struct ExecuteInstallerForType : public WorkflowTask
{
ExecuteInstallerForType(Manifest::InstallerTypeEnum installerType) : WorkflowTask("ExecuteInstallerForType"), m_installerType(installerType) {}

void operator()(Execution::Context& context) const override;

private:
Manifest::InstallerTypeEnum m_installerType;
};

// Runs the installer via ShellExecute.
// Required Args: None
// Inputs: Installer, InstallerPath
Expand All @@ -102,6 +116,12 @@ namespace AppInstaller::CLI::Workflow
// Outputs: None
void PortableInstall(Execution::Context& context);

// Runs the flow for installing a package from an archive.
// Required Args: None
// Inputs: Installer, InstallerPath, Manifest
// Outputs: None
void ArchiveInstall(Execution::Context& context);

// Verifies parameters for install to ensure success.
// Required Args: None
// Inputs:
Expand Down
12 changes: 12 additions & 0 deletions src/AppInstallerCLICore/Workflows/PortableFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -621,4 +621,16 @@ namespace AppInstaller::CLI::Workflow
EnsureVolumeSupportsReparsePoints;
}
}

// TODO: remove this check once support for portable in archive has been implemented
void EnsureNonPortableTypeForArchiveInstall(Execution::Context& context)
{
auto nestedInstallerType = context.Get<Execution::Data::Installer>().value().NestedInstallerType;

if (nestedInstallerType == InstallerTypeEnum::Portable)
{
context.Reporter.Error() << Resource::String::PortableInstallFromArchiveNotSupported << std::endl;
AICLI_TERMINATE_CONTEXT(ERROR_NOT_SUPPORTED);
}
}
}
2 changes: 2 additions & 0 deletions src/AppInstallerCLICore/Workflows/PortableFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ namespace AppInstaller::CLI::Workflow
void PortableUninstallImpl(Execution::Context& context);

void EnsureSupportForPortableInstall(Execution::Context& context);

void EnsureNonPortableTypeForArchiveInstall(Execution::Context& context);
}
Loading