From ce2ca6646e98ac8a8a164ceb5191cdbee61cc8ec Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Fri, 22 Mar 2013 22:46:26 +0600 Subject: [PATCH] [#19] add issue references from commit --- .../projects/comments_controller.rb | 2 +- app/controllers/projects/issues_controller.rb | 1 + app/models/activity_feed_observer.rb | 3 +- app/models/comment.rb | 29 ++++- .../commit_as_message_presenter.rb | 94 +++++++++----- app/views/projects/comments/_list.html.haml | 8 +- app/views/projects/issues/_issue.html.haml | 2 +- config/locales/layout/commits.en.yml | 5 +- config/locales/layout/commits.ru.yml | 5 +- ...0130319172358_add_automatic_to_comments.rb | 5 + db/schema.rb | 117 +++++++++--------- 11 files changed, 172 insertions(+), 99 deletions(-) create mode 100644 db/migrate/20130319172358_add_automatic_to_comments.rb diff --git a/app/controllers/projects/comments_controller.rb b/app/controllers/projects/comments_controller.rb index e1f7f1073..587d33c9a 100644 --- a/app/controllers/projects/comments_controller.rb +++ b/app/controllers/projects/comments_controller.rb @@ -53,7 +53,7 @@ class Projects::CommentsController < Projects::BaseController end def find_or_build_comment - @comment = params[:id].present? && Comment.find(params[:id]) || + @comment = params[:id].present? && Comment.where(:automatic => false).find(params[:id]) || current_user.comments.build(params[:comment]) {|c| c.commentable = @commentable; c.project = @project} end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 03d5ca7b5..5fd88f38f 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -10,6 +10,7 @@ class Projects::IssuesController < Projects::BaseController layout false, :only => [:update, :search_collaborators] def index(status = 200) + @system_user = User.find_by_uname 'rosa_system' @labels = params[:labels] || [] @issues = @project.issues.without_pull_requests @issues = @issues.where(:assignee_id => current_user.id) if @is_assigned_to_me = params[:filter] == 'to_me' diff --git a/app/models/activity_feed_observer.rb b/app/models/activity_feed_observer.rb index 7fe598a20..f0dcb1e01 100644 --- a/app/models/activity_feed_observer.rb +++ b/app/models/activity_feed_observer.rb @@ -34,6 +34,7 @@ class ActivityFeedObserver < ActiveRecord::Observer end when 'Comment' + return if record.automatic if record.issue_comment? subscribes = record.commentable.subscribes subscribes.each do |subscribe| @@ -95,6 +96,7 @@ class ActivityFeedObserver < ActiveRecord::Observer commits = commits[0...-3] options.merge!({:other_commits_count => commits.count, :other_commits => "#{commits[0].sha[0..9]}...#{commits[-1].sha[0..9]}"}) end + Comment.create_link_on_issues_from_commits(record, last_commits) if last_commits.count > 0 end options.merge!({:user_id => record.user.id, :user_name => record.user.name, :user_email => record.user.email}) if record.user @@ -156,5 +158,4 @@ class ActivityFeedObserver < ActiveRecord::Observer end end end - end diff --git a/app/models/comment.rb b/app/models/comment.rb index 61a2d1200..d53d3dbf6 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,11 +1,12 @@ # -*- encoding : utf-8 -*- class Comment < ActiveRecord::Base - belongs_to :commentable, :polymorphic => true, :touch => true + belongs_to :commentable, :polymorphic => true belongs_to :user belongs_to :project serialize :data - validates :body, :user_id, :commentable_id, :commentable_type, :project_id, :presence => true + validates :body, :commentable_id, :commentable_type, :project_id, :presence => true + validates :user_id, :presence => true, :unless => lambda {|c| c.automatic} scope :for_commit, lambda {|c| where(:commentable_id => c.id.hex, :commentable_type => c.class)} default_scope order("#{table_name}.created_at") @@ -129,6 +130,30 @@ class Comment < ActiveRecord::Base return true end + def self.create_link_on_issues_from_commits git_hook, commits + system_user = User.find_by_uname 'rosa_system' + commits.each do |commit| + commit[1].scan(/(?:[a-zA-Z0-9\-_]*\/)?(?:[a-zA-Z0-9\-_]*)?#[0-9]+/).each do |hash| + hash =~ /([a-zA-Z0-9\-_]*\/)?([a-zA-Z0-9\-_]*)?#([0-9]+)/ + owner_uname = Regexp.last_match[1].presence || git_hook.project.owner.uname + project_name = Regexp.last_match[2].presence || git_hook.project.name + serial_id = Regexp.last_match[3] + project = Project.find_by_owner_and_name(owner_uname.chomp('/'), project_name) + next unless project + next unless Ability.new(git_hook.user).can? :read, project + issue = project.issues.where(:serial_id => serial_id).first + next unless issue + repo_commit = git_hook.project.repo.commit commit[0] + comment = system_user.comments.new :body => 'automatic comment' + comment.commentable = issue + comment.automatic = true + comment.project = project + comment.data = {:commit_project_id => git_hook.project.id, :commit_hash => commit[0]} + comment.save + end + end + end + protected def subscribe_on_reply diff --git a/app/presenters/git_presenters/commit_as_message_presenter.rb b/app/presenters/git_presenters/commit_as_message_presenter.rb index 1d2604f55..b6165a5cc 100644 --- a/app/presenters/git_presenters/commit_as_message_presenter.rb +++ b/app/presenters/git_presenters/commit_as_message_presenter.rb @@ -2,33 +2,55 @@ class GitPresenters::CommitAsMessagePresenter < ApplicationPresenter include CommitHelper - attr_accessor :commit, :options + attr_accessor :commit attr_reader :header, :image, :date, :caption, :content, :expandable def initialize(commit, opts = {}) - @commit = commit - @options = opts + comment = opts[:comment] + @issue_reference = !!comment # is it reference issue from commit + @project = if comment + Project.where(:id => opts[:comment].data[:commit_project_id]).first + else + opts[:project] + end + if @project + commit = commit || @project.repo.commit(comment.data[:commit_hash]) + + @committer = commit.committer + @commit_hash = commit.id + @committed_date, @authored_date = commit.committed_date, commit.authored_date + @commit_message = commit.message + else + @committer = t('layout.commits.unknown_committer') + @commit_hash = comment.data[:commit_hash] + @committed_date = @authored_date = comment.created_at + @commit_message = t('layout.commits.deleted') + end prepare_message end def header - @header ||= if options[:project].present? - I18n.t("layout.messages.commits.header", - :committer => committer_link, :commit => commit_link, :project => options[:project].name) - end.html_safe + @header ||= if @issue_reference + I18n.t('layout.commits.reference', :committer => committer_link, :commit => commit_link) + elsif @project.present? + I18n.t('layout.messages.commits.header', + :committer => committer_link, :commit => commit_link, :project => @project.name) + end.html_safe end def image - c = committer - @image ||= if c.class == User - helpers.avatar_url(c, :medium) + @image ||= if committer.is_a? User + helpers.avatar_url(committer, :medium) + elsif committer.is_a? Grit::Actor + helpers.avatar_url_by_email(committer.email, :medium) else - helpers.avatar_url_by_email(c.email, :medium) + size = User.new.avatar.styles[:medium].geometry.split('x').first + helpers.gravatar_url('email', size) end end def date - @date ||= I18n.l(@commit.committed_date || @commit.authored_date, :format => :long) + @date ||= I18n.l(@committed_date || @authored_date, :format => :long) end def expandable? @@ -53,31 +75,37 @@ class GitPresenters::CommitAsMessagePresenter < ApplicationPresenter protected - def committer - @committer ||= User.where(:email => @commit.committer.email).first || @commit.committer - end + def committer + @committer ||= User.where(:email => @commiter.email).first || @commiter + end - def committer_link - @committer_link ||= if committer.is_a? User - link_to committer.uname, user_path(committer) - else - mail_to committer.email, committer.name - end + def committer_link + @committer_link ||= if committer.is_a? User + link_to committer.uname, user_path(committer) + elsif committer.is_a? Grit::Actor + mail_to committer.email, committer.name + else # unknown committer + committer end + end - def commit_link - link_to shortest_hash_id(@commit.id), commit_path(options[:project], @commit.id) + def commit_link + if @project + link_to shortest_hash_id(@commit_hash), commit_path(@project, @commit_hash) + else + shortest_hash_id(@commit_hash) end + end - def prepare_message - (@caption, @content) = @commit.message.split("\n\n", 2) - @caption = 'empty message' unless @caption.present? - if @caption.length > 72 - tmp = '...' + @caption[69..-1] - @content = (@content.present?) ? tmp + @content : tmp - @caption = @caption[0..68] + '...' - end + def prepare_message + (@caption, @content) = @commit_message.split("\n\n", 2) + @caption = 'empty message' unless @caption.present? + if @caption.length > 72 + tmp = '...' + @caption[69..-1] + @content = (@content.present?) ? tmp + @content : tmp + @caption = @caption[0..68] + '...' + end # @content = @content.gsub("\n", "
").html_safe if @content - @content = simple_format(@content, {}, :sanitize => true).html_safe if @content - end + @content = simple_format(@content, {}, :sanitize => true).html_safe if @content + end end diff --git a/app/views/projects/comments/_list.html.haml b/app/views/projects/comments/_list.html.haml index e63505aa7..10678bdf3 100644 --- a/app/views/projects/comments/_list.html.haml +++ b/app/views/projects/comments/_list.html.haml @@ -1,6 +1,12 @@ %a{ :name => "comments" } .hr %h3#block-list= t("layout.comments.comments_header") +- counter = 1 - list.each do |comment| - = render 'projects/comments/comment', :comment => comment, :data => {:project => project, :commentable => commentable} + -if comment.automatic + - GitPresenters::CommitAsMessagePresenter.present(nil, :comment => comment) do |presenter| + = render 'shared/feed_message', :presenter => presenter, :item_no => counter + - counter += 1 + -else + = render 'projects/comments/comment', :comment => comment, :data => {:project => project, :commentable => commentable} = render "projects/comments/markdown_help" diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index 3d2d0025e..1279527ae 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -24,5 +24,5 @@ %a{:href => "#{path}#block-list"} .answers .pic= image_tag 'answers.png' - .count=issue.comments.count + .count=issue.comments.where(:automatic => false).count .both diff --git a/config/locales/layout/commits.en.yml b/config/locales/layout/commits.en.yml index 33b5b42c3..359d0f4d8 100644 --- a/config/locales/layout/commits.en.yml +++ b/config/locales/layout/commits.en.yml @@ -6,4 +6,7 @@ en: pluralize: commit: commit commits: commits - commits2: commits \ No newline at end of file + commits2: commits + reference: "%{committer} referenced this issue from a commit %{commit}" + deleted: Commit has since been removed from the git-repository and is no longer available. + unknown_committer: Unknown \ No newline at end of file diff --git a/config/locales/layout/commits.ru.yml b/config/locales/layout/commits.ru.yml index 3e88b0da3..4f3f5d4a8 100644 --- a/config/locales/layout/commits.ru.yml +++ b/config/locales/layout/commits.ru.yml @@ -6,4 +6,7 @@ ru: pluralize: commit: коммит commits: коммита - commits2: коммитов \ No newline at end of file + commits2: коммитов + reference: "%{committer} ссылается на данную задачу в коммите %{commit}" + deleted: Коммит был удален и более недоступен в git-репозитории. + unknown_committer: Неизвестный \ No newline at end of file diff --git a/db/migrate/20130319172358_add_automatic_to_comments.rb b/db/migrate/20130319172358_add_automatic_to_comments.rb new file mode 100644 index 000000000..50bab4dec --- /dev/null +++ b/db/migrate/20130319172358_add_automatic_to_comments.rb @@ -0,0 +1,5 @@ +class AddAutomaticToComments < ActiveRecord::Migration + def change + add_column :comments, :automatic, :boolean, :default => false + end +end diff --git a/db/schema.rb b/db/schema.rb index 625a20902..fe6518137 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,14 +11,14 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20130227102900) do +ActiveRecord::Schema.define(:version => 20130319172358) do create_table "activity_feeds", :force => true do |t| t.integer "user_id", :null => false t.string "kind" t.text "data" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "advisories", :force => true do |t| @@ -53,8 +53,8 @@ ActiveRecord::Schema.define(:version => 20130227102900) do create_table "arches", :force => true do |t| t.string "name", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "arches", ["name"], :name => "index_arches_on_name", :unique => true @@ -63,8 +63,8 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.integer "user_id" t.string "provider" t.string "uid" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "authentications", ["provider", "uid"], :name => "index_authentications_on_provider_and_uid", :unique => true @@ -75,8 +75,8 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.integer "level" t.integer "status" t.integer "build_list_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "version" end @@ -110,8 +110,8 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.integer "project_id" t.integer "arch_id" t.datetime "notified_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "is_circle", :default => false t.text "additional_repos" t.string "name" @@ -149,11 +149,12 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.string "commentable_type" t.integer "user_id" t.text "body" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.decimal "commentable_id", :precision => 50, :scale => 0 t.integer "project_id" t.text "data" + t.boolean "automatic", :default => false end create_table "event_logs", :force => true do |t| @@ -168,8 +169,8 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.string "controller" t.string "action" t.text "message" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "flash_notifies", :force => true do |t| @@ -183,8 +184,8 @@ ActiveRecord::Schema.define(:version => 20130227102900) do create_table "groups", :force => true do |t| t.integer "owner_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "uname" t.integer "own_projects_count", :default => 0, :null => false t.text "description" @@ -201,8 +202,8 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.string "title" t.text "body" t.string "status", :default => "open" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "user_id" t.datetime "closed_at" t.integer "closed_by" @@ -279,14 +280,14 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.string "description" t.string "name", :null => false t.integer "parent_platform_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "released", :default => false, :null => false t.integer "owner_id" t.string "owner_type" t.string "visibility", :default => "open", :null => false t.string "platform_type", :default => "main", :null => false - t.string "distrib_type" + t.string "distrib_type", :null => false end add_index "platforms", ["name"], :name => "index_platforms_on_name", :unique => true, :case_sensitive => false @@ -295,16 +296,16 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.integer "platform_id" t.string "login" t.string "password" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "user_id" end create_table "product_build_lists", :force => true do |t| t.integer "product_id" - t.integer "status", :default => 3, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.integer "status", :default => 2, :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "project_id" t.string "project_version" t.string "commit_hash" @@ -321,8 +322,8 @@ ActiveRecord::Schema.define(:version => 20130227102900) do create_table "products", :force => true do |t| t.string "name", :null => false t.integer "platform_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.text "description" t.integer "project_id" t.string "params" @@ -335,8 +336,8 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.string "name" t.string "version" t.datetime "file_mtime" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "platform_id" end @@ -355,27 +356,27 @@ ActiveRecord::Schema.define(:version => 20130227102900) do create_table "project_to_repositories", :force => true do |t| t.integer "project_id" t.integer "repository_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "project_to_repositories", ["repository_id", "project_id"], :name => "index_project_to_repositories_on_repository_id_and_project_id", :unique => true create_table "projects", :force => true do |t| t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "owner_id" t.string "owner_type" t.string "visibility", :default => "open" t.text "description" t.string "ancestry" t.boolean "has_issues", :default => true - t.boolean "has_wiki", :default => false t.string "srpm_file_name" - t.string "srpm_content_type" t.integer "srpm_file_size" t.datetime "srpm_updated_at" + t.string "srpm_content_type" + t.boolean "has_wiki", :default => false t.string "default_branch", :default => "master" t.boolean "is_package", :default => true, :null => false t.integer "average_build_time", :default => 0, :null => false @@ -406,8 +407,8 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.string "token" t.boolean "approved", :default => false t.boolean "rejected", :default => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "interest" t.text "more" t.string "language" @@ -421,16 +422,16 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.string "actor_type" t.integer "target_id" t.string "target_type" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "role" end create_table "repositories", :force => true do |t| t.string "description", :null => false t.integer "platform_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "name", :null => false t.boolean "publish_without_qa", :default => true end @@ -444,8 +445,8 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.boolean "new_comment_reply", :default => true t.boolean "new_issue", :default => true t.boolean "issue_assign", :default => true - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "new_comment_commit_owner", :default => true t.boolean "new_comment_commit_repo_owner", :default => true t.boolean "new_comment_commit_commentor", :default => true @@ -468,8 +469,8 @@ ActiveRecord::Schema.define(:version => 20130227102900) do create_table "subscribes", :force => true do |t| t.string "subscribeable_type" t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "status", :default => true t.integer "project_id" t.decimal "subscribeable_id", :precision => 50, :scale => 0 @@ -477,21 +478,18 @@ ActiveRecord::Schema.define(:version => 20130227102900) do create_table "users", :force => true do |t| t.string "name" - t.string "email", :default => "", :null => false - t.string "encrypted_password", :default => "", :null => false + t.string "email", :default => "", :null => false + t.string "encrypted_password", :limit => 128, :default => "", :null => false t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.text "ssh_key" t.string "uname" t.string "role" - t.string "language", :default => "en" - t.integer "own_projects_count", :default => 0, :null => false - t.string "confirmation_token" - t.datetime "confirmed_at" - t.datetime "confirmation_sent_at" + t.string "language", :default => "en" + t.integer "own_projects_count", :default => 0, :null => false t.text "professional_experience" t.string "site" t.string "company" @@ -500,11 +498,14 @@ ActiveRecord::Schema.define(:version => 20130227102900) do t.string "avatar_content_type" t.integer "avatar_file_size" t.datetime "avatar_updated_at" - t.integer "failed_attempts", :default => 0 + t.integer "failed_attempts", :default => 0 t.string "unlock_token" t.datetime "locked_at" + t.string "confirmation_token" + t.datetime "confirmed_at" + t.datetime "confirmation_sent_at" t.string "authentication_token" - t.integer "build_priority", :default => 50 + t.integer "build_priority", :default => 50 end add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token"