diff --git a/.gitignore b/.gitignore index f31b3e2..e51fad3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store *.swp +.project diff --git a/app/controllers/github_hook_controller.rb b/app/controllers/github_hook_controller.rb index 837e1e5..2d03aa0 100644 --- a/app/controllers/github_hook_controller.rb +++ b/app/controllers/github_hook_controller.rb @@ -8,7 +8,7 @@ def index repository = find_repository # Fetch the changes from Github - update_repository(repository) + Git.new.update_repository(repository) # Fetch the new changesets into Redmine repository.fetch_changesets @@ -18,42 +18,6 @@ def index private - # Executes shell command. Returns true if the shell command exits with a success status code - def exec(command) - logger.debug { "GithubHook: Executing command: '#{command}'" } - - # Get a path to a temp file - logfile = Tempfile.new('github_hook_exec') - logfile.close - - success = system("#{command} > #{logfile.path} 2>&1") - output_from_command = File.readlines(logfile.path) - if success - logger.debug { "GithubHook: Command output: #{output_from_command.inspect}"} -#p "GithubHook: Command output: #{output_from_command.inspect}" - else - logger.error { "GithubHook: Command '#{command}' didn't exit properly. Full output: #{output_from_command.inspect}"} -#p "GithubHook: Command '#{command}' didn't exit properly. Full output: #{output_from_command.inspect}" - end - - return success - ensure - logfile.unlink - end - - def git_command(command, repository) - "git --git-dir='#{repository.url}' #{command}" - end - - # Fetches updates from the remote repository - def update_repository(repository) - command = git_command('fetch origin', repository) - if exec(command) - command = git_command("fetch origin '+refs/heads/*:refs/heads/*'", repository) - exec(command) - end - end - # Gets the project identifier from the querystring parameters and if that's not supplied, assume # the Github repository name is the same as the project identifier. def get_identifier @@ -79,5 +43,4 @@ def find_repository raise TypeError, "Repository for project '#{project.to_s}' ('#{project.identifier}') is not a Git repository" unless repository.is_a?(Repository::Git) return repository end - end diff --git a/app/models/repository_observer.rb b/app/models/repository_observer.rb index eabf309..52c2550 100644 --- a/app/models/repository_observer.rb +++ b/app/models/repository_observer.rb @@ -1,64 +1,18 @@ class RepositoryObserver < ActiveRecord::Observer - #observe Repository -#p 'hi, observe Repository' def before_save(repository) - if Setting.plugin_redmine_github_hook[:enabled] && repository.type == 'Git' && repository.url.match('.*github.com') - base_dir_name = repository.url[/[\/][^\/]+.git/] - url = repository.url - #p 'basedir=', base_dir_name - git_dir = Setting.plugin_redmine_github_hook[:git_dir].to_s - git_dir = git_dir + base_dir_name - #git_dir = '/opt/data/git_repos' + base_dir_name #repository.project.identifier - if Dir[git_dir] == [] - cmd = 'git clone --bare ' + url + ' ' + git_dir - if exec(cmd) - cmd = git_command('remote add origin '+url, git_dir) - exec(cmd) - cmd = git_command('fetch -v', git_dir) - exec(cmd) - cmd = git_command('fetch origin', git_dir) - exec(cmd) - cmd = git_command('reset --soft refs/remotes/origin/master', git_dir) - exec(cmd) - repository.url = git_dir - else - return false - end - end - end - end #defined before_save -------------- + if Setting.plugin_redmine_github_hook[:enabled] && repository.type == 'Git' && repository.url.match('.*github.com') + respistory_name = repository.url[/[\/][^\/]+.git/] + repository_url = repository.url + git_dir = Setting.plugin_redmine_github_hook[:git_dir].to_s + repository = git_dir + respistory_name - private - def git_command(command, git_dir) - "git --git-dir='#{git_dir}' #{command}" - end - - # Executes shell command. Returns output from command if the shell command exits with a success status code - def exec(command) - #logger.debug { "Github: Executing command: '#{command}'" } - #p "Github: Executing command: '#{command}'" - - # Get a path to a temp file - #logfile = Tempfile.new('github__exec') - #logfile.close - - #success = system("#{command} > #{logfile.path} 2>&1") - #output_from_command = File.readlines(logfile.path) - #output_from_command = %x[command] - shell = Shell.new(command) - shell.run - success = (shell.exitstatus == 0) - output_from_command = shell.output - if success - #logger.debug { "Github: Command output: #{output_from_command.inspect}"} - #p "Github: Command output: #{output_from_command.inspect}" - return output_from_command - else - #logger.error { "Github: Command '#{command}' didn't exit properly. Full output: #{output_from_command.inspect}"} - p "Github: Command failed '#{command}' didn't exit properly. Full output: #{output_from_command.inspect}" - end - - #ensure - #logfile.unlink + if !File.exists?(repository) + if Git.new.mirror_repsitory(url, repository) + repository.url = repository + else + return false + end end + end + end end diff --git a/app/views/repositories/show.rhtml b/app/views/repositories/show.rhtml index 10b6fd7..016f645 100644 --- a/app/views/repositories/show.rhtml +++ b/app/views/repositories/show.rhtml @@ -1,49 +1,7 @@ <%= call_hook(:view_repositories_show_contextual, { :repository => @repository, :project => @project }) %> -<% - def git_command(command, repository) - "git --git-dir='#{repository.url}' #{command}" - end - - # Executes shell command. Returns output from command if the shell command exits with a success status code - def exec(command) - logger.debug { "Github: Executing command: '#{command}'" } - - # Get a path to a temp file - logfile = Tempfile.new('github__exec') - logfile.close - - success = system("#{command} > #{logfile.path} 2>&1") - output_from_command = File.readlines(logfile.path) - if success - logger.debug { "Github: Command output: #{output_from_command.inspect}"} -#p "Github: Command output: #{output_from_command.inspect}" - return output_from_command - else - logger.error { "Github: Command '#{command}' didn't exit properly. Full output: #{output_from_command.inspect}"} -#p "Github: Command '#{command}' didn't exit properly. Full output: #{output_from_command.inspect}" - end - - ensure - logfile.unlink - end - - url = @project.repository.url - - if Setting.plugin_redmine_github_hook[:enabled] && @project.repository.type == 'Git' - command = git_command('remote -v', @repository) - result = exec(command) - if result and result.is_a?(Array) and result.length == 2 - remote_name = result[0].split("\t")[0].strip - remote_url = result[0].split("\t")[1] - if remote_name == 'origin' - url = result[0].split("\t")[1].split(' ')[0] - end - end - end -%>
<% if @project.is_public or @project.users.include?(User.current) %> - <%= @project.repository.type %> URL: + <%= @project.repository.type %> URL: <% end %> <%= render :partial => 'navigation' %>
diff --git a/lib/git.rb b/lib/git.rb new file mode 100644 index 0000000..e16574a --- /dev/null +++ b/lib/git.rb @@ -0,0 +1,39 @@ +class Git + + # Mirror remote repository. + def mirror_repsitory(url, repository) + exec(git_command("clone --mirror #{url}", repository)) + end + + # Fetches updates from the remote repository + def update_repository(repository) + command = git_command('fetch origin', repository) + if exec(command) + command = git_command("fetch origin '+refs/heads/*:refs/heads/*'", repository) + exec(command) + end + end + + # Get remote url + def get_remote_url(repository) + exec(git_command("remote -v", repository)) + end + + private + + def git_command(command, git_dir) + "git --git-dir='#{git_dir}' #{command}" + end + + def exec(command) + shell = Shell.new(command) + shell.run + success = (shell.exitstatus == 0) + output_from_command = shell.output + if success + return output_from_command + else + p "Github: Command failed '#{command}' didn't exit properly. Full output: #{output_from_command.inspect}" + end + end +end diff --git a/lib/repository_patch.rb b/lib/repository_patch.rb new file mode 100644 index 0000000..ce8964c --- /dev/null +++ b/lib/repository_patch.rb @@ -0,0 +1,39 @@ +require_dependency 'repository' + +# Patches Redmine's Repository dynamically. +module RepositoryPatch + def self.included(base) # :nodoc: + base.extend(ClassMethods) + + base.send(:include, InstanceMethods) + + # Same as typing in the class + base.class_eval do + unloadable # Send unloadable so it will not be unloaded in development + end + + end + + module ClassMethods + + end + + module InstanceMethods + # Get the remote url from the repoisotory. + def remote_url + if Setting.plugin_redmine_github_hook[:enabled] and self.type == 'Git' + result = Git.new.get_remote_url(self) + if result and result.is_a?(Array) and result.length == 2 + remote_name = result[0].split("\t")[0].strip + remote_url = result[0].split("\t")[1] + if remote_name == 'origin' + result[0].split("\t")[1].split(' ')[0] + end + end + end + end + end +end + +# Add module to Repository +Respository.send(:include, RepositoryPatch) \ No newline at end of file