class Eternity::Repository
Attributes
branches[R]
current[R]
id[R]
locker[R]
name[R]
tracker[R]
Public Class Methods
all()
click to toggle source
# File lib/eternity/repository.rb, line 174 def self.all sections_count = Eternity.keyspace[:repository].sections.count names = Eternity.connection.call('KEYS', Eternity.keyspace[:repository]['*']).map do |key| Restruct::Id.new(key).sections[sections_count] end.uniq names.map { |name| new name } end
new(name, options={})
click to toggle source
# File lib/eternity/repository.rb, line 6 def initialize(name, options={}) @name = name.to_s @id = Eternity.keyspace[:repository][@name] @tracker = Tracker.new self @current = Restruct::Hash.new connection: Eternity.connection, id: id[:current] @branches = Restruct::Hash.new connection: Eternity.connection, id: id[:branches] @locker = Eternity.locker_for @name @default_branch = options.fetch(:default_branch, 'master').to_s end
Public Instance Methods
[](collection)
click to toggle source
# File lib/eternity/repository.rb, line 16 def [](collection) tracker[collection] end
branch(name)
click to toggle source
# File lib/eternity/repository.rb, line 67 def branch(name) raise "Can't branch without commit" unless current_commit? raise "Can't branch with uncommitted changes" if changes? branches[name] = current_commit.id end
changes?()
click to toggle source
# File lib/eternity/repository.rb, line 24 def changes? !tracker.empty? end
changes_count()
click to toggle source
# File lib/eternity/repository.rb, line 28 def changes_count tracker.count end
checkout(options)
click to toggle source
# File lib/eternity/repository.rb, line 74 def checkout(options) raise "Can't checkout with uncommitted changes" if changes? locker.lock! :checkout do Eternity.logger.info(self.class) { "Checkout #{name} (#{options.map { |k,v| "#{k}: #{v}" }.join(', ')})" } original_commit = current_commit commit_id, branch = extract_commit_and_branch options if commit_id raise "Invalid commit #{commit_id}" unless Commit.exists? commit_id current[:commit] = commit_id branches[branch] = commit_id else current.delete :commit branches.delete branch end current[:branch] = branch Patch.diff original_commit, current_commit end end
commit(options)
click to toggle source
# File lib/eternity/repository.rb, line 58 def commit(options) raise 'Nothing to commit' unless changes? locker.lock! :commit do commit! message: options.fetch(:message), author: options.fetch(:author) end end
current_branch()
click to toggle source
# File lib/eternity/repository.rb, line 54 def current_branch current[:branch] || @default_branch end
current_commit()
click to toggle source
# File lib/eternity/repository.rb, line 50 def current_commit Commit.new current[:commit] end
current_commit?()
click to toggle source
# File lib/eternity/repository.rb, line 46 def current_commit? current.key? :commit end
delta()
click to toggle source
# File lib/eternity/repository.rb, line 32 def delta tracker.flatten end
delta=(delta)
click to toggle source
# File lib/eternity/repository.rb, line 36 def delta=(delta) tracker.clear delta.each do |collection, changes| changes.each do |id, change| args = [id, change['data']].compact self[collection].send(change['action'], *args) end end end
destroy()
click to toggle source
# File lib/eternity/repository.rb, line 153 def destroy tracker.destroy current.destroy branches.destroy end
empty?()
click to toggle source
# File lib/eternity/repository.rb, line 20 def empty? tracker.empty? && current.empty? && branches.empty? end
log()
click to toggle source
# File lib/eternity/repository.rb, line 149 def log current_commit? ? ([current_commit] + current_commit.history) : [] end
merge(options)
click to toggle source
# File lib/eternity/repository.rb, line 99 def merge(options) raise "Can't merge with uncommitted changes" if changes? commit_id = extract_commit options raise "Invalid commit #{commit_id}" unless Commit.exists? commit_id merge! Commit.new(commit_id) end
pull()
click to toggle source
# File lib/eternity/repository.rb, line 122 def pull raise "Can't pull with uncommitted changes" if changes? raise "Branch not found: #{current_branch}" unless Branch.exists? current_branch target_commit = Branch[current_branch] Eternity.logger.info(self.class) { "Pull #{name} (#{target_commit.id})" } if current_commit == target_commit || current_commit.fast_forward?(target_commit) Patch.merge current_commit, target_commit elsif target_commit.fast_forward?(current_commit) checkout commit: target_commit.id else merge! target_commit end end
push()
click to toggle source
# File lib/eternity/repository.rb, line 109 def push raise 'Push rejected (non fast forward)' if current_commit != Branch[current_branch] && !current_commit.fast_forward?(Branch[current_branch]) push! end
push!()
click to toggle source
# File lib/eternity/repository.rb, line 114 def push! raise "Can't push without commit" unless current_commit? Eternity.logger.info(self.class) { "Push #{name} (#{current_commit.id})" } Branch[current_branch] = current_commit.id end
restore(dump)
click to toggle source
# File lib/eternity/repository.rb, line 168 def restore(dump) current.merge! dump['current'] branches.merge! dump['branches'] self.delta = dump['delta'] end
revert()
click to toggle source
# File lib/eternity/repository.rb, line 139 def revert locker.lock! :revert do Eternity.logger.info(self.class) { "Revert #{name}" } current_commit.with_index do |index| Delta.revert(delta, index).tap { tracker.revert } end end end
to_h()
click to toggle source
# File lib/eternity/repository.rb, line 159 def to_h { 'current' => current.to_h, 'branches' => branches.to_h, 'delta' => delta } end
Also aliased as: dump
Private Instance Methods
commit!(options)
click to toggle source
# File lib/eternity/repository.rb, line 186 def commit!(options) Eternity.logger.info(self.class) { "Commit #{name} (author: #{options[:author]}, message: #{options[:message]})" } changes = delta options[:parents] ||= [current_commit.id] options[:delta] ||= write_delta changes options[:index] ||= write_index changes Commit.create(options).tap do |commit| current[:commit] = commit.id current[:branch] = current_branch branches[current_branch] = commit.id tracker.clear end end
extract_commit(options)
click to toggle source
# File lib/eternity/repository.rb, line 231 def extract_commit(options) extract_commit_and_branch(options).first end
extract_commit_and_branch(options)
click to toggle source
# File lib/eternity/repository.rb, line 235 def extract_commit_and_branch(options) branch = options.fetch(:branch) { current_branch } commit_id = options.fetch(:commit) do if branches.key? branch branches[branch] elsif Branch.exists?(branch) Branch[branch].id else raise "Invalid branch #{branch}" end end [commit_id, branch] end
merge!(target_commit)
click to toggle source
# File lib/eternity/repository.rb, line 202 def merge!(target_commit) locker.lock! :merge do Eternity.logger.info(self.class) { "Merge #{name} (#{target_commit.short_id} into #{current_commit.short_id})" } patch = Patch.merge current_commit, target_commit raise 'Already merged' if patch.merged? commit! message: "Merge #{target_commit.short_id} into #{current_commit.short_id} (#{name})", author: 'System', parents: [current_commit.id, target_commit.id], index: write_index(patch.delta), base: patch.base_commit.id patch end end
write_delta(delta)
click to toggle source
# File lib/eternity/repository.rb, line 227 def write_delta(delta) Blob.write :delta, delta end
write_index(delta)
click to toggle source
# File lib/eternity/repository.rb, line 220 def write_index(delta) current_commit.with_index do |index| index.apply delta index.write_blob end end