diff options
Diffstat (limited to 'lib/bitbucket_server/representation/comment.rb')
-rw-r--r-- | lib/bitbucket_server/representation/comment.rb | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/lib/bitbucket_server/representation/comment.rb b/lib/bitbucket_server/representation/comment.rb new file mode 100644 index 00000000000..99b97a3b181 --- /dev/null +++ b/lib/bitbucket_server/representation/comment.rb @@ -0,0 +1,130 @@ +# frozen_string_literal: true + +module BitbucketServer + module Representation + # A general comment with the structure: + # "comment": { + # "author": { + # "active": true, + # "displayName": "root", + # "emailAddress": "stanhu+bitbucket@gitlab.com", + # "id": 1, + # "links": { + # "self": [ + # { + # "href": "http://localhost:7990/users/root" + # } + # ] + # }, + # "name": "root", + # "slug": "root", + # "type": "NORMAL" + # } + # } + # } + class Comment < Representation::Base + attr_reader :parent_comment + + CommentNode = Struct.new(:raw_comments, :parent) + + def initialize(raw, parent_comment: nil) + super(raw) + + @parent_comment = parent_comment + end + + def id + raw_comment['id'] + end + + def author_username + author['displayName'] + end + + def author_email + author['emailAddress'] + end + + def note + raw_comment['text'] + end + + def created_at + self.class.convert_timestamp(created_date) + end + + def updated_at + self.class.convert_timestamp(created_date) + end + + # Bitbucket Server supports the ability to reply to any comment + # and created multiple threads. It represents these as a linked list + # of comments within comments. For example: + # + # "comments": [ + # { + # "author" : ... + # "comments": [ + # { + # "author": ... + # + # Since GitLab only supports a single thread, we flatten all these + # comments into a single discussion. + def comments + @comments ||= flatten_comments + end + + private + + # In order to provide context for each reply, we need to track + # the parent of each comment. This method works as follows: + # + # 1. Insert the root comment into the workset. The root element is the current note. + # 2. For each node in the workset: + # a. Examine if it has replies to that comment. If it does, + # insert that node into the workset. + # b. Parse that note into a Comment structure and add it to a flat list. + def flatten_comments + comments = raw_comment['comments'] + workset = + if comments + [CommentNode.new(comments, self)] + else + [] + end + + all_comments = [] + + until workset.empty? + node = workset.pop + parent = node.parent + + node.raw_comments.each do |comment| + new_comments = comment.delete('comments') + current_comment = Comment.new({ 'comment' => comment }, parent_comment: parent) + all_comments << current_comment + workset << CommentNode.new(new_comments, current_comment) if new_comments + end + end + + all_comments + end + + def raw_comment + raw.fetch('comment', {}) + end + + def author + raw_comment['author'] + end + + def created_date + raw_comment['createdDate'] + end + + def updated_date + raw_comment['updatedDate'] + end + end + end +end |