Class: MergeRequestDiffCommit

Inherits:
ApplicationRecord show all
Extended by:
SuppressCompositePrimaryKeyWarning
Includes:
BulkInsertSafe, CachedCommit, FromUnion, ShaAttribute
Defined in:
app/models/merge_request_diff_commit.rb

Constant Summary collapse

TRIM_USER_KEYS =

A list of keys of which their values need to be trimmed before they can be inserted into the merge_request_diff_commit_users table.

%i[author_name author_email committer_name committer_email].freeze

Constants included from BulkInsertSafe

BulkInsertSafe::ALLOWED_CALLBACKS, BulkInsertSafe::DEFAULT_BATCH_SIZE, BulkInsertSafe::MethodNotAllowedError, BulkInsertSafe::PrimaryKeySetError

Constants inherited from ApplicationRecord

ApplicationRecord::MAX_PLUCK

Constants included from HasCheckConstraints

HasCheckConstraints::NOT_NULL_CHECK_PATTERN

Constants included from ResetOnColumnErrors

ResetOnColumnErrors::MAX_RESET_PERIOD

Class Method Summary collapse

Instance Method Summary collapse

Methods included from CachedCommit

#extended_trailers, #parent_ids, #referenced_by

Methods inherited from ApplicationRecord

===, cached_column_list, #create_or_load_association, declarative_enum, default_select_columns, id_in, id_not_in, iid_in, nullable_column?, pluck_primary_key, primary_key_in, #readable_by?, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, #to_ability_name, underscore, where_exists, where_not_exists, with_fast_read_statement_timeout, without_order

Methods included from ResetOnColumnErrors

#reset_on_union_error, #reset_on_unknown_attribute_error

Methods included from Gitlab::SensitiveSerializableHash

#serializable_hash

Class Method Details

.create_bulk(merge_request_diff_id, commits, project, skip_commit_data: false) ⇒ Object

Deprecated; use ‘bulk_insert!` from `BulkInsertSafe` mixin instead. cf. gitlab.com/gitlab-org/gitlab/issues/207989 for progress



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'app/models/merge_request_diff_commit.rb', line 42

def self.create_bulk(merge_request_diff_id, commits, project, skip_commit_data: false)
  organization_id = project.organization_id
  with_organization = Feature.enabled?(:add_organization_to_diff_commit_users, project)
  commit_hashes, user_triples = prepare_commits_for_bulk_insert(commits, organization_id)
  users = MergeRequest::DiffCommitUser.bulk_find_or_create(
    user_triples,
    with_organization: with_organization
  )

  rows = commit_hashes.map.with_index do |commit_hash, index|
    sha = commit_hash.delete(:id)

    if with_organization
      author = users[[commit_hash[:author_name], commit_hash[:author_email], organization_id]]
      committer = users[[commit_hash[:committer_name], commit_hash[:committer_email], organization_id]]
    else
      author = users[[commit_hash[:author_name], commit_hash[:author_email]]]
      committer = users[[commit_hash[:committer_name], commit_hash[:committer_email]]]
    end

    # These fields are only used to determine the author/committer IDs, we
    # don't store them in the DB.
    #
    # Trailers are stored in the DB here in order to allow changelog parsing.
    # Rather than add an additional column for :extended_trailers, we're instead
    # ignoring it for now until we deprecate the :trailers field and replace it with
    # the new functionality.
    commit_hash = commit_hash
      .except(:author_name, :author_email, :committer_name, :committer_email, :extended_trailers)

    commit_hash = commit_hash.merge(
      commit_author_id: author.id,
      committer_id: committer.id,
      merge_request_diff_id: merge_request_diff_id,
      relative_order: index,
      sha: Gitlab::Database::ShaAttribute.serialize(sha),
      authored_date: Gitlab::Database.sanitize_timestamp(commit_hash[:authored_date]),
      committed_date: Gitlab::Database.sanitize_timestamp(commit_hash[:committed_date]),
      trailers: Gitlab::Json.dump(commit_hash.fetch(:trailers, {}))
    )

    if skip_commit_data
      commit_hash.merge(message: '')
    else
      commit_hash
    end
  end

  ApplicationRecord.legacy_bulk_insert(self.table_name, rows) # rubocop:disable Gitlab/BulkInsert
end

.oldest_merge_request_id_per_commit(project_id, shas) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'app/models/merge_request_diff_commit.rb', line 111

def self.oldest_merge_request_id_per_commit(project_id, shas)
  # This method is defined here and not on MergeRequest, otherwise the SHA
  # values used in the WHERE below won't be encoded correctly.
  select(['merge_request_diff_commits.sha AS sha', 'min(merge_requests.id) AS merge_request_id'])
    .joins(:merge_request_diff)
    .joins(
      'INNER JOIN merge_requests ' \
        'ON merge_requests.latest_merge_request_diff_id = merge_request_diffs.id'
    )
    .where(sha: shas)
    .where(
      merge_requests: {
        target_project_id: project_id,
        state_id: MergeRequest.available_states[:merged]
      }
    )
    .group(:sha)
end

.prepare_commits_for_bulk_insert(commits, organization_id) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'app/models/merge_request_diff_commit.rb', line 93

def self.prepare_commits_for_bulk_insert(commits, organization_id)
  user_triples = Set.new
  hashes = commits.map do |commit|
    hash = commit.to_hash.except(:parent_ids, :referenced_by)

    TRIM_USER_KEYS.each do |key|
      hash[key] = MergeRequest::DiffCommitUser.prepare(hash[key])
    end

    user_triples << [hash[:author_name], hash[:author_email], organization_id]
    user_triples << [hash[:committer_name], hash[:committer_email], organization_id]

    hash
  end

  [hashes, user_triples]
end

Instance Method Details

#author_emailObject



134
135
136
# File 'app/models/merge_request_diff_commit.rb', line 134

def author_email
  commit_author&.email
end

#author_nameObject



130
131
132
# File 'app/models/merge_request_diff_commit.rb', line 130

def author_name
  commit_author&.name
end

#committer_emailObject



142
143
144
# File 'app/models/merge_request_diff_commit.rb', line 142

def committer_email
  committer&.email
end

#committer_nameObject



138
139
140
# File 'app/models/merge_request_diff_commit.rb', line 138

def committer_name
  committer&.name
end

#messageObject



146
147
148
# File 'app/models/merge_request_diff_commit.rb', line 146

def message
  fetch_message
end

#to_hashObject



150
151
152
153
154
155
# File 'app/models/merge_request_diff_commit.rb', line 150

def to_hash
  super(exclude_keys: [:message]).merge({
    'id' => sha,
    message: fetch_message
  })
end