Skip to content

Commit

Permalink
Add new cmdlets and cancellation support for Microsoft.WinGet.Configu…
Browse files Browse the repository at this point in the history
…ration (#3614)

Test-WinGetConfiguration to test a configuration. Equivalent of winget configure test
Confirm-WinGetConfiguration to validate a configuration. Equivalent of winget configure validate except it just calls the configuration APIs without the extra validation winget does.
Support cancellation via CTRL-C for blocking cmdlets and Stop-WinGetConfiguration for configuration stated with Start-WinGetConfiguration
Add tests for Test-WinGetConfiguration and Confirm-WinGetConfiguration cmdlets.
Add more tests for Open-WinGetConfiguration
Cancellation verified manually
  • Loading branch information
msftrubengu authored and JohnMcPMS committed Sep 19, 2023
1 parent 157d768 commit c307ab6
Show file tree
Hide file tree
Showing 22 changed files with 902 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
namespace Microsoft.WinGet.Configuration.Cmdlets
{
using System.Management.Automation;
using System.Threading;
using Microsoft.WinGet.Configuration.Engine.Commands;
using Microsoft.WinGet.Configuration.Engine.PSObjects;

Expand All @@ -19,6 +18,8 @@ namespace Microsoft.WinGet.Configuration.Cmdlets
[Cmdlet(VerbsLifecycle.Complete, "WinGetConfiguration")]
public sealed class CompleteWinGetConfigurationCmdlet : PSCmdlet
{
private ConfigurationCommand runningCommand = null;

/// <summary>
/// Gets or sets the configuration task.
/// </summary>
Expand All @@ -34,8 +35,20 @@ public sealed class CompleteWinGetConfigurationCmdlet : PSCmdlet
/// </summary>
protected override void ProcessRecord()
{
var configCommand = new ConfigurationCommand(this);
configCommand.Continue(this.ConfigurationJob);
this.runningCommand = new ConfigurationCommand(this);
this.runningCommand.Continue(this.ConfigurationJob);
}

/// <summary>
/// Interrupts currently running code within the command.
/// </summary>
protected override void StopProcessing()
{
if (this.runningCommand != null)
{
this.runningCommand.Cancel(this.ConfigurationJob);
this.runningCommand.Cancel();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// -----------------------------------------------------------------------------
// <copyright file="ConfirmWinGetConfigurationCmdlet.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
// -----------------------------------------------------------------------------

namespace Microsoft.WinGet.Configuration.Cmdlets
{
using System.Management.Automation;
using Microsoft.WinGet.Configuration.Engine.Commands;
using Microsoft.WinGet.Configuration.Engine.PSObjects;

/// <summary>
/// Confirm-WinGetConfiguration
/// Validates winget configuration.
/// </summary>
[Cmdlet(VerbsLifecycle.Confirm, "WinGetConfiguration")]
public class ConfirmWinGetConfigurationCmdlet : PSCmdlet
{
private ConfigurationCommand runningCommand = null;

/// <summary>
/// Gets or sets the configuration set.
/// </summary>
[Parameter(
Position = 0,
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true)]
public PSConfigurationSet Set { get; set; }

/// <summary>
/// Validate configuration.
/// </summary>
protected override void ProcessRecord()
{
this.runningCommand = new ConfigurationCommand(this);
this.runningCommand.Validate(this.Set);
}

/// <summary>
/// Interrupts currently running code within the command.
/// </summary>
protected override void StopProcessing()
{
if (this.runningCommand != null)
{
this.runningCommand.Cancel();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ namespace Microsoft.WinGet.Configuration.Cmdlets
[Cmdlet(VerbsCommon.Get, "WinGetConfigurationDetails")]
public sealed class GetWinGetConfigurationDetailsCmdlet : PSCmdlet
{
private ConfigurationCommand runningCommand = null;

/// <summary>
/// Gets or sets the configuration set.
/// </summary>
Expand All @@ -33,8 +35,19 @@ public sealed class GetWinGetConfigurationDetailsCmdlet : PSCmdlet
/// </summary>
protected override void ProcessRecord()
{
var configCommand = new ConfigurationCommand(this);
configCommand.GetDetails(this.Set);
this.runningCommand = new ConfigurationCommand(this);
this.runningCommand.GetDetails(this.Set);
}

/// <summary>
/// Interrupts currently running code within the command.
/// </summary>
protected override void StopProcessing()
{
if (this.runningCommand != null)
{
this.runningCommand.Cancel();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

namespace Microsoft.WinGet.Configuration.Cmdlets
{
using System;
using System.Management.Automation;
using System.Threading;
using Microsoft.WinGet.Configuration.Engine.Commands;
using Microsoft.WinGet.Configuration.Engine.PSObjects;

Expand All @@ -20,6 +20,7 @@ namespace Microsoft.WinGet.Configuration.Cmdlets
public sealed class InvokeWinGetConfigurationCmdlet : PSCmdlet
{
private bool acceptedAgreements = false;
private ConfigurationCommand runningCommand = null;

/// <summary>
/// Gets or sets the configuration set.
Expand All @@ -42,7 +43,7 @@ public sealed class InvokeWinGetConfigurationCmdlet : PSCmdlet
/// </summary>
protected override void BeginProcessing()
{
this.acceptedAgreements = ConfigurationCommand.ConfirmConfigurationProcessing(this, this.AcceptConfigurationAgreements.ToBool());
this.acceptedAgreements = ConfigurationCommand.ConfirmConfigurationProcessing(this, this.AcceptConfigurationAgreements.ToBool(), true);
}

/// <summary>
Expand All @@ -52,8 +53,19 @@ protected override void ProcessRecord()
{
if (this.acceptedAgreements)
{
var configCommand = new ConfigurationCommand(this);
configCommand.Apply(this.Set);
this.runningCommand = new ConfigurationCommand(this);
this.runningCommand.Apply(this.Set);
}
}

/// <summary>
/// Interrupts currently running code within the command.
/// </summary>
protected override void StopProcessing()
{
if (this.runningCommand != null)
{
this.runningCommand.Cancel();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public sealed class StartWinGetConfigurationCmdlet : PSCmdlet
/// </summary>
protected override void BeginProcessing()
{
this.acceptedAgreements = ConfigurationCommand.ConfirmConfigurationProcessing(this, this.AcceptConfigurationAgreements.ToBool());
this.acceptedAgreements = ConfigurationCommand.ConfirmConfigurationProcessing(this, this.AcceptConfigurationAgreements.ToBool(), true);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// -----------------------------------------------------------------------------
// <copyright file="StopWinGetConfigurationCmdlet.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
// -----------------------------------------------------------------------------

namespace Microsoft.WinGet.Configuration.Cmdlets
{
using System.Management.Automation;
using Microsoft.WinGet.Configuration.Engine.Commands;
using Microsoft.WinGet.Configuration.Engine.PSObjects;

/// <summary>
/// Stop-WinGetConfiguration.
/// Cancels a configuration previously started by Start-WinGetConfiguration.
/// </summary>
[Cmdlet(VerbsLifecycle.Stop, "WinGetConfiguration")]
public sealed class StopWinGetConfigurationCmdlet : PSCmdlet
{
/// <summary>
/// Gets or sets the configuration task.
/// </summary>
[Parameter(
Position = 0,
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true)]
public PSConfigurationJob ConfigurationJob { get; set; }

/// <summary>
/// Starts to apply the configuration and wait for it to complete.
/// </summary>
protected override void ProcessRecord()
{
var configCommand = new ConfigurationCommand(this);
configCommand.Cancel(this.ConfigurationJob);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// -----------------------------------------------------------------------------
// <copyright file="TestWinGetConfigurationCmdlet.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
// -----------------------------------------------------------------------------

namespace Microsoft.WinGet.Configuration.Cmdlets
{
using System.Management.Automation;
using Microsoft.WinGet.Configuration.Engine.Commands;
using Microsoft.WinGet.Configuration.Engine.PSObjects;

/// <summary>
/// Test-WinGetConfiguration
/// Tests configuration.
/// </summary>
[Cmdlet(VerbsDiagnostic.Test, "WinGetConfiguration")]
public class TestWinGetConfigurationCmdlet : PSCmdlet
{
private bool acceptedAgreements = false;
private ConfigurationCommand runningCommand = null;

/// <summary>
/// Gets or sets the configuration set.
/// </summary>
[Parameter(
Position = 0,
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true)]
public PSConfigurationSet Set { get; set; }

/// <summary>
/// Gets or sets a value indicating whether to accept the configuration agreements.
/// </summary>
[Parameter(ValueFromPipelineByPropertyName = true)]
public SwitchParameter AcceptConfigurationAgreements { get; set; }

/// <summary>
/// Pre-processing operations.
/// </summary>
protected override void BeginProcessing()
{
this.acceptedAgreements = ConfigurationCommand.ConfirmConfigurationProcessing(this, this.AcceptConfigurationAgreements.ToBool(), false);
}

/// <summary>
/// Test configuration.
/// </summary>
protected override void ProcessRecord()
{
if (this.acceptedAgreements)
{
this.runningCommand = new ConfigurationCommand(this);
this.runningCommand.Test(this.Set);
}
}

/// <summary>
/// Interrupts currently running code within the command.
/// </summary>
protected override void StopProcessing()
{
if (this.runningCommand != null)
{
this.runningCommand.Cancel();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ public abstract class AsyncCommand
private readonly Thread originalThread;

private readonly CancellationTokenSource source = new ();

private CancellationToken cancellationToken;
private BlockingCollection<QueuedStream> queuedStreams = new ();

private int progressActivityId = 0;
Expand Down Expand Up @@ -73,7 +71,6 @@ public AsyncCommand(PSCmdlet psCmdlet)

this.PsCmdlet = psCmdlet;
this.originalThread = Thread.CurrentThread;
this.cancellationToken = this.source.Token;
}

/// <summary>
Expand Down Expand Up @@ -122,6 +119,14 @@ public enum StreamType
/// </summary>
protected PSCmdlet PsCmdlet { get; private set; }

/// <summary>
/// Request cancellation for this command.
/// </summary>
public void Cancel()
{
this.source.Cancel();
}

/// <summary>
/// Complete this operation.
/// </summary>
Expand Down Expand Up @@ -378,6 +383,15 @@ internal int GetNewProgressActivityId()
return Interlocked.Increment(ref this.progressActivityId);
}

/// <summary>
/// Gets the cancellation token.
/// </summary>
/// <returns>CancellationToken.</returns>
protected CancellationToken GetCancellationToken()
{
return this.source.Token;
}

private void CmdletWrite(StreamType streamType, object data, AsyncCommand writeCommand)
{
switch (streamType)
Expand Down
Loading

0 comments on commit c307ab6

Please sign in to comment.