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  |