Решение на Пета задача от Мария Рангелова

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

Към профила на Мария Рангелова

Резултати

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

Код

require 'digest/sha1'
class ObjectStore
def self.init(&block)
repo = new
repo.instance_eval &block if block_given?
repo
end
def initialize
@stage = {}
@branch_manager = BranchManager.new
end
def add(name, object)
@stage[name] = object
Status.new(message: "Added #{name} to stage.",
success: true,
result: object)
end
def remove(name)
if @stage.include? name
Status.new(message: "Added #{name} for removal.",
success: true,
result: @stage.delete(name))
else
Status.new(message: "Object #{name} is not committed.",
success: false)
end
end
def commit(message)
if number_of_objects_changed == 0
Status.new(message: "Nothing to commit, working directory clean.",
success: false)
else
objects_changed = number_of_objects_changed
current_branch.commits << Commit.new(message, @stage.dup)
Status.new(message: "#{message}\n\t#{objects_changed} objects changed",
success: true,
result: last_commit)
end
end
def number_of_objects_changed
return @stage.size unless last_commit
objects_added = (@stage.values - last_commit.objects).size
objects_removed = (last_commit.objects - @stage.values).size
objects_added + objects_removed
end
def last_commit
current_branch.commits.last
end
def head
if last_commit
Status.new(message: "#{last_commit.message}",
success: true,
result: last_commit)
else
Status.new(message: "Branch #{branch.current_branch.name} " \
"does not have any commits yet.",
success: false)
end
end
def log
if current_branch.commits.empty?
Status.new(message: "Branch #{branch.current_branch.name} " \
"does not have any commits yet.",
success: false)
else
message = current_branch.commits.reverse.map do |commit|
"Commit #{commit.hash}\n" \
"Date: #{commit.date.strftime("%a %b %d %H:%M %Y %z")}" \
"\n\n\t#{commit.message}"
end
Status.new(message: message.join("\n\n"),
success: true)
end
end
def checkout(sha1)
if current_branch.commits.none? { |commit| commit.hash == sha1 }
Status.new(message: "Commit #{sha1} does not exist.",
success: false)
else
commit_index =
current_branch.commits.find_index { |commit| commit.hash == sha1 }
current_branch.commits = current_branch.commits[0..commit_index]
@stage = last_commit.objects_with_names
Status.new(message: "HEAD is now at #{sha1}.",
success: true,
result: last_commit)
end
end
def branch
@branch_manager
end
def current_branch
branch.current_branch
end
def get(name)
if last_commit and last_commit.objects_with_names.include?(name)
Status.new(message: "Found object #{name}.",
success: true,
result: last_commit.objects_with_names[name])
else
Status.new(message: "Object #{name} is not committed.",
success: false)
end
end
class BranchManager
attr_accessor :current_branch, :branches
def initialize
@current_branch = Branch.new(name: 'master')
@branches = [@current_branch]
end
def create(name)
if branch_exists?(name)
Status.new(message: "Branch #{name} already exists.",
success: false)
else
branches << Branch.new(name: name, commits: current_branch.commits)
Status.new(message: "Created branch #{name}.",
success: true)
end
end
def remove(name)
if branch_exists?(name) and current_branch?(name)
Status.new(message: 'Cannot remove current branch.',
success: false)
elsif branch_exists?(name) and not current_branch?(name)
branches.delete_if { |branch| branch.name == name }
Status.new(message: "Removed branch #{name}.",
success: true)
elsif not branch_exists?(name)
Status.new(message: "Branch #{name} does not exist.",
success: false)
end
end
def checkout(name)
if branch_exists?(name)
current_branch = branches.find { |branch| branch.name == name }
unless current_branch.commits.empty?
@stage = current_branch.commits.last.objects_with_names
end
Status.new(message: "Switched to branch #{name}.",
success: true)
else
Status.new(message: "Branch #{name} does not exist.",
success: false)
end
end
def list
message = branches.map(&:name).sort.map do |name|
current_branch?(name) ? "* #{name}" : " #{name}"
end
Status.new(message: message.join("\n"),
success: true)
end
def branch_exists?(name)
branches.any? { |branch| branch.name == name}
end
def current_branch?(name)
current_branch.name == name
end
class Branch
attr_reader :name
attr_accessor :commits
def initialize(name:, commits: [])
@name = name
@commits = commits
end
end
end
class Status
attr_reader :message, :success, :result
def initialize(message:, success: , result: nil)
@message = message
@success = success
@result = result
end
def success?
success
end
def error?
not success?
end
end
class Commit
attr_reader :message, :objects, :objects_with_names, :date, :hash
def initialize(message, objects)
@message = message
@objects = objects.values
@objects_with_names = objects
@date = Time.now
@hash = Digest::SHA1.hexdigest "#{@time}#{message}"
end
end
end

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

........FFFF....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 #<ObjectStore::Status:0x007f679b461a40 @message="Commit 760af3b5c0afc87ffc251a7d6dcfc22706b198a4\nDate: Mon Jan 11 11:54 2016 +0200\n\n\tSo cool!", @success=true, @result=nil> to be success "Commit 381573fc6aa4a6bb947e617a74fc4e0a5e152245\nDate: Mon Jan 11 11:54 2016 +0200\n\n\tSo cool!"
     # /tmp/d20160111-5693-ln6xn9/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 #<ObjectStore::Status:0x007f679b45d008 @message="Commit 760af3b5c0afc87ffc251a7d6dcfc22706b198a4\nDate: Mon Jan 11 11:54 2016 +0200\n\n\tSo cool!", @success=true, @result=nil> to be success "Commit 381573fc6aa4a6bb947e617a74fc4e0a5e152245\nDate: Mon Jan 11 11:54 2016 +0200\n\n\tSo cool!"
     # /tmp/d20160111-5693-ln6xn9/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 #<ObjectStore::Status:0x007f679b4479b0 @message="Commit 461d2638f26a54dfb37f51bc222a7e6a6412c1fa\nDate: Mon Jan 11 11:54 2016 +0200\n\n\tSecond commit\n\nCommit 1d948d5579c61d4d80112a583877a2e08bf8d6da\nDate: Mon Jan 11 11:54 2016 +0200\n\n\tFirst commit", @success=true, @result=nil> to be success "Commit ffeb5391d1ec154dd4a821a1aeed876cad514a0d\nDate: Mon Jan 11 11:54 2016 +0200\n\n\tSecond commit\n\nCommit 48bd765d675f355375408e84d12573236b16ddc2\nDate: Mon Jan 11 11:54 2016 +0200\n\n\tFirst commit"
     # /tmp/d20160111-5693-ln6xn9/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 #<ObjectStore::Status:0x007f679b441240 @message="Commit 461d2638f26a54dfb37f51bc222a7e6a6412c1fa\nDate: Mon Jan 11 11:54 2016 +0200\n\n\tSecond commit\n\nCommit 1d948d5579c61d4d80112a583877a2e08bf8d6da\nDate: Mon Jan 11 11:54 2016 +0200\n\n\tFirst commit", @success=true, @result=nil> to be success "Commit 48bd765d675f355375408e84d12573236b16ddc2\nDate: Mon Jan 11 11:54 2016 +0200\n\n\tFirst commit"
     # /tmp/d20160111-5693-ln6xn9/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 #<ObjectStore::Status:0x007f679b080890 @message="Second commit", @success=true, @result=#<ObjectStore::Commit:0x007f679b0a1158 @message="Second commit", @objects=["content1", "content2"], @objects_with_names={"object1"=>"content1", "object2"=>"content2"}, @date=2016-01-11 11:54:58 +0200, @hash="461d2638f26a54dfb37f51bc222a7e6a6412c1fa">> to be success "First commit" and #<ObjectStore::Commit:0x007f679b0c0df0 @message="First commit", @objects=["content1"], @objects_with_names={"object1"=>"content1"}, @date=2016-01-11 11:54:58 +0200, @hash="1d948d5579c61d4d80112a583877a2e08bf8d6da">
     # /tmp/d20160111-5693-ln6xn9/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)>'

Finished in 0.03051 seconds
30 examples, 5 failures

Failed examples:

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

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

Мария обнови решението на 23.11.2015 14:49 (преди над 8 години)

+require 'digest/sha1'
+
+class ObjectStore
+ def self.init(&block)
+ repo = new
+ repo.instance_eval &block if block_given?
+ repo
+ end
+
+ def initialize
+ @stage = {}
+ @branch_manager = BranchManager.new
+ end
+
+ def add(name, object)
+ @stage[name] = object
+ Status.new(message: "Added #{name} to stage.",
+ success: true,
+ result: object)
+ end
+
+ def remove(name)
+ if @stage.include? name
+ Status.new(message: "Added #{name} for removal.",
+ success: true,
+ result: @stage.delete(name))
+ else
+ Status.new(message: "Object #{name} is not committed.",
+ success: false)
+ end
+ end
+
+ def commit(message)
+ if number_of_objects_changed == 0
+ Status.new(message: "Nothing to commit, working directory clean.",
+ success: false)
+ else
+ objects_changed = number_of_objects_changed
+ current_branch.commits << Commit.new(message, @stage.dup)
+ Status.new(message: "#{message}\n\t#{objects_changed} objects changed",
+ success: true,
+ result: last_commit)
+ end
+ end
+
+ def number_of_objects_changed
+ return @stage.size unless last_commit
+
+ objects_added = (@stage.values - last_commit.objects).size
+ objects_removed = (last_commit.objects - @stage.values).size
+
+ objects_added + objects_removed
+ end
+
+ def last_commit
+ current_branch.commits.last
+ end
+
+ def head
+ if last_commit
+ Status.new(message: "#{last_commit.message}",
+ success: true,
+ result: last_commit)
+ else
+ Status.new(message: "Branch #{branch.current_branch.name} " \
+ "does not have any commits yet.",
+ success: false)
+ end
+ end
+
+ def log
+ if current_branch.commits.empty?
+ Status.new(message: "Branch #{branch.current_branch.name} " \
+ "does not have any commits yet.",
+ success: false)
+ else
+ message = current_branch.commits.reverse.map do |commit|
+ "Commit #{commit.hash}\n" \
+ "Date: #{commit.date.strftime("%a %b %d %H:%M %Y %z")}" \
+ "\n\n\t#{commit.message}"
+ end
+ Status.new(message: message.join("\n\n"),
+ success: true)
+ end
+ end
+
+ def checkout(sha1)
+ if current_branch.commits.none? { |commit| commit.hash == sha1 }
+ Status.new(message: "Commit #{sha1} does not exist.",
+ success: false)
+ else
+ commit_index =
+ current_branch.commits.find_index { |commit| commit.hash == sha1 }
+ current_branch.commits = current_branch.commits[0..commit_index]
+ @stage = last_commit.objects_with_names
+
+ Status.new(message: "HEAD is now at #{sha1}.",
+ success: true,
+ result: last_commit)
+ end
+ end
+
+ def branch
+ @branch_manager
+ end
+
+ def current_branch
+ branch.current_branch
+ end
+
+ def get(name)
+ if last_commit and last_commit.objects_with_names.include?(name)
+ Status.new(message: "Found object #{name}.",
+ success: true,
+ result: last_commit.objects_with_names[name])
+ else
+ Status.new(message: "Object #{name} is not committed.",
+ success: false)
+ end
+ end
+
+ class BranchManager
+ attr_accessor :current_branch, :branches
+
+ def initialize
+ @current_branch = Branch.new(name: 'master')
+ @branches = [@current_branch]
+ end
+
+ def create(name)
+ if branch_exists?(name)
+ Status.new(message: "Branch #{name} already exists.",
+ success: false)
+ else
+ branches << Branch.new(name: name, commits: current_branch.commits)
+ Status.new(message: "Created branch #{name}.",
+ success: true)
+ end
+ end
+
+ def remove(name)
+ if branch_exists?(name) and current_branch?(name)
+ Status.new(message: 'Cannot remove current branch.',
+ success: false)
+ elsif branch_exists?(name) and not current_branch?(name)
+ branches.delete_if { |branch| branch.name == name }
+ Status.new(message: "Removed branch #{name}.",
+ success: true)
+ elsif not branch_exists?(name)
+ Status.new(message: "Branch #{name} does not exist.",
+ success: false)
+ end
+ end
+
+ def checkout(name)
+ if branch_exists?(name)
+ current_branch = branches.find { |branch| branch.name == name }
+ unless current_branch.commits.empty?
+ @stage = current_branch.commits.last.objects_with_names
+ end
+ Status.new(message: "Switched to branch #{name}.",
+ success: true)
+ else
+ Status.new(message: "Branch #{name} does not exist.",
+ success: false)
+ end
+ end
+
+ def list
+ message = branches.map(&:name).sort.map do |name|
+ current_branch?(name) ? "* #{name}" : " #{name}"
+ end
+ Status.new(message: message.join("\n"),
+ success: true)
+ end
+
+ def branch_exists?(name)
+ branches.any? { |branch| branch.name == name}
+ end
+
+ def current_branch?(name)
+ current_branch.name == name
+ end
+
+ class Branch
+ attr_reader :name
+ attr_accessor :commits
+
+ def initialize(name:, commits: [])
+ @name = name
+ @commits = commits
+ end
+ end
+ end
+
+ class Status
+ attr_reader :message, :success, :result
+
+ def initialize(message:, success: , result: nil)
+ @message = message
+ @success = success
+ @result = result
+ end
+
+ def success?
+ success
+ end
+
+ def error?
+ not success?
+ end
+ end
+
+ class Commit
+ attr_reader :message, :objects, :objects_with_names, :date, :hash
+
+ def initialize(message, objects)
+ @message = message
+ @objects = objects.values
+ @objects_with_names = objects
+ @date = Time.now
+ @hash = Digest::SHA1.hexdigest "#{@time}#{message}"
+ end
+ end
+end