public GitDataCollector() { // Gets the Calendar instance associated with a CultureInfo. _cultureInfo = new CultureInfo("en-US"); _calendar = _cultureInfo.Calendar; ActivityByHourOfDay = new DictionaryWithDefault <int, decimal>(); ActivityByDayOfWeek = new DictionaryWithDefault <int, int>(); ActivityByMonthOfYear = new DictionaryWithDefault <int, int>(); ActivityByHourOfWeek = new DictionaryWithDefault <int, DictionaryWithDefault <int, int> >(); ActivityByHourOfDayBusiest = 0; ActivityByHourOfWeekBusiest = 0; ActivityByYearWeek = new DictionaryWithDefault <string, int>(); ActivityByYearWeekPeak = 0; Authors = new DictionaryWithDefault <string, Author>(); Domains = new DictionaryWithDefault <string, Domain>(); AuthorOfMonth = new DictionaryWithDefault <string, DictionaryWithDefault <string, int> >(); AuthorOfYear = new DictionaryWithDefault <int, DictionaryWithDefault <string, int> >(); CommitsByMonth = new DictionaryWithDefault <string, int>(); CommitsByYear = new DictionaryWithDefault <int, int>(); ActiveDays = new List <DateTime>(); TotalLines = 0; TotalLinesAdded = 0; TotalLinesRemoved = 0; CommitsByTimezone = new DictionaryWithDefault <string, int>(); Tags = new DictionaryWithDefault <string, Tag>(); }
private void GetExtensions() { Extensions = new DictionaryWithDefault <string, Extension>(); var lines = GitStats.GetPipeOutput(new[] { "git ls-tree -r -z HEAD" }).Split("\0").ToList().Where(s => !string.IsNullOrWhiteSpace(s)).ToArray(); ; TotalFiles = lines.Length; Console.WriteLine($"Processing {TotalFiles} files in repo"); foreach (var line in lines) { if (line.Length == 0) { continue; } var parts = Regex.Split(line, "\\s+", RegexOptions.None); var sha1 = parts[2]; var filename = parts[3]; string ext; if (filename.IndexOf(".", StringComparison.Ordinal) == -1 || filename.IndexOf(".", StringComparison.Ordinal) == 0) { ext = ""; } else { ext = filename.Substring(filename.LastIndexOf(".", StringComparison.Ordinal) + 1); } if (ext.Length > _configuration.MaxExtensionLength) { ext = ""; } if (!Extensions.ContainsKey(ext)) { Extensions[ext] = new Extension(); } Extensions[ext].Files += 1; try { Extensions[ext].Lines += GetLinesInBlob(sha1); } catch { Console.WriteLine("Warning: Could not count lines for file \"%s\"", line); } } }
private void GetFilesByStampAndTotalCommits(List <string> lines) { // TODO Optimize this, it's the worst bottleneck // outputs "<stamp> <files>" for each revision lines.Clear(); FilesByStamp = new DictionaryWithDefault <DateTime, int>(); var revLines = GitStats.GetPipeOutput(new[] { "git rev-list --remotes --pretty=format:\"%at %T\" HEAD", "grep -v ^commit" }).Trim().Split("\n"); foreach (var revLine in revLines) { var tup2 = revLine.Split(" "); var time = tup2[0]; var rev = tup2[1]; var lineCount = GetFilesInCommit(rev); lines.Add($"{Convert.ToInt32(time)} {lineCount}"); } TotalCommits = lines.Count; foreach (var line in lines) { var parts = line.Split(" "); if (parts.Length != 2) { continue; } try { FilesByStamp[DateTimeOffset.FromUnixTimeSeconds(Convert.ToInt32(parts[0])).DateTime] = Convert.ToInt32(parts[1]); } catch (FormatException) { Console.WriteLine("Warning: failed to parse line \"%s\"", line); } } }
private void GetChangesByDateAndTotalLines() { // line statistics // outputs: // N files changed, N insertions (+), N deletions(-) // <stamp> <author> ChangesByDate = new DictionaryWithDefault <DateTime, Change>(); var lines = GitStats.GetPipeOutput(new[] { "git log --shortstat --pretty=format:\"%at %an\"" }).Split("\n") .ToList(); lines.Reverse(); var files = 0; var inserted = 0; var deleted = 0; var totalLines = 0; foreach (var line in lines) { if (line.Length == 0) { files = 0; inserted = 0; deleted = 0; continue; } if (line.IndexOf(" changed,", StringComparison.CurrentCultureIgnoreCase) == -1) { var pos = line.IndexOf(" ", StringComparison.CurrentCultureIgnoreCase); if (pos != -1) { try { var datetime = DateTimeOffset.FromUnixTimeSeconds(Convert.ToInt32(line.Substring(0, pos))).DateTime; var author = line.Substring(pos + 1); ChangesByDate[datetime] = new Change { Files = files, Inserted = inserted, Deleted = deleted, TotalLines = totalLines }; if (!Authors.ContainsKey(author)) { Authors[author] = new Author(); } Authors[author].LinesAdded += inserted; Authors[author].LinesRemoved += deleted; } catch (Exception) { Console.WriteLine($"Warning: unexpected line \"{line}\""); } } else { Console.WriteLine($"Warning: unexpected line \"{line}\""); } } else { files = GetIntFromStartOfRegex(line, "\\d+ file"); inserted = GetIntFromStartOfRegex(line, "\\d+ insertion"); deleted = GetIntFromStartOfRegex(line, "\\d+ delet"); totalLines += inserted; totalLines -= deleted; TotalLinesAdded += inserted; TotalLinesRemoved += deleted; } } TotalLines = totalLines; }
// Collect revision statistics // Outputs "<stamp> <date> <time> <timezone> <author> '<' <mail> '>'" private List <string> GetActivityDataAndAuthors() { var lines = GitStats.GetPipeOutput(new[] { "git rev-list --remotes --pretty=format:\"%at %ai %an <%aE>\" HEAD", "grep -v ^commit" }, PipingLevel.Full, true).Split("\n").ToList(); foreach (var line in lines) { var parts = Regex.Split(line, "([01-9-:+]+ )").Where(x => !string.IsNullOrEmpty(x)).Select(s => s.Trim()) .ToArray(); DateTime stamp; try { stamp = DateTimeOffset.FromUnixTimeSeconds(Convert.ToInt32(parts[0])).DateTime; } catch (FormatException) { stamp = DateTime.MinValue; } var timezone = parts[3]; var tup1 = parts[4].Split("<"); var author = tup1[0]; var mail = tup1[1]; author = author.TrimEnd(); mail = mail.TrimEnd('>'); var domain = "?"; if (mail.IndexOf("@", StringComparison.CurrentCultureIgnoreCase) != -1) { domain = mail.Split("@")[1]; } var date = stamp; // First and last commit stamp if (LastCommitStamp == DateTime.MinValue) { LastCommitStamp = stamp; } FirstCommitStamp = stamp; // activity // hour var hour = date.Hour; ActivityByHourOfDay[hour] = ActivityByHourOfDay[hour] + 1; // most active hour? if (ActivityByHourOfDay[hour] > ActivityByHourOfDayBusiest) { ActivityByHourOfDayBusiest = ActivityByHourOfDay[hour]; } // day of week var day = (int)date.DayOfWeek - 1; ActivityByDayOfWeek[day] = ActivityByDayOfWeek[day] + 1; // domain stats if (!Domains.ContainsKey(domain)) { Domains[domain] = new Domain(); } // commits Domains[domain].Commits = Domains[domain].Commits + 1; // hour of week if (!ActivityByHourOfWeek.ContainsKey(day)) { ActivityByHourOfWeek[day] = new DictionaryWithDefault <int, int>(); } ActivityByHourOfWeek[day][hour] = ActivityByHourOfWeek[day][hour] + 1; // most active hour? if (ActivityByHourOfWeek[day][hour] > ActivityByHourOfWeekBusiest) { ActivityByHourOfWeekBusiest = ActivityByHourOfWeek[day][hour]; } // month of year var month = date.Month; ActivityByMonthOfYear[month] = ActivityByMonthOfYear[month] + 1; // yearly/weekly activity var yyw = $"{date.Year}-{_calendar.GetWeekOfYear(date, _cultureInfo.DateTimeFormat.CalendarWeekRule, _cultureInfo.DateTimeFormat.FirstDayOfWeek)}"; ActivityByYearWeek[yyw] = ActivityByYearWeek[yyw] + 1; if (ActivityByYearWeekPeak < ActivityByYearWeek[yyw]) { ActivityByYearWeekPeak = ActivityByYearWeek[yyw]; } // author stats if (!Authors.ContainsKey(author)) { Authors[author] = new Author(); } // commits if (Authors[author].LastCommitStamp == DateTime.MinValue) { Authors[author].LastCommitStamp = stamp; } Authors[author].FirstCommitStamp = stamp; Authors[author].Commits = Authors[author].Commits + 1; // author of the month/year var yymm = $"{date.Year}-{date.Month:D2}"; if (AuthorOfMonth.ContainsKey(yymm)) { AuthorOfMonth[yymm][author] = AuthorOfMonth[yymm][author] + 1; } else { AuthorOfMonth[yymm] = new DictionaryWithDefault <string, int> { [author] = 1 } }; CommitsByMonth[yymm] = CommitsByMonth[yymm] + 1; var yy = date.Year; if (AuthorOfYear.ContainsKey(yy)) { AuthorOfYear[yy][author] = AuthorOfYear[yy][author] + 1; } else { AuthorOfYear[yy] = new DictionaryWithDefault <string, int> { [author] = 1 } }; CommitsByYear[yy] = CommitsByYear[yy] + 1; // authors: active days var yymmdd = date; if (Authors[author].LastActiveDay == DateTime.MinValue) { Authors[author].LastActiveDay = yymmdd; Authors[author].ActiveDays = 1; } else if (yymmdd != Authors[author].LastActiveDay) { Authors[author].LastActiveDay = yymmdd; Authors[author].ActiveDays += 1; } // project: active days if (yymmdd != LastActiveDay) { LastActiveDay = yymmdd; ActiveDays.Add(yymmdd); } // timezone CommitsByTimezone[timezone] = CommitsByTimezone[timezone] + 1; } return(lines); }