#!/usr/bin/env ruby -KU
ENV["PATH"] = "/usr/local/bin/:/opt/local/bin:#{ENV["PATH"]}"
ENV["RAILS_ENV"] ||= "production"
require File.dirname(__FILE__) + "/../config/environment"
abort("Usage: #{$0} repo_id") unless ARGV[0]
$stdout.sync = true
def create_repo_creation_events_for(project)
project.repository_clones.each do |repo|
puts "creating Repository clone event in #{project.slug}/#{repo.name}"
project.events.create({
:action => Action::CLONE_REPOSITORY,
:target => repo,
:user => repo.user,
:data => repo.parent_id,
:created_at => repo.created_at
})
end
end
def create_comment_events_for(repo, project)
repo.comments.each do |comment|
puts "creating Comment event on #{project.slug}/#{repo.name}"
project.events.create({
:action => Action::COMMENT,
:target => comment,
:user => comment.user,
:created_at => comment.created_at
})
end
end
def create_merge_request_events_for(repo, project)
repo.merge_requests.each do |mr|
puts "creating MergeRequest event on #{project.slug}/#{repo.name}"
project.events.create({
:action => Action::REQUEST_MERGE,
:target => mr,
:user => mr.user,
:created_at => mr.created_at,
})
unless mr.open?
puts "creating MergeRequest resolvement event on #{project.slug}/#{repo.name}"
project.events.create({
:action => Action::RESOLVE_MERGE_REQUEST,
:target => mr,
:user => mr.user,
:data => mr.status_string,
:created_at => mr.created_at,
})
end
end
end
def create_events_for_repository(repo, project)
tag_map = repo.git.tags.inject({}){|hsh, t| hsh[t.commit.id] = t.name;hsh}
parsed_commits = {} # Neccesary because of merge
repo.git.heads.each do |head|
users_commits = {}
Grit::Commit.find_all(repo.git, head.name, {:since => "1 year ago"}).each do |commit|
users_commits[commit.committer.email] ||= []
users_commits[commit.committer.email] << commit
end
users = User.find(:all, :conditions => ['email in (?)', users_commits.keys] )
users.each do |user|
commits = users_commits[user.email]
puts "\nindexing #{commits.size} commits for #{user.email} in #{project.slug}/#{repo.name}:#{head.name}"
commits.each_index do |i|
commit = commits[i]
previous_commit = commits[i-1]
newrev = commit.id
next if parsed_commits.has_key?(newrev)
parsed_commits[newrev] = true
oldrev = previous_commit.id if previous_commit
current_rev = newrev
newtype = oldtype = current_rev_type = "commit"
type = repo.git.git.name_rev({}, newrev).last.split("/").first
if type != "tags"
type = "heads"
end
action = :create
if !oldrev
action = :create
else
if commit.id =~ /^0+$/
action = :delete
else
action = :update
end
end
if action != :delete
newtype = repo.git.git.cat_file({:t => true}, newrev)
end
if action == :update
oldtype = repo.git.git.cat_file({:t => true}, oldrev)
end
if action == :delete
current_rev = oldrev
current_rev_type = oldtype
end
action_id = nil
ref = nil
if current_rev_type == "commit"
if type == "heads"
case action
when :create
action_id = Action::CREATE_BRANCH
ref = head.name
when :update
action_id = Action::COMMIT
ref = current_rev
when :delete
action_id = Action::DELETE_BRANCH
ref = head.name
end
elsif type == "tags"
if action == :create
action_id = Action::CREATE_TAG
ref = tag_map[commit.id]
elsif action == :delete
action_id = Action::DELETE_TAG
ref = tag_map[commit.id]
end
end
elsif current_rev_type == "tag"
if type == "tags"
if action == :create
action_id = Action::CREATE_TAG
ref = tag_map[commit.id]
elsif action == :delete
action_id = Action::DELETE_TAG
ref = tag_map[commit.id]
end
end
end
print "." if (i % 10 == 1)
#puts "#{current_rev_type}#{action.inspect} in #{project.slug}/#{repo.name}:#{head.name}: #{commit.short_message}"
project.events.create({
:action => action_id || Action::COMMIT,
:target => repo,
:user => user,
:body => commit.message,
:data => commit.id,
:created_at => commit.committed_date})
end
commits = nil
puts
end
users_commits = nil
end
parsed_commits = nil
end
def rebuild_project!(project)
puts "Destroying existing events on #{project.slug}"
project.events.destroy_all
project.repositories.each do |repo|
create_events_for_repository(repo, project)
create_comment_events_for(repo, project)
create_merge_request_events_for(repo, project)
end
create_repo_creation_events_for(project)
end
case ARGV[0]
when "all"
Project.find(:all).each do |project|
puts
puts "rebuilding #{project.slug}"
puts
begin
rebuild_project!(project)
GC.start
rescue
puts "!!! failed to rebuild #{project.slug} !!!"
puts "#{e.class}:#{e.message} \n#{e.backtrace.join("\n ")}"
puts
next
end
end
else
project = Project.find(ARGV[0])
rebuild_project!(project) if project
end