class DTK::Client::GitAdapter
Constants
- GitErrorPattern
- TEMP_BRANCH
Attributes
git_repo[RW]
Public Class Methods
clone(repo_url, target_path, branch, opts={})
click to toggle source
# File lib/domain/git_adapter.rb, line 251 def self.clone(repo_url, target_path, branch, opts={}) git_base = handle_git_error{Git.clone(repo_url, target_path)} unless branch.nil? if opts[:track_remote_branch] # This just tracks remote branch begin git_base.checkout(branch) rescue => e # TODO: see if any other kind of error raise DtkError.new("The branch or tag '#{branch}' does not exist on repo '#{repo_url}'") end else # This wil first create a remote branch; # TODO: this might be wrong and should be deprecated git_base.branch(branch).checkout end end git_base end
new(repo_dir, local_branch_name = nil)
click to toggle source
# File lib/domain/git_adapter.rb, line 29 def initialize(repo_dir, local_branch_name = nil) if DTK::Configuration.get(:debug_grit) logger = Logger.new(STDOUT) logger.level = Logger::INFO @git_repo = Git.init(repo_dir, :log => logger) else @git_repo = Git.init(repo_dir) end # If we want to log GIT interaction # @git_repo = Git.init(repo_dir, :log => Logger.new(STDOUT)) @local_branch_name = local_branch_name end
Private Class Methods
error_msg_when_git_error(lines)
click to toggle source
# File lib/domain/git_adapter.rb, line 345 def self.error_msg_when_git_error(lines) ret = lines.last.gsub(GitErrorPattern,'').strip() # TODO start putting in special cases here if ret =~ /adding files failed/ if lines.first =~ /\.git/ ret = "Cannot add files that are in a .git directory; remove any nested .git directory" end end ret end
handle_git_error() { || ... }
click to toggle source
# File lib/domain/git_adapter.rb, line 326 def self.handle_git_error(&block) ret = nil begin ret = yield rescue => e unless e.respond_to?(:message) raise e else err_msg = e.message lines = err_msg.split("\n") if lines.last =~ GitErrorPattern err_msg = error_msg_when_git_error(lines) end raise DtkError.new(err_msg) end end ret end
Public Instance Methods
add_file(file_rel_path, content)
click to toggle source
# File lib/domain/git_adapter.rb, line 228 def add_file(file_rel_path, content) content ||= String.new file_path = "#{@git_repo.dir}/#{file_rel_path}" File.open(file_path,"w"){|f|f << content} @git_repo.add(file_path) end
add_remote(name, url)
click to toggle source
# File lib/domain/git_adapter.rb, line 135 def add_remote(name, url) @git_repo.remove_remote(name) if is_there_remote?(name) @git_repo.add_remote(name, url) end
changed?()
click to toggle source
# File lib/domain/git_adapter.rb, line 47 def changed? (!(changed().empty? && untracked().empty? && deleted().empty?) || staged_commits?) end
checkout(branch, opts = {})
click to toggle source
# File lib/domain/git_adapter.rb, line 214 def checkout(branch, opts = {}) @git_repo.checkout(branch, opts) end
command(*args, &block)
click to toggle source
# File lib/domain/git_adapter.rb, line 43 def command(*args, &block) @git_repo.lib.command(*args, &block) end
commit(commit_msg = "")
click to toggle source
# File lib/domain/git_adapter.rb, line 131 def commit(commit_msg = "") @git_repo.commit(commit_msg) end
current_branch()
click to toggle source
# File lib/domain/git_adapter.rb, line 297 def current_branch() @git_repo.branches.local.find { |b| b.current } end
delete_branch(branch, opts = {})
click to toggle source
# File lib/domain/git_adapter.rb, line 210 def delete_branch(branch, opts = {}) @git_repo.branch(branch).delete end
diff_remote_summary(local_branch, remote_reference)
click to toggle source
# File lib/domain/git_adapter.rb, line 97 def diff_remote_summary(local_branch, remote_reference) branch_local_obj = @git_repo.branches.local.find { |b| b.name == local_branch } branch_remote_obj = @git_repo.branches.remote.find{|r| "#{r.remote}/#{r.name}" == remote_reference } if branch_local_obj && branch_remote_obj difference = @git_repo.lib.diff_full(branch_remote_obj, branch_local_obj) # difference = @git_repo.diff(branch_remote_obj, branch_local_obj) { :diffs => difference } else raise Error.new("Error finding branches: local branch '#{local_branch}' (found: #{!branch_local_obj.nil?}), remote branch '#{remote_reference}' (found: #{!branch_remote_obj.nil?})") end end
diff_summary(local_branch, remote_reference)
click to toggle source
# File lib/domain/git_adapter.rb, line 79 def diff_summary(local_branch, remote_reference) branch_local_obj = @git_repo.branches.local.find { |b| b.name == local_branch } branch_remote_obj = @git_repo.branches.remote.find{|r| "#{r.remote}/#{r.name}" == remote_reference } if branch_local_obj && branch_remote_obj difference = @git_repo.diff(branch_local_obj, branch_remote_obj) files_modified = difference.stats[:files] ? difference.stats[:files].keys.collect { |file| { :path => file }} : [] { :files_modified => files_modified, :are_there_changes => !files_modified.empty? } else raise Error.new("Error finding branches: local branch '#{local_branch}' (found: #{!branch_local_obj.nil?}), remote branch '#{remote_reference}' (found: #{!branch_remote_obj.nil?})") end end
fetch(remote = 'origin')
click to toggle source
# File lib/domain/git_adapter.rb, line 141 def fetch(remote = 'origin') @git_repo.fetch(remote) end
find_remote_sha(ref)
click to toggle source
# File lib/domain/git_adapter.rb, line 163 def find_remote_sha(ref) remote = @git_repo.branches.remote.find{|r| "#{r.remote}/#{r.name}" == ref} remote.gcommit.sha end
head_commit_sha()
click to toggle source
# File lib/domain/git_adapter.rb, line 159 def head_commit_sha() ret_local_branch.gcommit.sha end
local_branch_name()
click to toggle source
# File lib/domain/git_adapter.rb, line 280 def local_branch_name ret_local_branch.name end
local_summary()
click to toggle source
# File lib/domain/git_adapter.rb, line 112 def local_summary() { :files_added => (untracked() + added()).collect { |file| { :path => file }}, :files_modified => changed().collect { |file| { :path => file }}, :files_deleted => deleted().collect { |file| { :path => file }}, :are_there_changes => something_changed? } end
merge(remote_branch_ref)
click to toggle source
# File lib/domain/git_adapter.rb, line 247 def merge(remote_branch_ref) @git_repo.merge(remote_branch_ref) end
merge_relationship(type, ref, opts={})
click to toggle source
# File lib/domain/git_adapter.rb, line 168 def merge_relationship(type, ref, opts={}) ref_remote, ref_branch = ref.split('/') # fetch remote branch fetch(ref_remote) if opts[:fetch_if_needed] git_reference = case type when :remote_branch @git_repo.branches.remote.find { |r| "#{r.remote}/#{r.name}" == ref } when :local_branch @git_repo.branches.find { |b| b.name == ref } else raise Error.new("Illegal type parameter (#{type}) passed to merge_relationship") end local_sha = ret_local_branch.gcommit.sha opts[:ret_commit_shas][:local_sha] = local_sha if opts[:ret_commit_shas] unless git_reference return :no_remote_ref if type.eql?(:remote_branch) raise Error.new("Cannot find git ref '#{ref}'") end git_reference_sha = git_reference.gcommit.sha opts[:ret_commit_shas][:other_sha] = git_reference_sha if opts[:ret_commit_shas] # shas can be different but content the same if git_reference_sha.eql?(local_sha) || !any_differences?(local_sha, git_reference_sha) :equal else if rev_list_contains?(local_sha, git_reference_sha) :local_ahead elsif rev_list_contains?(git_reference_sha, local_sha) :local_behind else :branchpoint end end end
merge_theirs(remote_branch_ref)
click to toggle source
# File lib/domain/git_adapter.rb, line 303 def merge_theirs(remote_branch_ref) branch = local_branch_name # Git is not agile enoguh to work with following commands so we are using native commands to achive this Dir.chdir(repo_dir) do OsUtil.suspend_output do puts `git checkout -b #{TEMP_BRANCH} #{remote_branch_ref}` puts `git merge #{branch} -s ours` puts `git checkout #{branch}` puts `git reset #{TEMP_BRANCH} --hard` puts `git branch -D #{TEMP_BRANCH}` end end end
new_version()
click to toggle source
# File lib/domain/git_adapter.rb, line 122 def new_version() return local_summary() end
print_status()
click to toggle source
# File lib/domain/git_adapter.rb, line 68 def print_status() changes = [changed(), untracked(), deleted()] puts "\nModified files:\n".colorize(:green) unless changes[0].empty? changes[0].each { |item| puts "\t#{item}" } puts "\nAdded files:\n".colorize(:yellow) unless changes[1].empty? changes[1].each { |item| puts "\t#{item}" } puts "\nDeleted files:\n".colorize(:red) unless changes[2].empty? changes[2].each { |item| puts "\t#{item}" } puts "" end
pull_remote_to_local(remote_branch, local_branch, remote='origin')
click to toggle source
# File lib/domain/git_adapter.rb, line 235 def pull_remote_to_local(remote_branch, local_branch, remote='origin') # special case; if no branches and local_branch differs from master # creates master plus local_branch # special_case must be calculated before pull special_case = current_branch().nil? and local_branch != 'master' @git_repo.pull(remote,"#{remote_branch}:#{local_branch}") if special_case @git_repo.branch(local_branch).checkout @git_repo.branch('master').delete end end
push(remote_branch_ref, opts={})
click to toggle source
# File lib/domain/git_adapter.rb, line 218 def push(remote_branch_ref, opts={}) remote, remote_branch = remote_branch_ref.split('/') push_with_remote(remote, remote_branch, opts) end
push_with_remote(remote, remote_branch, opts={})
click to toggle source
# File lib/domain/git_adapter.rb, line 223 def push_with_remote(remote, remote_branch, opts={}) branch_for_push = "#{local_branch_name}:refs/heads/#{remote_branch||local_branch_name}" @git_repo.push(remote, branch_for_push, opts) end
repo_dir()
click to toggle source
# File lib/domain/git_adapter.rb, line 272 def repo_dir @git_repo.dir.path end
repo_exists?()
click to toggle source
# File lib/domain/git_adapter.rb, line 276 def repo_exists? File.exists?(repo_dir) end
reset_hard(current_branch_sha)
click to toggle source
# File lib/domain/git_adapter.rb, line 318 def reset_hard(current_branch_sha) @git_repo.reset_hard(current_branch_sha) end
ret_local_branch()
click to toggle source
# File lib/domain/git_adapter.rb, line 284 def ret_local_branch # This build in assumption that just one local branch unless ret = current_branch() raise Error.new("Unexpected that current_branch() is nil") end if @local_branch_name unless ret.name == @local_branch_name raise Error.new("Unexpected that @local_branch_name (#{@local_branch_name}) does not equal current branch (#{current_branch()})") end end ret end
rev_list(commit_sha)
click to toggle source
# File lib/domain/git_adapter.rb, line 145 def rev_list(commit_sha) git_command('rev-list', commit_sha) end
rev_list_contains?(container_sha, index_sha)
click to toggle source
# File lib/domain/git_adapter.rb, line 154 def rev_list_contains?(container_sha, index_sha) results = rev_list(container_sha) !results.split("\n").grep(index_sha).empty? end
stage_and_commit(commit_msg = "")
click to toggle source
# File lib/domain/git_adapter.rb, line 126 def stage_and_commit(commit_msg = "") stage_changes() commit(commit_msg) end
stage_changes()
click to toggle source
# File lib/domain/git_adapter.rb, line 51 def stage_changes() handle_git_error do @git_repo.add(untracked()) @git_repo.add(added()) @git_repo.add(changed()) end deleted().each do |file| begin @git_repo.remove(file) rescue # ignore this error means file has already been staged # we cannot support status of file, in 1.8.7 so this is # solution for that end end end
staged_commits?()
click to toggle source
# File lib/domain/git_adapter.rb, line 149 def staged_commits?() response = git_command('diff','--cached') !response.empty? end
Private Instance Methods
added()
click to toggle source
# File lib/domain/git_adapter.rb, line 374 def added status.is_a?(Hash) ? status.added().keys : status.added().collect { |file| file.first } end
any_differences?(sha1, sha2)
click to toggle source
# File lib/domain/git_adapter.rb, line 390 def any_differences?(sha1, sha2) @git_repo.diff(sha1, sha2).size > 0 end
changed()
click to toggle source
Method bellow show different behavior when working with 1.8.7 so based on Hash response we know it it is: Hash => 1.9.3 + Array => 1.8.7
# File lib/domain/git_adapter.rb, line 362 def changed status.is_a?(Hash) ? status.changed().keys : status.changed().collect { |file| file.first } end
deleted()
click to toggle source
# File lib/domain/git_adapter.rb, line 370 def deleted status.is_a?(Hash) ? status.deleted().keys : status.deleted().collect { |file| file.first } end
git_command(cmd, opts=[])
click to toggle source
# File lib/domain/git_adapter.rb, line 394 def git_command(cmd, opts=[]) ENV['GIT_DIR'] = "#{@git_repo.dir.path}/.git" ENV['GIT_INDEX_FILE'] = @git_repo.index.path path = @git_repo.dir.path opts = [opts].flatten.join(' ') response = `git #{cmd} #{opts}`.chomp ENV.delete('GIT_DIR') ENV.delete('GIT_INDEX_FILE') return response end
handle_git_error(&block)
click to toggle source
# File lib/domain/git_adapter.rb, line 323 def handle_git_error(&block) self.class.handle_git_error(&block) end
is_there_remote?(remote_name)
click to toggle source
# File lib/domain/git_adapter.rb, line 386 def is_there_remote?(remote_name) @git_repo.remotes.find { |r| r.name == remote_name } end
something_changed?()
click to toggle source
# File lib/domain/git_adapter.rb, line 378 def something_changed? ![changed, untracked, deleted, added].flatten.empty? end
status()
click to toggle source
# File lib/domain/git_adapter.rb, line 382 def status @git_repo.status end
untracked()
click to toggle source
# File lib/domain/git_adapter.rb, line 366 def untracked status.is_a?(Hash) ? status.untracked().keys : status.untracked().collect { |file| file.first } end