Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ namespace UniGetUI.PackageEngine.Managers.PowerShellManager;

internal sealed class PowerShellPkgOperationHelper : BasePkgOperationHelper
{
internal const string ErrorVariableName = "UniGetUIOperationError";

public PowerShellPkgOperationHelper(PowerShell manager)
: base(manager) { }

Expand Down Expand Up @@ -53,19 +55,30 @@ OperationType operation
parameters.AddRange(["-RequiredVersion", options.Version]);
}

parameters.AddRange(
operation switch
{
OperationType.Update => options.CustomParameters_Update,
OperationType.Uninstall => options.CustomParameters_Uninstall,
_ => options.CustomParameters_Install,
}
IReadOnlyList<string> customParameters = operation switch
{
OperationType.Update => options.CustomParameters_Update,
OperationType.Uninstall => options.CustomParameters_Uninstall,
_ => options.CustomParameters_Install,
};

bool bindsOwnErrorVariable = customParameters.Any(parameter =>
parameter.StartsWith("-ev", StringComparison.OrdinalIgnoreCase)
|| parameter.StartsWith("-errorv", StringComparison.OrdinalIgnoreCase)
);

if (!bindsOwnErrorVariable)
parameters.AddRange(["-ErrorVariable", ErrorVariableName]);

parameters.AddRange(customParameters);

// Windows PowerShell 5.x defaults to TLS 1.0/1.1, which the PowerShell Gallery rejects; force TLS 1.2 so gallery operations can connect under -NoProfile
if (operation is not OperationType.Uninstall)
parameters.Insert(0, "[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;");

if (!bindsOwnErrorVariable)
parameters.Add($";if(${ErrorVariableName}){{exit(1)}}");

return parameters;
}

Expand Down
52 changes: 52 additions & 0 deletions src/UniGetUI.PackageEngine.Tests/PowerShellManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,58 @@ public void GetParameters_UpdateOmitsScope()
Assert.DoesNotContain("-Scope", parameters);
}

[Theory]
[InlineData(OperationType.Install)]
[InlineData(OperationType.Update)]
[InlineData(OperationType.Uninstall)]
public void GetParameters_PropagatesNonTerminatingErrorsToTheExitCode(OperationType operation)
{
var manager = new PowerShell();
var package = BuildInstalledPackage(manager);

var parameters = manager.OperationHelper.GetParameters(package, new InstallOptions(), operation);

var errorVariableIndex = parameters.ToList().IndexOf("-ErrorVariable");
Assert.True(errorVariableIndex >= 0);
Assert.Equal(PowerShellPkgOperationHelper.ErrorVariableName, parameters[errorVariableIndex + 1]);
Assert.Equal(
$";if(${PowerShellPkgOperationHelper.ErrorVariableName}){{exit(1)}}",
parameters[^1]
);
}

[Theory]
[InlineData("-ErrorVariable")]
[InlineData("-ev")]
[InlineData("-errorvariable:mine")]
public void GetParameters_YieldsToACustomErrorVariable(string customParameter)
{
var manager = new PowerShell();
var package = BuildInstalledPackage(manager);

var options = new InstallOptions { CustomParameters_Update = [customParameter, "mine"] };
var parameters = manager.OperationHelper.GetParameters(package, options, OperationType.Update);

Assert.DoesNotContain(PowerShellPkgOperationHelper.ErrorVariableName, parameters);
Assert.DoesNotContain(
$";if(${PowerShellPkgOperationHelper.ErrorVariableName}){{exit(1)}}",
parameters
);
}

[Fact]
public void GetParameters_KeepsCustomParametersBoundToTheCmdlet()
{
var manager = new PowerShell();
var package = BuildInstalledPackage(manager);

var options = new InstallOptions { CustomParameters_Update = ["-Proxy", "http://proxy"] };
var parameters = manager.OperationHelper.GetParameters(package, options, OperationType.Update);

Assert.Equal("-Proxy", parameters[^3]);
Assert.Equal("http://proxy", parameters[^2]);
}

[Fact]
public void Capabilities_ScopeAppliesToInstallOnly()
{
Expand Down
Loading