static void Process(string path, SearchOptions options, SearchRange range, ActionType action, IEnumerable <ParsedCommit> commitsToIgnore) { IEnumerable <CommitInfo> commits = CommitFinder.Parse(path, range); Explain.Print($"Found {commits.Count ()} commits."); switch (action) { case ActionType.ListConsideredCommits: PrintCommits(commits); return; case ActionType.ListBugs: var parsedCommits = CommitParser.Parse(commits, options).ToList(); var bugCollection = BugCollector.ClassifyCommits(parsedCommits, options, commitsToIgnore); PrintBugs(bugCollection, options); if (options.ValidateBugStatus) { BugValidator.Validate(bugCollection, options); } return; default: throw new InvalidOperationException($"Internal Error - Unknown action requested {action}"); } }
static void PrintCommits(IEnumerable <CommitInfo> commits) { foreach (var commit in commits) { Console.WriteLine($"{commit.Hash} {commit.Title}"); } Explain.Print($"Only listing of commits was requested. Exiting."); }
public static IEnumerable <ParsedCommit> ParseSingle(CommitInfo commit, SearchOptions options) { Explain.Indent(); Explain.Print($"Analyzing {commit.Hash}."); var textToSearch = commit.Description.SplitLines(); foreach (var match in textToSearch.Select(x => ParseLine(x, options)).Where(x => x.Confidence != ParsingConfidence.Invalid)) { yield return(new ParsedCommit(commit, match.Link, match.ID, match.Confidence, match.BugzillaSummary, match.TargetMilestone, match.Status, match.Importance)); } Explain.Deindent(); }
public void Run(ActionType action) { // This can mutage Range so must be done first. var commitsToIgnore = ProcessOldestBranch(); Process(Path, Options, Range, action, commitsToIgnore); if (Options.Submodules) { string oldest = Range.Oldest.ValueOr(""); var initialSubmoduleStatus = CommitFinder.FindSubmodulesStatus(Path, oldest); string newest = Range.Newest.ValueOr("HEAD"); var finalSubmoduleStatus = CommitFinder.FindSubmodulesStatus(Path, newest); Explain.Print($"Processing {initialSubmoduleStatus.Count} submodules for change as well"); Explain.Indent(); foreach (var submodule in initialSubmoduleStatus.Keys) { string initialHash = initialSubmoduleStatus[submodule]; string finalHash = finalSubmoduleStatus[submodule]; if (initialHash == finalHash) { Explain.Print($"Submodule {submodule} had zero changes ({finalHash})."); continue; } Console.WriteLine($"\nSubmodule: {submodule}"); Explain.Print($"Processing {submodule} submodule from {initialHash} to {finalHash}."); SearchRange submoduleRange = new SearchRange() { Oldest = initialHash.Some(), Newest = finalHash.Some() }; Explain.Indent(); Process(System.IO.Path.Combine(Path, submodule), Options, submoduleRange, action, Enumerable.Empty <ParsedCommit> ()); Explain.Deindent(); } Explain.Deindent(); } }
static void ProcessBugStatus(BugCollection bugs) { foreach (var bug in bugs.Bugs) { switch (bug.BugInfo.Status) { case "CLOSED": case "VERIFIED": case "RESOLVED": break; default: Explain.Print($"{bug.ID} status may not be set correctly: {bug.BugInfo.Status}."); break; } } }
static void ProcessTargetMilestones(BugCollection bugs, SearchOptions options) { string targetMilestone = options.ExpectedTargetMilestone ?? GuessTargetMilestone(bugs); var unmatchingBugs = bugs.Bugs.Where(x => x.BugInfo.TargetMilestone != targetMilestone); if (unmatchingBugs.Any()) { Explain.Print($"The following bugs do not match the expected {targetMilestone}:"); Explain.Indent(); foreach (var bug in unmatchingBugs) { Explain.Print($"{bug.ID} - {bug.BugInfo.TargetMilestone}"); } } Explain.Deindent(); }
public static ValueTuple <IEnumerable <CommitInfo>, string> FindCommitsOnBranchToIgnore(string path, string branchName, SearchOptions options) { var merge = FindMergeBase(path, branchName); if (!merge.HasValue) { EntryPoint.Die($"Unable to find merge-base with {branchName} on {path}. Do you need to get fetch?"); return(new ValueTuple <IEnumerable <CommitInfo>, string> ()); } var mergeBase = merge.ValueOrFailure(); Explain.Print($"Found merge base for {branchName} at {mergeBase}."); var commitToIgnoreOnBranch = ParseSpecificRange(path, mergeBase, $"origin/{branchName}"); Explain.Print($"Found {commitToIgnoreOnBranch.Count ()} commits on {branchName} after branch."); return(new ValueTuple <IEnumerable <CommitInfo>, string> (commitToIgnoreOnBranch, mergeBase)); }
public static void Validate(BugCollection bugs, SearchOptions options) { bool explainStatus = Explain.Enabled; Explain.Enabled = true; Explain.Print("Validating Bug Status:"); if (options.Bugzilla != BugzillaLevel.Private) { Explain.Print("This will only cover public bugs as private as --bugzilla:private is not set."); } Explain.Indent(); ProcessBugStatus(bugs); Explain.Print(""); ProcessTargetMilestones(bugs, options); Explain.Deindent(); Explain.Enabled = explainStatus; }
IEnumerable <ParsedCommit> ProcessOldestBranch() { if (Range.OldestBranch.HasValue) { var branchName = Range.OldestBranch.ValueOrFailure(); if (branchName.StartsWith("origin/", StringComparison.InvariantCulture)) { branchName = branchName.Remove(0, 7); } var commitInfo = CommitFinder.FindCommitsOnBranchToIgnore(Path, branchName, Options); IEnumerable <ParsedCommit> commitsToIgnore = CommitParser.Parse(commitInfo.Item1, Options); Explain.Print($"Found {commitsToIgnore.Count ()} bugs on {branchName} after branch to ignore."); Range.Oldest = commitInfo.Item2.Some(); Range.IncludeOldest = false; return(commitsToIgnore); } return(Enumerable.Empty <ParsedCommit> ()); }
static string GuessTargetMilestone(BugCollection bugs) { Explain.Print("--expected-target-milestone was not set, so finding the most common Target Milestone."); var targetMilestoneCount = new Dictionary <string, int> (); foreach (var bug in bugs.Bugs) { if (targetMilestoneCount.ContainsKey(bug.BugInfo.TargetMilestone)) { targetMilestoneCount[bug.BugInfo.TargetMilestone] += 1; } else { targetMilestoneCount[bug.BugInfo.TargetMilestone] = 1; } } var targetMilestones = targetMilestoneCount.Keys.OrderByDescending(x => targetMilestoneCount[x]).ToList(); string guess = targetMilestones.FirstOrDefault(); Explain.Print($"{guess} is the most common Target Milestone."); return(guess); }
static ParseResults ParseLine(string line, SearchOptions options) { try { Explain.Indent(); foreach (Regex regex in AllRegex) { var match = regex.Match(line); if (match.Success) { int id; if (int.TryParse(match.Groups[match.Groups.Count - 1].Value, out id)) { Explain.Print($"Line \"{StripNewLine (line)}\" matched pattern {regex}."); if (id < 1000 || id > 250000) { Explain.Print($"Had an invalid id {id}."); return(new ParseResults { Confidence = ParsingConfidence.Invalid }); } Explain.Print($"Had a valid id {id}."); ParsingConfidence confidence = ParsingConfidence.High; if (line.StartsWith("Context", StringComparison.InvariantCultureIgnoreCase)) { confidence = ParsingConfidence.Invalid; } Explain.Print($"Default Confidence was {confidence}."); if (options.Bugzilla != BugzillaLevel.Disable) { var bugzillaSummary = GetTitle(id, options); if (bugzillaSummary == null) { confidence = ParsingConfidence.Low; Explain.Print($"Given low confidence due to lack of a matching bugzilla bug."); return(new ParseResults(confidence, match.Value, id)); } var status = GetStatus(id, options); var milestone = GetMilestone(id, options); var importance = GetImportance(id, options); return(new ParseResults(confidence, match.Value, id) { BugzillaSummary = bugzillaSummary, Status = status, TargetMilestone = milestone, Importance = importance }); } return(new ParseResults(confidence, match.Value, id)); } } } return(new ParseResults { Confidence = ParsingConfidence.Invalid }); } finally { Explain.Deindent(); } }