event.rb 5.31 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# == 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
#  created_at  :datetime         not null
#  updated_at  :datetime         not null
#  action      :integer
#  author_id   :integer
#

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
17
class Event < ActiveRecord::Base
18 19 20
  attr_accessible :project, :action, :data, :author_id, :project_id,
                  :target_id, :target_type

21
  default_scope { where.not(author_id: nil) }
22

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

Nihad Abbasov's avatar
Nihad Abbasov committed
33 34 35 36
  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

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

Andrey Kumanyaev's avatar
Andrey Kumanyaev committed
44
  # Scopes
Andrew8xx8's avatar
Andrew8xx8 committed
45
  scope :recent, -> { order("created_at DESC") }
46
  scope :code_push, -> { where(action: PUSHED) }
47
  scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent }
48

Andrey Kumanyaev's avatar
Andrey Kumanyaev committed
49 50 51
  class << self
    def determine_action(record)
      if [Issue, MergeRequest].include? record.class
52
        Event::CREATED
Andrey Kumanyaev's avatar
Andrey Kumanyaev committed
53
      elsif record.kind_of? Note
54
        Event::COMMENTED
Andrey Kumanyaev's avatar
Andrey Kumanyaev committed
55
      end
56
    end
57

58 59 60 61 62 63 64 65 66
    def create_ref_event(project, user, ref, action = 'add', prefix = 'refs/heads')
      if action.to_s == 'add'
        before = '00000000'
        after = ref.commit.id
      else
        before = ref.commit.id
        after = '00000000'
      end

67 68 69 70
      Event.create(
        project: project,
        action: Event::PUSHED,
        data: {
71
          ref: "#{prefix}/#{ref.name}",
72 73
          before: before,
          after: after
74 75 76 77
        },
        author_id: user.id
      )
    end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
78 79
  end

80 81 82 83 84 85 86 87
  def proper?
    if push?
      true
    elsif membership_changed?
      true
    else
      (issue? || merge_request? || note? || milestone?) && target
    end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
88 89
  end

90 91
  def project_name
    if project
92
      project.name_with_namespace
93
    else
Riyad Preukschas's avatar
Riyad Preukschas committed
94
      "(deleted project)"
95 96 97
    end
  end

98
  def target_title
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
99 100 101
    if target && target.respond_to?(:title)
      target.title
    end
102 103
  end

104
  def push?
105
    action == self.class::PUSHED && valid_push?
106 107
  end

108
  def merged?
109
    action == self.class::MERGED
110 111
  end

112
  def closed?
113
    action == self.class::CLOSED
114 115 116
  end

  def reopened?
117
    action == self.class::REOPENED
118 119
  end

120 121 122 123 124 125 126 127
  def milestone?
    target_type == "Milestone"
  end

  def note?
    target_type == "Note"
  end

128
  def issue?
129
    target_type == "Issue"
130 131
  end

132
  def merge_request?
133
    target_type == "MergeRequest"
134 135
  end

136
  def joined?
137
    action == JOINED
Alex Denisov's avatar
Alex Denisov committed
138 139 140
  end

  def left?
141
    action == LEFT
Alex Denisov's avatar
Alex Denisov committed
142 143 144 145
  end

  def membership_changed?
    joined? || left?
146 147
  end

148
  def issue
149 150 151 152 153 154 155
    target if target_type == "Issue"
  end

  def merge_request
    target if target_type == "MergeRequest"
  end

156 157 158 159
  def action_name
    if closed?
      "closed"
    elsif merged?
160
      "accepted"
161 162
    elsif joined?
      'joined'
Alex Denisov's avatar
Alex Denisov committed
163 164
    elsif left?
      'left'
165
    else
166
      "opened"
167 168
    end
  end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
169 170

  def valid_push?
171
    data[:ref] && ref_name.present?
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
  rescue => ex
    false
  end

  def tag?
    data[:ref]["refs/tags"]
  end

  def branch?
    data[:ref]["refs/heads"]
  end

  def new_branch?
    commit_from =~ /^00000/
  end

  def new_ref?
    commit_from =~ /^00000/
  end

  def rm_ref?
    commit_to =~ /^00000/
  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
    @branch_name ||= data[:ref].gsub("refs/heads/", "")
  end

  def tag_name
    @tag_name ||= data[:ref].gsub("refs/tags/", "")
  end

  # Max 20 commits from push DESC
  def commits
226
    @commits ||= (data[:commits] || []).reverse
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
  end

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

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

  def push_action_name
    if new_ref?
      "pushed new"
    elsif rm_ref?
      "deleted"
    else
      "pushed to"
    end
  end

  def push_with_commits?
248
    md_ref? && commits.any? && commit_from && commit_to
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
249 250 251 252 253 254 255 256 257 258
  end

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

  def note_commit_id
    target.commit_id
  end

259 260 261 262
  def target_iid
    target.respond_to?(:iid) ? target.iid : target_id
  end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
263 264 265 266 267 268 269 270
  def note_short_commit_id
    note_commit_id[0..8]
  end

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

Andrew8xx8's avatar
Andrew8xx8 committed
271 272 273 274
  def note_project_snippet?
    target.noteable_type == "Snippet"
  end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
275 276 277 278 279 280 281 282 283 284 285 286
  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
287 288 289 290 291 292 293 294
  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
295 296 297 298 299 300 301 302 303 304 305
  def wall_note?
    target.noteable_type.blank?
  end

  def note_target_type
    if target.noteable_type.present?
      target.noteable_type.titleize
    else
      "Wall"
    end.downcase
  end
306 307 308 309 310 311 312 313 314 315

  def body?
    if push?
      push_with_commits?
    elsif note?
      true
    else
      target.respond_to? :title
    end
  end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
316
end