public static void RunForFilePath([CallerFilePath] string sourceFilePath = "")
        {
            Guard.FileExists(sourceFilePath, nameof(sourceFilePath));
            var root = GitRepoDirectoryFinder.FindForFilePath(sourceFilePath);

            new DirectoryMarkdownProcessor(root).Run();
        }
        public override bool Execute()
        {
            var stopwatch = Stopwatch.StartNew();
            var root      = GitRepoDirectoryFinder.FindForDirectory(ProjectDirectory);

            var(fileConfig, configFilePath) = ConfigReader.Read(root);

            var configResult = ConfigDefaults.Convert(
                fileConfig,
                new ConfigInput
            {
                ReadOnly              = ReadOnly,
                ValidateContent       = ValidateContent,
                WriteHeader           = WriteHeader,
                Header                = Header,
                UrlPrefix             = UrlPrefix,
                LinkFormat            = LinkFormat,
                Convention            = Convention,
                Exclude               = Exclude,
                TocExcludes           = TocExcludes,
                TocLevel              = TocLevel,
                MaxWidth              = MaxWidth,
                UrlsAsSnippets        = UrlsAsSnippets,
                DocumentExtensions    = DocumentExtensions,
                TreatMissingAsWarning = TreatMissingAsWarning,
                HashSnippetAnchors    = HashSnippetAnchors,
            });

            var message = LogBuilder.BuildConfigLogMessage(root, configResult, configFilePath);

            Log.LogMessage(message);

            var processor = new DirectoryMarkdownProcessor(
                root,
                log: s => Log.LogMessage(s),
                readOnly: configResult.ReadOnly,
                directoryFilter: ExcludeToFilterBuilder.ExcludesToFilter(configResult.Exclude),
                writeHeader: configResult.WriteHeader,
                header: configResult.Header,
                urlPrefix: configResult.UrlPrefix,
                linkFormat: configResult.LinkFormat,
                convention: configResult.Convention,
                tocLevel: configResult.TocLevel,
                tocExcludes: configResult.TocExcludes,
                documentExtensions: configResult.DocumentExtensions,
                treatMissingAsWarning: configResult.TreatMissingAsWarning,
                maxWidth: configResult.MaxWidth,
                validateContent: configResult.ValidateContent,
                hashSnippetAnchors: configResult.HashSnippetAnchors);

            var snippets = new List <Snippet>();

            try
            {
                snippets.AppendUrlsAsSnippets(configResult.UrlsAsSnippets).GetAwaiter().GetResult();
                processor.AddSnippets(snippets);
                var snippetsInError = processor.Snippets.Where(x => x.IsInError).ToList();
                if (snippetsInError.Any())
                {
                    foreach (var snippet in snippetsInError)
                    {
                        Log.LogFileError($"Snippet error: {snippet.Error}. Key: {snippet.Key}", snippet.Path, snippet.StartLine, 0);
                    }

                    return(false);
                }

                processor.Run();
                return(true);
            }
            catch (MissingSnippetsException exception)
            {
                foreach (var missing in exception.Missing)
                {
                    if (configResult.TreatMissingAsWarning)
                    {
                        Log.LogWarning($"MarkdownSnippets: Missing snippet: {missing.Key}", missing.File, missing.LineNumber, 0);
                    }
                    else
                    {
                        Log.LogFileError($"MarkdownSnippets: Missing snippet: {missing.Key}", missing.File, missing.LineNumber, 0);
                    }
                }

                return(configResult.TreatMissingAsWarning);
            }
            catch (MissingIncludesException exception)
            {
                foreach (var missing in exception.Missing)
                {
                    if (configResult.TreatMissingAsWarning)
                    {
                        Log.LogWarning($"MarkdownSnippets: Missing include: {missing.Key}", missing.File, missing.LineNumber);
                    }
                    else
                    {
                        Log.LogFileError($"MarkdownSnippets: Missing include: {missing.Key}", missing.File, missing.LineNumber, 0);
                    }
                }

                return(configResult.TreatMissingAsWarning);
            }
            catch (ContentValidationException exception)
            {
                foreach (var error in exception.Errors)
                {
                    //TODO: add column
                    Log.LogFileError($"MarkdownSnippets: Content validation: {error.Error}", error.File, error.Line, error.Column);
                }

                return(configResult.TreatMissingAsWarning);
            }
            catch (MarkdownProcessingException exception)
            {
                Log.LogFileError($"MarkdownSnippets: {exception.Message}", exception.File, exception.LineNumber, 0);
                return(false);
            }
            catch (SnippetException exception)
            {
                Log.LogError($"MarkdownSnippets: {exception}");
                return(false);
            }
            finally
            {
                Log.LogMessageFromText($"Finished MarkdownSnippets {stopwatch.ElapsedMilliseconds}ms", MessageImportance.Normal);
            }
        }