diff options
Diffstat (limited to 'app/models/merge_request.rb')
-rw-r--r-- | app/models/merge_request.rb | 98 |
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) |