class GitRepo

Public Class Methods

new(dir) click to toggle source
# File lib/git-smart/git_repo.rb, line 7
  def initialize(dir)
    @dir = dir
    unless File.directory?(git_dir)
      raise GitSmart::RunFailed.new(
        <<-MSG.gsub(/^\s+/, '')
        You need to run this from within a Git directory.
        Current working directory: #{File.expand_path(dir)}
        Expected .git directory: #{git_dir}
        MSG
      )
    end
  end

Public Instance Methods

config(name) click to toggle source
# File lib/git-smart/git_repo.rb, line 159
def config(name)
  remote = git('config', name).chomp
  remote.empty? ? nil : remote
end
current_branch() click to toggle source
# File lib/git-smart/git_repo.rb, line 36
def current_branch
  head_file = File.join(git_dir, 'HEAD')
  File.read(head_file).strip.sub(%r(^.*refs/heads/), '')
end
dirty?() click to toggle source
# File lib/git-smart/git_repo.rb, line 101
def dirty?
  status.any? { |k,v| k != :untracked && v.any? }
end
exists?(ref) click to toggle source
# File lib/git-smart/git_repo.rb, line 70
def exists?(ref)
  git('rev-parse', ref)
  $?.success?
end
fast_forward!(upstream) click to toggle source
# File lib/git-smart/git_repo.rb, line 105
def fast_forward!(upstream)
  git!('merge', '--ff-only', upstream)
end
fetch!(remote) click to toggle source
# File lib/git-smart/git_repo.rb, line 62
def fetch!(remote)
  git!('fetch', remote)
end
git(*args) click to toggle source

helper methods, left public in case other commands want to use them directly

# File lib/git-smart/git_repo.rb, line 139
def git(*args)
  output = exec_git(*args)
  $?.success? ? output : ''
end
git!(*args) click to toggle source
# File lib/git-smart/git_repo.rb, line 144
def git!(*args)
  puts "Executing: #{['git', *args].join(" ")}"
  output = exec_git(*args)
  to_display = output.split("\n").map { |l| "  #{l}" }.join("\n")
  $?.success? ? puts(to_display) : raise(GitSmart::UnexpectedOutput.new(to_display))
  output
end
git_dir() click to toggle source
# File lib/git-smart/git_repo.rb, line 20
def git_dir
  gitdir = Pathname.new(@dir).join('.git')

  unless File.exists?(gitdir)
    @dir = git('rev-parse', '--show-toplevel').chomp
    gitdir = Pathname.new(@dir).join('.git') unless @dir.empty?
  end

  if File.file?(gitdir)
    submodule = YAML.load_file(gitdir)
    gitdir = Pathname.new(@dir).join(submodule['gitdir']).to_path
  end

  gitdir
end
git_shell(*args) click to toggle source
# File lib/git-smart/git_repo.rb, line 152
def git_shell(*args)
  puts "Executing: #{['git', *args].join(" ")}"
  Dir.chdir(@dir) {
    system('git', *args)
  }
end
last_commit_messages(nr) click to toggle source
# File lib/git-smart/git_repo.rb, line 125
def last_commit_messages(nr)
  read_log(nr).map(&:last)
end
log_to_shell(*args) click to toggle source
# File lib/git-smart/git_repo.rb, line 129
def log_to_shell(*args)
  git_shell('log', *args)
end
merge_base(ref_a, ref_b) click to toggle source
# File lib/git-smart/git_repo.rb, line 66
def merge_base(ref_a, ref_b)
  git('merge-base', ref_a, ref_b).chomp
end
merge_no_ff!(target) click to toggle source
# File lib/git-smart/git_repo.rb, line 133
def merge_no_ff!(target)
  git!('merge', '--no-ff', target)
end
raw_status() click to toggle source
# File lib/git-smart/git_repo.rb, line 79
def raw_status
  git('status', '-s')
end
read_log(nr) click to toggle source
# File lib/git-smart/git_repo.rb, line 121
def read_log(nr)
  git('log', '--oneline', '-n', nr.to_s).split("\n").map { |l| l.split(" ",2) }
end
rebase_preserving_merges!(upstream) click to toggle source
# File lib/git-smart/git_repo.rb, line 117
def rebase_preserving_merges!(upstream)
  git!('rebase', '--rebase-merges', upstream)
end
rev_list(ref_a, ref_b) click to toggle source
# File lib/git-smart/git_repo.rb, line 75
def rev_list(ref_a, ref_b)
  git('rev-list', "#{ref_a}..#{ref_b}").split("\n")
end
sha(ref) click to toggle source
# File lib/git-smart/git_repo.rb, line 41
def sha(ref)
  sha = git('rev-parse', ref).chomp
  sha.empty? ? nil : sha
end
stash!() click to toggle source
# File lib/git-smart/git_repo.rb, line 109
def stash!
  git!('stash')
end
stash_pop!() click to toggle source
# File lib/git-smart/git_repo.rb, line 113
def stash_pop!
  git!('stash', 'pop')
end
status() click to toggle source
# File lib/git-smart/git_repo.rb, line 83
def status
  raw_status.
    split("\n").
    map { |l| l.split(" ") }.
    group_by(&:first).
    map_values { |lines| lines.map(&:last) }.
    map_keys { |status|
      case status
        when /^[^ ]*M/; :modified
        when /^[^ ]*A/; :added
        when /^[^ ]*D/; :deleted
        when /^[^ ]*\?\?/; :untracked
        when /^[^ ]*UU/; :conflicted
        else raise GitSmart::UnexpectedOutput.new("Expected the output of git status to only have lines starting with A, M, D, UU, or ??. Got: \n#{raw_status}")
      end
    }
end
tracking_branch() click to toggle source
# File lib/git-smart/git_repo.rb, line 50
def tracking_branch
  key   = "branch.#{current_branch}.merge"
  value = config(key)
  if value.nil?
    value
  elsif value =~ /^refs\/heads\/(.*)$/
    $1
  else
    raise GitSmart::UnexpectedOutput.new("Expected the config of '#{key}' to be /refs/heads/branchname, got '#{value}'")
  end
end
tracking_remote() click to toggle source
# File lib/git-smart/git_repo.rb, line 46
def tracking_remote
  config("branch.#{current_branch}.remote")
end

Private Instance Methods

exec_git(*args) click to toggle source
# File lib/git-smart/git_repo.rb, line 166
def exec_git(*args)
  return if @dir.empty?
  Dir.chdir(@dir) {
    SafeShell.execute('git', *args)
  }
end