Клара обнови решението на 23.11.2015 08:37 (преди около 9 години)
+require 'digest/sha1'
+require 'date'
+
+class Commit
+
+ def initialize(message, objects)
+ @message = message
+ @date = DateTime.now.strftime("%a %b %d %H:%M %Y %z")
+ @hash = Digest::SHA1.hexdigest(@date + @message)
+ @objects = objects
+ end
+
+ attr_reader :hash,:date,:message,:objects
+
+end
+
+class ReturnObject
+
+ def initialize(is_success, message, result)
+ @result = result
+ @success = is_success
+ @message = message
+ end
+
+ def message
+ @message
+ end
+
+ def success?
+ @success
+ end
+
+ def error?
+ ! @success
+ end
+
+ def result
+ raise NoMethodError if ! @success
+ @result
+ end
+end
+
+class ObjectStore
+
+ def initialize
+ @add_history = {}
+ @object_for_remove = []
+ @current_branch = "master"
+ @branches_names = [@current_branch]
+ @branch_with_commits = {}
+ @branch_with_commits[@current_branch.to_sym] = {}
+ @count_times = 0
+ end
+
+ def add(name, object)
+ @add_history[name.to_sym] = object
+ ReturnObject.new(true, "Added #{ name } to stage.", object)
+ end
+
+ def check_if_there_is_nothing_to_commit(length,remove_length)
+ return ReturnObject.new(false,
+ "Nothing to commit, working directory clean.",
+ []) if length == 0 and remove_length == 0
+ return ReturnObject.new(true,
+ message + "\n\t#{length2} objects changed",
+ []) if remove_length > 0
+ end
+
+ def commit(message)
+ length, remove_length = @add_history.length, @object_for_remove.length
+ check_if_there_is_nothing_to_commit(length,remove_length)
+ @branch_with_commits[@current_branch.to_sym][message], @add_history =
+ Commit.new(message,@add_history), {}
+ ReturnObject.new(true,
+ message + "\n\t#{ length } objects changed",
+ @branch_with_commits[@current_branch.to_sym][message])
+ end
+
+ def remove(name)
+ @branch_with_commits[@current_branch.to_sym].each{ |commit_name,obj|
+ if obj.objects.has_key?(name.to_sym)
+ commit, current_branch = commit_name.to_sym, @current_branch.to_sym
+ @object_for_remove.push(@branch_with_commits[current_branch][commit])
+ return ReturnObject.new(true,
+ "Added #{ name } for removal.",
+ @object_for_remove)
+ end
+ }
+ ReturnObject.new(false, "Object #{ name } is not committed.", [])
+ end
+
+ def delete_commits_before_date(last_commit_date)
+ branch = @branch_with_commits[@current_branch.to_sym]
+ branch.each{ |key, value|
+ branch.delete(key) if value.date > last_commit_date }
+ end
+
+ def error
+ error_comit = Commit.new("Commit #{ commit_hash } does not exist.", [])
+ ReturnObject.new(false, error_comit.message, [])
+ end
+
+ def checkout(commit_hash)
+ last_commit_date = DateTime.new
+ branch = @branch_with_commits
+ branch[@current_branch.to_sym].each{ |key, value|
+ if commit_hash == value.hash
+ last_commit_date, current_branch = value.date, @current_branch.to_sym
+ delete_commits_before_date(last_commit_date)
+ return ReturnObject.new(true,
+ "HEAD is now at #{ value.hash }.",
+ @branch[current_branch][key.to_sym])
+ end
+ }
+ error
+ end
+
+ def branch
+ return @branches if @count_times != 0
+ @branches = Branch.new
+ @branches.set_branches(@branch_with_commits)
+ @count_times += 1
+ @branches
+ end
+
+ def self.init(&block)
+ new_repo = ObjectStore.new
+ if block_given?
+ new_repo.instance_eval &block
+ end
+ new_repo
+ end
+
+ def log
+ message = "Branch #{ @current_branch } does not have any commits yet."
+ branch, log_message = @branch_with_commits, ""
+ return ReturnObject.new(false,
+ message,
+ []) if @branch[@current_branch.to_sym].empty?
+ @branch_with_commits[@current_branch.to_sym].each { |message, commit_object|
+ commit = "Commit #{ commit_object.hash }\nDate: #{ commit_object.date }" +
+ "\n\n\t#{ message }"
+ log_message << commit + "\n\n"
+ }
+ ReturnObject.new(true, log_message, [])
+ end
+
+ def head
+ branch = @branch_with_commits
+ message = "Branch #{ @current_branch } does not have any commits yet."
+ return ReturnObject.new(false,
+ message,
+ []) if @branch[@current_branch.to_sym].empty?
+ message, result_object = @branch[@current_branch.to_sym].first
+ ReturnObject.new(true, message, result_object)
+ end
+
+ def get(name)
+ name = name.to_sym
+ @branch_with_commits[@current_branch.to_sym].each{ |commit_name, obj|
+ return ReturnObject.new(true,
+ "Found object #{ name }.",
+ obj.objects[name]) if obj.objects.has_key?(name)
+ }
+ ReturnObject.new(false, "Object #{ name } is not committed.", [])
+ end
+end
+
+class Branch < ObjectStore
+
+ def initialize
+ super
+ end
+
+ def set_branches(branches)
+ @branch_with_commits = branches
+ end
+
+ def create(branch_name)
+ return ReturnObject.new(false,
+ "Branch #{ branch_name } already exists.",
+ []) if @branches_names.include?(branch_name)
+ current_branch, branch_name = @current_branch.to_sym, branch_name.to_sym
+ @branch_with_commits[branch_name] = @branch_with_commits[current_branch]
+ @branches_names.push(branch_name)
+ ReturnObject.new(true, "Created branch #{ branch_name }.", [])
+ end
+
+ def checkout(branch_name)
+ return ReturnObject.new(false,
+ "Branch #{ branch_name } already exists.",
+ []) if ! @branches_names.include?(branch_name)
+ @current_branch = branch_name
+ ReturnObject.new(true, "Switched to branch #{branch_name}.", [])
+ end
+
+ def remove(branch_name)
+ return ReturnObject.new(false,
+ "Branch #{ branch_name } does not exist.",
+ []) if ! @branches_names.include?(branch_name)
+
+ return ReturnObject.new(false,
+ "Cannot remove current branch.",
+ []) if @current_branch == branch_name
+ @branches_names.delete(branch_name)
+ @branch_with_commits.delete(branch_name)
+ ReturnObject.new(true, "Removed branch #{ branch_name }.", [])
+ end
+
+ def list
+ new_branches_names = []
+ @branches_names.sort!.each{ |branch|
+ if @current_branch == branch
+ new_branches_names.push("* " + branch + "\n")
+ else
+ new_branches_names.push(" " + branch + "\n")
+ end
+ }
+ new_branches_names = new_branches_names.join("")
+ new_list = new_branches_names.slice(0,new_branches_names.length - 1)
+ ReturnObject.new(true,
+ new_list,
+ [])
+ end
+ end