Теперь можем добавлять комментарии

This commit is contained in:
Danil Kislov
2019-03-15 13:44:36 +03:00
parent 119670e072
commit e4148954d2
10 changed files with 179 additions and 41 deletions
@@ -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<string, string> buzzReplace = new Dictionary<string, string>()
{
{"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;
}
}
}
@@ -13,5 +13,6 @@ namespace JiraTimeBotForm.Configuration
public string JiraPassword { get; set; } public string JiraPassword { get; set; }
public TimeSpan ActivationTime { get; set; } public TimeSpan ActivationTime { get; set; }
public bool DummyMode { get; set; } public bool DummyMode { get; set; }
public bool AddCommentsToWorklog { get; set; }
} }
} }
+6 -2
View File
@@ -33,7 +33,7 @@ namespace JiraTimeBotForm.JiraIntegration
} }
} }
public void SetTodayWorklog(List<TaskTimeItem> taskTimeItems, DateTime? date = null, bool dummy = false) public void SetTodayWorklog(List<TaskTimeItem> taskTimeItems, DateTime? date = null, bool dummy = false, bool addCommentsToWorklog = false)
{ {
if (date == null) if (date == null)
{ {
@@ -86,7 +86,11 @@ namespace JiraTimeBotForm.JiraIntegration
if (!hasTodayWorklog) if (!hasTodayWorklog)
{ {
var timeSpentJira = $"{taskTimeItem.Time.TotalMinutes}m"; 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) if (!dummy)
{ {
workLogToAdd = issue.AddWorklogAsync(workLogToAdd).Result; workLogToAdd = issue.AddWorklogAsync(workLogToAdd).Result;
+1
View File
@@ -71,6 +71,7 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="CommitWorks\BuzzwordReplacer.cs" />
<Compile Include="Extensions\Extensions.cs" /> <Compile Include="Extensions\Extensions.cs" />
<Compile Include="Job.cs" /> <Compile Include="Job.cs" />
<Compile Include="Logger.cs" /> <Compile Include="Logger.cs" />
+5 -4
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using JiraTimeBotForm.CommitWorks;
using JiraTimeBotForm.Configuration; using JiraTimeBotForm.Configuration;
using JiraTimeBotForm.TaskProcessors; using JiraTimeBotForm.TaskProcessors;
using JiraTimeBotForm.TasksProcessors; using JiraTimeBotForm.TasksProcessors;
@@ -12,10 +13,12 @@ namespace JiraTimeBotForm
{ {
class Job class Job
{ {
private readonly BuzzwordReplacer _buzzwordReplacer;
private readonly ILog _log; private readonly ILog _log;
public Job(ILog log) public Job(BuzzwordReplacer buzzwordReplacer, ILog log)
{ {
_buzzwordReplacer = buzzwordReplacer;
_log = log; _log = log;
} }
@@ -28,9 +31,7 @@ namespace JiraTimeBotForm
private void DoTheJobImpl(Settings settings, ITasksProcessor tasksProcessor, CancellationToken cancellationToken) private void DoTheJobImpl(Settings settings, ITasksProcessor tasksProcessor, CancellationToken cancellationToken)
{ {
var taskDiscoverer = new TaskTimeDiscoverer(_log); var taskDiscoverer = new TaskTimeDiscoverer(_buzzwordReplacer, _log);
int daysDiff = 0; int daysDiff = 0;
if (tasksProcessor is MeetingProcessor) if (tasksProcessor is MeetingProcessor)
+89 -14
View File
@@ -2,7 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using JiraTimeBotForm.CommitWorks;
using JiraTimeBotForm.Configuration; using JiraTimeBotForm.Configuration;
using Mercurial; using Mercurial;
@@ -10,10 +13,12 @@ namespace JiraTimeBotForm.TaskTime
{ {
public class TaskTimeDiscoverer: ITaskTimeDiscoverer public class TaskTimeDiscoverer: ITaskTimeDiscoverer
{ {
private readonly BuzzwordReplacer _buzzwordReplacer;
private readonly ILog _log; private readonly ILog _log;
public TaskTimeDiscoverer(ILog log = null) public TaskTimeDiscoverer(BuzzwordReplacer buzzwordReplacer, ILog log = null)
{ {
_buzzwordReplacer = buzzwordReplacer;
_log = log; _log = log;
} }
@@ -23,8 +28,7 @@ namespace JiraTimeBotForm.TaskTime
date = date.GetValueOrDefault(DateTime.Now.Date); date = date.GetValueOrDefault(DateTime.Now.Date);
var workTasks = new List<string>(); var workTasks = new List<TaskTimeItem>();
foreach (var repoDirectory in Directory.GetDirectories(settings.RepositoryPath)) foreach (var repoDirectory in Directory.GetDirectories(settings.RepositoryPath))
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
@@ -42,7 +46,8 @@ namespace JiraTimeBotForm.TaskTime
var logCommand = new LogCommand var logCommand = new LogCommand
{ {
Date = date, Date = date,
Users = { settings.MercurialAuthorEmail } Users = { settings.MercurialAuthorEmail },
AdditionalArguments = { "--encoding=utf-8"},
}; };
var log = repo.Log(logCommand); var log = repo.Log(logCommand);
@@ -54,18 +59,21 @@ namespace JiraTimeBotForm.TaskTime
return workTimeItems; return workTimeItems;
} }
if (!changeset.Branch.Contains("-")) var commitMessage = FixEncoding(changeset.CommitMessage);
{ if (IsNeedToSkip(changeset.Branch, commitMessage))
continue;
}
//Пропускаем Close коммиты
if (changeset.CommitMessage.StartsWith($"Close {changeset.Branch} ", StringComparison.InvariantCultureIgnoreCase))
{ {
continue; continue;
} }
commitMessage = StripTechnicalInfo(commitMessage);
commitMessage = _buzzwordReplacer.FixBuzzwords(commitMessage);
workTasks.Add(changeset.Branch); workTasks.Add(new TaskTimeItem
_log?.Trace($" - Найден changeset: {changeset.Timestamp} - {changeset.Branch} - {changeset.AuthorEmailAddress}"); {
Description = commitMessage,
Branch = changeset.Branch,
Commits = 1,
});
_log?.Trace($" - Найден changeset: {changeset.Timestamp} - {changeset.Branch} - {changeset.AuthorEmailAddress} - {commitMessage}");
} }
} }
if (!workTasks.Any()) if (!workTasks.Any())
@@ -77,17 +85,24 @@ namespace JiraTimeBotForm.TaskTime
int totalCommitsCount = workTasks.Count; int totalCommitsCount = workTasks.Count;
//Нам нужно раскидать 480 минут в день. //Нам нужно раскидать 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 currentTaskCommits = taskGroup.Count();
int currentTaskTime = (int)RoundTo(settings.MinuterPerWorkDay / totalCommitsCount * currentTaskCommits); int currentTaskTime = (int)RoundTo(settings.MinuterPerWorkDay / totalCommitsCount * currentTaskCommits);
remainMinutes = remainMinutes - currentTaskTime; remainMinutes = remainMinutes - currentTaskTime;
StringBuilder sb = new StringBuilder();
foreach (var task in taskGroup)
{
sb.AppendLine($"- {task.Description}");
}
var taskTimeItem = new TaskTimeItem var taskTimeItem = new TaskTimeItem
{ {
Branch = taskGroup.Key, Branch = taskGroup.Key,
Time = TimeSpan.FromMinutes(currentTaskTime), Time = TimeSpan.FromMinutes(currentTaskTime),
Commits = taskGroup.Count(), Commits = taskGroup.Count(),
Description = sb.ToString()
}; };
workTimeItems.Add(taskTimeItem); workTimeItems.Add(taskTimeItem);
@@ -98,6 +113,67 @@ namespace JiraTimeBotForm.TaskTime
return workTimeItems; 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) private decimal RoundTo(decimal value, decimal to = 15, bool up = true)
{ {
if ((value % to) == 0) if ((value % to) == 0)
@@ -107,6 +183,5 @@ namespace JiraTimeBotForm.TaskTime
return (value - (value % to)); return (value - (value % to));
} }
} }
} }
+1
View File
@@ -4,6 +4,7 @@ namespace JiraTimeBotForm.TaskTime
{ {
public class TaskTimeItem public class TaskTimeItem
{ {
public string Description { get; set; }
public string Branch { get; set; } public string Branch { get; set; }
public TimeSpan Time { get; set; } public TimeSpan Time { get; set; }
public int Commits { get; set; } public int Commits { get; set; }
@@ -25,7 +25,7 @@ namespace JiraTimeBotForm.TasksProcessors
} }
var jira = new JiraApi(settings, _log); var jira = new JiraApi(settings, _log);
jira.SetTodayWorklog(taskTimes, dummy: settings.DummyMode); jira.SetTodayWorklog(taskTimes, dummy: settings.DummyMode, addCommentsToWorklog: settings.AddCommentsToWorklog);
} }
} }
} }
+14 -2
View File
@@ -48,6 +48,7 @@
this.txtDummyMode = new System.Windows.Forms.CheckBox(); this.txtDummyMode = new System.Windows.Forms.CheckBox();
this.btnMeeting = new System.Windows.Forms.Button(); this.btnMeeting = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button(); this.btnCancel = new System.Windows.Forms.Button();
this.chkAddComments = new System.Windows.Forms.CheckBox();
this.SuspendLayout(); this.SuspendLayout();
// //
// actTime // actTime
@@ -99,7 +100,6 @@
this.label2.Size = new System.Drawing.Size(82, 13); this.label2.Size = new System.Drawing.Size(82, 13);
this.label2.TabIndex = 6; this.label2.TabIndex = 6;
this.label2.Text = "Mercurial name:"; this.label2.Text = "Mercurial name:";
this.label2.Click += new System.EventHandler(this.label2_Click);
// //
// txtMercurialEmail // txtMercurialEmail
// //
@@ -119,7 +119,7 @@
// //
// btnSave // 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.Name = "btnSave";
this.btnSave.Size = new System.Drawing.Size(75, 23); this.btnSave.Size = new System.Drawing.Size(75, 23);
this.btnSave.TabIndex = 8; this.btnSave.TabIndex = 8;
@@ -205,11 +205,22 @@
this.btnCancel.UseVisualStyleBackColor = true; this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); 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 // frmMain
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(740, 292); this.ClientSize = new System.Drawing.Size(740, 292);
this.Controls.Add(this.chkAddComments);
this.Controls.Add(this.btnCancel); this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnMeeting); this.Controls.Add(this.btnMeeting);
this.Controls.Add(this.txtDummyMode); this.Controls.Add(this.txtDummyMode);
@@ -258,6 +269,7 @@
private System.Windows.Forms.CheckBox txtDummyMode; private System.Windows.Forms.CheckBox txtDummyMode;
private System.Windows.Forms.Button btnMeeting; private System.Windows.Forms.Button btnMeeting;
private System.Windows.Forms.Button btnCancel; private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.CheckBox chkAddComments;
} }
} }
+16 -18
View File
@@ -1,16 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using JiraTimeBotForm.CommitWorks;
using JiraTimeBotForm.Configuration; using JiraTimeBotForm.Configuration;
using JiraTimeBotForm.JiraIntegration;
using JiraTimeBotForm.Passwords; using JiraTimeBotForm.Passwords;
using JiraTimeBotForm.TasksProcessors; using JiraTimeBotForm.TasksProcessors;
using JiraTimeBotForm.TaskTime;
using Newtonsoft.Json; using Newtonsoft.Json;
// This is the code for your desktop app. // This is the code for your desktop app.
@@ -27,6 +24,7 @@ namespace JiraTimeBotForm
private Job _job; private Job _job;
private readonly IReadOnlyList<Control> _controls; private readonly IReadOnlyList<Control> _controls;
private CancellationTokenSource _tokenSource; private CancellationTokenSource _tokenSource;
private BuzzwordReplacer _buzzwordReplacer;
private CancellationTokenSource GetTokenSource() private CancellationTokenSource GetTokenSource()
{ {
@@ -45,20 +43,23 @@ namespace JiraTimeBotForm
InitializeComponent(); InitializeComponent();
_settingsPath = Path.Combine(Application.UserAppDataPath, "settings.json"); _settingsPath = Path.Combine(Application.UserAppDataPath, "settings.json");
_log = new Logger(txtLog); _log = new Logger(txtLog);
_buzzwordReplacer = new BuzzwordReplacer();
trayMenu = new ContextMenu(); trayMenu = new ContextMenu();
trayMenu.MenuItems.Add("Exit", OnExit); 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.Click += btnTray_Click;
trayIcon.DoubleClick += 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 }; _controls = new Control[] { txtJiraLogin, txtJiraPassword, txtMercurialEmail, actTime, txtRepoPath, txtDummyMode, btnSave, btnStart, btnMeeting };
} }
@@ -90,7 +91,8 @@ namespace JiraTimeBotForm
MercurialAuthorEmail = txtMercurialEmail.Text, MercurialAuthorEmail = txtMercurialEmail.Text,
ActivationTime = TimeSpan.Parse(actTime.Text), ActivationTime = TimeSpan.Parse(actTime.Text),
RepositoryPath = txtRepoPath.Text, RepositoryPath = txtRepoPath.Text,
DummyMode = txtDummyMode.Checked DummyMode = txtDummyMode.Checked,
AddCommentsToWorklog = chkAddComments.Checked,
}; };
LockUnlock(false); LockUnlock(false);
@@ -145,6 +147,7 @@ namespace JiraTimeBotForm
txtRepoPath.Text = settings.RepositoryPath; txtRepoPath.Text = settings.RepositoryPath;
actTime.Text = settings.ActivationTime.ToString("hh\\:mm\\:ss"); actTime.Text = settings.ActivationTime.ToString("hh\\:mm\\:ss");
txtDummyMode.Checked = settings.DummyMode; txtDummyMode.Checked = settings.DummyMode;
chkAddComments.Checked = settings.AddCommentsToWorklog;
} }
private async void btnStart_Click(object sender, EventArgs e) private async void btnStart_Click(object sender, EventArgs e)
@@ -229,12 +232,7 @@ namespace JiraTimeBotForm
LockUnlock(true); LockUnlock(true);
} }
private void label2_Click(object sender, EventArgs e)
{
}
private void btnCancel_Click(object sender, EventArgs e) private void btnCancel_Click(object sender, EventArgs e)
{ {
_tokenSource.Cancel(); _tokenSource.Cancel();