Class: GitRepo

Inherits:
Object show all
Defined in:
lib/git-smart/git_repo.rb

Instance Method Summary collapse

Constructor Details

#initialize(dir) ⇒ GitRepo

Returns a new instance of GitRepo.



7
8
9
10
11
12
13
14
15
16
17
18
# 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

Instance Method Details

#config(name) ⇒ Object



159
160
161
162
# File 'lib/git-smart/git_repo.rb', line 159

def config(name)
  remote = git('config', name).chomp
  remote.empty? ? nil : remote
end

#current_branchObject



36
37
38
39
# 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?Boolean

Returns:

  • (Boolean)


101
102
103
# File 'lib/git-smart/git_repo.rb', line 101

def dirty?
  status.any? { |k,v| k != :untracked && v.any? }
end

#exists?(ref) ⇒ Boolean

Returns:

  • (Boolean)


70
71
72
73
# File 'lib/git-smart/git_repo.rb', line 70

def exists?(ref)
  git('rev-parse', ref)
  $?.success?
end

#fast_forward!(upstream) ⇒ Object



105
106
107
# File 'lib/git-smart/git_repo.rb', line 105

def fast_forward!(upstream)
  git!('merge', '--ff-only', upstream)
end

#fetch!(remote) ⇒ Object



62
63
64
# File 'lib/git-smart/git_repo.rb', line 62

def fetch!(remote)
  git!('fetch', remote)
end

#git(*args) ⇒ Object

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



139
140
141
142
# File 'lib/git-smart/git_repo.rb', line 139

def git(*args)
  output = exec_git(*args)
  $?.success? ? output : ''
end

#git!(*args) ⇒ Object



144
145
146
147
148
149
150
# 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_dirObject



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 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) ⇒ Object



152
153
154
155
156
157
# 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) ⇒ Object



125
126
127
# File 'lib/git-smart/git_repo.rb', line 125

def last_commit_messages(nr)
  read_log(nr).map(&:last)
end

#log_to_shell(*args) ⇒ Object



129
130
131
# 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) ⇒ Object



66
67
68
# 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) ⇒ Object



133
134
135
# File 'lib/git-smart/git_repo.rb', line 133

def merge_no_ff!(target)
  git!('merge', '--no-ff', target)
end

#raw_statusObject



79
80
81
# File 'lib/git-smart/git_repo.rb', line 79

def raw_status
  git('status', '-s')
end

#read_log(nr) ⇒ Object



121
122
123
# 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) ⇒ Object



117
118
119
# File 'lib/git-smart/git_repo.rb', line 117

def rebase_preserving_merges!(upstream)
  git!('rebase', '-p', upstream)
end

#rev_list(ref_a, ref_b) ⇒ Object



75
76
77
# 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) ⇒ Object



41
42
43
44
# File 'lib/git-smart/git_repo.rb', line 41

def sha(ref)
  sha = git('rev-parse', ref).chomp
  sha.empty? ? nil : sha
end

#stash!Object



109
110
111
# File 'lib/git-smart/git_repo.rb', line 109

def stash!
  git!('stash')
end

#stash_pop!Object



113
114
115
# File 'lib/git-smart/git_repo.rb', line 113

def stash_pop!
  git!('stash', 'pop')
end

#statusObject



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# 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_branchObject



50
51
52
53
54
55
56
57
58
59
60
# 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_remoteObject



46
47
48
# File 'lib/git-smart/git_repo.rb', line 46

def tracking_remote
  config("branch.#{current_branch}.remote")
end