public int Run(MergeOptions mergeOptions) { try { string outputDirectory = mergeOptions.OutputDirectoryPath ?? Environment.CurrentDirectory; string outputFilePath = Path.Combine(outputDirectory, GetOutputFileName(mergeOptions)); if (mergeOptions.SplittingStrategy == 0) { if (!DriverUtilities.ReportWhetherOutputFileCanBeCreated(outputFilePath, mergeOptions.Force, _fileSystem)) { return(FAILURE); } } HashSet <string> sarifFiles = CreateTargetsSet(mergeOptions.TargetFileSpecifiers, mergeOptions.Recurse, _fileSystem); IEnumerable <SarifLog> allRuns = ParseFiles(sarifFiles); // Build one SarifLog with all the Runs. SarifLog mergedLog = allRuns .Merge(mergeOptions.MergeEmptyLogs) .InsertOptionalData(mergeOptions.DataToInsert.ToFlags()) .RemoveOptionalData(mergeOptions.DataToInsert.ToFlags()); // If there were no input files, the Merge operation set combinedLog.Runs to null. Although // null is valid in certain error cases, it is not valid here. Here, the correct value is // an empty list. See the SARIF spec, §3.13.4, "runs property". mergedLog.Runs ??= new List <Run>(); mergedLog.Version = SarifVersion.Current; mergedLog.SchemaUri = mergedLog.Version.ConvertToSchemaUri(); if (mergeOptions.SplittingStrategy != SplittingStrategy.PerRule) { _fileSystem.DirectoryCreate(outputDirectory); // Write output to file. WriteSarifFile(_fileSystem, mergedLog, outputFilePath, mergeOptions.Formatting); return(0); } var ruleToRunsMap = new Dictionary <string, HashSet <Run> >(); foreach (Run run in mergedLog.Runs) { IList <Result> cachedResults = run.Results; run.Results = null; if (mergeOptions.MergeRuns) { run.Tool.Driver.Rules = null; run.Artifacts = null; run.Invocations = null; } Run emptyRun = run.DeepClone(); run.Results = cachedResults; var idToRunMap = new Dictionary <string, Run>(); if (run.Results != null) { foreach (Result result in run.Results) { if (!idToRunMap.TryGetValue(result.RuleId, out Run splitRun)) { splitRun = idToRunMap[result.RuleId] = emptyRun.DeepClone(); } splitRun.Results ??= new List <Result>(); if (!ruleToRunsMap.TryGetValue(result.RuleId, out HashSet <Run> runs)) { IEqualityComparer <Run> comparer = Microsoft.CodeAnalysis.Sarif.Run.ValueComparer; runs = ruleToRunsMap[result.RuleId] = new HashSet <Run>(comparer); } runs.Add(splitRun); } } } foreach (string ruleId in ruleToRunsMap.Keys) { HashSet <Run> runs = ruleToRunsMap[ruleId]; var perRuleLog = new SarifLog { Runs = new List <Run>(runs) }; if (mergeOptions.MergeRuns) { new FixupVisitor().VisitSarifLog(perRuleLog); } _fileSystem.DirectoryCreate(outputDirectory); outputFilePath = Path.Combine(outputDirectory, GetOutputFileName(mergeOptions, ruleId)); if (!DriverUtilities.ReportWhetherOutputFileCanBeCreated(outputFilePath, mergeOptions.Force, _fileSystem)) { return(FAILURE); } WriteSarifFile(_fileSystem, perRuleLog, outputFilePath, mergeOptions.Formatting); } } catch (Exception ex) { Console.WriteLine(ex); return(FAILURE); } return(SUCCESS); }
internal static string GetOutputFileName(MergeOptions mergeOptions) { return(!string.IsNullOrEmpty(mergeOptions.OutputFileName) ? mergeOptions.OutputFileName : "combined.sarif"); }
internal static string GetOutputFileName(MergeOptions mergeOptions, string prefix = null) { return(string.IsNullOrEmpty(mergeOptions.OutputFileName) == false ? GetPrefix(prefix) + mergeOptions.OutputFileName : GetPrefix("merged.sarif")); }