BigW Consortium Gitlab

event.rb 5.76 KB
Newer Older
1
class Event < ActiveRecord::Base
2
  include Sortable
3
  default_scope { where.not(author_id: nil) }
4

5 6 7 8 9 10 11 12 13
  CREATED   = 1
  UPDATED   = 2
  CLOSED    = 3
  REOPENED  = 4
  PUSHED    = 5
  COMMENTED = 6
  MERGED    = 7
  JOINED    = 8 # User joined project
  LEFT      = 9 # User left project
14
  DESTROYED = 10
15

16 17 18
  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
19
  delegate :title, to: :note, prefix: true, allow_nil: true
20

randx committed
21
  belongs_to :author, class_name: "User"
22
  belongs_to :project
23
  belongs_to :target, polymorphic: true
24

25 26
  # For Hash only
  serialize :data
27

28 29 30
  # Callbacks
  after_create :reset_project_activity

Andrey Kumanyaev committed
31
  # Scopes
32
  scope :recent, -> { reorder(id: :desc) }
33
  scope :code_push, -> { where(action: PUSHED) }
34 35

  scope :in_projects, ->(projects) do
Josh Frye committed
36
    where(project_id: projects.map(&:id)).recent
37 38
  end

39
  scope :with_associations, -> { includes(project: :namespace) }
40
  scope :for_milestone_id, ->(milestone_id) { where(target_type: "Milestone", target_id: milestone_id) }
41

Andrey Kumanyaev committed
42
  class << self
43 44 45 46 47
    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
48 49 50 51 52 53

    def contributions
      where("action = ? OR (target_type in (?) AND action in (?))",
            Event::PUSHED, ["MergeRequest", "Issue"],
            [Event::CREATED, Event::CLOSED, Event::MERGED])
    end
54

55 56 57
    def limit_recent(limit = 20, offset = nil)
      recent.limit(limit).offset(offset)
    end
Dmitriy Zaporozhets committed
58 59
  end

60
  def visible_to_user?(user = nil)
61 62 63 64
    if push?
      true
    elsif membership_changed?
      true
65 66
    elsif created_project?
      true
67 68
    elsif issue? || issue_note?
      Ability.abilities.allowed?(user, :read_issue, note? ? note_target : target)
69
    else
70
      ((merge_request? || note?) && target) || milestone?
71
    end
72 73
  end

74 75
  def project_name
    if project
76
      project.name_with_namespace
77
    else
78
      "(deleted project)"
79 80 81
    end
  end

82
  def target_title
83
    target.try(:title)
84 85 86 87
  end

  def created?
    action == CREATED
88 89
  end

90
  def push?
91
    action == PUSHED && valid_push?
92 93
  end

94
  def merged?
95
    action == MERGED
96 97
  end

98
  def closed?
99
    action == CLOSED
100 101 102
  end

  def reopened?
103 104 105 106 107 108 109 110 111 112 113
    action == REOPENED
  end

  def joined?
    action == JOINED
  end

  def left?
    action == LEFT
  end

114 115 116 117
  def destroyed?
    action == DESTROYED
  end

118 119 120 121 122 123
  def commented?
    action == COMMENTED
  end

  def membership_changed?
    joined? || left?
124 125
  end

126
  def created_project?
127
    created? && !target && target_type.nil?
128 129 130 131 132 133
  end

  def created_target?
    created? && target
  end

134 135 136 137 138 139 140 141
  def milestone?
    target_type == "Milestone"
  end

  def note?
    target_type == "Note"
  end

142
  def issue?
143
    target_type == "Issue"
144 145
  end

146
  def merge_request?
147
    target_type == "MergeRequest"
148 149
  end

150 151
  def milestone
    target if milestone?
152 153
  end

154
  def issue
155
    target if issue?
156 157 158
  end

  def merge_request
159
    target if merge_request?
160 161
  end

162
  def note
163
    target if note?
164 165
  end

166
  def action_name
167 168 169 170 171 172 173 174 175
    if push?
      if new_ref?
        "pushed new"
      elsif rm_ref?
        "deleted"
      else
        "pushed to"
      end
    elsif closed?
176 177
      "closed"
    elsif merged?
178
      "accepted"
179 180
    elsif joined?
      'joined'
181 182
    elsif left?
      'left'
183 184
    elsif destroyed?
      'destroyed'
185 186
    elsif commented?
      "commented on"
187
    elsif created_project?
188
      if project.external_import?
189 190 191 192
        "imported"
      else
        "created"
      end
193
    else
194
      "opened"
195 196
    end
  end
Dmitriy Zaporozhets committed
197 198

  def valid_push?
199
    data[:ref] && ref_name.present?
200
  rescue
Dmitriy Zaporozhets committed
201 202 203 204
    false
  end

  def tag?
205
    Gitlab::Git.tag_ref?(data[:ref])
Dmitriy Zaporozhets committed
206 207 208
  end

  def branch?
209
    Gitlab::Git.branch_ref?(data[:ref])
Dmitriy Zaporozhets committed
210 211 212
  end

  def new_ref?
213
    Gitlab::Git.blank_ref?(commit_from)
Dmitriy Zaporozhets committed
214 215 216
  end

  def rm_ref?
217
    Gitlab::Git.blank_ref?(commit_to)
Dmitriy Zaporozhets committed
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
  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
241
    @branch_name ||= Gitlab::Git.ref_name(data[:ref])
Dmitriy Zaporozhets committed
242 243 244
  end

  def tag_name
245
    @tag_name ||= Gitlab::Git.ref_name(data[:ref])
Dmitriy Zaporozhets committed
246 247 248 249
  end

  # Max 20 commits from push DESC
  def commits
250
    @commits ||= (data[:commits] || []).reverse
Dmitriy Zaporozhets committed
251 252 253 254 255 256 257 258 259 260 261
  end

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

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

  def push_with_commits?
262
    !commits.empty? && commit_from && commit_to
Dmitriy Zaporozhets committed
263 264 265 266 267 268
  end

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

269 270 271 272
  def target_iid
    target.respond_to?(:iid) ? target.iid : target_id
  end

273
  def commit_note?
274
    target.for_commit?
Dmitriy Zaporozhets committed
275 276
  end

277
  def issue_note?
278
    note? && target && target.for_issue?
279 280
  end

281
  def project_snippet_note?
282
    target.for_snippet?
Andrew8xx8 committed
283 284
  end

Dmitriy Zaporozhets committed
285 286 287 288 289
  def note_target
    target.noteable
  end

  def note_target_id
290
    if commit_note?
Dmitriy Zaporozhets committed
291 292 293 294 295 296
      target.commit_id
    else
      target.noteable_id.to_s
    end
  end

297 298 299 300 301 302
  def note_target_reference
    return unless note_target

    # Commit#to_reference returns the full SHA, but we want the short one here
    if commit_note?
      note_target.short_id
Dmitriy Zaporozhets committed
303
    else
304 305
      note_target.to_reference
    end
Dmitriy Zaporozhets committed
306 307
  end

Dmitriy Zaporozhets committed
308 309 310 311 312 313 314
  def note_target_type
    if target.noteable_type.present?
      target.noteable_type.titleize
    else
      "Wall"
    end.downcase
  end
315 316 317 318 319 320 321 322 323 324

  def body?
    if push?
      push_with_commits?
    elsif note?
      true
    else
      target.respond_to? :title
    end
  end
325 326

  def reset_project_activity
327
    if project && Gitlab::ExclusiveLease.new("project:update_last_activity_at:#{project.id}", timeout: 60).try_obtain
Dmitriy Zaporozhets committed
328
      project.update_column(:last_activity_at, self.created_at)
329 330
    end
  end
331
end