Пламен обнови решението на 23.11.2015 15:57 (преди около 9 години)
+require 'base64'
+require 'date'
+
+class ObjectStore
+
+ attr_accessor :branch_list, :current_branch
+
+ def initialize
+ @current_branch = Branch.new("master", self)
+ @branch_list = [@current_branch]
+ end
+
+ def self.init
+ ObjectStore.new
+ end
+
+ def branch
+ @current_branch
+ end
+
+ def add(name, object)
+ @current_branch.objects_to_add << [name, object]
+ object = @current_branch.objects_to_add[-1][1]
+ message = "Added #{@current_branch.objects_to_add[-1][0]} to storage."
+ GoodResponse.new(message, object)
+ end
+
+ def make_changes
+ @current_branch.current_objects -= @current_branch.objects_to_remove
+ @current_branch.current_objects += @current_branch.objects_to_add
+ @current_branch.objects_to_remove = []
+ @current_branch.objects_to_add = []
+ end
+
+ def calculate_changes
+ changes = 0
+ changes += @current_branch.objects_to_add.size
+ changes += @current_branch.objects_to_remove.size
+ end
+
+ def commit(comment)
+ changes = calculate_changes
+ if changes == 0
+ BadResponse.new("Nothing to commit, working directory clean.")
+ else
+ make_changes
+ key = Base64.encode64(DateTime.now.to_s + comment)
+ comment_info = [@current_branch.current_objects, comment, DateTime.now]
+ @current_branch.commits[key] = comment_info
+ last_values = @current_branch.commits.values.last
+ @head = Commit.new(last_values, @current_branch.commits.keys.last)
+ GoodResponse.new("#{comment}\n\t#{changes} objects changed",@head)
+ end
+ end
+
+ def remove(name)
+ response = BadResponse.new("Object #{name} is not committed.")
+ @current_branch.current_objects.each do |object|
+ if object[0] == name
+ @current_branch.objects_to_remove << object
+ response = GoodResponse.new("Added #{name} for removal.",object)
+ end
+ end
+ response
+ end
+
+ def clean_commits(commits, hash)
+ commits.each do |key, commit|
+ if clean
+ commits.delete(key)
+ end
+
+ if key == hash
+ clean = true
+ end
+ end
+ commits
+ end
+
+ def checkout(commit_hash)
+ if @current_branch.commits.has_key?(commit_hash)
+ clean_commits(@current_branch.commits, commit_hash)
+ @current_branch.current_objects = @current_branch.commits[commit_hash]
+ commit = @current_branch.commits[commit_hash]
+ GoodResponse.new("HEAD is now at #{commit_hash}.", commit)
+ else
+ BadResponse.new("Commit #{commit_hash} does not exist.")
+ end
+ end
+
+ def visualise_log(log)
+ result = ""
+ log = log.to_a.reverse.to_h
+ log.each do |hash, commit|
+ result += "Commit #{hash}\nDate: #{commit[2]}\n\n\t#{commit[1]}"
+ result += "\n"
+ end
+ result.chop
+ Response.new(result)
+ end
+
+ def log
+ if @current_branch.commits
+ result = visualise_log(@current_branch.commits)
+ else
+ branch_name = @current_branch.branch_name
+ message = "Branch #{branch_name} does not have any commits yet."
+ BadResponse.new(message)
+ end
+ end
+
+ def head
+ if @current_branch.commits == {}
+ branch_name = @current_branch.branch_name
+ message = "Branch #{branch_name} does not have any commits yet."
+ BadResponse.new(message)
+ else
+ GoodResponse.new("#{@current_branch.commits.values.last[1]}",@head)
+ end
+ end
+
+ def get_objects_names
+ result = []
+ @current_branch.commits.values.last[0].each do |object|
+ result << object[0]
+ end
+ end
+
+ def get(name)
+ result = BadResponse.new("Object #{name} is not committed.")
+ get_objects_names.each do |object|
+ if object[0] == name
+ result = GoodResponse.new("Found object #{name}.", object)
+ end
+ end
+ result
+ end
+
+end
+
+class Commit
+
+ attr_accessor :hash, :objects, :message, :date
+
+ def initialize(data, hash)
+ @objects = data[0]
+ @message = data[1]
+ @date = data[2]
+ @hash = hash
+ end
+
+end
+
+class Branch
+
+ attr_accessor :objects_to_add, :objects_to_remove
+ attr_accessor :current_objects, :commits, :branch_name, :object_store
+
+ def initialize(branch_name, object_store, current_objects = [], commits = {})
+ @branch_name = branch_name
+ @object_store = object_store
+ @current_objects = current_objects
+ @commits = commits
+ @objects_to_add = []
+ @objects_to_remove = []
+ end
+
+ def create(branch_name)
+ response = Response.new("Created branch #{branch_name}")
+ @object_store.branch_list.each do |branch|
+ if branch.branch_name == branch
+ response = BadResponse.new("Branch #{branch_name} already exists.")
+ end
+ end
+ if response.kind_of?(Response)
+ branch = Branch.new(branch_name, @object_store,@current_objects, @commits)
+ @object_store.branch_list << branch
+ end
+ response
+ end
+
+ def checkout(branch_name)
+ result = BadResponse.new("Branch #{branch_name} does not exist.")
+ @object_store.branch_list.each do |branch|
+ if branch.branch_name == branch_name
+ result = Response.new("Switched to branch #{branch_name}.")
+ @object_store.current_branch = branch
+ end
+ end
+ result
+ end
+
+ def search_for_branch(name)
+ found = nil
+ @object_store.branch_list.each do |branch|
+ if branch.branch_name == name
+ found = branch
+ end
+ end
+ found
+ end
+
+ def remove(name)
+ current_branch_name = @object_store.current_branch.branch_name
+ if search_for_branch(name)
+ if search_for_branch(name).branch_name == current_branch_name
+ BadResponse.new("Cannot remove current branch.")
+ else
+ @object_store.branch_list.delete(search_for_branch(name))
+ Response.new("Removed branch #{name}.")
+ end
+ else
+ BadResponse.new("Branch #{name} does not exist.")
+ end
+ end
+
+ def list_to_string(list)
+ result = ""
+ list.each do |element|
+ if element == @object_store.current_branch.branch_name
+ result += "* " + element
+ else
+ result += " " + element
+ end
+ result += "\n"
+ end
+ result.chop
+ end
+
+ def list
+ result = []
+ @object_store.branch_list.each do |branch|
+ result << branch.branch_name
+ end
+ result.sort_by!{ |name| name.downcase }
+ Response.new(list_to_string(result))
+ end
+
+end
+
+class Response
+
+ def initialize(message)
+ @message = message
+ end
+
+ def message
+ "#{@message}"
+ end
+
+ def success?
+ true
+ end
+
+ def error?
+ false
+ end
+
+end
+
+class BadResponse < Response
+
+ def success?
+ false
+ end
+
+ def error?
+ true
+ end
+
+end
+
+class GoodResponse < Response
+
+ def initialize(message, result)
+ @message = message
+ @result = result
+ end
+
+ def result
+ @result
+ end
+
+end