Merge pull request #95 from abf/rosa-build:19-improvements

[#19] improvements for the reference
This commit is contained in:
warpc 2013-04-10 15:50:44 +04:00
commit d9dba145de
12 changed files with 136 additions and 96 deletions

View File

@ -41,6 +41,7 @@ class ActivityFeedObserver < ActiveRecord::Observer
:project_id => record.project.id, :issue_title => record.title, :project_name => record.project.name, :project_owner => record.project.owner.uname}
)
end
Comment.create_link_on_issues_from_item(record)
when 'Comment'
return if record.automatic
@ -145,7 +146,8 @@ class ActivityFeedObserver < ActiveRecord::Observer
:project_id => record.project.id, :project_name => record.project.name, :project_owner => record.project.owner.uname}
)
end
# dont remove outdated issues link
Comment.create_link_on_issues_from_item(record)
when 'BuildList'
if record.mass_build.blank? && ( # Do not show mass build activity in activity feeds
record.status_changed? && BUILD_LIST_STATUSES.include?(record.status) ||

View File

@ -4,7 +4,7 @@ class Comment < ActiveRecord::Base
# User/Project#Num
# User#Num
# #Num
ISSUES_REGEX = /(?:[a-zA-Z0-9\-_]*\/)?(?:[a-zA-Z0-9\-_]*)?[#!][0-9]+/
ISSUES_REGEX = /(?:[a-zA-Z0-9\-_]*\/)?(?:[a-zA-Z0-9\-_]*)?#[0-9]+/
belongs_to :commentable, :polymorphic => true, :touch => true
belongs_to :user
@ -137,49 +137,47 @@ class Comment < ActiveRecord::Base
def self.create_link_on_issues_from_item item, commits = nil
linker = item.user
elements = if item.is_a? Comment
[[item, item.body]]
elsif item.is_a? GitHook
commits
end
current_ability = Ability.new(linker)
case
when item.is_a?(GitHook)
elements = commits
when item.is_a?(Issue)
elements = [[item, item.title], [item, item.body]]
opts = {:created_from_issue_id => item.id}
when item.commentable_type == 'Issue'
elements = [[item, item.body]]
opts = {:created_from_issue_id => item.commentable_id}
when item.commentable_type == 'Grit::Commit'
elements = [[item, item.body]]
opts = {:created_from_commit_hash => item.commentable_id}
else
raise "Unsupported item type #{item.class.name}!"
end
elements.each do |element|
element[1].scan(ISSUES_REGEX).each do |hash|
delimiter = if hash.include? '!'
'!'
elsif hash.include? '#'
'#'
else
raise 'Unknown delimiter for the hash tag!'
end
issue = Issue.find_by_hash_tag hash, current_ability, item.project, delimiter
issue = Issue.find_by_hash_tag hash, current_ability, item.project
next unless issue
# dont create link to the same issue
next if item.respond_to?(:commentable) && issue == item.try(:commentable)
find_dup = {:automatic => true, :commentable_type => issue.class.name, :commentable_id => issue.id}
if item.is_a? GitHook
find_dup.merge! :created_from_commit_hash => element[0].hex
elsif item.commentable_type == 'Issue'
find_dup.merge! :created_from_issue_id => item.commentable_id
elsif item.commentable_type == 'Grit::Commit'
find_dup.merge! :created_from_commit_hash => item.commentable_id
next if opts[:created_from_issue_id] == issue.id
# dont create duplicate link to issue
next if Comment.find_existing_automatic_comment issue, opts
if item.is_a?(GitHook)
opts = {:created_from_commit_hash => element[0].hex}
# dont create link to outdated commit
next if !item.project.repo.commit(element[0])
end
next if Comment.exists? find_dup # dont create duplicate link to issue
comment = linker.comments.new :body => 'automatic comment'
comment.commentable, comment.project, comment.automatic = issue, issue.project, true
comment.data = {:from_project_id => item.project.id}
if item.is_a? GitHook
next unless item.project.repo.commit element[0]
comment.created_from_commit_hash = element[0].hex
if opts[:created_from_commit_hash]
comment.created_from_commit_hash = opts[:created_from_commit_hash]
elsif opts[:created_from_issue_id]
comment.data.merge!(:comment_id => item.id) if item.is_a? Comment
comment.created_from_issue_id = opts[:created_from_issue_id]
else
comment.data.merge! :comment_id => item.id
if item.commentable_type == 'Issue'
comment.created_from_issue_id = item.commentable_id
elsif item.commentable_type == 'Grit::Commit'
comment.created_from_commit_hash = item.commentable_id
end
raise 'Unsupported opts for automatic comment!'
end
comment.save
end
@ -204,4 +202,10 @@ class Comment < ActiveRecord::Base
end
end
end
def self.find_existing_automatic_comment issue, opts
find_dup = opts.merge(:automatic => true, :commentable_type => issue.class.name,
:commentable_id => issue.id)
Comment.exists? find_dup
end
end

View File

@ -51,6 +51,10 @@ class Group < Avatar
false
end
def fullname
return description.present? ? "#{uname} (#{description})" : uname
end
protected
def add_owner_to_members

View File

@ -67,8 +67,8 @@ class Issue < ActiveRecord::Base
recipients
end
def self.find_by_hash_tag hash_tag, current_ability, project, delimiter = '#'
hash_tag =~ /([a-zA-Z0-9\-_]*\/)?([a-zA-Z0-9\-_]*)?#{delimiter}([0-9]+)/
def self.find_by_hash_tag hash_tag, current_ability, project
hash_tag =~ /([a-zA-Z0-9\-_]*\/)?([a-zA-Z0-9\-_]*)?#([0-9]+)/
owner_uname = Regexp.last_match[1].presence || Regexp.last_match[2].presence || project.owner.uname
project_name = Regexp.last_match[1] ? Regexp.last_match[2] : project.name
serial_id = Regexp.last_match[3]

View File

@ -3,7 +3,8 @@ class CommentPresenter < ApplicationPresenter
include PullRequestHelper
attr_accessor :comment, :options
attr_reader :header, :image, :date, :caption, :content, :buttons, :is_reference_to_issue
attr_reader :header, :image, :date, :caption, :content, :buttons, :is_reference_to_issue,
:reference_project
def initialize(comment, opts = {})
@is_reference_to_issue = !!(comment.automatic && comment.created_from_issue_id) # is it reference issue from another issue
@ -14,7 +15,7 @@ class CommentPresenter < ApplicationPresenter
else
issue = Issue.where(:id => comment.created_from_issue_id).first
@referenced_issue = issue.pull_request || issue
if issue && Comment.exists?(comment.data[:comment_id])
if issue && (comment.data[:comment_id].nil? || Comment.exists?(comment.data[:comment_id]))
title = if issue == opts[:commentable]
"#{issue.serial_id}"
elsif issue.project.owner == opts[:commentable].project.owner
@ -110,4 +111,8 @@ class CommentPresenter < ApplicationPresenter
pull_status_label @referenced_issue
end.html_safe
end
def reference_project
@referenced_issue.project
end
end

View File

@ -3,13 +3,14 @@ class GitPresenters::CommitAsMessagePresenter < ApplicationPresenter
include CommitHelper
attr_accessor :commit
attr_reader :header, :image, :date, :caption, :content, :expandable, :is_reference_to_issue, :committer
attr_reader :header, :image, :date, :caption, :content, :expandable,
:is_reference_to_issue, :committer, :reference_project
def initialize(commit, opts = {})
comment = opts[:comment]
@is_reference_to_issue = !!comment # is it reference issue from commit
@project = if comment
Project.where(:id => opts[:comment].data[:from_project_id]).first
Project.where(:id => comment.data[:from_project_id]).first
else
opts[:project]
end
@ -76,6 +77,10 @@ class GitPresenters::CommitAsMessagePresenter < ApplicationPresenter
false
end
def reference_project
@project
end
protected
def committer_link

View File

@ -1,3 +1,4 @@
-if !presenter.is_reference_to_issue || can?(:show, presenter.reference_project)
.activity{:id => presenter.comment_id? ? presenter.comment_anchor : ''}
.top
- if presenter.buttons?

View File

@ -29,10 +29,10 @@ en:
reference_format: Reference Format
reference_format_example: |
for members: @abf
for issues:
#123 abf#123 abf/rosa-build#123
for pull requests:
!123 abf!123 abf/rosa-build!123
for issues and pull requests:
#123
abf#123
abf/rosa-build#123
for commits: 123456
issues: Issues

View File

@ -29,10 +29,10 @@ ru:
reference_format: Формат ссылок
reference_format_example: |
для участников: @abf
для задач:
#123 abf#123 abf/rosa-build#123
для пул реквестов:
!123 abf!123 abf/rosa-build!123
для задач и пул реквестов:
#123
abf#123
abf/rosa-build#123
для коммитов: 123456
issues: Задачи
pull_requests: Пул реквесты

View File

@ -9,14 +9,10 @@ module Modules
#
# Supported reference formats are:
# * @foo for team members
# * for issues:
# * for issues & pull requests:
# * #123
# * abf#123
# * abf/rosa-build#123
# * for pull requests:
# * !123
# * abf!123
# * abf/rosa-build!123
# * 123456 for commits
#
# It also parses Emoji codes to insert images. See
@ -104,15 +100,14 @@ module Modules
REFERENCE_PATTERN = %r{
(?<prefix>[\W\/])? # Prefix
( # Reference
@(?<user>[a-zA-Z][a-zA-Z0-9_\-\.]*) # User uname
@(?<user>[a-zA-Z][a-zA-Z0-9_\-\.]*) # User/Group uname
|(?<issue>(?:[a-zA-Z0-9\-_]*\/)?(?:[a-zA-Z0-9\-_]*)?\#[0-9]+) # Issue ID
|(?<pull_request>(?:[a-zA-Z0-9\-_]*\/)?(?:[a-zA-Z0-9\-_]*)?\![0-9]+) # PR ID
|(?<commit>[\h]{6,40}) # Commit ID
)
(?<suffix>\W)? # Suffix
}x.freeze
TYPES = [:user, :issue, :pull_request, :commit].freeze
TYPES = [:user, :issue, :commit].freeze
def parse_references(text)
# parse reference links
@ -166,24 +161,22 @@ module Modules
end
def reference_user(identifier)
if member = @project.all_members.select {|u| u.uname == identifier} #.joins(:user).where(users: {uname: identifier}).first
link_to("@#{identifier}", user_path(identifier), html_options.merge(class: "gfm gfm-team_member #{html_options[:class]}")) if member
member = User.where(uname: identifier).first || Group.where(uname: identifier).first
if member
link_to("@#{identifier}", "/#{identifier}", html_options.merge(title: member.fullname, class: "gfm gfm-member #{html_options[:class]}"))
end
end
def reference_issue(identifier)
if issue = Issue.find_by_hash_tag(identifier, current_ability, @project)
url = project_issue_path(issue.project.owner, issue.project.name, issue.serial_id)
title = "#{Issue.model_name.human}: #{issue.title}"
link_to(identifier, url, html_options.merge(title: title, class: "gfm gfm-issue #{html_options[:class]}"))
end
end
def reference_pull_request(identifier)
issue = Issue.find_by_hash_tag(identifier, current_ability, @project, '!')
if pull_request = issue.pull_request
if issue.pull_request
title = "#{PullRequest.model_name.human}: #{pull_request.title}"
link_to(identifier, project_pull_request_path(pull_request.to_project, pull_request), html_options.merge(title: title, class: "gfm gfm-pull_request #{html_options[:class]}"))
project_pull_request_path(pull_request.to_project, pull_request)
else
title = "#{Issue.model_name.human}: #{issue.title}"
url = project_issue_path(issue.project.owner, issue.project.name, issue.serial_id)
end
link_to(identifier, url, html_options.merge(title: title, class: "gfm gfm-issue #{html_options[:class]}"))
end
end

View File

@ -22,7 +22,7 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
code_class = "class=\"#{language.downcase}\"" if language.present?
<<-HTML
<pre><code #{code_class}">#{code}</code></pre>
<pre><code #{code_class}>#{code}</code></pre>
HTML
end

View File

@ -160,6 +160,7 @@ describe Comment do
:commentable_id => @second_issue.id,
:created_from_issue_id => @issue.id).count.should == 1
end
it 'should create two automatic comment' do
body = "test ##{@second_issue.serial_id}" +
" && [#{@another_project.name_with_owner}##{@issue_in_another_project.serial_id}]"
@ -167,6 +168,31 @@ describe Comment do
Comment.where(:automatic => true,
:created_from_issue_id => @issue.id).count.should == 2
end
it 'should create automatic comment by issue title' do
issue = FactoryGirl.create(:issue, :project => @project, :user => @user,
:title => "link to ##{@issue.serial_id}")
Comment.where(:automatic => true,
:created_from_issue_id => issue.id).count.should == 1
end
it 'should create automatic comment from issue body' do
issue = FactoryGirl.create(:issue, :project => @project, :user => @user,
:body => "link to ##{@issue.serial_id}")
Comment.where(:automatic => true,
:created_from_issue_id => issue.id).count.should == 1
end
it 'should create only one automatic comment from issue title and body' do
issue = FactoryGirl.create(:issue, :project => @project, :user => @user,
:title => "link to ##{@issue.serial_id} in title",
:body => "link to ##{@issue.serial_id} in body")
Comment.where(:automatic => true,
:created_from_issue_id => issue.id).count.should == 1
end
end
end
end