BigW Consortium Gitlab

merge_action.rb 2.55 KB
Newer Older
1 2
module Gitlab
  module Satellite
3
    # GitLab server-side merge
4
    class MergeAction < Action
5
      attr_accessor :merge_request
6

7 8
      def initialize(user, merge_request)
        super user, merge_request.project
9 10 11
        @merge_request = merge_request
      end

12
      # Checks if a merge request can be executed without user interaction
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
      def can_be_merged?
        in_locked_and_timed_satellite do |merge_repo|
          merge_in_satellite!(merge_repo)
        end
      end

      # Merges the source branch into the target branch in the satellite and
      # pushes it back to Gitolite.
      # It also removes the source branch if requested in the merge request.
      #
      # Returns false if the merge produced conflicts
      # Returns false if pushing from the satellite to Gitolite failed or was rejected
      # Returns true otherwise
      def merge!
        in_locked_and_timed_satellite do |merge_repo|
          if merge_in_satellite!(merge_repo)
            # push merge back to Gitolite
            # will raise CommandFailed when push fails
31
            merge_repo.git.push({raise: true, timeout: true}, :origin, merge_request.target_branch)
32 33 34 35

            # remove source branch
            if merge_request.should_remove_source_branch && !project.root_ref?(merge_request.source_branch)
              # will raise CommandFailed when push fails
36
              merge_repo.git.push({raise: true, timeout: true}, :origin, ":#{merge_request.source_branch}")
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
            end

            # merge, push and branch removal successful
            true
          end
        end
      rescue Grit::Git::CommandFailed => ex
        Gitlab::GitLogger.error(ex.message)
        false
      end

      private

      # Merges the source_branch into the target_branch in the satellite.
      #
      # Note: it will clear out the satellite before doing anything
      #
      # Returns false if the merge produced conflicts
      # Returns true otherwise
      def merge_in_satellite!(repo)
        prepare_satellite!(repo)

        # create target branch in satellite at the corresponding commit from Gitolite
60
        repo.git.checkout({raise: true, timeout: true, b: true}, merge_request.target_branch, "origin/#{merge_request.target_branch}")
61 62 63

        # merge the source branch from Gitolite into the satellite
        # will raise CommandFailed when merge fails
64
        repo.git.pull({raise: true, timeout: true, no_ff: true}, :origin, merge_request.source_branch)
65 66 67 68 69 70 71
      rescue Grit::Git::CommandFailed => ex
        Gitlab::GitLogger.error(ex.message)
        false
      end
    end
  end
end