Марк обнови решението на 23.11.2015 17:14 (преди около 9 години)
+require 'digest/sha1'
+
+class ReturnCommitObject
+
+ attr_accessor :date, :name, :objects, :store
+
+ def initialize()
+ @object = {}
+ @objects_to_remove = []
+ end
+
+ def message
+ message = "Nothing to commit, working directory clean."
+ success? ? "#{@name}" + "\n" + "\t#{ count } objects changed" : message
+ end
+
+ def count
+ @object.length + @objects_to_remove.size
+ end
+
+ def time
+ message = ""
+ message = "#{ @date.strftime("%a") } " + "#{ @date.strftime("%b") } "
+ message << "#{ @date.strftime("%d") } " + "#{ @date.strftime("%H") }"
+ message << ":#{ @date.strftime("%M") } " + "#{ @date.strftime("%Y") } "
+ message << "#{ @date.strftime('%z') }"
+ end
+
+ def hash
+ Digest::SHA1.hexdigest "#{time}#{name}"
+ end
+
+ def add(name,object)
+ @object[name] = object
+ end
+
+ def remove(name)
+ @objects_to_remove << name
+ end
+
+ def object
+ @object
+ end
+
+ def result
+ self
+ end
+
+ def find(name,object)
+ @object.each { |key,value| object = value if key == name }
+ end
+
+ def objects_to_remove
+ @objects_to_remove
+ end
+
+ def objects
+ @store.last.objects = @store.map {
+ |commit| commit.object.map { |key, value| value }
+ }.flatten
+ end
+
+ def success?
+ count > 0
+ end
+
+ def remove_objects
+ @objects_to_remove.each do |name|
+ remove_object(name)
+ end
+ end
+
+ def remove_object(name)
+ @store.each do |commit|
+ commit.object.delete_if { |key,value| key == name }
+ end
+ end
+ def error?
+ count == 0
+ end
+end
+
+class ObjectStore
+
+ def initialize ()
+ @store = []
+ @current_commit = ReturnCommitObject.new
+ @branch = Branch.new(@store)
+ end
+
+ def self.init(&block)
+ object = self.new
+ object.instance_eval &block if block_given?
+ object
+ end
+
+ def add(name, object)
+ @current_commit.add(name,object)
+ ReturnAddObject.new(name, object)
+ end
+
+ def commit(message)
+ @current_commit.store = @store
+ @current_commit.remove_objects
+ if (@current_commit.count != 0)
+ @current_commit.date, @current_commit.name = Time.now, message
+ @store << @current_commit.clone
+ @current_commit = ReturnCommitObject.new()
+ @store.last
+ else
+ ReturnCommitObject.new()
+ end
+ end
+
+ def remove(name)
+ condition = @store.any? do |commit|
+ commit.object.any? { |key,value| key == name }
+ end
+ @current_commit.remove(name) if condition
+ object = nil
+ @store.each do |commit|
+ commit.find(name, object)
+ end
+ ReturnRemoveObject.new(name, object)
+ end
+
+ def checkout(commit_hash)
+ if (@store.any? { |elem| elem.hash == commit_hash} )
+ while(@store.last.hash != commit_hash)
+ @store.pop
+ end
+ puts @store.last
+ ReturnCheckoutObject.new(@store.last, commit_hash)
+ else
+ ReturnCheckoutObject.new(nil, commit_hash)
+ end
+ end
+
+ def remove_object(name)
+ @store.each do |commit|
+ commit.object.delete_if { |key,value| key == name }
+ end
+ end
+ def log
+ ReturnLogObject.new(@store,branch.current_name)
+ end
+
+ def head
+ ReturnHeadObject.new(branch.current_name, @store)
+ end
+
+ def get(name)
+ object = nil
+ @store.each do |commit|
+ commit.find(name, object)
+ end
+ ReturnGetObject.new(name, object)
+ end
+
+ def branch
+ @branch
+ end
+
+ def to_s
+ @store.each { |commit| puts commit.object }
+ end
+end
+
+class ReturnGetObject
+ def initialize(name, object)
+ @name = name
+ @object = object
+ end
+
+ def message
+ success? ? "Found object #{@name}." : "Object #{@name} is not committed."
+ end
+
+ def result
+ @object
+ end
+
+ def success?
+ @object != nil
+ end
+
+ def error?
+ @object == nil
+ end
+end
+
+class ReturnLogObject
+ def initialize(store, name)
+ @store = store.clone
+ @name = name
+ end
+
+ def message
+ if(success?)
+ messages = @store.reverse.map do |commit|
+ message = "Commit #{commit.hash}\nDate: #{commit.time}\n\n\t#{commit.name}"
+ end
+ messages.join("\n\n")
+ else
+ "Branch #{@name} does not have any commits yet."
+ end
+ end
+
+ def success?
+ @store != []
+ end
+
+ def error?
+ @store == []
+ end
+end
+
+class ReturnHeadObject
+ def initialize(name,store)
+ @name = name
+ @store = store.clone
+ end
+
+ def message
+ message = "Branch #{@name} does not have any commits yet."
+ success? ? "#{@store.last.name}" : message
+ end
+
+ def result
+ result = @store.last
+ end
+
+ def success?
+ @store != []
+ end
+
+ def error?
+ @store == []
+ end
+end
+
+class ReturnAddObject
+ def initialize(name, object)
+ @name = name
+ @object = object
+ end
+
+ def message
+ "Added #{@name} to stage."
+ end
+
+ def result
+ @object
+ end
+
+ def success?
+ true
+ end
+
+ def error?
+ false
+ end
+end
+
+class ReturnRemoveObject
+ def initialize(name, object)
+ @name = name
+ @object = object
+ end
+
+ def message
+ message = "Object #{@name} is not committed."
+ success? ? "Added #{@name} for removal." : message
+ end
+
+ def result
+ @object
+ end
+
+ def success?
+ @object != nil
+ end
+
+ def error?
+ @object == nil
+ end
+end
+
+class ReturnCheckoutObject
+ def initialize(commit, commit_hash)
+ @commit = commit
+ @commit_hash = commit_hash
+ end
+
+ def message
+ message = "Commit #{@commit_hash} does not exist."
+ success? ? "HEAD is now at #{@commit_hash}." : message
+ end
+
+ def result
+ @commit
+ end
+
+ def success?
+ @commit != nil
+ end
+
+ def error?
+ @commit == nil
+ end
+end
+
+class BranchCreateObject
+ def initialize(flag, branch_name)
+ @name = branch_name
+ @flag = flag
+ end
+
+ def message
+ message = "Branch #{ @name } already exists."
+ success? ? "Created branch #{ @name }." : message
+ end
+
+ def success?
+ @flag == true
+ end
+
+ def error?
+ @flag != true
+ end
+end
+
+class BranchChechoutObject
+ def initialize(flag, store, branch_name)
+ @name = branch_name
+ @store = store.clone
+ @flag = flag
+ end
+
+ def message
+ message = "Branch #{ @name } does not exist."
+ success? ? "Switched to branch #{ @name }." : message
+ end
+
+ def result
+ @store
+ end
+
+ def success?
+ @flag == true
+ end
+
+ def error?
+ @flag != true
+ end
+end
+
+class BranchRemoveObject
+ def initialize(message, branch_name)
+ @name = branch_name
+ @message = message
+ end
+
+ def message
+ case @message
+ when 1
+ "Removed branch #{@name}."
+ when 2
+ "Cannot remove current branch."
+ when 3
+ "Branch #{@name} does not exist."
+ end
+ end
+
+ def success?
+ @message == 1
+ end
+
+ def error?
+ @message != 1
+ end
+end
+
+class BranchListObject
+ def initialize(branches, current_name)
+ @branches = branches.clone
+ @current_name = current_name
+ end
+
+ def message
+ message = ""
+ @branches.keys.sort.each do |elem|
+ elem == @current_name ? message << "* #{elem}\n" : message << " #{elem}\n"
+ end
+ message.chomp
+ end
+
+ def result
+ @branches
+ end
+
+ def success?
+ true
+ end
+
+ def error?
+ false
+ end
+end
+
+class Branch
+
+ attr_accessor :current_name
+
+ def initialize(store)
+ @current_store = store
+ @current_name = "master"
+ @branches = { "master" => store }
+ end
+
+ def create(branch_name)
+ if (@branches.has_key?(branch_name))
+ BranchCreateObject.new(false, branch_name)
+ else
+ @branches[branch_name] = @current_store.clone
+ BranchCreateObject.new(true, branch_name)
+ end
+ end
+
+ def checkout(branch_name)
+ if (@branches.has_key?(branch_name))
+ @branches[@current_name] = @current_store.clone
+ @current_name = branch_name
+ @current_store.replace(@branches[branch_name])
+ BranchChechoutObject.new(true, @current_store, branch_name)
+ else
+ BranchChechoutObject.new(false, @current_name, branch_name)
+ end
+ end
+
+ def remove(branch_name)
+ if(@branches.has_key?(branch_name))
+ if(branch_name == @current_name)
+ BranchRemoveObject.new(2, branch_name)
+ else
+ @branches.delete(branch_name)
+ BranchRemoveObject.new(1, branch_name)
+ end
+ else
+ BranchRemoveObject.new(3, branch_name)
+ end
+ end
+
+ def list()
+ BranchListObject.new(@branches, @current_name)
+ end
+
+ def to_s
+ @branches.each { |key,value|
+ puts "#{key}"
+ value.each { |commit| puts commit.object } }
+ end
+
+ def to_sto
+ puts @current_name
+ @current_store.each { |commit| puts commit.object }
+ end
+end