Class: Metior::Repository Abstract
- Includes:
- AutoIncludeVCS
- Defined in:
- lib/metior/repository.rb
Overview
It has to be subclassed to implement a repository representation for a specific VCS.
This class represents a source code repository.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#path ⇒ String
readonly
The file system path of this repository.
Instance Method Summary collapse
-
#actor(actor) ⇒ Actor
Returns a single VCS specific actor object from the raw data of the actor provided by the VCS implementation.
-
#authors(range = self.class::DEFAULT_BRANCH) ⇒ ActorCollection
(also: #contributors)
Returns all authors from the given commit range in a hash where the IDs of the authors are the keys and the authors are the values.
-
#branches ⇒ Array<String>
Returns the names of all branches of this repository.
-
#build_commits(raw_commits) ⇒ Array<Commit>
private
Builds VCS specific commit objects for each given commit's raw data that is provided by the VCS implementation.
-
#cached_commits(range) ⇒ Array<Commit>
private
Tries to retrieve as many commits as possible in the given commit range from the commit cache.
-
#commits(range = self.class::DEFAULT_BRANCH) ⇒ CommitCollection
Loads all commits including their committers and authors from the given commit range.
-
#committers(range = self.class::DEFAULT_BRANCH) ⇒ ActorCollection
(also: #collaborators)
Returns all committers from the given commit range in a hash where the IDs of the committers are the keys and the committers are the values.
-
#description ⇒ String
Returns the description of the project contained in the repository.
-
#file_stats(range = self.class::DEFAULT_BRANCH) ⇒ Hash<String, Hash<Symbol, Object>>
This evaluates basic statistics about the files in a given commit range.
-
#id_for_ref(ref) ⇒ Object
private
abstract
Returns the unique identifier for the commit the given reference – like a branch name – is pointing to.
-
#initialize(path) ⇒ Repository
constructor
Creates a new repository instance with the given file system path.
-
#line_history(range = self.class::DEFAULT_BRANCH) ⇒ Hash<Symbol, Array>
This evaluates the changed lines in each commit of the given commit range.
-
#load_branches ⇒ Hash<String, Object>
private
abstract
Loads all branches and the corresponding commit IDs of this repository.
-
#load_commits(range = self.class::DEFAULT_BRANCH) ⇒ Array<Commit>
private
abstract
Loads all commits from the given commit range.
-
#load_description ⇒ Object
private
abstract
Loads the description of the project contained in the repository.
-
#load_name ⇒ Object
private
abstract
Loads the name of the project contained in the repository.
-
#load_tags ⇒ Hash<String, Object>
private
abstract
Loads all tags and the corresponding commit IDs of this repository.
-
#name ⇒ String
Returns the name of the project contained in the repository.
-
#parse_range(range) ⇒ Range
private
Parses a string or range of commit IDs or ref names into the coresponding range of unique commit IDs.
-
#significant_authors(range = self.class::DEFAULT_BRANCH, count = 3) ⇒ Array<Actor>
(also: #significant_contributors)
Returns a list of authors with the biggest impact on the repository, i.e.
-
#significant_commits(range = self.class::DEFAULT_BRANCH, count = 10) ⇒ Array<Actor>
Returns a list of commits with the biggest impact on the repository, i.e.
-
#tags ⇒ Array<String>
Returns the names of all tags of this repository.
-
#top_authors(range = self.class::DEFAULT_BRANCH, count = 3) ⇒ Array<Actor>
(also: #top_contributors)
Returns a list of top contributors in the given commit range.
Methods included from AutoIncludeVCS
Constructor Details
#initialize(path) ⇒ Repository
Creates a new repository instance with the given file system path
27 28 29 30 31 32 33 34 |
# File 'lib/metior/repository.rb', line 27 def initialize(path) @actors = {} @commits = {} @description = nil @name = nil @path = path @refs = {} end |
Instance Attribute Details
#path ⇒ String (readonly)
Returns The file system path of this repository.
22 23 24 |
# File 'lib/metior/repository.rb', line 22 def path @path end |
Instance Method Details
#actor(actor) ⇒ Actor
Returns a single VCS specific actor object from the raw data of the actor provided by the VCS implementation
The actor object is either created from the given raw data or retrieved from the cache using the VCS specific unique identifier of the actor.
45 46 47 48 |
# File 'lib/metior/repository.rb', line 45 def actor(actor) id = self.class::Actor.id_for(actor) @actors[id] ||= self.class::Actor.new(self, actor) end |
#authors(range = self.class::DEFAULT_BRANCH) ⇒ ActorCollection Also known as: contributors
Returns all authors from the given commit range in a hash where the IDs of the authors are the keys and the authors are the values
This will call commits(range)
if the authors for the commit range are
not known yet.
63 64 65 |
# File 'lib/metior/repository.rb', line 63 def (range = self.class::DEFAULT_BRANCH) commits(range). end |
#branches ⇒ Array<String>
Returns the names of all branches of this repository
71 72 73 |
# File 'lib/metior/repository.rb', line 71 def branches load_branches.each { |name, id| @refs[name] = id }.keys.sort end |
#build_commits(raw_commits) ⇒ Array<Commit> (private)
Builds VCS specific commit objects for each given commit's raw data that is provided by the VCS implementation
The raw data will be transformed into commit objects that will also be saved into the commit cache. Authors and committers of the given commits will be created and stored into the cache or loaded from the cache if they already exist. Additionally this method will establish an association between the commits and their children.
305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/metior/repository.rb', line 305 def build_commits(raw_commits) child_commit_id = nil raw_commits.map do |commit| commit = self.class::Commit.new(self, commit) commit.add_child child_commit_id unless child_commit_id.nil? child_commit_id = commit.id @commits[commit.id] = commit @actors[commit..id] ||= commit. commit end end |
#cached_commits(range) ⇒ Array<Commit> (private)
Tries to retrieve as many commits as possible in the given commit range from the commit cache
This method calls itself recursively to walk the given commit range either from the start to the end or vice versa depending on which commit could be found in the cache.
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# File 'lib/metior/repository.rb', line 330 def cached_commits(range) commits = [] direction = nil if @commits.key? range.last current_commits = [@commits[range.last]] direction = :parents elsif @commits.key? range.first current_commits = [@commits[range.first]] direction = :children end unless direction.nil? while !current_commits.empty? do new_commits = [] current_commits.each do |commit| new_commits += commit.send direction commits << commit if commit.id != range.first if direction == :parents && new_commits.include?(range.first) new_commits = [] break end end unless new_commits.include? range.first current_commits = new_commits.uniq.map do |commit| commit = @commits[commit] commits.include?(commit) ? nil : commit end.compact end end end commits.sort_by { |c| c.committed_date }.reverse end |
#commits(range = self.class::DEFAULT_BRANCH) ⇒ CommitCollection
Loads all commits including their committers and authors from the given commit range
84 85 86 87 88 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 'lib/metior/repository.rb', line 84 def commits(range = self.class::DEFAULT_BRANCH) range = parse_range range commits = cached_commits range if commits.empty? base_commit, raw_commits = load_commits(range) commits = commits + build_commits(raw_commits) unless base_commit.nil? base_commit = self.class::Commit.new(self, base_commit) base_commit.add_child commits.last.id @commits[base_commit.id] = base_commit end else if range.first == '' unless commits.last.parents.empty? raw_commits = load_commits(''..commits.last.id).last commits += build_commits raw_commits[0..-2] end else if commits.first.id != range.last raw_commits = load_commits(commits.first.id..range.last).last commits = build_commits(raw_commits) + commits end unless commits.last.parents.include? range.first raw_commits = load_commits(range.first..commits.last.id).last commits += build_commits raw_commits end end end CommitCollection.new commits end |
#committers(range = self.class::DEFAULT_BRANCH) ⇒ ActorCollection Also known as: collaborators
Returns all committers from the given commit range in a hash where the IDs of the committers are the keys and the committers are the values
This will call commits(range)
if the committers for the commit range
are not known yet.
130 131 132 |
# File 'lib/metior/repository.rb', line 130 def committers(range = self.class::DEFAULT_BRANCH) commits(range).committers end |
#description ⇒ String
Returns the description of the project contained in the repository
This will load the description through a VCS specific mechanism if required.
142 143 144 145 |
# File 'lib/metior/repository.rb', line 142 def description load_description if @description.nil? @description end |
#file_stats(range = self.class::DEFAULT_BRANCH) ⇒ Hash<String, Hash<Symbol, Object>>
This evaluates basic statistics about the files in a given commit range.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/metior/repository.rb', line 172 def file_stats(range = self.class::DEFAULT_BRANCH) support! :line_stats stats = {} commits(range).each_value do |commit| commit.added_files.each do |file| stats[file] = { :modifications => 0 } unless stats.key? file stats[file][:added_date] = commit. stats[file][:modifications] += 1 end commit.modified_files.each do |file| stats[file] = { :modifications => 0 } unless stats.key? file stats[file][:last_modified_date] = commit. stats[file][:modifications] += 1 end commit.deleted_files.each do |file| stats[file] = { :modifications => 0 } unless stats.key? file stats[file][:deleted_date] = commit. end end stats end |
#id_for_ref(ref) ⇒ Object (private)
Has to be implemented by VCS subclasses
Returns the unique identifier for the commit the given reference – like a branch name – is pointing to
372 373 374 |
# File 'lib/metior/repository.rb', line 372 def id_for_ref(ref) raise NotImplementedError end |
#line_history(range = self.class::DEFAULT_BRANCH) ⇒ Hash<Symbol, Array>
This evaluates the changed lines in each commit of the given commit range.
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.
215 216 217 |
# File 'lib/metior/repository.rb', line 215 def line_history(range = self.class::DEFAULT_BRANCH) commits(range).line_history end |
#load_branches ⇒ Hash<String, Object> (private)
Has to be implemented by VCS specific subclasses
Loads all branches and the corresponding commit IDs of this repository
381 382 383 |
# File 'lib/metior/repository.rb', line 381 def load_branches raise NotImplementedError end |
#load_commits(range = self.class::DEFAULT_BRANCH) ⇒ Array<Commit> (private)
Has to be implemented by VCS specific subclasses
Loads all commits from the given commit range
394 395 396 |
# File 'lib/metior/repository.rb', line 394 def load_commits(range = self.class::DEFAULT_BRANCH) raise NotImplementedError end |
#load_description ⇒ Object (private)
Has to be implemented by VCS specific subclasses
Loads the description of the project contained in the repository
402 403 404 |
# File 'lib/metior/repository.rb', line 402 def load_description raise NotImplementedError end |
#load_name ⇒ Object (private)
Has to be implemented by VCS specific subclasses
Loads the name of the project contained in the repository
410 411 412 |
# File 'lib/metior/repository.rb', line 410 def load_name raise NotImplementedError end |
#load_tags ⇒ Hash<String, Object> (private)
Has to be implemented by VCS specific subclasses
Loads all tags and the corresponding commit IDs of this repository
419 420 421 |
# File 'lib/metior/repository.rb', line 419 def raise NotImplementedError end |
#name ⇒ String
Returns the name of the project contained in the repository
This will load the name through a VCS specific mechanism if required.
225 226 227 228 |
# File 'lib/metior/repository.rb', line 225 def name load_name if @name.nil? @name end |
#parse_range(range) ⇒ Range (private)
Parses a string or range of commit IDs or ref names into the coresponding range of unique commit IDs
430 431 432 433 434 435 436 437 438 |
# File 'lib/metior/repository.rb', line 430 def parse_range(range) unless range.is_a? Range range = range.to_s.split '..' range = ((range.size == 1) ? '' : range.first)..range.last end range = id_for_ref(range.first)..range.last if range.first != '' range.first..id_for_ref(range.last) end |
#significant_authors(range = self.class::DEFAULT_BRANCH, count = 3) ⇒ Array<Actor> Also known as: significant_contributors
Returns a list of authors with the biggest impact on the repository, i.e. changing the most code
242 243 244 |
# File 'lib/metior/repository.rb', line 242 def (range = self.class::DEFAULT_BRANCH, count = 3) (range).most_significant(count) end |
#significant_commits(range = self.class::DEFAULT_BRANCH, count = 10) ⇒ Array<Actor>
Returns a list of commits with the biggest impact on the repository, i.e. changing the most code
259 260 261 |
# File 'lib/metior/repository.rb', line 259 def significant_commits(range = self.class::DEFAULT_BRANCH, count = 10) commits(range).most_significant(count) end |
#tags ⇒ Array<String>
Returns the names of all tags of this repository
266 267 268 |
# File 'lib/metior/repository.rb', line 266 def .each { |name, id| @refs[name] = id }.keys.sort end |
#top_authors(range = self.class::DEFAULT_BRANCH, count = 3) ⇒ Array<Actor> Also known as: top_contributors
Returns a list of top contributors in the given commit range
This will first have to load all authors (and i.e. commits) from the given commit range.
284 285 286 |
# File 'lib/metior/repository.rb', line 284 def (range = self.class::DEFAULT_BRANCH, count = 3) (range).top(count) end |