Example #1
0
        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();
 }
Example #3
0
 public override IList <ValidationResult> Execute(SchemaFile file)
 {
     return(Fragments
            .Where(ScalarExpressionIsNotPrefixed)
            .ToValidationResults());
 }
Example #4
0
        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)}"        );
        }
Example #5
0
 public override IList <ValidationResult> Execute(SchemaFile file)
 {
     return(Fragments
            .Where(x => CheckForStringLiteral(x) || CheckForBinaryExpression(x))
            .ToValidationResults());
 }
Example #6
0
 public override IList <ValidationResult> Execute(SchemaFile file)
 {
     return(Fragments
            .Where(SchemaIdentifierIsEmpty)
            .ToValidationResults());
 }