# module PushObserver

Includes methods for handling Git Push events

Triggered by PostReceive job

### Public Instance Methods

execute_hooks(oldrev, newrev, ref, user) click to toggle source

    # File app/roles/push_observer.rb, line 33
    def execute_hooks(oldrev, newrev, ref, user)
      ref_parts = ref.split('/')

      # Return if this is not a push to a branch (e.g. new commits)
      return if ref_parts[1] !~ %rheads/ || oldrev == "00000000000000000000000000000000"

      data = post_receive_data(oldrev, newrev, ref, user)

      hooks.each { |hook| hook.execute(data) }
    end

observe_push(oldrev, newrev, ref, user) click to toggle source

    # File app/roles/push_observer.rb, line 5
    def observe_push(oldrev, newrev, ref, user)
      data = post_receive_data(oldrev, newrev, ref, user)

      Event.create(
        project: self,
        action: Event::Pushed,
        data: data,
        author_id: data[:user_id]
      )
    end

post_receive_data(oldrev, newrev, ref, user) click to toggle source

    # File app/roles/push_observer.rb, line 44
    def post_receive_data(oldrev, newrev, ref, user)

      push_commits = commits_between(oldrev, newrev)

      # Total commits count
      push_commits_count = push_commits.size

      # Get latest 20 commits ASC
      push_commits_limited = push_commits.last(20)

      # Hash to be passed as post_receive_data
      data = {
        before: oldrev,
        after: newrev,
        ref: ref,
        user_id: user.id,
        user_name: user.name,
        repository: {
          name: name,
          url: web_url,
          description: description,
          homepage: web_url,
        },
        commits: [],
        total_commits_count: push_commits_count
      }

      # For perfomance purposes maximum 20 latest commits
      # will be passed as post receive hook data.
      #
      push_commits_limited.each do |commit|
        data[:commits] << {
          id: commit.id,
          message: commit.safe_message,
          timestamp: commit.date.xmlschema,
          url: "#{Gitlab.config.url}/#{code}/commits/#{commit.id}",
          author: {
            name: commit.author_name,
            email: commit.author_email
          }
        }
      end

      data
    end

trigger_post_receive(oldrev, newrev, ref, user) click to toggle source

This method will be called after each post receive and only if the provided user is present in GitLab.

All callbacks for post receive should be placed here.

    # File app/roles/push_observer.rb, line 94
    def trigger_post_receive(oldrev, newrev, ref, user)
      # Create push event
      self.observe_push(oldrev, newrev, ref, user)

      # Close merged MR
      self.update_merge_requests(oldrev, newrev, ref, user)

      # Execute web hooks
      self.execute_hooks(oldrev, newrev, ref, user)

      # Create satellite
      self.satellite.create unless self.satellite.exists?

      # Discover the default branch, but only if it hasn't already been set to
      # something else
      if default_branch.nil?
        update_attributes(default_branch: discover_default_branch)
      end
    end

update_merge_requests(oldrev, newrev, ref, user) click to toggle source

    # File app/roles/push_observer.rb, line 16
    def update_merge_requests(oldrev, newrev, ref, user)
      return true unless ref =~ %rheads/
      branch_name = ref.gsub("refs/heads/", "")
      c_ids = self.commits_between(oldrev, newrev).map(&:id)

      # Update code for merge requests
      mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all
      mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }

      # Close merge requests
      mrs = self.merge_requests.opened.where(target_branch: branch_name).all
      mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) }
      mrs.each { |merge_request| merge_request.merge!(user.id) }

      true
    end