Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hooks #118

Closed
wants to merge 2 commits into from
Closed

Hooks #118

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion lib/grit/git.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,18 @@ def select_existing_objects(object_ids)

class << self
attr_accessor :git_timeout, :git_max_size

def git_binary
@git_binary ||=
ENV['PATH'].split(':').
map { |p| File.join(p, 'git') }.
find { |p| File.exist?(p) }
end
attr_writer :git_binary

def git_hook_whitelist
['pre-commit', 'post-commit']
end
end

self.git_timeout = 10
Expand Down Expand Up @@ -496,6 +501,31 @@ def transform_options(options)
end
args
end
end # Git

# Execute a hook
#
# name - The name of the hook as a String
#
# Returns false if the hook exits with a non-zero exitstatus, true in
# all other cases.
def execute_hook(name)
hooks = File.join(self.git_dir, 'hooks')
hook = File.join(hooks, name)

if Git.git_hook_whitelist.include?(name) && File.executable?(hook)
process = Child.new(hook, :chdir => self.work_tree,
:timeout => Grit::Git.git_timeout,
:max => Git.git_max_size)
status = process.status

Grit.log(process.out) if Grit.debug
Grit.log(process.err) if Grit.debug

status.exitstatus.zero?
else
true
end
end

end # Git
end # Grit
8 changes: 7 additions & 1 deletion lib/grit/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def read_tree(tree)
# message - The String commit message.
# options - An optional Hash of index options.
# :parents - Array of String commit SHA1s or Grit::Commit
# objects to attach this commit to to form a
# objects to attach this commit to to form a
# new head (default: nil).
# :actor - The Grit::Actor details of the user making
# the commit (default: nil).
Expand Down Expand Up @@ -102,6 +102,9 @@ def read_tree(tree)
# Returns a String of the SHA1 of the new commit.
def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master')
commit_tree_sha = nil

return false unless self.repo.execute_hook('pre-commit')

if parents.is_a?(Hash)
commit_tree_sha = parents[:commit_tree_sha]
actor = parents[:actor]
Expand Down Expand Up @@ -150,6 +153,9 @@ def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master'
commit_sha1 = self.repo.git.put_raw_object(contents, 'commit')

self.repo.update_ref(head, commit_sha1) if head

self.repo.execute_hook('post-commit')

commit_sha1
end

Expand Down
32 changes: 26 additions & 6 deletions lib/grit/repo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,31 @@ class Repo
# Public: The Grit::Git command line interface object.
attr_accessor :git

# Public: Boolean indicating whether git hooks should be executed
attr_reader :should_execute_hooks

# Public: Create a new Repo instance.
#
# path - The String path to either the root git directory or the bare
# git repo. Bare repos are expected to end with ".git".
# options - A Hash of options (default: {}):
# :is_bare - Boolean whether to consider the repo as bare even
# if the repo name does not end with ".git".
#
# options - A Hash of options (default: { :is_bare => false, :execute_hooks => true }):
# :is_bare - Boolean whether to consider the repo as bare even
# if the repo name does not end with ".git".
# :should_execute_hooks - Boolean indicating whether git hooks should be
# executed.
# Examples
#
# r = Repo.new("/Users/tom/dev/normal")
# r = Repo.new("/Users/tom/public/bare.git")
# r = Repo.new("/Users/tom/public/bare", {:is_bare => true})
# r = Repo.new("/Users/tom/public/bare", {:is_bare => true, :should_execute_hooks => false})
#
# Returns a newly initialized Grit::Repo.
# Raises Grit::InvalidGitRepositoryError if the path exists but is not
# a Git repository.
# Raises Grit::NoSuchPathError if the path does not exist.
def initialize(path, options = {})
epath = File.expand_path(path)
epath = File.expand_path(path)
@should_execute_hooks = options[:should_execute_hooks] || true

if File.exist?(File.join(epath, '.git'))
self.working_dir = epath
Expand Down Expand Up @@ -201,6 +206,21 @@ def description
self.git.fs_read('description').chomp
end

# If should_execute_hooks is true then the hook is executed (see
# [Git#execute_hooks]). Otherwise it returns true and executes nothing.
#
# name - The name of the hook as a String
#
# Returns true if the hook exits with a zero exitstatus, false in
# all other cases.
def execute_hook(name)
if self.should_execute_hooks
self.git.execute_hook(name)
else
true
end
end

def blame(file, commit = nil)
Blame.new(self, file, commit)
end
Expand Down