event.rb 5.75 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
# == Schema Information
#
# Table name: events
#
#  id          :integer          not null, primary key
#  target_type :string(255)
#  target_id   :integer
#  title       :string(255)
#  data        :text
#  project_id  :integer
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
11 12
#  created_at  :datetime
#  updated_at  :datetime
13 14 15 16
#  action      :integer
#  author_id   :integer
#

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
17
class Event < ActiveRecord::Base
18
  include Sortable
19
  default_scope { where.not(author_id: nil) }
20

21 22 23 24 25 26 27 28 29
  CREATED   = 1
  UPDATED   = 2
  CLOSED    = 3
  REOPENED  = 4
  PUSHED    = 5
  COMMENTED = 6
  MERGED    = 7
  JOINED    = 8 # User joined project
  LEFT      = 9 # User left project
30
  DESTROYED = 10
31

Nihad Abbasov's avatar
Nihad Abbasov committed
32 33 34
  delegate :name, :email, to: :author, prefix: true, allow_nil: true
  delegate :title, to: :issue, prefix: true, allow_nil: true
  delegate :title, to: :merge_request, prefix: true, allow_nil: true
35
  delegate :title, to: :note, prefix: true, allow_nil: true
Nihad Abbasov's avatar
Nihad Abbasov committed
36

randx's avatar
randx committed
37
  belongs_to :author, class_name: "User"
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
38
  belongs_to :project
39
  belongs_to :target, polymorphic: true
40

randx's avatar
randx committed
41 42
  # For Hash only
  serialize :data
43

44 45 46
  # Callbacks
  after_create :reset_project_activity

Andrey Kumanyaev's avatar
Andrey Kumanyaev committed
47
  # Scopes
48
  scope :recent, -> { reorder(id: :desc) }
49
  scope :code_push, -> { where(action: PUSHED) }
50
  scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent }
51
  scope :with_associations, -> { includes(project: :namespace) }
52
  scope :for_milestone_id, ->(milestone_id) { where(target_type: "Milestone", target_id: milestone_id) }
53

Andrey Kumanyaev's avatar
Andrey Kumanyaev committed
54
  class << self
55 56 57 58 59
    def reset_event_cache_for(target)
      Event.where(target_id: target.id, target_type: target.class.to_s).
        order('id DESC').limit(100).
        update_all(updated_at: Time.now)
    end
60 61 62 63 64 65

    def contributions
      where("action = ? OR (target_type in (?) AND action in (?))",
            Event::PUSHED, ["MergeRequest", "Issue"],
            [Event::CREATED, Event::CLOSED, Event::MERGED])
    end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
66 67
  end

68 69 70 71 72
  def proper?
    if push?
      true
    elsif membership_changed?
      true
73 74
    elsif created_project?
      true
75
    else
76
      ((issue? || merge_request? || note?) && target) || milestone?
77
    end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
78 79
  end

80 81
  def project_name
    if project
82
      project.name_with_namespace
83
    else
Riyad Preukschas's avatar
Riyad Preukschas committed
84
      "(deleted project)"
85 86 87
    end
  end

88
  def target_title
89 90 91 92 93
    target.title if target && target.respond_to?(:title)
  end

  def created?
    action == CREATED
94 95
  end

96
  def push?
97
    action == PUSHED && valid_push?
98 99
  end

100
  def merged?
101
    action == MERGED
102 103
  end

104
  def closed?
105
    action == CLOSED
106 107 108
  end

  def reopened?
109 110 111 112 113 114 115 116 117 118 119
    action == REOPENED
  end

  def joined?
    action == JOINED
  end

  def left?
    action == LEFT
  end

120 121 122 123
  def destroyed?
    action == DESTROYED
  end

124 125 126 127 128 129
  def commented?
    action == COMMENTED
  end

  def membership_changed?
    joined? || left?
130 131
  end

132
  def created_project?
133
    created? && !target && target_type.nil?
134 135 136 137 138 139
  end

  def created_target?
    created? && target
  end

140 141 142 143 144 145 146 147
  def milestone?
    target_type == "Milestone"
  end

  def note?
    target_type == "Note"
  end

148
  def issue?
149
    target_type == "Issue"
150 151
  end

152
  def merge_request?
153
    target_type == "MergeRequest"
154 155
  end

156 157
  def milestone
    target if milestone?
158 159
  end

160
  def issue
161
    target if issue?
162 163 164
  end

  def merge_request
165
    target if merge_request?
166 167
  end

168
  def note
169
    target if note?
170 171
  end

172
  def action_name
173 174 175 176 177 178 179 180 181
    if push?
      if new_ref?
        "pushed new"
      elsif rm_ref?
        "deleted"
      else
        "pushed to"
      end
    elsif closed?
182 183
      "closed"
    elsif merged?
184
      "accepted"
185 186
    elsif joined?
      'joined'
Alex Denisov's avatar
Alex Denisov committed
187 188
    elsif left?
      'left'
189 190
    elsif destroyed?
      'destroyed'
191 192
    elsif commented?
      "commented on"
193
    elsif created_project?
194 195 196 197 198
      if project.import?
        "imported"
      else
        "created"
      end
199
    else
200
      "opened"
201 202
    end
  end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
203 204

  def valid_push?
205
    data[:ref] && ref_name.present?
206
  rescue
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
207 208 209 210
    false
  end

  def tag?
211
    Gitlab::Git.tag_ref?(data[:ref])
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
212 213 214
  end

  def branch?
215
    Gitlab::Git.branch_ref?(data[:ref])
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
216 217 218
  end

  def new_ref?
219
    Gitlab::Git.blank_ref?(commit_from)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
220 221 222
  end

  def rm_ref?
223
    Gitlab::Git.blank_ref?(commit_to)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
  end

  def md_ref?
    !(rm_ref? || new_ref?)
  end

  def commit_from
    data[:before]
  end

  def commit_to
    data[:after]
  end

  def ref_name
    if tag?
      tag_name
    else
      branch_name
    end
  end

  def branch_name
247
    @branch_name ||= Gitlab::Git.ref_name(data[:ref])
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
248 249 250
  end

  def tag_name
251
    @tag_name ||= Gitlab::Git.ref_name(data[:ref])
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
252 253 254 255
  end

  # Max 20 commits from push DESC
  def commits
256
    @commits ||= (data[:commits] || []).reverse
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
257 258 259 260 261 262 263 264 265 266 267
  end

  def commits_count
    data[:total_commits_count] || commits.count || 0
  end

  def ref_type
    tag? ? "tag" : "branch"
  end

  def push_with_commits?
268
    !commits.empty? && commit_from && commit_to
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
269 270 271 272 273 274 275 276 277 278
  end

  def last_push_to_non_root?
    branch? && project.default_branch != branch_name
  end

  def note_commit_id
    target.commit_id
  end

279 280 281 282
  def target_iid
    target.respond_to?(:iid) ? target.iid : target_id
  end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
283
  def note_short_commit_id
284
    Commit.truncate_sha(note_commit_id)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
285 286 287 288 289 290
  end

  def note_commit?
    target.noteable_type == "Commit"
  end

Andrew8xx8's avatar
Andrew8xx8 committed
291 292 293 294
  def note_project_snippet?
    target.noteable_type == "Snippet"
  end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
295 296 297 298 299 300 301 302 303 304 305 306
  def note_target
    target.noteable
  end

  def note_target_id
    if note_commit?
      target.commit_id
    else
      target.noteable_id.to_s
    end
  end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
307 308 309 310 311 312 313 314
  def note_target_iid
    if note_target.respond_to?(:iid)
      note_target.iid
    else
      note_target_id
    end.to_s
  end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
315 316 317 318 319 320 321
  def note_target_type
    if target.noteable_type.present?
      target.noteable_type.titleize
    else
      "Wall"
    end.downcase
  end
322 323 324 325 326 327 328 329 330 331

  def body?
    if push?
      push_with_commits?
    elsif note?
      true
    else
      target.respond_to? :title
    end
  end
332 333 334

  def reset_project_activity
    if project
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
335
      project.update_column(:last_activity_at, self.created_at)
336 337
    end
  end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
338
end