Merge branch 'master' into 465-use-pundit-instead-of-cancan

This commit is contained in:
Alexander Machehin 2015-04-14 19:21:42 +05:00
commit c7d5ca7305
32 changed files with 441 additions and 148 deletions

View File

@ -29,7 +29,7 @@ gem 'state_machines-activerecord'
gem 'redis-rails' gem 'redis-rails'
gem 'grack', git: 'git://github.com/rosa-abf/grack.git', require: 'git_http' gem 'grack', git: 'git://github.com/rosa-abf/grack.git', require: 'git_http'
gem 'grit', git: 'git://github.com/rosa-abf/grit.git', tag: '2.6.16' gem 'grit', git: 'git://github.com/rosa-abf/grit.git', tag: '2.6.17'
gem 'charlock_holmes' gem 'charlock_holmes'
gem 'github-linguist', '3.1.5', require: 'linguist' gem 'github-linguist', '3.1.5', require: 'linguist'
gem 'diff-display' gem 'diff-display'

View File

@ -34,8 +34,8 @@ GIT
GIT GIT
remote: git://github.com/rosa-abf/grit.git remote: git://github.com/rosa-abf/grit.git
revision: a9548c92188cc307e7af1dd41a733e7000a783a9 revision: b733f0ceefb44b18a9dec8f509ba5493dab59e4e
tag: 2.6.16 tag: 2.6.17
specs: specs:
grit (2.5.0) grit (2.5.0)
diff-lcs (~> 1.1) diff-lcs (~> 1.1)

View File

@ -75,15 +75,22 @@ CommentsController = (Comment, Preview, confirmMessage, $scope, compileHTML, $ro
else else
false false
vm.add = -> vm.add = ($event)->
$event.preventDefault()
$event.stopPropagation()
vm.processing = true vm.processing = true
promise = Comment.add(vm.project, vm.commentable, vm.new_body) Comment.add(vm.project, vm.commentable, vm.new_body)
promise.then (response) -> .success (data) ->
element = compileHTML.run($scope, response.data.html) element = compileHTML.run($scope, data.html)
list.append(element) list.append(element)
vm.new_body = '' vm.new_body = ''
location.hash = "#comment" + response.data.id; location.hash = "#comment" + data.id;
vm.processing = false
$.notify(data.message, 'success')
.error (data) ->
$.notify(data.message, 'error')
vm.processing = false vm.processing = false
false false
@ -91,8 +98,8 @@ CommentsController = (Comment, Preview, confirmMessage, $scope, compileHTML, $ro
vm.remove = (id) -> vm.remove = (id) ->
return false unless confirmMessage.show() return false unless confirmMessage.show()
vm.processing = true vm.processing = true
promise = Comment.remove(vm.project, vm.commentable, id) Comment.remove(vm.project, vm.commentable, id)
promise.then () -> .success (data)->
parent = $('#comment'+id+',#diff-comment'+id).parents('tr.line-comments') parent = $('#comment'+id+',#diff-comment'+id).parents('tr.line-comments')
if parent.find('.line-comment').length is 1 if parent.find('.line-comment').length is 1
# there is only one line comment, remove all line # there is only one line comment, remove all line
@ -100,16 +107,21 @@ CommentsController = (Comment, Preview, confirmMessage, $scope, compileHTML, $ro
else else
$('#comment'+id+',#diff-comment'+id+',#update-comment'+id).remove() $('#comment'+id+',#diff-comment'+id+',#update-comment'+id).remove()
$.notify(data.message, 'success')
vm.processing = false
.error (data)->
$.notify(data.message, 'error')
vm.processing = false vm.processing = false
false false
vm.update = (id) -> vm.update = (id) ->
vm.processing = true vm.processing = true
promise = Comment.update(vm.project, vm.commentable, id) Comment.update(vm.project, vm.commentable, id)
promise.then (response) -> .success (data) ->
form = $('#comment'+id+ ' .md_and_cm.cm-s-default').html(response.data.body) form = $('#comment'+id+ ' .md_and_cm.cm-s-default').html(data.body)
$.notify(data.message, 'success')
vm.processing = false vm.processing = false
form = $('.open-comment.comment-'+id) form = $('.open-comment.comment-'+id)
if form.length is 1 if form.length is 1
@ -117,6 +129,9 @@ CommentsController = (Comment, Preview, confirmMessage, $scope, compileHTML, $ro
return true return true
else else
return false return false
.error (data) ->
$.notify(data.message, 'error')
vm.processing = false
vm.showInlineForm = ($event, params = {}) -> vm.showInlineForm = ($event, params = {}) ->
line_comments = findInlineComments($event, params) line_comments = findInlineComments($event, params)

View File

@ -108,9 +108,8 @@ PullRequestController = (dataservice, $http, ApiPullRequest, ApiProject, DateTim
promise = ApiPullRequest.get_diff(vm.pull_params) promise = ApiPullRequest.get_diff(vm.pull_params)
promise.then (response) -> promise.then (response) ->
diff.html(null) diff.html(null)
#html = compileHTML.run($scope, response.data)
#diff.html(html)
$rootScope.$broadcast('compile_html', { element: diff, html: response.data }) $rootScope.$broadcast('compile_html', { element: diff, html: response.data })
$('[data-toggle="tooltip"]').tooltip()
vm.processing = false vm.processing = false
vm.is_diff_updated = true vm.is_diff_updated = true
false false

View File

@ -1,5 +1,5 @@
$(document).ready -> $(document).ready ->
$(document).on 'click', '#diff_header .panel-body table a', -> $(document).on 'click', '#diff_header .panel-body li.list-group-item a', ->
href = $(this).attr('href') href = $(this).attr('href')
$(".diff_data.collapse#"+href.slice(1)+"_content").collapse('show') $(".diff_data.collapse#"+href.slice(1)+"_content").collapse('show')

View File

@ -3,7 +3,7 @@
overflow-x: auto overflow-x: auto
table.table.diff.inline table.table.diff.inline
//border: 1px solid #DDD margin-bottom: 0
tr.changes tr.changes
pre pre
@ -66,17 +66,6 @@ table.table.diff.inline
.line-comment, #new_inline_comment .line-comment, #new_inline_comment
max-width: 700px max-width: 700px
td.diff-image
text-align: center
span.diff-image
text-align: center
margin: 0
padding: 0
img
margin-top: 5px
div.file div.top div.file div.top
min-height: 28px min-height: 28px
background: #ededed background: #ededed

View File

@ -6,15 +6,19 @@ class Projects::CommentsController < Projects::BaseController
include CommentsHelper include CommentsHelper
def create def create
if !@comment.set_additional_data params respond_to do |format|
render json: { if !@comment.set_additional_data params
error: I18n.t("flash.comment.save_error"), format.json {
message: @comment.errors.full_messages render json: {
} message: I18n.t("flash.comment.save_error"),
elsif @comment.save error: @comment.errors.full_messages
render :create }
else }
render json: { error: I18n.t("flash.comment.save_error") }, status: 422 elsif @comment.save
format.json {}
else
format.json { render json: { message: I18n.t("flash.comment.save_error") }, status: 422 }
end
end end
end end
@ -22,17 +26,24 @@ class Projects::CommentsController < Projects::BaseController
end end
def update def update
status, message = if @comment.update_attributes(params[:comment]) respond_to do |format|
[200, view_context.markdown(@comment.body)] if @comment.update_attributes(params[:comment])
else format.json { render json: {message:t('flash.comment.updated'), body: view_context.markdown(@comment.body)} }
[422, 'error'] else
format.json { render json: {message:t('flash.comment.error_in_updating')}, status: 422 }
end
end end
render json: {body: message}, status: status
end end
def destroy def destroy
@comment.destroy respond_to do |format|
render json: nil if @comment.present? && @comment.destroy
format.json { render json: {message: I18n.t('flash.comment.destroyed')} }
else
format.json {
render json: {message: t('flash.comment.error_in_deleting')}, status: 422 }
end
end
end end
protected protected

View File

@ -14,7 +14,7 @@ class Projects::Git::CommitsController < Projects::Git::BaseController
respond_to do |format| respond_to do |format|
format.html format.html
format.diff { render text: (@commit.diffs.map(&:diff).join("\n") rescue ''), content_type: "text/plain" } format.diff { render text: (@commit.show.map(&:diff).join("\n") rescue ''), content_type: "text/plain" }
format.patch { render text: (@commit.to_patch rescue ''), content_type: "text/plain" } format.patch { render text: (@commit.to_patch rescue ''), content_type: "text/plain" }
end end
end end

View File

@ -1,23 +1,31 @@
module CommitHelper module CommitHelper
MAX_FILES_WITHOUT_COLLAPSE = 25 MAX_FILES_WITHOUT_COLLAPSE = 25
def render_commit_stats(stats) def render_commit_stats(options = {})
res = ["<table class='table table-responsive boffset0'>"] stats = options[:stats]
diff = options[:diff]
repo = options[:repo]
commit = options[:commit]
parent_commit = commit.parents.try(:first)
res = ["<ul class='list-group boffset0'>"]
ind=0 ind=0
stats.files.each do |filename, adds, deletes, total| stats.files.each do |filename, adds, deletes, total|
res << "<tr>" file_name = get_filename_in_diff(diff[ind], filename)
res << "<td><a href='#diff-#{ind}'>#{h(filename.rtruncate 120)}</a></td>" file_status = t "layout.projects.diff.#{get_file_status_in_diff(diff[ind])}"
res << "<td class='diffstat'>" res << "<li class='list-group-item'>"
res << I18n.t("layout.projects.inline_changes_count", count: total).strip + res << "<div class='row'>"
" (" + res << "<div class='col-sm-8'>"
I18n.t("layout.projects.inline_additions_count", count: adds).strip + res << "<a href='#diff-#{ind}' data-toggle='tooltip' data-placement='top' title='#{file_status}'>"
", " + res << "#{diff_file_icon(diff[ind])} #{h(file_name)}"
I18n.t("layout.projects.inline_deletions_count", count: deletes).strip + res << "</a></div>"
")" res << render_file_changes(diff: diff[ind], adds: adds, deletes: deletes, total: total,
res << "</td>" repo: repo, commit: commit, parent_commit: parent_commit, file_status: file_status)
res << "</div"
res << "</li>"
ind +=1 ind +=1
end end
res << "</table>" res << "</ul>"
wrap_commit_header_list(stats, res) wrap_commit_header_list(stats, res)
end end
@ -73,9 +81,116 @@ module CommitHelper
Russian.p(commits_count, *commits_pluralization_arr) Russian.p(commits_count, *commits_pluralization_arr)
end end
def is_file_open_in_diff(blob, diff)
return true if blob.binary? && blob.render_as == :image
return true if diff.diff.blank? && diff.a_mode != diff.b_mode
diff.diff.present? && diff.diff.split("\n").count <= DiffHelper::MAX_LINES_WITHOUT_COLLAPSE
end
def file_blob_in_diff(repo, commit_id, diff)
return if repo.nil? || commit_id.nil? || diff.nil?
tree = repo.tree(commit_id)
blob = diff.renamed_file ? (tree / diff.b_path) : (tree / (diff.a_path || diff.b_path))
blob || diff.a_blob || diff.b_blob
end
def get_commit_id_for_file(diff, commit, parent_commit)
diff.deleted_file ? parent_commit.id : commit.id
end
def get_file_status_in_diff(diff)
if diff.renamed_file
:renamed_file
elsif diff.new_file
:new_file
elsif diff.deleted_file
:deleted_file
else
:changed_file
end
end
def get_filename_in_diff(diff, filename)
if diff.renamed_file
"#{diff.a_path.rtruncate 50} => #{diff.b_path.rtruncate 50}"
else
filename.rtruncate(100)
end
end
protected protected
def commits_pluralization_arr def commits_pluralization_arr
pluralize ||= t('layout.commits.pluralize').map {|base, title| title.to_s} pluralize ||= t('layout.commits.pluralize').map {|base, title| title.to_s}
end end
def render_file_changes(options = {})
diff = options[:diff]
adds = options[:adds]
deletes = options[:deletes]
total = options[:total]
repo = options[:repo]
file_status = options[:file_status]
commit_id = get_commit_id_for_file(diff, options[:commit], options[:parent_commit])
blob = file_blob_in_diff(repo, commit_id, diff)
res = ''
res << "<div class='col-sm-3'>"
res << "<div class='pull-right'>"
if blob.binary?
res << "<strong class='text-primary'>#{t 'layout.projects.diff.binary'} #{file_status}</strong>"
elsif total > 0
res << "<strong class='text-success'>+#{adds}</strong> <strong class='text-danger'>-#{deletes}</strong>"
else # total == 0
res << "<strong class='text-primary'>#{t 'layout.projects.diff.without_changes'}</strong>"
end
res << "</div>"
res << "</div>"
res << "<div class='col-sm-1'>"
res << render_progress_bar(adds, deletes, total, blob)
res << "</div>"
end
def render_progress_bar(adds, deletes, total, blob)
res = ''
pluses = 0
minuses = 0
if total > 0
pluses = ((adds/(adds+deletes).to_f)*100).round
minuses = 100 - pluses
end
title = if total >0
t 'layout.projects.inline_changes_count', count: total
elsif !blob.binary?
t 'layout.projects.diff.without_changes'
else
'BIN'
end
res << "<div class='progress' style='margin-bottom: 0' data-toggle='tooltip' data-placement='top' title='#{title}'>"
res << "<div class='progress-bar progress-bar-success' style='width: #{pluses}%'></div>"
res << "<div class='progress-bar progress-bar-danger' style='width: #{minuses}%'></div>"
res << "</div>"
res
end
def diff_file_icon(diff)
icon = case get_file_status_in_diff(diff)
when :renamed_file
'fa-caret-square-o-right text-info'
when :new_file
'fa-plus-square text-success'
when :deleted_file
'fa-minus-square text-danger'
when :changed_file
'fa-pencil-square text-primary'
else
'fa-exclamation-circle text-danger'
end
"<i class='fa #{icon}'></i>"
end
end end

View File

@ -1,26 +1,41 @@
module DiffHelper module DiffHelper
MAX_FILES_WITHOUT_COLLAPSE = 25 include CommitHelper
MAX_LINES_WITHOUT_COLLAPSE = 50 MAX_LINES_WITHOUT_COLLAPSE = 50
def render_diff_stats(stats) def render_diff_stats(options = {})
res = ["<table class='table table-responsive boffset0'>"] stats = options[:stats]
diff = options[:diff]
repo = options[:repo]
commit = options[:commit]
parent_commit = options[:common_ancestor]
res = ["<ul class='list-group boffset0'>"]
stats.each_with_index do |stat, ind| stats.each_with_index do |stat, ind|
res << "<tr>" adds = stat.additions
res << "<td>#{link_to stat.filename.rtruncate(120), "#diff-#{ind}"}</td>" deletes = stat.deletions
res << "<td class='diffstat'>" total = adds + deletes
res << I18n.t("layout.projects.inline_changes_count", count: stat.additions + stat.deletions).strip + file_name = get_filename_in_diff(diff[ind], stat.filename)
" (" + file_status = t "layout.projects.diff.#{get_file_status_in_diff(diff[ind])}"
I18n.t("layout.projects.inline_additions_count", count: stat.additions).strip +
", " + res << "<li class='list-group-item'>"
I18n.t("layout.projects.inline_deletions_count", count: stat.deletions).strip + res << "<div class='row'>"
")" res << "<div class='col-sm-8'>"
res << "</td>" res << "<a href='#diff-#{ind}' data-toggle='tooltip' data-placement='top' title='#{file_status}'>"
res << "#{diff_file_icon(diff[ind])} #{h(file_name)}"
res << "</a></div>"
res << render_file_changes(diff: diff[ind], adds: adds, deletes: deletes, total: total,
repo: repo, commit: commit, parent_commit: parent_commit, file_status: file_status)
res << "</div"
res << "</li>"
ind +=1
end end
res << '</table>' res << "</ul>"
wrap_header_list(stats, res)
wrap_diff_header_list(stats, res)
end end
def wrap_header_list(stats, list) def wrap_diff_header_list(stats, list)
is_stats_open = stats.count <= MAX_FILES_WITHOUT_COLLAPSE ? 'in' : '' is_stats_open = stats.count <= MAX_FILES_WITHOUT_COLLAPSE ? 'in' : ''
res = ["<div class='panel-group' id='diff_header' role='tablist' aria-multiselectable='false'>"] res = ["<div class='panel-group' id='diff_header' role='tablist' aria-multiselectable='false'>"]
res << "<div class='panel panel-default'>" res << "<div class='panel panel-default'>"

View File

@ -65,7 +65,7 @@ class Comment < ActiveRecord::Base
end end
return data[:actual] = true if commentable_type == 'Grit::Commit' return data[:actual] = true if commentable_type == 'Grit::Commit'
filepath, line_number = data[:path], data[:line] filepath, line_number = data[:path], data[:line]
diff_path = (diff || commentable.diffs ).select {|d| d.a_path == data[:path]} diff_path = (diff || commentable.show ).select {|d| d.a_path == data[:path]}
comment_line = data[:line].to_i comment_line = data[:line].to_i
# NB! also dont create a comment to the diff header # NB! also dont create a comment to the diff header
return data[:actual] = false if diff_path.blank? || comment_line == 0 return data[:actual] = false if diff_path.blank? || comment_line == 0

View File

@ -163,9 +163,8 @@ class PullRequest < ActiveRecord::Base
@diff_stats ||= repo.diff_stats(to_commit.id, from_commit.id) @diff_stats ||= repo.diff_stats(to_commit.id, from_commit.id)
end end
# FIXME maybe move to warpc/grit?
def diff def diff
@diff ||= Grit::Commit.diff(repo, to_commit.id, from_commit.id) @diff ||= repo.diff(to_commit.id, from_commit.id)
end end
def set_user_and_time user def set_user_and_time user

View File

@ -13,7 +13,7 @@ h3
ang_model: 'new_body' ang_model: 'new_body'
hr hr
button.btn.btn-primary[ ng-disabled = 'commentsCtrl.isDisabledNewCommentButton()' button.btn.btn-primary[ ng-disabled = 'commentsCtrl.isDisabledNewCommentButton()'
ng-click = 'commentsCtrl.add()' ] ng-click = 'commentsCtrl.add($event)' ]
= t('layout.create') = t('layout.create')
.panel-footer .panel-footer
=> t('layout.comments.notifications_are') => t('layout.comments.notifications_are')

View File

@ -1,2 +1,3 @@
json.id @comment.id json.id @comment.id
json.html render partial: 'projects/comments/line_comment.html.slim' json.html render partial: 'projects/comments/line_comment.html.slim'
json.message t('flash.comment.saved')

View File

@ -12,6 +12,6 @@
ul.list-group ul.list-group
- commits.each_with_index do |commit| - commits.each_with_index do |commit|
li.list-group-item li.list-group-item
- GitPresenters::CommitAsMessagePresenter.present(commit, project: @project) do |presenter| - GitPresenters::CommitAsMessagePresenter.present(commit, project: project) do |presenter|
== render 'shared/feed_commit', presenter: presenter, item_no: counter == render 'shared/feed_commit', presenter: presenter, item_no: counter
- counter += 1 - counter += 1

View File

@ -1,9 +1,8 @@
- commit_id = diff.deleted_file ? parent_commit.try(:id) : @commit.id - parent_commit = defined?(common_ancestor) ? common_ancestor : commit.parents.try(:first)
- commit_id = get_commit_id_for_file diff, commit, parent_commit
- diff_counter_content = "diff-#{diff_counter}_content" - diff_counter_content = "diff-#{diff_counter}_content"
- blob = file_blob_in_diff(@project.repo, commit_id, diff)
- if diff.diff.present? - is_file_open = 'in' if is_file_open_in_diff(blob, diff)
- blob = @project.repo.tree(commit_id) / diff.a_path
- is_file_open = 'in' if !blob.binary? && diff.diff.split("\n").count <= DiffHelper::MAX_LINES_WITHOUT_COLLAPSE
.file.offset10 .file.offset10
a name = "diff-#{diff_counter}" a name = "diff-#{diff_counter}"
@ -14,23 +13,23 @@
aria-expanded = 'true' aria-expanded = 'true'
aria-controls = diff_counter_content ] aria-controls = diff_counter_content ]
span.fa class= (is_file_open ? 'fa-chevron-down' : 'fa-chevron-up') span.fa class= (is_file_open ? 'fa-chevron-down' : 'fa-chevron-up')
=< h(diff.a_path.rtruncate 120) =< diff_file_icon(diff).html_safe
=< get_filename_in_diff(diff, diff.a_path)
- if diff.b_path.present? - if diff.b_path.present?
button.btn.btn-link.pull-right button.btn.btn-link.pull-right
= link_to "view file @ #{shortest_hash_id(commit_id)}", blob_path(@project, commit_id, diff.b_path) = link_to "view file @ #{shortest_hash_id(commit_id)}", blob_path(@project, commit_id, diff.b_path)
.clearfix .clearfix
- if diff.diff.present? .diff_data.collapse id= diff_counter_content class= is_file_open
.diff_data.collapse[ id = diff_counter_content class = is_file_open ] - if blob.respond_to?(:render_as) && blob.render_as == :image && diff.diff.present?
- old_blob = file_blob_in_diff(@project.repo, parent_commit.try(:id), diff)
== render 'show_image', diff: diff, blob: blob, old_blob: old_blob
- if blob.render_as == :image - if diff.a_mode != diff.b_mode && diff.diff.blank?
table.table.diff.inline.table-bordered[ cellspacing = 0 cellpadding = 0 ] == render 'file_change_mode', blob: blob, diff: diff
tr
td.diff-image - elsif diff.diff.blank? && diff.renamed_file
span.diff-image == render 'file_removed_not_changed', blob: blob
img[ src = "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}"
style = 'max-width: 600px;' ] - elsif !blob.binary?
- elsif !blob.binary? == render_diff(diff, diff_counter: diff_counter, comments: @comments)
- if (@project.repo.tree(commit_id) / diff.b_path).nil?
= "a_path=#{diff.a_path}; b_path=#{diff.b_path}"
== render_diff(diff, diff_counter: diff_counter, comments: @comments)

View File

@ -0,0 +1,10 @@
.table-responsive.overflow-auto
table.table.diff.inline.table-borderless cellspacing= 0 cellpadding= 0
tr.header
td.line_numbers[] ...
td.line_numbers[] ...
td.header.text-danger= "oldmode #{diff.a_mode}"
tr.header
td.line_numbers[] ...
td.line_numbers[] ...
td.header.text-success= "newmode #{diff.b_mode}"

View File

@ -0,0 +1,9 @@
.table-responsive.overflow-auto
table.table.diff.inline.table-borderless cellspacing= 0 cellpadding= 0
tr.header
td.line_numbers[] ...
td.line_numbers[] ...
td.header
strong.text-primary
- binary = t('layout.projects.diff.binary') if blob.binary?
= "#{binary} #{ t 'layout.projects.diff.renamed_file'} #{t 'layout.projects.diff.without_changes'}"

View File

@ -1,6 +1,7 @@
- begin - begin
- stats = @commit.stats - diffs = @commit.show
= render_commit_stats(stats) - stats = Grit::CommitStats.find_all(@project.repo, @commit.sha, max_count: 1, skip: 0)[0][-1]
= render_commit_stats(stats: stats, diff: @commit.show, repo: @project.repo, commit: @commit)
.pull-right .pull-right
=> link_to 'raw diff', commit_path(@project, @commit.id, :diff) => link_to 'raw diff', commit_path(@project, @commit.id, :diff)
@ -8,6 +9,6 @@
=< link_to 'patch', commit_path(@project, @commit.id, :patch) =< link_to 'patch', commit_path(@project, @commit.id, :patch)
.clearfix .clearfix
== render partial: 'diff', collection: @commit.diffs, locals: { parent_commit: @commit.parents.try(:first) } == render partial: 'diff', collection: diffs, locals: { commit: @commit }
- rescue Grit::Git::GitTimeout - rescue Grit::Git::GitTimeout
h3.text-danger= t('layout.git.repositories.commit_diff_too_big') h3.text-danger= t('layout.git.repositories.commit_diff_too_big')

View File

@ -0,0 +1,18 @@
.row
- if get_file_status_in_diff(diff) == :changed_file
.col-md-6.col-xs-12
p.text-center.text-danger= t 'layout.projects.diff.deleted_file'
img[ class= 'img-responsive center-block'
src= "data:#{old_blob.mime_type};base64,#{Base64.encode64(old_blob.data)}"
style= 'border: 1px solid red;' ]
.col-md-6.col-xs-12
p.text-center.text-success= t 'layout.projects.diff.new_file'
img[ class= 'img-responsive center-block'
src= "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}"
style= 'border: 1px solid green;' ]
- else
.col-xs-12
img[ class= 'img-responsive center-block offset10'
src= "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}"
style= 'border: 1px solid #87CEFA;' ]

View File

@ -12,18 +12,13 @@
h3= title h3= title
#repo-wrapper #repo-wrapper
.leftside
-total_additions = @stats.inject(0) {|sum, n| sum + n.additions}
-total_deletions = @stats.inject(0) {|sum, n| sum + n.deletions}
h5= t("layout.projects.diff_show_header",
files: t("layout.projects.commit_files_count", count: @stats.count),
additions: t("layout.projects.commit_additions_count", count: total_additions),
deletions: t("layout.projects.commit_deletions_count", count: total_deletions))
-begin -begin
== render_diff_stats @stats - diffs = @project.repo.diff @common_ancestor.id, @commit.id
- diffs = Grit::Commit.diff(@project.repo, @common_ancestor.id, @commit.id) == render_diff_stats(stats: @stats, diff: diffs, repo: @project.repo,
== render partial: 'projects/git/commits/diff', collection: diffs, locals: { parent_commit: @common_ancestor } commit: @commit, common_ancestor: @common_ancestor)
== render partial: 'projects/git/commits/diff', collection: diffs,
locals: { commit: @commit, common_ancestor: @common_ancestor}
- rescue Grit::Git::GitTimeout - rescue Grit::Git::GitTimeout
p= t 'layout.git.repositories.commit_diff_too_big' p= t 'layout.git.repositories.commit_diff_too_big'

View File

@ -1,6 +1,8 @@
-begin -begin
== render_diff_stats(@stats) - diff = @pull.diff
== render partial: 'pull_diff', collection: @pull.diff == render_diff_stats(stats: @stats, diff: diff, repo: @pull.repo,
commit: @pull.from_commit, common_ancestor: @pull.to_commit)
== render partial: 'pull_diff', collection: diff
- rescue => ex - rescue => ex
-if ex.try(:message) == 'Grit::Git::GitTimeout' -if ex.try(:message) == 'Grit::Git::GitTimeout'
p= t 'layout.git.repositories.commit_diff_too_big' p= t 'layout.git.repositories.commit_diff_too_big'

View File

@ -1,10 +1,11 @@
- commit_id = pull_diff.deleted_file ? @pull.to_commit.id : @pull.from_commit.id - diff = pull_diff
- diff_counter = "diff-#{pull_diff_counter}" - diff_counter = "diff-#{pull_diff_counter}"
- diff_counter_content = "#{diff_counter}_content"
-if pull_diff.diff.present? - parent_commit = @pull.to_commit
- blob = @pull.repo.tree(commit_id) / pull_diff.b_path - commit_id = get_commit_id_for_file diff, @pull.from_commit, parent_commit
- is_file_open = 'in' if !blob.binary? && pull_diff.diff.split("\n").count <= DiffHelper::MAX_LINES_WITHOUT_COLLAPSE - diff_counter_content = "#{diff_counter}_content"
- blob = file_blob_in_diff(@pull.repo, commit_id, diff)
- is_file_open = 'in' if is_file_open_in_diff(blob, diff)
.file.offset10 .file.offset10
a name = diff_counter a name = diff_counter
@ -15,19 +16,23 @@
aria-expanded = 'true' aria-expanded = 'true'
aria-controls = diff_counter_content ] aria-controls = diff_counter_content ]
span.fa class= (is_file_open ? 'fa-chevron-down' : 'fa-chevron-up') span.fa class= (is_file_open ? 'fa-chevron-down' : 'fa-chevron-up')
=< h(pull_diff.renamed_file ? "#{pull_diff.a_path.rtruncate 60}=>#{pull_diff.b_path.rtruncate 60}" : pull_diff.b_path.rtruncate(120)) =< diff_file_icon(diff).html_safe
=< get_filename_in_diff(diff, diff.a_path)
- if @pull.from_project.present? - if @pull.from_project.present?
button.btn.btn-link.pull-right button.btn.btn-link.pull-right
= link_to "view file @ #{short_hash_id(commit_id)}", blob_path(@pull.from_project, commit_id, pull_diff.b_path) = link_to "view file @ #{short_hash_id(commit_id)}", blob_path(@pull.from_project, commit_id, pull_diff.b_path)
.clearfix .clearfix
-if pull_diff.diff.present? .diff_data.collapse id= diff_counter_content class= is_file_open
.diff_data.collapse[ id = diff_counter_content class = is_file_open ] - if blob.render_as == :image && diff.diff.present?
- if blob.render_as == :image - old_blob = file_blob_in_diff(@project.repo, parent_commit.id, diff)
table.table.diff.inline.table-bordered[ cellspacing = 0 cellpadding = 0 ] == render 'projects/git/commits/show_image', diff: diff, blob: blob, old_blob: old_blob
tr
td.diff-image - if diff.a_mode != diff.b_mode && diff.diff.blank?
span.diff-image == render 'file_change_mode', blob: blob, diff: diff
img[ src = "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}"
style = 'max-width: 600px;' ] - elsif diff.diff.blank? && diff.renamed_file
== render 'projects/git/commits/file_removed_not_changed', blob: blob
- elsif !blob.binary?
== render_diff(pull_diff, diff_counter: pull_diff_counter, comments: @comments) unless blob.binary? == render_diff(pull_diff, diff_counter: pull_diff_counter, comments: @comments) unless blob.binary?

View File

@ -47,6 +47,9 @@ en:
saved: Comment saved saved: Comment saved
save_error: Error while saving comment save_error: Error while saving comment
destroyed: Comment deleted destroyed: Comment deleted
error_in_deleting: Error deleting comment
updated: Comment updated
error_in_updating: Error updating comment
activerecord: activerecord:
attributes: attributes:

View File

@ -43,9 +43,12 @@ ru:
flash: flash:
comment: comment:
saved: Комментарий успешно сохранен saved: Комментарий сохранен
save_error: Ошибка сохранения комментария save_error: Ошибка сохранения комментария
destroyed: Комментарий удален destroyed: Комментарий удален
error_in_deleting: Ошибка при удалении комментария
updated: Комментарий обновлен
error_in_updating: Ошибка при обновлении комментария
activerecord: activerecord:
attributes: attributes:

View File

@ -94,6 +94,14 @@ en:
public: Public public: Public
private: Private private: Private
diff:
binary: Binary
new_file: file added
deleted_file: file removed
renamed_file: file renamed
changed_file: file changed
without_changes: without changes
flash: flash:
project: project:
mass_import_added_to_queue: Mass import added to queue mass_import_added_to_queue: Mass import added to queue

View File

@ -95,6 +95,14 @@ ru:
public: Публичные public: Публичные
private: Приватные private: Приватные
diff:
binary: Бинарный
new_file: файл добавлен
deleted_file: файл удален
renamed_file: файл переименован
changed_file: файл изменен
without_changes: без изменений
flash: flash:
project: project:
mass_import_added_to_queue: Массовый импорт добавлен в очередь mass_import_added_to_queue: Массовый импорт добавлен в очередь

View File

@ -11,12 +11,6 @@ en:
one: "%{count} deletion" one: "%{count} deletion"
other: "%{count} deletions" other: "%{count} deletions"
inline_additions_count:
one: "%{count} addition"
other: "%{count} additions"
inline_deletions_count:
one: "%{count} deletion"
other: "%{count} deletions"
inline_changes_count: inline_changes_count:
one: "%{count} change" one: "%{count} change"
other: "%{count} changes" other: "%{count} changes"

View File

@ -14,14 +14,6 @@ ru:
few: "%{count} удалениями" few: "%{count} удалениями"
many: "%{count} удалениями" many: "%{count} удалениями"
inline_additions_count:
one: "%{count} добавление"
few: "%{count} добавления"
many: "%{count} добавлений"
inline_deletions_count:
one: "%{count} удаление"
few: "%{count} удаления"
many: "%{count} удалений"
inline_changes_count: inline_changes_count:
one: "%{count} изменение" one: "%{count} изменение"
few: "%{count} изменения" few: "%{count} изменения"

View File

@ -7,7 +7,9 @@ class String
force_encoding(default_encoding) force_encoding(default_encoding)
else # should encode else # should encode
options = {invalid: :replace, undef: :replace, replace: ''} options = {invalid: :replace, undef: :replace, replace: ''}
if (detected = detect_encoding) && detected[:encoding] if encoding.name == 'UTF-8'
encode!(default_encoding, 'UTF-8', options)
elsif (detected = detect_encoding) && detected[:encoding]
force_encoding(detected[:encoding]).encode!(default_encoding, detected[:encoding], options) force_encoding(detected[:encoding]).encode!(default_encoding, detected[:encoding], options)
end end
scrub('') scrub('')

View File

@ -63,8 +63,7 @@ module Grit
end end
def diff(a, b, *paths) def diff(a, b, *paths)
diff = self.git.native('diff', {M: true}, "#{a}...#{b}", '--', *paths) diff = self.git.native('diff', {}, "#{a}...#{b}", '--', *paths)
if diff =~ /diff --git a/ if diff =~ /diff --git a/
diff = diff.sub(/.*?(diff --git a)/m, '\1') diff = diff.sub(/.*?(diff --git a)/m, '\1')
else else

101
lib/ext/posix_spawn.rb Normal file
View File

@ -0,0 +1,101 @@
require 'posix/spawn'
module POSIX
module Spawn
class Child
include POSIX::Spawn
private
# Start a select loop writing any input on the child's stdin and reading
# any output from the child's stdout or stderr.
#
# input - String input to write on stdin. May be nil.
# stdin - The write side IO object for the child's stdin stream.
# stdout - The read side IO object for the child's stdout stream.
# stderr - The read side IO object for the child's stderr stream.
# timeout - An optional Numeric specifying the total number of seconds
# the read/write operations should occur for.
#
# Returns an [out, err] tuple where both elements are strings with all
# data written to the stdout and stderr streams, respectively.
# Raises TimeoutExceeded when all data has not been read / written within
# the duration specified in the timeout argument.
# Raises MaximumOutputExceeded when the total number of bytes output
# exceeds the amount specified by the max argument.
def read_and_write(input, stdin, stdout, stderr, timeout=nil, max=nil)
max = nil if max && max <= 0
@out, @err = '', ''
offset = 0
# force all string and IO encodings to BINARY under 1.9 for now
#if @out.respond_to?(:force_encoding) and stdin.respond_to?(:set_encoding)
# [stdin, stdout, stderr].each do |fd|
# fd.set_encoding('BINARY', 'BINARY')
# end
# @out.force_encoding('BINARY')
# @err.force_encoding('BINARY')
# input = input.dup.force_encoding('BINARY') if input
#end
timeout = nil if timeout && timeout <= 0.0
@runtime = 0.0
start = Time.now
readers = [stdout, stderr]
writers =
if input
[stdin]
else
stdin.close
[]
end
slice_method = input.respond_to?(:byteslice) ? :byteslice : :slice
t = timeout
while readers.any? || writers.any?
ready = IO.select(readers, writers, readers + writers, t)
raise TimeoutExceeded if ready.nil?
# write to stdin stream
ready[1].each do |fd|
begin
boom = nil
size = fd.write_nonblock(input)
input = input.send(slice_method, size..-1)
rescue Errno::EPIPE => boom
rescue Errno::EAGAIN, Errno::EINTR
end
if boom || input.bytesize == 0
stdin.close
writers.delete(stdin)
end
end
# read from stdout and stderr streams
ready[0].each do |fd|
buf = (fd == stdout) ? @out : @err
begin
buf << fd.readpartial(BUFSIZE)
rescue Errno::EAGAIN, Errno::EINTR
rescue EOFError
readers.delete(fd)
fd.close
end
end
# keep tabs on the total amount of time we've spent here
@runtime = Time.now - start
if timeout
t = timeout - @runtime
raise TimeoutExceeded if t < 0.0
end
# maybe we've hit our max output
if max && ready[0].any? && (@out.size + @err.size) > max
raise MaximumOutputExceeded
end
end
[@out.mb_chars.default_encoding!, @err.mb_chars.default_encoding!]
end
end
end
end