From e4148954d28561344d6323782edac8d7f2bf4e1a Mon Sep 17 00:00:00 2001 From: Danil Kislov Date: Fri, 15 Mar 2019 13:44:36 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A2=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D0=BC?= =?UTF-8?q?=D0=BE=D0=B6=D0=B5=D0=BC=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D1=8F=D1=82=D1=8C=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=D1=80=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CommitWorks/BuzzwordReplacer.cs | 45 ++++++++ JiraTimeBotForm/Configuration/Settings.cs | 1 + JiraTimeBotForm/JiraIntegration/JiraApi.cs | 8 +- JiraTimeBotForm/JiraTimeBotForm.csproj | 1 + JiraTimeBotForm/Job.cs | 9 +- .../TaskTime/TaskTimeDiscoverer.cs | 103 +++++++++++++++--- JiraTimeBotForm/TaskTime/TaskTimeItem.cs | 1 + .../TasksProcessors/WorkLogTasksProcessor.cs | 2 +- JiraTimeBotForm/frmMain.Designer.cs | 16 ++- JiraTimeBotForm/frmMain.cs | 34 +++--- 10 files changed, 179 insertions(+), 41 deletions(-) create mode 100644 JiraTimeBotForm/CommitWorks/BuzzwordReplacer.cs diff --git a/JiraTimeBotForm/CommitWorks/BuzzwordReplacer.cs b/JiraTimeBotForm/CommitWorks/BuzzwordReplacer.cs new file mode 100644 index 0000000..a56cccd --- /dev/null +++ b/JiraTimeBotForm/CommitWorks/BuzzwordReplacer.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace JiraTimeBotForm.CommitWorks +{ + public class BuzzwordReplacer + { + public string FixBuzzwords(string commitMessage) + { + Dictionary buzzReplace = new Dictionary() + { + {"fix", "исправление"}, + {"up", "обновил"}, + {"init", "начало"}, + {"build", "сборка"}, + {"namespace", "неймспейс"} + }; + + foreach (var buzzReplaceItm in buzzReplace) + { + commitMessage = ReplaceCaseInsensitive(commitMessage, $" {buzzReplaceItm.Key} ", $" {buzzReplaceItm.Value} "); + commitMessage = ReplaceCaseInsensitive(commitMessage, $" {buzzReplaceItm.Key}.", $" {buzzReplaceItm.Value}."); + commitMessage = ReplaceCaseInsensitive(commitMessage, $" {buzzReplaceItm.Key},", $" {buzzReplaceItm.Value},"); + if (commitMessage.StartsWith($"{buzzReplaceItm.Key}", StringComparison.InvariantCultureIgnoreCase)) + { + commitMessage = ReplaceCaseInsensitive(commitMessage, $"{buzzReplaceItm.Key} ", $"{buzzReplaceItm.Value} "); + } + } + + return commitMessage; + } + + private string ReplaceCaseInsensitive(string input, string search, string replacement){ + string result = Regex.Replace( + input, + Regex.Escape(search), + replacement.Replace("$","$$"), + RegexOptions.IgnoreCase + ); + return result; + } + + } +} diff --git a/JiraTimeBotForm/Configuration/Settings.cs b/JiraTimeBotForm/Configuration/Settings.cs index 0dd6d48..6505967 100644 --- a/JiraTimeBotForm/Configuration/Settings.cs +++ b/JiraTimeBotForm/Configuration/Settings.cs @@ -13,5 +13,6 @@ namespace JiraTimeBotForm.Configuration public string JiraPassword { get; set; } public TimeSpan ActivationTime { get; set; } public bool DummyMode { get; set; } + public bool AddCommentsToWorklog { get; set; } } } diff --git a/JiraTimeBotForm/JiraIntegration/JiraApi.cs b/JiraTimeBotForm/JiraIntegration/JiraApi.cs index 77cceae..a397818 100644 --- a/JiraTimeBotForm/JiraIntegration/JiraApi.cs +++ b/JiraTimeBotForm/JiraIntegration/JiraApi.cs @@ -33,7 +33,7 @@ namespace JiraTimeBotForm.JiraIntegration } } - public void SetTodayWorklog(List taskTimeItems, DateTime? date = null, bool dummy = false) + public void SetTodayWorklog(List taskTimeItems, DateTime? date = null, bool dummy = false, bool addCommentsToWorklog = false) { if (date == null) { @@ -86,7 +86,11 @@ namespace JiraTimeBotForm.JiraIntegration if (!hasTodayWorklog) { var timeSpentJira = $"{taskTimeItem.Time.TotalMinutes}m"; - var workLogToAdd = new Worklog(timeSpentJira, date.Value); + Worklog workLogToAdd = new Worklog(timeSpentJira, date.Value); + if (addCommentsToWorklog) + { + workLogToAdd = new Worklog(timeSpentJira, date.Value, taskTimeItem.Description); + } if (!dummy) { workLogToAdd = issue.AddWorklogAsync(workLogToAdd).Result; diff --git a/JiraTimeBotForm/JiraTimeBotForm.csproj b/JiraTimeBotForm/JiraTimeBotForm.csproj index 7f21a5a..f75af83 100644 --- a/JiraTimeBotForm/JiraTimeBotForm.csproj +++ b/JiraTimeBotForm/JiraTimeBotForm.csproj @@ -71,6 +71,7 @@ + diff --git a/JiraTimeBotForm/Job.cs b/JiraTimeBotForm/Job.cs index 38d8fa1..12b7ab0 100644 --- a/JiraTimeBotForm/Job.cs +++ b/JiraTimeBotForm/Job.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using JiraTimeBotForm.CommitWorks; using JiraTimeBotForm.Configuration; using JiraTimeBotForm.TaskProcessors; using JiraTimeBotForm.TasksProcessors; @@ -12,10 +13,12 @@ namespace JiraTimeBotForm { class Job { + private readonly BuzzwordReplacer _buzzwordReplacer; private readonly ILog _log; - public Job(ILog log) + public Job(BuzzwordReplacer buzzwordReplacer, ILog log) { + _buzzwordReplacer = buzzwordReplacer; _log = log; } @@ -28,9 +31,7 @@ namespace JiraTimeBotForm private void DoTheJobImpl(Settings settings, ITasksProcessor tasksProcessor, CancellationToken cancellationToken) { - var taskDiscoverer = new TaskTimeDiscoverer(_log); - - + var taskDiscoverer = new TaskTimeDiscoverer(_buzzwordReplacer, _log); int daysDiff = 0; if (tasksProcessor is MeetingProcessor) diff --git a/JiraTimeBotForm/TaskTime/TaskTimeDiscoverer.cs b/JiraTimeBotForm/TaskTime/TaskTimeDiscoverer.cs index 3dd54f2..fcb71a1 100644 --- a/JiraTimeBotForm/TaskTime/TaskTimeDiscoverer.cs +++ b/JiraTimeBotForm/TaskTime/TaskTimeDiscoverer.cs @@ -2,7 +2,10 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; +using System.Text.RegularExpressions; using System.Threading; +using JiraTimeBotForm.CommitWorks; using JiraTimeBotForm.Configuration; using Mercurial; @@ -10,10 +13,12 @@ namespace JiraTimeBotForm.TaskTime { public class TaskTimeDiscoverer: ITaskTimeDiscoverer { + private readonly BuzzwordReplacer _buzzwordReplacer; private readonly ILog _log; - public TaskTimeDiscoverer(ILog log = null) + public TaskTimeDiscoverer(BuzzwordReplacer buzzwordReplacer, ILog log = null) { + _buzzwordReplacer = buzzwordReplacer; _log = log; } @@ -23,8 +28,7 @@ namespace JiraTimeBotForm.TaskTime date = date.GetValueOrDefault(DateTime.Now.Date); - var workTasks = new List(); - + var workTasks = new List(); foreach (var repoDirectory in Directory.GetDirectories(settings.RepositoryPath)) { if (cancellationToken.IsCancellationRequested) @@ -42,7 +46,8 @@ namespace JiraTimeBotForm.TaskTime var logCommand = new LogCommand { Date = date, - Users = { settings.MercurialAuthorEmail } + Users = { settings.MercurialAuthorEmail }, + AdditionalArguments = { "--encoding=utf-8"}, }; var log = repo.Log(logCommand); @@ -54,18 +59,21 @@ namespace JiraTimeBotForm.TaskTime return workTimeItems; } - if (!changeset.Branch.Contains("-")) - { - continue; - } - //Пропускаем Close коммиты - if (changeset.CommitMessage.StartsWith($"Close {changeset.Branch} ", StringComparison.InvariantCultureIgnoreCase)) + var commitMessage = FixEncoding(changeset.CommitMessage); + if (IsNeedToSkip(changeset.Branch, commitMessage)) { continue; } + commitMessage = StripTechnicalInfo(commitMessage); + commitMessage = _buzzwordReplacer.FixBuzzwords(commitMessage); - workTasks.Add(changeset.Branch); - _log?.Trace($" - Найден changeset: {changeset.Timestamp} - {changeset.Branch} - {changeset.AuthorEmailAddress}"); + workTasks.Add(new TaskTimeItem + { + Description = commitMessage, + Branch = changeset.Branch, + Commits = 1, + }); + _log?.Trace($" - Найден changeset: {changeset.Timestamp} - {changeset.Branch} - {changeset.AuthorEmailAddress} - {commitMessage}"); } } if (!workTasks.Any()) @@ -77,17 +85,24 @@ namespace JiraTimeBotForm.TaskTime int totalCommitsCount = workTasks.Count; //Нам нужно раскидать 480 минут в день. - foreach (var taskGroup in workTasks.GroupBy(f => f).OrderByDescending(f=>f.Count())) + foreach (var taskGroup in workTasks.GroupBy(f => f.Branch).OrderByDescending(f=>f.Count())) { int currentTaskCommits = taskGroup.Count(); int currentTaskTime = (int)RoundTo(settings.MinuterPerWorkDay / totalCommitsCount * currentTaskCommits); remainMinutes = remainMinutes - currentTaskTime; + StringBuilder sb = new StringBuilder(); + foreach (var task in taskGroup) + { + sb.AppendLine($"- {task.Description}"); + } + var taskTimeItem = new TaskTimeItem { Branch = taskGroup.Key, Time = TimeSpan.FromMinutes(currentTaskTime), Commits = taskGroup.Count(), + Description = sb.ToString() }; workTimeItems.Add(taskTimeItem); @@ -98,6 +113,67 @@ namespace JiraTimeBotForm.TaskTime return workTimeItems; } + + private string StripTechnicalInfo(string commitMessage) + { + if (!commitMessage.Contains("Signed-by:")) + { + return commitMessage; + } + + var arr = commitMessage.Split('\n'); + var sb = new StringBuilder(); + foreach (var itm in arr) + { + if (string.IsNullOrEmpty(itm)) + { + continue; + } + if (itm.StartsWith("Signed-by")) + { + continue; + } + if (itm.StartsWith("Jira:")) + { + continue; + } + + sb.AppendLine(itm); + } + + var message = sb.ToString(); + message = message.TrimEnd('\n'); + message = message.TrimEnd('\r'); + + return message; + } + + private bool IsNeedToSkip(string branch, string commitMessage) + { + if (!branch.Contains("-")) + { + return true; + } + + //Пропускаем Close и Merge коммиты + if (commitMessage.StartsWith($"Close {branch} ", StringComparison.InvariantCultureIgnoreCase) || + commitMessage.StartsWith($"Merge with ", StringComparison.InvariantCultureIgnoreCase)) + { + return true; + } + + return false; + } + + private string FixEncoding(string source) + { + //перекодируем сообщение - ибо оно криво забирается в 1252 + Encoding srcEncodingFormat = Encoding.GetEncoding("windows-1252"); + byte[] originalByteString = srcEncodingFormat.GetBytes(source); + var commitMessage = Encoding.UTF8.GetString(originalByteString); + return commitMessage; + } + private decimal RoundTo(decimal value, decimal to = 15, bool up = true) { if ((value % to) == 0) @@ -107,6 +183,5 @@ namespace JiraTimeBotForm.TaskTime return (value - (value % to)); } - } } diff --git a/JiraTimeBotForm/TaskTime/TaskTimeItem.cs b/JiraTimeBotForm/TaskTime/TaskTimeItem.cs index 9f7aa80..8e8ad77 100644 --- a/JiraTimeBotForm/TaskTime/TaskTimeItem.cs +++ b/JiraTimeBotForm/TaskTime/TaskTimeItem.cs @@ -4,6 +4,7 @@ namespace JiraTimeBotForm.TaskTime { public class TaskTimeItem { + public string Description { get; set; } public string Branch { get; set; } public TimeSpan Time { get; set; } public int Commits { get; set; } diff --git a/JiraTimeBotForm/TasksProcessors/WorkLogTasksProcessor.cs b/JiraTimeBotForm/TasksProcessors/WorkLogTasksProcessor.cs index 2c317f9..93cc81d 100644 --- a/JiraTimeBotForm/TasksProcessors/WorkLogTasksProcessor.cs +++ b/JiraTimeBotForm/TasksProcessors/WorkLogTasksProcessor.cs @@ -25,7 +25,7 @@ namespace JiraTimeBotForm.TasksProcessors } var jira = new JiraApi(settings, _log); - jira.SetTodayWorklog(taskTimes, dummy: settings.DummyMode); + jira.SetTodayWorklog(taskTimes, dummy: settings.DummyMode, addCommentsToWorklog: settings.AddCommentsToWorklog); } } } diff --git a/JiraTimeBotForm/frmMain.Designer.cs b/JiraTimeBotForm/frmMain.Designer.cs index 5ad9214..2db1b1c 100644 --- a/JiraTimeBotForm/frmMain.Designer.cs +++ b/JiraTimeBotForm/frmMain.Designer.cs @@ -48,6 +48,7 @@ this.txtDummyMode = new System.Windows.Forms.CheckBox(); this.btnMeeting = new System.Windows.Forms.Button(); this.btnCancel = new System.Windows.Forms.Button(); + this.chkAddComments = new System.Windows.Forms.CheckBox(); this.SuspendLayout(); // // actTime @@ -99,7 +100,6 @@ this.label2.Size = new System.Drawing.Size(82, 13); this.label2.TabIndex = 6; this.label2.Text = "Mercurial name:"; - this.label2.Click += new System.EventHandler(this.label2_Click); // // txtMercurialEmail // @@ -119,7 +119,7 @@ // // btnSave // - this.btnSave.Location = new System.Drawing.Point(62, 146); + this.btnSave.Location = new System.Drawing.Point(82, 169); this.btnSave.Name = "btnSave"; this.btnSave.Size = new System.Drawing.Size(75, 23); this.btnSave.TabIndex = 8; @@ -205,11 +205,22 @@ this.btnCancel.UseVisualStyleBackColor = true; this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); // + // chkAddComments + // + this.chkAddComments.AutoSize = true; + this.chkAddComments.Location = new System.Drawing.Point(61, 146); + this.chkAddComments.Name = "chkAddComments"; + this.chkAddComments.Size = new System.Drawing.Size(133, 17); + this.chkAddComments.TabIndex = 16; + this.chkAddComments.Text = "Добавлять описание"; + this.chkAddComments.UseVisualStyleBackColor = true; + // // frmMain // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(740, 292); + this.Controls.Add(this.chkAddComments); this.Controls.Add(this.btnCancel); this.Controls.Add(this.btnMeeting); this.Controls.Add(this.txtDummyMode); @@ -258,6 +269,7 @@ private System.Windows.Forms.CheckBox txtDummyMode; private System.Windows.Forms.Button btnMeeting; private System.Windows.Forms.Button btnCancel; + private System.Windows.Forms.CheckBox chkAddComments; } } diff --git a/JiraTimeBotForm/frmMain.cs b/JiraTimeBotForm/frmMain.cs index 712d545..6637179 100644 --- a/JiraTimeBotForm/frmMain.cs +++ b/JiraTimeBotForm/frmMain.cs @@ -1,16 +1,13 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Runtime.Remoting.Messaging; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; +using JiraTimeBotForm.CommitWorks; using JiraTimeBotForm.Configuration; -using JiraTimeBotForm.JiraIntegration; using JiraTimeBotForm.Passwords; using JiraTimeBotForm.TasksProcessors; -using JiraTimeBotForm.TaskTime; using Newtonsoft.Json; // This is the code for your desktop app. @@ -27,6 +24,7 @@ namespace JiraTimeBotForm private Job _job; private readonly IReadOnlyList _controls; private CancellationTokenSource _tokenSource; + private BuzzwordReplacer _buzzwordReplacer; private CancellationTokenSource GetTokenSource() { @@ -45,20 +43,23 @@ namespace JiraTimeBotForm InitializeComponent(); _settingsPath = Path.Combine(Application.UserAppDataPath, "settings.json"); _log = new Logger(txtLog); + _buzzwordReplacer = new BuzzwordReplacer(); trayMenu = new ContextMenu(); trayMenu.MenuItems.Add("Exit", OnExit); - - trayIcon = new NotifyIcon(); - trayIcon.Text = "JiraTimeBot"; - trayIcon.Icon = this.Icon;// new Icon(SystemIcons.WinLogo, 40, 40); - trayIcon.ContextMenu = trayMenu; + trayIcon = new NotifyIcon + { + Text = "JiraTimeBot", + Icon = this.Icon, + ContextMenu = trayMenu, + Visible = false, + + }; trayIcon.Click += btnTray_Click; trayIcon.DoubleClick += btnTray_Click; - trayIcon.Visible = false; - _job = new Job(_log); + _job = new Job(_buzzwordReplacer, _log); _controls = new Control[] { txtJiraLogin, txtJiraPassword, txtMercurialEmail, actTime, txtRepoPath, txtDummyMode, btnSave, btnStart, btnMeeting }; } @@ -90,7 +91,8 @@ namespace JiraTimeBotForm MercurialAuthorEmail = txtMercurialEmail.Text, ActivationTime = TimeSpan.Parse(actTime.Text), RepositoryPath = txtRepoPath.Text, - DummyMode = txtDummyMode.Checked + DummyMode = txtDummyMode.Checked, + AddCommentsToWorklog = chkAddComments.Checked, }; LockUnlock(false); @@ -145,6 +147,7 @@ namespace JiraTimeBotForm txtRepoPath.Text = settings.RepositoryPath; actTime.Text = settings.ActivationTime.ToString("hh\\:mm\\:ss"); txtDummyMode.Checked = settings.DummyMode; + chkAddComments.Checked = settings.AddCommentsToWorklog; } private async void btnStart_Click(object sender, EventArgs e) @@ -229,12 +232,7 @@ namespace JiraTimeBotForm LockUnlock(true); } - - private void label2_Click(object sender, EventArgs e) - { - - } - + private void btnCancel_Click(object sender, EventArgs e) { _tokenSource.Cancel();