Веселин обнови решението на 23.11.2015 16:19 (преди около 9 години)
+require 'digest/sha1'
+require 'time'
+
+class ObjectStore
+ attr :temporary_data, :remove_data, :data, :branch
+
+ def initialize(block = nil)
+ @temporary_data, @remove_data, @data = {}, [], {}
+ branch.create('master')
+ branch.current_branch = 'master'
+ instance_eval &block if not block.nil?
+ end
+
+ def self.init(&block)
+ instance = ObjectStore.new(block)
+ instance
+ end
+
+ def add(name, object)
+ @temporary_data[name] = object
+ Operation.new("Added #{name} to stage.", true, object)
+ end
+
+ def commit(message)
+ if @temporary_data.empty? and @remove_data.empty?
+ Operation.new('Nothing to commit, working directory clean.', false)
+ else
+ count = @temporary_data.length + @remove_data.length
+ update_data
+ branch.log_commit(@temporary_data, @remove_data, @data, message)
+ @remove_data.clear
+ @temporary_data.clear
+ Operation.new("#{message}\n\t#{count} objects changed", true, head)
+ end
+ end
+
+ def update_data()
+ @remove_data.each { |name| @data.delete(name) }
+ @temporary_data.each { |name, object| @data[name] = object }
+ end
+
+ def remove(name)
+ if @data.include?(name)
+ @remove_data.push(name)
+ object = @data[name]
+ Operation.new("Added #{name} for removal.", true, object)
+ else
+ Operation.new("Object #{name} is not committed.", false)
+ end
+ end
+
+ def checkout(commit_hash)
+ commit = nil
+ branch.log[branch.current_branch].each do |c|
+ (@data = c.data and commit = c and break) if c.hash == commit_hash
+ end
+
+ if commit.nil?
+ Operation.new("Commit #{commit_hash} does not exist.", false)
+ else
+ delete_newer_commits(commit)
+ Operation.new("HEAD is now at #{commit_hash}.", true, commit)
+ end
+ end
+
+ def delete_newer_commits(commit)
+ delete, check = false, false
+ branch.log[branch.current_branch].delete_if do |c|
+ delete = true if commit.hash == c.hash
+ if delete and check
+ true
+ else
+ false
+ end
+ check = true if delete
+ end
+ end
+
+ def branch
+ if @branch == nil
+ @branch = Branch.new
+ end
+
+ @branch.data = @data
+
+ @branch
+ end
+
+ def log
+ if branch.log.empty?
+ error = "Branch #{branch.current_branch} does not have any commits yet."
+ Operation.new(error, false)
+ else
+ branch_log = branch.log[branch.current_branch].reverse
+ messages, sample = "", "Commit %s\nDate: %s\n\n\t%s\n\n"
+ branch_log.each { |c| messages << sample % [c.hash, c.date, c.message] }
+ messages.strip!
+ Operation.new(messages, true)
+ end
+ end
+
+ def get(name)
+ if @data.include?(name)
+ Operation.new("Found object #{name}.", true, @data[name])
+ else
+ Operation.new("Object #{name} is not committed.", false)
+ end
+ end
+
+ def head
+ if branch.log.empty?
+ error = "Branch #{branch.current_branch} does not have any commits yet."
+ Operation.new(error, false)
+ else
+ commit = branch.log[branch.current_branch].last
+ Operation.new(commit.message, true, commit)
+ end
+ end
+
+ class Commit
+ attr_reader :date, :message, :hash, :objects, :data
+
+ def initialize(*args)
+ @message, @date, @hash = args[0][0], args[0][1], args[0][2]
+ @added_data, @removed_data, @data = args[0][3], args[0][4], args[0][5]
+ @objects = @data.to_a
+ end
+ end
+
+ class Operation
+ attr_reader :message
+ attr :status, :result_text
+
+ def initialize(message, status, result_text = nil)
+ @message, @status, @result_text = message, status, result_text
+
+ unless result_text.nil?
+ define_singleton_method(:result) { @result_text }
+ end
+ end
+
+ def success?
+ status == true
+ end
+
+ def error?
+ status == false
+ end
+ end
+
+ class Branch
+ attr :branches
+ attr_writer :data
+ attr_accessor :current_branch, :log
+
+ def initialize
+ @branches, @log = {}, {}
+ @current_branch = nil
+ end
+
+ def create(branch_name)
+ if @branches.include?(branch_name)
+ Operation.new("Branch #{branch_name} already exists.", false)
+ else
+ @branches[branch_name] = @data
+ Operation.new("Created branch #{branch_name}.", true)
+ end
+ end
+
+ def checkout(branch_name)
+ if @branches.include?(branch_name)
+ @branches[@current_branch] = @data
+ @current_branch = branch_name
+ @data = @branches[@current_branch]
+ Operation.new("Switched to branch #{current_branch}.", true)
+ else
+ Operation.new("Branch #{branch_name} does not exist.", false)
+ end
+ end
+
+ def remove(branch_name)
+ if @branches.include?(branch_name)
+ if not branch_name == @current_branch
+ @branches.delete(branch_name)
+ Operation.new("Removed branch #{branch_name}.", true)
+ else
+ Operation.new("Cannot remove current branch.", false)
+ end
+ else
+ Operation.new("Branch #{branch_name} does not exist.", false)
+ end
+ end
+
+ def list
+ result, i, length = '', 0, @branches.length
+ @branches.keys.sort.each do |key|
+ result.concat(key == @current_branch ? "* #{key}" : " #{key}")
+ result.concat("\n") if not i + 1 == length and not length == 0
+ i += 1
+ end
+ Operation.new(result, true)
+ end
+
+ def log_commit(added_data, removed_data, new_data, message)
+ date = Time.new.strftime("%a %b %d %H:%M %Y %z")
+ hash = Digest::SHA1.hexdigest("#{date}#{message}")
+ commit_data = [message, date, hash, added_data, removed_data, new_data]
+ @log[@current_branch] = [] if @log[@current_branch].nil?
+ @log[@current_branch].push(Commit.new(commit_data))
+ end
+ end
+end
Така и не успях да разбера защо не минава примерните тестове. Когато си тествам "ръчно", всичко си работи както е описано в условието на задачата. Ще помоля ако някой проверяващ прегледа решението ми, да ме насочи къде е проблемът.