Permalink
Browse files

Merge branch 'post-receive-urls'

  • Loading branch information...
2 parents 1aec254 + 62bb4e7 commit ab914dc2252ac5eb95a25b240f4930663d3623cd @xdissent xdissent committed Jun 8, 2012
@@ -12,6 +12,92 @@ def stub
render(:code => 404)
end
+ # Returns an array of GitHub post-receive hook style hashes
+ # http://help.github.com/post-receive-hooks/
+ def post_receive_payloads(refs, project=nil)
+ project ||= @project
+ payloads = []
+ refs.each do |ref|
+ oldhead, newhead, refname = ref.split(',')
+
+ # Only pay attention to branch updates
+ next if not refname.match(/refs\/heads\//)
+ branch = refname.gsub('refs/heads/', '')
+
+ if newhead.match(/^0{40}$/)
+ # Deleting a branch
+ GitHosting.logger.debug "Deleting branch \"#{branch}\""
+ next
+ elsif oldhead.match(/^0{40}$/)
+ # Creating a branch
+ GitHosting.logger.debug "Creating branch \"#{branch}\""
+ range = newhead
+ else
+ range = "#{oldhead}..#{newhead}"
+ end
+
+ revisions_in_range = %x[#{GitHosting.git_exec} --git-dir='#{GitHosting.repository_path(project)}' rev-list --reverse #{range}]
+ #GitHosting.logger.debug "Revisions in Range: #{revisions.split().join(' ')}"
+
+ commits = []
+ revisions_in_range.split().each do |rev|
+ revision = project.repository.find_changeset_by_name(rev.strip)
+ commit = {
+ "id" => revision.revision,
+ "url" => url_for(:controller => "repositories", :action => "revision",
+ :id => project, :rev => rev, :only_path => false,
+ :host => Setting['host_name'], :protocol => Setting['protocol']
+ ),
+ "author" => {
+ "name" => revision.committer.gsub(/^([^<]+)\s+.*$/, '\1'),
+ "email" => revision.committer.gsub(/^.*<([^>]+)>.*$/, '\1')
+ },
+ "message" => revision.comments,
+ "timestamp" => revision.committed_on,
+ "added" => [],
+ "modified" => [],
+ "removed" => []
+ }
+ revision.changes.each do |change|
+ if change.action == "M"
+ commit["modified"] << change.path
+ elsif change.action == "A"
+ commit["added"] << change.path
+ elsif change.action == "D"
+ commit["removed"] << change.path
+ end
+ end
+ commits << commit
+ end
+
+ payloads << {
+ "before" => oldhead,
+ "after" => newhead,
+ "ref" => refname,
+ "commits" => commits,
+ "repository" => {
+ "description" => project.description,
+ "fork" => false,
+ "forks" => 0,
+ "homepage" => project.homepage,
+ "name" => project.identifier,
+ "open_issues" => project.issues.open.length,
+ "owner" => {
+ "name" => Setting["app_title"],
+ "email" => Setting["mail_from"]
+ },
+ "private" => !project.is_public,
+ "url" => url_for(:controller => "repositories", :action => "show",
+ :id => project, :only_path => false,
+ :host => Setting["host_name"], :protocol => Setting["protocol"]
+ ),
+ "watchers" => 0
+ }
+ }
+ end
+ payloads
+ end
+
def post_receive
if not @project.repository.extra.validate_encoded_time(params[:clear_time], params[:encoded_time])
@@ -47,46 +133,49 @@ def post_receive
output.flush
} if @project.repository_mirrors.any?
+ payloads = []
+ if @project.repository.extra.notify_cia == 1 or @project.repository_post_receive_urls.any?
+ payloads = post_receive_payloads(params[:refs])
+ end
+
+ # Post to each post-receive URL
+ @project.repository_post_receive_urls.all(:order => "active DESC, created_at ASC", :conditions => "active=1").each do |prurl|
+ msg = "Posting #{payloads.length} post-receive payloads to #{prurl.url} ... "
+ GitHosting.logger.debug msg
+ output.write msg
+ output.flush
+ uri = URI(prurl.url)
+ payloads.each do |payload|
+ if prurl.mode == :github
+ res = Net::HTTP.post_form(uri, {"payload" => payload})
+ else
+ res = Net::HTTP.get_response(uri)
+ end
+ output.write res.is_a?(Net::HTTPSuccess) ? "[success] " : "[failure] "
+ output.flush
+ end
+ output.write "done\n"
+ output.flush
+ end if @project.repository_post_receive_urls.any?
+
# Notify CIA
#Thread.abort_on_exception = true
- Thread.new(@project, params[:refs]) {|project, refs|
+ Thread.new(@project, payloads) {|project, payloads|
GitHosting.logger.debug "Notifying CIA"
output.write("Notifying CIA\n")
output.flush
- #GitHosting.logger.debug "REFS #{refs}"
-
- refs.each {|ref|
- oldhead, newhead, refname = ref.split(',')
- # Only pay attention to branch updates
- next if not refname.match(/refs\/heads\//)
-
- branch = refname.gsub('refs/heads/', '')
-
- if newhead.match(/^0{40}$/)
- # Deleting a branch
- GitHosting.logger.debug "Deleting branch \"#{branch}\""
- next
- elsif oldhead.match(/^0{40}$/)
- # Creating a branch
- GitHosting.logger.debug "Creating branch \"#{branch}\""
- range = newhead
- else
- range = "#{oldhead}..#{newhead}"
- end
-
- revisions = %x[#{GitHosting.git_exec} --git-dir='#{GitHosting.repository_path(@project)}' rev-list --reverse #{range}]
- #GitHosting.logger.debug "Revisions in Range: #{revisions.split().join(' ')}"
-
- revisions.split().each{|rev|
- revision = project.repository.find_changeset_by_name(rev.strip)
- #GitHosting.logger.debug "Revision Found: #{revision.revision}"
+ payloads.each do |payload|
+ branch = payload["ref"].gsub("refs/heads/", "")
+ payload["commits"].each do |commit|
+ revision = project.repository.find_changeset_by_name(commit["id"])
next if project.repository.cia_notifications.notified?(revision) # Already notified about this commit
GitHosting.logger.info "Notifying CIA: Branch => #{branch} REVISION => #{revision.revision}"
CiaNotificationMailer.deliver_notification(revision, branch)
project.repository.cia_notifications.notified(revision)
- }
- }
+ end
+ end
+
} if !params[:refs].nil? && @project.repository.extra.notify_cia==1
}, :layout => false
end
@@ -0,0 +1,143 @@
+class RepositoryPostReceiveUrlsController < ApplicationController
+ unloadable
+
+ before_filter :require_login
+ before_filter :set_user_variable
+ before_filter :set_project_variable
+ before_filter :check_required_permissions
+ before_filter :check_xhr_request
+ before_filter :find_repository_post_receive_url, :except => [:index, :create]
+
+ menu_item :settings, :only => :settings
+
+ layout Proc.new { |controller| controller.request.xhr? ? 'popup' : 'base' }
+
+ def index
+ render_404
+ end
+
+ def create
+ @prurl = RepositoryPostReceiveUrl.new(params[:repository_post_receive_urls])
+ if request.get?
+ # display create view
+ else
+ @prurl.update_attributes(params[:repository_post_receive_urls])
+ @prurl.project = @project
+
+ if @prurl.save
+ respond_to do |format|
+ format.html {
+ redirect_to(
+ url_for(
+ :controller => 'projects',
+ :action => 'settings',
+ :id => @prurl.project.identifier,
+ :tab => 'repository'
+ ),
+ :notice => l(:post_receive_url_notice_created)
+ )
+ }
+ end
+ else
+ respond_to do |format|
+ flash[:notice] = l(:post_receive_url_notice_create_failed)
+ end
+ end
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ respond_to do |format|
+ if @prurl.update_attributes(params[:repository_post_receive_urls])
+ format.html {
+ redirect_to(
+ url_for(
+ :controller => 'projects',
+ :action => 'settings',
+ :id => @prurl.project.identifier,
+ :tab => 'repository'
+ ),
+ :notice => l(:post_receive_url_notice_updated)
+ )
+ }
+ else
+ format.html { render :action => "edit" }
+ end
+ end
+
+
+ end
+
+ def destroy
+ if request.get?
+ # display confirmation view
+ else
+ if params[:confirm]
+ redirect_url = url_for(
+ :controller => 'projects',
+ :action => 'settings',
+ :id => @prurl.project.identifier,
+ :tab => 'repository'
+ )
+ @prurl.destroy
+ respond_to do |format|
+ format.html {redirect_to(redirect_url, :notice => l(:post_receive_url_notice_deleted))}
+ end
+ end
+ end
+ end
+
+ def settings
+ end
+
+ protected
+
+
+
+ def set_user_variable
+ @user = User.current
+ end
+
+ def set_project_variable
+ @project = Project.find(:first, :conditions => ["identifier = ?", params[:project_id]])
+ end
+
+ def find_repository_post_receive_url
+ prurl = RepositoryPostReceiveUrl.find_by_id(params[:id])
+
+ @prurls = @project.repository_post_receive_urls
+
+ if prurl and prurl.project == @project
+ @prurl = prurl
+ elsif prurl
+ render_403
+ else
+ render_404
+ end
+ end
+
+ def check_required_permissions
+ # Deny access if the curreent user is not allowed to manage the project's repositoy
+ if not @project.module_enabled?(:repository)
+ render_403
+ end
+ not_enough_perms = true
+ @user.roles_for_project(@project).each{|role|
+ if role.allowed_to? :manage_repository
+ not_enough_perms = false
+ break
+ end
+ }
+ if not_enough_perms
+ render_403
+ end
+ end
+
+ def check_xhr_request
+ @is_xhr ||= request.xhr?
+ end
+
+end
@@ -43,6 +43,16 @@ def self.can_edit_mirrors(project)
return User.current.allowed_to?(:edit_repository_mirrors, project)
end
+ def self.can_create_post_receive_urls(project)
+ return User.current.allowed_to?(:create_repository_post_receive_urls, project)
+ end
+ def self.can_view_post_receive_urls(project)
+ return User.current.allowed_to?(:view_repository_post_receive_urls, project)
+ end
+ def self.can_edit_post_receive_urls(project)
+ return User.current.allowed_to?(:edit_repository_post_receive_urls, project)
+ end
+
@@file_actions = {
"a" => "add",
"m" => "modify",
@@ -86,7 +86,11 @@ def update_repositories(object,*flags)
when User then projects = object.projects unless is_login_save?(object)
when GitolitePublicKey then projects = object.user.projects
when Member then projects.push(object.project)
- when Role then projects = object.members.map(&:project).flatten.uniq.compact
+ when Role
+ begin
+ projects = object.members.map(&:project).flatten.uniq.compact
+ rescue
+ end
end
if (projects.length > 0)
if (@@updating_active)
Oops, something went wrong.

0 comments on commit ab914dc

Please sign in to comment.