Commit 686f6855 authored by Robert Speicher's avatar Robert Speicher

Update SystemNoteService method naming conventions

Now the verb comes first, and there is no restriction on
singular/plural.
parent ff3a62aa
...@@ -2,17 +2,17 @@ class IssuableBaseService < BaseService ...@@ -2,17 +2,17 @@ class IssuableBaseService < BaseService
private private
def create_assignee_note(issuable) def create_assignee_note(issuable)
SystemNoteService.assignee_change( SystemNoteService.change_assignee(
issuable, issuable.project, current_user, issuable.assignee) issuable, issuable.project, current_user, issuable.assignee)
end end
def create_milestone_note(issuable) def create_milestone_note(issuable)
SystemNoteService.milestone_change( SystemNoteService.change_milestone(
issuable, issuable.project, current_user, issuable.milestone) issuable, issuable.project, current_user, issuable.milestone)
end end
def create_labels_note(issuable, added_labels, removed_labels) def create_labels_note(issuable, added_labels, removed_labels)
SystemNoteService.label_change( SystemNoteService.change_label(
issuable, issuable.project, current_user, added_labels, removed_labels) issuable, issuable.project, current_user, added_labels, removed_labels)
end end
end end
...@@ -14,7 +14,7 @@ module Issues ...@@ -14,7 +14,7 @@ module Issues
private private
def create_note(issue, current_commit) def create_note(issue, current_commit)
SystemNoteService.status_change(issue, issue.project, current_user, issue.state, current_commit) SystemNoteService.change_status(issue, issue.project, current_user, issue.state, current_commit)
end end
end end
end end
...@@ -14,7 +14,7 @@ module Issues ...@@ -14,7 +14,7 @@ module Issues
private private
def create_note(issue) def create_note(issue)
SystemNoteService.status_change(issue, issue.project, current_user, issue.state, nil) SystemNoteService.change_status(issue, issue.project, current_user, issue.state, nil)
end end
end end
end end
...@@ -2,7 +2,7 @@ module MergeRequests ...@@ -2,7 +2,7 @@ module MergeRequests
class BaseService < ::IssuableBaseService class BaseService < ::IssuableBaseService
def create_note(merge_request) def create_note(merge_request)
SystemNoteService.status_change(merge_request, merge_request.target_project, current_user, merge_request.state, nil) SystemNoteService.change_status(merge_request, merge_request.target_project, current_user, merge_request.state, nil)
end end
def hook_data(merge_request, action) def hook_data(merge_request, action)
......
...@@ -82,7 +82,7 @@ module MergeRequests ...@@ -82,7 +82,7 @@ module MergeRequests
mr_commit_ids.include?(commit.id) mr_commit_ids.include?(commit.id)
end end
SystemNoteService.commit_add(merge_request, merge_request.project, SystemNoteService.add_commits(merge_request, merge_request.project,
@current_user, new_commits, @current_user, new_commits,
existing_commits, @oldrev) existing_commits, @oldrev)
end end
......
...@@ -2,66 +2,48 @@ ...@@ -2,66 +2,48 @@
# #
# Used for creating system notes (e.g., when a user references a merge request # Used for creating system notes (e.g., when a user references a merge request
# from an issue, an issue's assignee changes, an issue is closed, etc.) # from an issue, an issue's assignee changes, an issue is closed, etc.)
#
# All methods creating notes should be named using a singular noun and
# present-tense verb (e.g., "assignee_change" not "assignee_changed",
# "label_change" not "labels_change").
class SystemNoteService class SystemNoteService
# Called when the assignee of a Noteable is changed or removed # Called when commits are added to a Merge Request
# #
# noteable - Noteable object # noteable - Noteable object
# project - Project owning noteable # project - Project owning noteable
# author - User performing the change # author - User performing the change
# assignee - User being assigned, or nil # new_commits - Array of Commits added since last push
# # existing_commits - Array of Commits added in a previous push
# Example Note text: # oldrev - TODO (rspeicher): I have no idea what this actually does
#
# "Assignee removed"
# #
# "Reassigned to @rspeicher" # See new_commit_summary and existing_commit_summary.
# #
# Returns the created Note object # Returns the created Note object
def self.assignee_change(noteable, project, author, assignee) def self.add_commits(noteable, project, author, new_commits, existing_commits = [], oldrev = nil)
body = assignee.nil? ? 'Assignee removed' : "Reassigned to @#{assignee.username}" total_count = new_commits.length + existing_commits.length
commits_text = "#{total_count} commit".pluralize(total_count)
body = "Added #{commits_text}:\n\n"
body << existing_commit_summary(noteable, existing_commits, oldrev)
body << new_commit_summary(new_commits).join("\n")
create_note(noteable: noteable, project: project, author: author, note: body) create_note(noteable: noteable, project: project, author: author, note: body)
end end
# Called when a Mentionable references a Noteable # Called when the assignee of a Noteable is changed or removed
# #
# noteable - Noteable object being referenced # noteable - Noteable object
# mentioner - Mentionable object # project - Project owning noteable
# author - User performing the reference # author - User performing the change
# assignee - User being assigned, or nil
# #
# Example Note text: # Example Note text:
# #
# "Mentioned in #1" # "Assignee removed"
#
# "Mentioned in !2"
#
# "Mentioned in 54f7727c"
# #
# See cross_reference_note_content. # "Reassigned to @rspeicher"
# #
# Returns the created Note object # Returns the created Note object
def self.cross_reference(noteable, mentioner, author) def self.change_assignee(noteable, project, author, assignee)
return if cross_reference_disallowed?(noteable, mentioner) body = assignee.nil? ? 'Assignee removed' : "Reassigned to @#{assignee.username}"
gfm_reference = mentioner_gfm_ref(noteable, mentioner)
note_options = {
project: noteable.project,
author: author,
note: cross_reference_note_content(gfm_reference)
}
if noteable.kind_of?(Commit)
note_options.merge!(noteable_type: 'Commit', commit_id: noteable.id)
else
note_options.merge!(noteable: noteable)
end
create_note(note_options) create_note(noteable: noteable, project: project, author: author, note: body)
end end
# Called when one or more labels on a Noteable are added and/or removed # Called when one or more labels on a Noteable are added and/or removed
...@@ -81,7 +63,7 @@ class SystemNoteService ...@@ -81,7 +63,7 @@ class SystemNoteService
# "Removed ~5 label" # "Removed ~5 label"
# #
# Returns the created Note object # Returns the created Note object
def self.label_change(noteable, project, author, added_labels, removed_labels) def self.change_label(noteable, project, author, added_labels, removed_labels)
labels_count = added_labels.count + removed_labels.count labels_count = added_labels.count + removed_labels.count
references = ->(label) { "~#{label.id}" } references = ->(label) { "~#{label.id}" }
...@@ -119,36 +101,13 @@ class SystemNoteService ...@@ -119,36 +101,13 @@ class SystemNoteService
# "Miletone changed to 7.11" # "Miletone changed to 7.11"
# #
# Returns the created Note object # Returns the created Note object
def self.milestone_change(noteable, project, author, milestone) def self.change_milestone(noteable, project, author, milestone)
body = 'Milestone ' body = 'Milestone '
body += milestone.nil? ? 'removed' : "changed to #{milestone.title}" body += milestone.nil? ? 'removed' : "changed to #{milestone.title}"
create_note(noteable: noteable, project: project, author: author, note: body) create_note(noteable: noteable, project: project, author: author, note: body)
end end
# Called when commits are added to a Merge Request
#
# noteable - Noteable object
# project - Project owning noteable
# author - User performing the change
# new_commits - Array of Commits added since last push
# existing_commits - Array of Commits added in a previous push
# oldrev - TODO (rspeicher): I have no idea what this actually does
#
# See new_commit_summary and existing_commit_summary.
#
# Returns the created Note object
def self.commit_add(noteable, project, author, new_commits, existing_commits = [], oldrev = nil)
total_count = new_commits.length + existing_commits.length
commits_text = "#{total_count} commit".pluralize(total_count)
body = "Added #{commits_text}:\n\n"
body << existing_commit_summary(noteable, existing_commits, oldrev)
body << new_commit_summary(new_commits).join("\n")
create_note(noteable: noteable, project: project, author: author, note: body)
end
# Called when the status of a Noteable is changed # Called when the status of a Noteable is changed
# #
# noteable - Noteable object # noteable - Noteable object
...@@ -164,13 +123,50 @@ class SystemNoteService ...@@ -164,13 +123,50 @@ class SystemNoteService
# "Status changed to closed by bc17db76" # "Status changed to closed by bc17db76"
# #
# Returns the created Note object # Returns the created Note object
def self.status_change(noteable, project, author, status, source) def self.change_status(noteable, project, author, status, source)
body = "Status changed to #{status}" body = "Status changed to #{status}"
body += " by #{source.gfm_reference}" if source body += " by #{source.gfm_reference}" if source
create_note(noteable: noteable, project: project, author: author, note: body) create_note(noteable: noteable, project: project, author: author, note: body)
end end
# Called when a Mentionable references a Noteable
#
# noteable - Noteable object being referenced
# mentioner - Mentionable object
# author - User performing the reference
#
# Example Note text:
#
# "Mentioned in #1"
#
# "Mentioned in !2"
#
# "Mentioned in 54f7727c"
#
# See cross_reference_note_content.
#
# Returns the created Note object
def self.cross_reference(noteable, mentioner, author)
return if cross_reference_disallowed?(noteable, mentioner)
gfm_reference = mentioner_gfm_ref(noteable, mentioner)
note_options = {
project: noteable.project,
author: author,
note: cross_reference_note_content(gfm_reference)
}
if noteable.kind_of?(Commit)
note_options.merge!(noteable_type: 'Commit', commit_id: noteable.id)
else
note_options.merge!(noteable: noteable)
end
create_note(note_options)
end
def self.cross_reference?(note_text) def self.cross_reference?(note_text)
note_text.start_with?(cross_reference_note_prefix) note_text.start_with?(cross_reference_note_prefix)
end end
......
...@@ -23,95 +23,110 @@ describe SystemNoteService do ...@@ -23,95 +23,110 @@ describe SystemNoteService do
end end
end end
describe '.assignee_change' do describe '.add_commits' do
let(:assignee) { create(:user) } let(:noteable) { create(:merge_request, source_project: project) }
let(:new_commits) { noteable.commits }
let(:old_commits) { [] }
let(:oldrev) { nil }
subject { described_class.assignee_change(noteable, project, author, assignee) } subject { described_class.add_commits(noteable, project, author, new_commits, old_commits, oldrev) }
it_behaves_like 'a system note' it_behaves_like 'a system note'
context 'when assignee added' do describe 'note body' do
it 'sets the note text' do let(:note_lines) { subject.note.split("\n").reject(&:blank?) }
expect(subject.note).to eq "Reassigned to @#{assignee.username}"
end
end
context 'when assignee removed' do context 'without existing commits' do
let(:assignee) { nil } it 'adds a message header' do
expect(note_lines[0]).to eq "Added #{new_commits.size} commits:"
end
it 'sets the note text' do it 'adds a message line for each commit' do
expect(subject.note).to eq 'Assignee removed' new_commits.each_with_index do |commit, i|
# Skip the header
expect(note_lines[i + 1]).to eq "* #{commit.short_id} - #{commit.title}"
end end
end end
end end
describe '.cross_reference' do describe 'summary line for existing commits' do
let(:mentioner) { create(:issue, project: project) } let(:summary_line) { note_lines[1] }
subject { described_class.cross_reference(noteable, mentioner, author) } context 'with one existing commit' do
let(:old_commits) { [noteable.commits.last] }
it_behaves_like 'a system note' it 'includes the existing commit' do
expect(summary_line).to eq "* #{old_commits.first.short_id} - 1 commit from branch `feature`"
end
end
context 'when cross-reference disallowed' do context 'with multiple existing commits' do
before do let(:old_commits) { noteable.commits[3..-1] }
expect(described_class).to receive(:cross_reference_disallowed?).and_return(true)
context 'with oldrev' do
let(:oldrev) { noteable.commits[2].id }
it 'includes a commit range' do
expect(summary_line).to start_with "* #{Commit.truncate_sha(oldrev)}...#{old_commits.last.short_id}"
end end
it 'returns nil' do it 'includes a commit count' do
expect(subject).to be_nil expect(summary_line).to end_with " - 2 commits from branch `feature`"
end end
end end
context 'when cross-reference allowed' do context 'without oldrev' do
before do it 'includes a commit range' do
expect(described_class).to receive(:cross_reference_disallowed?).and_return(false) expect(summary_line).to start_with "* #{old_commits[0].short_id}..#{old_commits[-1].short_id}"
end end
describe 'note_body' do it 'includes a commit count' do
context 'cross-project' do expect(summary_line).to end_with " - 2 commits from branch `feature`"
let(:project2) { create(:project) } end
let(:mentioner) { create(:issue, project: project2) } end
context 'from Commit' do context 'on a fork' do
let(:mentioner) { project2.repository.commit } before do
expect(noteable).to receive(:for_fork?).and_return(true)
end
it 'references the mentioning commit' do it 'includes the project namespace' do
expect(subject.note).to eq "mentioned in commit #{project2.path_with_namespace}@#{mentioner.id}" expect(summary_line).to end_with "`#{noteable.target_project_namespace}:feature`"
end
end end
end end
context 'from non-Commit' do
it 'references the mentioning object' do
expect(subject.note).to eq "mentioned in issue #{project2.path_with_namespace}##{mentioner.iid}"
end end
end end
end end
context 'same project' do describe '.change_assignee' do
context 'from Commit' do let(:assignee) { create(:user) }
let(:mentioner) { project.repository.commit }
it 'references the mentioning commit' do subject { described_class.change_assignee(noteable, project, author, assignee) }
expect(subject.note).to eq "mentioned in commit #{mentioner.id}"
end
end
context 'from non-Commit' do it_behaves_like 'a system note'
it 'references the mentioning object' do
expect(subject.note).to eq "mentioned in issue ##{mentioner.iid}" context 'when assignee added' do
end it 'sets the note text' do
expect(subject.note).to eq "Reassigned to @#{assignee.username}"
end end
end end
context 'when assignee removed' do
let(:assignee) { nil }
it 'sets the note text' do
expect(subject.note).to eq 'Assignee removed'
end end
end end
end end
describe '.label_change' do describe '.change_label' do
let(:labels) { create_list(:label, 2) } let(:labels) { create_list(:label, 2) }
let(:added) { [] } let(:added) { [] }
let(:removed) { [] } let(:removed) { [] }
subject { described_class.label_change(noteable, project, author, added, removed) } subject { described_class.change_label(noteable, project, author, added, removed) }
it_behaves_like 'a system note' it_behaves_like 'a system note'
...@@ -143,10 +158,10 @@ describe SystemNoteService do ...@@ -143,10 +158,10 @@ describe SystemNoteService do
end end
end end
describe '.milestone_change' do describe '.change_milestone' do
let(:milestone) { create(:milestone, project: project) } let(:milestone) { create(:milestone, project: project) }
subject { described_class.milestone_change(noteable, project, author, milestone) } subject { described_class.change_milestone(noteable, project, author, milestone) }
it_behaves_like 'a system note' it_behaves_like 'a system note'
...@@ -165,101 +180,86 @@ describe SystemNoteService do ...@@ -165,101 +180,86 @@ describe SystemNoteService do
end end
end end
describe '.commit_add' do describe '.change_status' do
let(:noteable) { create(:merge_request, source_project: project) } let(:status) { 'new_status' }
let(:new_commits) { noteable.commits } let(:source) { nil }
let(:old_commits) { [] }
let(:oldrev) { nil }
subject { described_class.commit_add(noteable, project, author, new_commits, old_commits, oldrev) } subject { described_class.change_status(noteable, project, author, status, source) }
it_behaves_like 'a system note' it_behaves_like 'a system note'
describe 'note body' do context 'with a source' do
let(:note_lines) { subject.note.split("\n").reject(&:blank?) } let(:source) { double('commit', gfm_reference: 'commit 123456') }
context 'without existing commits' do it 'sets the note text' do
it 'adds a message header' do expect(subject.note).to eq "Status changed to #{status} by commit 123456"
expect(note_lines[0]).to eq "Added #{new_commits.size} commits:" end
end end
it 'adds a message line for each commit' do context 'without a source' do
new_commits.each_with_index do |commit, i| it 'sets the note text' do
# Skip the header expect(subject.note).to eq "Status changed to #{status}"
expect(note_lines[i + 1]).to eq "* #{commit.short_id} - #{commit.title}"
end end
end end
end end
describe 'summary line for existing commits' do describe '.cross_reference' do
let(:summary_line) { note_lines[1] } let(:mentioner) { create(:issue, project: project) }
context 'with one existing commit' do
let(:old_commits) { [noteable.commits.last] }
it 'includes the existing commit' do
expect(summary_line).to eq "* #{old_commits.first.short_id} - 1 commit from branch `feature`"
end
end
context 'with multiple existing commits' do subject { described_class.cross_reference(noteable, mentioner, author) }
let(:old_commits) { noteable.commits[3..-1] }
context 'with oldrev' do it_behaves_like 'a system note'
let(:oldrev) { noteable.commits[2].id }
it 'includes a commit range' do context 'when cross-reference disallowed' do
expect(summary_line).to start_with "* #{Commit.truncate_sha(oldrev)}...#{old_commits.last.short_id}" before do
expect(described_class).to receive(:cross_reference_disallowed?).and_return(true)
end end
it 'includes a commit count' do it 'returns nil' do
expect(summary_line).to end_with " - 2 commits from branch `feature`" expect(subject).to be_nil
end end
end end
context 'without oldrev' do context 'when cross-reference allowed' do
it 'includes a commit range' do before do
expect(summary_line).to start_with "* #{old_commits[0].short_id}..#{old_commits[-1].short_id}" expect(described_class).to receive(:cross_reference_disallowed?).and_return(false)
end end
it 'includes a commit count' do describe 'note_body' do
expect(summary_line).to end_with " - 2 commits from branch `feature`" context 'cross-project' do
end let(:project2) { create(:project) }
end let(:mentioner) { create(:issue, project: project2) }
context 'on a fork' do context 'from Commit' do
before do let(:mentioner) { project2.repository.commit }
expect(noteable).to receive(:for_fork?).and_return(true)
end
it 'includes the project namespace' do it 'references the mentioning commit' do
expect(summary_line).to end_with "`#{noteable.target_project_namespace}:feature`" expect(subject.note).to eq "mentioned in commit #{project2.path_with_namespace}@#{mentioner.id}"
end
end end
end end
context 'from non-Commit' do
it 'references the mentioning object' do
expect(subject.note).to eq "mentioned in issue #{project2.path_with_namespace}##{mentioner.iid}"
end end
end end
end end
describe '.status_change' do context 'same project' do
let(:status) { 'new_status' } context 'from Commit' do
let(:source) { nil } let(:mentioner) { project.repository.commit }
subject { described_class.status_change(noteable, project, author, status, source) }
it_behaves_like 'a system note'
context 'with a source' do
let(:source) { double('commit', gfm_reference: 'commit 123456') }
it 'sets the note text' do it 'references the mentioning commit' do
expect(subject.note).to eq "Status changed to #{status} by commit 123456" expect(subject.note).to eq "mentioned in commit #{mentioner.id}"
end end
end end
context 'without a source' do context 'from non-Commit' do
it 'sets the note text' do it 'references the mentioning object' do
expect(subject.note).to eq "Status changed to #{status}" expect(subject.note).to eq "mentioned in issue ##{mentioner.iid}"
end
end
end
end end
end end
end end
...@@ -274,6 +274,7 @@ describe SystemNoteService do ...@@ -274,6 +274,7 @@ describe SystemNoteService do
end end
end end
# TODO (rspeicher)
describe '.cross_reference_disallowed?' describe '.cross_reference_disallowed?'
describe '.cross_reference_exists?' do describe '.cross_reference_exists?' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment