public void Build() { Console.WriteLine($"Generating {GetFilePath()}"); var deserializer = new DeserializerBuilder().Build(); var serializer = new SerializerBuilder().Build(); var fragmentsNotFound = new HashSet <FragmentName>(); var requiredFragments = new HashSet <FragmentName>(); var recommendedFragments = new HashSet <FragmentName>(); var processedFragments = new HashSet <FragmentName>(); var unprocessedFragments = new HashSet <FragmentName>(); var services = new List <KeyValuePair <YamlNode, YamlNode> >(); var volumes = new List <KeyValuePair <YamlNode, YamlNode> >(); var networks = new List <KeyValuePair <YamlNode, YamlNode> >(); var exclusives = new List <(FragmentName FragmentName, string Exclusivity)>(); var incompatibles = new List <(FragmentName FragmentName, string Exclusivity)>(); foreach (var fragment in Fragments.Where(NotExcluded)) { unprocessedFragments.Add(fragment); } reprocessFragments: foreach (var fragment in unprocessedFragments.ToList()) { var fragmentPath = GetFragmentLocation(fragment); if (!File.Exists(fragmentPath)) { fragmentsNotFound.Add(fragment); unprocessedFragments.Remove(fragment); } } foreach (var o in unprocessedFragments.Select(f => (f, ParseDocument(f))).ToList()) { var doc = o.Item2; var fragment = o.f; if (doc.Children.ContainsKey("services") && doc.Children["services"] is YamlMappingNode fragmentServicesRoot) { services.AddRange(fragmentServicesRoot.Children); } if (doc.Children.ContainsKey("volumes") && doc.Children["volumes"] is YamlMappingNode fragmentVolumesRoot) { volumes.AddRange(fragmentVolumesRoot.Children); } if (doc.Children.ContainsKey("networks") && doc.Children["networks"] is YamlMappingNode fragmentNetworksRoot) { networks.AddRange(fragmentNetworksRoot.Children); } if (doc.Children.ContainsKey("exclusive") && doc.Children["exclusive"] is YamlSequenceNode fragmentExclusiveRoot) { foreach (var node in fragmentExclusiveRoot) { exclusives.Add((fragment, node.ToString())); } } if (doc.Children.ContainsKey("incompatible") && doc.Children["incompatible"] is YamlSequenceNode fragmentIncompatibleRoot) { foreach (var node in fragmentIncompatibleRoot) { incompatibles.Add((fragment, node.ToString())); } } if (doc.Children.ContainsKey("required") && doc.Children["required"] is YamlSequenceNode fragmentRequireRoot) { foreach (var node in fragmentRequireRoot) { if (ExcludeFragments.Contains(new FragmentName(node.ToString()))) { throw new YamlBuildException($"You excluded fragment {new FragmentName(node.ToString())} but it is required by {fragment}"); } requiredFragments.Add(new FragmentName(node.ToString())); } } if (doc.Children.ContainsKey("recommended") && doc.Children["recommended"] is YamlSequenceNode fragmentRecommendedRoot) { foreach (var node in fragmentRecommendedRoot) { if (!ExcludeFragments.Contains(new FragmentName(node.ToString()))) { recommendedFragments.Add(new FragmentName(node.ToString())); } } } processedFragments.Add(fragment); unprocessedFragments.Remove(fragment); } foreach (var fragment in requiredFragments.Concat(recommendedFragments).Where(f => !processedFragments.Contains(f))) { unprocessedFragments.Add(fragment); } if (unprocessedFragments.Count != 0) { goto reprocessFragments; } var exclusiveConflict = exclusives.GroupBy(e => e.Exclusivity) .Where(e => e.Count() != 1) .FirstOrDefault(); if (exclusiveConflict != null) { throw new YamlBuildException($"The fragments {String.Join(", ", exclusiveConflict.Select(e => e.FragmentName))} can't be used simultaneously (group '{exclusiveConflict.Key}')"); } var groups = exclusives.ToDictionary(e => e.Exclusivity, e => e.FragmentName); var incompatible = incompatibles .Select(i => groups.TryGetValue(i.Exclusivity, out _) ? (i.FragmentName, i.Exclusivity) : (null, null)) .Where(i => i.Exclusivity != null) .FirstOrDefault(); if (incompatible.Exclusivity != null) { throw new YamlBuildException($"The fragment {incompatible.FragmentName} is incompatible with '{incompatible.Exclusivity}'"); } Console.WriteLine($"Selected fragments:"); foreach (var fragment in processedFragments) { Console.WriteLine($"\t{fragment}"); } foreach (var fragment in fragmentsNotFound) { var fragmentPath = GetFragmentLocation(fragment); ConsoleUtils.WriteLine($"\t{fragment} not found in {fragmentPath}, ignoring...", ConsoleColor.Yellow); } YamlMappingNode output = new YamlMappingNode(); output.Add("version", new YamlScalarNode("3") { Style = YamlDotNet.Core.ScalarStyle.DoubleQuoted }); output.Add("services", new YamlMappingNode(Merge(services))); output.Add("volumes", new YamlMappingNode(volumes)); output.Add("networks", new YamlMappingNode(networks)); PostProcess(output); var dockerImages = ((YamlMappingNode)output["services"]).Children.Select(kv => kv.Value["image"].ToString()).ToList(); dockerImages.Add("btcpayserver/docker-compose-builder:1.24.1"); dockerImages.Add("btcpayserver/docker-compose-generator:latest"); StringBuilder pullImageSh = new StringBuilder(); pullImageSh.Append($"#!/bin/bash\n\n"); pullImageSh.Append($"# This script is automatically generated via the docker-compose generator and can be use to pull all required docker images \n"); foreach (var image in dockerImages) { pullImageSh.Append($"docker pull $BTCPAY_DOCKER_PULL_FLAGS \"{image}\"\n"); } var outputFile = GetFilePath("pull-images.sh"); File.WriteAllText(outputFile, pullImageSh.ToString()); Console.WriteLine($"Generated {outputFile}"); StringBuilder saveImages = new StringBuilder(); saveImages.Append($"#!/bin/bash\n\n"); saveImages.Append($"# This script is automatically generated via the docker-compose generator and can be use to save the docker images in an archive \n"); saveImages.Append($"# ./save-images.sh output.tar \n"); saveImages.Append($"docker save -o \"$1\" \\\n {string.Join(" \\\n", dockerImages.Select(o => $"\"{o}\""))}"); outputFile = GetFilePath("save-images.sh"); File.WriteAllText(outputFile, saveImages.ToString()); Console.WriteLine($"Generated {outputFile}"); var result = serializer.Serialize(output); outputFile = GetFilePath(); File.WriteAllText(outputFile, result.Replace("''", "")); Console.WriteLine($"Generated {outputFile}"); Console.WriteLine(); }
private void SetNumbers() { numbers = Fragments.Where(f => f.Number.HasValue).Select(f => f.Number.Value).ToArray(); }
public override IList <ValidationResult> Execute(SchemaFile file) { return(Fragments .Where(ScalarExpressionIsNotPrefixed) .ToValidationResults()); }
private string GenerateMatch(MatcherEngineGenerator generator) { return($@" public override MatcherResult Match(string code, string fragmentMatcher, bool matchFullText = true) {{ FragmentMatchData matchData = new FragmentMatchData {{ StartIndex = 0 }}; {(IndexingMode == IndexingMode.Lazy ? $"Span<int> checkFlags = stackalloc int[{Patterns.Count + 1}];" : null)} State state = new State() {{ Code = code{(IndexingMode != IndexingMode.None ? @", DistinctStringMatches = new List<StringMatchData>(2000)" : null)}{(IndexingMode == IndexingMode.Lazy ? @", CheckFlags = checkFlags" : null)}{(Fragments.Any(fragment => fragment.Cacheable) ? @", MatchCache = new Dictionary<ValueTuple<string, int>, FragmentMatchData>()" : null)}{(LogMatches ? $@", MatchLogBuilder = new StringBuilder()" : null)} }}; {(IndexingMode == IndexingMode.Eager ? "PreMatchPatterns(ref state);" : null)} bool success = false; switch (fragmentMatcher) {{ {string.Join("\n", Fragments.Where(matcher => !matcher.FallThrough && !matcher.IsNoise).Select(matcher => $@" case ""{HttpUtility.JavaScriptStringEncode(matcher.Name)}"": success = {matcher.Generate(generator)}; break; "))} }} IMatchData resultMatchData = matchData.Parts.FirstOrDefault(); int? failureIndex = success ? null : state.FailureIndex; if (success && matchFullText && state.CurrentIndex != state.Code.Length) {{ success = false; failureIndex = state.CurrentIndex; }} return new MatcherResult(resultMatchData, success, state.CurrentIndex, failureIndex, state.MatchLogBuilder?.ToString()); }} public override MatcherResult Match(string code, bool matchFullText = true) {{ FragmentMatchData matchData = new FragmentMatchData {{ StartIndex = 0 }}; {(IndexingMode == IndexingMode.Lazy ? $"Span<int> checkFlags = stackalloc int[{Patterns.Count + 1}];" : null)} State state = new State() {{ Code = code{(IndexingMode != IndexingMode.None ? @", DistinctStringMatches = new List<StringMatchData>(2000)" : null)}{(IndexingMode == IndexingMode.Lazy ? @", CheckFlags = checkFlags" : null)}{(Fragments.Any(fragment => fragment.Cacheable) ? @", MatchCache = new Dictionary<ValueTuple<string, int>, FragmentMatchData>()" : null)}{(LogMatches ? $@", MatchLogBuilder = new StringBuilder()" : null)} }}; {(IndexingMode == IndexingMode.Eager ? "PreMatchPatterns(ref state);" : null)} bool success = {StartingFragment.Generate(generator)}; IMatchData resultMatchData = matchData?.Parts.FirstOrDefault(); int? failureIndex = success ? null : state.FailureIndex; if (success && matchFullText && state.CurrentIndex != state.Code.Length) {{ success = false; failureIndex = Math.Max(state.FailureIndex ?? 0, state.CurrentIndex); }} return new MatcherResult(resultMatchData, success, state.CurrentIndex, failureIndex, state.MatchLogBuilder?.ToString()); }} {(IndexingMode == IndexingMode.Eager ? $@"private bool PreMatchPatterns(ref State state) {{ int codeLength = state.Code.Length; bool success = true; bool previousNoise = false; StringMatchData matchData = null; int currentIndex = 0; while ((currentIndex = state.CurrentIndex) < codeLength) {{ success = {string.Join(" ||\n", Patterns.Select(pattern => $@"{string.Format(GenerateMatchPattern(generator, pattern), "matchData", "true", "false")}"))}; if (!success) {{ break; }} else {{ {(generator.LanguageMatcher.LogMatches ? $@"state.MatchLogBuilder.AppendLine($""{{currentIndex}}. Prematched {{matchData.Name}}: {{matchData.Text}}"");" : null)} if (matchData.IsNoise) {{ previousNoise = true; }} else if (previousNoise) {{ if (state.DistinctIndex > 1) {{ StringMatchData previousMatchData = state.DistinctStringMatches[state.DistinctIndex - 2]; if (previousMatchData.Name == matchData.Name && previousMatchData.Mergable) {{ previousMatchData.Text += matchData.Text; previousMatchData.Length = state.CurrentIndex - previousMatchData.StartIndex; state.DistinctIndex--; state.MaxDistinctIndex--; state.DistinctStringMatches.RemoveAt(state.DistinctIndex); }} }} previousNoise = false; }} }} }} state.CurrentIndex = 0; {(IndexingMode != IndexingMode.None ? "state.DistinctIndex = 0;" : null)} return success; }}" : null)}" ); }
public override IList <ValidationResult> Execute(SchemaFile file) { return(Fragments .Where(x => CheckForStringLiteral(x) || CheckForBinaryExpression(x)) .ToValidationResults()); }
public override IList <ValidationResult> Execute(SchemaFile file) { return(Fragments .Where(SchemaIdentifierIsEmpty) .ToValidationResults()); }