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) ⇒ Object
- #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
122 123 124 |
# File 'app/models/commit_collection.rb', line 122 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
37 38 39 |
# File 'app/models/commit_collection.rb', line 37 def committer_user_ids committers.pluck(:id) end |
#committers(with_merge_commits: false) ⇒ Object
27 28 29 30 31 32 33 34 35 |
# File 'app/models/commit_collection.rb', line 27 def committers(with_merge_commits: false) emails = if with_merge_commits commits.filter_map(&:committer_email).uniq else without_merge_commits.filter_map(&:committer_email).uniq end User.by_any_email(emails) 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.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'app/models/commit_collection.rb', line 89 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
83 84 85 |
# File 'app/models/commit_collection.rb', line 83 def fully_enriched? unenriched.empty? end |
#load_tags ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'app/models/commit_collection.rb', line 130 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
126 127 128 |
# File 'app/models/commit_collection.rb', line 126 def next_page @pagination.next_page end |
#respond_to_missing?(message, inc_private = false) ⇒ Boolean
117 118 119 |
# File 'app/models/commit_collection.rb', line 117 def respond_to_missing?(, inc_private = false) commits.respond_to?(, inc_private) end |
#unenriched ⇒ Object
79 80 81 |
# File 'app/models/commit_collection.rb', line 79 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.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/models/commit_collection.rb', line 53 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).
73 74 75 76 77 |
# File 'app/models/commit_collection.rb', line 73 def with_markdown_cache Commit.preload_markdown_cache!(commits) self end |
#without_merge_commits ⇒ Object
41 42 43 44 45 46 47 |
# File 'app/models/commit_collection.rb', line 41 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 |