# class MergeRequest

### Constants

BROKEN_DIFF
CANNOT_BE_MERGED
CAN_BE_MERGED
UNCHECKED

### Attributes

should_remove_source_branch[RW]

### Public Class Methods

find_all_by_branch(branch_name) click to toggle source

    # File app/models/merge_request.rb, line 25
    def self.find_all_by_branch(branch_name)
      where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name)
    end

### Public Instance Methods

automerge!(current_user) click to toggle source

    # File app/models/merge_request.rb, line 169
    def automerge!(current_user)
      if Gitlab::Merge.new(self, current_user).merge! && self.unmerged_commits.empty?
        self.merge!(current_user.id)
        true
      end
    rescue
      self.mark_as_unmergable
      false
    end

broken_diffs?() click to toggle source

    # File app/models/merge_request.rb, line 86
    def broken_diffs?
      diffs == [BROKEN_DIFF]
    end

can_be_merged?() click to toggle source

    # File app/models/merge_request.rb, line 58
    def can_be_merged?
      state == CAN_BE_MERGED
    end

check_if_can_be_merged() click to toggle source

    # File app/models/merge_request.rb, line 62
    def check_if_can_be_merged
      self.state = if Gitlab::Merge.new(self, self.author).can_be_merged?
                     CAN_BE_MERGED
                   else
                     CANNOT_BE_MERGED
                   end
      self.save
    end

closed_event() click to toggle source

    # File app/models/merge_request.rb, line 114
    def closed_event
      self.project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::Closed).last
    end

commits() click to toggle source

    # File app/models/merge_request.rb, line 118
    def commits
      st_commits || []
    end

diffs() click to toggle source

    # File app/models/merge_request.rb, line 71
    def diffs
      st_diffs || []
    end

human_state() click to toggle source

    # File app/models/merge_request.rb, line 29
    def human_state
      states = {
        CAN_BE_MERGED =>  "can_be_merged",
        CANNOT_BE_MERGED => "cannot_be_merged",
        UNCHECKED => "unchecked"
      }
      states[self.state]
    end

last_commit() click to toggle source

    # File app/models/merge_request.rb, line 102
    def last_commit
      commits.first
    end

mark_as_merged!() click to toggle source

    # File app/models/merge_request.rb, line 131
    def mark_as_merged!
      self.merged = true
      self.closed = true
      save
    end

mark_as_unchecked() click to toggle source

    # File app/models/merge_request.rb, line 53
    def mark_as_unchecked
      self.state = UNCHECKED
      self.save
    end

mark_as_unmergable() click to toggle source

    # File app/models/merge_request.rb, line 137
    def mark_as_unmergable
      self.state = CANNOT_BE_MERGED
      self.save
    end

merge!(user_id) click to toggle source

    # File app/models/merge_request.rb, line 158
    def merge!(user_id)
      self.mark_as_merged!
      Event.create(
        project: self.project,
        action: Event::Merged,
        target_id: self.id,
        target_type: "MergeRequest",
        author_id: user_id
      )
    end

merge_event() click to toggle source

    # File app/models/merge_request.rb, line 110
    def merge_event
      self.project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::Merged).last
    end

merged?() click to toggle source

    # File app/models/merge_request.rb, line 106
    def merged?
      merged && merge_event
    end

mr_and_commit_notes() click to toggle source

    # File app/models/merge_request.rb, line 191
    def mr_and_commit_notes
      commit_ids = commits.map(&:id)
      Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND noteable_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
    end

open?() click to toggle source

    # File app/models/merge_request.rb, line 127
    def open?
      !closed
    end

probably_merged?() click to toggle source

    # File app/models/merge_request.rb, line 122
    def probably_merged?
      unmerged_commits.empty? &&
        commits.any? && open?
    end

reload_code() click to toggle source

    # File app/models/merge_request.rb, line 44
    def reload_code
      self.reloaded_commits
      self.reloaded_diffs
    end

reloaded_commits() click to toggle source

    # File app/models/merge_request.rb, line 142
    def reloaded_commits
      if open? && unmerged_commits.any?
        self.st_commits = unmerged_commits
        save
      end
      commits
    end

reloaded_diffs() click to toggle source

    # File app/models/merge_request.rb, line 75
    def reloaded_diffs
      if open? && unmerged_diffs.any?
        self.st_diffs = unmerged_diffs
        self.save
      end

    rescue Grit::Git::GitTimeout
      self.st_diffs = [BROKEN_DIFF]
      self.save
    end

to_raw() click to toggle source

    # File app/models/merge_request.rb, line 179
    def to_raw
      FileUtils.mkdir_p(Rails.root.join("tmp", "patches"))
      patch_path = Rails.root.join("tmp", "patches", "merge_request_#{self.id}.patch")

      from = commits.last.id
      to = source_branch

      project.repo.git.run('', "format-patch" , " > #{patch_path.to_s}", {}, ["#{from}..#{to}", "--stdout"])

      patch_path
    end

unchecked?() click to toggle source

    # File app/models/merge_request.rb, line 49
    def unchecked?
      state == UNCHECKED
    end

unmerged_commits() click to toggle source

    # File app/models/merge_request.rb, line 150
    def unmerged_commits
      self.project.repo.
        commits_between(self.target_branch, self.source_branch).
        map {|c| Commit.new(c)}.
        sort_by(&:created_at).
        reverse
    end

unmerged_diffs() click to toggle source

    # File app/models/merge_request.rb, line 94
    def unmerged_diffs
      # Only show what is new in the source branch compared to the target branch, not the other way around.
      # The linex below with merge_base is equivalent to diff with three dots (git diff branch1...branch2)
      # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B"
      common_commit = project.repo.git.native(:merge_base, {}, [target_branch, source_branch]).strip
      diffs = project.repo.diff(common_commit, source_branch)
    end

valid_diffs?() click to toggle source

    # File app/models/merge_request.rb, line 90
    def valid_diffs?
      !broken_diffs?
    end

validate_branches() click to toggle source

    # File app/models/merge_request.rb, line 38
    def validate_branches
      if target_branch == source_branch
        errors.add :base, "You can not use same branch for source and target branches"
      end
    end