From 7504a5a2936aea19ff60bd8a57850b49deef5419 Mon Sep 17 00:00:00 2001 From: "Wyatt J. Miller" Date: Tue, 23 Aug 2022 11:28:48 -0400 Subject: [PATCH 1/8] added PdfSharpCore dependency --- DrillSergeant.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/DrillSergeant.csproj b/DrillSergeant.csproj index 6863f6b..40dcd28 100644 --- a/DrillSergeant.csproj +++ b/DrillSergeant.csproj @@ -14,6 +14,7 @@ + From ddabd6080f5b19fc3ba9830387a4b65aa3b7f862 Mon Sep 17 00:00:00 2001 From: "Wyatt J. Miller" Date: Tue, 23 Aug 2022 11:29:12 -0400 Subject: [PATCH 2/8] added functionality to export commit reports to a PDF --- DAL/PdfDataService.cs | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 DAL/PdfDataService.cs diff --git a/DAL/PdfDataService.cs b/DAL/PdfDataService.cs new file mode 100644 index 0000000..f195197 --- /dev/null +++ b/DAL/PdfDataService.cs @@ -0,0 +1,46 @@ +using PdfSharpCore; +using PdfSharpCore.Drawing; +using PdfSharpCore.Pdf; +using PdfSharpCore.Pdf.IO; +using Pastel; + +public class PdfDataService : IDataService +{ + private string _fileName; + private string _pathName; + private string _dateTime; + + public PdfDataService() + { + _dateTime = DateTime.Now.ToString("yyyyMMddhhmm"); + _fileName = $"CommitReport-{_dateTime}.pdf"; + _pathName = Directory.GetCurrentDirectory() + "/" + _fileName; + } + + public void WriteAll(SortedList dictResults) + { + // sort the dictionary passed in + var sortedResults = dictResults.OrderByDescending(d => d.Value).ToList(); + + // setting the created document + var document = new PdfDocument(); + var page = document.AddPage(); + + // heading + var gfx = XGraphics.FromPdfPage(page); + var fontHeading = new XFont("Times New Roman", 36, XFontStyle.Underline); + gfx.DrawString("Commit Report", fontHeading, XBrushes.Black, new XRect(0, 0, page.Width, page.Height), XStringFormats.TopCenter); + + // details + var fontDetails = new XFont("Times New Roman", 16, XFontStyle.Regular); + int positionValue = 50; + + foreach (var i in sortedResults) + { + gfx.DrawString($"{i.Key}: {i.Value}", fontDetails, XBrushes.Black, new XRect(0, positionValue, page.Width, page.Width), XStringFormats.TopCenter); + positionValue += 30; + } + + document.Save(_fileName); + } +} From 7478f3878207715177833a582292f00d3498065d Mon Sep 17 00:00:00 2001 From: "Wyatt J. Miller" Date: Tue, 23 Aug 2022 11:30:01 -0400 Subject: [PATCH 3/8] added command line args to export to a PDF --- Program.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Program.cs b/Program.cs index d93bbc9..3430aad 100644 --- a/Program.cs +++ b/Program.cs @@ -7,7 +7,7 @@ static class Program var outputOption = new Option( "--output", "Specify the output given to the user" - ).FromAmong("stdout", "xlsx"); + ).FromAmong("stdout", "xlsx", "pdf"); outputOption.AddAlias("-o"); var branchOption = new Option( @@ -59,6 +59,22 @@ static class Program break; } break; + case "pdf": + PdfDataService pdfDataService = new PdfDataService(); + DataAccess dataAccessPdfCase = new DataAccess(pdfDataService); + + switch (branchOptionValue) + { + case null: + commits.GetCurrentCommitsByName(); + dataAccessPdfCase.WriteData(commits.CommitDetails); + break; + default: + commits.GetCommitsByBranch(branchOptionValue); + dataAccessPdfCase.WriteData(commits.CommitDetails); + break; + } + break; case null: StdOutDataService stdOutDataService = new StdOutDataService(); DataAccess dataAccessNullCase = new DataAccess(stdOutDataService); From 1894b68c5abcff7fd754ad96abeff4e28a2604b0 Mon Sep 17 00:00:00 2001 From: "Wyatt J. Miller" Date: Tue, 23 Aug 2022 16:34:55 -0400 Subject: [PATCH 4/8] removed imports --- DAL/PdfDataService.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/DAL/PdfDataService.cs b/DAL/PdfDataService.cs index f195197..0d2fa64 100644 --- a/DAL/PdfDataService.cs +++ b/DAL/PdfDataService.cs @@ -1,8 +1,5 @@ -using PdfSharpCore; using PdfSharpCore.Drawing; using PdfSharpCore.Pdf; -using PdfSharpCore.Pdf.IO; -using Pastel; public class PdfDataService : IDataService { @@ -38,7 +35,7 @@ public class PdfDataService : IDataService foreach (var i in sortedResults) { gfx.DrawString($"{i.Key}: {i.Value}", fontDetails, XBrushes.Black, new XRect(0, positionValue, page.Width, page.Width), XStringFormats.TopCenter); - positionValue += 30; + positionValue += 25; } document.Save(_fileName); From 908c9cf9dc962bd5f0379ebd5b380c1ff464af0f Mon Sep 17 00:00:00 2001 From: "Wyatt J. Miller" Date: Tue, 23 Aug 2022 16:35:31 -0400 Subject: [PATCH 5/8] modified readme --- README.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f5bfb8b..d12616a 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Licensed by the Mozilla Public License v2.0 (see [LICENSE](./LICENSE.md)) ###### Table of Contents - [Overview](#overview) +- [Usage](#usage) - [Installation](#installation) - [Release](#release) - [Source](#source) @@ -24,17 +25,65 @@ Licensed by the Mozilla Public License v2.0 (see [LICENSE](./LICENSE.md)) When I was in university, I wanted a program that would tally up my git commits in a certain project that I'm working on. Based on search engine ninja skills, I couldn't find a program that did this. I decided to scratch my own itch. -I present DrillSergeant, where you can get a tally of the contributors' commits in a certain project. Additionally, you can filter by branch to get commits by branch. +I present DrillSergeant. This is a command-line application to tally up commits, ordered by commit count per contributor. In other words, DrillSergeant orders the contributors by how many commits they have made in descending order. For example, the first contributor listed will have the most commits in the project. The second contributor will have the second most commits, and so on. ## Usage -Please see the wiki for information. +To use this command-line application, you must be in a git project. Otherwise, a nasty error will appear and you won't get your report. You can filter by branch or by tag (cannot be both, another nasty error appears here). You can get your report in your terminal, in a spreadsheet, or a PDF. + +### Command-line arguments + +```bash + -o, --output Specify the output given to the user + -b, --branch Specify the branch to filter by + -t, --tag Specify the tag to filter by +``` + +Throw the `-h` flag for quick assistance. Throw the `--version` flag for version information. + +### Examples + +To get a commit report to your terminal: + +```bash +drillsergeant -o stdout +``` + +Or you can simply: + +```bash +drillsergeant +``` + +To get a commit report to your terminal filtered by the `devel` branch: + +``` +drillsergeant -b devel +``` + +To get a commit report to a spreadsheet: + +```bash +drillsergeant -o xlsx +``` + +To get a commit report to a PDF file filtered by the `devel` branch: + +```bash +drillsergeant -o pdf -b devel +``` + +Got too many contributors to fit onto your terminal? Run this by installing [bat](https://github.com/sharkdp/bat): + +```bash +drillsergeant | bat +``` ## Installation There's are two forms of installation: releases and building from sources. This readme goes through both. -### Releases +### Release You may get releases from the [releases page](https://scm.wyattjmiller.com/wymiller/DrillSergeant/releases). This is the recommended way to start using DrillSergeant. @@ -42,6 +91,20 @@ There will be three separate downloads: Windows (x86 64-bit), Linux (x86 64-bit) Once downloaded and extracted, you can move it to your `$PATH`. +On Windows (Powershell): + +```powershell +Copy-Item drillsergeant C:\Windows\ +``` + +On Linux: + +```bash +cp drillsergeant /usr/local/bin +``` + +The following commands assume you have elevated privileges. + If you do not have any of these platforms, read on to source installation as that's the next best option. ### Source @@ -97,3 +160,5 @@ Thank you to the developers, engineers, project managers, and contributors of th - [OpenXML](https://docs.microsoft.com/en-us/office/open-xml/open-xml-sdk) - [System.CommandLine](https://github.com/dotnet/command-line-api) - [Pastel](https://github.com/silkfire/Pastel) +- [PdfSharpCore](https://github.com/ststeiger/PdfSharpCore) + From e4d8e3f66eaf6fe6fcd41fa0babd40654271ed42 Mon Sep 17 00:00:00 2001 From: "Wyatt J. Miller" Date: Tue, 23 Aug 2022 18:56:56 -0400 Subject: [PATCH 6/8] added commit filtering by tag --- BLL/CommitDetail.cs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/BLL/CommitDetail.cs b/BLL/CommitDetail.cs index 4681e1d..d4c56c2 100644 --- a/BLL/CommitDetail.cs +++ b/BLL/CommitDetail.cs @@ -120,8 +120,29 @@ public class CommitDetail { using (var repo = new Repository(Directory.GetCurrentDirectory())) { - var tagResult = repo.Tags[tagName]; - System.Console.WriteLine(tagResult); + var tagResult = repo.Tags[tagName].Target.Sha; + + var commitFilter = new CommitFilter + { + IncludeReachableFrom = tagResult, + }; + + var query = repo.Commits.QueryBy(commitFilter); + + foreach (var c in query) + { + if (!_authors.Contains(c.Author.Name)) + { + _authors.Add(c.Author.Name); + } + } + + foreach (var a in _authors) + { + int commitCount = query.Where(r => r.Author.Name == a).Count(); + _commitDetails.Add(a, commitCount); + } + } } } From 7721031d6287bf0a23bf98d7f7f3364c33afcef7 Mon Sep 17 00:00:00 2001 From: "Wyatt J. Miller" Date: Tue, 23 Aug 2022 18:57:18 -0400 Subject: [PATCH 7/8] added command line arg for tag filtering, added arg logic for tag filtering --- Program.cs | 101 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 32 deletions(-) diff --git a/Program.cs b/Program.cs index d93bbc9..4e839b2 100644 --- a/Program.cs +++ b/Program.cs @@ -16,13 +16,20 @@ static class Program ); branchOption.AddAlias("-b"); + var tagOption = new Option( + "--tag", + "Specify the tag to filter by" + ); + tagOption.AddAlias("-t"); + var rootCommand = new RootCommand("Get a tally of contributors' commits") { outputOption, branchOption, + tagOption, }; - rootCommand.SetHandler((outputOptionValue, branchOptionValue) => { + rootCommand.SetHandler((outputOptionValue, branchOptionValue, tagOptionValue) => { CommitDetail commits = new CommitDetail(); switch (outputOptionValue) @@ -31,48 +38,78 @@ static class Program StdOutDataService outDataService = new StdOutDataService(); DataAccess dataAccess = new DataAccess(outDataService); - switch (branchOptionValue) - { - case null: - commits.GetCurrentCommitsByName(); - dataAccess.WriteData(commits.CommitDetails); - break; - default: - commits.GetCommitsByBranch(branchOptionValue); - dataAccess.WriteData(commits.CommitDetails); - break; + if (branchOptionValue != null && tagOptionValue != null) { + Console.WriteLine("Please specify either a branch or a tag"); + Environment.Exit(2); + } else if (branchOptionValue != null && tagOptionValue == null) { + switch (branchOptionValue) + { + case null: + commits.GetCurrentCommitsByName(); + dataAccess.WriteData(commits.CommitDetails); + break; + default: + commits.GetCommitsByBranch(branchOptionValue); + dataAccess.WriteData(commits.CommitDetails); + break; + } + break; + } else if (branchOptionValue == null && tagOptionValue != null) { + commits.GetCommitsByTag(tagOptionValue); + dataAccess.WriteData(commits.CommitDetails); } break; case "xlsx": ExcelDataService excelDataService = new ExcelDataService(); DataAccess dataAccessExcelCase = new DataAccess(excelDataService); - switch (branchOptionValue) - { - case null: - commits.GetCurrentCommitsByName(); - dataAccessExcelCase.WriteData(commits.CommitDetails); - break; - default: - commits.GetCommitsByBranch(branchOptionValue); - dataAccessExcelCase.WriteData(commits.CommitDetails); - break; + if (branchOptionValue != null && tagOptionValue != null) { + Console.WriteLine("Please specify either a branch or a tag."); + Environment.Exit(2); + } else if (branchOptionValue != null && tagOptionValue == null) { + switch (branchOptionValue) + { + case null: + commits.GetCurrentCommitsByName(); + dataAccessExcelCase.WriteData(commits.CommitDetails); + break; + default: + commits.GetCommitsByBranch(branchOptionValue); + dataAccessExcelCase.WriteData(commits.CommitDetails); + break; + } + break; + } else if (branchOptionValue == null && tagOptionValue != null) { + commits.GetCommitsByTag(tagOptionValue); + dataAccessExcelCase.WriteData(commits.CommitDetails); } break; case null: StdOutDataService stdOutDataService = new StdOutDataService(); DataAccess dataAccessNullCase = new DataAccess(stdOutDataService); - switch (branchOptionValue) - { - case null: - commits.GetCurrentCommitsByName(); - dataAccessNullCase.WriteData(commits.CommitDetails); - break; - default: - commits.GetCommitsByBranch(branchOptionValue); - dataAccessNullCase.WriteData(commits.CommitDetails); - break; + if (branchOptionValue != null && tagOptionValue != null) { + Console.WriteLine("Please specify either a branch or a tag."); + Environment.Exit(2); + } else if (branchOptionValue != null && tagOptionValue == null) { + switch (branchOptionValue) + { + case null: + commits.GetCurrentCommitsByName(); + dataAccessNullCase.WriteData(commits.CommitDetails); + break; + default: + commits.GetCommitsByBranch(branchOptionValue); + dataAccessNullCase.WriteData(commits.CommitDetails); + break; + } + break; + } else if (branchOptionValue == null && tagOptionValue != null) { + commits.GetCommitsByTag(tagOptionValue); + dataAccessNullCase.WriteData(commits.CommitDetails); + } else { + commits.GetCurrentCommitsByName(); + dataAccessNullCase.WriteData(commits.CommitDetails); } break; default: @@ -81,7 +118,7 @@ static class Program break; } }, - outputOption, branchOption); + outputOption, branchOption, tagOption); rootCommand.Invoke(args); } From 5873bdb2a6936aab9aab126519d36d51b86dce4d Mon Sep 17 00:00:00 2001 From: "Wyatt J. Miller" Date: Tue, 23 Aug 2022 19:31:39 -0400 Subject: [PATCH 8/8] try catch all the things --- BLL/CommitDetail.cs | 57 ++++++++++++++++++++++++++++----------------- Program.cs | 2 +- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/BLL/CommitDetail.cs b/BLL/CommitDetail.cs index d4c56c2..b9702f6 100644 --- a/BLL/CommitDetail.cs +++ b/BLL/CommitDetail.cs @@ -93,11 +93,19 @@ public class CommitDetail { var branchResult = repo.Branches[branchName]; - if (branchResult == null) + try { - branchResult = repo.Branches[$"origin/{branchName}"]; - var remoteBranch = repo.CreateBranch(branchName, branchResult.Tip); - repo.Branches.Update(remoteBranch, b => b.UpstreamBranch = $"refs/heads/{branchName}"); + if (branchResult == null) + { + branchResult = repo.Branches[$"origin/{branchName}"]; + var remoteBranch = repo.CreateBranch(branchName, branchResult.Tip); + repo.Branches.Update(remoteBranch, b => b.UpstreamBranch = $"refs/heads/{branchName}"); + } + } + catch (System.Exception) + { + Console.WriteLine($"Cannot fetch {branchName} branch."); + Environment.Exit(1); } foreach (var c in branchResult.Commits) @@ -120,29 +128,36 @@ public class CommitDetail { using (var repo = new Repository(Directory.GetCurrentDirectory())) { - var tagResult = repo.Tags[tagName].Target.Sha; - - var commitFilter = new CommitFilter + try { - IncludeReachableFrom = tagResult, - }; - - var query = repo.Commits.QueryBy(commitFilter); - - foreach (var c in query) - { - if (!_authors.Contains(c.Author.Name)) + var tagResult = repo.Tags[tagName].Target.Sha; + + var commitFilter = new CommitFilter { - _authors.Add(c.Author.Name); + IncludeReachableFrom = tagResult, + }; + + var query = repo.Commits.QueryBy(commitFilter); + + foreach (var c in query) + { + if (!_authors.Contains(c.Author.Name)) + { + _authors.Add(c.Author.Name); + } + } + + foreach (var a in _authors) + { + int commitCount = query.Where(r => r.Author.Name == a).Count(); + _commitDetails.Add(a, commitCount); } } - - foreach (var a in _authors) + catch (System.Exception) { - int commitCount = query.Where(r => r.Author.Name == a).Count(); - _commitDetails.Add(a, commitCount); + Console.WriteLine($"Cannot find the tag {tagName}"); + Environment.Exit(3); } - } } } diff --git a/Program.cs b/Program.cs index 7413e47..a156caa 100644 --- a/Program.cs +++ b/Program.cs @@ -130,7 +130,7 @@ static class Program break; default: System.Console.WriteLine("This should not happen..."); - Environment.Exit(90); + Environment.Exit(4); break; } },