Skip to content
Open
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
39 changes: 39 additions & 0 deletions README.mkd
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,45 @@ credentials create" dialog is actually a convenience dialog in that it allows th
even suggesting a name for the deployment credential, with the eye to deployments that have a separate deploy key for each repository. Reusing a deploy key in
another credential is a simple matter of selecting the key from a drop-down menu.

## Additional Post-Receive Hooks

As of version 0.5.1x, this plugin supports the execution of additional
post-receive hooks in repositories managed with it. To get updated
about new data in the repository, the plugin installs a post-receive
hook. If you want additional post-receive hooks to be run, you have to
decide whether a hook should be a local or a global one. Local extra
hooks will only be run for the repository they are installed in.
Global extra hooks will be run for *every* gitolite repository.

To create local hooks, place them in a directory with the name
"post-receive.local.d" within the repository's hook directory. If a
file in this folder is marked as executable, the plugin's hook will
execute it.

In a standard gitolite install with a repository called "test", this
will be a valid path of an additional local post-receive hook:

/home/gitolite/repositories/test.git/hooks/post-receive.local.d/do-something

If the "do-something" file is executable, the plugin will pick it up.

To create global hooks, place an executable in a folder called
"post-receive.d" that lives in a hook directory of a gitolite
repository. All these "post-receive.d" directories are actually links
to one common "post-receive.d" directory within the gitolite
installation.

In a standard gitolite install with a repository called "test", this
will be a valid path of an additional global post-receive hook:

/home/gitolite/repositories/test.git/hooks/post-receive.d/do-something

Again, the "do-something" file needs to be executable, to be picked
up. All other repositories will have the "do-something" hook as well.

Note that all additional hooks get passed the same STDIN stream as the
plugin's hook got.

## Post-Receive URLs

As of version 0.4.6x, this plugin supports the inclusion of GitHub-style Post-Receive URLs. Once added, a post-receive URL will be notified when new changes
Expand Down
87 changes: 85 additions & 2 deletions contrib/hooks/post-receive.redmine_gitolite.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,72 @@ def run_query(url_str, params, with_https)
success
end

def get_extra_hooks()
# Get global extra hooks
global_extra_hooks = get_executables("hooks/post-receive.d")
if global_extra_hooks.length == 0
log("No global extra hooks found", true, true)
end
# Get local extra hooks
local_extra_hooks = get_executables("hooks/post-receive.local.d")
if local_extra_hooks.length == 0
log("No local extra hooks found", true, true)
end
# Join both results and return result
result = []
result.concat(global_extra_hooks)
result.concat(local_extra_hooks)
result
end

def get_executables(directory)
executables = Array.new
if File.directory?(directory)
log("Found folder: #{directory}", true, true)
Dir.foreach(directory) do |item|
next if item == '.' or item == '..'
# Use full relative path
path = "#{directory}/#{item}"
# Test if the file is executable
if File.executable?(path)
log("Found executable file: #{path}...", true, false)
# Remember it, if so
executables.push path
log("Added", true, true)
else
log("Found non-executable file: #{item}", true, true)
end
end
else
log("\n\nFolder not found: #{directory}", true, true)
end
executables
end

def call_extra_hooks(stdin, extra_hooks)
success = false
# Call each exectuble found with the parameters we got
log("Beginning to execute additional hooks", true, true)
extra_hooks.each do |extra_hook|
log("Executing extra hook '#{extra_hook}'")

output = ""
IO.popen("#{extra_hook}", "w+") do |pipe|
begin
pipe.puts stdin
pipe.close_write
rescue Errno::EPIPE
log("The hook #{extra_hook} does't expect data on STDIN", true, true)
end
output = pipe.read
end

log("#{output}")
log("Done", true, true)
end
success = true
success
end

rgh_vars = {}
rgh_var_names = [ "hooks.redmine_gitolite.key", "hooks.redmine_gitolite.url", "hooks.redmine_gitolite.projectid", "hooks.redmine_gitolite.repositoryid", "hooks.redmine_gitolite.debug", "hooks.redmine_gitolite.asynch"]
Expand All @@ -96,11 +160,14 @@ def run_query(url_str, params, with_https)
$debug = rgh_vars["debug"] == "true"


# Let's read the refs passed to us
# Let's read the refs passed to us, but also copy stdin
# for potential use with extra hooks.
refs = []
$<.each do |line|
stdin_copy = ""
$<.each do |line|
r = line.chomp.strip.split
refs.push( [ r[0].to_s, r[1].to_s, r[2].to_s ].join(",") )
stdin_copy = (stdin_copy == ""? "" : $/) + line
end
rgh_vars["refs[]"] = refs

Expand Down Expand Up @@ -132,4 +199,20 @@ def run_query(url_str, params, with_https)
end
log("\n\n", false, true)

extra_hooks = get_extra_hooks()
if extra_hooks.length > 0
log("Calling additional post-receive hooks...", true, true)
success = call_extra_hooks(stdin_copy, extra_hooks)
if(!success)
log("Error calling additional hooks.", false, true)
else
log("Success", true, true)
log("", true, true)
end
log("\n\n", false, true)
else
log("No extra hooks found that could be run additionally.", true, true)
log("\n\n", true, true)
end

exit
65 changes: 62 additions & 3 deletions lib/git_adapter_hooks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@
module GitHosting
class GitAdapterHooks

def self.check_hooks_installed
files_installed = check_hook_files_installed
dir_installed = check_hook_dir_installed
files_installed && dir_installed
end

@@check_hooks_installed_stamp = nil
@@check_hooks_installed_cached = nil
@@post_receive_hook_path = nil
def self.check_hooks_installed
def self.check_hook_files_installed
if not @@check_hooks_installed_cached.nil? and (Time.new - @@check_hooks_installed_stamp <= 0.5)
return @@check_hooks_installed_cached
end
Expand All @@ -31,7 +37,7 @@ def self.check_hooks_installed
@@check_hooks_installed_stamp = Time.new
@@check_hooks_installed_cached = true
rescue
logger.error "check_hooks_installed(): Problems installing hooks and initializing gitolite!"
logger.error "check_hook_files_installed(): Problems installing hooks and initializing gitolite!"
end
return @@check_hooks_installed_cached
else
Expand Down Expand Up @@ -59,7 +65,7 @@ def self.check_hooks_installed
logger.info "Finished installing hooks in the gitolite install..."
@@check_hooks_installed_cached = true
rescue
logger.error "check_hooks_installed(): Problems installing hooks and initializing gitolite!"
logger.error "check_hook_files_installed(): Problems installing hooks and initializing gitolite!"
end
end
@@check_hooks_installed_stamp = Time.new
Expand All @@ -68,6 +74,47 @@ def self.check_hooks_installed
end
end

@@check_hooks_dir_installed_cached = nil
@@check_hooks_dir_installed_stamp = nil
def self.check_hook_dir_installed
if not @@check_hooks_dir_installed_cached.nil? and (Time.new - @@check_hooks_dir_installed_stamp <= 0.5)
return @@check_hooks_dir_installed_cached
end

@@post_receive_hook_dir_path ||= File.join(gitolite_hooks_dir, 'post-receive.d')
post_receive_dir_exists = (%x[#{GitHosting.git_user_runner} test -r '#{@@post_receive_hook_dir_path}' && echo 'yes' || echo 'no']).match(/yes/)

if (!post_receive_dir_exists)
begin
logger.info "\"post-receive.d\" folder not yet created, installing it..."
install_hook_dir("post-receive.d")
logger.info "\"post-receive.d installed"
logger.info "Running \"gl-setup\" on the gitolite install..."
GitHosting.shell %[#{GitHosting.git_user_runner} gl-setup]
logger.info "Finished installing global hook directory in the gitolite install..."
@@check_hooks_dir_installed_stamp = Time.new
@@check_hooks_dir_installed_cached = true
rescue
logger.error "check_hook_dir_installed(): Problems installing hooks and initializing gitolite!"
end
return @@check_hooks_dir_installed_cached
else
error_msg = "Global \"post-receive.d\" directory is already present, will not touch it!"
logger.warn error_msg
@@check_hooks_dir_installed_cached = error_msg
begin
logger.info "Running \"gl-setup\" on the gitolite install..."
GitHosting.shell %[#{GitHosting.git_user_runner} gl-setup]
logger.info "Finished installing hook directory in the gitolite install..."
@@check_hooks_dir_installed_cached = true
rescue
logger.error "check_hook_dir_installed(): Problems installing hook directory and initializing gitolite!"
end
@@check_hooks_dir_installed_stamp = Time.new
return @@check_hooks_dir_installed_cached
end
end

def self.setup_hooks(projects=nil)
check_hooks_installed

Expand Down Expand Up @@ -145,6 +192,18 @@ def self.rgh_hook_digest(recreate=false)
@@cached_hook_digest
end

def self.install_hook_dir(hooks_dir)
begin
dest_dir = File.join(gitolite_hooks_dir, hooks_dir)
logger.info "Installing hook directory to #{dest_dir}"
GitHosting.shell %[#{GitHosting.git_user_runner} 'mkdir -p #{dest_dir}']
GitHosting.shell %[#{GitHosting.git_user_runner} 'chown #{git_user} #{dest_dir}']
GitHosting.shell %[#{GitHosting.git_user_runner} 'chmod 700 #{dest_dir}']
rescue
logger.error "install_hooks_dir(): Problems installing hook directory to #{dest_dir}"
end
end

def self.install_hook(hook_name)
begin
hook_source_path = File.join(package_hooks_dir, hook_name)
Expand Down