Решение на Пета задача от Десислава Цветкова

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

Към профила на Десислава Цветкова

Резултати

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

Код

require 'time'
require 'digest/sha1'
class ObjectStore
class Result
attr_reader :message, :result
attr_writer :result
def initialize(message, success, error, result = nil)
@message = message
@success = success
@error = error
@result = result
end
def success?
@success
end
def error?
@error
end
end
class Repository
class Commit
attr_accessor :commit_files
attr_reader :message, :date, :hash
def initialize(files, hash, message, date)
@hash = hash
@commit_files = files
@message = message
@date = date
end
def objects
@commit_files.values
end
end
class Branch
attr_accessor :added_files, :removed_files, :changed_files, :commits
attr_reader :name
def initialize(name, commits = [])
@name = name
@commits = commits
end
def remove_file(name)
removed = @commits.last.commit_files[name]
Result.new("Added #{name} for removal." , true, false, removed)
end
def make_new_commit(message, date, commit_files, changed_files)
hash = Digest::SHA1.hexdigest(date.to_s + message)
@commits << Commit.new(commit_files, hash, message, date)
result = Result.new("#{message}\n\t#{changed_files} objects changed",
true, false, @commits.last)
end
def checkout(hash)
index_commit = @commits.index{|x| x.hash == hash}
if index_commit.nil?
Result.new("Commit #{hash} does not exist.", false, true)
else
@commits = @commits.take(index_commit + 1)
Result.new("HEAD is now at #{hash}.", true, false, @commits.last)
end
end
end
class BranchManager
attr_reader :current_branch, :branches
def initialize
@current_branch = Branch.new("master")
@branches = {"master": @current_branch}
@added_files = {}
@removed_files = {}
@changed_files = 0
end
def add(name, object)
@changed_files += 1 unless @added_files.has_key?(name)
@added_files[name] = object
message = "Added #{name} to stage."
Result.new(message, true, false, object)
end
def clean_files
@added_files = {}
@removed_files = []
@changed_files = 0
end
def remove_extra(name)
@removed_files << name
@changed_files += 1
end
def make_commit_files
if @current_branch.commits.empty?
data = @added_files
else
data = @current_branch.commits.last.commit_files.merge(@added_files)
end
data.delete_if{|key, value| @removed_files.member?(key)}
end
def commit(message, date)
if @changed_files == 0
return Result.new("Nothing to commit, working directory clean.",
false,
true)
end
result = @current_branch.make_new_commit(message,
date,
make_commit_files,
@changed_files)
clean_files
result
end
def remove_file(name)
has_commits = head.success?
if @added_files.has_key?(name)
removed = @added_files.delete(name)
remove_extra(name)
Result.new("Added #{name} for removal." , true, false, removed)
elsif has_commits and @current_branch.commits.last.commit_files.
has_key?(name)
remove_extra(name)
@current_branch.remove_file(name)
else
return Result.new("Object #{name} is not committed.", false, true)
end
end
def checkout_hash(hash)
@current_branch.checkout(hash)
end
def create(branch_name)
if @branches.has_key?(branch_name.to_sym)
Result.new("Branch #{branch_name} already exists.", false, true)
else
new_branch = Branch.new(branch_name, @current_branch.commits.clone)
@branches[branch_name.to_sym] = new_branch
Result.new("Created branch #{branch_name}.", true, false, new_branch)
end
end
def checkout(branch_name)
if @branches.has_key?(branch_name.to_sym)
@current_branch = @branches[branch_name.to_sym]
Result.new("Switched to branch #{branch_name}.",
true,
false,
@current_branch)
else
Result.new("Branch #{branch_name} does not exist.", false, true)
end
end
def remove(branch_name)
if not @branches.has_key?(branch_name.to_sym)
Result.new("Branch #{branch_name} does not exist.", false, true)
elsif @current_branch.name.to_sym == branch_name.to_sym
Result.new("Cannot remove current branch.", false, true)
else
removed_branch = @branches.delete(branch_name.to_sym)
Result.new("Removed branch #{branch_name}.",
true,
false,
removed_branch)
end
end
def list
names = @branches.keys.map(&:to_s).sort
result = names.reduce("") do |message, name|
if name == @current_branch.name
message += "\n* " + name
else
message += "\n " + name
end
end
Result.new(result[1..-1], true, false)
end
def log
if @current_branch.commits.empty?
mess = "Branch #{@current_branch.name} does not have any commits yet."
Result.new(mess, false, true)
else
message = @current_branch.commits.reverse.reduce("") do |mess, commit|
mess + "Commit #{commit.hash}\n" \
"Date: #{commit.date.strftime('%a %b %-d %H:%M %Y %z')}" \
"\n\n\t#{commit.message}" + "\n\n"
end
Result.new(message.strip, true, false)
end
end
def head
if @current_branch.commits.empty?
Result.new("Branch #{@current_branch.name}" \
" does not have any commits yet.", false, true)
else
last_commit = @current_branch.commits.last
Result.new(last_commit.message, true, false, last_commit)
end
end
def get(name)
result_mistake = Result.new("Object #{name} is not committed.",
false,
true)
if @current_branch.commits.empty?
return result_mistake
end
if @current_branch.commits.last.commit_files.has_key?(name)
object = @current_branch.commits.last.commit_files[name]
else
return result_mistake
end
Result.new("Found object #{name}.", true, false, object)
end
end
attr_reader :branch_manager
def initialize
@branch_manager = BranchManager.new
end
def add(name, object)
@branch_manager.add(name, object)
end
def commit(message)
date = Time.now #"%a %b %e %k:%M %Y %z"
@branch_manager.commit(message, date)
end
def remove(name)
@branch_manager.remove_file(name)
end
def checkout(hash)
@branch_manager.checkout_hash(hash)
end
def branch
@branch_manager
end
def log
@branch_manager.log
end
def head
@branch_manager.head
end
def get(name)
@branch_manager.get(name)
end
end
class << self
def init(&block)
repo = Repository.new
return repo if not block_given?
repo.instance_eval(&block)
repo
end
end
end

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

........FFFF..................

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::Result:0x007f1a1bbc74d8 @message="Commit 7affe32f45ba2896015b8d376f57eea1c6123225\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSo cool!", @success=true, @error=false, @result=nil> to be success "Commit 020f94292ff683fc536310fe33c03adfbf64bbca\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSo cool!"
     # /tmp/d20160111-5693-1wo964q/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::Result:0x007f1a1bb87f90 @message="Commit 7affe32f45ba2896015b8d376f57eea1c6123225\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSo cool!", @success=true, @error=false, @result=nil> to be success "Commit 020f94292ff683fc536310fe33c03adfbf64bbca\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSo cool!"
     # /tmp/d20160111-5693-1wo964q/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::Result:0x007f1a1bb4f050 @message="Commit da5adbf12041a81e45509f56a0fd49bf1283515a\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tSecond commit\n\nCommit 820b55454995bd0c755c9ce77923ae16250f4d83\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tFirst commit", @success=true, @error=false, @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-1wo964q/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::Result:0x007f1a1bb35010 @message="Commit 820b55454995bd0c755c9ce77923ae16250f4d83\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tFirst commit", @success=true, @error=false, @result=nil> to be success "Commit 9a97b358afe869ba1e523d99dd2101dfc0570dc0\nDate: Mon Jan 11 11:55 2016 +0200\n\n\tFirst commit"
     # /tmp/d20160111-5693-1wo964q/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)>'

Finished in 0.03629 seconds
30 examples, 4 failures

Failed examples:

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

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

Десислава обнови решението на 15.11.2015 23:14 (преди над 8 години)

+require 'date'
+require 'digest/sha1'
+
+
+class ObjectStore
+
+ class Result
+ attr_reader :message, :result
+ attr_writer :result
+
+ def initialize(message, success, error, result = nil)
+ @message = message
+ @success = success
+ @error = error
+ @result = result
+ end
+
+ def success?
+ @success
+ end
+
+ def error?
+ @error
+ end
+ end
+
+ class Repository
+
+ class Commit
+ attr_accessor :commit_files
+ attr_reader :message, :date, :hash
+
+ def initialize(files, hash, message, date)
+ @hash = hash
+ @commit_files = files
+ @message = message
+ @date = date
+ end
+
+ def objects
+ @commit_files
+ end
+ end
+
+ class Branch
+ attr_accessor :added_files, :removed_files, :changed_files, :commits
+ attr_reader :name
+
+ def initialize(name, commits = [])
+ @name = name
+ @commits = commits
+ @added_files = {}
+ @removed_files = {}
+ @changed_files = 0
+ end
+
+ def clean_files
+ @added_files = {}
+ @removed_files = {}
+ @changed_files = 0
+ end
+
+ def add_file(name, object)
+ @changed_files += 1 unless @added_files.has_key?(name)
+ @added_files[name] = object
+ message = "Added #{name} to stage."
+ Result.new(message, true, false, object)
+ end
+
+ def remove_file(name)
+ if @added_files.has_key?(name)
+ removed = @added_files.delete(name)
+ elsif not @commits.empty? and @commits.last.commit_files.has_key?(name)
+ removed = @commits.last.commit_files.delete(name)
+ else
+ return Result.new("Object #{name} is not committed.", false, true)
+ end
+ @changed_files += 1
+ Result.new("Added #{name} for removal." , true, false, removed)
+ end
+
+ def make_commit_files
+ if @commits.empty?
+ all_data = @added_files
+ else
+ all_data = @commits.last.commit_files.merge(@added_files)
+ end
+ all_data.delete_if{|key, value| @removed_files.has_key?(key)}
+ end
+
+ def make_new_commit(message, date)
+ if @changed_files == 0
+ return Result.new("Nothing to commit, working directory clean.",
+ false,
+ true)
+ end
+
+ hash = Digest::SHA1.hexdigest(date.to_s + message)
+
+ @commits << Commit.new(make_commit_files, hash, message, date)
+ result = Result.new("#{message}\n\t#{@changed_files} objects changed",
+ true, false, @commits.last)
+ clean_files
+ result
+ end
+
+ def checkout(hash)
+ index_commit = @commits.index{|x| x.hash == hash}
+ if index_commit.nil?
+ Result.new("Commit #{hash} does not exist.", false, true)
+ else
+ @commits = @commits.take(index_commit + 1)
+ Result.new("HEAD is now at #{hash}.", true, false, @commits.last)
+ end
+ end
+ end
+
+ class BranchManager
+
+ attr_reader :current_branch, :branches
+ def initialize
+ @current_branch = Branch.new("master")
+ @branches = {"master": @current_branch}
+ end
+
+ def add(name, object)
+ @current_branch.add_file(name, object)
+ end
+
+ def commit(message, date)
+ @current_branch.make_new_commit(message, date)
+ end
+
+ def remove_file(name)
+ @current_branch.remove_file(name)
+ end
+
+ def checkout_hash(hash)
+ @current_branch.checkout(hash)
+ end
+
+ def create(branch_name)
+ if @branches.has_key?(branch_name)
+ Result.new("Branch #{branch_name} already exists.", false, true)
+ else
+ new_branch = Branch.new(branch_name, @current_branch.commits.clone)
+ @branches[branch_name] = new_branch
+ Result.new("Created branch #{branch_name}.", true, false, new_branch)
+ end
+ end
+
+ def checkout(branch_name)
+ if @branches.has_key?(branch_name)
+ @current_branch = @branches[branch_name]
+ Result.new("Switched to branch #{branch_name}.",
+ true,
+ false,
+ @current_branch)
+ else
+ Result.new("Branch #{branch_name} does not exist.", false, true)
+ end
+ end
+
+ def remove(branch_name)
+ if not @branches.has_key?(branch_name)
+ Result.new("Branch #{branch_name} does not exist.", false, true)
+ elsif @current_branch.name == branch_name
+ Result.new("Cannot remove current branch.", false, true)
+ else
+ removed_branch = @branches.delete(branch_name)
+ Result.new("Removed branch #{branch_name}.",
+ true,
+ false,
+ removed_branch)
+ end
+ end
+
+ def list
+ names = @branches.keys.map(&:to_s).sort
+ result = names.reduce("") do |message, name|
+ if name == @current_branch.name
+ message += "\n* " + name
+ else
+ message += "\n " + name
+ end
+ end
+ Result.new(result[1..-1], true, false)
+ end
+
+ def log
+ if @current_branch.commits.empty?
+ mess = "Branch #{@current_branch.name} does not have any commits yet."
+ Result.new(mess, false, true)
+ else
+ message = @current_branch.commits.reduce("") do |mess, commit|
+ mess + "Commit #{commit.hash}\n" \
+ "Date: #{commit.date}\n\n\t#{commit.message}"
+ end
+ Result.new(message, true, false)
+ end
+ end
+
+ def head
+ if @current_branch.commits.empty?
+ Result.new("Branch #{@current_branch.name}" \
+ " does not have any commits yet.", false, true)
+ else
+ last_commit = @current_branch.commits.last
+ Result.new(last_commit.message, true, false, last_commit)
+ end
+ end
+
+ def get(name)
+ result_mistake = Result.new("Object #{name} is not committed.",
+ false,
+ true)
+ if @current_branch.commits.empty?
+ return result_mistake
+ end
+
+ if @current_branch.commits.last.objects.has_key?(name)
+ object = @current_branch.commits.last.objects[name]
+ else
+ return result_mistake
+ end
+ Result.new("Found object #{name}.", true, false, object)
+ end
+ end
+
+ attr_reader :branch_manager
+ def initialize
+ @branch_manager = BranchManager.new
+ end
+
+ def add(name, object)
+ @branch_manager.add(name, object)
+ end
+
+ def commit(message)
+ date = DateTime.now.strftime("%a %b %e %k:%M %Y %z")
+ @branch_manager.commit(message, date)
+ end
+
+ def remove(name)
+ @branch_manager.remove_file(name)
+ end
+
+ def checkout(hash)
+ @branch_manager.checkout_hash(hash)
+ end
+
+ def branch
+ @branch_manager
+ end
+
+ def log
+ @branch_manager.log
+ end
+
+ def head
+ @branch_manager.head
+ end
+
+ def get(name)
+ @branch_manager.get(name)
+ end
+ end
+
+ class << self
+ def init(&block)
+ repo = Repository.new
+ return repo if not block_given?
+ repo.instance_eval(&block)
+ repo
+ end
+ end
+end

Десислава обнови решението на 15.11.2015 23:20 (преди над 8 години)

require 'date'
require 'digest/sha1'
class ObjectStore
class Result
attr_reader :message, :result
attr_writer :result
def initialize(message, success, error, result = nil)
@message = message
@success = success
@error = error
@result = result
end
def success?
@success
end
def error?
@error
end
end
class Repository
class Commit
attr_accessor :commit_files
attr_reader :message, :date, :hash
def initialize(files, hash, message, date)
@hash = hash
@commit_files = files
@message = message
@date = date
end
def objects
@commit_files
end
end
class Branch
attr_accessor :added_files, :removed_files, :changed_files, :commits
attr_reader :name
def initialize(name, commits = [])
@name = name
@commits = commits
@added_files = {}
@removed_files = {}
@changed_files = 0
end
def clean_files
@added_files = {}
@removed_files = {}
@changed_files = 0
end
def add_file(name, object)
@changed_files += 1 unless @added_files.has_key?(name)
@added_files[name] = object
message = "Added #{name} to stage."
Result.new(message, true, false, object)
end
def remove_file(name)
if @added_files.has_key?(name)
removed = @added_files.delete(name)
elsif not @commits.empty? and @commits.last.commit_files.has_key?(name)
removed = @commits.last.commit_files.delete(name)
else
return Result.new("Object #{name} is not committed.", false, true)
end
@changed_files += 1
Result.new("Added #{name} for removal." , true, false, removed)
end
def make_commit_files
if @commits.empty?
all_data = @added_files
else
all_data = @commits.last.commit_files.merge(@added_files)
end
all_data.delete_if{|key, value| @removed_files.has_key?(key)}
end
def make_new_commit(message, date)
if @changed_files == 0
return Result.new("Nothing to commit, working directory clean.",
- false,
- true)
+ false,
+ true)
end
hash = Digest::SHA1.hexdigest(date.to_s + message)
@commits << Commit.new(make_commit_files, hash, message, date)
result = Result.new("#{message}\n\t#{@changed_files} objects changed",
true, false, @commits.last)
clean_files
result
end
def checkout(hash)
index_commit = @commits.index{|x| x.hash == hash}
if index_commit.nil?
Result.new("Commit #{hash} does not exist.", false, true)
else
@commits = @commits.take(index_commit + 1)
Result.new("HEAD is now at #{hash}.", true, false, @commits.last)
end
end
end
class BranchManager
attr_reader :current_branch, :branches
def initialize
@current_branch = Branch.new("master")
@branches = {"master": @current_branch}
end
def add(name, object)
@current_branch.add_file(name, object)
end
def commit(message, date)
@current_branch.make_new_commit(message, date)
end
def remove_file(name)
@current_branch.remove_file(name)
end
def checkout_hash(hash)
@current_branch.checkout(hash)
end
def create(branch_name)
if @branches.has_key?(branch_name)
Result.new("Branch #{branch_name} already exists.", false, true)
else
new_branch = Branch.new(branch_name, @current_branch.commits.clone)
@branches[branch_name] = new_branch
Result.new("Created branch #{branch_name}.", true, false, new_branch)
end
end
def checkout(branch_name)
if @branches.has_key?(branch_name)
@current_branch = @branches[branch_name]
Result.new("Switched to branch #{branch_name}.",
- true,
- false,
- @current_branch)
+ true,
+ false,
+ @current_branch)
else
Result.new("Branch #{branch_name} does not exist.", false, true)
end
end
def remove(branch_name)
if not @branches.has_key?(branch_name)
Result.new("Branch #{branch_name} does not exist.", false, true)
elsif @current_branch.name == branch_name
Result.new("Cannot remove current branch.", false, true)
else
removed_branch = @branches.delete(branch_name)
Result.new("Removed branch #{branch_name}.",
- true,
- false,
- removed_branch)
+ true,
+ false,
+ removed_branch)
end
end
def list
names = @branches.keys.map(&:to_s).sort
result = names.reduce("") do |message, name|
if name == @current_branch.name
message += "\n* " + name
else
message += "\n " + name
end
end
Result.new(result[1..-1], true, false)
end
def log
if @current_branch.commits.empty?
mess = "Branch #{@current_branch.name} does not have any commits yet."
Result.new(mess, false, true)
else
message = @current_branch.commits.reduce("") do |mess, commit|
mess + "Commit #{commit.hash}\n" \
"Date: #{commit.date}\n\n\t#{commit.message}"
end
Result.new(message, true, false)
end
end
def head
if @current_branch.commits.empty?
Result.new("Branch #{@current_branch.name}" \
" does not have any commits yet.", false, true)
else
last_commit = @current_branch.commits.last
Result.new(last_commit.message, true, false, last_commit)
end
end
def get(name)
result_mistake = Result.new("Object #{name} is not committed.",
- false,
- true)
+ false,
+ true)
if @current_branch.commits.empty?
return result_mistake
end
if @current_branch.commits.last.objects.has_key?(name)
object = @current_branch.commits.last.objects[name]
else
return result_mistake
end
Result.new("Found object #{name}.", true, false, object)
end
end
attr_reader :branch_manager
def initialize
@branch_manager = BranchManager.new
end
def add(name, object)
@branch_manager.add(name, object)
end
def commit(message)
date = DateTime.now.strftime("%a %b %e %k:%M %Y %z")
@branch_manager.commit(message, date)
end
def remove(name)
@branch_manager.remove_file(name)
end
def checkout(hash)
@branch_manager.checkout_hash(hash)
end
def branch
@branch_manager
end
def log
@branch_manager.log
end
def head
@branch_manager.head
end
def get(name)
@branch_manager.get(name)
end
end
class << self
def init(&block)
repo = Repository.new
return repo if not block_given?
repo.instance_eval(&block)
repo
end
end
end

Десислава обнови решението на 15.11.2015 23:58 (преди над 8 години)

require 'date'
require 'digest/sha1'
class ObjectStore
class Result
attr_reader :message, :result
attr_writer :result
def initialize(message, success, error, result = nil)
@message = message
@success = success
@error = error
@result = result
end
def success?
@success
end
def error?
@error
end
end
class Repository
class Commit
attr_accessor :commit_files
attr_reader :message, :date, :hash
def initialize(files, hash, message, date)
@hash = hash
@commit_files = files
@message = message
@date = date
end
def objects
@commit_files
end
end
class Branch
attr_accessor :added_files, :removed_files, :changed_files, :commits
attr_reader :name
def initialize(name, commits = [])
@name = name
@commits = commits
@added_files = {}
@removed_files = {}
@changed_files = 0
end
def clean_files
@added_files = {}
@removed_files = {}
@changed_files = 0
end
def add_file(name, object)
@changed_files += 1 unless @added_files.has_key?(name)
@added_files[name] = object
message = "Added #{name} to stage."
Result.new(message, true, false, object)
end
def remove_file(name)
if @added_files.has_key?(name)
removed = @added_files.delete(name)
elsif not @commits.empty? and @commits.last.commit_files.has_key?(name)
removed = @commits.last.commit_files.delete(name)
else
return Result.new("Object #{name} is not committed.", false, true)
end
@changed_files += 1
Result.new("Added #{name} for removal." , true, false, removed)
end
def make_commit_files
if @commits.empty?
all_data = @added_files
else
all_data = @commits.last.commit_files.merge(@added_files)
end
all_data.delete_if{|key, value| @removed_files.has_key?(key)}
end
def make_new_commit(message, date)
if @changed_files == 0
return Result.new("Nothing to commit, working directory clean.",
false,
true)
end
hash = Digest::SHA1.hexdigest(date.to_s + message)
@commits << Commit.new(make_commit_files, hash, message, date)
result = Result.new("#{message}\n\t#{@changed_files} objects changed",
true, false, @commits.last)
clean_files
result
end
def checkout(hash)
index_commit = @commits.index{|x| x.hash == hash}
if index_commit.nil?
Result.new("Commit #{hash} does not exist.", false, true)
else
@commits = @commits.take(index_commit + 1)
Result.new("HEAD is now at #{hash}.", true, false, @commits.last)
end
end
end
class BranchManager
attr_reader :current_branch, :branches
def initialize
@current_branch = Branch.new("master")
@branches = {"master": @current_branch}
end
def add(name, object)
@current_branch.add_file(name, object)
end
def commit(message, date)
@current_branch.make_new_commit(message, date)
end
def remove_file(name)
@current_branch.remove_file(name)
end
def checkout_hash(hash)
@current_branch.checkout(hash)
end
def create(branch_name)
if @branches.has_key?(branch_name)
Result.new("Branch #{branch_name} already exists.", false, true)
else
new_branch = Branch.new(branch_name, @current_branch.commits.clone)
@branches[branch_name] = new_branch
Result.new("Created branch #{branch_name}.", true, false, new_branch)
end
end
def checkout(branch_name)
if @branches.has_key?(branch_name)
@current_branch = @branches[branch_name]
Result.new("Switched to branch #{branch_name}.",
true,
false,
@current_branch)
else
Result.new("Branch #{branch_name} does not exist.", false, true)
end
end
def remove(branch_name)
if not @branches.has_key?(branch_name)
Result.new("Branch #{branch_name} does not exist.", false, true)
elsif @current_branch.name == branch_name
Result.new("Cannot remove current branch.", false, true)
else
removed_branch = @branches.delete(branch_name)
Result.new("Removed branch #{branch_name}.",
true,
false,
removed_branch)
end
end
def list
names = @branches.keys.map(&:to_s).sort
result = names.reduce("") do |message, name|
if name == @current_branch.name
message += "\n* " + name
else
message += "\n " + name
end
end
Result.new(result[1..-1], true, false)
end
def log
if @current_branch.commits.empty?
mess = "Branch #{@current_branch.name} does not have any commits yet."
Result.new(mess, false, true)
else
- message = @current_branch.commits.reduce("") do |mess, commit|
+ message = @current_branch.commits.reverse.reduce("") do |mess, commit|
mess + "Commit #{commit.hash}\n" \
- "Date: #{commit.date}\n\n\t#{commit.message}"
+ "Date: #{commit.date}\n\n\t#{commit.message}" + "\n\n"
end
Result.new(message, true, false)
end
end
def head
if @current_branch.commits.empty?
Result.new("Branch #{@current_branch.name}" \
" does not have any commits yet.", false, true)
else
last_commit = @current_branch.commits.last
Result.new(last_commit.message, true, false, last_commit)
end
end
def get(name)
result_mistake = Result.new("Object #{name} is not committed.",
false,
true)
if @current_branch.commits.empty?
return result_mistake
end
if @current_branch.commits.last.objects.has_key?(name)
object = @current_branch.commits.last.objects[name]
else
return result_mistake
end
Result.new("Found object #{name}.", true, false, object)
end
end
attr_reader :branch_manager
def initialize
@branch_manager = BranchManager.new
end
def add(name, object)
@branch_manager.add(name, object)
end
def commit(message)
date = DateTime.now.strftime("%a %b %e %k:%M %Y %z")
@branch_manager.commit(message, date)
end
def remove(name)
@branch_manager.remove_file(name)
end
def checkout(hash)
@branch_manager.checkout_hash(hash)
end
def branch
@branch_manager
end
def log
@branch_manager.log
end
def head
@branch_manager.head
end
def get(name)
@branch_manager.get(name)
end
end
class << self
def init(&block)
repo = Repository.new
return repo if not block_given?
repo.instance_eval(&block)
repo
end
end
end

Десислава обнови решението на 17.11.2015 01:34 (преди над 8 години)

-require 'date'
+require 'time'
require 'digest/sha1'
class ObjectStore
class Result
attr_reader :message, :result
attr_writer :result
def initialize(message, success, error, result = nil)
@message = message
@success = success
@error = error
@result = result
end
def success?
@success
end
def error?
@error
end
end
class Repository
class Commit
attr_accessor :commit_files
attr_reader :message, :date, :hash
def initialize(files, hash, message, date)
@hash = hash
@commit_files = files
@message = message
@date = date
end
def objects
- @commit_files
+ @commit_files.map{|x| x.last}
end
end
class Branch
attr_accessor :added_files, :removed_files, :changed_files, :commits
attr_reader :name
def initialize(name, commits = [])
@name = name
@commits = commits
@added_files = {}
@removed_files = {}
@changed_files = 0
end
def clean_files
@added_files = {}
@removed_files = {}
@changed_files = 0
end
def add_file(name, object)
@changed_files += 1 unless @added_files.has_key?(name)
@added_files[name] = object
message = "Added #{name} to stage."
Result.new(message, true, false, object)
end
def remove_file(name)
if @added_files.has_key?(name)
removed = @added_files.delete(name)
elsif not @commits.empty? and @commits.last.commit_files.has_key?(name)
removed = @commits.last.commit_files.delete(name)
else
return Result.new("Object #{name} is not committed.", false, true)
end
@changed_files += 1
Result.new("Added #{name} for removal." , true, false, removed)
end
def make_commit_files
if @commits.empty?
all_data = @added_files
else
all_data = @commits.last.commit_files.merge(@added_files)
end
all_data.delete_if{|key, value| @removed_files.has_key?(key)}
end
def make_new_commit(message, date)
if @changed_files == 0
return Result.new("Nothing to commit, working directory clean.",
false,
true)
end
hash = Digest::SHA1.hexdigest(date.to_s + message)
@commits << Commit.new(make_commit_files, hash, message, date)
result = Result.new("#{message}\n\t#{@changed_files} objects changed",
true, false, @commits.last)
clean_files
result
end
def checkout(hash)
index_commit = @commits.index{|x| x.hash == hash}
if index_commit.nil?
Result.new("Commit #{hash} does not exist.", false, true)
else
@commits = @commits.take(index_commit + 1)
Result.new("HEAD is now at #{hash}.", true, false, @commits.last)
end
end
end
class BranchManager
attr_reader :current_branch, :branches
def initialize
@current_branch = Branch.new("master")
@branches = {"master": @current_branch}
end
def add(name, object)
@current_branch.add_file(name, object)
end
def commit(message, date)
@current_branch.make_new_commit(message, date)
end
def remove_file(name)
@current_branch.remove_file(name)
end
def checkout_hash(hash)
@current_branch.checkout(hash)
end
def create(branch_name)
- if @branches.has_key?(branch_name)
+ if @branches.has_key?(branch_name.to_sym)
Result.new("Branch #{branch_name} already exists.", false, true)
else
new_branch = Branch.new(branch_name, @current_branch.commits.clone)
- @branches[branch_name] = new_branch
+ @branches[branch_name.to_sym] = new_branch
Result.new("Created branch #{branch_name}.", true, false, new_branch)
end
end
def checkout(branch_name)
- if @branches.has_key?(branch_name)
- @current_branch = @branches[branch_name]
+ if @branches.has_key?(branch_name.to_sym)
+ @current_branch = @branches[branch_name.to_sym]
Result.new("Switched to branch #{branch_name}.",
true,
false,
@current_branch)
else
Result.new("Branch #{branch_name} does not exist.", false, true)
end
end
def remove(branch_name)
- if not @branches.has_key?(branch_name)
+ if not @branches.has_key?(branch_name.to_sym)
Result.new("Branch #{branch_name} does not exist.", false, true)
- elsif @current_branch.name == branch_name
+ elsif @current_branch.name.to_sym == branch_name.to_sym
Result.new("Cannot remove current branch.", false, true)
else
- removed_branch = @branches.delete(branch_name)
+ removed_branch = @branches.delete(branch_name.to_sym)
Result.new("Removed branch #{branch_name}.",
true,
false,
removed_branch)
end
end
def list
names = @branches.keys.map(&:to_s).sort
result = names.reduce("") do |message, name|
if name == @current_branch.name
message += "\n* " + name
else
message += "\n " + name
end
end
Result.new(result[1..-1], true, false)
end
def log
if @current_branch.commits.empty?
mess = "Branch #{@current_branch.name} does not have any commits yet."
Result.new(mess, false, true)
else
message = @current_branch.commits.reverse.reduce("") do |mess, commit|
mess + "Commit #{commit.hash}\n" \
- "Date: #{commit.date}\n\n\t#{commit.message}" + "\n\n"
+ "Date: #{commit.date.strftime('%a %b %-d %H:%M %Y %z')}" \
+ "\n\n\t#{commit.message}" + "\n\n"
end
- Result.new(message, true, false)
+ Result.new(message.strip, true, false)
end
end
def head
if @current_branch.commits.empty?
Result.new("Branch #{@current_branch.name}" \
" does not have any commits yet.", false, true)
else
last_commit = @current_branch.commits.last
Result.new(last_commit.message, true, false, last_commit)
end
end
def get(name)
result_mistake = Result.new("Object #{name} is not committed.",
false,
true)
if @current_branch.commits.empty?
return result_mistake
end
- if @current_branch.commits.last.objects.has_key?(name)
- object = @current_branch.commits.last.objects[name]
+ if @current_branch.commits.last.commit_files.has_key?(name)
+ object = @current_branch.commits.last.commit_files[name]
else
return result_mistake
end
Result.new("Found object #{name}.", true, false, object)
end
end
attr_reader :branch_manager
def initialize
@branch_manager = BranchManager.new
end
def add(name, object)
@branch_manager.add(name, object)
end
def commit(message)
- date = DateTime.now.strftime("%a %b %e %k:%M %Y %z")
+ date = Time.now #"%a %b %e %k:%M %Y %z"
@branch_manager.commit(message, date)
end
def remove(name)
@branch_manager.remove_file(name)
end
def checkout(hash)
@branch_manager.checkout_hash(hash)
end
def branch
@branch_manager
end
def log
@branch_manager.log
end
def head
@branch_manager.head
end
def get(name)
@branch_manager.get(name)
end
end
class << self
def init(&block)
repo = Repository.new
return repo if not block_given?
repo.instance_eval(&block)
repo
end
end
end

Десислава обнови решението на 22.11.2015 23:21 (преди над 8 години)

require 'time'
require 'digest/sha1'
class ObjectStore
class Result
attr_reader :message, :result
attr_writer :result
def initialize(message, success, error, result = nil)
@message = message
@success = success
@error = error
@result = result
end
def success?
@success
end
def error?
@error
end
end
class Repository
class Commit
attr_accessor :commit_files
attr_reader :message, :date, :hash
def initialize(files, hash, message, date)
@hash = hash
@commit_files = files
@message = message
@date = date
end
def objects
@commit_files.map{|x| x.last}
end
end
class Branch
attr_accessor :added_files, :removed_files, :changed_files, :commits
attr_reader :name
def initialize(name, commits = [])
@name = name
@commits = commits
- @added_files = {}
- @removed_files = {}
- @changed_files = 0
end
- def clean_files
- @added_files = {}
- @removed_files = {}
- @changed_files = 0
- end
-
- def add_file(name, object)
- @changed_files += 1 unless @added_files.has_key?(name)
- @added_files[name] = object
- message = "Added #{name} to stage."
- Result.new(message, true, false, object)
- end
-
def remove_file(name)
- if @added_files.has_key?(name)
- removed = @added_files.delete(name)
- elsif not @commits.empty? and @commits.last.commit_files.has_key?(name)
removed = @commits.last.commit_files.delete(name)
- else
- return Result.new("Object #{name} is not committed.", false, true)
- end
- @changed_files += 1
- Result.new("Added #{name} for removal." , true, false, removed)
+ Result.new("Added #{name} for removal." , true, false, removed)
end
- def make_commit_files
- if @commits.empty?
- all_data = @added_files
- else
- all_data = @commits.last.commit_files.merge(@added_files)
- end
- all_data.delete_if{|key, value| @removed_files.has_key?(key)}
- end
-
- def make_new_commit(message, date)
- if @changed_files == 0
- return Result.new("Nothing to commit, working directory clean.",
- false,
- true)
- end
-
+ def make_new_commit(message, date, commit_files, changed_files)
hash = Digest::SHA1.hexdigest(date.to_s + message)
-
- @commits << Commit.new(make_commit_files, hash, message, date)
- result = Result.new("#{message}\n\t#{@changed_files} objects changed",
+ @commits << Commit.new(commit_files, hash, message, date)
+ result = Result.new("#{message}\n\t#{changed_files} objects changed",
true, false, @commits.last)
- clean_files
- result
end
def checkout(hash)
index_commit = @commits.index{|x| x.hash == hash}
if index_commit.nil?
Result.new("Commit #{hash} does not exist.", false, true)
else
@commits = @commits.take(index_commit + 1)
Result.new("HEAD is now at #{hash}.", true, false, @commits.last)
end
end
end
class BranchManager
attr_reader :current_branch, :branches
def initialize
@current_branch = Branch.new("master")
@branches = {"master": @current_branch}
+ @added_files = {}
+ @removed_files = {}
+ @changed_files = 0
end
def add(name, object)
- @current_branch.add_file(name, object)
+ @changed_files += 1 unless @added_files.has_key?(name)
+ @added_files[name] = object
+ message = "Added #{name} to stage."
+ Result.new(message, true, false, object)
end
+ def clean_files
+ @added_files = {}
+ @removed_files = {}
+ @changed_files = 0
+ end
+
+ def make_commit_files
+ if @current_branch.commits.empty?
+ data = @added_files
+ else
+ data = @current_branch.commits.last.commit_files.merge(@added_files)
+ end
+ data.delete_if{|key, value| @removed_files.has_key?(key)}
+ end
+
def commit(message, date)
- @current_branch.make_new_commit(message, date)
+ if @changed_files == 0
+ return Result.new("Nothing to commit, working directory clean.",
+ false,
+ true)
+ end
+ result = @current_branch.make_new_commit(message,
+ date,
+ make_commit_files,
+ @changed_files)
+ clean_files
+ result
end
def remove_file(name)
- @current_branch.remove_file(name)
+ has_commits = head.success?
+ if @added_files.has_key?(name)
+ removed = @added_files.delete(name)
+ @changed_files += 1
+ Result.new("Added #{name} for removal." , true, false, removed)
+
+ elsif has_commits and @current_branch.commits.last.commit_files.
+ has_key?(name)
+ @changed_files += 1
+ @current_branch.remove_file(name)
+ else
+ return Result.new("Object #{name} is not committed.", false, true)
+ end
end
def checkout_hash(hash)
@current_branch.checkout(hash)
end
def create(branch_name)
if @branches.has_key?(branch_name.to_sym)
Result.new("Branch #{branch_name} already exists.", false, true)
else
new_branch = Branch.new(branch_name, @current_branch.commits.clone)
@branches[branch_name.to_sym] = new_branch
Result.new("Created branch #{branch_name}.", true, false, new_branch)
end
end
def checkout(branch_name)
if @branches.has_key?(branch_name.to_sym)
@current_branch = @branches[branch_name.to_sym]
Result.new("Switched to branch #{branch_name}.",
true,
false,
@current_branch)
else
Result.new("Branch #{branch_name} does not exist.", false, true)
end
end
def remove(branch_name)
if not @branches.has_key?(branch_name.to_sym)
Result.new("Branch #{branch_name} does not exist.", false, true)
elsif @current_branch.name.to_sym == branch_name.to_sym
Result.new("Cannot remove current branch.", false, true)
else
removed_branch = @branches.delete(branch_name.to_sym)
Result.new("Removed branch #{branch_name}.",
true,
false,
removed_branch)
end
end
def list
names = @branches.keys.map(&:to_s).sort
result = names.reduce("") do |message, name|
if name == @current_branch.name
message += "\n* " + name
else
message += "\n " + name
end
end
Result.new(result[1..-1], true, false)
end
def log
if @current_branch.commits.empty?
mess = "Branch #{@current_branch.name} does not have any commits yet."
Result.new(mess, false, true)
else
message = @current_branch.commits.reverse.reduce("") do |mess, commit|
mess + "Commit #{commit.hash}\n" \
"Date: #{commit.date.strftime('%a %b %-d %H:%M %Y %z')}" \
"\n\n\t#{commit.message}" + "\n\n"
end
Result.new(message.strip, true, false)
end
end
def head
if @current_branch.commits.empty?
Result.new("Branch #{@current_branch.name}" \
" does not have any commits yet.", false, true)
else
last_commit = @current_branch.commits.last
Result.new(last_commit.message, true, false, last_commit)
end
end
def get(name)
result_mistake = Result.new("Object #{name} is not committed.",
false,
true)
if @current_branch.commits.empty?
return result_mistake
end
if @current_branch.commits.last.commit_files.has_key?(name)
object = @current_branch.commits.last.commit_files[name]
else
return result_mistake
end
Result.new("Found object #{name}.", true, false, object)
end
end
attr_reader :branch_manager
def initialize
@branch_manager = BranchManager.new
end
def add(name, object)
@branch_manager.add(name, object)
end
def commit(message)
date = Time.now #"%a %b %e %k:%M %Y %z"
@branch_manager.commit(message, date)
end
def remove(name)
@branch_manager.remove_file(name)
end
def checkout(hash)
@branch_manager.checkout_hash(hash)
end
def branch
@branch_manager
end
def log
@branch_manager.log
end
def head
@branch_manager.head
end
def get(name)
@branch_manager.get(name)
end
end
class << self
def init(&block)
repo = Repository.new
return repo if not block_given?
repo.instance_eval(&block)
repo
end
end
end

Десислава обнови решението на 22.11.2015 23:36 (преди над 8 години)

require 'time'
require 'digest/sha1'
class ObjectStore
class Result
attr_reader :message, :result
attr_writer :result
def initialize(message, success, error, result = nil)
@message = message
@success = success
@error = error
@result = result
end
def success?
@success
end
def error?
@error
end
end
class Repository
class Commit
attr_accessor :commit_files
attr_reader :message, :date, :hash
def initialize(files, hash, message, date)
@hash = hash
@commit_files = files
@message = message
@date = date
end
def objects
@commit_files.map{|x| x.last}
end
end
class Branch
attr_accessor :added_files, :removed_files, :changed_files, :commits
attr_reader :name
def initialize(name, commits = [])
@name = name
@commits = commits
end
def remove_file(name)
- removed = @commits.last.commit_files.delete(name)
+ removed = @commits.last.commit_files[name]
Result.new("Added #{name} for removal." , true, false, removed)
end
def make_new_commit(message, date, commit_files, changed_files)
hash = Digest::SHA1.hexdigest(date.to_s + message)
@commits << Commit.new(commit_files, hash, message, date)
result = Result.new("#{message}\n\t#{changed_files} objects changed",
true, false, @commits.last)
end
def checkout(hash)
index_commit = @commits.index{|x| x.hash == hash}
if index_commit.nil?
Result.new("Commit #{hash} does not exist.", false, true)
else
@commits = @commits.take(index_commit + 1)
Result.new("HEAD is now at #{hash}.", true, false, @commits.last)
end
end
end
class BranchManager
attr_reader :current_branch, :branches
def initialize
@current_branch = Branch.new("master")
@branches = {"master": @current_branch}
@added_files = {}
@removed_files = {}
@changed_files = 0
end
def add(name, object)
@changed_files += 1 unless @added_files.has_key?(name)
@added_files[name] = object
message = "Added #{name} to stage."
Result.new(message, true, false, object)
end
def clean_files
@added_files = {}
- @removed_files = {}
+ @removed_files = []
@changed_files = 0
end
+ def remove_extra(name)
+ @removed_files << name
+ @changed_files += 1
+ end
+
def make_commit_files
if @current_branch.commits.empty?
data = @added_files
else
data = @current_branch.commits.last.commit_files.merge(@added_files)
end
- data.delete_if{|key, value| @removed_files.has_key?(key)}
+ data.delete_if{|key, value| @removed_files.member?(key)}
end
def commit(message, date)
if @changed_files == 0
return Result.new("Nothing to commit, working directory clean.",
false,
true)
end
result = @current_branch.make_new_commit(message,
date,
make_commit_files,
@changed_files)
clean_files
result
end
def remove_file(name)
has_commits = head.success?
if @added_files.has_key?(name)
removed = @added_files.delete(name)
- @changed_files += 1
+ remove_extra(name)
Result.new("Added #{name} for removal." , true, false, removed)
elsif has_commits and @current_branch.commits.last.commit_files.
has_key?(name)
- @changed_files += 1
+ remove_extra(name)
@current_branch.remove_file(name)
else
return Result.new("Object #{name} is not committed.", false, true)
end
end
def checkout_hash(hash)
@current_branch.checkout(hash)
end
def create(branch_name)
if @branches.has_key?(branch_name.to_sym)
Result.new("Branch #{branch_name} already exists.", false, true)
else
new_branch = Branch.new(branch_name, @current_branch.commits.clone)
@branches[branch_name.to_sym] = new_branch
Result.new("Created branch #{branch_name}.", true, false, new_branch)
end
end
def checkout(branch_name)
if @branches.has_key?(branch_name.to_sym)
@current_branch = @branches[branch_name.to_sym]
Result.new("Switched to branch #{branch_name}.",
true,
false,
@current_branch)
else
Result.new("Branch #{branch_name} does not exist.", false, true)
end
end
def remove(branch_name)
if not @branches.has_key?(branch_name.to_sym)
Result.new("Branch #{branch_name} does not exist.", false, true)
elsif @current_branch.name.to_sym == branch_name.to_sym
Result.new("Cannot remove current branch.", false, true)
else
removed_branch = @branches.delete(branch_name.to_sym)
Result.new("Removed branch #{branch_name}.",
true,
false,
removed_branch)
end
end
def list
names = @branches.keys.map(&:to_s).sort
result = names.reduce("") do |message, name|
if name == @current_branch.name
message += "\n* " + name
else
message += "\n " + name
end
end
Result.new(result[1..-1], true, false)
end
def log
if @current_branch.commits.empty?
mess = "Branch #{@current_branch.name} does not have any commits yet."
Result.new(mess, false, true)
else
message = @current_branch.commits.reverse.reduce("") do |mess, commit|
mess + "Commit #{commit.hash}\n" \
"Date: #{commit.date.strftime('%a %b %-d %H:%M %Y %z')}" \
"\n\n\t#{commit.message}" + "\n\n"
end
Result.new(message.strip, true, false)
end
end
def head
if @current_branch.commits.empty?
Result.new("Branch #{@current_branch.name}" \
" does not have any commits yet.", false, true)
else
last_commit = @current_branch.commits.last
Result.new(last_commit.message, true, false, last_commit)
end
end
def get(name)
result_mistake = Result.new("Object #{name} is not committed.",
false,
true)
if @current_branch.commits.empty?
return result_mistake
end
if @current_branch.commits.last.commit_files.has_key?(name)
object = @current_branch.commits.last.commit_files[name]
else
return result_mistake
end
Result.new("Found object #{name}.", true, false, object)
end
end
attr_reader :branch_manager
def initialize
@branch_manager = BranchManager.new
end
def add(name, object)
@branch_manager.add(name, object)
end
def commit(message)
date = Time.now #"%a %b %e %k:%M %Y %z"
@branch_manager.commit(message, date)
end
def remove(name)
@branch_manager.remove_file(name)
end
def checkout(hash)
@branch_manager.checkout_hash(hash)
end
def branch
@branch_manager
end
def log
@branch_manager.log
end
def head
@branch_manager.head
end
def get(name)
@branch_manager.get(name)
end
end
class << self
def init(&block)
repo = Repository.new
return repo if not block_given?
repo.instance_eval(&block)
repo
end
end
end

Десислава обнови решението на 23.11.2015 00:02 (преди над 8 години)

require 'time'
require 'digest/sha1'
class ObjectStore
class Result
attr_reader :message, :result
attr_writer :result
def initialize(message, success, error, result = nil)
@message = message
@success = success
@error = error
@result = result
end
def success?
@success
end
def error?
@error
end
end
class Repository
class Commit
attr_accessor :commit_files
attr_reader :message, :date, :hash
def initialize(files, hash, message, date)
@hash = hash
@commit_files = files
@message = message
@date = date
end
def objects
- @commit_files.map{|x| x.last}
+ @commit_files.values
end
end
class Branch
attr_accessor :added_files, :removed_files, :changed_files, :commits
attr_reader :name
def initialize(name, commits = [])
@name = name
@commits = commits
end
def remove_file(name)
removed = @commits.last.commit_files[name]
Result.new("Added #{name} for removal." , true, false, removed)
end
def make_new_commit(message, date, commit_files, changed_files)
hash = Digest::SHA1.hexdigest(date.to_s + message)
@commits << Commit.new(commit_files, hash, message, date)
result = Result.new("#{message}\n\t#{changed_files} objects changed",
true, false, @commits.last)
end
def checkout(hash)
index_commit = @commits.index{|x| x.hash == hash}
if index_commit.nil?
Result.new("Commit #{hash} does not exist.", false, true)
else
@commits = @commits.take(index_commit + 1)
Result.new("HEAD is now at #{hash}.", true, false, @commits.last)
end
end
end
class BranchManager
attr_reader :current_branch, :branches
def initialize
@current_branch = Branch.new("master")
@branches = {"master": @current_branch}
@added_files = {}
@removed_files = {}
@changed_files = 0
end
def add(name, object)
@changed_files += 1 unless @added_files.has_key?(name)
@added_files[name] = object
message = "Added #{name} to stage."
Result.new(message, true, false, object)
end
def clean_files
@added_files = {}
@removed_files = []
@changed_files = 0
end
def remove_extra(name)
@removed_files << name
@changed_files += 1
end
def make_commit_files
if @current_branch.commits.empty?
data = @added_files
else
data = @current_branch.commits.last.commit_files.merge(@added_files)
end
data.delete_if{|key, value| @removed_files.member?(key)}
end
def commit(message, date)
if @changed_files == 0
return Result.new("Nothing to commit, working directory clean.",
false,
true)
end
result = @current_branch.make_new_commit(message,
date,
make_commit_files,
@changed_files)
clean_files
result
end
def remove_file(name)
has_commits = head.success?
if @added_files.has_key?(name)
removed = @added_files.delete(name)
remove_extra(name)
Result.new("Added #{name} for removal." , true, false, removed)
elsif has_commits and @current_branch.commits.last.commit_files.
has_key?(name)
remove_extra(name)
@current_branch.remove_file(name)
else
return Result.new("Object #{name} is not committed.", false, true)
end
end
def checkout_hash(hash)
@current_branch.checkout(hash)
end
def create(branch_name)
if @branches.has_key?(branch_name.to_sym)
Result.new("Branch #{branch_name} already exists.", false, true)
else
new_branch = Branch.new(branch_name, @current_branch.commits.clone)
@branches[branch_name.to_sym] = new_branch
Result.new("Created branch #{branch_name}.", true, false, new_branch)
end
end
def checkout(branch_name)
if @branches.has_key?(branch_name.to_sym)
@current_branch = @branches[branch_name.to_sym]
Result.new("Switched to branch #{branch_name}.",
true,
false,
@current_branch)
else
Result.new("Branch #{branch_name} does not exist.", false, true)
end
end
def remove(branch_name)
if not @branches.has_key?(branch_name.to_sym)
Result.new("Branch #{branch_name} does not exist.", false, true)
elsif @current_branch.name.to_sym == branch_name.to_sym
Result.new("Cannot remove current branch.", false, true)
else
removed_branch = @branches.delete(branch_name.to_sym)
Result.new("Removed branch #{branch_name}.",
true,
false,
removed_branch)
end
end
def list
names = @branches.keys.map(&:to_s).sort
result = names.reduce("") do |message, name|
if name == @current_branch.name
message += "\n* " + name
else
message += "\n " + name
end
end
Result.new(result[1..-1], true, false)
end
def log
if @current_branch.commits.empty?
mess = "Branch #{@current_branch.name} does not have any commits yet."
Result.new(mess, false, true)
else
message = @current_branch.commits.reverse.reduce("") do |mess, commit|
mess + "Commit #{commit.hash}\n" \
"Date: #{commit.date.strftime('%a %b %-d %H:%M %Y %z')}" \
"\n\n\t#{commit.message}" + "\n\n"
end
Result.new(message.strip, true, false)
end
end
def head
if @current_branch.commits.empty?
Result.new("Branch #{@current_branch.name}" \
" does not have any commits yet.", false, true)
else
last_commit = @current_branch.commits.last
Result.new(last_commit.message, true, false, last_commit)
end
end
def get(name)
result_mistake = Result.new("Object #{name} is not committed.",
false,
true)
if @current_branch.commits.empty?
return result_mistake
end
if @current_branch.commits.last.commit_files.has_key?(name)
object = @current_branch.commits.last.commit_files[name]
else
return result_mistake
end
Result.new("Found object #{name}.", true, false, object)
end
end
attr_reader :branch_manager
def initialize
@branch_manager = BranchManager.new
end
def add(name, object)
@branch_manager.add(name, object)
end
def commit(message)
date = Time.now #"%a %b %e %k:%M %Y %z"
@branch_manager.commit(message, date)
end
def remove(name)
@branch_manager.remove_file(name)
end
def checkout(hash)
@branch_manager.checkout_hash(hash)
end
def branch
@branch_manager
end
def log
@branch_manager.log
end
def head
@branch_manager.head
end
def get(name)
@branch_manager.get(name)
end
end
class << self
def init(&block)
repo = Repository.new
return repo if not block_given?
repo.instance_eval(&block)
repo
end
end
end