Николай обнови решението на 18.11.2015 10:20 (преди около 9 години)
+class Message
+ def initialize(message, success)
+ @message = message
+ @success = success
+ end
+
+ def message
+ @message
+ end
+
+ def success?
+ @success
+ end
+
+ def error?
+ ! @success
+ end
+end
+
+class AddMessage < Message
+ def initialize(message, *result)
+ @message = message
+ @success = true
+ @result = result[0]
+ end
+
+ def message
+ "Added #{@message} to stage."
+ end
+
+ def result
+ return @result if @success
+ end
+end
+
+class CommitMessage < Message
+ def initialize(message, success, changed_objects)
+ @message = message
+ @success = success
+ @changed_objects = changed_objects
+ end
+
+ def message
+ if @success
+ "#{@message}\n#{@changed_objects} objects changed"
+ else
+ "Nothing to commit, working directory clean."
+ end
+ end
+end
+
+class RemoveMessage < Message
+ def message
+ if @success
+ "Added #{@message} for removal."
+ else
+ "Object #{@message} is not commited."
+ end
+ end
+end
+
+class CheckoutMessage < Message
+ def initialize(message, success, *result)
+ @message = message
+ @success = success
+ @result = result[0]
+ end
+
+ def message
+ if @success
+ "HEAD is now at #{@message}."
+ else
+ "Commit #{@message} does not exist."
+ end
+ end
+
+ def result
+ return @result if @success
+ end
+end
+
+class LogMessage < Message
+ def initialize(branch_name, success, commits)
+ @branch_name = branch_name
+ @success = success
+ @commits = commits
+ end
+
+ def message
+ if @success
+ string = ""
+ @commits.each{ |commit| string += information(commit) }
+ string
+ else
+ "Branch #{@branch_name} does not have any commits yet."
+ end
+ end
+
+ def information(commit)
+ log = "Commit #{commit.commit_hash} \n"\
+ "Date: #{commit.date}"\
+ "\n\t #{commit.message}\n"
+ end
+end
+
+class CreateMessage < Message
+ def message
+ if @success
+ "Created branch #{@message}."
+ else
+ "Branch #{@message} already exists."
+ end
+ end
+end
+
+class BranchCheckoutMessage < Message
+ def message
+ if @success
+ "Switched to #{@message}."
+ else
+ "Branch #{@message} does not exists."
+ end
+ end
+end
+
+class BranchRemoveMessage < Message
+ def initialize(branch_name, success, *current)
+ @branch_name = branch_name
+ @success = success
+ @current = current[0]
+ end
+
+ def message
+ if @success
+ "Removed branch #{@branch_name}."
+ else
+ if @current
+ "Cannot remove current branch."
+ else
+ "Branch #{@branch_name} does not exist."
+ end
+ end
+ end
+end
+
+class BranchListMessage < Message
+
+end
+
+class ObjectElement
+ attr_accessor :name
+ attr_accessor :info
+
+ def initialize(name, info)
+ @name = name
+ @info = info
+ end
+
+ def == (other)
+ if @name == other
+ true
+ else
+ false
+ end
+ end
+end
+
+class Commit
+ require 'digest/sha1'
+
+ attr_accessor :commit_hash
+ attr_accessor :message
+ attr_accessor :date
+ attr_accessor :repo_state
+
+ def initialize(message, repo_state)
+ @message = message
+ @repo_state = repo_state
+ @date = Time.now.asctime
+ @commit_hash = Digest::SHA1.hexdigest (@date + @message)
+ end
+
+ def include?(object_name)
+ repo_state.each { |object| return true if object == object_name }
+ false
+ end
+end
+
+class ObjectStore
+ attr_accessor :branch
+ attr_accessor :commit_store
+ attr_accessor :head
+ attr_accessor :working_commit
+ attr_accessor :changes
+
+ def initialize
+ @working_commit = []
+ @commit_store = []
+ @changes = 0
+ @branch = BranchController.new(@commit_store)
+ end
+
+ def self.init
+ repo = ObjectStore.new
+ if block_given?
+ repo.instance_eval do
+ yield
+ end
+ end
+ repo
+ end
+
+ def add(name, object)
+ @working_commit.push(ObjectElement.new(name , object))
+ @changes += 1
+ AddMessage.new(name, object)
+ end
+
+ def commit(message)
+ return CommitMessage.new(message, false, 0) if @changes == 0
+ @commit_store.push(Commit.new(message, @working_commit.dup))
+ @head = @commit_store.last
+ m = CommitMessage.new(message, true, @changes)
+ @changes = 0
+ m
+ end
+
+ def remove(name)
+ for_remove = @working_commit.select{ |x| x if x == name}
+ if for_remove[0] != nil
+ @working_commit.delete(for_remove[0])
+ @changes += 1
+ RemoveMessage.new(name, true)
+ else
+ RemoveMessage.new(name, false)
+ end
+ end
+
+ def checkout(commit_hash)
+ @commit_store.each do |commit|
+ message = CheckoutMessage.new(commit_hash, true, commit)
+ @working_commit = commit.repo_state
+ changes += 1
+ @head = commit
+ return message if commit.commit_hash == commit_hash
+ end
+ CheckoutMessage.new(commit_hash, false)
+ end
+
+ def log
+ unless @commit_store.empty?
+ LogMessage.new(branch.name, true, @commit_store)
+ else
+ LogMessage.new(branch.name, false, @commit_store)
+ end
+ end
+
+end
+
+class BranchController
+ attr_accessor :branches
+ attr_accessor :active_branch
+ attr_accessor :active_repo
+ def initialize(repo_state)
+ @branches = []
+ @branches.push(Branch.new("master", repo_state.dup))
+ @active_branch = @branches[0]
+ @active_repo = repo_state
+ end
+
+ def name
+ @active_branch.name
+ end
+
+ def create(branch_name)
+ message = CreateMessage.new(branch_name, false)
+ return message if @branches.any?{ |branch| branch.name == branch_name }
+ @branches.push(Branch.new(branch_name, active_repo.dup))
+ CreateMessage.new(branch_name, true)
+ end
+
+ def remove(branch_name)
+ if @active_branch.name == branch_name
+ BranchRemoveMessage.new(branch_name, false, true)
+ elsif @branches.any?{ |branch| branch.name == branch_name }
+ selected = @branches.select{ |branch| branch.name == branch_name }
+ @branches.delete(selected[0])
+ BranchRemoveMessage.new(branch_name, true)
+ else
+ BranchRemoveMessage.new(branch_name, false, false)
+ end
+ end
+
+ def list
+ names = []
+ @branches.each{ |branch| names.push(branch.name) }
+ names.each{ |name| name << "\n" }
+ names.sort!
+ names[names.index(active_branch.name)] = "* " + active_branch.name
+ BranchListMessage.new(names.join, true)
+ end
+
+ def checkout(branch_name)
+ message = BranchCheckoutMessage.new(branch_name, false)
+ selected = @branches.select{|branch| branch.name == branch_name}
+ if selected[0] == nil
+ BranchCheckoutMessage.new(branch_name, false)
+ else
+ @active_branch.repo_state = @active_repo.dup
+ @active_branch = selected[0]
+ @active_repo.replace(selected[0].repo_state)
+ BranchCheckoutMessage.new(branch_name, true)
+ end
+ end
+end
+
+class Branch
+ attr_accessor :name
+ attr_accessor :repo_state
+ def initialize(name, repo_state)
+ @name = name
+ @repo_state = repo_state
+ end
+end