diff options
author | Izaak Alpert <ihalpert@blackberry.com> | 2013-04-25 18:15:33 +0400 |
---|---|---|
committer | Izaak Alpert <ialpert@blackberry.com> | 2013-07-18 06:41:30 +0400 |
commit | 3d7194f0112da12e8732df9ffe8b34fe7d0a9f6b (patch) | |
tree | 9b3c68c04b5ead5e35456595a07453b036b2dbc8 /app | |
parent | fd033671933fcc0f472480d98c907aefde357416 (diff) |
Merge Request on forked projects
The good:
- You can do a merge request for a forked commit and it will merge properly (i.e. it does work).
- Push events take into account merge requests on forked projects
- Tests around merge_actions now present, spinach, and other rspec tests
- Satellites now clean themselves up rather then recreate
The questionable:
- Events only know about target projects
- Project's merge requests only hold on to MR's where they are the target
- All operations performed in the satellite
The bad:
- Duplication between project's repositories and satellites (e.g. commits_between)
(for reference: http://feedback.gitlab.com/forums/176466-general/suggestions/3456722-merge-requests-between-projects-repos)
Fixes:
Make test repos/satellites only create when needed
-Spinach/Rspec now only initialize test directory, and setup stubs (things that are relatively cheap)
-project_with_code, source_project_with_code, and target_project_with_code now create/destroy their repos individually
-fixed remote removal
-How to merge renders properly
-Update emails to show project/branches
-Edit MR doesn't set target branch
-Fix some failures on editing/creating merge requests, added a test
-Added back a test around merge request observer
-Clean up project_transfer_spec, Remove duplicate enable/disable observers
-Ensure satellite lock files are cleaned up, Attempted to add some testing around these as well
-Signifant speed ups for tests
-Update formatting ordering in notes_on_merge_requests
-Remove wiki schema update
Fixes for search/search results
-Search results was using by_project for a list of projects, updated this to use in_projects
-updated search results to reference the correct (target) project
-udpated search results to print both sides of the merge request
Change-Id: I19407990a0950945cc95d62089cbcc6262dab1a8
Diffstat (limited to 'app')
42 files changed, 412 insertions, 215 deletions
diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index 20c772d8e94..2f98df3fe41 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -415,6 +415,17 @@ img.emoji { @extend .light-well; @extend .light; margin-bottom: 10px; + +.label-project { + @include border-radius(4px); + padding: 2px 4px; + border: none; + font-size: 14px; + background: #474D57; + color: #fff; + font-family: $monospace_font; + text-shadow: 0 1px 1px #111; + font-weight: normal; } .group-name { diff --git a/app/contexts/filter_context.rb b/app/contexts/filter_context.rb index 401d19b31c8..7349abb8d6e 100644 --- a/app/contexts/filter_context.rb +++ b/app/contexts/filter_context.rb @@ -12,7 +12,7 @@ class FilterContext def apply_filter items if params[:project_id] - items = items.where(project_id: params[:project_id]) + items = items.by_project(params[:project_id]) end if params[:search].present? @@ -20,12 +20,12 @@ class FilterContext end case params[:status] - when 'closed' - items.closed - when 'all' - items - else - items.opened + when 'closed' + items.closed + when 'all' + items + else + items.opened end end end diff --git a/app/contexts/merge_requests_load_context.rb b/app/contexts/merge_requests_load_context.rb index fd44572c0eb..9eba81295a9 100644 --- a/app/contexts/merge_requests_load_context.rb +++ b/app/contexts/merge_requests_load_context.rb @@ -14,7 +14,7 @@ class MergeRequestsLoadContext < BaseContext end merge_requests = merge_requests.page(params[:page]).per(20) - merge_requests = merge_requests.includes(:author, :project).order("created_at desc") + merge_requests = merge_requests.includes(:author, :source_project, :target_project).order("created_at desc") # Filter by specific assignee_id (or lack thereof)? if params[:assignee_id].present? diff --git a/app/contexts/search_context.rb b/app/contexts/search_context.rb index 22cda709f69..4b1be84a2e1 100644 --- a/app/contexts/search_context.rb +++ b/app/contexts/search_context.rb @@ -19,7 +19,7 @@ class SearchContext if params[:search_code].present? result[:blobs] = project.repository.search_files(query, params[:repository_ref]) unless project.empty_repo? else - result[:merge_requests] = MergeRequest.where(project_id: project_ids).search(query).limit(10) + result[:merge_requests] = MergeRequest.in_projects(project_ids).search(query).limit(10) result[:issues] = Issue.where(project_id: project_ids).search(query).limit(10) result[:wiki_pages] = [] end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 33c1a1feff7..6c5285be0a2 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -24,8 +24,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController format.html format.js - format.diff { render text: @merge_request.to_diff } - format.patch { render text: @merge_request.to_patch } + format.diff { render text: @merge_request.to_diff(current_user) } + format.patch { render text: @merge_request.to_patch(current_user) } end end @@ -33,25 +33,39 @@ class Projects::MergeRequestsController < Projects::ApplicationController @commit = @merge_request.last_commit @comments_allowed = @reply_allowed = true - @comments_target = { noteable_type: 'MergeRequest', - noteable_id: @merge_request.id } + @comments_target = {noteable_type: 'MergeRequest', + noteable_id: @merge_request.id} @line_notes = @merge_request.notes.where("line_code is not null") end def new @merge_request = @project.merge_requests.new(params[:merge_request]) + + if params[:merge_request] && params[:merge_request][:source_project_id] + @merge_request.source_project = Project.find_by_id(params[:merge_request][:source_project_id]) + else + @merge_request.source_project = @project + end + if params[:merge_request] && params[:merge_request][:target_project_id] + @merge_request.target_project = Project.find_by_id(params[:merge_request][:target_project_id]) + end + @target_branches = @merge_request.target_project.nil? ? [] : @merge_request.target_project.repository.branch_names + @merge_request end def edit + @target_branches = @merge_request.target_project.repository.branch_names end def create @merge_request = @project.merge_requests.new(params[:merge_request]) @merge_request.author = current_user - + @merge_request.source_project_id = params[:merge_request][:source_project_id].to_i + @merge_request.target_project_id = params[:merge_request][:target_project_id].to_i + @target_branches ||= [] if @merge_request.save @merge_request.reload_code - redirect_to [@project, @merge_request], notice: 'Merge request was successfully created.' + redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully created.' else render "new" end @@ -89,22 +103,36 @@ class Projects::MergeRequestsController < Projects::ApplicationController end def branch_from + #This is always source @commit = @repository.commit(params[:ref]) end def branch_to - @commit = @repository.commit(params[:ref]) + @target_project = selected_target_project + @commit = @target_project.repository.commit(params[:ref]) end + def update_branches + @target_project = selected_target_project + @target_branches = (@target_project.repository.branch_names).unshift("Select branch") + @target_branches + end + + def ci_status status = project.gitlab_ci_service.commit_status(merge_request.last_commit.sha) - response = { status: status } + response = {status: status} render json: response end protected + def selected_target_project + ((@project.id.to_s == params[:target_project_id]) || @project.forked_project_link.nil?) ? @project : @project.forked_project_link.forked_from_project + end + + def merge_request @merge_request ||= @project.merge_requests.find(params[:id]) end @@ -123,11 +151,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController def validates_merge_request # Show git not found page if target branch doesn't exist - return invalid_mr unless @project.repository.branch_names.include?(@merge_request.target_branch) + return invalid_mr unless @merge_request.target_project.repository.branch_names.include?(@merge_request.target_branch) # Show git not found page if source branch doesn't exist # and there is no saved commits between source & target branch - return invalid_mr if !@project.repository.branch_names.include?(@merge_request.source_branch) && @merge_request.commits.blank? + return invalid_mr if !@merge_request.source_project.repository.branch_names.include?(@merge_request.source_branch) && @merge_request.commits.blank? end def define_show_vars diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 86979156d94..ed0d4d34585 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -108,8 +108,8 @@ module CommitsHelper end end - def commit_to_html commit - escape_javascript(render 'projects/commits/commit', commit: commit) + def commit_to_html commit, project + escape_javascript(render 'projects/commits/commit', commit: commit, project: project) unless commit.nil? end def diff_line_content(line) diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index 05ffec066f8..e8e7bf990ac 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -1,13 +1,27 @@ module MergeRequestsHelper def new_mr_path_from_push_event(event) new_project_merge_request_path( - event.project, - merge_request: { + event.project, + new_mr_from_push_event(event, event.project) + ) + end + + def new_mr_path_for_fork_from_push_event(event) + new_project_merge_request_path( + event.project, + new_mr_from_push_event(event, event.project.forked_from_project) + ) + end + + + def new_mr_from_push_event(event, target_project) + return :merge_request => { + source_project_id: event.project.id, + target_project_id: target_project.id, source_branch: event.branch_name, - target_branch: event.project.repository.root_ref, + target_branch: target_project.repository.root_ref, title: event.branch_name.titleize - } - ) + } end def mr_css_classes mr @@ -18,6 +32,6 @@ module MergeRequestsHelper end def ci_build_details_path merge_request - merge_request.project.gitlab_ci_service.build_page(merge_request.last_commit.sha) + merge_request.source_project.gitlab_ci_service.build_page(merge_request.last_commit.sha) end end diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb index de47903c0d4..3dc3ddc3efd 100644 --- a/app/mailers/emails/merge_requests.rb +++ b/app/mailers/emails/merge_requests.rb @@ -2,28 +2,65 @@ module Emails module MergeRequests def new_merge_request_email(recipient_id, merge_request_id) @merge_request = MergeRequest.find(merge_request_id) - @project = @merge_request.project - mail(to: recipient(recipient_id), subject: subject("new merge request !#{@merge_request.id}", @merge_request.title)) + mail(to: @merge_request.assignee_email, subject: subject("new merge request !#{@merge_request.id}", @merge_request.title)) end def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id) @merge_request = MergeRequest.find(merge_request_id) @previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id - @project = @merge_request.project mail(to: recipient(recipient_id), subject: subject("changed merge request !#{@merge_request.id}", @merge_request.title)) end def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id) @merge_request = MergeRequest.find(merge_request_id) - @project = @merge_request.project @updated_by = User.find updated_by_user_id mail(to: recipient(recipient_id), subject: subject("Closed merge request !#{@merge_request.id}", @merge_request.title)) end def merged_merge_request_email(recipient_id, merge_request_id) @merge_request = MergeRequest.find(merge_request_id) - @project = @merge_request.project mail(to: recipient(recipient_id), subject: subject("Accepted merge request !#{@merge_request.id}", @merge_request.title)) end end + + + # Over rides default behavour to show source/target + # Formats arguments into a String suitable for use as an email subject + # + # extra - Extra Strings to be inserted into the subject + # + # Examples + # + # >> subject('Lorem ipsum') + # => "GitLab Merge Request | Lorem ipsum" + # + # # Automatically inserts Project name: + # Forked MR + # => source project => <Project id: 1, name: "Ruby on Rails", path: "ruby_on_rails", ...> + # => target project => <Project id: 2, name: "My Ror", path: "ruby_on_rails", ...> + # => source branch => source + # => target branch => target + # >> subject('Lorem ipsum') + # => "GitLab Merge Request | Ruby on Rails:source >> My Ror:target | Lorem ipsum " + # + # Non Forked MR + # => source project => <Project id: 1, name: "Ruby on Rails", path: "ruby_on_rails", ...> + # => target project => <Project id: 1, name: "Ruby on Rails", path: "ruby_on_rails", ...> + # => source branch => source + # => target branch => target + # >> subject('Lorem ipsum') + # => "GitLab Merge Request | Ruby on Rails | source >> target | Lorem ipsum " + # # Accepts multiple arguments + # >> subject('Lorem ipsum', 'Dolor sit amet') + # => "GitLab Merge Request | Lorem ipsum | Dolor sit amet" + def subject(*extra) + subject = "GitLab Merge Request |" + if @merge_request.for_fork? + subject << "#{@merge_request.source_project.name_with_namespace}:#{merge_request.source_branch} >> #{@merge_request.target_project.name_with_namespace}:#{merge_request.target_branch}" + else + subject << "#{@merge_request.source_project.name_with_namespace} | #{merge_request.source_branch} >> #{merge_request.target_branch}" + end + subject << " | " + extra.join(' | ') if extra.present? + subject + end end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 8868e818daa..88de1a037aa 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -9,19 +9,14 @@ module Issuable include Mentionable included do - belongs_to :project belongs_to :author, class_name: "User" belongs_to :assignee, class_name: "User" belongs_to :milestone has_many :notes, as: :noteable, dependent: :destroy - validates :project, presence: true validates :author, presence: true validates :title, presence: true, length: { within: 0..255 } - scope :opened, -> { with_state(:opened) } - scope :closed, -> { with_state(:closed) } - scope :of_group, ->(group) { where(project_id: group.project_ids) } scope :assigned_to, ->(u) { where(assignee_id: u.id)} scope :recent, -> { order("created_at DESC") } scope :assigned, -> { where("assignee_id IS NOT NULL") } diff --git a/app/models/issue.rb b/app/models/issue.rb index f56928891dc..c171941928c 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -17,8 +17,18 @@ # class Issue < ActiveRecord::Base + include Issuable + belongs_to :project + validates :project, presence: true + + scope :of_group, ->(group) { where(project_id: group.project_ids) } + scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) } + scope :opened, -> { with_state(:opened) } + scope :closed, -> { with_state(:closed) } + scope :by_project, ->(project_id) {where(project_id:project_id)} + attr_accessible :title, :assignee_id, :position, :description, :milestone_id, :label_list, :author_id_of_changes, :state_event diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 2a476355404..0e0ae3c3a07 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -2,30 +2,37 @@ # # 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" + + BROKEN_DIFF = "--broken-diff" + + 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,22 +81,29 @@ 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? @@ -137,7 +151,14 @@ class MergeRequest < ActiveRecord::Base end def unmerged_diffs - project.repository.diffs_between(source_branch, target_branch) + #TODO:[IA-8] this needs to be handled better -- logged etc + diffs = Gitlab::Satellite::MergeAction.new(author, self).diffs_between_satellite + if diffs + diffs = diffs.map { |diff| Gitlab::Git::Diff.new(diff) } + else + diffs = [] + end + diffs end def last_commit @@ -145,11 +166,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 @@ -158,24 +179,30 @@ class MergeRequest < ActiveRecord::Base def probably_merged? unmerged_commits.empty? && - commits.any? && opened? + commits.any? && opened? end def reloaded_commits 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). - sort_by(&:created_at). - reverse + commits = Gitlab::Satellite::MergeAction.new(self.author,self).commits_between + commits = commits.map{ |commit| Gitlab::Git::Commit.new(commit, nil) } + if commits.present? + commits = Commit.decorate(commits). + sort_by(&:created_at). + reverse + end + commits end + def merge!(user_id) self.author_id_of_changes = user_id self.merge @@ -195,25 +222,33 @@ class MergeRequest < ActiveRecord::Base commit_ids = commits.map(&:id) Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids) end - # 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) diff --git a/app/models/note.rb b/app/models/note.rb index c23aab03bcc..0175430be4d 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -32,8 +32,8 @@ class Note < ActiveRecord::Base delegate :name, :email, to: :author, prefix: true validates :note, :project, presence: true - validates :line_code, format: { with: /\A[a-z0-9]+_\d+_\d+\Z/ }, allow_blank: true - validates :attachment, file_size: { maximum: 10.megabytes.to_i } + validates :line_code, format: {with: /\A[a-z0-9]+_\d+_\d+\Z/}, allow_blank: true + validates :attachment, file_size: {maximum: 10.megabytes.to_i} validates :noteable_id, presence: true, if: ->(n) { n.noteable_type.present? && n.noteable_type != 'Commit' } validates :commit_id, presence: true, if: ->(n) { n.noteable_type == 'Commit' } @@ -45,24 +45,24 @@ class Note < ActiveRecord::Base scope :inline, -> { where("line_code IS NOT NULL") } scope :not_inline, -> { where(line_code: [nil, '']) } - scope :common, ->{ where(noteable_type: ["", nil]) } - scope :fresh, ->{ order("created_at ASC, id ASC") } - scope :inc_author_project, ->{ includes(:project, :author) } - scope :inc_author, ->{ includes(:author) } + scope :common, -> { where(noteable_type: ["", nil]) } + scope :fresh, -> { order("created_at ASC, id ASC") } + scope :inc_author_project, -> { includes(:project, :author) } + scope :inc_author, -> { includes(:author) } - def self.create_status_change_note(noteable, author, status) + def self.create_status_change_note(noteable, project, author, status) create({ - noteable: noteable, - project: noteable.project, - author: author, - note: "_Status changed to #{status}_" - }, without_protection: true) + noteable: noteable, + project: project, + author: author, + note: "_Status changed to #{status}_" + }, without_protection: true) end def commit_author @commit_author ||= - project.users.find_by_email(noteable.author_email) || - project.users.find_by_name(noteable.author_name) + project.users.find_by_email(noteable.author_email) || + project.users.find_by_name(noteable.author_name) rescue nil end @@ -97,8 +97,8 @@ class Note < ActiveRecord::Base # otherwise false is returned def downvote? votable? && (note.start_with?('-1') || - note.start_with?(':-1:') - ) + note.start_with?(':-1:') + ) end def for_commit? @@ -136,8 +136,8 @@ class Note < ActiveRecord::Base else super end - # Temp fix to prevent app crash - # if note commit id doesn't exist + # Temp fix to prevent app crash + # if note commit id doesn't exist rescue nil end @@ -146,8 +146,8 @@ class Note < ActiveRecord::Base # otherwise false is returned def upvote? votable? && (note.start_with?('+1') || - note.start_with?(':+1:') - ) + note.start_with?(':+1:') + ) end def votable? diff --git a/app/models/project.rb b/app/models/project.rb index 8297c11ba8a..f373446f579 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -53,7 +53,7 @@ class Project < ActiveRecord::Base has_many :services, dependent: :destroy has_many :events, dependent: :destroy - has_many :merge_requests, dependent: :destroy + has_many :merge_requests, dependent: :destroy, foreign_key: "target_project_id" has_many :issues, dependent: :destroy, order: "state DESC, created_at DESC" has_many :milestones, dependent: :destroy has_many :notes, dependent: :destroy diff --git a/app/observers/activity_observer.rb b/app/observers/activity_observer.rb index ee3e4629b4c..3740274db2d 100644 --- a/app/observers/activity_observer.rb +++ b/app/observers/activity_observer.rb @@ -1,5 +1,5 @@ class ActivityObserver < BaseObserver - observe :issue, :merge_request, :note, :milestone + observe :issue, :note, :milestone def after_create(record) event_author_id = record.author_id @@ -13,47 +13,27 @@ class ActivityObserver < BaseObserver end if event_author_id - Event.create( - project: record.project, - target_id: record.id, - target_type: record.class.name, - action: Event.determine_action(record), - author_id: event_author_id - ) + create_event(record, Event.determine_action(record)) end end def after_close(record, transition) - Event.create( - project: record.project, - target_id: record.id, - target_type: record.class.name, - action: Event::CLOSED, - author_id: record.author_id_of_changes - ) + create_event(record, Event::CLOSED) end def after_reopen(record, transition) - Event.create( - project: record.project, - target_id: record.id, - target_type: record.class.name, - action: Event::REOPENED, - author_id: record.author_id_of_changes - ) + create_event(record, Event::REOPENED) end - def after_merge(record, transition) - # Since MR can be merged via sidekiq - # to prevent event duplication do this check - return true if record.merge_event + protected + def create_event(record, status) Event.create( - project: record.project, - target_id: record.id, - target_type: record.class.name, - action: Event::MERGED, - author_id: record.author_id_of_changes + project: record.project, + target_id: record.id, + target_type: record.class.name, + action: status, + author_id: record.author_id ) end end diff --git a/app/observers/issue_observer.rb b/app/observers/issue_observer.rb index 888fa7f6b73..50538419776 100644 --- a/app/observers/issue_observer.rb +++ b/app/observers/issue_observer.rb @@ -23,6 +23,6 @@ class IssueObserver < BaseObserver # Create issue note with service comment like 'Status changed to closed' def create_note(issue) - Note.create_status_change_note(issue, current_user, issue.state) + Note.create_status_change_note(issue, issue.project, current_user, issue.state) end end diff --git a/app/observers/merge_request_observer.rb b/app/observers/merge_request_observer.rb index 03d4a22c1e6..6260b79593a 100644 --- a/app/observers/merge_request_observer.rb +++ b/app/observers/merge_request_observer.rb @@ -1,23 +1,56 @@ -class MergeRequestObserver < BaseObserver +class MergeRequestObserver < ActivityObserver + observe :merge_request + cattr_accessor :current_user + def after_create(merge_request) + event_author_id = merge_request.author_id + if event_author_id + create_event(merge_request, Event.determine_action(merge_request)) + end + notification.new_merge_request(merge_request, current_user) end def after_close(merge_request, transition) - Note.create_status_change_note(merge_request, current_user, merge_request.state) + create_event(merge_request, Event::CLOSED) + Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state) notification.close_mr(merge_request, current_user) end def after_merge(merge_request, transition) notification.merge_mr(merge_request) + # Since MR can be merged via sidekiq + # to prevent event duplication do this check + return true if merge_request.merge_event + + Event.create( + project: merge_request.target_project, + target_id: merge_request.id, + target_type: merge_request.class.name, + action: Event::MERGED, + author_id: merge_request.author_id_of_changes + ) end def after_reopen(merge_request, transition) - Note.create_status_change_note(merge_request, current_user, merge_request.state) + create_event(merge_request, Event::REOPENED) + Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state) end def after_update(merge_request) notification.reassigned_merge_request(merge_request, current_user) if merge_request.is_being_reassigned? end + + + def create_event(record, status) + Event.create( + project: record.target_project, + target_id: record.id, + target_type: record.class.name, + action: status, + author_id: record.author_id + ) + end + end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index f3dc552a8e7..75704e2eb0e 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -23,7 +23,7 @@ class NotificationService # * project team members with notification level higher then Participating # def new_issue(issue, current_user) - new_resource_email(issue, 'new_issue_email') + new_resource_email(issue, issue.project, 'new_issue_email') end # When we close an issue we should send next emails: @@ -33,7 +33,7 @@ class NotificationService # * project team members with notification level higher then Participating # def close_issue(issue, current_user) - close_resource_email(issue, current_user, 'closed_issue_email') + close_resource_email(issue, issue.project, current_user, 'closed_issue_email') end # When we reassign an issue we should send next emails: @@ -42,7 +42,7 @@ class NotificationService # * issue new assignee if his notification level is not Disabled # def reassigned_issue(issue, current_user) - reassign_resource_email(issue, current_user, 'reassigned_issue_email') + reassign_resource_email(issue, issue.project, current_user, 'reassigned_issue_email') end @@ -51,7 +51,7 @@ class NotificationService # * mr assignee if his notification level is not Disabled # def new_merge_request(merge_request, current_user) - new_resource_email(merge_request, 'new_merge_request_email') + new_resource_email(merge_request, merge_request.target_project, 'new_merge_request_email') end # When we reassign a merge_request we should send next emails: @@ -60,7 +60,7 @@ class NotificationService # * merge_request assignee if his notification level is not Disabled # def reassigned_merge_request(merge_request, current_user) - reassign_resource_email(merge_request, current_user, 'reassigned_merge_request_email') + reassign_resource_email(merge_request, merge_request.target_project, current_user, 'reassigned_merge_request_email') end # When we close a merge request we should send next emails: @@ -70,7 +70,7 @@ class NotificationService # * project team members with notification level higher then Participating # def close_mr(merge_request, current_user) - close_resource_email(merge_request, current_user, 'closed_merge_request_email') + close_resource_email(merge_request, merge_request.target_project, current_user, 'closed_merge_request_email') end # When we merge a merge request we should send next emails: @@ -80,8 +80,10 @@ class NotificationService # * project team members with notification level higher then Participating # def merge_mr(merge_request) - recipients = reject_muted_users([merge_request.author, merge_request.assignee], merge_request.project) - recipients = recipients.concat(project_watchers(merge_request.project)).uniq + recipients = reject_muted_users([merge_request.author, merge_request.assignee], merge_request.source_project) + recipients = recipients.concat(reject_muted_users([merge_request.author, merge_request.assignee], merge_request.target_project)) + recipients = recipients.concat(project_watchers(merge_request.source_project)) + recipients = recipients.concat(project_watchers(merge_request.target_project)).uniq recipients.each do |recipient| mailer.merged_merge_request_email(recipient.id, merge_request.id) @@ -102,7 +104,7 @@ class NotificationService # ignore wall messages return true unless note.noteable_type.present? - opts = { noteable_type: note.noteable_type, project_id: note.project_id } + opts = {noteable_type: note.noteable_type, project_id: note.project_id} if note.commit_id.present? opts.merge!(commit_id: note.commit_id) @@ -191,14 +193,14 @@ class NotificationService end end - def new_resource_email(target, method) + def new_resource_email(target, project, method) if target.respond_to?(:participants) recipients = target.participants else recipients = [] end - recipients = reject_muted_users(recipients, target.project) - recipients = recipients.concat(project_watchers(target.project)).uniq + recipients = reject_muted_users(recipients, project) + recipients = recipients.concat(project_watchers(project)).uniq recipients.delete(target.author) recipients.each do |recipient| @@ -206,9 +208,9 @@ class NotificationService end end - def close_resource_email(target, current_user, method) - recipients = reject_muted_users([target.author, target.assignee], target.project) - recipients = recipients.concat(project_watchers(target.project)).uniq + def close_resource_email(target, project, current_user, method) + recipients = reject_muted_users([target.author, target.assignee], project) + recipients = recipients.concat(project_watchers(project)).uniq recipients.delete(current_user) recipients.each do |recipient| @@ -216,14 +218,14 @@ class NotificationService end end - def reassign_resource_email(target, current_user, method) + def reassign_resource_email(target, project, current_user, method) recipients = User.where(id: [target.assignee_id, target.assignee_id_was]) # Add watchers to email list - recipients = recipients.concat(project_watchers(target.project)) + recipients = recipients.concat(project_watchers(project)) # reject users with disabled notifications - recipients = reject_muted_users(recipients, target.project) + recipients = reject_muted_users(recipients, project) # Reject me from recipients if I reassign an item recipients.delete(current_user) diff --git a/app/views/events/_event_last_push.html.haml b/app/views/events/_event_last_push.html.haml index de5634d3c55..a634365ff3e 100644 --- a/app/views/events/_event_last_push.html.haml +++ b/app/views/events/_event_last_push.html.haml @@ -9,6 +9,9 @@ = time_ago_in_words(event.created_at) ago. .pull-right - = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn btn-create btn-small" do + = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn btn-new-mr" do Create Merge Request + - if !event.project.nil? && event.project.forked? + = link_to new_mr_path_for_fork_from_push_event(event), title: "New Merge Request", class: "btn btn-create btn-small" do + Create Merge Request on fork %hr diff --git a/app/views/merge_requests/update_branches.js.haml b/app/views/merge_requests/update_branches.js.haml new file mode 100644 index 00000000000..c9171622669 --- /dev/null +++ b/app/views/merge_requests/update_branches.js.haml @@ -0,0 +1,8 @@ +:plain + $(".target_branch").html("#{escape_javascript(options_for_select(@target_branches))}"); + $(".target_branch").trigger("liszt:updated"); + $(".mr_target_commit").html(""); + + + + diff --git a/app/views/notify/closed_merge_request_email.html.haml b/app/views/notify/closed_merge_request_email.html.haml index 0c6c79e097a..306c1ff8f60 100644 --- a/app/views/notify/closed_merge_request_email.html.haml +++ b/app/views/notify/closed_merge_request_email.html.haml @@ -3,7 +3,7 @@ %p = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.project, @merge_request) %p - Branches: #{@merge_request.source_branch} → #{@merge_request.target_branch} + Projects:Branches: #{@merge_request.source_project.path_with_namespace}:#{@merge_request.source_branch} → #{@merge_request.target_project.path_with_namespace}:#{@merge_request.target_branch} %p Assignee: #{@merge_request.author_name} → #{@merge_request.assignee_name} diff --git a/app/views/notify/closed_merge_request_email.text.haml b/app/views/notify/closed_merge_request_email.text.haml index ee4648e3d09..1c92e004ff6 100644 --- a/app/views/notify/closed_merge_request_email.text.haml +++ b/app/views/notify/closed_merge_request_email.text.haml @@ -1,8 +1,8 @@ = "Merge Request #{@merge_request.id} was closed by #{@updated_by.name}" -Merge Request url: #{project_merge_request_url(@merge_request.project, @merge_request)} +Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)} -Branches: #{@merge_request.source_branch} - #{@merge_request.target_branch} +Project:Branches: #{@merge_request.source_project.path_with_namespace}/#{@merge_request.source_branch} - #{@merge_request.target_project.path_with_namespace}#{@merge_request.target_branch} Author: #{@merge_request.author_name} Assignee: #{@merge_request.assignee_name} diff --git a/app/views/notify/merged_merge_request_email.html.haml b/app/views/notify/merged_merge_request_email.html.haml index 2b8cc030b23..4115adf1b42 100644 --- a/app/views/notify/merged_merge_request_email.html.haml +++ b/app/views/notify/merged_merge_request_email.html.haml @@ -1,9 +1,9 @@ %p = "Merge Request #{@merge_request.id} was merged" %p - = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.project, @merge_request) + = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request) %p - Branches: #{@merge_request.source_branch} → #{@merge_request.target_branch} + Projects:Branches: #{@merge_request.source_project.path_with_namespace}:#{@merge_request.source_branch} → #{@merge_request.target_project.path_with_namespace}:#{@merge_request.target_branch} %p Assignee: #{@merge_request.author_name} → #{@merge_request.assignee_name} diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml index 91c23360195..5f19473fae0 100644 --- a/app/views/notify/merged_merge_request_email.text.haml +++ b/app/views/notify/merged_merge_request_email.text.haml @@ -1,8 +1,8 @@ = "Merge Request #{@merge_request.id} was merged" -Merge Request Url: #{project_merge_request_url(@merge_request.project, @merge_request)} +Merge Request Url: #{project_merge_request_url(@merge_request.target_project, @merge_request)} -Branches: #{@merge_request.source_branch} - #{@merge_request.target_branch} +Project:Branches: #{@merge_request.source_project.path_with_namespace}/#{@merge_request.source_branch} - #{@merge_request.target_project.path_with_namespace}#{@merge_request.target_branch} Author: #{@merge_request.author_name} Assignee: #{@merge_request.assignee_name} diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml index 0f1cfff5831..fc4ffba1102 100644 --- a/app/views/notify/new_merge_request_email.html.haml +++ b/app/views/notify/new_merge_request_email.html.haml @@ -1,9 +1,9 @@ %p = "New Merge Request !#{@merge_request.id}" %p - = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.project, @merge_request) + = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request) %p - Branches: #{@merge_request.source_branch} → #{@merge_request.target_branch} + Project:Branches: #{@merge_request.source_project.path_with_namespace}/#{@merge_request.source_branch} - #{@merge_request.target_project.path_with_namespace}#{@merge_request.target_branch} %p Assignee: #{@merge_request.author_name} → #{@merge_request.assignee_name} diff --git a/app/views/notify/new_merge_request_email.text.erb b/app/views/notify/new_merge_request_email.text.erb index 3393d8384f1..4c1a93f7dcc 100644 --- a/app/views/notify/new_merge_request_email.text.erb +++ b/app/views/notify/new_merge_request_email.text.erb @@ -1,9 +1,8 @@ New Merge Request <%= @merge_request.id %> -<%= url_for(project_merge_request_url(@merge_request.project, @merge_request)) %> - +<%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %> -Branches: <%= @merge_request.source_branch %> to <%= @merge_request.target_branch %> +From: <%= @merge_request.source_project.path_with_namespace%>:<%= @merge_request.source_branch %> to <%= @merge_request.target_project.path_with_namespace%>:<%= @merge_request.target_branch %> Author: <%= @merge_request.author_name %> Asignee: <%= @merge_request.assignee_name %> diff --git a/app/views/notify/note_merge_request_email.html.haml b/app/views/notify/note_merge_request_email.html.haml index 4f97867e49d..14abcca6070 100644 --- a/app/views/notify/note_merge_request_email.html.haml +++ b/app/views/notify/note_merge_request_email.html.haml @@ -1,8 +1,8 @@ %p - if @note.for_diff_line? - = link_to "New comment on diff", diffs_project_merge_request_url(@merge_request.project, @merge_request, anchor: "note_#{@note.id}") + = link_to "New comment on diff", diffs_project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}") - else - = link_to "New comment", project_merge_request_url(@merge_request.project, @merge_request, anchor: "note_#{@note.id}") + = link_to "New comment", project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}") for Merge Request ##{@merge_request.id} %cite "#{truncate(@merge_request.title, length: 20)}" = render 'note_message' diff --git a/app/views/notify/note_merge_request_email.text.erb b/app/views/notify/note_merge_request_email.text.erb index 26c73bdaa38..3daa091db81 100644 --- a/app/views/notify/note_merge_request_email.text.erb +++ b/app/views/notify/note_merge_request_email.text.erb @@ -1,6 +1,6 @@ New comment for Merge Request <%= @merge_request.id %> -<%= url_for(project_merge_request_url(@merge_request.project, @merge_request, anchor: "note_#{@note.id}")) %> +<%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}")) %> <%= @note.author_name %> diff --git a/app/views/notify/reassigned_merge_request_email.html.haml b/app/views/notify/reassigned_merge_request_email.html.haml index 5ad72764e38..314b2882672 100644 --- a/app/views/notify/reassigned_merge_request_email.html.haml +++ b/app/views/notify/reassigned_merge_request_email.html.haml @@ -1,6 +1,6 @@ %p = "Reassigned Merge Request !#{@merge_request.id}" - = link_to_gfm truncate(@merge_request.title, length: 30), project_merge_request_url(@merge_request.project, @merge_request) + = link_to_gfm truncate(@merge_request.title, length: 30), project_merge_request_url(@merge_request.target_project, @merge_request) %p Assignee changed - if @previous_assignee diff --git a/app/views/notify/reassigned_merge_request_email.text.erb b/app/views/notify/reassigned_merge_request_email.text.erb index 25b2a43fcdd..05a9797165d 100644 --- a/app/views/notify/reassigned_merge_request_email.text.erb +++ b/app/views/notify/reassigned_merge_request_email.text.erb @@ -1,6 +1,6 @@ Reassigned Merge Request <%= @merge_request.id %> -<%= url_for(project_merge_request_url(@merge_request.project, @merge_request)) %> +<%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %> Assignee changed <%= "from #{@previous_assignee.name}" if @previous_assignee %> to <%= @merge_request.assignee_name %> diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index eba6c206c46..eb5bdb886e2 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -1,12 +1,12 @@ %li.commit .browse_code_link_holder %p - %strong= link_to "Browse Code »", project_tree_path(@project, commit), class: "right" + %strong= link_to "Browse Code »", project_tree_path(project, commit), class: "right" %p - = link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id" + = link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id" = commit_author_link(commit, avatar: true, size: 24) - = link_to_gfm truncate(commit.title, length: 70), project_commit_path(@project, commit.id), class: "row_title" + = link_to_gfm truncate(commit.title, length: 70), project_commit_path(project, commit.id), class: "row_title" %time.committed_ago{ datetime: commit.committed_date, title: commit.committed_date.stamp("Aug 21, 2011 9:23pm") } = time_ago_in_words(commit.committed_date) @@ -14,7 +14,7 @@ %span.notes_count - - notes = @project.notes.for_commit_id(commit.id) + - notes = project.notes.for_commit_id(commit.id) - if notes.any? %span.badge.badge-info %i.icon-comment diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml index acdb8891344..d8b84aa5041 100644 --- a/app/views/projects/commits/_commits.html.haml +++ b/app/views/projects/commits/_commits.html.haml @@ -3,7 +3,6 @@ .title %i.icon-calendar %span= day.stamp("28 Aug, 2010") - .pull-right %small= pluralize(commits.count, 'commit') - %ul.well-list= render commits + %ul.well-list= render commits, :project => @project diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index 5e6b5b71753..e18fd6cc093 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -15,7 +15,7 @@ %div.ui-box .title Commits (#{@commits.count}) - %ul.well-list= render Commit.decorate(@commits) + %ul.well-list= render Commit.decorate(@commits), project: @project - unless @diffs.empty? %h4 Diff diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml index 86c442142bf..c378739c111 100644 --- a/app/views/projects/merge_requests/_form.html.haml +++ b/app/views/projects/merge_requests/_form.html.haml @@ -1,4 +1,4 @@ -= form_for [@project, @merge_request], html: { class: "#{controller.action_name}-merge-request form-horizontal" } do |f| += form_for [@project, @merge_request], html: { class: "#{controller.action_name}-merge-request form-horizontal" } do |form_helper| -if @merge_request.errors.any? .alert.alert-error %ul @@ -12,18 +12,20 @@ .row .span5 .light-well - %h5.cgray From (Head Branch) - = f.select(:source_branch, @repository.branch_names, { include_blank: "Select branch" }, {class: 'chosen span4'}) + %h5.cgray From + .padded= form_helper.select(:source_project_id,[[@merge_request.source_project.path_with_namespace,@merge_request.source_project.id]] , {}, {class: 'source_project chosen span4'}) + .padded= form_helper.select(:source_branch, @merge_request.source_project.repository.branch_names, { include_blank: "Select branch" }, {class: 'source_branch chosen span4'}) .mr_source_commit.prepend-top-10 - .span2 %h1.merge-request-angle %i.icon-angle-right .span5 .light-well - %h5.cgray To (Base Branch) - = f.select(:target_branch, @repository.branch_names, { include_blank: "Select branch" }, {class: 'chosen span4'}) - .mr_target_commit.prepend-top-10 + %h5.cgray To + - projects = @project.forked_from_project.nil? ? [@project] : [ @project,@project.forked_from_project] + .padded= form_helper.select(:target_project_id, projects.map { |proj| [proj.path_with_namespace,proj.id] }, {include_blank: "Select Target Project" }, {class: 'target_project chosen span4'}) + .padded= form_helper.select(:target_branch, @target_branches, { include_blank: "Select branch" }, {class: 'target_branch chosen span4'}) + .mr_target_commit.prepend-top-10 %hr @@ -47,12 +49,11 @@ Milestone .input= f.select(:milestone_id, @project.milestones.active.all.map {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'}) - .form-actions - if @merge_request.new_record? - = f.submit 'Submit merge request', class: "btn btn-create" + = form_helper.submit 'Submit merge request', class: "btn btn-create" -else - = f.submit 'Save changes', class: "btn btn-save" + = form_helper.submit 'Save changes', class: "btn btn-save" - if @merge_request.new_record? = link_to project_merge_requests_path(@project), class: "btn btn-cancel" do Cancel @@ -63,16 +64,23 @@ :javascript disableButtonIfEmptyField("#merge_request_title", ".btn-save"); - var source_branch = $("#merge_request_source_branch") - , target_branch = $("#merge_request_target_branch"); + var source_branch = $("#merge_request_source_branch") + , target_branch = $("#merge_request_target_branch") + , target_project = $("#merge_request_target_project_id"); - $.get("#{branch_from_project_merge_requests_path(@project)}", {ref: source_branch.val() }); - $.get("#{branch_to_project_merge_requests_path(@project)}", {ref: target_branch.val() }); + $.get("#{branch_from_project_merge_requests_path(@project)}", {ref: source_branch.val() }); + $.get("#{branch_to_project_merge_requests_path(@project)}", {target_project_id: target_project.val(),ref: target_branch.val() }); - source_branch.live("change", function() { - $.get("#{branch_from_project_merge_requests_path(@project)}", {ref: $(this).val() }); - }); + target_project.live("change", function() { + $.get("#{update_branches_project_merge_requests_path(@project)}", {target_project_id: $(this).val() }); + }); + source_branch.live("change", function() { + $.get("#{branch_from_project_merge_requests_path(@project)}", {ref: $(this).val() }); + }); + target_branch.live("change", function() { + $.get("#{branch_to_project_merge_requests_path(@project)}", {target_project_id: target_project.val(),ref: $(this).val() }); + }); - target_branch.live("change", function() { - $.get("#{branch_to_project_merge_requests_path(@project)}", {ref: $(this).val() }); }); + + diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index ffc6b8fda1e..84bdde756d4 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -1,18 +1,19 @@ %li{ class: mr_css_classes(merge_request) } .merge-request-title %span.light= "##{merge_request.id}" - = link_to_gfm truncate(merge_request.title, length: 80), project_merge_request_path(merge_request.project, merge_request), class: "row_title" + = link_to_gfm truncate(merge_request.title, length: 80), project_merge_request_path(merge_request.target_project, merge_request), class: "row_title" - if merge_request.merged? %small.pull-right %i.icon-ok = "MERGED" - else %span.pull-right + = "#{merge_request.source_project.path_with_namespace}/#{merge_request.source_branch}" %i.icon-angle-right - = merge_request.target_branch + = "#{merge_request.target_project.path_with_namespace}/#{merge_request.target_branch}" .merge-request-info - if merge_request.author - authored by #{link_to_member(@project, merge_request.author)} + authored by #{link_to_member(merge_request.source_project, merge_request.author)} - if merge_request.votes_count > 0 = render 'votes/votes_inline', votable: merge_request - if merge_request.notes.any? diff --git a/app/views/projects/merge_requests/branch_from.js.haml b/app/views/projects/merge_requests/branch_from.js.haml index 0637fdcb72e..a680c708d63 100644 --- a/app/views/projects/merge_requests/branch_from.js.haml +++ b/app/views/projects/merge_requests/branch_from.js.haml @@ -1,2 +1,2 @@ :plain - $(".mr_source_commit").html("#{commit_to_html(@commit)}"); + $(".mr_source_commit").html("#{commit_to_html(@commit, @project)}"); diff --git a/app/views/projects/merge_requests/branch_to.js.haml b/app/views/projects/merge_requests/branch_to.js.haml index 974100d1ba7..f4e2886ee44 100644 --- a/app/views/projects/merge_requests/branch_to.js.haml +++ b/app/views/projects/merge_requests/branch_to.js.haml @@ -1,2 +1,2 @@ :plain - $(".mr_target_commit").html("#{commit_to_html(@commit)}"); + $(".mr_target_commit").html("#{commit_to_html(@commit, @target_project)}"); diff --git a/app/views/projects/merge_requests/show/_commits.html.haml b/app/views/projects/merge_requests/show/_commits.html.haml index 40876d16ddd..7b0e67053a5 100644 --- a/app/views/projects/merge_requests/show/_commits.html.haml +++ b/app/views/projects/merge_requests/show/_commits.html.haml @@ -7,19 +7,19 @@ - if @commits.count > 8 %ul.first-commits.well-list - @commits.first(8).each do |commit| - = render "projects/commits/commit", commit: commit + = render "projects/commits/commit", commit: commit, project: @merge_request.source_project %li.bottom 8 of #{@commits.count} commits displayed. %strong %a.show-all-commits Click here to show all %ul.all-commits.hide.well-list - @commits.each do |commit| - = render "projects/commits/commit", commit: commit + = render "projects/commits/commit", commit: commit, project: @merge_request.source_project - else %ul.well-list - @commits.each do |commit| - = render "projects/commits/commit", commit: commit + = render "projects/commits/commit", commit: commit, project: @merge_request.source_project - else %h4.nothing_here_message diff --git a/app/views/projects/merge_requests/show/_how_to_merge.html.haml b/app/views/projects/merge_requests/show/_how_to_merge.html.haml index 7f1e33418de..a0eb2309585 100644 --- a/app/views/projects/merge_requests/show/_how_to_merge.html.haml +++ b/app/views/projects/merge_requests/show/_how_to_merge.html.haml @@ -3,17 +3,49 @@ %a.close{href: "#"} × %h3 How To Merge .modal-body - %p - %strong Step 1. - Checkout target branch and get recent objects from GitLab - %pre.dark - :preserve - git checkout #{@merge_request.target_branch} - git fetch origin - %p - %strong Step 2. - Merge source branch into target branch and push changes to GitLab - %pre.dark - :preserve - git merge origin/#{@merge_request.source_branch} - git push origin #{@merge_request.target_branch} + - if @merge_request.for_fork? + - source_remote = @merge_request.source_project.namespace.nil? ? "source" :@merge_request.source_project.namespace.path + - target_remote = @merge_request.target_project.namespace.nil? ? "target" :@merge_request.target_project.namespace.path + %p + %strong Step 1. + Checkout target branch and get recent objects from GitLab + Assuming remote for #{@merge_request.target_project.path_with_namespace} is called #{target_remote} + remote for #{@merge_request.source_project.path_with_namespace} is called #{source_remote} + %pre.dark + :preserve + git checkout #{target_remote} #{@merge_request.target_branch} + git fetch #{source_remote} + %p + %strong Step 2. + Merge source branch into target branch and push changes to GitLab + %pre.dark + :preserve + git merge #{source_remote}/#{@merge_request.source_branch} + git push #{target_remote} #{@merge_request.target_branch} + - else + %p + %strong Step 1. + Checkout target branch and get recent objects from GitLab + %pre.dark + :preserve + git checkout #{@merge_request.target_branch} + git fetch origin + %p + %strong Step 2. + Merge source branch into target branch and push changes to GitLab + %pre.dark + :preserve + git merge origin/#{@merge_request.source_branch} + git push origin #{@merge_request.target_branch} + + +:javascript + $(function(){ + var modal = $('#modal_merge_info').modal({modal: true, show:false}); + $('.how_to_merge_link').bind("click", function(){ + modal.show(); + }); + $('.modal-header .close').bind("click", function(){ + modal.hide(); + }) + }) diff --git a/app/views/projects/merge_requests/show/_mr_accept.html.haml b/app/views/projects/merge_requests/show/_mr_accept.html.haml index 01378d99c99..47db8cdc8d2 100644 --- a/app/views/projects/merge_requests/show/_mr_accept.html.haml +++ b/app/views/projects/merge_requests/show/_mr_accept.html.haml @@ -15,7 +15,7 @@ for instructions .accept_group = f.submit "Accept Merge Request", class: "btn btn-create accept_merge_request" - - unless @project.root_ref? @merge_request.source_branch + - unless @merge_request.disallow_source_branch_removal? .remove_branch_holder = label_tag :should_remove_source_branch, class: "checkbox" do = check_box_tag :should_remove_source_branch diff --git a/app/views/projects/merge_requests/show/_mr_title.html.haml b/app/views/projects/merge_requests/show/_mr_title.html.haml index 5a07258f91c..2c31c2dbf31 100644 --- a/app/views/projects/merge_requests/show/_mr_title.html.haml +++ b/app/views/projects/merge_requests/show/_mr_title.html.haml @@ -1,8 +1,10 @@ %h3.page-title = "Merge Request ##{@merge_request.id}:" + %span.label-project= @merge_request.source_project.path_with_namespace %span.label-branch= @merge_request.source_branch → + %span.label-project= @merge_request.target_project.path_with_namespace %span.label-branch= @merge_request.target_branch %span.pull-right diff --git a/app/views/search/_result.html.haml b/app/views/search/_result.html.haml index 4e56eea084e..064c683e3d7 100644 --- a/app/views/search/_result.html.haml +++ b/app/views/search/_result.html.haml @@ -22,11 +22,11 @@ - @merge_requests.each do |merge_request| %li merge request: - = link_to [merge_request.project, merge_request] do + = link_to [merge_request.target_project, merge_request] do %span ##{merge_request.id} %strong.term = truncate merge_request.title, length: 50 - %span.light (#{merge_request.project.name_with_namespace}) + %span.light (#{merge_request.source_project.name_with_namespace}:#{merge_request.source_branch} → #{merge_request.target_project.name_with_namespace}:#{merge_request.target_branch}) - @issues.each do |issue| %li issue: diff --git a/app/views/shared/_merge_requests.html.haml b/app/views/shared/_merge_requests.html.haml index 935a7a7f7c0..5276f4bae31 100644 --- a/app/views/shared/_merge_requests.html.haml +++ b/app/views/shared/_merge_requests.html.haml @@ -1,5 +1,5 @@ - if @merge_requests.any? - - @merge_requests.group_by(&:project).each do |group| + - @merge_requests.group_by(&:target_project).each do |group| .ui-box - project = group[0] .title |