Merge branch 'master' of abf.rosalinux.ru:abf/rosa-build

This commit is contained in:
Vladmir Sharhsov(warpc) 2013-04-10 15:50:57 +04:00
commit 7fd8764ca8
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} :project_id => record.project.id, :issue_title => record.title, :project_name => record.project.name, :project_owner => record.project.owner.uname}
) )
end end
Comment.create_link_on_issues_from_item(record)
when 'Comment' when 'Comment'
return if record.automatic 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} :project_id => record.project.id, :project_name => record.project.name, :project_owner => record.project.owner.uname}
) )
end end
# dont remove outdated issues link
Comment.create_link_on_issues_from_item(record)
when 'BuildList' when 'BuildList'
if record.mass_build.blank? && ( # Do not show mass build activity in activity feeds if record.mass_build.blank? && ( # Do not show mass build activity in activity feeds
record.status_changed? && BUILD_LIST_STATUSES.include?(record.status) || record.status_changed? && BUILD_LIST_STATUSES.include?(record.status) ||

View File

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

View File

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

View File

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

View File

@ -3,7 +3,8 @@ class CommentPresenter < ApplicationPresenter
include PullRequestHelper include PullRequestHelper
attr_accessor :comment, :options 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 = {}) def initialize(comment, opts = {})
@is_reference_to_issue = !!(comment.automatic && comment.created_from_issue_id) # is it reference issue from another issue @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 else
issue = Issue.where(:id => comment.created_from_issue_id).first issue = Issue.where(:id => comment.created_from_issue_id).first
@referenced_issue = issue.pull_request || issue @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] title = if issue == opts[:commentable]
"#{issue.serial_id}" "#{issue.serial_id}"
elsif issue.project.owner == opts[:commentable].project.owner elsif issue.project.owner == opts[:commentable].project.owner
@ -110,4 +111,8 @@ class CommentPresenter < ApplicationPresenter
pull_status_label @referenced_issue pull_status_label @referenced_issue
end.html_safe end.html_safe
end end
def reference_project
@referenced_issue.project
end
end end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -160,6 +160,7 @@ describe Comment do
:commentable_id => @second_issue.id, :commentable_id => @second_issue.id,
:created_from_issue_id => @issue.id).count.should == 1 :created_from_issue_id => @issue.id).count.should == 1
end end
it 'should create two automatic comment' do it 'should create two automatic comment' do
body = "test ##{@second_issue.serial_id}" + body = "test ##{@second_issue.serial_id}" +
" && [#{@another_project.name_with_owner}##{@issue_in_another_project.serial_id}]" " && [#{@another_project.name_with_owner}##{@issue_in_another_project.serial_id}]"
@ -167,6 +168,31 @@ describe Comment do
Comment.where(:automatic => true, Comment.where(:automatic => true,
:created_from_issue_id => @issue.id).count.should == 2 :created_from_issue_id => @issue.id).count.should == 2
end 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 end
end end