Class: CommitCollection
- Inherits:
-
Object
- Object
- CommitCollection
- Includes:
- Enumerable, Gitlab::Utils::StrongMemoize
- Defined in:
- app/models/commit_collection.rb
Overview
A collection of Commit instances for a specific container and Git reference.
Instance Attribute Summary collapse
-
#commits ⇒ Object
readonly
Returns the value of attribute commits.
-
#container ⇒ Object
readonly
Returns the value of attribute container.
-
#ref ⇒ Object
readonly
Returns the value of attribute ref.
Instance Method Summary collapse
- #committer_user_ids ⇒ Object
- #committers(with_merge_commits: false, lazy: false, include_author_when_signed: false) ⇒ Object
- #committers_lazy(with_merge_commits: false, include_author_when_signed: false) ⇒ Object (also: #add_committers_to_batch_loader)
- #each(&block) ⇒ Object
-
#enrich! ⇒ Object
Batch load any commits that are not backed by full gitaly data, and replace them in the collection.
- #fully_enriched? ⇒ Boolean
-
#initialize(container, commits, ref = nil, page: nil, per_page: nil, count: nil) ⇒ CommitCollection
constructor
container - The object the commits belong to.
- #load_tags ⇒ Object
-
#method_missing(message, *args, &block) ⇒ Object
rubocop:disable GitlabSecurity/PublicSend.
- #next_page ⇒ Object
- #respond_to_missing?(message, inc_private = false) ⇒ Boolean
- #unenriched ⇒ Object
-
#with_latest_pipeline(ref = nil) ⇒ Object
Returns the collection with the latest pipeline for every commit pre-set.
-
#with_markdown_cache ⇒ Object
Returns the collection with markdown fields preloaded.
- #without_merge_commits ⇒ Object
Constructor Details
#initialize(container, commits, ref = nil, page: nil, per_page: nil, count: nil) ⇒ CommitCollection
container - The object the commits belong to. commits - The Commit instances to store. ref - The name of the ref (e.g. “master”).
16 17 18 19 20 21 |
# File 'app/models/commit_collection.rb', line 16 def initialize(container, commits, ref = nil, page: nil, per_page: nil, count: nil) @container = container @commits = commits @ref = ref @pagination = Gitlab::PaginationDelegate.new(page: page, per_page: per_page, count: count) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(message, *args, &block) ⇒ Object
rubocop:disable GitlabSecurity/PublicSend
144 145 146 |
# File 'app/models/commit_collection.rb', line 144 def method_missing(, *args, &block) commits.public_send(, *args, &block) end |
Instance Attribute Details
#commits ⇒ Object (readonly)
Returns the value of attribute commits.
8 9 10 |
# File 'app/models/commit_collection.rb', line 8 def commits @commits end |
#container ⇒ Object (readonly)
Returns the value of attribute container.
8 9 10 |
# File 'app/models/commit_collection.rb', line 8 def container @container end |
#ref ⇒ Object (readonly)
Returns the value of attribute ref.
8 9 10 |
# File 'app/models/commit_collection.rb', line 8 def ref @ref end |
Instance Method Details
#committer_user_ids ⇒ Object
59 60 61 |
# File 'app/models/commit_collection.rb', line 59 def committer_user_ids committers.pluck(:id) end |
#committers(with_merge_commits: false, lazy: false, include_author_when_signed: false) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'app/models/commit_collection.rb', line 27 def committers(with_merge_commits: false, lazy: false, include_author_when_signed: false) if lazy return committers_lazy( with_merge_commits: with_merge_commits, include_author_when_signed: ).flatten end User.by_any_email( committers_emails( with_merge_commits: with_merge_commits, include_author_when_signed: ) ) end |
#committers_lazy(with_merge_commits: false, include_author_when_signed: false) ⇒ Object Also known as: add_committers_to_batch_loader
43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'app/models/commit_collection.rb', line 43 def committers_lazy(with_merge_commits: false, include_author_when_signed: false) emails = committers_emails( with_merge_commits: with_merge_commits, include_author_when_signed: ) emails.map do |email| BatchLoader.for(email.downcase).batch(default_value: []) do |committer_emails, loader| User.by_any_email(committer_emails).each do |user| loader.call(user.email) { |memo| memo << user } end end end end |
#each(&block) ⇒ Object
23 24 25 |
# File 'app/models/commit_collection.rb', line 23 def each(&block) commits.each(&block) end |
#enrich! ⇒ Object
Batch load any commits that are not backed by full gitaly data, and replace them in the collection.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'app/models/commit_collection.rb', line 111 def enrich! # A container is needed in order to fetch data from gitaly. Containers # can be absent from commits in certain rare situations (like when # viewing a MR of a deleted fork). In these cases, assume that the # enriched data is not needed. return self if container.blank? || fully_enriched? # Batch load full Commits from the repository # and map to a Hash of id => Commit replacements = unenriched.each_with_object({}) do |c, result| result[c.id] = Commit.lazy(container, c.id) end.compact # Replace the commits, keeping the same order @commits = @commits.map do |original_commit| # Return the original instance: if it didn't need to be batchloaded, it was # already enriched. batch_loaded_commit = replacements.fetch(original_commit.id, original_commit) # If batch loading the commit failed, fall back to the original commit. # We need to explicitly check `.nil?` since otherwise a `BatchLoader` instance # that looks like `nil` is returned. batch_loaded_commit.nil? ? original_commit : batch_loaded_commit end self end |
#fully_enriched? ⇒ Boolean
105 106 107 |
# File 'app/models/commit_collection.rb', line 105 def fully_enriched? unenriched.empty? end |
#load_tags ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'app/models/commit_collection.rb', line 152 def oids = commits.map(&:id) references = repository.list_refs([Gitlab::Git::TAG_REF_PREFIX], pointing_at_oids: oids, peel_tags: true) oid_to_references = references.group_by { |reference| reference.peeled_target.presence || reference.target } return self if oid_to_references.empty? commits.each do |commit| grouped_references = oid_to_references[commit.id] next unless grouped_references commit.referenced_by = grouped_references.map(&:name) end self end |
#next_page ⇒ Object
148 149 150 |
# File 'app/models/commit_collection.rb', line 148 def next_page @pagination.next_page end |
#respond_to_missing?(message, inc_private = false) ⇒ Boolean
139 140 141 |
# File 'app/models/commit_collection.rb', line 139 def respond_to_missing?(, inc_private = false) commits.respond_to?(, inc_private) end |
#unenriched ⇒ Object
101 102 103 |
# File 'app/models/commit_collection.rb', line 101 def unenriched commits.reject(&:gitaly_commit?) end |
#with_latest_pipeline(ref = nil) ⇒ Object
Returns the collection with the latest pipeline for every commit pre-set.
Setting the pipeline for each commit ahead of time removes the need for running a query for every commit we’re displaying.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'app/models/commit_collection.rb', line 75 def with_latest_pipeline(ref = nil) return self unless project pipelines = project.ci_pipelines.latest_pipeline_per_commit(map(&:id), ref) each do |commit| pipeline = pipelines[commit.id] pipeline&.number_of_warnings # preload number of warnings commit.set_latest_pipeline_for_ref(ref, pipeline) end self end |
#with_markdown_cache ⇒ Object
Returns the collection with markdown fields preloaded.
Get the markdown cache from redis using pipeline to prevent n+1 requests when rendering the markdown of an attribute (e.g. title, full_title, description).
95 96 97 98 99 |
# File 'app/models/commit_collection.rb', line 95 def with_markdown_cache Commit.preload_markdown_cache!(commits) self end |
#without_merge_commits ⇒ Object
63 64 65 66 67 68 69 |
# File 'app/models/commit_collection.rb', line 63 def without_merge_commits strong_memoize(:without_merge_commits) do # `#enrich!` the collection to ensure all commits contain # the necessary parent data enrich!.commits.reject(&:merge_commit?) end end |