2012-04-28 18:28:57 +01:00
|
|
|
class PullRequest < ActiveRecord::Base
|
2012-04-18 18:08:53 +01:00
|
|
|
extend StateMachine::MacroMethods # no method state_machine WTF?!
|
|
|
|
#TODO add validates to serialized data
|
2012-04-16 19:40:50 +01:00
|
|
|
|
2012-04-28 18:28:57 +01:00
|
|
|
belongs_to :issue, :autosave => true, :dependent => :destroy, :touch => true, :validate => true
|
|
|
|
belongs_to :base_project, :class_name => 'Project', :foreign_key => 'base_project_id'
|
|
|
|
belongs_to :head_project, :class_name => 'Project', :foreign_key => 'head_project_id'
|
2012-05-05 17:57:12 +01:00
|
|
|
delegate :user, :title, :body, :serial_id, :assignee, :state, :to => :issue, :allow_nil => true
|
2012-04-28 18:28:57 +01:00
|
|
|
accepts_nested_attributes_for :issue
|
|
|
|
#attr_accessible #FIXME disable for development
|
2012-05-16 17:50:30 +01:00
|
|
|
scope :needed_checking, where(:state => ['open', 'blocked', 'ready'])
|
2012-04-28 18:28:57 +01:00
|
|
|
|
2012-04-16 19:40:50 +01:00
|
|
|
state_machine :initial => :open do
|
2012-04-18 18:08:53 +01:00
|
|
|
#after_transition [:ready, :blocked] => [:merged, :closed] do |pull, transition|
|
|
|
|
# FileUtils.rm_rf(pull.path) # What about diff?
|
|
|
|
#end
|
2012-04-16 19:40:50 +01:00
|
|
|
|
2012-04-18 18:08:53 +01:00
|
|
|
event :ready do
|
|
|
|
transition [:open, :blocked] => :ready
|
2012-04-16 19:40:50 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
event :block do
|
2012-04-19 20:08:33 +01:00
|
|
|
transition [:open, :ready] => :blocked
|
2012-04-16 19:40:50 +01:00
|
|
|
end
|
|
|
|
|
2012-04-20 17:23:28 +01:00
|
|
|
event :already do
|
|
|
|
transition [:open, :blocked, :ready] => :already
|
|
|
|
end
|
|
|
|
|
2012-04-18 18:08:53 +01:00
|
|
|
event :merging do
|
|
|
|
transition :ready => :merged
|
2012-04-16 19:40:50 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
event :close do
|
2012-04-18 18:08:53 +01:00
|
|
|
transition [:open, :ready, :blocked] => :closed
|
|
|
|
end
|
|
|
|
|
|
|
|
event :reopen do
|
|
|
|
transition :closed => :open
|
2012-04-16 19:40:50 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-05-10 10:42:25 +01:00
|
|
|
def state=(value)
|
|
|
|
issue.state = value
|
|
|
|
end
|
|
|
|
|
2012-04-16 19:40:50 +01:00
|
|
|
def can_merge?
|
2012-04-18 18:08:53 +01:00
|
|
|
state == 'ready'
|
|
|
|
end
|
|
|
|
|
|
|
|
def check
|
2012-04-20 17:23:28 +01:00
|
|
|
ret = merge
|
|
|
|
if ret =~ /Already up-to-date/
|
|
|
|
already
|
2012-05-02 16:36:39 +01:00
|
|
|
elsif ret =~ /Merge made by the 'recursive' strategy/
|
2012-04-18 18:08:53 +01:00
|
|
|
system("cd #{path} && git reset --hard HEAD^") # remove merge commit
|
|
|
|
ready
|
2012-05-02 16:36:39 +01:00
|
|
|
elsif ret =~ /Automatic merge failed/
|
2012-04-18 18:08:53 +01:00
|
|
|
system("cd #{path} && git reset --hard HEAD")
|
|
|
|
block
|
2012-05-02 16:36:39 +01:00
|
|
|
else
|
2012-05-10 10:42:25 +01:00
|
|
|
raise ret
|
2012-04-18 18:08:53 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def merge!(who)
|
|
|
|
return false unless can_merge?
|
|
|
|
Dir.chdir(path) do
|
2012-04-20 16:17:43 +01:00
|
|
|
system "git config user.name \"#{who.uname}\" && git config user.email \"#{who.email}\""
|
2012-04-18 18:08:53 +01:00
|
|
|
if merge
|
|
|
|
merging
|
|
|
|
system("git push origin HEAD")
|
2012-05-17 17:47:36 +01:00
|
|
|
system("git reset --hard HEAD") # for diff maybe FIXME
|
2012-04-18 18:08:53 +01:00
|
|
|
end
|
|
|
|
end
|
2012-04-16 19:40:50 +01:00
|
|
|
end
|
|
|
|
|
2012-04-28 18:28:57 +01:00
|
|
|
def self.default_base_project(project)
|
|
|
|
project.is_root? ? project : project.root
|
|
|
|
end
|
|
|
|
|
|
|
|
def clean #FIXME move to protected
|
|
|
|
Dir.chdir(path) do
|
|
|
|
base_project.branches.each {|branch| system 'git', 'checkout', branch.name}
|
|
|
|
system 'git', 'checkout', base_ref
|
|
|
|
|
|
|
|
base_project.branches.each do |branch|
|
2012-05-12 17:23:39 +01:00
|
|
|
system 'git', 'branch', '-D', branch.name unless [base_ref, head_branch].include? branch.name
|
2012-04-28 18:28:57 +01:00
|
|
|
end
|
|
|
|
base_project.tags.each do |tag|
|
2012-05-12 17:23:39 +01:00
|
|
|
system 'git', 'tag', '-d', tag.name unless [base_ref, head_branch].include? tag.name
|
2012-04-28 18:28:57 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-04-16 19:40:50 +01:00
|
|
|
def path
|
2012-05-17 17:47:36 +01:00
|
|
|
filename = [id, base_ref, head_project.owner.uname, head_project.name, head_ref].compact.join('-')
|
2012-04-16 19:40:50 +01:00
|
|
|
if Rails.env == "production"
|
2012-05-17 17:47:36 +01:00
|
|
|
File.join('/srv/rosa_build/shared/tmp', "pull_requests", base_project.owner.uname, base_project.name, filename)
|
2012-04-16 19:40:50 +01:00
|
|
|
else
|
2012-05-17 17:47:36 +01:00
|
|
|
File.join(Rails.root, "tmp", Rails.env, "pull_requests", base_project.owner.uname, base_project.name, filename)
|
2012-04-16 19:40:50 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-05-12 17:23:39 +01:00
|
|
|
def head_branch
|
|
|
|
if base_project != head_project
|
|
|
|
"head_#{head_ref}"
|
|
|
|
else
|
|
|
|
head_ref
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-05-05 17:57:12 +01:00
|
|
|
protected
|
|
|
|
|
2012-04-16 19:40:50 +01:00
|
|
|
def merge
|
|
|
|
clone
|
2012-05-12 17:23:39 +01:00
|
|
|
%x(cd #{path} && git checkout #{base_ref} && git merge --no-ff #{head_branch}) #FIXME need sanitize branch name!
|
2012-04-16 19:40:50 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def clone
|
2012-04-18 18:08:53 +01:00
|
|
|
git = Grit::Git.new(path)
|
2012-04-16 19:40:50 +01:00
|
|
|
|
|
|
|
unless git.exist?
|
|
|
|
FileUtils.mkdir_p(path)
|
2012-04-28 18:28:57 +01:00
|
|
|
system("git clone --local --no-hardlinks #{base_project.path} #{path}")
|
|
|
|
if base_project != head_project
|
|
|
|
Dir.chdir(path) do
|
|
|
|
system 'git', 'remote', 'add', 'head', head_project.path
|
|
|
|
end
|
|
|
|
end
|
2012-04-19 20:08:33 +01:00
|
|
|
end
|
2012-04-28 18:28:57 +01:00
|
|
|
|
|
|
|
clean
|
2012-04-19 20:08:33 +01:00
|
|
|
Dir.chdir(path) do
|
2012-04-28 18:28:57 +01:00
|
|
|
system 'git', 'checkout', base_ref
|
|
|
|
system 'git', 'pull', 'origin', base_ref
|
|
|
|
if base_project == head_project
|
|
|
|
system 'git', 'checkout', head_ref
|
|
|
|
system 'git', 'pull', 'origin', head_ref
|
|
|
|
else
|
2012-05-12 17:23:39 +01:00
|
|
|
system 'git', 'fetch', 'head', "+#{head_ref}:#{head_branch}"
|
2012-04-16 19:40:50 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
# TODO catch errors
|
|
|
|
end
|
|
|
|
end
|