File: pull_request_comment.rb

package info (click to toggle)
gitlab 17.6.5-19
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 629,368 kB
  • sloc: ruby: 1,915,304; javascript: 557,307; sql: 60,639; xml: 6,509; sh: 4,567; makefile: 1,239; python: 406
file content (132 lines) | stat: -rw-r--r-- 3,216 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# frozen_string_literal: true

module BitbucketServer
  module Representation
    # An inline comment with the following structure that identifies
    # the part of the diff:
    #
    # "commentAnchor": {
    #   "diffType": "EFFECTIVE",
    #   "fileType": "TO",
    #   "fromHash": "c5f4288162e2e6218180779c7f6ac1735bb56eab",
    #   "line": 1,
    #   "lineType": "ADDED",
    #   "orphaned": false,
    #   "path": "CHANGELOG.md",
    #   "toHash": "a4c2164330f2549f67c13f36a93884cf66e976be"
    #  }
    #
    # More details in https://docs.atlassian.com/bitbucket-server/rest/5.12.0/bitbucket-rest.html.
    class PullRequestComment < Comment
      def from_sha
        comment_anchor['fromHash']
      end

      def to_sha
        comment_anchor['toHash']
      end

      def to?
        file_type == 'TO'
      end

      def from?
        file_type == 'FROM'
      end

      def added?
        line_type == 'ADDED'
      end

      def removed?
        line_type == 'REMOVED'
      end

      # There are three line comment types: added, removed, or context.
      #
      # 1. An added type means a new line was inserted, so there is no old position.
      # 2. A removed type means a line was removed, so there is no new position.
      # 3. A context type means the line was unmodified, so there is both a
      #    old and new position.
      def new_pos
        return if removed?
        return unless line_position

        line_position[1]
      end

      def old_pos
        return if added?
        return unless line_position

        line_position[0]
      end

      def file_path
        comment_anchor.fetch('path')
      end

      def to_hash
        super.merge(
          from_sha: from_sha,
          to_sha: to_sha,
          file_path: file_path,
          old_pos: old_pos,
          new_pos: new_pos
        )
      end

      private

      def file_type
        comment_anchor['fileType']
      end

      def line_type
        comment_anchor['lineType']
      end

      # Each comment contains the following information about the diff:
      #
      # hunks: [
      #     {
      #         segments: [
      #             {
      #                 "lines": [
      #                     {
      #                         "commentIds": [ N ],
      #                         "source": X,
      #                         "destination": Y
      #                     }, ...
      #                   ] ....
      #
      # To determine the line position of a comment, we search all the lines
      # entries until we find this comment ID.
      def line_position
        @line_position ||= diff_hunks.each do |hunk|
          segments = hunk.fetch('segments', [])
          segments.each do |segment|
            lines = segment.fetch('lines', [])
            lines.each do |line|
              if line['commentIds']&.include?(id)
                return [line['source'], line['destination']]
              end
            end
          end
        end
      end

      def comment_anchor
        raw.fetch('commentAnchor', {})
      end

      def diff
        raw.fetch('diff', {})
      end

      def diff_hunks
        diff.fetch('hunks', [])
      end
    end
  end
end