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
31 changes: 31 additions & 0 deletions dotnet/src/Devolutions.Pinget.Cli/ImportInstallRequestFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Text.Json;
using Devolutions.Pinget.Core;

namespace Devolutions.Pinget.Cli;

internal static class ImportInstallRequestFactory
{
internal static InstallRequest Create(
PackageQuery query,
JsonElement package,
bool acceptPackageAgreements,
bool noUpgrade) =>
new()
{
Query = query with
{
Channel = GetString(package, "Channel") ?? query.Channel,
InstallScope = GetString(package, "Scope") ?? query.InstallScope,
},
Mode = InstallerMode.SilentWithProgress,
Custom = GetString(package, "InitialCustomSwitches"),
Override = GetString(package, "InitialOverrideArguments"),
AcceptPackageAgreements = acceptPackageAgreements,
NoUpgrade = noUpgrade,
};

private static string? GetString(JsonElement element, string propertyName) =>
element.TryGetProperty(propertyName, out var value) && value.ValueKind == JsonValueKind.String
? value.GetString()
: null;
}
16 changes: 2 additions & 14 deletions dotnet/src/Devolutions.Pinget.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1165,28 +1165,16 @@
try
{
Console.Write($"Installing {pkgId}...");
var result = repo.Install(CreateInstallRequest(
var result = repo.Install(ImportInstallRequestFactory.Create(
new PackageQuery
{
Id = pkgId,
Source = sourceName,
Exact = true,
Version = pkgVersion,
},
null,
InstallerMode.SilentWithProgress,
null,
null,
null,
null,
false,
false,
pkg,
acceptPackageAgreements,
false,
null,
false,
false,
null,
noUpgrade));
if (result.NoOp)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using System.Text.Json;
using Devolutions.Pinget.Cli;
using Devolutions.Pinget.Core;
using Xunit;

namespace Devolutions.Pinget.Core.Tests;

public class ImportInstallRequestTests
{
[Fact]
public void ImportCustomSwitchesReachInstallerDispatch()
{
using var document = JsonDocument.Parse("""{"InitialCustomSwitches":"/custom-from-import"}""");
var request = ImportInstallRequestFactory.Create(
new PackageQuery { Id = "Test.Package", Exact = true },
document.RootElement,
acceptPackageAgreements: false,
noUpgrade: false);

var args = InstallerDispatch.BuildArguments(
"exe",
request,
new Manifest { Id = "Test.Package", Name = "Test", Version = "1.0" },
new Installer { InstallerType = "exe" });

Assert.Contains("/custom-from-import", args);
}

[Fact]
public void ImportOverrideArgumentsReachInstallerDispatch()
{
using var document = JsonDocument.Parse("""{"InitialOverrideArguments":"/override-from-import /quiet"}""");
var request = ImportInstallRequestFactory.Create(
new PackageQuery { Id = "Test.Package", Exact = true },
document.RootElement,
acceptPackageAgreements: false,
noUpgrade: false);

var args = InstallerDispatch.BuildArguments(
"exe",
request,
new Manifest { Id = "Test.Package", Name = "Test", Version = "1.0" },
new Installer { InstallerType = "exe" });

Assert.Equal(["/override-from-import", "/quiet"], args);
}

[Fact]
public void ImportScopeAndChannelReachPackageSelection()
{
using var document = JsonDocument.Parse("""{"Scope":"machine","Channel":"preview"}""");
var request = ImportInstallRequestFactory.Create(
new PackageQuery { Id = "Test.Package", Exact = true },
document.RootElement,
acceptPackageAgreements: false,
noUpgrade: false);

Assert.Equal("machine", request.Query.InstallScope);
Assert.Equal("preview", request.Query.Channel);
}

[Fact]
public void ImportWithoutOptionsKeepsExistingInstallRequestDefaults()
{
using var document = JsonDocument.Parse("""{"PackageIdentifier":"Test.Package"}""");
var request = ImportInstallRequestFactory.Create(
new PackageQuery { Id = "Test.Package", Exact = true },
document.RootElement,
acceptPackageAgreements: false,
noUpgrade: false);

Assert.Equal(InstallerMode.SilentWithProgress, request.Mode);
Assert.Null(request.Custom);
Assert.Null(request.Override);
Assert.False(request.AcceptPackageAgreements);
Assert.False(request.NoUpgrade);

var manifest = new Manifest { Id = "Test.Package", Name = "Test", Version = "1.0" };
var installer = new Installer { InstallerType = "exe" };
var importedArgs = InstallerDispatch.BuildArguments("exe", request, manifest, installer);
var defaultArgs = InstallerDispatch.BuildArguments(
"exe",
new InstallRequest { Query = request.Query, Mode = InstallerMode.SilentWithProgress },
manifest,
installer);

Assert.Equal(defaultArgs, importedArgs);
}
}
68 changes: 64 additions & 4 deletions rust/crates/pinget-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2564,8 +2564,9 @@ fn do_import(
exact: true,
..Default::default()
};
let request = create_import_install_request(query, package, accept_package_agreements, no_upgrade);

match repository.search(&query) {
match repository.search(&request.query) {
Ok(result) if !result.matches.is_empty() => {
let m = &result.matches[0];
if dry_run {
Expand All @@ -2582,9 +2583,6 @@ fn do_import(
m.version.as_deref().unwrap_or("?"),
source_name
);
let mut request = InstallRequest::new(query.clone());
request.accept_package_agreements = accept_package_agreements;
request.no_upgrade = no_upgrade;
match repository.install_request(&request) {
Ok(r) if r.no_op => {
println!(" NO-OP");
Expand Down Expand Up @@ -2628,6 +2626,34 @@ fn do_import(
Ok(())
}

fn create_import_install_request(
query: PackageQuery,
package: &serde_json::Value,
accept_package_agreements: bool,
no_upgrade: bool,
) -> InstallRequest {
let mut request = InstallRequest::new(query);
request.query.channel = package
.get("Channel")
.and_then(serde_json::Value::as_str)
.map(str::to_owned);
request.query.install_scope = package
.get("Scope")
.and_then(serde_json::Value::as_str)
.map(str::to_owned);
request.custom = package
.get("InitialCustomSwitches")
.and_then(serde_json::Value::as_str)
.map(str::to_owned);
request.override_args = package
.get("InitialOverrideArguments")
.and_then(serde_json::Value::as_str)
.map(str::to_owned);
request.accept_package_agreements = accept_package_agreements;
request.no_upgrade = no_upgrade;
request
}

fn can_ignore_unavailable_import_failure(error: &anyhow::Error) -> bool {
let message = error.to_string().to_ascii_lowercase();
message.contains("no package matched") || message.contains("no applicable installer found")
Expand Down Expand Up @@ -2667,6 +2693,40 @@ mod tests {
assert!(!parse_boolean_setting_value("0").expect("bool"));
}

#[test]
fn import_install_request_preserves_custom_switches_and_override_arguments() {
let package = serde_json::json!({
"InitialCustomSwitches": "/custom-switch",
"InitialOverrideArguments": "/override-arguments",
"Channel": "preview",
"Scope": "machine"
});
let request = create_import_install_request(PackageQuery::default(), &package, true, true);

assert_eq!(request.custom.as_deref(), Some("/custom-switch"));
assert_eq!(request.override_args.as_deref(), Some("/override-arguments"));
assert_eq!(request.query.channel.as_deref(), Some("preview"));
assert_eq!(request.query.install_scope.as_deref(), Some("machine"));
assert!(request.accept_package_agreements);
assert!(request.no_upgrade);
}

#[test]
fn import_install_request_without_options_keeps_default_install_behavior() {
let request = create_import_install_request(
PackageQuery::default(),
&serde_json::json!({ "PackageIdentifier": "Test.Package" }),
false,
false,
);

assert_eq!(request.mode, InstallerMode::SilentWithProgress);
assert!(request.custom.is_none());
assert!(request.override_args.is_none());
assert!(!request.accept_package_agreements);
assert!(!request.no_upgrade);
}

#[test]
fn serialize_json_pretty_preserves_pascal_case_list_fields() {
let response = ListResponse {
Expand Down
Loading