Defect #8857 » 0001-Pass-revisions-to-git-log-via-stdin.patch
lib/redmine/scm/adapters/abstract_adapter.rb | ||
---|---|---|
206 | 206 |
self.class.logger |
207 | 207 |
end |
208 | 208 | |
209 |
def shellout(cmd, &block) |
|
210 |
self.class.shellout(cmd, &block) |
|
209 |
def shellout(cmd, options = {}, &block)
|
|
210 |
self.class.shellout(cmd, options, &block)
|
|
211 | 211 |
end |
212 | 212 | |
213 | 213 |
def self.logger |
214 | 214 |
Rails.logger |
215 | 215 |
end |
216 | 216 | |
217 |
def self.shellout(cmd, &block) |
|
217 |
def self.shellout(cmd, options = {}, &block)
|
|
218 | 218 |
if logger && logger.debug? |
219 | 219 |
logger.debug "Shelling out: #{strip_credential(cmd)}" |
220 | 220 |
end |
... | ... | |
223 | 223 |
cmd = "#{cmd} 2>>#{shell_quote(Rails.root.join('log/scm.stderr.log').to_s)}" |
224 | 224 |
end |
225 | 225 |
begin |
226 |
if RUBY_VERSION < '1.9' |
|
227 |
mode = "r+" |
|
228 |
else |
|
229 |
mode = "r+:ASCII-8BIT" |
|
230 |
end |
|
226 |
mode = (options[:mode] || 'r').to_s |
|
231 | 227 |
IO.popen(cmd, mode) do |io| |
232 |
io.close_write
|
|
228 |
io.set_encoding("ASCII-8BIT") if io.respond_to?(:set_encoding)
|
|
233 | 229 |
block.call(io) if block_given? |
234 | 230 |
end |
235 | 231 |
## If scm command does not exist, |
lib/redmine/scm/adapters/git_adapter.rb | ||
---|---|---|
197 | 197 | |
198 | 198 |
def revisions(path, identifier_from, identifier_to, options={}) |
199 | 199 |
revs = Revisions.new |
200 |
cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller --parents| |
|
200 |
cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller --parents --stdin|
|
|
201 | 201 |
cmd_args << "--reverse" if options[:reverse] |
202 | 202 |
cmd_args << "-n" << "#{options[:limit].to_i}" if options[:limit] |
203 |
from_to = "" |
|
203 |
cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty? |
|
204 |
revisions = [] |
|
204 | 205 |
if identifier_from || identifier_to |
205 |
from_to << "#{identifier_from}.." if identifier_from
|
|
206 |
from_to << "#{identifier_to}" if identifier_to
|
|
207 |
cmd_args << from_to if !from_to.empty?
|
|
206 |
revisions << ""
|
|
207 |
revisions[0] << "#{identifier_from}.." if identifier_from
|
|
208 |
revisions[0] << "#{identifier_to}" if identifier_to
|
|
208 | 209 |
else |
209 |
cmd_args += options[:includes] unless options[:includes].blank? |
|
210 |
unless options[:includes].blank? |
|
211 |
revisions += ignore_missing_revisions(options[:includes]) |
|
212 |
end |
|
210 | 213 |
unless options[:excludes].blank? |
211 |
cmd_args << "--not"
|
|
212 |
cmd_args += options[:excludes]
|
|
214 |
revisions +=
|
|
215 |
ignore_missing_revisions(options[:excludes]).map{|r| "^#{r}"}
|
|
213 | 216 |
end |
214 | 217 |
end |
215 |
cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty? |
|
216 | 218 | |
217 |
scm_cmd *cmd_args do |io| |
|
219 |
scm_cmd(*cmd_args, :mode => "r+") do |io| |
|
220 |
io.puts(revisions.join("\n")) |
|
221 |
io.close_write |
|
222 | ||
218 | 223 |
files=[] |
219 | 224 |
changeset = {} |
220 | 225 |
parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files |
... | ... | |
384 | 389 |
end |
385 | 390 | |
386 | 391 |
def scm_cmd(*args, &block) |
392 |
options = args.last.kind_of?(Hash) ? args.pop : {} |
|
387 | 393 |
repo_path = root_url || url |
388 | 394 |
full_args = ['--git-dir', repo_path] |
389 | 395 |
if self.class.client_version_above?([1, 7, 2]) |
... | ... | |
393 | 399 |
full_args += args |
394 | 400 |
ret = shellout( |
395 | 401 |
self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '), |
402 |
options, |
|
396 | 403 |
&block |
397 | 404 |
) |
398 | 405 |
if $? && $?.exitstatus != 0 |
... | ... | |
401 | 408 |
ret |
402 | 409 |
end |
403 | 410 |
private :scm_cmd |
411 | ||
412 |
# Return an array containing only the given revisions that exist in the |
|
413 |
# repository. |
|
414 |
# |
|
415 |
# NOTE: |
|
416 |
# This can be removed once the minimum supported Git version supports |
|
417 |
# the --ignore-missing option for git-log and #revisions is modified to |
|
418 |
# use that option. |
|
419 |
def ignore_missing_revisions(revisions) |
|
420 |
revisions.select do |revision| |
|
421 |
begin |
|
422 |
scm_cmd(*%w|rev-parse --verify --quiet|, revision) do |io| |
|
423 |
# Read and discard the output in order to make the command |
|
424 |
# happy. |
|
425 |
io.read |
|
426 |
end |
|
427 |
true |
|
428 |
rescue ScmCommandAborted |
|
429 |
false |
|
430 |
end |
|
431 |
end |
|
432 |
end |
|
433 |
private :ignore_missing_revisions |
|
404 | 434 |
end |
405 | 435 |
end |
406 | 436 |
end |
test/unit/lib/redmine/scm/adapters/git_adapter_test.rb | ||
---|---|---|
289 | 289 |
end |
290 | 290 | |
291 | 291 |
def test_revisions_invalid_rev_excludes |
292 |
assert_equal [], |
|
293 |
@adapter.revisions('', nil, nil, |
|
294 |
{:reverse => true, |
|
295 |
:includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'], |
|
296 |
:excludes => ['0123abcd4567']}) |
|
297 |
assert_raise Redmine::Scm::Adapters::CommandFailed do |
|
298 |
revs1 = [] |
|
299 |
@adapter.revisions('', nil, nil, |
|
300 |
{:reverse => true, |
|
301 |
:includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'], |
|
302 |
:excludes => ['0123abcd4567']}) do |rev| |
|
303 |
revs1 << rev |
|
304 |
end |
|
292 |
revs1 = @adapter.revisions('', nil, nil, |
|
293 |
{:reverse => true, |
|
294 |
:includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'], |
|
295 |
:excludes => ['0123abcd4567']}) |
|
296 |
assert_equal 15, revs1.length |
|
297 |
assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier |
|
298 |
assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[ 0].identifier |
|
299 | ||
300 |
revs2 = [] |
|
301 |
@adapter.revisions('', nil, nil, |
|
302 |
{:reverse => true, |
|
303 |
:includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'], |
|
304 |
:excludes => ['0123abcd4567']}) do |rev| |
|
305 |
revs2 << rev |
|
305 | 306 |
end |
307 |
assert_equal 15, revs2.length |
|
308 |
assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier |
|
309 |
assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier |
|
306 | 310 |
end |
307 | 311 | |
308 | 312 |
def test_getting_revisions_with_spaces_in_filename |