Решение на Пета задача от Мартин Симеонов

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

Към профила на Мартин Симеонов

Резултати

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

Код

require 'digest/sha1'
class ObjectStore
class << self
def init
repo = new
repo.instance_eval(&Proc.new) if block_given?
repo
end
private :new
end
def initialize
@branches = BranchStore.new
end
def add(name, object)
@branches.current_branch.add(name, object)
end
def remove(name)
@branches.current_branch.remove(name)
end
def commit(message)
@branches.current_branch.commit(message)
end
def checkout(commit_hash)
@branches.current_branch.checkout(commit_hash)
end
def branch
@branches
end
def log
@branches.current_branch.log
end
def head
@branches.current_branch.head
end
def get(name)
@branches.current_branch.get(name)
end
end
class Branch
attr_accessor :name
def initialize(name)
@storage = {}
@commit_add = {}
@commit_remove = {}
@commit_log = {}
@name = name
end
def add(name, object)
@commit_add[name] = object
ResultOperation.new("Added #{name} to stage.", true, object)
end
def remove(name)
if @storage.key?(name)
@commit_remove[name] = 'remove'
ResultOperation.new("Added #{name} for removal.", true, @storage[name])
else
Operation.new("Object #{name} is not committed.", false)
end
end
def commit(message)
if @commit_add.empty? and @commit_remove.empty?
Operation.new('Nothing to commit, working directory clean.', false)
else
count_changes = perform_changes
commit = Commit.new(message, true, @storage.values)
@commit_log[commit.hash] = commit
commit_message = "#{message}\n\t#{count_changes} objects changed"
ResultOperation.new(commit_message, true, commit)
end
end
def checkout(commit_hash)
if @commit_log.key?(commit_hash)
commit = @commit_log[commit_hash]
@storage = commit.clone
@commit_log.delete_if { |_, value| value.date < commit.date }
@commit_add.clear
@commit_remove.clear
ResultOperation.new("HEAD is now at #{commit_hash}.", true, commit)
else
Operation.new("Commit #{commit_hash} does not exist.", false)
end
end
def log
if @commit_log.empty?
Operation.new("Branch #{@name} does not have any commits yet.", false)
else
message = ''
@commit_log.reverse_each do |_, commit|
message += "Commit #{commit.hash}\nDate: "
message += "#{commit.date.strftime('%a %b %d %H:%M %Y %z')}\n\n\t"
message += "#{commit.message}\n\n"
end
Operation.new(message.chomp.chomp, true)
end
end
def head
if @commit_log.empty?
message = "Branch #{name} does not have any commits yet."
Operation.new(message, false)
else
message = @commit_log.values.last.message
ResultOperation.new(message, true, @commit_log.values.last)
end
end
def get(name)
if @storage.key?(name)
ResultOperation.new("Found object #{name}.", true, @storage[name])
else
Operation.new("Object #{name} is not committed.", false)
end
end
private
def perform_changes
count_changes = @commit_add.count + @commit_remove.count
@storage.merge!(@commit_add)
@storage.delete_if { |key, _| @commit_remove.key?(key) }
@commit_add.clear
@commit_remove.clear
count_changes
end
end
class BranchStore
attr_reader :current_branch
def initialize
@current_branch = Branch.new('master')
@branches = { 'master' => @current_branch }
end
def create(branch_name)
if @branches.key?(branch_name)
Operation.new("Branch #{branch_name} already exists.", false)
else
branch = @current_branch.clone
branch.name = branch_name
@branches[branch_name] = branch
Operation.new("Created branch #{branch_name}.", true)
end
end
def checkout(branch_name)
if @branches.key?(branch_name)
@current_branch = @branches[branch_name]
Operation.new("Switched to branch #{branch_name}.", true)
else
Operation.new("Branch #{branch_name} does not exist.", false)
end
end
def remove(branch_name)
if @branches.key?(branch_name)
if @branches[branch_name] == @current_branch
Operation.new('Cannot remove current branch.', false)
else
@branches.delete(branch_name)
Operation.new("Removed branch #{branch_name}.", true)
end
else
Operation.new("Branch #{branch_name} does not exist.", false)
end
end
def list
message = ''
@branches.sort.map do |name, branch|
if branch == @current_branch
message += "* #{name}\n"
else
message += " #{name}\n"
end
end
Operation.new(message.chomp, true)
end
end
class Operation
attr_reader :message
def initialize(message, success)
@message = message
@success = success
end
def success?
@success
end
def error?
not @success
end
end
class ResultOperation < Operation
attr_reader :result
def initialize(message, success, result)
super message, success
@result = result
end
end
class Commit < ResultOperation
attr_reader :date, :hash, :objects
def initialize(commit_message, success, objects = nil)
@date = Time.now
@hash = Digest::SHA1.hexdigest("#{date}#{commit_message}")
@objects = objects.clone
super commit_message, success, self
end
end

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

........FFFF....F........F....

Failures:

  1) 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 #<Operation:0x007fb16699afd8 @message="Commit 95a3b74e7aa90dce0d26a1db8112a3c4c3f934f5\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSo cool!", @success=true> to be success "Commit 020f94292ff683fc536310fe33c03adfbf64bbca\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSo cool!"
     # /tmp/d20160111-5693-1c0z31f/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)>'

  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 #<Operation:0x007fb16698c488 @message="Commit 95a3b74e7aa90dce0d26a1db8112a3c4c3f934f5\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSo cool!", @success=true> to be success "Commit 020f94292ff683fc536310fe33c03adfbf64bbca\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSo cool!"
     # /tmp/d20160111-5693-1c0z31f/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)>'

  3) 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 #<Operation:0x007fb16694d8f0 @message="Commit dbc3910c728cf522587c2d74a47b434b21c43ef1\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSecond commit\n\nCommit 64c04edc60821a93d41206816b23d2528b54bfca\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tFirst commit", @success=true> 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-1c0z31f/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)>'

  4) 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")
       expected #<Operation:0x007fb166921ac0 @message="Commit dbc3910c728cf522587c2d74a47b434b21c43ef1\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSecond commit\n\nCommit 64c04edc60821a93d41206816b23d2528b54bfca\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tFirst commit", @success=true> to be success "Commit 9a97b358afe869ba1e523d99dd2101dfc0570dc0\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tFirst commit"
     # /tmp/d20160111-5693-1c0z31f/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)>'

  5) ObjectStore can switch branches
     Failure/Error: expect(repo.head).to be_success("First commit", first_commit)
       expected #<ResultOperation:0x007fb166640360 @message="Second commit", @success=true, @result=#<Commit:0x007fb166824988 @date=2016-01-11 11:55:22 +0200, @hash="dbc3910c728cf522587c2d74a47b434b21c43ef1", @objects=["content1", "content2"], @message="Second commit", @success=true, @result=#<Commit:0x007fb166824988 ...>>> to be success "First commit" and #<Commit:0x007fb16683b570 @date=2016-01-11 11:55:22 +0200, @hash="64c04edc60821a93d41206816b23d2528b54bfca", @objects=["content1"], @message="First commit", @success=true, @result=#<Commit:0x007fb16683b570 ...>>
     # /tmp/d20160111-5693-1c0z31f/spec.rb:163: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 can checkout commits
     Failure/Error: expect(repo.head).to be_success("First commit", first_commit)
       expected #<ResultOperation:0x007fb1674c1ad8 @message="Second commit", @success=true, @result=#<Commit:0x007fb1674c4418 @date=2016-01-11 11:55:22 +0200, @hash="dbc3910c728cf522587c2d74a47b434b21c43ef1", @objects=[21], @message="Second commit", @success=true, @result=#<Commit:0x007fb1674c4418 ...>>> to be success "First commit" and #<Commit:0x007fb1674c4a30 @date=2016-01-11 11:55:22 +0200, @hash="64c04edc60821a93d41206816b23d2528b54bfca", @objects=[42], @message="First commit", @success=true, @result=#<Commit:0x007fb1674c4a30 ...>>
     # /tmp/d20160111-5693-1c0z31f/spec.rb:224: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.03324 seconds
30 examples, 6 failures

Failed examples:

rspec /tmp/d20160111-5693-1c0z31f/spec.rb:77 # ObjectStore can show log of changes for a single commit
rspec /tmp/d20160111-5693-1c0z31f/spec.rb:86 # ObjectStore can show log of changes for a single commit
rspec /tmp/d20160111-5693-1c0z31f/spec.rb:95 # ObjectStore can show log of changes for multiple commits
rspec /tmp/d20160111-5693-1c0z31f/spec.rb:111 # ObjectStore shows the log for the current branch only
rspec /tmp/d20160111-5693-1c0z31f/spec.rb:153 # ObjectStore can switch branches
rspec /tmp/d20160111-5693-1c0z31f/spec.rb:217 # ObjectStore can checkout commits

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

Мартин обнови решението на 22.11.2015 19:10 (преди около 9 години)

+require 'digest/sha1'
+
+class ObjectStore
+ class << self
+ def init
+ repo = new
+ repo.instance_eval(&Proc.new) if block_given?
+ repo
+ end
+
+ private :new
+ end
+
+ def initialize
+ @branches = BranchStore.new
+ end
+
+ def add(name, object)
+ @branches.current_branch.add(name, object)
+ end
+
+ def remove(name)
+ @branches.current_branch.remove(name)
+ end
+
+ def commit(message)
+ @branches.current_branch.commit(message)
+ end
+
+ def checkout(commit_hash)
+ @branches.current_branch.checkout(commit_hash)
+ end
+
+ def branch
+ @branches
+ end
+
+ def log
+ @branches.current_branch.log
+ end
+
+ def head
+ @branches.current_branch.head
+ end
+
+ def get(name)
+ @branches.current_branch.get(name)
+ end
+end
+
+class Branch
+ attr_accessor :name
+
+ def initialize(name)
+ @storage = Hash.new
+ @commit_add = Hash.new
+ @commit_remove = Hash.new
+ @commit_log = Hash.new
+ @name = name
+ end
+
+ def add(name, object)
+ @commit_add[name] = object
+ ResultOperation.new("Added #{name} to stage.", true, object)
+ end
+
+ def remove(name)
+ if @storage.has_key?(name)
+ @commit_remove[name] = "remove"
+ ResultOperation.new("Added #{name} for removal.", true, @storage[name])
+ else
+ Operation.new("Object #{name} is not committed.", false)
+ end
+ end
+
+ def commit(message)
+ if @commit_add.empty? and @commit_remove.empty?
+ Operation.new("Nothing to commit, working directory clean.", false)
+ else
+ count_changes = perform_changes
+ commit = Commit.new(message, true, @storage.values)
+ @commit_log[commit.hash] = commit
+ commit_message = "#{message}\n\t#{count_changes} objects changed"
+ ResultOperation.new(commit_message, true, commit)
+ end
+ end
+
+ def checkout(commit_hash)
+ if @commit_log.has_key?(commit_hash)
+ commit = @commit_log[commit_hash]
+ @storage = commit.clone
+ @commit_log.delete_if { |_, value| value.date < commit.date }
+ @commit_add.clear
+ @commit_remove.clear
+ ResultOperation.new("HEAD is now at #{commit_hash}.", true, commit)
+ else
+ Operation.new("Commit #{commit_hash} does not exist.", false)
+ end
+ end
+
+ def log
+ if @commit_log.empty?
+ Operation.new("Branch #{@name} does not have any commits yet.", false)
+ else
+ message = ""
+ @commit_log.reverse_each do |_, commit|
+ message += "Commit #{commit.hash}\nDate: "
+ message += "#{commit.date.strftime("%a %b %d %H:%M %Y %z")}\n\n\t"
+ message += "#{commit.message}\n\n"
+ end
+ Operation.new(message.chomp.chomp, true)
+ end
+ end
+
+ def head
+ if @commit_log.empty?
+ message = "Branch #{name} does not have any commits yet."
+ ResultOperation.new(message, false, nil)
+ else
+ message = @commit_log.values.last.message
+ ResultOperation.new(message, true, @commit_log.values.last)
+ end
+ end
+
+ def get(name)
+ if @storage.has_key?(name)
+ ResultOperation.new("Found object #{name}.", true, @storage[name])
+ else
+ Operation.new("Object #{name} is not committed.", false)
+ end
+ end
+
+private
+
+ def perform_changes
+ count_changes = @commit_add.count + @commit_remove.count
+ @storage.merge!(@commit_add)
+ @storage.delete_if { |key, value| @commit_remove.has_key?(key) }
+ @commit_add.clear
+ @commit_remove.clear
+ count_changes
+ end
+end
+
+class BranchStore
+ attr_reader :current_branch
+
+ def initialize
+ @current_branch = Branch.new("master")
+ @branches = { "master" => @current_branch }
+ end
+
+ def create(branch_name)
+ if @branches.has_key?(branch_name)
+ Operation.new("Branch #{branch_name} already exists.", false)
+ else
+ branch = @current_branch.clone
+ branch.name = branch_name
+ @branches[branch_name] = branch
+ Operation.new("Created branch #{branch_name}.", true)
+ end
+ end
+
+ def checkout(branch_name)
+ if @branches.has_key?(branch_name)
+ @current_branch = @branches[branch_name]
+ Operation.new("Switched to branch #{branch_name}.", true)
+ else
+ Operation.new("Branch #{branch_name} does not exist.", false)
+ end
+ end
+
+ def remove(branch_name)
+ if @branches.has_key?(branch_name)
+ if @branches[branch_name] == @current_branch
+ Operation.new("Cannot remove current branch.", false)
+ else
+ @branches.delete(branch_name)
+ Operation.new("Removed branch #{branch_name}.", true)
+ end
+ else
+ Operation.new("Branch #{branch_name} does not exist.", false)
+ end
+ end
+
+ def list
+ message = ""
+ @branches.sort.map do |name, branch|
+ if branch == @current_branch
+ message += "* #{name}\n"
+ else
+ message += " #{name}\n"
+ end
+ end
+ Operation.new(message.chomp, true)
+ end
+end
+
+class Operation
+ attr_reader :message
+
+ def initialize(message, success)
+ @message = message
+ @success = success
+ end
+
+ def success?
+ @success
+ end
+
+ def error?
+ not @success
+ end
+end
+
+class ResultOperation < Operation
+ attr_reader :result
+
+ def initialize(message, success, result)
+ super message, success
+ @result = result
+ end
+end
+
+class Commit < ResultOperation
+ attr_reader :date, :hash, :objects
+
+ def initialize(commit_message, success, objects = nil)
+ @date = Time.now
+ @hash = Digest::SHA1.hexdigest("#{date}#{commit_message}")
+ @objects = objects.clone
+ super commit_message, success, self
+ end
+end

Мартин обнови решението на 22.11.2015 20:00 (преди около 9 години)

require 'digest/sha1'
class ObjectStore
class << self
def init
repo = new
repo.instance_eval(&Proc.new) if block_given?
repo
end
private :new
end
def initialize
@branches = BranchStore.new
end
def add(name, object)
@branches.current_branch.add(name, object)
end
def remove(name)
@branches.current_branch.remove(name)
end
def commit(message)
@branches.current_branch.commit(message)
end
def checkout(commit_hash)
@branches.current_branch.checkout(commit_hash)
end
def branch
@branches
end
def log
@branches.current_branch.log
end
def head
@branches.current_branch.head
end
def get(name)
@branches.current_branch.get(name)
end
end
class Branch
attr_accessor :name
def initialize(name)
- @storage = Hash.new
- @commit_add = Hash.new
- @commit_remove = Hash.new
- @commit_log = Hash.new
+ @storage = {}
+ @commit_add = {}
+ @commit_remove = {}
+ @commit_log = {}
@name = name
end
def add(name, object)
@commit_add[name] = object
ResultOperation.new("Added #{name} to stage.", true, object)
end
def remove(name)
- if @storage.has_key?(name)
- @commit_remove[name] = "remove"
+ if @storage.key?(name)
+ @commit_remove[name] = 'remove'
ResultOperation.new("Added #{name} for removal.", true, @storage[name])
else
Operation.new("Object #{name} is not committed.", false)
end
end
def commit(message)
if @commit_add.empty? and @commit_remove.empty?
- Operation.new("Nothing to commit, working directory clean.", false)
+ Operation.new('Nothing to commit, working directory clean.', false)
else
count_changes = perform_changes
commit = Commit.new(message, true, @storage.values)
@commit_log[commit.hash] = commit
commit_message = "#{message}\n\t#{count_changes} objects changed"
ResultOperation.new(commit_message, true, commit)
end
end
def checkout(commit_hash)
- if @commit_log.has_key?(commit_hash)
+ if @commit_log.key?(commit_hash)
commit = @commit_log[commit_hash]
@storage = commit.clone
@commit_log.delete_if { |_, value| value.date < commit.date }
@commit_add.clear
@commit_remove.clear
ResultOperation.new("HEAD is now at #{commit_hash}.", true, commit)
else
Operation.new("Commit #{commit_hash} does not exist.", false)
end
end
def log
if @commit_log.empty?
Operation.new("Branch #{@name} does not have any commits yet.", false)
else
- message = ""
+ message = ''
@commit_log.reverse_each do |_, commit|
message += "Commit #{commit.hash}\nDate: "
- message += "#{commit.date.strftime("%a %b %d %H:%M %Y %z")}\n\n\t"
+ message += "#{commit.date.strftime('%a %b %d %H:%M %Y %z')}\n\n\t"
message += "#{commit.message}\n\n"
end
Operation.new(message.chomp.chomp, true)
end
end
def head
if @commit_log.empty?
message = "Branch #{name} does not have any commits yet."
- ResultOperation.new(message, false, nil)
+ Operation.new(message, false)
else
message = @commit_log.values.last.message
ResultOperation.new(message, true, @commit_log.values.last)
end
end
def get(name)
- if @storage.has_key?(name)
+ if @storage.key?(name)
ResultOperation.new("Found object #{name}.", true, @storage[name])
else
Operation.new("Object #{name} is not committed.", false)
end
end
-private
+ private
def perform_changes
count_changes = @commit_add.count + @commit_remove.count
@storage.merge!(@commit_add)
- @storage.delete_if { |key, value| @commit_remove.has_key?(key) }
+ @storage.delete_if { |key, _| @commit_remove.key?(key) }
@commit_add.clear
@commit_remove.clear
count_changes
end
end
class BranchStore
attr_reader :current_branch
def initialize
- @current_branch = Branch.new("master")
- @branches = { "master" => @current_branch }
+ @current_branch = Branch.new('master')
+ @branches = { 'master' => @current_branch }
end
def create(branch_name)
- if @branches.has_key?(branch_name)
+ if @branches.key?(branch_name)
Operation.new("Branch #{branch_name} already exists.", false)
else
branch = @current_branch.clone
branch.name = branch_name
@branches[branch_name] = branch
Operation.new("Created branch #{branch_name}.", true)
end
end
def checkout(branch_name)
- if @branches.has_key?(branch_name)
+ if @branches.key?(branch_name)
@current_branch = @branches[branch_name]
Operation.new("Switched to branch #{branch_name}.", true)
else
Operation.new("Branch #{branch_name} does not exist.", false)
end
end
def remove(branch_name)
- if @branches.has_key?(branch_name)
+ if @branches.key?(branch_name)
if @branches[branch_name] == @current_branch
- Operation.new("Cannot remove current branch.", false)
+ Operation.new('Cannot remove current branch.', false)
else
@branches.delete(branch_name)
Operation.new("Removed branch #{branch_name}.", true)
end
else
Operation.new("Branch #{branch_name} does not exist.", false)
end
end
def list
- message = ""
+ message = ''
@branches.sort.map do |name, branch|
if branch == @current_branch
message += "* #{name}\n"
else
message += " #{name}\n"
end
end
Operation.new(message.chomp, true)
end
end
class Operation
attr_reader :message
def initialize(message, success)
@message = message
@success = success
end
def success?
@success
end
def error?
not @success
end
end
class ResultOperation < Operation
attr_reader :result
def initialize(message, success, result)
super message, success
@result = result
end
end
class Commit < ResultOperation
attr_reader :date, :hash, :objects
def initialize(commit_message, success, objects = nil)
@date = Time.now
@hash = Digest::SHA1.hexdigest("#{date}#{commit_message}")
@objects = objects.clone
super commit_message, success, self
end
end