Решение на Пета задача от Бойко Караджов

Обратно към всички решения

Към профила на Бойко Караджов

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 23 успешни тест(а)
  • 7 неуспешни тест(а)

Код

require 'digest/sha1'
class Response
attr_reader :message, :result
def initialize(message, success, result = nil)
@message, @success, @result = message, success, result
end
def success?
@success
end
def error?
not @success
end
end
class Change
attr_reader :action, :name, :object
def initialize(action, name, object = nil)
@action, @name, @object = action, name, object
end
end
class Commit
attr_reader :date, :message, :hash
TIME_FORMAT = "%a %b %d %H:%M %Y %z"
def initialize(parent_commit, changes, message)
@parent_commit, @changes, @message = parent_commit, changes, message
@date = Time.now
formatted_time = @date.getgm.strftime(Commit::TIME_FORMAT)
@hash = Digest::SHA1.hexdigest "#{formatted_time}#{message}"
end
def size
@changes.size
end
def to_s
formatted_time = @date.strftime(Commit::TIME_FORMAT)
"Commit #@hash\nDate: #{formatted_time}\n\n\t#@message"
end
def objects(excluding = Array.new)
total = Array.new
if @parent_commit != nil
total_exclude = excluding | @changes.map { |key, value| key }
total = @parent_commit.objects(total_exclude)
end
total.concat(@changes.select { |key, value|
value.action == :add unless excluding.include?(value.name)
}.map { |key, value| value.object })
end
def get(name)
if @changes.has_key? name
change = @changes[name]
change.object unless change.action == :remove
else
@parent_commit.get(name) unless @parent_commit == nil
end
end
def log
if @parent_commit != nil
to_s + "\n\n" + @parent_commit.log
else
to_s
end
end
end
class BranchDecorator
attr_reader :heads
def initialize(repository)
@repository = repository
@heads = Hash.new
@heads["master"] = nil
end
def create(branch_name)
if @heads.has_key? branch_name
Response.new "Branch #{branch_name} already exists.", false
else
@heads[branch_name] = @repository.head
Response.new "Created branch #{branch_name}.", true
end
end
def checkout(branch_name)
if @heads.has_key? branch_name
@repository.current_branch = branch_name
Response.new "Switched to branch #{branch_name}.", true
else
Response.new "Branch #{branch_name} does not exist.", false
end
end
def remove(branch_name)
if @heads.has_key? branch_name
if branch_name != @repository.current_branch
@heads.delete branch_name
Response.new "Removed branch #{branch_name}.", true
else
Response.new "Cannot remove current branch.", false
end
else
Response.new "Branch #{branch_name} does not exist.", false
end
end
def list
@heads.map { |key, value|
if @repository.current_branch == key
"* " + key
else
" " + key
end
}.join("\n")
end
end
class ObjectStore
private_class_method :new
attr_reader :branch
attr_accessor :current_branch
def self.init(&block)
new(&block)
end
def initialize(&block)
@branch = BranchDecorator.new self
@pending_changes = Hash.new
@history = Hash.new
@current_branch = "master"
self.instance_eval &block if block_given?
end
def add(name, object)
@pending_changes[name] = Change.new(:add, name, object)
Response.new "Added #{name} to stage.", true, object
end
def remove(name)
if get(name).success?
@pending_changes[name] = Change.new(:remove, name)
Response.new "Added #{name} for removal.", true, get(name)
else
Response.new "Object #{name} is not committed.", false
end
end
def commit(message)
count = @pending_changes.size
set_head Commit.new(head.result, @pending_changes, message)
@history[head.result.hash] = head.result
@pending_changes = Hash.new
if count > 0
Response.new "#{message}\n\t#{count} objects changed", true, head.result
else
Response.new "Nothing to commit, working directory clean.", false
end
end
def head
result = @branch.heads[@current_branch]
if result != nil
Response.new result.message, true, result
else
Response.new "Branch #@current_branch does not have any commits yet.",
false
end
end
def set_head(value)
@branch.heads[@current_branch] = value
end
def checkout(commit_hash)
if @history.has_key? commit_hash
set_head @history[commit_hash]
Response.new "HEAD is now at #{commit_hash}.", true, head.result
else
Response.new "Commit #{commit_hash} does not exist.", false
end
end
def log
if head.success?
Response.new head.result.log, true
else
Response.new "Nothing to commit, working directory clean.", false
end
end
def get(name)
result = head.result.get(name) unless head.error?
if result != nil
Response.new "Found object #{name}.", true, result
else
Response.new "Object #{name} is not committed.", false
end
end
end

Лог от изпълнението

...F....FFFFFF................

Failures:

  1) ObjectStore can remove objects
     Failure/Error: expect(repo.remove("object1")).to be_success("Added object1 for removal.", "content1")
       expected #<Response:0x007f5d2c739750 @message="Added object1 for removal.", @success=true, @result=#<Response:0x007f5d2c739868 @message="Found object object1.", @success=true, @result="content1">> to be success "Added object1 for removal." and "content1"
     # /tmp/d20160111-5693-dbgxlg/spec.rb:43:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) ObjectStore can show log of changes for a single commit
     Failure/Error: expect(repo.log).to be_success("Commit #{commit_hash}\nDate: #{Time.now.strftime("%a %b %d %H:%M %Y %z")}\n\n\tSo cool!")
       expected #<Response:0x007f5d2c345838 @message="Commit 0f480dedeee718e660111f0585f807169850ecaf\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSo cool!", @success=true, @result=nil> to be success "Commit 020f94292ff683fc536310fe33c03adfbf64bbca\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSo cool!"
     # /tmp/d20160111-5693-dbgxlg/spec.rb:83:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) ObjectStore can show log of changes for a single commit
     Failure/Error: expect(repo.log).to be_success("Commit #{commit_hash}\nDate: #{Time.now.strftime("%a %b %d %H:%M %Y %z")}\n\n\tSo cool!")
       expected #<Response:0x007f5d2c30f648 @message="Commit 0f480dedeee718e660111f0585f807169850ecaf\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSo cool!", @success=true, @result=nil> to be success "Commit 020f94292ff683fc536310fe33c03adfbf64bbca\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSo cool!"
     # /tmp/d20160111-5693-dbgxlg/spec.rb:92:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) ObjectStore can show log of changes for multiple commits
     Failure/Error: expect(repo.log).to be_success("Commit #{commit2_hash}\nDate: #{current_time}\n\n\tSecond commit\n\nCommit #{commit1_hash}\nDate: #{current_time}\n\n\tFirst commit")
       expected #<Response:0x007f5d2c2dea98 @message="Commit 8532b8e15c1ca0973921eb55a8eb27505aed7ab8\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSecond commit\n\nCommit bd5985b202652cfe211a916980b476ae1121aafa\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tFirst commit", @success=true, @result=nil> to be success "Commit a6bf7130a3150d375443c25d06c1bf8077e4b4fb\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSecond commit\n\nCommit 9a97b358afe869ba1e523d99dd2101dfc0570dc0\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tFirst commit"
     # /tmp/d20160111-5693-dbgxlg/spec.rb:108:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) ObjectStore shows the log for the current branch only
     Failure/Error: expect(repo.log).to be_success("Commit #{commit1_hash}\nDate: #{current_time}\n\n\tFirst commit")
     NoMethodError:
       undefined method `log' for #<Response:0x007f5d2c2c9670>
     # /tmp/d20160111-5693-dbgxlg/solution.rb:199:in `log'
     # /tmp/d20160111-5693-dbgxlg/spec.rb:128:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) ObjectStore cannot show log for empty repository
     Failure/Error: expect(repo.log).to be_error("Branch master does not have any commits yet.")
       expected #<Response:0x007f5d2c2c0e30 @message="Nothing to commit, working directory clean.", @success=false, @result=nil> to be error "Branch master does not have any commits yet."
     # /tmp/d20160111-5693-dbgxlg/spec.rb:133:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  7) ObjectStore can list branches
     Failure/Error: actual.message == message &&
     NoMethodError:
       undefined method `message' for "* master\n  develop\n  feature":String
     # /tmp/d20160111-5693-dbgxlg/spec.rb:6:in `block (3 levels) in <top (required)>'
     # /tmp/d20160111-5693-dbgxlg/spec.rb:140:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.03287 seconds
30 examples, 7 failures

Failed examples:

rspec /tmp/d20160111-5693-dbgxlg/spec.rb:38 # ObjectStore can remove objects
rspec /tmp/d20160111-5693-dbgxlg/spec.rb:77 # ObjectStore can show log of changes for a single commit
rspec /tmp/d20160111-5693-dbgxlg/spec.rb:86 # ObjectStore can show log of changes for a single commit
rspec /tmp/d20160111-5693-dbgxlg/spec.rb:95 # ObjectStore can show log of changes for multiple commits
rspec /tmp/d20160111-5693-dbgxlg/spec.rb:111 # ObjectStore shows the log for the current branch only
rspec /tmp/d20160111-5693-dbgxlg/spec.rb:131 # ObjectStore cannot show log for empty repository
rspec /tmp/d20160111-5693-dbgxlg/spec.rb:136 # ObjectStore can list branches

История (1 версия и 0 коментара)

Бойко обнови решението на 18.11.2015 00:40 (преди над 8 години)

+require 'digest/sha1'
+
+class Response
+ attr_reader :message, :result
+
+ def initialize(message, success, result = nil)
+ @message, @success, @result = message, success, result
+ end
+
+ def success?
+ @success
+ end
+
+ def error?
+ not @success
+ end
+end
+
+class Change
+ attr_reader :action, :name, :object
+
+ def initialize(action, name, object = nil)
+ @action, @name, @object = action, name, object
+ end
+end
+
+class Commit
+ attr_reader :date, :message, :hash
+
+ TIME_FORMAT = "%a %b %d %H:%M %Y %z"
+
+ def initialize(parent_commit, changes, message)
+ @parent_commit, @changes, @message = parent_commit, changes, message
+
+ @date = Time.now
+ formatted_time = @date.getgm.strftime(Commit::TIME_FORMAT)
+ @hash = Digest::SHA1.hexdigest "#{formatted_time}#{message}"
+ end
+
+ def size
+ @changes.size
+ end
+
+ def to_s
+ formatted_time = @date.strftime(Commit::TIME_FORMAT)
+ "Commit #@hash\nDate: #{formatted_time}\n\n\t#@message"
+ end
+
+ def objects(excluding = Array.new)
+ total = Array.new
+ if @parent_commit != nil
+ total_exclude = excluding | @changes.map { |key, value| key }
+ total = @parent_commit.objects(total_exclude)
+ end
+
+ total.concat(@changes.select { |key, value|
+ value.action == :add unless excluding.include?(value.name)
+ }.map { |key, value| value.object })
+ end
+
+ def get(name)
+ if @changes.has_key? name
+ change = @changes[name]
+ change.object unless change.action == :remove
+ else
+ @parent_commit.get(name) unless @parent_commit == nil
+ end
+ end
+
+ def log
+ if @parent_commit != nil
+ to_s + "\n\n" + @parent_commit.log
+ else
+ to_s
+ end
+ end
+end
+
+class BranchDecorator
+ attr_reader :heads
+
+ def initialize(repository)
+ @repository = repository
+ @heads = Hash.new
+ @heads["master"] = nil
+ end
+
+ def create(branch_name)
+ if @heads.has_key? branch_name
+ Response.new "Branch #{branch_name} already exists.", false
+ else
+ @heads[branch_name] = @repository.head
+ Response.new "Created branch #{branch_name}.", true
+ end
+ end
+
+ def checkout(branch_name)
+ if @heads.has_key? branch_name
+ @repository.current_branch = branch_name
+ Response.new "Switched to branch #{branch_name}.", true
+ else
+ Response.new "Branch #{branch_name} does not exist.", false
+ end
+ end
+
+ def remove(branch_name)
+ if @heads.has_key? branch_name
+ if branch_name != @repository.current_branch
+ @heads.delete branch_name
+ Response.new "Removed branch #{branch_name}.", true
+ else
+ Response.new "Cannot remove current branch.", false
+ end
+ else
+ Response.new "Branch #{branch_name} does not exist.", false
+ end
+ end
+
+ def list
+ @heads.map { |key, value|
+ if @repository.current_branch == key
+ "* " + key
+ else
+ " " + key
+ end
+ }.join("\n")
+ end
+end
+
+class ObjectStore
+ private_class_method :new
+
+ attr_reader :branch
+ attr_accessor :current_branch
+
+ def self.init(&block)
+ new(&block)
+ end
+
+ def initialize(&block)
+ @branch = BranchDecorator.new self
+ @pending_changes = Hash.new
+ @history = Hash.new
+ @current_branch = "master"
+ self.instance_eval &block if block_given?
+ end
+
+ def add(name, object)
+ @pending_changes[name] = Change.new(:add, name, object)
+ Response.new "Added #{name} to stage.", true, object
+ end
+
+ def remove(name)
+ if get(name).success?
+ @pending_changes[name] = Change.new(:remove, name)
+ Response.new "Added #{name} for removal.", true, get(name)
+ else
+ Response.new "Object #{name} is not committed.", false
+ end
+ end
+
+ def commit(message)
+ count = @pending_changes.size
+ set_head Commit.new(head.result, @pending_changes, message)
+ @history[head.result.hash] = head.result
+ @pending_changes = Hash.new
+ if count > 0
+ Response.new "#{message}\n\t#{count} objects changed", true, head.result
+ else
+ Response.new "Nothing to commit, working directory clean.", false
+ end
+ end
+
+ def head
+ result = @branch.heads[@current_branch]
+ if result != nil
+ Response.new result.message, true, result
+ else
+ Response.new "Branch #@current_branch does not have any commits yet.",
+ false
+ end
+ end
+
+ def set_head(value)
+ @branch.heads[@current_branch] = value
+ end
+
+ def checkout(commit_hash)
+ if @history.has_key? commit_hash
+ set_head @history[commit_hash]
+ Response.new "HEAD is now at #{commit_hash}.", true, head.result
+ else
+ Response.new "Commit #{commit_hash} does not exist.", false
+ end
+ end
+
+ def log
+ if head.success?
+ Response.new head.result.log, true
+ else
+ Response.new "Nothing to commit, working directory clean.", false
+ end
+ end
+
+ def get(name)
+ result = head.result.get(name) unless head.error?
+ if result != nil
+ Response.new "Found object #{name}.", true, result
+ else
+ Response.new "Object #{name} is not committed.", false
+ end
+ end
+end