/// <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);
    }
Example #3
0
        /// <summary>
        /// Logs an exception to the configured error store, or the in-memory default store if none is configured
        /// </summary>
        /// <param name="ex">The exception to log</param>
        /// <param name="context">The HTTPContext to record variables from.  If this isn't a web request, pass <see langword="null" /> in here</param>
        /// <param name="appendFullStackTrace">Whether to append a full stack trace to the exception's detail</param>
        /// <param name="rollupPerServer">Whether to log up per-server, e.g. errors are only duplicates if they have same stack on the same machine</param>
        /// <param name="customData">Any custom data to store with the exception like UserId, etc...this will be rendered as JSON in the error view for script use</param>
        /// <param name="applicationName">If specified, the application name to log with, if not specified the name in the config is used</param>
        /// <returns>The Error created, if one was created and logged, null if nothing was logged</returns>
        /// <remarks>
        /// When dealing with a non web requests, pass <see langword="null" /> in for context.
        /// It shouldn't be forgotten for most web application usages, so it's not an optional parameter.
        /// </remarks>
        public static Error LogException(Exception ex, HttpContext context, bool appendFullStackTrace = false, bool rollupPerServer = false, Dictionary <string, string> customData = null, string applicationName = null)
        {
            if (!_enableLogging)
            {
                return(null);
            }
            try
            {
                if (IgnoreRegexes.Any(re => re.IsMatch(ex.ToString())))
                {
                    return(null);
                }
                if (IgnoreExceptions.Any(type => IsDescendentOf(ex.GetType(), type.ToString())))
                {
                    return(null);
                }

                if (customData == null && GetCustomData != null)
                {
                    customData = new Dictionary <string, string>();
                    try
                    {
                        GetCustomData(ex, context, customData);
                    }
                    catch (Exception cde)
                    {
                        // if there was an error getting custom errors, log it so we can display such in the view...and not fail to log the original error
                        customData.Add(CustomDataErrorKey, cde.ToString());
                    }
                }

                var error = new Error(ex, context, applicationName)
                {
                    RollupPerServer = rollupPerServer,
                    CustomData      = customData ?? new Dictionary <string, string>()
                };

                if (GetIPAddress != null)
                {
                    try
                    {
                        error.IPAddress = GetIPAddress();
                    }
                    catch (Exception gipe)
                    {
                        // if there was an error getting the IP, log it so we can display such in the view...and not fail to log the original error
                        error.CustomData.Add(CustomDataErrorKey, "Fetching IP Adddress: " + gipe);
                    }
                }

                var exCursor = ex;
                while (exCursor != null)
                {
                    error.AddFromData(exCursor);
                    exCursor = exCursor.InnerException;
                }

                if (appendFullStackTrace)
                {
                    var frames = new StackTrace(fNeedFileInfo: true).GetFrames();
                    if (frames != null && frames.Length > 2)
                    {
                        error.Detail += "\n\nFull Trace:\n\n" + string.Join("", frames.Skip(2));
                    }
                    error.ErrorHash = error.GetHash();
                }

                if (OnBeforeLog != null)
                {
                    try
                    {
                        var args = new ErrorBeforeLogEventArgs(error);
                        OnBeforeLog(Default, args);
                        if (args.Abort)
                        {
                            return(null);            // if we've been told to abort, then abort dammit!
                        }
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine(e);
                    }
                }

                Trace.WriteLine(ex); // always echo the error to trace for local debugging
                Default.Log(error);

                if (OnAfterLog != null)
                {
                    try
                    {
                        OnAfterLog(Default, new ErrorAfterLogEventArgs(error));
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine(e);
                    }
                }
                return(error);
            }
            catch (Exception e)
            {
                Trace.WriteLine(e);
                return(null);
            }
        }
        /// <summary>
        /// Logs an exception to the configured error store, or the in-memory default store if none is configured
        /// </summary>
        /// <param name="ex">The exception to log</param>
        /// <param name="context">The HTTPContext to record variables from.  If this isn't a web request, pass <see langword="null" /> in here</param>
        /// <param name="appendFullStackTrace">Wehther to append a full stack trace to the exception's detail</param>
        /// <param name="rollupPerServer">Whether to log up per-server, e.g. errors are only duplicates if they have same stack on the same machine</param>
        /// <param name="customData">Any custom data to store with the exception like UserId, etc...this will be rendered as JSON in the error view for script use</param>
        /// <remarks>
        /// When dealing with a non web requests, pass <see langword="null" /> in for context.
        /// It shouldn't be forgotten for most web application usages, so it's not an optional parameter.
        /// </remarks>
        public static void LogException(Exception ex, HttpContext context, bool appendFullStackTrace = false, bool rollupPerServer = false, Dictionary <string, string> customData = null)
        {
            if (!_enableLogging)
            {
                return;
            }
            try
            {
                if (IgnoreRegexes.Any(re => re.IsMatch(ex.ToString())))
                {
                    return;
                }
                if (IgnoreExceptions.Any(type => IsDescendentOf(ex.GetType(), type.ToString())))
                {
                    return;
                }

                if (customData == null && GetCustomData != null)
                {
                    customData = new Dictionary <string, string>();
                    try
                    {
                        GetCustomData(ex, context, customData);
                    }
                    catch (Exception cde)
                    {
                        // if there was an error getting custom errors, log it so we can display such in the view...and not fail to log the original error
                        customData.Add(CustomDataErrorKey, cde.ToString());
                    }
                }

                var error = new Error(ex, context)
                {
                    RollupPerServer = rollupPerServer,
                    CustomData      = customData
                };

                var exCursor = ex;
                while (exCursor != null)
                {
                    if (exCursor.Data.Contains("SQL"))
                    {
                        error.SQL = exCursor.Data["SQL"] as string;
                    }
                    exCursor = exCursor.InnerException;
                }

                if (appendFullStackTrace)
                {
                    var frames = new StackTrace(fNeedFileInfo: true).GetFrames();
                    if (frames != null)
                    {
                        error.Detail += "\n\nFull Trace:\n\n" + string.Join("", frames.Skip(2));
                    }
                }

                Trace.WriteLine(ex); // always echo the error to trace for local debugging
                Default.Log(error);
            }
            catch (Exception e)
            {
                Trace.WriteLine(e);
            }
        }
 /// <summary>
 /// Adds a regular expression for ignoring files.
 /// </summary>
 public void AddIgnoreRegex() => IgnoreRegexes.Add("New Ignore Regex");