Files
FSI.BT.IR.Tools/RoboSharp/Results/RoboCopyResultsStatus.cs
Maier Stephan SI d01747f75a Sicherung
2023-01-02 04:33:49 +01:00

246 lines
9.8 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using RoboSharp.Interfaces;
namespace RoboSharp.Results
{
/// <summary>
/// Object that evaluates the ExitCode reported after RoboCopy finishes executing.
/// </summary>
/// <remarks>
/// <see href="https://github.com/tjscience/RoboSharp/wiki/RoboCopyExitStatus"/>
/// </remarks>
public class RoboCopyExitStatus
{
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Object"/> class.
/// </summary>
public RoboCopyExitStatus(int exitCodeValue)
{
ExitCodeValue = exitCodeValue;
}
/// <summary>ExitCode as reported by RoboCopy</summary>
public int ExitCodeValue { get; protected set; }
/// <summary>ExitCode reported by RoboCopy converted into the Enum</summary>
public RoboCopyExitCodes ExitCode => (RoboCopyExitCodes)ExitCodeValue;
/// <inheritdoc cref="RoboCopyExitCodes.FilesCopiedSuccessful"/>
public bool Successful => !WasCancelled && ExitCodeValue < 0x10;
/// <inheritdoc cref="RoboCopyExitCodes.MismatchedDirectoriesDetected"/>
public bool HasWarnings => ExitCodeValue >= 0x4;
/// <inheritdoc cref="RoboCopyExitCodes.SeriousErrorOccurred"/>
public bool HasErrors => ExitCodeValue >= 0x10;
/// <inheritdoc cref="RoboCopyExitCodes.Cancelled"/>
public virtual bool WasCancelled => ExitCodeValue < 0x0;
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
public override string ToString()
{
return $"ExitCode: {ExitCodeValue} ({ExitCode})";
}
}
/// <summary>
/// Represents the combination of multiple Exit Statuses
/// </summary>
public sealed class RoboCopyCombinedExitStatus : RoboCopyExitStatus, IRoboCopyCombinedExitStatus
{
#region < Constructor >
/// <summary>
/// Initializes a new instance of the <see cref="RoboCopyCombinedExitStatus"/> class.
/// </summary>
public RoboCopyCombinedExitStatus() : base(0) { }
/// <summary>
/// Initializes a new instance of the <see cref="RoboCopyCombinedExitStatus"/> class.
/// </summary>
public RoboCopyCombinedExitStatus(int exitCodeValue) : base(exitCodeValue) { }
/// <summary>
/// Clone this into a new instance
/// </summary>
/// <param name="obj"></param>
public RoboCopyCombinedExitStatus(RoboCopyCombinedExitStatus obj) :base((int)obj.ExitCode)
{
wascancelled = obj.wascancelled;
noCopyNoError = obj.noCopyNoError;
}
#endregion
#region < Fields and Event >
//Private bools for the Combine methods
private bool wascancelled;
private bool noCopyNoError;
private bool EnablePropertyChangeEvent = true;
/// <summary>This event when the ExitStatus summary has changed </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region < Public Properties >
/// <summary>Overides <see cref="RoboCopyExitStatus.WasCancelled"/></summary>
/// <returns> <see cref="AnyWasCancelled"/></returns>
public override bool WasCancelled => AnyWasCancelled;
/// <summary>
/// Atleast one <see cref="RoboCopyExitStatus"/> objects combined into this result resulted in no errors and no files/directories copied.
/// </summary>
public bool AnyNoCopyNoError => noCopyNoError || ExitCodeValue == 0x0;
/// <summary>
/// Atleast one <see cref="RoboCopyExitStatus"/> object combined into this result had been cancelled / exited prior to completion.
/// </summary>
public bool AnyWasCancelled => wascancelled || ExitCodeValue < 0x0;
/// <summary>
/// All jobs completed without errors or warnings.
/// </summary>
public bool AllSuccessful => !WasCancelled && (ExitCodeValue == 0x0 || ExitCodeValue == 0x1);
/// <summary>
/// All jobs completed without errors or warnings, but Extra Files/Folders were detected.
/// </summary>
public bool AllSuccessful_WithWarnings => !WasCancelled && Successful && ExitCodeValue > 0x1;
#endregion
#region < RaiseEvent Methods >
#if !NET40
[MethodImpl(methodImplOptions: MethodImplOptions.AggressiveInlining)]
#endif
private object[] StoreCurrentValues()
{
return new object[10]
{
WasCancelled, AnyNoCopyNoError, AnyWasCancelled, AllSuccessful, AllSuccessful_WithWarnings, HasErrors, HasWarnings, Successful, ExitCode, ExitCodeValue
};
}
#if !NET40
[MethodImpl(methodImplOptions: MethodImplOptions.AggressiveInlining)]
#endif
private void CompareAndRaiseEvents(object[] OriginalValues)
{
object[] CurrentValues = StoreCurrentValues();
if (CurrentValues[0] != OriginalValues[0]) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("WasCancelled"));
if (CurrentValues[1] != OriginalValues[1]) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("AnyNoCopyNoError"));
if (CurrentValues[2] != OriginalValues[2]) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("AnyWasCancelled"));
if (CurrentValues[3] != OriginalValues[3]) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("AllSuccessful"));
if (CurrentValues[4] != OriginalValues[4]) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("AllSuccessful_WithWarnings"));
if (CurrentValues[5] != OriginalValues[5]) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("HasErrors"));
if (CurrentValues[6] != OriginalValues[6]) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("HasWarnings"));
if (CurrentValues[7] != OriginalValues[7]) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Successful"));
if (CurrentValues[8] != OriginalValues[8]) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ExitCode"));
if (CurrentValues[9] != OriginalValues[9]) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ExitCodeValue"));
}
#endregion
/// <summary>
/// Combine the RoboCopyExitCodes of the supplied ExitStatus with this ExitStatus.
/// </summary>
/// <remarks>If any were Cancelled, set the WasCancelled property to TRUE. Otherwise combine the exit codes.</remarks>
/// <param name="status">ExitStatus to combine with</param>
#if !NET40
[MethodImpl(methodImplOptions: MethodImplOptions.AggressiveInlining)]
#endif
public void CombineStatus(RoboCopyExitStatus status)
{
if (status == null) return;
object[] OriginalValues = EnablePropertyChangeEvent ? StoreCurrentValues() : null;
//Combine the status
if (status.WasCancelled)
{
wascancelled = true;
}
else
{
if (status.ExitCode == 0x0) this.noCopyNoError = true; //0x0 is lost if any other values have been added, so this logs the state
RoboCopyExitCodes code = this.ExitCode | status.ExitCode;
this.ExitCodeValue = (int)code;
}
//Raise Property Change Events
if (EnablePropertyChangeEvent) CompareAndRaiseEvents(OriginalValues);
}
internal void CombineStatus(RoboCopyExitStatus status, bool enablePropertyChangeEvent)
{
EnablePropertyChangeEvent = enablePropertyChangeEvent;
CombineStatus(status);
EnablePropertyChangeEvent = enablePropertyChangeEvent;
}
/// <summary>
/// Combine all the RoboCopyExitStatuses together.
/// </summary>
/// <param name="status">Array or List of ExitStatuses to combine.</param>
public void CombineStatus(IEnumerable<RoboCopyExitStatus> status)
{
foreach (RoboCopyExitStatus s in status)
{
EnablePropertyChangeEvent = s == status.Last();
CombineStatus(s);
}
}
/// <summary>
/// Combine all the RoboCopyExitStatuses together.
/// </summary>
/// <param name="statuses">Array or List of ExitStatuses to combine.</param>
/// <returns> new RoboCopyExitStatus object </returns>
public static RoboCopyCombinedExitStatus CombineStatuses(IEnumerable<RoboCopyExitStatus> statuses)
{
RoboCopyCombinedExitStatus ret = new RoboCopyCombinedExitStatus(0);
ret.CombineStatus(statuses);
return ret;
}
/// <summary>
/// Reset the value of the object
/// </summary>
#if !NET40
[MethodImpl(methodImplOptions: MethodImplOptions.AggressiveInlining)]
#endif
public void Reset()
{
object[] OriginalValues = EnablePropertyChangeEvent ? StoreCurrentValues() : null;
this.wascancelled = false;
this.noCopyNoError = false;
this.ExitCodeValue = 0;
if (EnablePropertyChangeEvent) CompareAndRaiseEvents(OriginalValues);
}
/// <summary>
/// Reset the value of the object
/// </summary>
internal void Reset(bool enablePropertyChangeEvent)
{
EnablePropertyChangeEvent = enablePropertyChangeEvent;
Reset();
EnablePropertyChangeEvent = true;
}
/// <inheritdoc cref="ICloneable.Clone"/>
public RoboCopyCombinedExitStatus Clone() => new RoboCopyCombinedExitStatus(this);
object ICloneable.Clone() => Clone();
}
}