예제 #1
0
        async private Task <bool> createMergeRequestWithoutPosition(NewDiscussionParameters parameters)
        {
            if (_discussionOperator == null)
            {
                return(false);
            }

            Debug.Assert(parameters.Position != null);

            Trace.TraceInformation("[DicsussionCreator] Reporting a discussion without Position (fallback)");

            NewDiscussionParameters newDiscussionParameters = new NewDiscussionParameters(
                getFallbackInfo(parameters.Position.Value) + "<br>" + parameters.Body, null);

            try
            {
                await _discussionOperator.CreateDiscussionAsync(_mergeRequestKey, newDiscussionParameters);
            }
            catch (OperatorException ex)
            {
                ExceptionHandlers.Handle("Cannot create a discussion (again)", ex);
                return(false);
            }
            return(true);
        }
예제 #2
0
        async private Task deleteMostRecentNote(NewDiscussionParameters parameters)
        {
            Debug.Assert(parameters.Position != null);

            Trace.TraceInformation("[DicsussionCreator] Looking up for a note with bad position...");

            IEnumerable <Discussion> discussions;

            try
            {
                discussions = await _discussionOperator.GetDiscussionsAsync(_mergeRequestKey, null);
            }
            catch (OperatorException ex)
            {
                ExceptionHandlers.Handle("Cannot obtain discussions", ex);
                return;
            }

            int?deletedNoteId = new int?();

            foreach (Discussion discussion in discussions.Reverse())
            {
                if (discussion.Notes.Count() == 1)
                {
                    DiscussionNote note = discussion.Notes.First();
                    if (_currentUser != null &&
                        note != null &&
                        note.Type == "DiffNote" &&
                        note.Author != null &&
                        note.Author.Id == _currentUser.Id &&
                        note.Body == parameters.Body)
                    {
                        Trace.TraceInformation(
                            "[DicsussionCreator] Deleting discussion note." +
                            " Id: {0}, Author.Username: {1}, Created_At: {2}, Body:\n{3}",
                            note.Id.ToString(), note.Author.Username, note.Created_At, note.Body);

                        try
                        {
                            await _discussionOperator.DeleteNoteAsync(_mergeRequestKey, note.Id);

                            deletedNoteId = note.Id;
                        }
                        catch (OperatorException ex)
                        {
                            ExceptionHandlers.Handle("Cannot delete discussion note", ex);
                        }

                        break;
                    }
                }
            }

            string message = deletedNoteId.HasValue
            ? String.Format("[DicsussionCreator] Deleted note with Id {0}", deletedNoteId.Value)
            : "Could not find a note to delete (or could not delete it)";

            Trace.TraceInformation(message);
        }
예제 #3
0
 internal Task <Discussion> CreateDiscussionAsync(MergeRequestKey mrk, NewDiscussionParameters parameters)
 {
     return(callWithSharedClient(
                async(client) =>
                await OperatorCallWrapper.Call(
                    async() =>
                    (Discussion)await client.RunAsync(
                        async(gl) =>
                        await gl.Projects.Get(mrk.ProjectKey.ProjectName).MergeRequests.Get(mrk.IId).
                        Discussions.CreateNewTaskAsync(parameters)))));
 }
예제 #4
0
        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;
                }
            }
        }
예제 #5
0
        async public Task CreateDiscussionAsync(NewDiscussionParameters parameters)
        {
            try
            {
                await DiscussionOperator.CreateDiscussionAsync(MergeRequestDescriptor, parameters);
            }
            catch (OperatorException ex)
            {
                bool handled = await handleGitlabError(parameters, ex);

                throw new DiscussionCreatorException(handled);
            }
        }
예제 #6
0
        async public Task CreateDiscussionAsync(NewDiscussionParameters parameters, bool revertOnError)
        {
            try
            {
                await _discussionOperator.CreateDiscussionAsync(_mergeRequestKey, parameters);
            }
            catch (OperatorException ex)
            {
                bool handled = await handleGitlabError(parameters, ex, revertOnError);

                throw new DiscussionCreatorException(handled, ex);
            }
        }
예제 #7
0
        async private Task <bool> handleGitlabError(NewDiscussionParameters parameters, OperatorException ex,
                                                    bool revertOnError)
        {
            if (ex == null)
            {
                Trace.TraceWarning("[DiscussionCreator] An exception with null value was caught");
                return(false);
            }

            if (parameters.Position == null)
            {
                Trace.TraceWarning("[DiscussionCreator] Unexpected situation at GitLab");
                return(false);
            }

            if (ex.InnerException is GitLabRequestException rx)
            {
                if (rx.InnerException is System.Net.WebException wx)
                {
                    if (wx.Response == null)
                    {
                        Trace.TraceWarning("[DiscussionCreator] Null Response in WebException");
                        return(false);
                    }

                    System.Net.HttpWebResponse response = wx.Response as System.Net.HttpWebResponse;
                    if (response.StatusCode == System.Net.HttpStatusCode.BadRequest)
                    {
                        // Something went wrong at the GitLab, let's report a discussion without Position
                        return(await createMergeRequestWithoutPosition(parameters));
                    }
                    else if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
                    {
                        // Something went wrong at the GitLab
                        if (revertOnError)
                        {
                            await deleteMostRecentNote(parameters);

                            return(await createMergeRequestWithoutPosition(parameters));
                        }
                        return(true);
                    }
                }
            }

            return(false);
        }
예제 #8
0
        async private Task submitDiscussionAsync(MatchInfo matchInfo, Snapshot snapshot, DiffPosition position,
                                                 string body, bool includeContext)
        {
            if (body.Length == 0)
            {
                MessageBox.Show("Discussion text cannot be empty", "Warning",
                                MessageBoxButtons.OK, MessageBoxIcon.Exclamation,
                                MessageBoxDefaultButton.Button1, MessageBoxOptions.ServiceNotification);
                return;
            }

            NewDiscussionParameters parameters = new NewDiscussionParameters(
                body, includeContext ? createPositionParameters(position) : new PositionParameters?());

            MergeRequestKey    mrk            = getMergeRequestKey(snapshot);
            GitLabInstance     gitLabInstance = new GitLabInstance(snapshot.Host, Program.Settings);
            IDiscussionCreator creator        = Shortcuts.GetDiscussionCreator(
                gitLabInstance, _modificationListener, mrk, _currentUser);

            try
            {
                await creator.CreateDiscussionAsync(parameters, true);
            }
            catch (DiscussionCreatorException ex)
            {
                Trace.TraceInformation(
                    "Additional information about exception:\n" +
                    "Position: {0}\n" +
                    "Include context: {1}\n" +
                    "Snapshot refs: {2}\n" +
                    "MatchInfo: {3}\n" +
                    "Body:\n{4}",
                    position.ToString(),
                    includeContext.ToString(),
                    snapshot.Refs.ToString(),
                    matchInfo.ToString(),
                    body);

                if (!ex.Handled)
                {
                    throw;
                }
            }
        }
예제 #9
0
        async private Task <bool> createMergeRequestWithoutPosition(NewDiscussionParameters parameters)
        {
            Debug.Assert(parameters.Position.HasValue);

            Trace.TraceInformation("Reporting a discussion without Position (fallback)");

            parameters.Body     = getFallbackInfo(parameters.Position.Value) + "<br>" + parameters.Body;
            parameters.Position = null;

            try
            {
                await DiscussionOperator.CreateDiscussionAsync(MergeRequestDescriptor, parameters);
            }
            catch (OperatorException ex)
            {
                ExceptionHandlers.Handle(ex, "Cannot create a discussion (again)");
                return(false);
            }
            return(true);
        }
예제 #10
0
        async public Task <Discussion> CreateDiscussionAsync(NewDiscussionParameters parameters, bool revertOnError)
        {
            if (_discussionOperator == null)
            {
                return(null);
            }

            try
            {
                var result = await _discussionOperator.CreateDiscussionAsync(_mergeRequestKey, parameters);

                _modificationListener.OnDiscussionModified(_mergeRequestKey);
                return(result);
            }
            catch (OperatorException ex)
            {
                bool handled = await handleGitlabError(parameters, ex, revertOnError);

                throw new DiscussionCreatorException(handled, ex);
            }
        }
예제 #11
0
        async internal Task CreateDiscussionAsync(MergeRequestDescriptor mrd, NewDiscussionParameters 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).
                                      Discussions.CreateNewTaskAsync(parameters));
            }
            catch (Exception ex)
            {
                Debug.Assert(!(ex is GitLabClientCancelled));
                if (ex is GitLabSharpException || ex is GitLabRequestException)
                {
                    ExceptionHandlers.Handle(ex, "Cannot create a discussion");
                    throw new OperatorException(ex);
                }
                throw;
            }
        }
예제 #12
0
        async private Task <bool> handleGitlabError(NewDiscussionParameters parameters, OperatorException ex)
        {
            if (ex.InternalException is GitLabRequestException rex)
            {
                var webException = rex.WebException;
                var response     = ((System.Net.HttpWebResponse)webException.Response);

                if (response.StatusCode == System.Net.HttpStatusCode.BadRequest)
                {
                    // Something went wrong at the GitLab site, let's report a discussion without Position
                    return(await createMergeRequestWithoutPosition(parameters));
                }
                else if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
                {
                    // Something went wrong at the GitLab site, let's report a discussion without Position
                    await cleanupBadNotes(parameters);

                    return(await createMergeRequestWithoutPosition(parameters));
                }
            }

            return(false);
        }
예제 #13
0
        // Instead of searching for a latest discussion note with some heuristically prepared parameters,
        // let's clean up all similar notes, including a recently added one
        async private Task cleanupBadNotes(NewDiscussionParameters parameters)
        {
            Debug.Assert(parameters.Position.HasValue);

            Trace.TraceInformation("Looking up for a note with bad position...");

            int deletedCount = 0;

            List <Discussion> discussions = await DiscussionOperator.GetDiscussionsAsync(MergeRequestDescriptor);

            if (discussions == null)
            {
                Trace.TraceWarning(String.Format("No discussions found"));
                return;
            }

            foreach (Discussion discussion in discussions)
            {
                foreach (DiscussionNote note in discussion.Notes)
                {
                    if (arePositionsEqual(note.Position, parameters.Position.Value))
                    {
                        Trace.TraceInformation(
                            "Deleting discussion note." +
                            " Id: {0}, Author.Username: {1}, Created_At: {2} (LocalTime), Body:\n{3}",
                            note.Id.ToString(), note.Author.Username, note.Created_At.ToLocalTime(), note.Body);

                        await DiscussionOperator.DeleteNoteAsync(MergeRequestDescriptor, note.Id);

                        ++deletedCount;
                    }
                }
            }

            Trace.TraceInformation(String.Format("Deleted {0} notes", deletedCount));
        }