private void processSystemNotes(MergeRequestDescriptor mrd, User currentUser, List <Note> notes) { TimeSpan span = TimeSpan.Zero; foreach (Note note in notes) { if (note.Author.Id == currentUser.Id) { Match m = spentTimeRe.Match(note.Body); if (!m.Success) { continue; } int hours = m.Groups["hours"].Success ? int.Parse(m.Groups["hours"].Value) : 0; int minutes = m.Groups["minutes"].Success ? int.Parse(m.Groups["minutes"].Value) : 0; int seconds = m.Groups["seconds"].Success ? int.Parse(m.Groups["seconds"].Value) : 0; if (m.Groups["operation"].Value == "added") { span += new TimeSpan(hours, minutes, seconds); } else { Debug.Assert(m.Groups["operation"].Value == "subtracted"); span -= new TimeSpan(hours, minutes, seconds); } } } MergeRequestTimes[mrd] = span; PostLoadTotalTime?.Invoke(mrd); }
async internal Task ModifyNoteBodyAsync(MergeRequestDescriptor mrd, string discussionId, int noteId, string body) { GitLabClient client = new GitLabClient(mrd.HostName, Tools.Tools.GetAccessToken(mrd.HostName, Settings)); try { await client.RunAsync(async (gitlab) => await gitlab.Projects.Get(mrd.ProjectName).MergeRequests.Get(mrd.IId). Discussions.Get(discussionId).ModifyNoteTaskAsync(noteId, new ModifyDiscussionNoteParameters { Type = ModifyDiscussionNoteParameters.ModificationType.Body, Body = body })); } catch (Exception ex) { Debug.Assert(!(ex is GitLabClientCancelled)); if (ex is GitLabSharpException || ex is GitLabRequestException) { ExceptionHandlers.Handle(ex, "Cannot update discussion text"); throw new OperatorException(ex); } throw; } }
async private void ButtonTimeEdit_Click(object sender, EventArgs s) { TimeSpan oldSpan = TimeSpan.Parse(labelTimeTrackingTrackedTime.Text); using (EditTimeForm form = new EditTimeForm(oldSpan)) { if (form.ShowDialog() == DialogResult.OK) { TimeSpan newSpan = form.GetTimeSpan(); bool add = newSpan > oldSpan; TimeSpan diff = add ? newSpan - oldSpan : oldSpan - newSpan; if (diff != TimeSpan.Zero) { MergeRequestDescriptor mrd = _workflow.State.MergeRequestDescriptor; await _timeTrackingManager.AddSpanAsync(add, diff, mrd); updateTotalTime(_workflow.State.MergeRequestDescriptor); labelWorkflowStatus.Text = "Total spent time updated"; Trace.TraceInformation(String.Format("[MainForm] Total time for MR {0} (project {1}) changed to {2}", mrd.IId, mrd.ProjectName, diff.ToString())); } } } }
async internal Task ResolveDiscussionAsync(MergeRequestDescriptor mrd, string discussionId, bool resolved) { GitLabClient client = new GitLabClient(mrd.HostName, Tools.Tools.GetAccessToken(mrd.HostName, Settings)); try { await client.RunAsync(async (gitlab) => await gitlab.Projects.Get(mrd.ProjectName).MergeRequests.Get(mrd.IId). Discussions.Get(discussionId).ResolveTaskAsync( new ResolveThreadParameters { Resolve = resolved })); } catch (Exception ex) { Debug.Assert(!(ex is GitLabClientCancelled)); if (ex is GitLabSharpException || ex is GitLabRequestException) { ExceptionHandlers.Handle(ex, "Cannot toggle 'Resolved' state of a discussion"); throw new OperatorException(ex); } throw; } }
private void onTotalTimeLoaded(MergeRequestDescriptor mrd) { updateTotalTime(mrd); labelWorkflowStatus.Text = "Total spent time loaded"; Trace.TraceInformation(String.Format("[MainForm.Workflow] Total spent time loaded")); }
async internal Task AddSpanAsync(bool add, TimeSpan span, MergeRequestDescriptor mrd) { GitLabClient client = new GitLabClient(mrd.HostName, Tools.Tools.GetAccessToken(mrd.HostName, Settings)); try { await client.RunAsync(async (gitlab) => await gitlab.Projects.Get(mrd.ProjectName).MergeRequests.Get(mrd.IId).AddSpentTimeAsync( new AddSpentTimeParameters { Add = add, Span = span })); } catch (Exception ex) { Debug.Assert(!(ex is GitLabClientCancelled)); if (ex is GitLabSharpException || ex is GitLabRequestException) { ExceptionHandlers.Handle(ex, "Cannot send tracked time to GitLab"); throw new OperatorException(ex); } throw; } }
async internal Task ReplyAsync(MergeRequestDescriptor mrd, string discussionId, string body) { GitLabClient client = new GitLabClient(mrd.HostName, Tools.Tools.GetAccessToken(mrd.HostName, Settings)); try { await client.RunAsync(async (gitlab) => await gitlab.Projects.Get(mrd.ProjectName).MergeRequests.Get(mrd.IId). Discussions.Get(discussionId).CreateNewNoteTaskAsync( new CreateNewNoteParameters { Body = body })); } catch (Exception ex) { Debug.Assert(!(ex is GitLabClientCancelled)); if (ex is GitLabSharpException || ex is GitLabRequestException) { ExceptionHandlers.Handle(ex, "Cannot create a reply to discussion"); throw new OperatorException(ex); } throw; } }
async public Task <List <Discussion> > GetDiscussionsAsync(MergeRequestDescriptor mrd) { try { return(await DiscussionOperator.GetDiscussionsAsync(mrd)); } catch (OperatorException) { throw new DiscussionManagerException(); } }
private static void submitDiscussion(Snapshot snapshot, DiffToolInfo diffToolInfo, DiffPosition position, string body, bool includeContext) { if (body.Length == 0) { MessageBox.Show("Discussion text cannot be empty", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } NewDiscussionParameters parameters = new NewDiscussionParameters { Body = body, Position = includeContext ? createPositionParameters(position) : new Nullable <PositionParameters>() }; MergeRequestDescriptor mergeRequestDescriptor = new MergeRequestDescriptor { HostName = snapshot.Host, ProjectName = snapshot.Project, IId = snapshot.MergeRequestIId }; UserDefinedSettings settings = new UserDefinedSettings(false); DiscussionManager manager = new DiscussionManager(settings); DiscussionCreator creator = manager.GetDiscussionCreator(mergeRequestDescriptor); try { creator.CreateDiscussionAsync(parameters).Wait(); } catch (DiscussionCreatorException ex) { Trace.TraceInformation( "Additional information about exception:\n" + "Position: {0}\n" + "Include context: {1}\n" + "Snapshot refs: {2}\n" + "DiffToolInfo: {3}\n" + "Body:\n{4}", position.ToString(), includeContext.ToString(), snapshot.Refs.ToString(), diffToolInfo.ToString(), body); if (!ex.Handled) { throw; } } }
async public Task AddSpanAsync(bool add, TimeSpan span, MergeRequestDescriptor mrd) { await TimeTrackingOperator.AddSpanAsync(add, span, mrd); if (add) { MergeRequestTimes[mrd] += span; } else { MergeRequestTimes[mrd] -= span; } }
/// <summary> /// Throws: /// ArgumentException /// </summary> internal DiscussionsForm(MergeRequestDescriptor mrd, string mrTitle, User mergeRequestAuthor, IGitRepository gitRepository, int diffContextDepth, ColorScheme colorScheme, List <Discussion> discussions, DiscussionManager manager, User currentUser, Func <MergeRequestDescriptor, Task> updateGitRepository) { _mergeRequestDescriptor = mrd; _mergeRequestTitle = mrTitle; _mergeRequestAuthor = mergeRequestAuthor; _gitRepository = gitRepository; _diffContextDepth = diffContextDepth; _colorScheme = colorScheme; _manager = manager; _updateGitRepository = updateGitRepository; _currentUser = currentUser; if (_currentUser.Id == 0) { throw new ArgumentException("Bad user Id"); } InitializeComponent(); DiscussionFilterState state = new DiscussionFilterState { ByCurrentUserOnly = false, ByAnswers = FilterByAnswers.Answered | FilterByAnswers.Unanswered, ByResolution = FilterByResolution.Resolved | FilterByResolution.NotResolved }; DisplayFilter = new DiscussionFilter(_currentUser, _mergeRequestAuthor, state); SystemFilter = new DiscussionFilter(_currentUser, _mergeRequestAuthor, state); FilterPanel = new DiscussionFilterPanel(DisplayFilter.Filter, () => { DisplayFilter.Filter = FilterPanel.Filter; updateLayout(null); }); ActionsPanel = new DiscussionActionsPanel(async() => await onRefresh()); Controls.Add(FilterPanel); Controls.Add(ActionsPanel); if (!renderDiscussions(discussions)) { throw new NoDiscussionsToShow(); } }
async internal Task CreateNoteAsync(MergeRequestDescriptor mrd, CreateNewNoteParameters parameters) { GitLabClient client = new GitLabClient(mrd.HostName, Tools.Tools.GetAccessToken(mrd.HostName, Settings)); try { await client.RunAsync(async (gitlab) => await gitlab.Projects.Get(mrd.ProjectName).MergeRequests.Get(mrd.IId). Notes.CreateNewTaskAsync(parameters)); } catch (Exception ex) { Debug.Assert(!(ex is GitLabClientCancelled)); if (ex is GitLabSharpException || ex is GitLabRequestException) { ExceptionHandlers.Handle(ex, "Cannot create a note"); throw new OperatorException(ex); } throw; } }
async internal Task <Discussion> GetDiscussionAsync(MergeRequestDescriptor mrd, string discussionId) { GitLabClient client = new GitLabClient(mrd.HostName, Tools.Tools.GetAccessToken(mrd.HostName, Settings)); try { return((Discussion)(await client.RunAsync(async(gitlab) => await gitlab.Projects.Get(mrd.ProjectName).MergeRequests.Get(mrd.IId). Discussions.Get(discussionId).LoadTaskAsync()))); } catch (Exception ex) { Debug.Assert(!(ex is GitLabClientCancelled)); if (ex is GitLabSharpException || ex is GitLabRequestException) { ExceptionHandlers.Handle(ex, "Cannot load discussion from GitLab"); throw new OperatorException(ex); } throw; } }
/// <summary> /// Load Versions from GitLab and cache them /// </summary> async private Task cacheVersionsAsync(string hostname, MergeRequest mergeRequest) { Debug.Assert(InternalDetails.GetProjectKey(mergeRequest.Id).ProjectId != 0); MergeRequestDescriptor mrd = new MergeRequestDescriptor { HostName = hostname, ProjectName = InternalDetails.GetProjectName(getProjectKey(hostname, mergeRequest.Project_Id)), IId = mergeRequest.IId }; Version latestVersion; try { latestVersion = await Operator.GetLatestVersionAsync(mrd); } catch (OperatorException ex) { ExceptionHandlers.Handle(ex, String.Format("Cannot load latest version for MR Id {0}", mergeRequest.Id)); return; // silent return } DateTime previouslyCachedTimestamp = InternalDetails.GetLatestChangeTimestamp(mergeRequest.Id); InternalDetails.SetLatestChangeTimestamp(mergeRequest.Id, latestVersion.Created_At); if (previouslyCachedTimestamp > latestVersion.Created_At) { Debug.Assert(false); Trace.TraceWarning("[WorkflowDetailsCache] Latest version is older than a previous one"); } Trace.TraceInformation(String.Format( "[WorkflowDetailsCache] Latest version of merge request with Id {0} has timestamp {1} (was {2} before update)", mergeRequest.Id, latestVersion.Created_At.ToLocalTime().ToString(), previouslyCachedTimestamp.ToLocalTime().ToString())); }
async internal Task <Version> GetLatestVersionAsync(MergeRequestDescriptor mrd) { GitLabClient client = new GitLabClient(mrd.HostName, Tools.Tools.GetAccessToken(mrd.HostName, Settings)); try { List <Version> versions = (List <Version>)(await client.RunAsync(async(gitlab) => await gitlab.Projects.Get(mrd.ProjectName).MergeRequests.Get(mrd.IId). Versions.LoadTaskAsync(new PageFilter { PerPage = 1, PageNumber = 1 }))); return(versions.Count > 0 ? versions[0] : new Version()); } catch (Exception ex) { Debug.Assert(!(ex is GitLabClientCancelled)); if (ex is GitLabSharpException || ex is GitLabRequestException) { ExceptionHandlers.Handle(ex, "Cannot load the latest version from GitLab"); throw new OperatorException(ex); } throw; } }
internal DiscussionEditor(MergeRequestDescriptor mrd, string discussionId, DiscussionOperator discussionOperator) { DiscussionOperator = discussionOperator; MergeRequestDescriptor = mrd; DiscussionId = discussionId; }
internal RemoteProjectChecker(MergeRequestDescriptor mrd, UpdateOperator updateOperator) { MergeRequestDescriptor = mrd; Operator = updateOperator; }
public DiscussionEditor GetDiscussionEditor(MergeRequestDescriptor mrd, string discussionId) { return(new DiscussionEditor(mrd, discussionId, DiscussionOperator)); }
internal DiscussionCreator(MergeRequestDescriptor mrd, DiscussionOperator discussionOperator) { DiscussionOperator = discussionOperator; MergeRequestDescriptor = mrd; }
/// <summary> /// Makes a request to GitLab to detect if there are project changes caused by new versions of a merge request /// </summary> public IInstantProjectChecker GetRemoteProjectChecker(MergeRequestDescriptor mrd) { return(new RemoteProjectChecker(mrd, new UpdateOperator(Settings))); }
internal TimeTracker(MergeRequestDescriptor mrd, OnTrackerStoppedAsync onTrackerStopped) { MergeRequestDescriptor = mrd; OnStopped = onTrackerStopped; Stopwatch = new Stopwatch(); }
public TimeTracker GetTracker(MergeRequestDescriptor mrd) { return(new TimeTracker(mrd, async(span, descriptor) => { await AddSpanAsync(true, span, descriptor); })); }
public DiscussionCreator GetDiscussionCreator(MergeRequestDescriptor mrd) { return(new DiscussionCreator(mrd, DiscussionOperator)); }
public TimeSpan GetTotalTime(MergeRequestDescriptor mrd) { return(MergeRequestTimes.ContainsKey(mrd) ? MergeRequestTimes[mrd] : default(TimeSpan)); }