diff options
Diffstat (limited to 'lib/gitlab/git')
-rw-r--r-- | lib/gitlab/git/repository.rb | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 4b6ad8037ce..9c68060064a 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -324,24 +324,30 @@ module Gitlab end def log_by_shell(sha, options) + limit = options[:limit].to_i + offset = options[:offset].to_i + use_follow_flag = options[:follow] && options[:path].present? + + # We will perform the offset in Ruby because --follow doesn't play well with --skip. + # See: https://gitlab.com/gitlab-org/gitlab-ce/issues/3574#note_3040520 + offset_in_ruby = use_follow_flag && options[:offset].present? + limit += offset if offset_in_ruby + cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path} log) - cmd += %W(-n #{options[:limit].to_i}) + cmd += %W(-n #{limit}) cmd += %w(--format=%H) - cmd += %W(--skip=#{options[:offset].to_i}) - cmd += %w(--follow) if options[:follow] + cmd += %W(--skip=#{offset}) unless offset_in_ruby + cmd += %w(--follow) if use_follow_flag cmd += %w(--no-merges) if options[:skip_merges] cmd += %W(--after=#{options[:after].iso8601}) if options[:after] cmd += %W(--before=#{options[:before].iso8601}) if options[:before] cmd += [sha] cmd += %W(-- #{options[:path]}) if options[:path].present? - raw_output = IO.popen(cmd) {|io| io.read } - - log = raw_output.lines.map do |c| - Rugged::Commit.new(rugged, c.strip) - end + raw_output = IO.popen(cmd) { |io| io.read } + lines = offset_in_ruby ? raw_output.lines.drop(offset) : raw_output.lines - log.is_a?(Array) ? log : [] + lines.map { |c| Rugged::Commit.new(rugged, c.strip) } end def sha_from_ref(ref) |