summaryrefslogtreecommitdiff
path: root/app/models/merge_request.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/merge_request.rb')
-rw-r--r--app/models/merge_request.rb98
1 files changed, 66 insertions, 32 deletions
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 2a476355404..703032649b9 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -2,30 +2,35 @@
#
# Table name: merge_requests
#
-# id :integer not null, primary key
-# target_branch :string(255) not null
-# source_branch :string(255) not null
-# project_id :integer not null
-# author_id :integer
-# assignee_id :integer
-# title :string(255)
-# created_at :datetime
-# updated_at :datetime
-# st_commits :text(2147483647)
-# st_diffs :text(2147483647)
-# milestone_id :integer
-# state :string(255)
-# merge_status :string(255)
+# id :integer not null, primary key
+# target_project_id :integer not null
+# target_branch :string(255) not null
+# source_project_id :integer not null
+# source_branch :string(255) not null
+# author_id :integer
+# assignee_id :integer
+# title :string(255)
+# created_at :datetime
+# updated_at :datetime
+# st_commits :text(2147483647)
+# st_diffs :text(2147483647)
+# milestone_id :integer
+# state :string(255)
+# merge_status :string(255)
#
require Rails.root.join("app/models/commit")
require Rails.root.join("lib/static_model")
class MergeRequest < ActiveRecord::Base
+
include Issuable
- attr_accessible :title, :assignee_id, :target_branch, :source_branch, :milestone_id,
- :author_id_of_changes, :state_event
+ belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project"
+ belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project"
+
+ attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :author_id_of_changes, :state_event
+
attr_accessor :should_remove_source_branch
@@ -74,30 +79,37 @@ class MergeRequest < ActiveRecord::Base
serialize :st_commits
serialize :st_diffs
+ validates :source_project, presence: true
validates :source_branch, presence: true
+ validates :target_project, presence: true
validates :target_branch, presence: true
- validate :validate_branches
+ validate :validate_branches
+ scope :of_group, ->(group) { where("source_project_id in (:group_project_ids) OR target_project_id in (:group_project_ids)", group_project_ids: group.project_ids) }
+ scope :of_user_team, ->(team) { where("(source_project_id in (:team_project_ids) OR target_project_id in (:team_project_ids) AND assignee_id in (:team_member_ids))", team_project_ids: team.project_ids, team_member_ids: team.member_ids) }
+ scope :opened, -> { with_state(:opened) }
+ scope :closed, -> { with_state(:closed) }
scope :merged, -> { with_state(:merged) }
- scope :by_branch, ->(branch_name) { where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name) }
+ scope :by_branch, ->(branch_name) { where("(source_branch LIKE :branch) OR (target_branch LIKE :branch)", branch: branch_name) }
scope :cared, ->(user) { where('assignee_id = :user OR author_id = :user', user: user.id) }
scope :by_milestone, ->(milestone) { where(milestone_id: milestone) }
-
+ scope :by_project, ->(project_id) { where("source_project_id = :project_id OR target_project_id = :project_id", project_id: project_id) }
+ scope :in_projects, ->(project_ids) { where("source_project_id in (:project_ids) OR target_project_id in (:project_ids)", project_ids: project_ids) }
# Closed scope for merge request should return
# both merged and closed mr's
scope :closed, -> { with_states(:closed, :merged) }
def validate_branches
- if target_branch == source_branch
- errors.add :branch_conflict, "You can not use same branch for source and target branches"
+ if target_project==source_project && target_branch == source_branch
+ errors.add :branch_conflict, "You can not use same project/branch for source and target"
end
if opened? || reopened?
- similar_mrs = self.project.merge_requests.where(source_branch: source_branch, target_branch: target_branch).opened
+ similar_mrs = self.target_project.merge_requests.where(source_branch: source_branch, target_branch: target_branch, source_project_id: source_project.id).opened
similar_mrs = similar_mrs.where('id not in (?)', self.id) if self.id
if similar_mrs.any?
- errors.add :base, "There is already an open merge request for this branches"
+ errors.add :base, "Cannot Create: This merge request already exists: #{similar_mrs.pluck(:title)}"
end
end
end
@@ -137,7 +149,13 @@ class MergeRequest < ActiveRecord::Base
end
def unmerged_diffs
- project.repository.diffs_between(source_branch, target_branch)
+ if for_fork?
+ diffs = Gitlab::Satellite::MergeAction.new(author, self).diffs_between_satellite
+ else
+ diffs = target_project.repository.diffs_between(source_branch, target_branch)
+ end
+ diffs ||= []
+ diffs
end
def last_commit
@@ -145,11 +163,11 @@ class MergeRequest < ActiveRecord::Base
end
def merge_event
- self.project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last
+ self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last
end
def closed_event
- self.project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last
+ self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last
end
def commits
@@ -165,15 +183,23 @@ class MergeRequest < ActiveRecord::Base
if opened? && unmerged_commits.any?
self.st_commits = dump_commits(unmerged_commits)
save
+
end
commits
end
def unmerged_commits
- self.project.repository.
- commits_between(self.target_branch, self.source_branch).
+ if for_fork?
+ commits = Gitlab::Satellite::MergeAction.new(self.author, self).commits_between
+ else
+ commits = target_project.repository.commits_between(self.target_branch, self.source_branch)
+ end
+ if commits.present?
+ commits = Commit.decorate(commits).
sort_by(&:created_at).
reverse
+ end
+ commits
end
def merge!(user_id)
@@ -199,21 +225,29 @@ class MergeRequest < ActiveRecord::Base
# Returns the raw diff for this merge request
#
# see "git diff"
- def to_diff
- project.repo.git.native(:diff, {timeout: 30, raise: true}, "#{target_branch}...#{source_branch}")
+ def to_diff(current_user)
+ Gitlab::Satellite::MergeAction.new(current_user, self).diff_in_satellite
end
# Returns the commit as a series of email patches.
#
# see "git format-patch"
- def to_patch
- project.repo.git.format_patch({timeout: 30, raise: true, stdout: true}, "#{target_branch}..#{source_branch}")
+ def to_patch(current_user)
+ Gitlab::Satellite::MergeAction.new(current_user, self).format_patch
end
def last_commit_short_sha
@last_commit_short_sha ||= last_commit.sha[0..10]
end
+ def for_fork?
+ target_project != source_project
+ end
+
+ def disallow_source_branch_removal?
+ (source_project.root_ref? source_branch) || for_fork?
+ end
+
private
def dump_commits(commits)