Class: Metior::CommitCollection

Inherits:
Collection show all
Defined in:
lib/metior/collections/commit_collection.rb

Overview

This class implements a collection of commits and provides functionality specific to commits.

See Also:

Author:

  • Sebastian Staudt

Instance Method Summary collapse

Methods inherited from Collection

#each, #last, #merge!

Constructor Details

#initialize(commits = []) ⇒ CommitCollection

Creates a new collection with the given commits

Parameters:

  • commits (Array<Commit>) (defaults to: [])

    The commits that should be initially inserted into the collection



24
25
26
27
28
29
# File 'lib/metior/collections/commit_collection.rb', line 24

def initialize(commits = [])
  @additions = nil
  @deletions = nil

  super
end

Instance Method Details

#<<(commit) ⇒ CommitCollection

Adds a commit to this collection

Parameters:

  • commit (Commit)

    The commit to add to this collection

Returns:



35
36
37
38
39
40
41
42
43
44
# File 'lib/metior/collections/commit_collection.rb', line 35

def <<(commit)
  return self if key? commit.id

  unless @additions.nil?
    @additions += commit.additions
    @deletions += commit.deletions
  end

  super
end

#activityHash<Symbol, Object>

Calculate some predefined activity statistics for the commits in this collection

Returns:

  • (Hash<Symbol, Object>)

    The calculated statistics for the commits in this collection

See Also:



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
# File 'lib/metior/collections/commit_collection.rb', line 52

def activity
  activity = {}
  commit_count = values.size

  active_days = {}
  each do |commit|
    date = commit.committed_date.utc
    day  = Time.utc(date.year, date.month, date.day)
    if active_days.key? day
      active_days[day] += 1
    else
      active_days[day] = 1
    end
  end

  most_active_day = active_days.sort_by { |day, count| count }.last.first

  activity[:first_commit_date] = last.committed_date
  activity[:last_commit_date]  = first.committed_date

  age_in_days = (Time.now - activity[:first_commit_date]) / 86400.0

  activity[:active_days]            = active_days
  activity[:most_active_day]        = most_active_day
  activity[:commits_per_day]        = commit_count / age_in_days
  activity[:commits_per_active_day] = commit_count.to_f / active_days.size

  activity
end

#additionsFixnum

Returns the lines of code that have been added by the commits in this collection

This will load the line stats from the commits if not done yet.

Returns:

  • (Fixnum)

     The lines of code that have been added

See Also:



89
90
91
92
93
94
# File 'lib/metior/collections/commit_collection.rb', line 89

def additions
  first.support! :line_stats

  load_line_stats if @additions.nil?
  @additions
end

#after(date) ⇒ CommitCollection Also known as: newer

Returns the commits in this collection that have been committed after the given time

Parameters:

  • date (Time, Date, DateTime, String)

    The time to use as the lower limit to filter the commits

Returns:

  • (CommitCollection)

    The commits that have been committed after the given date

See Also:



105
106
107
108
109
110
111
112
# File 'lib/metior/collections/commit_collection.rb', line 105

def after(date)
  date = Time.parse date if date.is_a? String
  commits = CommitCollection.new
  each do |commit|
    commits << commit if commit.committed_date > date
  end
  commits
end

#authors(commit_id = nil) ⇒ ActorCollection

Returns the authors of all or a specific commit in this collection

Parameters:

  • commit_id (Object) (defaults to: nil)

    The ID of the commit, if only the author of a specific commit should be returned

Returns:

  • (ActorCollection)

    All authors of the commits in this collection or the author of a specific commit

See Also:



122
123
124
125
126
127
128
129
130
# File 'lib/metior/collections/commit_collection.rb', line 122

def authors(commit_id = nil)
  authors = ActorCollection.new
  if commit_id.nil?
    each { |commit| authors << commit.author }
  elsif key? commit_id
    authors << self[commit_id].author
  end
  authors
end

#before(date) ⇒ CommitCollection Also known as: older

Returns the commits in this collection that have been committed before the given time

Parameters:

  • date (Time, Date, DateTime, String)

    The time to use as the upper limit to filter the commits

Returns:

  • (CommitCollection)

    The commits that have been committed after the given date

See Also:



141
142
143
144
145
146
147
148
# File 'lib/metior/collections/commit_collection.rb', line 141

def before(date)
  date = Time.parse date if date.is_a? String
  commits = CommitCollection.new
  each do |commit|
    commits << commit if commit.committed_date < date
  end
  commits
end

#by(*author_ids) ⇒ CommitCollection

Returns the list of commits that have been authored by the given authors

Parameters:

  • author_ids (Array<Actor, Object>)

    One or more actual Actor instances or IDs of the authors that the commits should be filtered by

Returns:

  • (CommitCollection)

    The commits that have been authored by the given authors

See Also:



159
160
161
162
163
164
165
166
167
168
# File 'lib/metior/collections/commit_collection.rb', line 159

def by(*author_ids)
  author_ids = author_ids.flatten.map do |author_id|
    author_id.is_a?(Actor) ? author_id.id : author_id
  end
  commits = CommitCollection.new
  each do |commit|
    commits << commit if author_ids.include? commit.author.id
  end
  commits
end

#changing(*files) ⇒ CommitCollection Also known as: touching

Returns the commits in this collection that change any of the given files

Parameters:

  • files (Array<String>)

    The path of the files to filter commits by

Returns:

See Also:



178
179
180
181
182
183
184
185
186
187
# File 'lib/metior/collections/commit_collection.rb', line 178

def changing(*files)
  first.support! :file_stats

  commits = CommitCollection.new
  each do |commit|
    commit_files = commit.added_files + commit.deleted_files + commit.modified_files
    commits << commit unless (commit_files & files).empty?
  end
  commits
end

#committers(commit_id = nil) ⇒ ActorCollection

Returns the committers of all or a specific commit in this collection

Parameters:

  • commit_id (Object) (defaults to: nil)

    The ID of the commit, if only the committer of a specific commit should be returned

Returns:

  • (ActorCollection)

    All committers of the commits in this collection or the committer of a specific commit

See Also:



197
198
199
200
201
202
203
204
205
# File 'lib/metior/collections/commit_collection.rb', line 197

def committers(commit_id = nil)
  committers = ActorCollection.new
  if commit_id.nil?
    each { |commit| committers << commit.committer }
  elsif key? commit_id
    committers << self[commit_id].committer
  end
  committers
end

#deletionsFixnum

Returns the lines of code that have been deleted by the commits in this collection

This will load the line stats from the commits if not done yet.

Returns:

  • (Fixnum)

     The lines of code that have been deleted

See Also:



214
215
216
217
218
219
# File 'lib/metior/collections/commit_collection.rb', line 214

def deletions
  first.support! :line_stats

  load_line_stats if @deletions.nil?
  @deletions
end

#line_historyHash<Symbol, Array>

This evaluates the changed lines in each commit of this collection

For easier use, the values are stored in separate arrays where each number represents the number of changed (i.e. added or deleted) lines in one commit.

Examples:

commits.line_history
=> { :additions => [10, 5, 0], :deletions => [0, -2, -1] }

Returns:

  • (Hash<Symbol, Array>)

    Added lines are returned in an Array assigned to key :additions, deleted lines are assigned to :deletions

See Also:



235
236
237
238
239
240
241
242
243
244
245
# File 'lib/metior/collections/commit_collection.rb', line 235

def line_history
  first.support! :line_stats

  history = { :additions => [], :deletions => [] }
  values.reverse.each do |commit|
    history[:additions] <<  commit.additions
    history[:deletions] << -commit.deletions
  end

  history
end

#load_line_statsObject (private)

Loads the line stats for all commits in this collection



298
299
300
301
302
303
304
305
# File 'lib/metior/collections/commit_collection.rb', line 298

def load_line_stats
  @additions = 0
  @deletions = 0
  each do |commit|
    @additions += commit.additions
    @deletions += commit.deletions
  end
end

#modificationsFixnum

Returns the total of lines changed by the commits in this collection

Returns:

  • (Fixnum)

     The total number of lines changed

See Also:



252
253
254
# File 'lib/metior/collections/commit_collection.rb', line 252

def modifications
  additions + deletions
end

#most_significant(count = 10) ⇒ CommitCollection Also known as: top

Returns the given number of commits with most line changes on the repository

Parameters:

  • count (Numeric) (defaults to: 10)

    The number of commits to return

Returns:

See Also:



262
263
264
265
266
267
268
269
270
271
# File 'lib/metior/collections/commit_collection.rb', line 262

def most_significant(count = 10)
  first.support! :line_stats

  commits = CommitCollection.new
  sort_by { |commit| -commit.modifications }.each do |commit|
    commits << commit
    break if commits.size == count
  end
  commits
end

#with_impact(line_count) ⇒ CommitCollection

Returns the commits in this collection that change at least the given number of lines

Parameters:

  • line_count (Numeric)

    The number of lines that should be changed at least by the commits

Returns:

  • (CommitCollection)

    The commits that change at least the given number of lines

See Also:



282
283
284
285
286
287
288
289
290
# File 'lib/metior/collections/commit_collection.rb', line 282

def with_impact(line_count)
  first.support! :line_stats

  commits = CommitCollection.new
  each do |commit|
    commits << commit if commit.modifications >= line_count
  end
  commits
end