// // Counts the type of reviews in a set of commits // public static GetCommitStatsResult GetCommitStatistics(SvnLogs.Log[] svnLogs, Logging logger, StatisticGenerated statGenerated) { // We need to track the types of reviews Object writeLock = new Object(); int logCount = 0; int unknownReviews = 0; int[] commitCounts = new int[Enum.GetNames(typeof(RB_Tools.Shared.Review.Properties.Level)).Length]; // Keep track of the reviews we find var reviews = new List <CommitReview>(); // Spin through them all and parse the log message logger.Log("Starting to pull out the commit statistics from the SVN logs"); ParallelLoopResult result = Parallel.ForEach(svnLogs, new ParallelOptions { MaxDegreeOfParallelism = 16 }, (thisLog, loopState) => { // Get the line with the review state in it string reviewStateLine = thisLog.Message.FirstOrDefault(line => { Match regExMatch = Regex.Match(line, @".*\[Review State.*:.*\]"); return(regExMatch.Success); }); // Identify what we have logger.Log(@"* Found the review state line '{0}' in revision {1}", reviewStateLine, thisLog.Revision); // Do we have anything bool unknownReview = false; if (string.IsNullOrEmpty(reviewStateLine) == true) { unknownReview = true; } // Get the type of review if we need to int commitType = -1; CommitReview commitToAdd = null; if (unknownReview == false) { try { // Get the type of review string string[] reviewTypeSplit = reviewStateLine.Split(':'); string reviewType = reviewTypeSplit[1].Replace("]", "").Trim(); // Find the review type this is for (int i = 0; i < commitCounts.Length; ++i) { string thisEnumName = ((RB_Tools.Shared.Review.Properties.Level)i).GetSplitName(); if (thisEnumName.Equals(reviewType, StringComparison.InvariantCultureIgnoreCase) == true) { // Let us know what type of review we found logger.Log(@"* Found review type '{0}'", ((RB_Tools.Shared.Review.Properties.Level)i).ToString()); // If this is a review, pull out the review if (i == (int)RB_Tools.Shared.Review.Properties.Level.FullReview) { string reviewUrl = GetReviewUrl(thisLog.Message); if (string.IsNullOrEmpty(reviewUrl) == false) { commitToAdd = new CommitReview(thisLog, reviewUrl); } } // Track the number of reviews commitType = i; break; } } } catch { // Something has gone wrong loopState.Stop(); } } // Only bother if we need to if (loopState.IsStopped == false) { // Update our information lock (writeLock) { // Update logger.Log("Updating the review type counts"); // Update the view type if (unknownReview == true) { ++unknownReviews; } else if (commitType >= 0) { ++commitCounts[commitType]; } // Store if needed if (commitToAdd != null) { reviews.Add(commitToAdd); } // Another one done statGenerated(++logCount); } } }); // Did we fail if (result.IsCompleted == false) { logger.Log("The commit statistics completed unsuccessfully"); return(null); } // Update what we found logger.Log("The following review types were found"); logger.Log("* Commit count: {0}", commitCounts); logger.Log("* Unknown reviews: {0}", unknownReviews); for (int i = 0; i < reviews.Count; ++i) { logger.Log("* {0}: {1}", ((RB_Tools.Shared.Review.Properties.Level)i).ToString(), reviews[i]); } // Return our reviews return(new GetCommitStatsResult(commitCounts, unknownReviews, reviews.ToArray())); }
// // Returns the statistics on the raised reviews // public static ReviewStatistics[] GetReviewStatistics(CommitReview[] reviewList, string workingDirectory, Simple credentials, Logging logger, StatisticGenerated statGenerated) { // Track our updates Object writeLock = new object(); int reviewCount = 0; var properties = new List <ReviewStatistics>(reviewList.Length); // We need to spin through every review and pull out the information about each one logger.Log("Starting to pull out the review stats from generated reviews"); ParallelLoopResult result = Parallel.ForEach(reviewList, new ParallelOptions { MaxDegreeOfParallelism = 16 }, (thisReview, loopState) => { // Get our properties ReviewStatistics reviewProperties = GetPropertiesOfReview(thisReview, workingDirectory, credentials, logger); if (reviewProperties == null) { loopState.Stop(); } // Continue? if (loopState.IsStopped == false) { // Update lock (writeLock) { logger.Log("Updating review properties"); // Update properties.Add(reviewProperties); statGenerated(++reviewCount); } } }); // How did we do? if (result.IsCompleted == false) { logger.Log("The review statistics completed unsuccessfully"); return(null); } // Return our properties logger.Log("Created {0} review stats", properties.Count); return(properties.ToArray()); }
// // Builds up stats about Jira usage // public static JiraStatistics GetJiraStatistics(SvnLogs.Log[] revisionLogs, Simple credentials, Logging logger, StatisticGenerated statsGenerated) { // Track our updates Object writeLock = new object(); int revisionCount = 0; int commitsWithoutJira = 0; ConcurrentDictionary <string, UInt64> validJiras = new ConcurrentDictionary <string, ulong>(); ConcurrentDictionary <string, UInt64> invalidJiras = new ConcurrentDictionary <string, ulong>(); // We need to spin through every review and pull out the information about each one logger.Log("Starting to pull out the Jira stats from the given revision list"); ParallelLoopResult result = Parallel.ForEach(revisionLogs, new ParallelOptions { MaxDegreeOfParallelism = 1 }, (thisRevision, loopState) => { // Assume no Jira until we have one bool noJira = true; // Get the Jira line string jiraLine = thisRevision.Message.FirstOrDefault(line => { return(line.Contains(@"[Jira Issue(s):")); }); // Do we have one? if (string.IsNullOrEmpty(jiraLine) == false && jiraLine.Contains(@"N/A") == false) { // Pull out the Jira information string[] splitIssuesLine = jiraLine.Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries); // We need two, the description and the Jira if (splitIssuesLine.Length == 2) { // Ok, this is something we should be able to use... // Get rid of the [] which might exist at the moment string jirasOnly = splitIssuesLine[1].Replace("[", "").Replace("]", "").Replace(" ", ""); string[] individualJiras = jirasOnly.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); // Check the Jira is valid foreach (string thisJira in individualJiras) { // Note we have a Jira now noJira = false; // Check if we track this as valid or invalid bool isJiraValid = false; try { isJiraValid = RB_Tools.Shared.Targets.Jira.ValidateJiraTicker(credentials, thisJira); } catch (Exception) { // It's not valid } // Get the dictionary and update it ConcurrentDictionary <string, UInt64> dictionaryToUpdate = isJiraValid == true ? validJiras : invalidJiras; dictionaryToUpdate.AddOrUpdate(thisJira, 1, (jira, count) => { return(++count); }); } } } // Continue? if (loopState.IsStopped == false) { // Update lock (writeLock) { logger.Log("Updating Jira properties"); // Update our stats if (noJira) { ++commitsWithoutJira; } // Update statsGenerated(++revisionCount); } } }); return(new JiraStatistics(commitsWithoutJira, revisionLogs.Length - commitsWithoutJira, validJiras, invalidJiras)); }