/// <summary>
    /// Calculates all files that will be removed from the final archive and displays them to the user.
    /// </summary>
    public void ShowExcludedFiles()
    {
        var compiledIgnoreRegexes  = IgnoreRegexes.Select(x => new Regex(x, RegexOptions.Compiled));
        var compiledIncludeRegexes = IncludeRegexes.Select(x => new Regex(x, RegexOptions.Compiled));

        var allFiles     = Directory.GetFiles(GetModFolder(), "*.*", SearchOption.AllDirectories).Select(x => Paths.GetRelativePath(x, GetModFolder()));
        var ignoredFiles = allFiles.Where(path => path.TryMatchAnyRegex(compiledIgnoreRegexes) && !path.TryMatchAnyRegex(compiledIncludeRegexes)).ToHashSet();

        Actions.DisplayMessagebox.Invoke(Resources.PublishModRegexDialogTitle.Get(), string.Join('\n', ignoredFiles));
    }
    /// <summary>
    /// Builds a new release.
    /// </summary>
    /// <param name="cancellationToken">Used to cancel the current build.</param>
    /// <returns>True if a build has started and the operation completed, else false.</returns>
    public async Task <bool> BuildAsync(CancellationToken cancellationToken = default)
    {
        // Check if Auto Delta can be performed.
        if (AutomaticDelta && !Singleton <ReleaseMetadata> .Instance.CanReadFromDirectory(OutputFolder, null, out _, out _))
        {
            var description = string.Format(Resources.PublishAutoDeltaWarningDescriptionFormat.Get(), Singleton <ReleaseMetadata> .Instance.GetDefaultFileName());
            Actions.DisplayMessagebox(Resources.PublishAutoDeltaWarningTitle.Get(), description);
            return(false);
        }

        // Perform Build
        CanBuild = false;
        try
        {
            await Task.Run(async() =>
            {
                await PublishAsync(new PublishArgs()
                {
                    PublishTarget       = PublishTarget,
                    OutputFolder        = OutputFolder,
                    ModTuple            = _modTuple,
                    IgnoreRegexes       = IgnoreRegexes.Select(x => x.Value).ToList(),
                    IncludeRegexes      = IncludeRegexes.Select(x => x.Value).ToList(),
                    Progress            = new Progress <double>(d => BuildProgress = d * 100),
                    AutomaticDelta      = AutomaticDelta,
                    CompressionLevel    = CompressionLevel,
                    CompressionMethod   = CompressionMethod,
                    OlderVersionFolders = OlderVersionFolders.Select(x => x.Value).ToList(),
                    PackageName         = PackageName,
                    MetadataFileName    = _modTuple.Config.ReleaseMetadataFileName,
                    ChangelogPath       = ChangelogPath,
                    ReadmePath          = ReadmePath
                });
            });

            ProcessExtensions.OpenFileWithExplorer(OutputFolder);
        }
        catch (Exception ex)
        {
            Errors.HandleException(ex);
            return(false);
        }
        finally
        {
            CanBuild = true;
        }

        return(true);
    }
 /// <summary>
 /// Adds a regular expression for including files.
 /// </summary>
 public void AddIncludeRegex() => IncludeRegexes.Add("New Include Regex");