Merge branch 'master' into 706-get-list-of-projects-by-repository

This commit is contained in:
Vokhmin Alexey V 2012-10-19 18:51:11 +04:00
commit e9fd2a2df6
54 changed files with 977 additions and 329 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1,17 +1,19 @@
$(document).ready(function() {
$('.buttons a.edit_comment').live('click', function() {
$(this).parent().parent().parent().hide();
$('#open-comment'+'.comment.'+$(this).attr('id')).show();
var new_comment = $('#open-comment.comment.hidden.new_line_comment');
$(document).on('click', '.buttons a.edit_comment', function() {
$(this).parents('div.activity').hide()
.next().show();
return false;
});
$('.cancel_edit_comment.button').live('click', function() {
$(this).parent().parent().parent().hide();
$('.buttons a.edit_comment#'+$(this).attr('id')).parent().parent().parent().show();
$(document).on('click', '.cancel_edit_comment.button', function() {
$(this).parents('#open-comment.comment').hide()
.prev().show();
return false;
});
$('form.edit_comment').live('submit', function() {
$(document).on('submit', 'form.edit_comment', function() {
var form = $(this);
form.parent().find('.flash').remove();
$.ajax({
@ -20,8 +22,9 @@ $(document).ready(function() {
data: form.serialize(),
success: function(data){
var cancel_button = form.find('.cancel_edit_comment.button');
var id = cancel_button.attr('id').match(/\d+$/)[0];
cancel_button.click();
$('.buttons a.edit_comment#'+cancel_button.attr('id')).parent().parent().find('.cm-s-default.md_and_cm').html(data).find('code').each(function (code) { CodeMirrorRun(this); })
$('#comment'+id+', #diff-comment'+id).parent().find('.cm-s-default.md_and_cm').html(data).find('code').each(function (code) { CodeMirrorRun(this); })
},
error: function(data){
form.before(data.responseText);
@ -30,5 +33,69 @@ $(document).ready(function() {
return false;
});
$('.new_inline_comment.button').on('click', function() {
$(this).parents('tr').prev('tr').find("a[href='"+$(this).attr('href')+"']").click();
return false;
});
$('.add_line-comment').on('click', function() {
function ProcessData(data) {
if(yield) {
var str = "<tr class='inline-comments'><td class='line_numbers' colspan='2'></td>"+"<td>"+data+"</td></tr>";
par.after(str);
par = par.next();
}
else {
par.find('td:last').append(data);
}
par.find('#md_tabs.nav.nav-tabs').each(function(i) {
$(this).find('a:first').tab('show');
$(this).parent().find('#new_line_edit_input').focus();
});
}
var line = $(this);
var tmp = line.parents('tr');
var yield = false;
var par = null;
if(tmp.hasClass('inline-comments')) {
par = tmp;
}
else {
par = tmp.next('tr.inline-comments');
}
if(par.length == 0) {
par = tmp;
yield = true;
}
// Hide visible new comment form
$('#open-comment.new_line_comment').parents('.inline-comments').each(function(i) {
if($(this).find('.line-comments').length > 0) {
$(this).find('#open-comment.new_line_comment').remove();
$(this).find('.new_inline_comment.button').show();
}
else {
$(this).remove();
}
});
par.find('.new_inline_comment.button').hide();
$.get(line.attr('href'), null, ProcessData);
return false;
});
$(document).on('click', '.cancel_inline_comment.button', function() {
var tr = $(this).parents('.inline-comments');
if(tr.find('.line-comments').length > 0) {
tr.find('#open-comment.new_line_comment').remove();
tr.find('.new_inline_comment.button').show();
}
else {
tr.remove();
}
return false;
});
});

View File

@ -2,7 +2,7 @@ $(document).ready(function() {
var preview_url = $('#preview_url').val();
$('#md_tabs.nav.nav-tabs').each(function(i) { $(this).find('a:first').tab('show') });
$('#md_tabs a[data-toggle="tab"]').on('shown', function (e) {
$(document).on('shown','#md_tabs a[data-toggle="tab"]', function (e) {
if(e.relatedTarget) { var hash = e.relatedTarget.hash; }
else { var hash = e.currentTarget.hash; }
var el = $(hash+'_input');

View File

@ -24,4 +24,9 @@ $(document).ready(function() {
location.hash = href;
}
});
var diff_tab = $('#pull_tabs a[href="#diff"]');
$('.link_to_full_changes').on('click', function(){
diff_tab.tab('show');
});
});

View File

@ -119,6 +119,7 @@ div.activity, .commits_activity {
margin-left: 10px;
display: inline-block;
width: 12px;
cursor: pointer;
}
.data-expander.collapsed {
background: #FFF image-url('expand-gray.png') no-repeat;
@ -1612,6 +1613,48 @@ table.tablesorter.platform-maintainers.static-search thead tr.search th input[ty
}
}
#repo-wrapper .add_line-comment {
position: absolute;
width: 25px;
height: 18px;
margin-left: -103px;
margin-top: 0;
cursor: pointer;
opacity: 0;
filter: alpha(Opacity=0);
-moz-opacity:0;
}
#repo-wrapper tr:hover .add_line-comment {
opacity: 1;
filter: alpha(Opacity=100);
-moz-opacity:1;
}
div.file .inline-comments {
.top {
height:auto;
background: none;
box-shadow: none;
}
.activity {
border-radius: 0;
max-width: 752px;
margin-left: 10px;
}
}
tr.inline-comments td {
border: solid #DDD;
border-width: 1px 0;
}
.inline-comments #open-comment {
max-width: 754px;
margin: 10px;
}
#repo-wrapper .edit_form.issue div.comment div.wrapper {
background: 0;
border: 0;
@ -1654,10 +1697,15 @@ form#new_pull_request {
padding: 0;
}
.new_inline_comment.button {
margin: 10px 0 10px 10px;
}
.niceRadio input {
display:none;
}
table#myTable thead tr.search th form.button_to div input {
margin-top: 2px;
}
}

View File

@ -5,8 +5,6 @@ class AdvisoriesController < ApplicationController
load_resource :find_by => :advisory_id
authorize_resource
before_filter :fetch_packages_info, :only => [:show]
def index
@advisories = @advisories.scoped(:include => :platforms)
@advisories = @advisories.search_by_id(params[:q]) if params[:q]
@ -18,6 +16,7 @@ class AdvisoriesController < ApplicationController
end
def show
@packages_info = @advisory.fetch_packages_info
end
def search
@ -27,24 +26,4 @@ class AdvisoriesController < ApplicationController
format.json { render @advisory }
end
end
protected
# this method fetches and structurize packages attached to current advisory.
def fetch_packages_info
@packages_info = Hash.new { |h, k| h[k] = {} } # maaagic, it's maaagic ;)
@advisory.build_lists.find_in_batches(:include => [:save_to_platform, :packages, :project]) do |batch|
batch.each do |build_list|
tmp = build_list.packages.inject({:srpm => nil, :rpm => []}) do |h, p|
p.package_type == 'binary' ? h[:rpm] << p.fullname : h[:srpm] = p.fullname
h
end
h = { build_list.project => tmp }
@packages_info[build_list.save_to_platform].merge!(h) do |pr, old, new|
{:srpm => new[:srpm], :rpm => old[:rpm].concat(new[:rpm]).uniq}
end
end
end
end
end

View File

@ -0,0 +1,44 @@
# -*- encoding : utf-8 -*-
class Api::V1::AdvisoriesController < Api::V1::BaseController
before_filter :authenticate_user!
skip_before_filter :authenticate_user!, :only => [:index, :show] if APP_CONFIG['anonymous_access']
load_resource :advisory, :find_by => :advisory_id
before_filter :find_and_authorize_build_list, :only => [:create, :update]
authorize_resource :build_list, :only => [:create, :update]
def index
@advisories = @advisories.scoped(:include => :platforms).
paginate(paginate_params)
end
def show
@packages_info = @advisory.fetch_packages_info
end
def create
if @build_list.can_attach_to_advisory? &&
@build_list.associate_and_create_advisory(params[:advisory]) &&
@build_list.save
render_json_response @advisory, 'Advisory has been created successfully'
else
render_validation_error @advisory, error_message(@build_list, 'Advisory has not been created')
end
end
def update
if @advisory && @build_list.can_attach_to_advisory? &&
@advisory.attach_build_list(@build_list) && @build_list.save
render_json_response @advisory, "Build list '#{@build_list.id}' has been attached to advisory successfully"
else
render_validation_error @advisory, error_message(@build_list, 'Build list has not been attached to advisory')
end
end
protected
def find_and_authorize_build_list
@build_list = BuildList.find params[:build_list_id]
authorize! :update, @build_list.save_to_platform
end
end

View File

@ -83,7 +83,7 @@ class Api::V1::BaseController < ApplicationController
id = status != 200 ? nil : subject.id
render :json => {
subject.class.name.downcase.to_sym => {
subject.class.name.underscore.to_sym => {
:id => id,
:message => message
}

View File

@ -196,23 +196,13 @@ class Projects::BuildListsController < Projects::BaseController
if params[:attach_advisory] == 'new'
# create new advisory
unless @build_list.build_advisory(params[:build_list][:advisory]) do |a|
a.update_type = @build_list.update_type
a.projects << @build_list.project
a.platforms << @build_list.save_to_platform unless a.platforms.include? @build_list.save_to_platform
end.save
unless @build_list.associate_and_create_advisory(params[:build_list][:advisory])
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
end
else
# attach existing advisory
a = Advisory.where(:advisory_id => params[:attach_advisory]).limit(1).first
if a.update_type != @build_list.update_type
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
end
a.platforms << @build_list.save_to_platform unless a.platforms.include? @build_list.save_to_platform
a.projects << @build_list.project unless a.projects.include? @build_list.project
@build_list.advisory = a
unless a.save
a = Advisory.where(:advisory_id => params[:attach_advisory]).first
unless (a && a.attach_build_list(@build_list))
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
end
end

View File

@ -4,19 +4,22 @@ class Projects::CommentsController < Projects::BaseController
load_and_authorize_resource :project
before_filter :find_commentable
before_filter :find_or_build_comment
load_and_authorize_resource #:through => :commentable
load_and_authorize_resource :new => :new_line
include CommentsHelper
def create
if @comment.save
anchor = ''
if !@comment.set_additional_data params
flash[:error] = I18n.t("flash.comment.save_error")
elsif @comment.save
flash[:notice] = I18n.t("flash.comment.saved")
redirect_to project_commentable_path(@project, @commentable)
anchor = view_context.comment_anchor(@comment)
else
flash[:error] = I18n.t("flash.comment.save_error")
flash[:warning] = @comment.errors.full_messages.join('. ')
redirect_to project_commentable_path(@project, @commentable)
end
redirect_to "#{project_commentable_path(@project, @commentable)}##{anchor}"
end
def edit
@ -37,6 +40,11 @@ class Projects::CommentsController < Projects::BaseController
redirect_to project_commentable_path(@project, @commentable)
end
def new_line
@path = view_context.project_commentable_comments_path(@project, @commentable)
render :layout => false
end
protected
def find_commentable

View File

@ -9,10 +9,12 @@ class Projects::Git::CommitsController < Projects::Git::BaseController
end
def show
@commit = @project.repo.commit(params[:id])
@commit = @commentable = @project.repo.commit(params[:id]) || raise(ActiveRecord::RecordNotFound)
@comments, @diff = Comment.for_commit(@commit), @commit.diffs
respond_to do |format|
format.html
format.diff { render :text => (@commit.diffs.map(&:diff).join("\n") rescue ''), :content_type => "text/plain" }
format.diff { render :text => (@diff.map(&:diff).join("\n") rescue ''), :content_type => "text/plain" }
format.patch { render :text => (@commit.to_patch rescue ''), :content_type => "text/plain" }
end
end

View File

@ -104,7 +104,7 @@ class Projects::ProjectsController < Projects::BaseController
end
def preview
render :inline => view_context.markdown(params[:text]), :layout => false
render :inline => view_context.markdown(params[:text] || ''), :layout => false
end
def refs_list

View File

@ -128,16 +128,12 @@ class Projects::PullRequestsController < Projects::BaseController
end
def load_diff_commits_data
repo = Grit::Repo.new(@pull.path)
@base_commit = @pull.common_ancestor
@head_commit = repo.commits(@pull.head_branch).first
@commits = repo.commits_between(repo.commits(@pull.to_ref).first, @head_commit)
@commits = @pull.repo.commits_between(@pull.to_commit, @pull.from_commit)
@total_commits = @commits.count
@commits = @commits.last(100)
@diff = @pull.diff repo, @base_commit, @head_commit
@stats = @pull.diff_stats repo, @base_commit, @head_commit
@diff, @stats = @pull.diff, @pull.diff_stats
@comments, @commentable = @issue.comments, @issue
end
def find_destination_project bang=true

View File

@ -1,20 +1,30 @@
# -*- encoding : utf-8 -*-
module CommentsHelper
def project_commentable_comment_path(project, commentable, comment)
case
when Comment.issue_comment?(commentable.class)
if Comment.issue_comment?(commentable.class)
project_issue_comment_path(project, commentable, comment)
when Comment.commit_comment?(commentable.class)
elsif Comment.commit_comment?(commentable.class)
project_commit_comment_path(project, commentable, comment)
end
end
def project_commentable_path(project, commentable)
case
when Comment.issue_comment?(commentable.class)
if Comment.issue_comment?(commentable.class)
polymorphic_path [project, commentable.pull_request ? commentable.pull_request : commentable]
when Comment.commit_comment?(commentable.class)
elsif Comment.commit_comment?(commentable.class)
commit_path project, commentable.id
end
end
def project_commentable_comments_path(project, commentable)
if commentable.is_a? Issue
project_issue_comments_path(@project, @commentable)
elsif commentable.is_a? Grit::Commit
project_commit_comments_path(@project, @commentable)
end
end
def comment_anchor c
"#{(c.data.present? && c.actual_inline_comment?(@diff)) ? 'diff-' : ''}comment#{c.id}"
end
end

View File

@ -1,23 +1,5 @@
# -*- encoding : utf-8 -*-
module DiffHelper
def render_diff(diff, diff_counter)
diff_display ||= Diff::Display::Unified.new(diff.diff)
path = if @pull
@pull.id ? polymorphic_path([@project, @pull]) : ''
elsif @commit
commit_path @project, @commit
end
res = "<table class='diff inline' cellspacing='0' cellpadding='0'>"
res += "<tbody>"
res += diff_display.render(Git::Diff::InlineCallback.new(diff_counter, path))
res += "</tbody>"
res += "</table>"
res.html_safe
end
def render_diff_stats(stats)
path = @pull.id ? polymorphic_path([@project, @pull]) : ''
res = ["<table class='commit_stats'>"]
@ -38,4 +20,248 @@ module DiffHelper
res.join("\n").html_safe.default_encoding!
end
#include Git::Diff::InlineCallback
def render_diff(diff, args = {})#diff_counter, comments, opts = nil diffpath = nil)
if diff.respond_to?(:diff)
diff, filepath, in_discussion = diff.diff, diff.a_path, false
comments = (args[:comments] || []).select{|c| c.data.try('[]', :path) == filepath}
else
filepath, in_discussion, comments = args[:diffpath], true, args[:comments]
end
diff_display ||= Diff::Display::Unified.new(diff)
url = if @pull
@pull.id ? polymorphic_path([@project, @pull]) : ''
elsif @commit
commit_path @project, @commit
end
prepare(args.merge({:filepath => filepath, :comments => comments, :in_discussion => in_discussion}))
res = "<table class='diff inline' cellspacing='0' cellpadding='0'>"
res += "<tbody>"
res += renderer diff_display.data #diff_display.render(Git::Diff::InlineCallback.new comments, path)
res += tr_line_comments(comments) if in_discussion
res += "</tbody>"
res += "</table>"
res.html_safe
end
########################################################
# FIXME: Just to dev, remove to lib. Really need it?
########################################################
def prepare(args)
@url, @diff_counter, @in_discussion = args[:url], args[:diff_counter], args[:in_discussion]
@filepath, @line_comments, @in_wiki = args[:filepath], args[:comments], args[:in_wiki]
@add_reply_id, @num_line = if @in_discussion
[@line_comments[0].id, @line_comments[0].data[:line].to_i - @line_comments[0].data[:strings].lines.count.to_i-1]
else
[nil, -1]
end
end
def headerline(line)
set_line_number
"<tr class='header'>
<td class='line_numbers'>...</td>
<td class='line_numbers'>...</td>
<td class='header'>#{line}</td>
</tr>"
end
def addline(line)
set_line_number
"<tr class='changes'>
<td class='line_numbers'></td>
#{td_line_link "diff-F#{@diff_counter}R#{line.new_number}", line.new_number}
<td class='code ins'>
#{line_comment}
<pre>#{render_line(line)}</pre>
</td>
</tr>
#{render_line_comments}"
end
def remline(line)
set_line_number
"<tr class='changes'>
#{td_line_link "diff-F#{@diff_counter}L#{line.old_number}", line.old_number}
<td class='line_numbers'></td>
<td class='code del'>
#{line_comment}
<pre>#{render_line(line)}</pre>
</td>
</tr>
#{render_line_comments}"
end
def modline(line)
set_line_number
"<tr clas='chanes line'>
#{td_line_link "diff-F#{@diff_counter}L#{line.old_number}", line.old_number}
#{td_line_link "diff-F#{@diff_counter}R#{line.new_number}", line.new_number}
<td class='code unchanged modline'>
#{line_comment}
<pre>#{render_line(line)}</pre>
</td>
</tr>
#{render_line_comments}"
end
def unmodline(line)
set_line_number
"<tr class='changes unmodline'>
#{td_line_link "diff-F#{@diff_counter}L#{line.old_number}", line.old_number}
#{td_line_link "diff-F#{@diff_counter}R#{line.new_number}", line.new_number}
<td class='code unchanged unmodline'>
#{line_comment}
<pre>#{render_line(line)}</pre>
</td>
</tr>
#{render_line_comments}"
end
def sepline(line)
"<tr class='changes hunk-sep'>
<td class='line_numbers line_num_cut'>&hellip;</td>
<td class='line_numbers line_num_cut'>&hellip;</td>
<td class='code cut-line'></td>
</tr>"
end
def nonewlineline(line)
set_line_number
"<tr class='changes'>
#{td_line_link "diff-F#{@diff_counter}L#{line.old_number}", line.old_number}
#{td_line_link "diff-F#{@diff_counter}R#{line.new_number}", line.new_number}
<td class='code modline unmodline'>
#{line_comment}
<pre>#{render_line(line)}</pre>
</td>
</tr>
#{render_line_comments}"
end
def before_headerblock(block)
end
def after_headerblock(block)
end
def before_unmodblock(block)
end
def before_modblock(block)
end
def before_remblock(block)
end
def before_addblock(block)
end
def before_sepblock(block)
end
def before_nonewlineblock(block)
end
def after_unmodblock(block)
end
def after_modblock(block)
end
def after_remblock(block)
end
def after_addblock(block)
end
def after_sepblock(block)
end
def after_nonewlineblock(block)
end
def new_line
""
end
def renderer(data)
result = []
data.each do |block|
result << send("before_" + classify(block), block)
result << block.map { |line| send(classify(line), line) }
result << send("after_" + classify(block), block)
end
result.compact.join(new_line)
end
protected
def classify(object)
object.class.name[/\w+$/].downcase
end
def escape(str)
str.to_s.gsub('&', '&amp;').gsub('<', '&lt;').gsub('>', '&gt;').gsub('"', '&#34;')
end
def render_line(line)
res = '<span class="diff-content">'
if line.inline_changes?
prefix, changed, postfix = line.segments.map{|segment| escape(segment) }
res += "#{prefix}<span class='idiff'>#{changed}</span>#{postfix}"
else
res += escape(line)
end
res += '</span>'
res
end
def set_line_number
@num_line = @num_line.succ
end
def line_comment
return if @in_wiki || (@in_discussion && @add_reply_id && @line_comments[0].data[:line].to_i != @num_line)
link_to image_tag('line_comment.png', :alt => t('layout.comments.new_header')), new_comment_path, :class => 'add_line-comment'
end
def render_line_comments
unless @in_wiki || @in_discussion
comments = @line_comments.select do |c|
c.data.try('[]', :line) == @num_line.to_s && c.actual_inline_comment?(@diff)
end
tr_line_comments(comments) if comments.count > 0
end
end
def td_line_link id, num
"<td class='line_numbers' id='#{id}'><a href='#{@url}##{id}'>#{num}</a></td>"
end
def tr_line_comments comments
return if @in_wiki
res="<tr class='inline-comments'>
<td class='line_numbers' colspan='2'>#{comments.count}</td>
<td>"
comments.each do |comment|
res << "<div class='line-comments'>
#{render 'projects/comments/comment', :comment => comment, :data => {:project => @project, :commentable => @commentable, :add_anchor => 'inline', :in_discussion => @in_discussion}}
</div>"
end
res << link_to(t('layout.comments.new_inline'), new_comment_path, :class => 'new_inline_comment button')
res << "</td></tr>"
end
def new_comment_path
hash = {:path => @filepath, :line => @num_line}
if @commentable.is_a? Issue
project_new_line_pull_comment_path(@project, @commentable, hash.merge({:in_reply => @add_reply_id}))
elsif @commentable.is_a? Grit::Commit
new_line_commit_comment_path(@project, @commentable, hash)
end
end
end

View File

@ -1,9 +1,11 @@
# -*- encoding : utf-8 -*-
module PullRequestHelper
def merge_activity comments, commits
issue_comments = @issue.comments.map{ |c| [c.created_at, c] }
commits = @commits.map{ |c| [(c.committed_date || c.authored_date), c] }
(issue_comments + commits).sort_by{ |c| c[0] }.map{ |c| c[1] }
common_comments, pull_comments = comments.partition {|c| c.data.blank?}
common_comments = common_comments.map{ |c| [c.created_at, c] }
pull_comments = pull_comments.group_by(&:data).map{|data, c| [c.first.created_at, [data || {}, [c].flatten]]}
commits = commits.map{ |c| [(c.committed_date || c.authored_date), c] }
(common_comments + pull_comments + commits).sort_by{ |c| c[0] }.map{ |c| c[1] }
end
def pull_status_label pull

View File

@ -133,8 +133,8 @@ class Ability
can :create, PullRequest
can([:update, :merge], PullRequest) {|pull| pull.user_id == user.id or local_admin?(pull.to_project)}
can(:create, Comment) {|comment| can? :read, comment.project}
can(:update, Comment) {|comment| comment.user == user or comment.project.owner == user or local_admin?(comment.project)}
can([:create, :new_line], Comment) {|comment| can? :read, comment.project}
can([:update, :destroy], Comment) {|comment| comment.user == user or comment.project.owner == user or local_admin?(comment.project)}
cannot :manage, Comment do |c|
c.commentable_type == 'Issue' && !c.project.has_issues && !c.commentable.pull_request # when switch off issues
end

View File

@ -21,6 +21,32 @@ class Advisory < ActiveRecord::Base
advisory_id
end
def attach_build_list(build_list)
return false if update_type != build_list.update_type
self.platforms << build_list.save_to_platform unless platforms.include? build_list.save_to_platform
self.projects << build_list.project unless projects.include? build_list.project
build_list.advisory = self
save
end
# this method fetches and structurize packages attached to current advisory.
def fetch_packages_info
packages_info = Hash.new { |h, k| h[k] = {} } # maaagic, it's maaagic ;)
build_lists.find_in_batches(:include => [:save_to_platform, :packages, :project]) do |batch|
batch.each do |build_list|
tmp = build_list.packages.inject({:srpm => nil, :rpm => []}) do |h, p|
p.package_type == 'binary' ? h[:rpm] << p.fullname : h[:srpm] = p.fullname
h
end
h = { build_list.project => tmp }
packages_info[build_list.save_to_platform].merge!(h) do |pr, old, new|
{:srpm => new[:srpm], :rpm => old[:rpm].concat(new[:rpm]).uniq}
end
end
end
packages_info
end
protected
def generate_advisory_id
@ -38,4 +64,4 @@ class Advisory < ActiveRecord::Base
end
end
Advisory.include_root_in_json = false
Advisory.include_root_in_json = false

View File

@ -303,6 +303,18 @@ class BuildList < ActiveRecord::Base
#[WAITING_FOR_RESPONSE, BuildServer::BUILD_PENDING, BuildServer::BUILD_STARTED].include?(status)
end
def associate_and_create_advisory(params)
build_advisory(params){ |a| a.update_type = update_type }
advisory.attach_build_list(self)
end
def can_attach_to_advisory?
!save_to_repository.publish_without_qa &&
save_to_platform.main? &&
save_to_platform.released &&
status == BUILD_PUBLISHED
end
protected
def notify_users

View File

@ -3,6 +3,7 @@ class Comment < ActiveRecord::Base
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
@ -12,7 +13,7 @@ class Comment < ActiveRecord::Base
after_create :subscribe_on_reply, :unless => lambda {|c| c.commit_comment?}
after_create :subscribe_users
attr_accessible :body
attr_accessible :body, :data
def commentable
# raise commentable_id.inspect
@ -53,6 +54,79 @@ class Comment < ActiveRecord::Base
User.find(subscribe.user).notifier.new_comment && User.find(subscribe.user).notifier.can_notify
end
def actual_inline_comment?(diff, force = false)
unless force
raise "This is not inline comment!" if data.blank? # for debug
return data[:actual] unless data[:actual].nil?
end
filepath, line_number = data[:path], data[:line]
diff_path = (diff || commentable.diffs ).select {|d| d.a_path == data[:path]}
comment_line = data[:line].to_i
# NB! also dont create a comment to the diff header
return data[:actual] = false if diff_path.blank? || comment_line == 0
return data[:actual] = true if commentable_type == 'Grit::Commit'
res, ind = true, 0
diff_path[0].diff.each_line do |line|
if self.persisted? && (comment_line-2..comment_line+2).include?(ind) && data.try('[]', "line#{ind-comment_line}") != line.chomp
break res = false
end
ind = ind + 1
end
if ind < comment_line
return data[:actual] = false
else
return data[:actual] = res
end
end
def inline_diff
data[:strings] + data['line0']
end
def pull_comment?
return true if commentable.is_a?(Issue) && commentable.pull_request.present?
end
def set_additional_data params
return true if params[:path].blank? && params[:line].blank? # not inline comment
if params[:in_reply].present? && reply = Comment.where(:id => params[:in_reply]).first
self.data = reply.data
return true
end
self.data = {:path => params[:path], :line => params[:line]}
if commentable.is_a?(Issue) && pull = commentable.pull_request
diff_path = pull.diff.select {|d| d.a_path == params[:path]}
return false unless actual_inline_comment?(pull.diff, true)
comment_line, line_number, strings = params[:line].to_i, -1, []
diff_path[0].diff.each_line do |line|
line_number = line_number.succ
# Save 2 lines above and bottom of the diff comment line
break if line_number > comment_line + 2
if (comment_line-2..comment_line+2).include? line_number
data["line#{line_number-comment_line}"] = line.chomp
end
# Save lines from the closest header for rendering in the discussion
if line_number < comment_line
# Header is the line like "@@ -47,9 +50,8 @@ def initialize(user)"
if line =~ Diff::Display::Unified::Generator::LINE_NUM_RE
strings = [line]
else
strings << line
end
end
end
## Bug with numbers of diff lines, now store all diff
data[:strings] = strings.join
# Limit stored diff to 10 lines (see inline_diff)
#data[:strings] = ((strings.count) <= 9 ? strings : [strings[0]] + strings.last(8)).join
##
data[:view_path] = h(diff_path[0].renamed_file ? "#{diff_path[0].a_path.rtruncate 60} -> #{diff_path[0].b_path.rtruncate 60}" : diff_path[0].a_path.rtruncate(120))
end
return true
end
protected
def subscribe_on_reply

View File

@ -20,10 +20,6 @@ class PullRequest < ActiveRecord::Base
scope :needed_checking, includes(:issue).where(:issues => {:status => ['open', 'blocked', 'ready']})
state_machine :status, :initial => :open do
#after_transition [:ready, :blocked] => [:merged, :closed] do |pull, transition|
# FileUtils.rm_rf(pull.path) # What about diff?
#end
event :ready do
transition [:ready, :open, :blocked] => :ready
end
@ -65,11 +61,8 @@ class PullRequest < ActiveRecord::Base
end
if do_transaction
if new_status == 'already'
ready; merging
else
send(new_status)
end
new_status == 'already' ? (ready; merging) : send(new_status)
self.update_inline_comments
else
self.status = new_status == 'block' ? 'blocked' : new_status
end
@ -93,7 +86,7 @@ class PullRequest < ActiveRecord::Base
File.join(APP_CONFIG['root_path'], 'pull_requests', to_project.owner.uname, to_project.name, filename)
end
def head_branch
def from_branch
if to_project != from_project
"head_#{from_ref}"
else
@ -103,16 +96,15 @@ class PullRequest < ActiveRecord::Base
def common_ancestor
return @common_ancestor if @common_ancestor
repo = Grit::Repo.new(path)
base_commit = repo.commits(to_ref).first
head_commit = repo.commits(head_branch).first
@common_ancestor = repo.commit(repo.git.merge_base({}, base_commit, head_commit)) || base_commit
@common_ancestor = repo.commit(repo.git.merge_base({}, base_commit, from_commit)) || base_commit
end
alias_method :to_commit, :common_ancestor
def diff_stats(repo, a,b)
def diff_stats
stats = []
Dir.chdir(path) do
lines = repo.git.native(:diff, {:numstat => true, :M => true}, "#{a.id}...#{b.id}").split("\n")
lines = repo.git.native(:diff, {:numstat => true, :M => true}, "#{to_commit.id}...#{from_commit.id}").split("\n")
while !lines.empty?
files = []
while lines.first =~ /^([-\d]+)\s+([-\d]+)\s+(.+)/
@ -127,15 +119,16 @@ class PullRequest < ActiveRecord::Base
end
# FIXME maybe move to warpc/grit?
def diff(repo, a, b)
diff = repo.git.native('diff', {:M => true}, "#{a}...#{b}")
def diff
return @diff if @diff.present?
diff = repo.git.native('diff', {:M => true}, "#{to_commit.id}...#{from_commit.id}")
if diff =~ /diff --git a/
diff = diff.sub(/.*?(diff --git a)/m, '\1')
else
diff = ''
end
Grit::Diff.list_from_string(repo, diff)
@diff = Grit::Diff.list_from_string(repo, diff)
end
def set_user_and_time user
@ -154,12 +147,21 @@ class PullRequest < ActiveRecord::Base
end
end
def repo
return @repo if @repo.present? #&& !id_changed?
@repo = Grit::Repo.new path
end
def from_commit
repo.commits(from_branch).first
end
protected
def merge
clone
message = "Merge pull request ##{serial_id} from #{from_project.name_with_owner}:#{from_ref}\r\n #{title}"
%x(cd #{path} && git checkout #{to_ref} && git merge --no-ff #{head_branch} -m '#{message}')
%x(cd #{path} && git checkout #{to_ref} && git merge --no-ff #{from_branch} -m '#{message}')
end
def clone
@ -175,7 +177,7 @@ class PullRequest < ActiveRecord::Base
system 'git', 'remote', 'add', 'head', from_project.path
end
end
clean
clean # Need testing
end
Dir.chdir(path) do
@ -185,7 +187,7 @@ class PullRequest < ActiveRecord::Base
system 'git', 'checkout', from_ref
system 'git', 'pull', 'origin', from_ref
else
system 'git', 'fetch', 'head', "+#{from_ref}:#{head_branch}"
system 'git', 'fetch', 'head', "+#{from_ref}:#{from_branch}"
end
end
# TODO catch errors
@ -197,10 +199,10 @@ class PullRequest < ActiveRecord::Base
system 'git', 'checkout', to_ref
to_project.repo.branches.each do |branch|
system 'git', 'branch', '-D', branch.name unless [to_ref, head_branch].include? branch.name
system 'git', 'branch', '-D', branch.name unless [to_ref, from_branch].include? branch.name
end
to_project.repo.tags.each do |tag|
system 'git', 'tag', '-d', tag.name unless [to_ref, head_branch].include? tag.name
system 'git', 'tag', '-d', tag.name unless [to_ref, from_branch].include? tag.name
end
end
end
@ -208,4 +210,13 @@ class PullRequest < ActiveRecord::Base
def clean_dir
FileUtils.rm_rf path
end
def update_inline_comments
self.comments.each do |c|
if c.data.present? # maybe need add new column 'actual'?
c.actual_inline_comment? diff, true
c.save
end
end
end
end

View File

@ -27,24 +27,17 @@ class CommentPresenter < ApplicationPresenter
def caption?
false
end
def buttons
project = options[:project]
commentable = options[:commentable]
(ep, dp) = if Comment.issue_comment?(commentable.class)
[edit_project_issue_comment_path(project, commentable, comment),
project_issue_comment_path(project, commentable, comment)]
elsif Comment.commit_comment?(commentable.class)
[edit_project_commit_comment_path(project, commentable, comment),
project_commit_comment_path(project, commentable, comment)]
end
res = []
def buttons
project, commentable = options[:project], options[:commentable]
path = helpers.project_commentable_comment_path(project, commentable, comment)
res = [link_to(t("layout.link"), "#{helpers.project_commentable_path(project, commentable)}##{comment_anchor}", :class => "#{@options[:in_discussion].present? ? 'in_discussion_' : ''}link_to_comment").html_safe]
if controller.can? :update, @comment
res << link_to(t('layout.comments.md_cheatsheet_header'), '#md_help', 'data-toggle' => 'modal')
res << link_to(t("layout.edit"), ep, :id => "comment-#{comment.id}", :class => "edit_comment").html_safe
res << link_to(t("layout.edit"), path, :id => "comment-#{comment.id}", :class => "edit_comment").html_safe
end
if controller.can? :delete, @comment
res << link_to(t("layout.delete"), dp, :method => "delete",
if controller.can? :destroy, @comment
res << link_to(t("layout.delete"), path, :method => "delete",
:confirm => t("layout.comments.confirm_delete")).html_safe
end
res
@ -70,4 +63,15 @@ class CommentPresenter < ApplicationPresenter
def comment_id
@comment.id
end
def comment_anchor
# check for pull diff inline comment
before = if @options[:add_anchor].present? && !@options[:in_discussion]
'diff-'
else
''
end
"#{before}comment#{@comment.id}"
end
end

View File

@ -4,7 +4,7 @@
.text
%span
= raw t("notifications.bodies.new_comment_notification.title", :user_link => link_to(user_name, user_path(user_id)) )
= raw t("notifications.bodies.new_comment_notification.commit_content", {:commit_link => link_to(commit_message, commit_path(project_owner, project_name, commit_id) + "#comment##{comment_id}")})
= raw t("notifications.bodies.new_comment_notification.commit_content", {:commit_link => link_to(commit_message, commit_path(project_owner, project_name, commit_id) + "#comment#{comment_id}")})
= raw t("notifications.bodies.project", :project_link => link_to("#{project_owner}/#{project_name}", project_path(project_owner, project_name)) )
.both
%span.date= activity_feed.created_at

View File

@ -4,7 +4,7 @@
.text
%span
= raw t("notifications.bodies.new_comment_notification.title", {:user_link => link_to(user_name, user_path(user_id))})
= raw t("notifications.bodies.new_comment_notification.content", {:issue_link => link_to(issue_title, project_issue_path(project_owner, project_name, issue_serial_id) + "#comment##{comment_id}")})
= raw t("notifications.bodies.new_comment_notification.content", {:issue_link => link_to(issue_title, project_issue_path(project_owner, project_name, issue_serial_id) + "#comment#{comment_id}")})
= raw t("notifications.bodies.project", :project_link => link_to("#{project_owner}/#{project_name}", project_path(project_owner, project_name)) )
.both
%span.date= activity_feed.created_at

View File

@ -0,0 +1,12 @@
json.id advisory.advisory_id
json.(advisory, :description)
json.platforms advisory.platforms do |json_platform, platform|
json_platform.(platform, :id, :released)
json_platform.url api_v1_platform_path(platform.id, :format => :json)
end
json.projects advisory.projects do |json_project, project|
json_project.(project, :id, :name)
json_project.fullname project.name_with_owner
json_project.url api_v1_project_path(project.id, :format => :json)
end
json.url api_v1_advisory_path(advisory.advisory_id, :format => :json)

View File

@ -0,0 +1,4 @@
json.advisories @advisories do |json, advisory|
json.partial! 'advisory', :advisory => advisory, :json => json
end
json.url api_v1_advisories_path(:format => :json)

View File

@ -0,0 +1,27 @@
json.advisory do |json|
json.partial! 'advisory', :advisory => @advisory, :json => json
json.created_at @advisory.created_at.to_i
json.updated_at @advisory.updated_at.to_i
json.(@advisory, :update_type)
json.references @advisory.references.split('\n')
json.build_lists @advisory.build_lists do |json_build_list, build_list|
json_build_list.(build_list, :id)
json_build_list.url api_v1_build_list_path(build_list.id, :format => :json)
end
json.affected_in @packages_info do |json_platform, package_info|
platform = package_info[0]
json_platform.(platform, :id)
json_platform.url api_v1_platform_path(platform.id, :format => :json)
json_platform.projects package_info[1] do |json_project, info|
project = info[0]
json_project.(project, :id)
json_project.url api_v1_project_path(project.id, :format => :json)
packages = info[1]
json_project.srpm packages[:srpm]
json_project.rpm packages[:rpm]
end
end
end

View File

@ -1,5 +1,5 @@
#open-comment.comment.view
=link_to t('layout.comments.md_cheatsheet_header'), '#md_help', 'data-toggle' => 'modal', :style => 'float:right;'
=render 'projects/comments/button_md_help'
%h3.tmargin0= t("layout.comments.new_header")
- if Comment.issue_comment?(commentable.class)
- new_path = project_issue_comments_path(project, commentable)

View File

@ -0,0 +1,2 @@
=link_to t('layout.comments.md_cheatsheet_header'), '#md_help', 'data-toggle' => 'modal', :style => 'float:right;'

View File

@ -1,9 +1,10 @@
- CommentPresenter.present(comment, :project => project, :commentable => commentable) do |presenter|
- CommentPresenter.present(comment, data) do |presenter|
= render 'shared/feed_message', :presenter => presenter
#open-comment.comment.hidden{:class => "comment-#{comment.id}"}
=render 'projects/comments/button_md_help'
%h3.tmargin0= t("layout.comments.edit_header")
= form_for comment, :url => project_commentable_comment_path(project, commentable, comment), :html => { :class => 'form edit_comment' } do |f|
= render "projects/comments/form", :f => f, :id => "edit_#{comment.id}"
= form_for comment, :url => project_commentable_comment_path(data[:project], data[:commentable], comment), :html => { :class => 'form edit_comment' } do |f|
= render "projects/comments/form", :f => f, :id => "#{data[:add_id]}edit_#{comment.id}"
.comment-left
=link_to t('layout.cancel'), '#', :id => "comment-#{comment.id}", :class => 'cancel_edit_comment button'
.both

View File

@ -2,5 +2,5 @@
.hr
%h3#block-list= t("layout.comments.comments_header")
- list.each do |comment|
= render 'projects/comments/comment', :comment => comment, :project => project, :commentable => commentable
= render 'projects/comments/comment', :comment => comment, :data => {:project => project, :commentable => commentable}
= render "projects/comments/markdown_help"

View File

@ -0,0 +1,11 @@
#open-comment.comment.view.new_line_comment
=render 'projects/comments/button_md_help'
%h3.tmargin0= t("layout.comments.new_header")
= form_for :comment, :url => @path, :method => :post, :html => { :class => :form } do |f|
= render "projects/comments/form", :f => f, :id => 'new_line'
.comment-left
=link_to t('layout.cancel'), '#', :class => 'cancel_inline_comment button'
=hidden_field_tag :path, params[:path]
=hidden_field_tag :line, params[:line]
=hidden_field_tag :in_reply, params[:in_reply] if params[:in_reply].present?
.both

View File

@ -6,5 +6,5 @@
- if commit_diff.b_path.present?
.r= link_to "view file @ #{short_hash_id(commit_id)}", blob_path(@project, commit_id, commit_diff.b_path)
.clear
.diff_data= render_diff(commit_diff, commit_diff_counter) unless (@project.repo.tree(commit_id) / commit_diff.b_path).binary?
-unless (@project.repo.tree(commit_id) / commit_diff.b_path).binary?
.diff_data=render_diff(commit_diff, :diff_counter => commit_diff_counter, :comments => @comments)

View File

@ -13,6 +13,6 @@
-begin
= render_commit_stats(stats)
= render :partial => 'commit_diff', :collection => @commit.diffs
= render :partial => 'commit_diff', :collection => @diff
- rescue Grit::Git::GitTimeout
%p= t 'layout.git.repositories.commit_diff_too_big'

View File

@ -2,17 +2,15 @@
= render 'submenu'
= render 'about_block', :project => @project
%h3= t("layout.projects.last_commit")
- GitPresenters::CommitAsMessagePresenter.present(@commit, :branch => @branch, :project => @project) do |presenter|
= render :partial => 'shared/feed_message', :locals => {:presenter => presenter, :item_no => 1}
.both
#repo-wrapper
= render 'show'
= render "projects/comments/list", :list => Comment.for_commit(@commit), :project => @project, :commentable => @commit
-comments = @comments.select {|c| c.data.blank? } # dont work @comments.where(:data => nil)
= render "projects/comments/list", :list => comments, :project => @project, :commentable => @commit
= render "projects/comments/add", :project => @project, :commentable => @commit if current_user
=hidden_field_tag :preview_url, project_md_preview_path(@project)

View File

@ -2,7 +2,7 @@
%h3.tmargin0= t 'activerecord.attributes.issue.title'
.wrapper= f.text_area :title, :cols => 80, :rows => 1
#open-comment.comment.view
=link_to t('layout.comments.md_cheatsheet_header'), '#md_help', 'data-toggle' => 'modal', :style => 'float:right;'
=render 'projects/comments/button_md_help'
%h3.tmargin0= t 'activerecord.attributes.issue.body'
=render 'projects/comments/body', :f => f, :id => id
.both

View File

@ -1,23 +1,23 @@
%a{ :name => "comments" }
.hr
%h3#block-list= t("layout.comments.comments_header")
-commits_queue = []
-merge_activity(@comments, @commits).each do |item| #
-if item.is_a? Comment
=render 'projects/git/commits/commits_small', :commits => commits_queue if commits_queue.present?
-commits_queue.clear
=render 'projects/comments/comment', :comment => item, :data => {:project => @project, :commentable => @commentable}
-elsif item.is_a? Grit::Commit
-commits_queue << item
-elsif item.is_a? Array
=render 'projects/git/commits/commits_small', :commits => commits_queue if commits_queue.present?
-commits_queue.clear
-unless item[1].first.data[:actual]
-exp_id = "expand-comment#{item[1].first.id}"
.activity
=t '.show_outdated_diff'
%span.data-expander.collapsed{:id => exp_id} &nbsp;
.hidden{:id => "content-#{exp_id}"}
=render 'projects/pull_requests/discussion_comments', :item => item, :add_id => nil
-else
=render 'projects/pull_requests/discussion_comments', :item => item, :add_id => nil
=render 'projects/git/commits/commits_small', :commits => commits_queue if commits_queue.present?
- commits_queue = []
- merge_activity(@issue.comments, @commits).each do |item| #
- if item.is_a?(Comment)
- if commits_queue.present?
= render 'projects/git/commits/commits_small', :commits => commits_queue
- commits_queue = []
= render 'projects/comments/comment', :comment => item, :project => @project, :commentable => @issue
- else
- commits_queue << item
- comments_for_commit = Comment.for_commit(item)
- if comments_for_commit.present?
= render 'projects/git/commits/commits_small', :commits => commits_queue
- comments_for_commit.each do |comment|
= render 'projects/comments/comment', :comment => comment, :project => @project, :commentable => item
- commits_queue = []
- if commits_queue.present?
= render 'projects/git/commits/commits_small', :commits => commits_queue
= render "projects/comments/markdown_help"

View File

@ -0,0 +1,15 @@
-comment = item[1].first
.file
.top
.l=comment.data[:view_path]
-if comment.actual_inline_comment? @diff
.r=link_to t("layout.pull_requests.view_full_changes"),
"#{project_commentable_path(@project, @commentable)}##{comment_anchor(comment)}",
:class => 'link_to_full_changes'
-else
.r
=t'projects.pull_requests.outdated_diff'
=image_tag 'x.png'
.clear
.diff_data=render_diff(comment.inline_diff, :diff_counter => 0, :comments => item[1], :filepath => comment.data[:path])

View File

@ -1,4 +1,4 @@
- commit_id = pull_diff.deleted_file ? @base_commit.id : @head_commit.id
- commit_id = pull_diff.deleted_file ? @pull.to_commit.id : @pull.from_commit.id
.file
%a{:name => "diff-#{pull_diff_counter}"}
.top
@ -6,5 +6,5 @@
- if pull_diff.b_path.present?
.r= link_to "view file @ #{short_hash_id(commit_id)}", blob_path(@project, commit_id, pull_diff.b_path)
.clear
-if pull_diff.diff.present? && !(Grit::Repo.new(@pull.path).tree(commit_id) / pull_diff.b_path).binary?
.diff_data= render_diff(pull_diff, pull_diff_counter)
-if pull_diff.diff.present? && !(@pull.repo.tree(commit_id) / pull_diff.b_path).binary?
.diff_data=render_diff(pull_diff, :diff_counter => pull_diff_counter, :comments => @comments)

View File

@ -16,4 +16,4 @@
=render 'status'
=render 'diff_commits_tabs' unless @pull.already?
=hidden_field_tag :preview_url, project_md_preview_path(@project)
= render "projects/comments/markdown_help"

View File

@ -3,4 +3,5 @@
.top
.l= h((diff.deleted_file ? diff.a_path : diff.b_path).rtruncate 100)
.clear
.diff_data.highlight= render_diff(diff, diff_counter)
.diff_data.highlight= render_diff(diff, :diff_counter => diff_counter, :in_wiki => true)

View File

@ -1,4 +1,4 @@
.activity{:id => presenter.comment_id? ? "comment##{presenter.comment_id}" : ''}
.activity{:id => presenter.comment_id? ? presenter.comment_anchor : ''}
.top
- if presenter.buttons?
%span.buttons= raw presenter.buttons.join(' | ').html_safe

View File

@ -48,6 +48,7 @@ en:
invalid_content_type: incorrect type
atom_link_tag_title: Private feed for %{nickname} | %{app_name}
preview: Preview
link: Link
settings:
label: Settings

View File

@ -3,6 +3,7 @@ en:
comments:
confirm_delete: Are you sure you want to delete the comment?
new_header: New comment
new_inline: Add a line comment
edit_header: Editing a comment
has_commented: added a note
notifications_are: Notifications for new comments are

View File

@ -3,6 +3,7 @@ ru:
comments:
confirm_delete: Вы уверены, что хотите удалить комментарий?
new_header: Новый комментарий
new_inline: Добавить комментарий к строке
edit_header: Редактирование комментария
has_commented: оставил комментарий
notifications_are: Уведомления о последующих комментариях

View File

@ -28,7 +28,9 @@ en:
ready: Ready
merged: Merged
closed: Closed
outdated_diff: Outdated diff
activity:
show_outdated_diff: Show outdated_diff
pull_requests:
tabs:
discussion: Discussion
@ -53,3 +55,4 @@ en:
layout:
pull_requests:
search: Find pull request...
view_full_changes: View full changes

View File

@ -2,13 +2,11 @@ ru:
projects:
pull_requests:
new:
header: 'Создать пул реквест'
header: Создать пул реквест
submit: Создать пул реквест
update: Обновить коммиты
show:
pull: Пул реквест
into: из
from: в
header: Пул реквест
status:
close: Закрыть пул реквест
@ -23,14 +21,16 @@ ru:
%{user} смержил <span class="label-bootstrap label-info font14">%{to_ref}</span>
с <span class="label-bootstrap label-info font14">%{from_ref}</span> в %{time}'
closed: '%{user} закрыл пул реквест в %{time}'
is_big: Этот пул реквест слишком большой! Мы показываем только последние %{count} комитов.
is_big: Этот пул реквест слишком большой! Мы показываем только последние %{count} коммитов.
open: ''
statuses:
blocked: Заблокирован
ready: Готов к мержу
merged: Смержен
closed: Закрыт
outdated_diff: Устаревшие изменения
activity:
show_outdated_diff: Отобразить устаревшие изменения
pull_requests:
tabs:
discussion: Дискуссия
@ -55,3 +55,4 @@ ru:
layout:
pull_requests:
search: Найти пул реквест...
view_full_changes: Посмотреть все изменения

View File

@ -48,6 +48,7 @@ ru:
invalid_content_type: имеет неверный тип
atom_link_tag_title: Приватная лента для %{nickname} | %{app_name}
preview: Предосмотр
link: Ссылка
settings:
label: 'Настройки'

View File

@ -12,6 +12,7 @@ Rosa::Application.routes.draw do
namespace :api do
namespace :v1 do
resources :advisories, :only => [:index, :show, :create, :update]
resources :build_lists, :only => [:index, :create, :show] do
member {
get :publish
@ -256,6 +257,7 @@ Rosa::Application.routes.draw do
end
post '/preview' => 'projects#preview', :as => 'md_preview'
post 'refs_list' => 'projects#refs_list', :as => 'refs_list'
get '/pull_requests/:issue_id/add_line_comments(.:format)' => "comments#new_line", :as => :new_line_pull_comment
end
# Resource
@ -281,6 +283,7 @@ Rosa::Application.routes.draw do
get '/commit/:commit_id/comments/:id(.:format)' => "comments#edit", :as => :edit_project_commit_comment
put '/commit/:commit_id/comments/:id(.:format)' => "comments#update", :as => :project_commit_comment
delete '/commit/:commit_id/comments/:id(.:format)' => "comments#destroy"
get '/commit/:commit_id/add_line_comments(.:format)' => "comments#new_line", :as => :new_line_commit_comment
# Commit subscribes
post '/commit/:commit_id/subscribe' => "commit_subscribes#create", :as => :subscribe_commit
delete '/commit/:commit_id/unsubscribe' => "commit_subscribes#destroy", :as => :unsubscribe_commit

View File

@ -0,0 +1,5 @@
class AddDataToComments < ActiveRecord::Migration
def change
add_column :comments, :data, :text
end
end

View File

@ -11,14 +11,14 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20121003154246) do
ActiveRecord::Schema.define(:version => 20121005100158) 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"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "advisories", :force => true do |t|
@ -53,8 +53,8 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
create_table "arches", :force => true do |t|
t.string "name", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "arches", ["name"], :name => "index_arches_on_name", :unique => true
@ -63,8 +63,8 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
t.integer "user_id"
t.string "provider"
t.string "uid"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "authentications", ["provider", "uid"], :name => "index_authentications_on_provider_and_uid", :unique => true
@ -75,8 +75,8 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
t.integer "level"
t.integer "status"
t.integer "build_list_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "version"
end
@ -110,8 +110,8 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
t.integer "project_id"
t.integer "arch_id"
t.datetime "notified_at"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "is_circle", :default => false
t.text "additional_repos"
t.string "name"
@ -142,10 +142,11 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
t.string "commentable_type"
t.integer "user_id"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.decimal "commentable_id", :precision => 50, :scale => 0
t.integer "project_id"
t.text "data"
end
create_table "event_logs", :force => true do |t|
@ -160,8 +161,8 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
t.string "controller"
t.string "action"
t.text "message"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "flash_notifies", :force => true do |t|
@ -175,8 +176,8 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
create_table "groups", :force => true do |t|
t.integer "owner_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "uname"
t.integer "own_projects_count", :default => 0, :null => false
t.text "description"
@ -193,8 +194,8 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
t.string "title"
t.text "body"
t.string "status", :default => "open"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "user_id"
t.datetime "closed_at"
t.integer "closed_by"
@ -254,14 +255,14 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
t.string "description"
t.string "name", :null => false
t.integer "parent_platform_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
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", :null => false
t.string "distrib_type"
end
add_index "platforms", ["name"], :name => "index_platforms_on_name", :unique => true, :case_sensitive => false
@ -270,16 +271,16 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
t.integer "platform_id"
t.string "login"
t.string "password"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "user_id"
end
create_table "product_build_lists", :force => true do |t|
t.integer "product_id"
t.integer "status", :default => 2, :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "product_build_lists", ["product_id"], :name => "index_product_build_lists_on_product_id"
@ -287,8 +288,8 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
create_table "products", :force => true do |t|
t.string "name", :null => false
t.integer "platform_id", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.text "build_script"
t.text "counter"
t.text "ks"
@ -307,8 +308,8 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
t.string "name"
t.string "version"
t.datetime "file_mtime"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "platform_id"
end
@ -317,25 +318,25 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
create_table "project_to_repositories", :force => true do |t|
t.integer "project_id"
t.integer "repository_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "projects", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
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
@ -363,8 +364,8 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
t.string "token"
t.boolean "approved", :default => false
t.boolean "rejected", :default => false
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "interest"
t.text "more"
t.string "language"
@ -378,16 +379,16 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
t.string "actor_type"
t.integer "target_id"
t.string "target_type"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
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"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "name", :null => false
t.boolean "publish_without_qa", :default => true
end
@ -399,8 +400,8 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
t.boolean "new_comment_reply", :default => true
t.boolean "new_issue", :default => true
t.boolean "issue_assign", :default => true
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
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
@ -411,8 +412,8 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
create_table "subscribes", :force => true do |t|
t.string "subscribeable_type"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "status", :default => true
t.integer "project_id"
t.decimal "subscribeable_id", :precision => 50, :scale => 0
@ -420,18 +421,21 @@ ActiveRecord::Schema.define(:version => 20121003154246) do
create_table "users", :force => true do |t|
t.string "name"
t.string "email", :default => "", :null => false
t.string "encrypted_password", :limit => 128, :default => "", :null => false
t.string "email", :default => "", :null => false
t.string "encrypted_password", :default => "", :null => false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
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 "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.text "professional_experience"
t.string "site"
t.string "company"
@ -440,14 +444,11 @@ ActiveRecord::Schema.define(:version => 20121003154246) 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"

View File

@ -1,95 +0,0 @@
# -*- encoding : utf-8 -*-
module Git
module Diff
class InlineCallback < ::Diff::Renderer::Base
def initialize diff_counter, path
@diff_counter = diff_counter
@path = path
end
def before_headerblock(block)
end
def after_headerblock(block)
end
def headerline(line)
"<tr class='header'>
<td class='line_numbers'>...</td>
<td class='line_numbers'>...</td>
<td class='header'>#{line}</td>
</tr>"
end
def addline(line)
"<tr class='changes'>
<td class='line_numbers'></td>
#{td_line_link "diff-F#{@diff_counter}R#{line.new_number}", line.new_number}
<td class='code ins'><pre>#{render_line(line)}</pre></td>
</tr>"
end
def remline(line)
"<tr class='changes'>
#{td_line_link "diff-F#{@diff_counter}L#{line.old_number}", line.old_number}
<td class='line_numbers'></td>
<td class='code del'><pre>#{render_line(line)}</pre></td>
</tr>"
end
def modline(line)
"<tr clas='chanes line'>
#{td_line_link "diff-F#{@diff_counter}L#{line.old_number}", line.old_number}
#{td_line_link "diff-F#{@diff_counter}R#{line.new_number}", line.new_number}
<td class='code unchanged modline'><pre>#{render_line(line)}</pre></td>
</tr>"
end
def unmodline(line)
"<tr class='changes unmodline'>
#{td_line_link "diff-F#{@diff_counter}L#{line.old_number}", line.old_number}
#{td_line_link "diff-F#{@diff_counter}R#{line.new_number}", line.new_number}
<td class='code unchanged unmodline'><pre>#{render_line(line)}</pre></td>
</tr>"
end
def sepline(line)
"<tr class='changes hunk-sep'>
<td class='line_numbers line_num_cut'>&hellip;</td>
<td class='line_numbers line_num_cut'>&hellip;</td>
<td class='code cut-line'></td>
</tr>"
end
def nonewlineline(line)
"<tr class='changes'>
#{td_line_link "diff-F#{@diff_counter}L#{line.old_number}", line.old_number}
#{td_line_link "diff-F#{@diff_counter}R#{line.new_number}", line.new_number}
<td class='code modline unmodline'><pre>#{render_line(line)}</pre></td>
</tr>"
end
protected
def escape(str)
str.to_s.gsub('&', '&amp;').gsub('<', '&lt;').gsub('>', '&gt;').gsub('"', '&#34;')
end
def render_line(line)
res = '<span class="diff-content">'
if line.inline_changes?
prefix, changed, postfix = line.segments.map{|segment| escape(segment) }
res += "#{prefix}<span class='idiff'>#{changed}</span>#{postfix}"
else
res += escape(line)
end
res += '</span>'
res
end
def td_line_link id, num
"<td class='line_numbers' id='#{id}'><a href='#{@path}##{id}'>#{num}</a></td>"
end
end
end
end

View File

@ -0,0 +1,144 @@
# -*- encoding : utf-8 -*-
require 'spec_helper'
shared_examples_for 'api advisories user with show rights' do
it 'should be able to perform show action' do
get :show, :id => @advisory.advisory_id, :format => :json
response.should be_success
end
it 'should be able to perform index action' do
get :index, :format => :json
response.should be_success
end
end
shared_examples_for 'api advisories user with admin rights' do
context 'api advisories user with create rights' do
let(:params) { {:build_list_id => @build_list.id, :advisory => {:description => 'test'}} }
it 'should be able to perform create action' do
post :create, params, :format => :json
response.should be_success
end
it 'ensures that advisory has been created' do
lambda { post :create, params, :format => :json }.should change{ Advisory.count }.by(1)
end
it 'ensures that build_list has been associated with advisory' do
post :create, params, :format => :json
@build_list.reload
@build_list.advisory.should_not be_nil
end
end
context 'api advisories user with update rights' do
let(:params) { {:id => @advisory.advisory_id, :build_list_id => @build_list.id} }
it 'should be able to perform update action' do
put :update, params, :format => :json
response.should be_success
end
it 'ensures that advisory has not been created' do
lambda { put :update, params, :format => :json }.should_not change{ Advisory.count }
end
it 'ensures that build_list has been associated with advisory' do
put :update, params, :format => :json
@build_list.reload
@build_list.advisory.should_not be_nil
end
end
end
shared_examples_for 'api advisories user without admin rights' do
context 'api advisories user without create rights' do
let(:params) { {:build_list_id => @build_list.id, :advisory => {:description => 'test'}} }
it 'should not be able to perform create action' do
post :create, params, :format => :json
response.should_not be_success
end
it 'ensures that advisory has not been created' do
lambda { post :create, params, :format => :json }.should_not change{ Advisory.count }
end
it 'ensures that build_list has not been associated with advisory' do
post :create, params, :format => :json
@build_list.reload
@build_list.advisory.should be_nil
end
end
context 'api advisories user without update rights' do
let(:params) { {:id => @advisory.advisory_id, :build_list_id => @build_list.id} }
it 'should not be able to perform update action' do
put :update, params, :format => :json
response.should_not be_success
end
it 'ensures that advisory has not been created' do
lambda { put :update, params, :format => :json }.should_not change{ Advisory.count }
end
it 'ensures that build_list has not been associated with advisory' do
put :update, params, :format => :json
@build_list.reload
@build_list.advisory.should be_nil
end
end
end
describe Api::V1::AdvisoriesController do
before do
stub_symlink_methods
@advisory = FactoryGirl.create(:advisory)
@build_list = FactoryGirl.create(:build_list_core)
@build_list.save_to_platform.update_column(:released, true)
@build_list.save_to_repository.update_column(:publish_without_qa, false)
@build_list.update_column(:status, BuildList::BUILD_PUBLISHED)
end
context 'for guest' do
if APP_CONFIG['anonymous_access']
it_should_behave_like 'api advisories user with show rights'
end
it 'should not be able to perform show action', :anonymous_access => false do
get :show, :id => @advisory.advisory_id, :format => :json
response.should_not be_success
end
it 'should not be able to perform index action', :anonymous_access => false do
get :index, :format => :json
response.should_not be_success
end
it_should_behave_like 'api advisories user without admin rights'
end
context 'for simple user' do
before do
@user = FactoryGirl.create(:user)
http_login(@user)
end
it_should_behave_like 'api advisories user with show rights'
it_should_behave_like 'api advisories user without admin rights'
end
context 'for admin' do
before do
@admin = FactoryGirl.create(:admin)
http_login(@admin)
end
it_should_behave_like 'api advisories user with show rights'
it_should_behave_like 'api advisories user with admin rights'
end
context 'for user who has access to update build_list' do
before do
@user = FactoryGirl.create(:user)
@build_list.save_to_platform.relations.create(:role => 'admin', :actor => @user)
http_login(@user)
end
it_should_behave_like 'api advisories user with show rights'
it_should_behave_like 'api advisories user with admin rights'
end
end

View File

@ -0,0 +1,7 @@
# -*- encoding : utf-8 -*-
FactoryGirl.define do
factory :advisory do
description { FactoryGirl.generate(:string) }
update_type 'security'
end
end