Мариян обнови решението на 23.11.2015 14:16 (преди над 9 години)
+require 'digest'
+
+class OperationResult
+ attr_reader :message, :result
+
+ def initialize(message, is_successful, result = nil)
+ @message = message
+ @is_successful = is_successful
+ @result = result
+ end
+
+ def success?
+ @is_successful
+ end
+
+ def error?
+ not @is_successful
+ end
+end
+
+class Commit
+ attr_reader :objects_hash, :message, :parent, :date, :hash
+
+ def initialize(objects, message, parent)
+ @objects_hash = objects.dup
+ @message = message.dup
+ @parent = parent
+ @date = Time.now
+ formatted_date = @date.strftime "%a %b %d %H:%M %Y %z"
+ @hash = Digest::SHA1.hexdigest "#{formatted_date}#{message}"
+ end
+
+ def result
+ self
+ end
+
+ def objects
+ @objects_hash.to_a
+ end
+
+ def to_s
+ formatted_date = @date.strftime "%a %b %d %H:%M %Y %z"
+ "Commit #{@hash}\nDate: #{formatted_date}\n\n\t#{@message}"
+ end
+end
+
+class Branch
+ attr_reader :name
+ attr_accessor :last_commit
+
+ def initialize(context, name)
+ @context = context
+ @name = name.dup
+ @context.branches.insert 0, self
+ end
+
+ def create(branch_name)
+ if @context.branches.any? { |branch| branch.name == branch_name }
+ OperationResult.new("Branch #{branch_name} already exists.", false)
+ else
+ self.class.new(@context, branch_name)
+ OperationResult.new("Created branch #{branch_name}.", true)
+ end
+ end
+
+ def checkout(branch_name)
+ branch_found = @context.branches.find do |branch|
+ branch.name == branch_name
+ end
+ if branch_found == nil
+ OperationResult.new("Branch #{branch_name} does not exist.", false)
+ else
+ @context.branch = branch_found
+ OperationResult.new("Switched to branch #{branch_name}.", true)
+ end
+ end
+
+ def remove(branch_name)
+ if @context.branch.name == branch_name
+ OperationResult.new("Cannot remove current branch.", false)
+ elsif @context.branches.none? { |branch| branch.name == branch_name }
+ OperationResult.new("Branch #{branch_name} does not exist.", false)
+ else
+ @context.branches.delete_if { |branch| branch.name == branch_name }
+ OperationResult.new("Removed branch #{branch_name}.", true)
+ end
+ end
+
+ def list
+ message = @context.branches.map do |branch|
+ branch_name = branch == @context.branch ? "* " : " "
+ branch_name << branch.name
+ end.join "\n"
+ OperationResult.new(message, true)
+ end
+end
+
+class ObjectStore
+ attr_reader :branches
+ attr_accessor :branch
+
+ def initialize(&block)
+ @to_be_added = {}
+ @to_be_removed = []
+ @branches = []
+ @branch = Branch.new(self, "master")
+ instance_eval &block if block_given?
+ end
+
+ def head
+ @branch.last_commit
+ end
+
+ def add(name, object)
+ @to_be_added[name] = object
+ @to_be_removed.delete name
+ OperationResult.new("Added #{name} to stage.", true, object)
+ end
+
+ def remove(name)
+ if head != nil and head.objects_hash.key? name
+ deleted_object = head.objects_hash[name]
+ @to_be_added.delete name
+ @to_be_removed << name
+ OperationResult.new("Added #{name} for removal.", true, deleted_object)
+ else
+ OperationResult.new("Object #{name} is not committed.", false)
+ end
+ end
+
+ def commit(message)
+ changed_objects = @to_be_added.size + @to_be_removed.size
+ if changed_objects == 0
+ OperationResult.new("Nothing to commit, working directory clean.", false)
+ else
+ objects = head == nil ? {} : @branch.last_commit.objects_hash
+ objects.merge!(@to_be_added)
+ @to_be_removed.each { |name| objects.delete name }
+ [@to_be_added, @to_be_removed].each { |object| object.clear }
+ @branch.last_commit = Commit.new(objects, message, @branch.last_commit)
+ message = "#{message}\n\t#{changed_objects} objects changed"
+ OperationResult.new(message, true, @branch.last_commit)
+ end
+ end
+
+ def checkout(commit_hash)
+ commit = head
+ until commit == nil or commit.hash == commit_hash
+ commit = commit.parent
+ end
+ if commit == nil
+ OperationResult.new("Commit #{commit_hash} does not exist.", false)
+ else
+ @branch.last_commit = commit
+ OperationResult.new("HEAD is now at #{commit_hash}.", true, head)
+ end
+ end
+
+ def get(name)
+ if head == nil or not head.objects_hash.key?(name)
+ OperationResult.new("Object #{name} is not committed.", false)
+ else
+ object = head.objects_hash[name]
+ OperationResult.new("Found object #{name}.", true, object)
+ end
+ end
+
+ def log
+ if head == nil
+ message = "Branch #{branch.name} does not have any commits yet."
+ OperationResult.new(message, false)
+ else
+ message = ""
+ commit = head
+ until commit == nil
+ message << commit.to_s
+ message << "\n\n"
+ commit = commit.parent
+ end
+ OperationResult.new(message.chomp("\n\n"), true)
+ end
+ end
+end
+
+class << ObjectStore
+ alias :init :new
+end