public DocumentBuilder( IEnumerable <Assembly> assemblies, ImmutableArray <string> postProcessorNames, string templateHash, string intermediateFolder = null, string commitFromSHA = null, string commitToSHA = null) { Logger.LogVerbose("Loading plug-in..."); using (new LoggerPhaseScope("ImportPlugins", true)) { var assemblyList = assemblies?.ToList(); _container = GetContainer(assemblyList); _container.SatisfyImports(this); _currentBuildInfo.CommitFromSHA = commitFromSHA; _currentBuildInfo.CommitToSHA = commitToSHA; if (intermediateFolder != null) { _currentBuildInfo.PluginHash = ComputePluginHash(assemblyList); _currentBuildInfo.TemplateHash = templateHash; _currentBuildInfo.DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder); } } Logger.LogInfo($"{Processors.Count()} plug-in(s) loaded."); foreach (var processor in Processors) { Logger.LogVerbose($"\t{processor.Name} with build steps ({string.Join(", ", from bs in processor.BuildSteps orderby bs.BuildOrder select bs.Name)})"); } _postProcessors = GetPostProcessor(postProcessorNames); _intermediateFolder = intermediateFolder; _lastBuildInfo = LoadLastBuildInfo(); }
public void TestIncrementalWithNullLastPostProcessInfo() { var intermediateFolder = GetRandomFolder(); var currentBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder) }; // Pass null as last build info var postProcessors = GetPostProcessors(typeof(AppendStringPostProcessor)); var increContext = new IncrementalPostProcessorsContext(intermediateFolder, currentBuildInfo, null, postProcessors, true); // Check context Assert.True(increContext.ShouldTraceIncrementalInfo); Assert.False(increContext.IsIncremental); var increPostProcessorHandler = new PostProcessorsHandlerWithIncremental(PostProcessorsHandler, increContext); var manifest = JsonUtility.Deserialize <Manifest>("PostProcessors/Data/manifest_incremental.json"); var outputFolder = GetRandomFolder(); PrepareOutput(outputFolder, "a", "b", "c"); increPostProcessorHandler.Handle(postProcessors, manifest, outputFolder); // Check incremental flag Assert.True(manifest.Files.All(f => f.IsIncremental == false)); // Check output content VerifyOutput(outputFolder, AppendStringPostProcessor.AppendString, "a", "b", "c"); // Check cached PostProcessInfo Assert.NotNull(currentBuildInfo.PostProcessInfo); var postProcessorInfos = currentBuildInfo.PostProcessInfo.PostProcessorInfos; Assert.Equal(1, currentBuildInfo.PostProcessInfo.PostProcessorInfos.Count); Assert.Equal($"{typeof(AppendStringPostProcessor).Name}", postProcessorInfos[0].Name); Assert.Null(postProcessorInfos[0].IncrementalContextHash); var postProcessOutputs = currentBuildInfo.PostProcessInfo.PostProcessOutputs; Assert.Equal(9, postProcessOutputs.Count); VerifyCachedOutput(Path.Combine(intermediateFolder, currentBuildInfo.DirectoryName), postProcessOutputs, AppendStringPostProcessor.AppendString, AppendStringPostProcessor.AdditionalExtensionString, "a", "b", "c"); Assert.Equal <ManifestItem>(manifest.Files, currentBuildInfo.PostProcessInfo.ManifestItems); // Check incremental info Assert.Equal(1, manifest.IncrementalInfo.Count); Assert.Equal(false, manifest.IncrementalInfo[0].Status.CanIncremental); Assert.Equal(IncrementalPhase.PostProcessing, manifest.IncrementalInfo[0].Status.IncrementalPhase); Assert.Equal("Cannot support incremental post processing, the reason is: last post processor info is null.", manifest.IncrementalInfo[0].Status.Details); }
public void TestIncrementalWithNotSupportIncrementalPostProcessor() { var intermediateFolder = GetRandomFolder(); var currentBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder) }; var lastBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder), PostProcessInfo = new PostProcessInfo() }; lastBuildInfo.PostProcessInfo.PostProcessorInfos.Add(new PostProcessorInfo { Name = typeof(NonIncrementalPostProcessor).Name }); // Add not post processor which not support incremental var postProcessors = GetPostProcessors(typeof(NonIncrementalPostProcessor)); var increContext = new IncrementalPostProcessorsContext(intermediateFolder, currentBuildInfo, lastBuildInfo, postProcessors, true); // Check context Assert.False(increContext.ShouldTraceIncrementalInfo); Assert.False(increContext.IsIncremental); var increPostProcessorHandler = new PostProcessorsHandlerWithIncremental(PostProcessorsHandler, increContext); var manifest = JsonUtility.Deserialize <Manifest>("PostProcessors/Data/manifest_incremental.json"); var outputFolder = GetRandomFolder(); PrepareOutput(outputFolder, "a", "b", "c"); increPostProcessorHandler.Handle(postProcessors, manifest, outputFolder); // Check incremental flag Assert.True(manifest.Files.All(f => f.IsIncremental == false)); // Check output content should append nothing VerifyOutput(outputFolder, string.Empty, "a", "b", "c"); // Check cached PostProcessInfo is null Assert.Null(currentBuildInfo.PostProcessInfo); // Check incremental info Assert.Equal(1, manifest.IncrementalInfo.Count); Assert.Equal(false, manifest.IncrementalInfo[0].Status.CanIncremental); Assert.Equal(IncrementalPhase.PostProcessing, manifest.IncrementalInfo[0].Status.IncrementalPhase); Assert.Equal("Cannot support incremental post processing, the reason is: should not trace intermediate info.", manifest.IncrementalInfo[0].Status.Details); }
public DocumentBuilder( IEnumerable <Assembly> assemblies, ImmutableArray <string> postProcessorNames, string templateHash, string intermediateFolder = null, string commitFromSHA = null, string commitToSHA = null) { Logger.LogVerbose("Loading plug-in..."); using (new LoggerPhaseScope("ImportPlugins", LogLevel.Verbose)) { var assemblyList = assemblies?.ToList() ?? new List <Assembly>(); assemblyList.Add(typeof(DocumentBuilder).Assembly); _container = CompositionUtility.GetContainer(assemblyList); _container.SatisfyImports(this); _currentBuildInfo.CommitFromSHA = commitFromSHA; _currentBuildInfo.CommitToSHA = commitToSHA; if (intermediateFolder != null) { _currentBuildInfo.PluginHash = ComputePluginHash(assemblyList); _currentBuildInfo.TemplateHash = templateHash; _currentBuildInfo.DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder); } } Logger.LogInfo($"{Processors.Count()} plug-in(s) loaded."); foreach (var processor in Processors) { Logger.LogVerbose($"\t{processor.Name} with build steps ({string.Join(", ", from bs in processor.BuildSteps orderby bs.BuildOrder select bs.Name)})"); } if (intermediateFolder != null) { var expanded = Environment.ExpandEnvironmentVariables(intermediateFolder); if (expanded.Length == 0) { expanded = "."; } _intermediateFolder = Path.GetFullPath(expanded); } _lastBuildInfo = BuildInfo.Load(_intermediateFolder); _postProcessorsManager = new PostProcessorsManager(_container, postProcessorNames); }
public void Build(IList <DocumentBuildParameters> parameters, string outputDirectory) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (parameters.Count == 0) { throw new ArgumentException("Parameters are empty.", nameof(parameters)); } var markdownServiceProvider = CompositionContainer.GetExport <IMarkdownServiceProvider>(_container, parameters[0].MarkdownEngineName); if (markdownServiceProvider == null) { Logger.LogError($"Unable to find markdown engine: {parameters[0].MarkdownEngineName}"); throw new DocfxException($"Unable to find markdown engine: {parameters[0].MarkdownEngineName}"); } Logger.LogInfo($"Markdown engine is {parameters[0].MarkdownEngineName}"); var logCodesLogListener = new LogCodesLogListener(); Logger.RegisterListener(logCodesLogListener); // Load schema driven processor from template var sdps = LoadSchemaDrivenDocumentProcessors(parameters[0]).ToList(); if (sdps.Count > 0) { Logger.LogInfo($"{sdps.Count()} schema driven document processor plug-in(s) loaded."); Processors = Processors.Union(sdps); } BuildInfo lastBuildInfo = null; var currentBuildInfo = new BuildInfo { BuildStartTime = DateTime.UtcNow, DocfxVersion = EnvironmentContext.Version, }; try { lastBuildInfo = BuildInfo.Load(_intermediateFolder, true); currentBuildInfo.CommitFromSHA = _commitFromSHA; currentBuildInfo.CommitToSHA = _commitToSHA; if (_intermediateFolder != null) { currentBuildInfo.PluginHash = ComputePluginHash(_assemblyList); currentBuildInfo.TemplateHash = _templateHash; if (!_cleanupCacheHistory && lastBuildInfo != null) { // Reuse the directory for last incremental if cleanup is disabled currentBuildInfo.DirectoryName = lastBuildInfo.DirectoryName; } else { currentBuildInfo.DirectoryName = IncrementalUtility.CreateRandomDirectory(Environment.ExpandEnvironmentVariables(_intermediateFolder)); } } _postProcessorsManager.IncrementalInitialize(_intermediateFolder, currentBuildInfo, lastBuildInfo, parameters[0].ForcePostProcess, parameters[0].MaxParallelism); var manifests = new List <Manifest>(); bool transformDocument = false; if (parameters.All(p => p.Files.Count == 0)) { Logger.LogWarning( $"No file found, nothing will be generated. Please make sure docfx.json is correctly configured.", code: WarningCodes.Build.EmptyInputFiles); } var noContentFound = true; var emptyContentGroups = new List <string>(); foreach (var parameter in parameters) { if (parameter.CustomLinkResolver != null) { if (_container.TryGetExport(parameter.CustomLinkResolver, out ICustomHrefGenerator chg)) { parameter.ApplyTemplateSettings.HrefGenerator = chg; } else { Logger.LogWarning($"Custom href generator({parameter.CustomLinkResolver}) is not found."); } } FileAbstractLayerBuilder falBuilder; if (_intermediateFolder == null) { falBuilder = FileAbstractLayerBuilder.Default .ReadFromRealFileSystem(EnvironmentContext.BaseDirectory) .WriteToRealFileSystem(parameter.OutputBaseDir); } else { falBuilder = FileAbstractLayerBuilder.Default .ReadFromRealFileSystem(EnvironmentContext.BaseDirectory) .WriteToLink(Path.Combine(_intermediateFolder, currentBuildInfo.DirectoryName)); } if (!string.IsNullOrEmpty(parameter.FALName)) { if (_container.TryGetExport <IInputFileAbstractLayerBuilderProvider>( parameter.FALName, out var provider)) { falBuilder = provider.Create(falBuilder, parameter); } else { Logger.LogWarning($"Input fal builder provider not found, name: {parameter.FALName}."); } } EnvironmentContext.FileAbstractLayerImpl = falBuilder.Create(); if (parameter.ApplyTemplateSettings.TransformDocument) { transformDocument = true; } if (parameter.Files.Count == 0) { manifests.Add(new Manifest()); } else { if (!parameter.Files.EnumerateFiles().Any(s => s.Type == DocumentType.Article)) { if (!string.IsNullOrEmpty(parameter.GroupInfo?.Name)) { emptyContentGroups.Add(parameter.GroupInfo.Name); } } else { noContentFound = false; } parameter.Metadata = _postProcessorsManager.PrepareMetadata(parameter.Metadata); if (!string.IsNullOrEmpty(parameter.VersionName)) { Logger.LogInfo($"Start building for version: {parameter.VersionName}"); } using (new LoggerPhaseScope("BuildCore")) { manifests.Add(BuildCore(parameter, markdownServiceProvider, currentBuildInfo, lastBuildInfo)); } } } if (noContentFound) { Logger.LogWarning( $"No content file found. Please make sure the content section of docfx.json is correctly configured.", code: WarningCodes.Build.EmptyInputContents); } else if (emptyContentGroups.Count > 0) { Logger.LogWarning( $"No content file found in group: {string.Join(",", emptyContentGroups)}. Please make sure the content section of docfx.json is correctly configured.", code: WarningCodes.Build.EmptyInputContents); } using (new LoggerPhaseScope("Postprocess", LogLevel.Verbose)) { var generatedManifest = ManifestUtility.MergeManifest(manifests); generatedManifest.SitemapOptions = parameters.FirstOrDefault()?.SitemapOptions; ManifestUtility.RemoveDuplicateOutputFiles(generatedManifest.Files); ManifestUtility.ApplyLogCodes(generatedManifest.Files, logCodesLogListener.Codes); EnvironmentContext.FileAbstractLayerImpl = FileAbstractLayerBuilder.Default .ReadFromManifest(generatedManifest, parameters[0].OutputBaseDir) .WriteToManifest(generatedManifest, parameters[0].OutputBaseDir) .Create(); using (new PerformanceScope("Process")) { _postProcessorsManager.Process(generatedManifest, outputDirectory); } using (new PerformanceScope("Dereference")) { if (parameters[0].KeepFileLink) { var count = (from f in generatedManifest.Files from o in f.OutputFiles select o.Value into v where v.LinkToPath != null select v).Count(); if (count > 0) { Logger.LogInfo($"Skip dereferencing {count} files."); } } else { generatedManifest.Dereference(parameters[0].OutputBaseDir, parameters[0].MaxParallelism); } } using (new PerformanceScope("SaveManifest")) { // Save to manifest.json EnvironmentContext.FileAbstractLayerImpl = FileAbstractLayerBuilder.Default .ReadFromRealFileSystem(parameters[0].OutputBaseDir) .WriteToRealFileSystem(parameters[0].OutputBaseDir) .Create(); SaveManifest(generatedManifest); } using (new PerformanceScope("Cleanup")) { EnvironmentContext.FileAbstractLayerImpl = null; // overwrite intermediate cache files if (_intermediateFolder != null && transformDocument) { try { currentBuildInfo.IsValid = Logger.WarningCount < Logger.WarningThrottling; currentBuildInfo.Save(_intermediateFolder); if (_cleanupCacheHistory) { ClearCacheExcept(currentBuildInfo.DirectoryName); } } catch (Exception ex) { Logger.LogWarning($"Error happened while saving cache. Message: {ex.Message}."); } } } } } catch { // Leave cache folder there as it contains historical data // exceptions happens in this build does not corrupt the cache theoretically // however the cache file created by this build will never be cleaned up with DisableIncrementalFolderCleanup option if (_intermediateFolder != null && _cleanupCacheHistory) { ClearCacheExcept(lastBuildInfo?.DirectoryName); } throw; } finally { Logger.UnregisterListener(logCodesLogListener); } }
public void TestIncrementalWithContextChange() { var intermediateFolder = GetRandomFolder(); var currentBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder) }; var lastBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder), PostProcessInfo = new PostProcessInfo() }; lastBuildInfo.PostProcessInfo.PostProcessorInfos.Add(new PostProcessorInfo { Name = typeof(AppendIntegerPostProcessor).Name }); // Add post processor which has changed context hash var postProcessors = GetPostProcessors(typeof(AppendIntegerPostProcessor)); var increContext = new IncrementalPostProcessorsContext(intermediateFolder, currentBuildInfo, lastBuildInfo, postProcessors, true); // Check context Assert.True(increContext.ShouldTraceIncrementalInfo); Assert.False(increContext.IsIncremental); var increPostProcessorHandler = new PostProcessorsHandlerWithIncremental(PostProcessorsHandler, increContext); var manifest = JsonUtility.Deserialize <Manifest>("PostProcessors/Data/manifest_incremental.json"); var outputFolder = GetRandomFolder(); PrepareOutput(outputFolder, "a", "b", "c"); increPostProcessorHandler.Handle(postProcessors, manifest, outputFolder); // Check incremental flag Assert.True(manifest.Files.All(f => f.IsIncremental == false)); // Check output content VerifyOutput(outputFolder, AppendIntegerPostProcessor.AppendInteger, "a", "b", "c"); // Check cached PostProcessInfo Assert.NotNull(currentBuildInfo.PostProcessInfo); var postProcessorInfos = currentBuildInfo.PostProcessInfo.PostProcessorInfos; Assert.Equal(1, currentBuildInfo.PostProcessInfo.PostProcessorInfos.Count); Assert.Equal($"{typeof(AppendIntegerPostProcessor).Name}", postProcessorInfos[0].Name); Assert.NotNull(postProcessorInfos[0].IncrementalContextHash); var postProcessOutputs = currentBuildInfo.PostProcessInfo.PostProcessOutputs; Assert.Equal(6, postProcessOutputs.Count); VerifyCachedOutput(Path.Combine(intermediateFolder, currentBuildInfo.DirectoryName), postProcessOutputs, AppendIntegerPostProcessor.AppendInteger, null, "a", "b", "c"); Assert.Equal <ManifestItem>(manifest.Files, currentBuildInfo.PostProcessInfo.ManifestItems); // Check incremental info Assert.Equal(1, manifest.IncrementalInfo.Count); Assert.Equal(false, manifest.IncrementalInfo[0].Status.CanIncremental); Assert.Equal(IncrementalPhase.PostProcessing, manifest.IncrementalInfo[0].Status.IncrementalPhase); Assert.Equal(@"Cannot support incremental post processing, the reason is: post processor info changed from last {""Name"":""AppendIntegerPostProcessor""} to current {""Name"":""AppendIntegerPostProcessor"",""IncrementalContextHash"":""1024""}.", manifest.IncrementalInfo[0].Status.Details); }
public void TestIncrementalWithFileInDirectory() { var intermediateFolder = GetRandomFolder(); var currentBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder) }; var lastBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder), PostProcessInfo = new PostProcessInfo() }; lastBuildInfo.PostProcessInfo.PostProcessorInfos.Add(new PostProcessorInfo { Name = typeof(AppendStringPostProcessor).Name }); // Exclude c, which is not incremental var preparedManifest = JsonUtility.Deserialize <Manifest>("PostProcessors/Data/manifest_incremental_with_directory.json"); PrepareCachedOutput(intermediateFolder, lastBuildInfo, AppendStringPostProcessor.AppendString, preparedManifest.Files, AppendStringPostProcessor.AdditionalExtensionString, "a/b"); var postProcessors = GetPostProcessors(typeof(AppendStringPostProcessor)); var increContext = new IncrementalPostProcessorsContext(intermediateFolder, currentBuildInfo, lastBuildInfo, postProcessors, true); // Check context Assert.True(increContext.ShouldTraceIncrementalInfo); Assert.True(increContext.IsIncremental); var increPostProcessorHandler = new PostProcessorsHandlerWithIncremental(PostProcessorsHandler, increContext); var manifest = JsonUtility.Deserialize <Manifest>("PostProcessors/Data/manifest_incremental_with_directory.json"); var outputFolder = GetRandomFolder(); PrepareOutput(outputFolder, "a/b", "c"); CreateFile("breadcrumb.json", "breadcrumb", outputFolder); increPostProcessorHandler.Handle(postProcessors, manifest, outputFolder); // Check incremental flag Assert.Equal(3, manifest.Files.Count); Assert.True(manifest.Files.Single(i => i.SourceRelativePath == "a/b.md").IsIncremental); Assert.False(manifest.Files.Single(i => i.SourceRelativePath == "c.md").IsIncremental); Assert.False(manifest.Files.Single(i => i.SourceRelativePath == "breadcrumb.json").IsIncremental); // Check output content VerifyOutput(outputFolder, AppendStringPostProcessor.AppendString, "a/b", "c"); Assert.Equal("breadcrumb", EnvironmentContext.FileAbstractLayer.ReadAllText(Path.Combine(outputFolder, "breadcrumb.json"))); // Check cached PostProcessInfo Assert.NotNull(currentBuildInfo.PostProcessInfo); var postProcessorInfos = currentBuildInfo.PostProcessInfo.PostProcessorInfos; Assert.Equal(1, currentBuildInfo.PostProcessInfo.PostProcessorInfos.Count); Assert.Equal($"{typeof(AppendStringPostProcessor).Name}", postProcessorInfos[0].Name); Assert.Null(postProcessorInfos[0].IncrementalContextHash); Assert.Equal <ManifestItem>(manifest.Files, currentBuildInfo.PostProcessInfo.ManifestItems); var postProcessOutputs = currentBuildInfo.PostProcessInfo.PostProcessOutputs; Assert.Equal(6, postProcessOutputs.Count); VerifyCachedOutput(Path.Combine(intermediateFolder, currentBuildInfo.DirectoryName), postProcessOutputs, AppendStringPostProcessor.AppendString, AppendStringPostProcessor.AdditionalExtensionString, "a/b", "c"); }
public void TestIncrementalWithFirstCanIncrementalButSecondShouldnotTraceIncrementalInfo() { // | Should trace incremental info | Can incremental | // --------------------------------------------------------- // First | yes | yes | // Second | no | no | // Step 1: trace intermediate info and post process incrementally var intermediateFolder = GetRandomFolder(); var currentBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder) }; var lastBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder), PostProcessInfo = new PostProcessInfo() }; lastBuildInfo.PostProcessInfo.PostProcessorInfos.Add(new PostProcessorInfo { Name = typeof(AppendStringPostProcessor).Name }); // Exclude c, which is not incremental var preparedManifest = JsonUtility.Deserialize <Manifest>("PostProcessors/Data/manifest_incremental.json"); PrepareCachedOutput(intermediateFolder, lastBuildInfo, AppendStringPostProcessor.AppendString, preparedManifest.Files, AppendStringPostProcessor.AdditionalExtensionString, "a", "b"); var postProcessors = GetPostProcessors(typeof(AppendStringPostProcessor)); var appendString = $"{AppendStringPostProcessor.AppendString}"; var increContext = new IncrementalPostProcessorsContext(intermediateFolder, currentBuildInfo, lastBuildInfo, postProcessors, true); // Check context Assert.True(increContext.ShouldTraceIncrementalInfo); Assert.True(increContext.IsIncremental); var increPostProcessorHandler = new PostProcessorsHandlerWithIncremental(PostProcessorsHandler, increContext); var manifest = JsonUtility.Deserialize <Manifest>("PostProcessors/Data/manifest_incremental.json"); var outputFolder = GetRandomFolder(); PrepareOutput(outputFolder, "a", "b", "c"); increPostProcessorHandler.Handle(postProcessors, manifest, outputFolder); // Check incremental flag Assert.Equal(3, manifest.Files.Count); Assert.True(manifest.Files.Single(i => i.SourceRelativePath == "a.md").IsIncremental); Assert.True(manifest.Files.Single(i => i.SourceRelativePath == "b.md").IsIncremental); Assert.False(manifest.Files.Single(i => i.SourceRelativePath == "c.md").IsIncremental); foreach (var file in manifest.Files) { Assert.True(file.OutputFiles.ContainsKey(AppendStringPostProcessor.AdditionalExtensionString)); } // Check output content VerifyOutput(outputFolder, appendString, "a", "b", "c"); // Check cached PostProcessInfo Assert.NotNull(currentBuildInfo.PostProcessInfo); var postProcessorInfos = currentBuildInfo.PostProcessInfo.PostProcessorInfos; Assert.Equal(1, currentBuildInfo.PostProcessInfo.PostProcessorInfos.Count); Assert.Equal($"{typeof(AppendStringPostProcessor).Name}", postProcessorInfos[0].Name); Assert.Null(postProcessorInfos[0].IncrementalContextHash); Assert.Equal <ManifestItem>(manifest.Files, currentBuildInfo.PostProcessInfo.ManifestItems); var postProcessOutputs = currentBuildInfo.PostProcessInfo.PostProcessOutputs; Assert.Equal(9, postProcessOutputs.Count); VerifyCachedOutput(Path.Combine(intermediateFolder, currentBuildInfo.DirectoryName), postProcessOutputs, appendString, AppendStringPostProcessor.AdditionalExtensionString, "a", "b", "c"); // Step 2: should not trace inter incremental post process currentBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder) }; lastBuildInfo = new BuildInfo { DirectoryName = Path.GetFileName(increContext.CurrentBaseDir), PostProcessInfo = increContext.CurrentInfo }; // Add post processor which not supports incremental postProcessors.AddRange(GetPostProcessors(typeof(NonIncrementalPostProcessor))); increContext = new IncrementalPostProcessorsContext(intermediateFolder, currentBuildInfo, lastBuildInfo, postProcessors, true); // Check context Assert.False(increContext.ShouldTraceIncrementalInfo); Assert.False(increContext.IsIncremental); increPostProcessorHandler = new PostProcessorsHandlerWithIncremental(PostProcessorsHandler, increContext); manifest = JsonUtility.Deserialize <Manifest>("PostProcessors/Data/manifest_incremental.json"); outputFolder = GetRandomFolder(); PrepareOutput(outputFolder, "a", "b", "c"); increPostProcessorHandler.Handle(postProcessors, manifest, outputFolder); // Check incremental flag Assert.True(manifest.Files.All(f => f.IsIncremental == false)); // Check output content VerifyOutput(outputFolder, appendString, "a", "b", "c"); // Check cached PostProcessInfo should be null Assert.Null(currentBuildInfo.PostProcessInfo); }
public void TestIncrementalBasicScenario() { var intermediateFolder = GetRandomFolder(); var currentBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder) }; var lastBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder), PostProcessInfo = new PostProcessInfo() }; lastBuildInfo.PostProcessInfo.PostProcessorInfos.Add(new PostProcessorInfo { Name = typeof(AppendStringPostProcessor).Name }); // Exclude c, which is not incremental var preparedManifest = JsonUtility.Deserialize <Manifest>("PostProcessors/Data/manifest_incremental.json"); PrepareCachedOutput(intermediateFolder, lastBuildInfo, AppendStringPostProcessor.AppendString, preparedManifest.Files, AppendStringPostProcessor.AdditionalExtensionString, "a", "b"); var postProcessors = GetPostProcessors(typeof(AppendStringPostProcessor)); var increContext = new IncrementalPostProcessorsContext(intermediateFolder, currentBuildInfo, lastBuildInfo, postProcessors, true); // Check context Assert.True(increContext.ShouldTraceIncrementalInfo); Assert.True(increContext.IsIncremental); var increPostProcessorHandler = new PostProcessorsHandlerWithIncremental(PostProcessorsHandler, increContext); var manifest = JsonUtility.Deserialize <Manifest>("PostProcessors/Data/manifest_incremental.json"); var outputFolder = GetRandomFolder(); PrepareOutput(outputFolder, "a", "b", "c"); increPostProcessorHandler.Handle(postProcessors, manifest, outputFolder); // Check incremental flag Assert.Equal(3, manifest.Files.Count); Assert.True(manifest.Files.Single(i => i.SourceRelativePath == "a.md").IsIncremental); Assert.True(manifest.Files.Single(i => i.SourceRelativePath == "b.md").IsIncremental); Assert.False(manifest.Files.Single(i => i.SourceRelativePath == "c.md").IsIncremental); foreach (var file in manifest.Files) { Assert.True(file.OutputFiles.ContainsKey(AppendStringPostProcessor.AdditionalExtensionString)); } // Check output content VerifyOutput(outputFolder, AppendStringPostProcessor.AppendString, "a", "b", "c"); // Check cached PostProcessInfo Assert.NotNull(currentBuildInfo.PostProcessInfo); var postProcessorInfos = currentBuildInfo.PostProcessInfo.PostProcessorInfos; Assert.Equal(1, currentBuildInfo.PostProcessInfo.PostProcessorInfos.Count); Assert.Equal($"{typeof(AppendStringPostProcessor).Name}", postProcessorInfos[0].Name); Assert.Null(postProcessorInfos[0].IncrementalContextHash); var postProcessOutputs = currentBuildInfo.PostProcessInfo.PostProcessOutputs; Assert.Equal(9, postProcessOutputs.Count); VerifyCachedOutput(Path.Combine(intermediateFolder, currentBuildInfo.DirectoryName), postProcessOutputs, AppendStringPostProcessor.AppendString, AppendStringPostProcessor.AdditionalExtensionString, "a", "b", "c"); // Check incremental info Assert.Equal(1, manifest.IncrementalInfo.Count); Assert.Equal(true, manifest.IncrementalInfo[0].Status.CanIncremental); Assert.Equal(IncrementalPhase.PostProcessing, manifest.IncrementalInfo[0].Status.IncrementalPhase); Assert.Equal("Can support incremental post processing.", manifest.IncrementalInfo[0].Status.Details); }
public void TestIncrementalWithFirstCannotIncrementalButSecondCanIncremental() { // | Should trace incremental info | Can incremental | // --------------------------------------------------------- // First | yes | no | // Second | yes | yes | var intermediateFolder = GetRandomFolder(); const string phaseName = PrependIncrementalPhaseName + "FirstCannotIncrementalButSecondCanIncremental"; var postProcessors = GetPostProcessors(typeof(AppendStringPostProcessor), typeof(AppendIntegerPostProcessor)); var appendString = $"{AppendStringPostProcessor.AppendString}{AppendIntegerPostProcessor.AppendInteger}"; IncrementalPostProcessorsContext increContext = null; IncrementalActions (phaseName, () => { // Step 1: trace intermediate info using (new LoggerPhaseScope(phaseName + "First")) { var currentBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder) }; increContext = new IncrementalPostProcessorsContext(intermediateFolder, currentBuildInfo, null, postProcessors, true); // Check context Assert.True(increContext.ShouldTraceIncrementalInfo); Assert.False(increContext.IsIncremental); var increPostProcessorHandler = new PostProcessorsHandlerWithIncremental(PostProcessorsHandler, increContext); var manifest = JsonUtility.Deserialize <Manifest>("PostProcessors/Data/manifest_incremental.json"); var outputFolder = GetRandomFolder(); PrepareOutput(outputFolder, "a", "b", "c"); increPostProcessorHandler.Handle(postProcessors, manifest, outputFolder); // Check incremental flag Assert.True(manifest.Files.All(f => f.IsIncremental == false)); // Check output content VerifyOutput(outputFolder, appendString, "a", "b", "c"); // Check cached PostProcessInfo Assert.NotNull(currentBuildInfo.PostProcessInfo); var postProcessorInfos = currentBuildInfo.PostProcessInfo.PostProcessorInfos; Assert.Equal(2, currentBuildInfo.PostProcessInfo.PostProcessorInfos.Count); Assert.Equal($"{typeof(AppendStringPostProcessor).Name}", postProcessorInfos[0].Name); Assert.Null(postProcessorInfos[0].IncrementalContextHash); Assert.Equal($"{typeof(AppendIntegerPostProcessor).Name}", postProcessorInfos[1].Name); Assert.Equal(AppendIntegerPostProcessor.HashValue, postProcessorInfos[1].IncrementalContextHash); Assert.NotNull(postProcessorInfos[1].ContextInfoFile); Assert.Equal(new List <string> { "a.html", "b.html", "c.html" }, JsonUtility.Deserialize <List <string> >(Path.Combine(intermediateFolder, currentBuildInfo.DirectoryName, postProcessorInfos[1].ContextInfoFile))); Assert.Equal(3, currentBuildInfo.PostProcessInfo.ManifestItems.Count); Assert.Equal <ManifestItem>(manifest.Files, currentBuildInfo.PostProcessInfo.ManifestItems); var postProcessOutputs = currentBuildInfo.PostProcessInfo.PostProcessOutputs; Assert.Equal(9, postProcessOutputs.Count); VerifyCachedOutput(Path.Combine(intermediateFolder, currentBuildInfo.DirectoryName), postProcessOutputs, appendString, AppendStringPostProcessor.AdditionalExtensionString, "a", "b", "c"); // Check log messages var logs = Listener.Items.Where(i => i.Phase.StartsWith(phaseName)).ToList(); Assert.Equal(3, logs.Count); Assert.True(logs.All(l => l.Message.Contains("is not in html format."))); } }, () => { // Step 2: incremental post process using (new LoggerPhaseScope(phaseName + "Second")) { var secondBuildInfo = new BuildInfo { DirectoryName = IncrementalUtility.CreateRandomDirectory(intermediateFolder) }; var lastBuildInfo = new BuildInfo { DirectoryName = Path.GetFileName(increContext.CurrentBaseDir), PostProcessInfo = increContext.CurrentInfo }; increContext = new IncrementalPostProcessorsContext(intermediateFolder, secondBuildInfo, lastBuildInfo, postProcessors, true); // Check context Assert.True(increContext.ShouldTraceIncrementalInfo); Assert.True(increContext.IsIncremental); var increPostProcessorHandler = new PostProcessorsHandlerWithIncremental(PostProcessorsHandler, increContext); var manifest = JsonUtility.Deserialize <Manifest>("PostProcessors/Data/manifest_incremental.json"); var outputFolder = GetRandomFolder(); PrepareOutput(outputFolder, "a", "b", "c"); increPostProcessorHandler.Handle(postProcessors, manifest, outputFolder); // Check incremental flag Assert.Equal(3, manifest.Files.Count); Assert.True(manifest.Files.Single(i => i.SourceRelativePath == "a.md").IsIncremental); Assert.True(manifest.Files.Single(i => i.SourceRelativePath == "b.md").IsIncremental); Assert.False(manifest.Files.Single(i => i.SourceRelativePath == "c.md").IsIncremental); foreach (var file in manifest.Files) { Assert.True(file.OutputFiles.ContainsKey(AppendStringPostProcessor.AdditionalExtensionString)); } // Check output content VerifyOutput(outputFolder, appendString, "a", "b", "c"); // Check cached PostProcessInfo Assert.NotNull(secondBuildInfo.PostProcessInfo); var postProcessorInfos = secondBuildInfo.PostProcessInfo.PostProcessorInfos; Assert.Equal(2, secondBuildInfo.PostProcessInfo.PostProcessorInfos.Count); Assert.Equal($"{typeof(AppendStringPostProcessor).Name}", postProcessorInfos[0].Name); Assert.Null(postProcessorInfos[0].IncrementalContextHash); Assert.Equal($"{typeof(AppendIntegerPostProcessor).Name}", postProcessorInfos[1].Name); Assert.Equal(AppendIntegerPostProcessor.HashValue, postProcessorInfos[1].IncrementalContextHash); Assert.NotNull(postProcessorInfos[1].ContextInfoFile); Assert.Equal(new List <string> { "a.html", "b.html", "c.html" }, JsonUtility.Deserialize <List <string> >(Path.Combine(intermediateFolder, secondBuildInfo.DirectoryName, postProcessorInfos[1].ContextInfoFile))); Assert.Equal(3, secondBuildInfo.PostProcessInfo.ManifestItems.Count); Assert.Equal <ManifestItem>(manifest.Files, secondBuildInfo.PostProcessInfo.ManifestItems); var postProcessOutputs = secondBuildInfo.PostProcessInfo.PostProcessOutputs; Assert.Equal(9, postProcessOutputs.Count); VerifyCachedOutput(Path.Combine(intermediateFolder, secondBuildInfo.DirectoryName), postProcessOutputs, appendString, AppendStringPostProcessor.AdditionalExtensionString, "a", "b", "c"); // Check log messages var logs = Listener.Items.Where(i => i.Phase.StartsWith(phaseName)).ToList(); Assert.Equal(3, logs.Count); Assert.True(logs.All(l => l.Message.Contains("is not in html format."))); } }); }