Class: GitHooks::Repository

Inherits:
Object show all
Extended by:
SystemUtils
Defined in:
lib/githooks/repository.rb,
lib/githooks/repository/file.rb,
lib/githooks/repository/config.rb,
lib/githooks/repository/limiter.rb,
lib/githooks/repository/diff_index_entry.rb

Defined Under Namespace

Classes: Config, DiffIndexEntry, File, Limiter

Constant Summary collapse

CHANGE_TYPE_SYMBOLS =
{
  added:     'A', copied:    'C',
  deleted:   'D', modified:  'M',
  renamed:   'R', retyped:   'T',
  unknown:   'U', unmerged:  'X',
  broken:    'B', untracked: '?',
  any:       '*', tracked:   '^'
}.freeze
CHANGE_TYPES =
CHANGE_TYPE_SYMBOLS.invert.freeze
DEFAULT_DIFF_INDEX_OPTIONS =
{ staged: true }
DiffIndexEntryDelegateClass =
DelegateClass(DiffIndexEntry)

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from SystemUtils

command, commands, find_bin, which, with_path

Constructor Details

#initialize(path = nil) ⇒ Repository

Returns a new instance of Repository.



48
49
50
51
52
# File 'lib/githooks/repository.rb', line 48

def initialize(path = nil)
  @path   = Pathname.new(get_root_path(path || Dir.getwd))
  @hooks  = Pathname.new(@path).join('.git', 'hooks')
  @config = Repository::Config.new(self)
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



46
47
48
# File 'lib/githooks/repository.rb', line 46

def config
  @config
end

#hooksObject (readonly)

Returns the value of attribute hooks.



46
47
48
# File 'lib/githooks/repository.rb', line 46

def hooks
  @hooks
end

#pathObject (readonly)

Returns the value of attribute path.



46
47
48
# File 'lib/githooks/repository.rb', line 46

def path
  @path
end

Instance Method Details

#branch_point_shaObject



152
153
154
155
156
157
158
159
160
161
162
# File 'lib/githooks/repository.rb', line 152

def branch_point_sha
  # Try to backtrack back to where we branched from, and use that as our
  # sha to compare against.

  # HACK: there's a better way but, it's too late and I'm too tired to
  # think of it right now.
  refs = 0.upto(100).to_a.collect { |x| "#{current_branch}~#{x}" }
  previous_branch = git('name-rev', '--name-only', *refs).
                    output_lines.find { |x| x.strip != current_branch }
  revision_sha(previous_branch) if previous_branch != current_branch
end

#current_branchObject



136
137
138
139
140
141
142
143
144
145
# File 'lib/githooks/repository.rb', line 136

def current_branch
  @branch ||= begin
    branch = git('symbolic-ref', '--short', '--quiet', 'HEAD').output.strip
    if branch.empty?
      hash = git('rev-parse', 'HEAD').output.strip
      branch = git('name-rev', '--name-only', hash).output.strip
    end
    branch
  end
end

#get_root_path(path) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/githooks/repository.rb', line 62

def get_root_path(path)
  git('rev-parse', '--show-toplevel', chdir: path).tap do |result|
    unless result.status.success? && result.output !~ /not a git repository/i
      fail Error::NotAGitRepo, "Unable to find a valid git repo in #{path}"
    end
  end.output.strip
end

#hooks_pathObject



58
59
60
# File 'lib/githooks/repository.rb', line 58

def hooks_path
  config['hooks-path']
end

#hooks_scriptObject



54
55
56
# File 'lib/githooks/repository.rb', line 54

def hooks_script
  config['script']
end

#last_unpushed_commit_parent_shaObject



164
165
166
167
168
169
# File 'lib/githooks/repository.rb', line 164

def last_unpushed_commit_parent_sha
  last_unpushed_sha = unpushed_commits.last
  revision_sha("#{last_unpushed_sha}~1") unless last_unpushed_sha.nil?
rescue Error::RemoteNotSet
  nil
end

#manifest(options = {}) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/githooks/repository.rb', line 78

def manifest(options = {})
  ref = options.delete(:ref)

  return staged_manifest(ref: ref) if options.delete(:staged)

  manifest_list = unstaged_manifest(ref: ref)

  tracked_manifest(ref: ref).each_with_object(manifest_list) do |file, list|
    list << file
  end if options.delete(:tracked)

  untracked_manifest(ref: ref).each_with_object(manifest_list) do |file, list|
    list << file
  end if options.delete(:untracked)

  manifest_list.sort
end

#remote_branchObject



147
148
149
150
# File 'lib/githooks/repository.rb', line 147

def remote_branch
  result = git('rev-parse', '--symbolic-full-name', '--abbrev-ref', "#{current_branch}@{u}")
  result.success? ? result.output.strip.split('/').last : nil
end

#revision_sha(revision) ⇒ Object



131
132
133
134
# File 'lib/githooks/repository.rb', line 131

def revision_sha(revision)
  return unless (result = git('rev-parse', revision)).status.success?
  result.output.strip
end

#staged_manifest(options = {}) ⇒ Object Also known as: commit_manifest



96
97
98
# File 'lib/githooks/repository.rb', line 96

def staged_manifest(options = {})
  diff_index(options.merge(staged: true))
end

#stashObject



70
71
72
# File 'lib/githooks/repository.rb', line 70

def stash
  git(*%w(stash -q --keep-index -a)).status.success?
end

#tracked_manifestObject



105
106
107
108
109
110
111
# File 'lib/githooks/repository.rb', line 105

def tracked_manifest(*)
  files = git('ls-files', '--exclude-standard').output.strip.split(/\s*\n\s*/)
  files.collect { |path|
    next unless self.path.join(path).file?
    DiffIndexEntry.from_file_path(self, path, true).to_repo_file
  }.compact
end

#unpushed_commitsObject



121
122
123
124
125
126
127
128
129
# File 'lib/githooks/repository.rb', line 121

def unpushed_commits
  unless remote_branch
    fail Error::RemoteNotSet, "No upstream remote configured for branch '#{current_branch}'"
  end

  git('log', '--format=%H', '@{upstream}..') do |result|
    fail(Error::CommandExecutionFailure, result.error) if result.failure?
  end.output.split(/\s*\n\s*/).collect(&:strip)
end

#unstaged_manifest(options = {}) ⇒ Object



101
102
103
# File 'lib/githooks/repository.rb', line 101

def unstaged_manifest(options = {})
  diff_index(options.merge(staged: false))
end

#unstashObject



74
75
76
# File 'lib/githooks/repository.rb', line 74

def unstash
  git(*%w(stash pop -q)).status.success?
end

#untracked_manifestObject



113
114
115
116
117
118
119
# File 'lib/githooks/repository.rb', line 113

def untracked_manifest(*)
  files = git('ls-files', '--others', '--exclude-standard').output.strip.split(/\s*\n\s*/)
  files.collect { |path|
    next unless self.path.join(path).file?
    DiffIndexEntry.from_file_path(self, path).to_repo_file
  }.compact
end