pull_request_importer.rb 4.2 KB
Newer Older
1 2 3 4 5 6
# frozen_string_literal: true

module Gitlab
  module GithubImport
    module Importer
      class PullRequestImporter
7 8
        include Gitlab::Import::MergeRequestHelpers

9 10 11 12 13 14 15 16 17 18 19
        attr_reader :pull_request, :project, :client, :user_finder,
                    :milestone_finder, :issuable_finder

        # pull_request - An instance of
        #                `Gitlab::GithubImport::Representation::PullRequest`.
        # project - An instance of `Project`
        # client - An instance of `Gitlab::GithubImport::Client`
        def initialize(pull_request, project, client)
          @pull_request = pull_request
          @project = project
          @client = client
20
          @user_finder = GithubImport::UserFinder.new(project, client)
21 22 23 24 25 26
          @milestone_finder = MilestoneFinder.new(project)
          @issuable_finder =
            GithubImport::IssuableFinder.new(project, pull_request)
        end

        def execute
27 28 29 30 31
          mr, already_exists = create_merge_request

          if mr
            insert_git_data(mr, already_exists)
            issuable_finder.cache_database_id(mr.id)
32 33 34 35 36 37
          end
        end

        # Creates the merge request and returns its ID.
        #
        # This method will return `nil` if the merge request could not be
38 39 40 41 42
        # created, otherwise it will return an Array containing the following
        # values:
        #
        # 1. A MergeRequest instance.
        # 2. A boolean indicating if the MR already exists.
43 44 45 46 47 48
        def create_merge_request
          author_id, author_found = user_finder.author_id_for(pull_request)

          description = MarkdownText
            .format(pull_request.description, pull_request.author, author_found)

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
          attributes = {
            iid: pull_request.iid,
            title: pull_request.truncated_title,
            description: description,
            source_project_id: project.id,
            target_project_id: project.id,
            source_branch: pull_request.formatted_source_branch,
            target_branch: pull_request.target_branch,
            state: pull_request.state,
            milestone_id: milestone_finder.id_for(pull_request),
            author_id: author_id,
            assignee_id: user_finder.assignee_id_for(pull_request),
            created_at: pull_request.created_at,
            updated_at: pull_request.updated_at
          }
64

65
          create_merge_request_without_hooks(project, attributes, pull_request.iid)
66 67
        end

68 69
        def insert_git_data(merge_request, already_exists)
          insert_or_replace_git_data(merge_request, pull_request.source_branch_sha, pull_request.target_branch_sha, already_exists)
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
          # We need to create the branch after the merge request is
          # populated to ensure the merge request is in the right state
          # when the branch is created.
          create_source_branch_if_not_exists(merge_request)
        end

        # An imported merge request will not be mergeable unless the
        # source branch exists. For pull requests from forks, the source
        # branch will be in the form of
        # "github/fork/{project-name}/{source_branch}". This branch will never
        # exist, so we create it here.
        #
        # Note that we only create the branch if the merge request is still open.
        # For projects that have many pull requests, we assume that if it's closed
        # the branch has already been deleted.
        def create_source_branch_if_not_exists(merge_request)
          return unless merge_request.open?

          source_branch = pull_request.formatted_source_branch

          return if project.repository.branch_exists?(source_branch)

92
          project.repository.add_branch(project.creator, source_branch, pull_request.source_branch_sha)
93 94 95 96 97 98 99
        rescue Gitlab::Git::CommandError => e
          Gitlab::Sentry.track_acceptable_exception(e,
                                                    extra: {
                                                      source_branch: source_branch,
                                                      project_id: merge_request.project.id,
                                                      merge_request_id: merge_request.id
                                                    })
100 101 102 103 104
        end
      end
    end
  end
end