Change Git::Repository#log to return Commits
This commit is contained in:
parent
e691f5b812
commit
b2ecf0aa35
3 changed files with 90 additions and 86 deletions
|
@ -38,7 +38,7 @@ module Gitlab
|
||||||
repo = options.delete(:repo)
|
repo = options.delete(:repo)
|
||||||
raise 'Gitlab::Git::Repository is required' unless repo.respond_to?(:log)
|
raise 'Gitlab::Git::Repository is required' unless repo.respond_to?(:log)
|
||||||
|
|
||||||
repo.log(options).map { |c| decorate(c) }
|
repo.log(options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Get single commit
|
# Get single commit
|
||||||
|
|
|
@ -331,83 +331,7 @@ module Gitlab
|
||||||
# )
|
# )
|
||||||
#
|
#
|
||||||
def log(options)
|
def log(options)
|
||||||
default_options = {
|
raw_log(options).map { |c| Commit.decorate(c) }
|
||||||
limit: 10,
|
|
||||||
offset: 0,
|
|
||||||
path: nil,
|
|
||||||
follow: false,
|
|
||||||
skip_merges: false,
|
|
||||||
disable_walk: false,
|
|
||||||
after: nil,
|
|
||||||
before: nil
|
|
||||||
}
|
|
||||||
|
|
||||||
options = default_options.merge(options)
|
|
||||||
options[:limit] ||= 0
|
|
||||||
options[:offset] ||= 0
|
|
||||||
actual_ref = options[:ref] || root_ref
|
|
||||||
begin
|
|
||||||
sha = sha_from_ref(actual_ref)
|
|
||||||
rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError
|
|
||||||
# Return an empty array if the ref wasn't found
|
|
||||||
return []
|
|
||||||
end
|
|
||||||
|
|
||||||
if log_using_shell?(options)
|
|
||||||
log_by_shell(sha, options)
|
|
||||||
else
|
|
||||||
log_by_walk(sha, options)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def log_using_shell?(options)
|
|
||||||
options[:path].present? ||
|
|
||||||
options[:disable_walk] ||
|
|
||||||
options[:skip_merges] ||
|
|
||||||
options[:after] ||
|
|
||||||
options[:before]
|
|
||||||
end
|
|
||||||
|
|
||||||
def log_by_walk(sha, options)
|
|
||||||
walk_options = {
|
|
||||||
show: sha,
|
|
||||||
sort: Rugged::SORT_NONE,
|
|
||||||
limit: options[:limit],
|
|
||||||
offset: options[:offset]
|
|
||||||
}
|
|
||||||
Rugged::Walker.walk(rugged, walk_options).to_a
|
|
||||||
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 << "--max-count=#{limit}"
|
|
||||||
cmd << '--format=%H'
|
|
||||||
cmd << "--skip=#{offset}" unless offset_in_ruby
|
|
||||||
cmd << '--follow' if use_follow_flag
|
|
||||||
cmd << '--no-merges' if options[:skip_merges]
|
|
||||||
cmd << "--after=#{options[:after].iso8601}" if options[:after]
|
|
||||||
cmd << "--before=#{options[:before].iso8601}" if options[:before]
|
|
||||||
cmd << sha
|
|
||||||
|
|
||||||
# :path can be a string or an array of strings
|
|
||||||
if options[:path].present?
|
|
||||||
cmd << '--'
|
|
||||||
cmd += Array(options[:path])
|
|
||||||
end
|
|
||||||
|
|
||||||
raw_output = IO.popen(cmd) { |io| io.read }
|
|
||||||
lines = offset_in_ruby ? raw_output.lines.drop(offset) : raw_output.lines
|
|
||||||
|
|
||||||
lines.map! { |c| Rugged::Commit.new(rugged, c.strip) }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def count_commits(options)
|
def count_commits(options)
|
||||||
|
@ -912,6 +836,86 @@ module Gitlab
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def raw_log(options)
|
||||||
|
default_options = {
|
||||||
|
limit: 10,
|
||||||
|
offset: 0,
|
||||||
|
path: nil,
|
||||||
|
follow: false,
|
||||||
|
skip_merges: false,
|
||||||
|
disable_walk: false,
|
||||||
|
after: nil,
|
||||||
|
before: nil
|
||||||
|
}
|
||||||
|
|
||||||
|
options = default_options.merge(options)
|
||||||
|
options[:limit] ||= 0
|
||||||
|
options[:offset] ||= 0
|
||||||
|
actual_ref = options[:ref] || root_ref
|
||||||
|
begin
|
||||||
|
sha = sha_from_ref(actual_ref)
|
||||||
|
rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError
|
||||||
|
# Return an empty array if the ref wasn't found
|
||||||
|
return []
|
||||||
|
end
|
||||||
|
|
||||||
|
if log_using_shell?(options)
|
||||||
|
log_by_shell(sha, options)
|
||||||
|
else
|
||||||
|
log_by_walk(sha, options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_using_shell?(options)
|
||||||
|
options[:path].present? ||
|
||||||
|
options[:disable_walk] ||
|
||||||
|
options[:skip_merges] ||
|
||||||
|
options[:after] ||
|
||||||
|
options[:before]
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_by_walk(sha, options)
|
||||||
|
walk_options = {
|
||||||
|
show: sha,
|
||||||
|
sort: Rugged::SORT_NONE,
|
||||||
|
limit: options[:limit],
|
||||||
|
offset: options[:offset]
|
||||||
|
}
|
||||||
|
Rugged::Walker.walk(rugged, walk_options).to_a
|
||||||
|
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 << "--max-count=#{limit}"
|
||||||
|
cmd << '--format=%H'
|
||||||
|
cmd << "--skip=#{offset}" unless offset_in_ruby
|
||||||
|
cmd << '--follow' if use_follow_flag
|
||||||
|
cmd << '--no-merges' if options[:skip_merges]
|
||||||
|
cmd << "--after=#{options[:after].iso8601}" if options[:after]
|
||||||
|
cmd << "--before=#{options[:before].iso8601}" if options[:before]
|
||||||
|
cmd << sha
|
||||||
|
|
||||||
|
# :path can be a string or an array of strings
|
||||||
|
if options[:path].present?
|
||||||
|
cmd << '--'
|
||||||
|
cmd += Array(options[:path])
|
||||||
|
end
|
||||||
|
|
||||||
|
raw_output = IO.popen(cmd) { |io| io.read }
|
||||||
|
lines = offset_in_ruby ? raw_output.lines.drop(offset) : raw_output.lines
|
||||||
|
|
||||||
|
lines.map! { |c| Rugged::Commit.new(rugged, c.strip) }
|
||||||
|
end
|
||||||
|
|
||||||
# We are trying to deprecate this method because it does a lot of work
|
# We are trying to deprecate this method because it does a lot of work
|
||||||
# but it seems to be used only to look up submodule URL's.
|
# but it seems to be used only to look up submodule URL's.
|
||||||
# https://gitlab.com/gitlab-org/gitaly/issues/329
|
# https://gitlab.com/gitlab-org/gitaly/issues/329
|
||||||
|
|
|
@ -705,9 +705,9 @@ describe Gitlab::Git::Repository, seed_helper: true do
|
||||||
# Add new commits so that there's a renamed file in the commit history
|
# Add new commits so that there's a renamed file in the commit history
|
||||||
repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
|
repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
|
||||||
|
|
||||||
commit_with_old_name = new_commit_edit_old_file(repo)
|
commit_with_old_name = Gitlab::Git::Commit.decorate(new_commit_edit_old_file(repo))
|
||||||
rename_commit = new_commit_move_file(repo)
|
rename_commit = Gitlab::Git::Commit.decorate(new_commit_move_file(repo))
|
||||||
commit_with_new_name = new_commit_edit_new_file(repo)
|
commit_with_new_name = Gitlab::Git::Commit.decorate(new_commit_edit_new_file(repo))
|
||||||
end
|
end
|
||||||
|
|
||||||
after(:context) do
|
after(:context) do
|
||||||
|
@ -880,8 +880,8 @@ describe Gitlab::Git::Repository, seed_helper: true do
|
||||||
|
|
||||||
context "compare results between log_by_walk and log_by_shell" do
|
context "compare results between log_by_walk and log_by_shell" do
|
||||||
let(:options) { { ref: "master" } }
|
let(:options) { { ref: "master" } }
|
||||||
let(:commits_by_walk) { repository.log(options).map(&:oid) }
|
let(:commits_by_walk) { repository.log(options).map(&:id) }
|
||||||
let(:commits_by_shell) { repository.log(options.merge({ disable_walk: true })).map(&:oid) }
|
let(:commits_by_shell) { repository.log(options.merge({ disable_walk: true })).map(&:id) }
|
||||||
|
|
||||||
it { expect(commits_by_walk).to eq(commits_by_shell) }
|
it { expect(commits_by_walk).to eq(commits_by_shell) }
|
||||||
|
|
||||||
|
@ -924,7 +924,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
|
||||||
|
|
||||||
expect(commits.size).to be > 0
|
expect(commits.size).to be > 0
|
||||||
expect(commits).to satisfy do |commits|
|
expect(commits).to satisfy do |commits|
|
||||||
commits.all? { |commit| commit.time >= options[:after] }
|
commits.all? { |commit| commit.committed_date >= options[:after] }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -937,7 +937,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
|
||||||
|
|
||||||
expect(commits.size).to be > 0
|
expect(commits.size).to be > 0
|
||||||
expect(commits).to satisfy do |commits|
|
expect(commits).to satisfy do |commits|
|
||||||
commits.all? { |commit| commit.time <= options[:before] }
|
commits.all? { |commit| commit.committed_date <= options[:before] }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -946,7 +946,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
|
||||||
let(:options) { { ref: 'master', path: ['PROCESS.md', 'README.md'] } }
|
let(:options) { { ref: 'master', path: ['PROCESS.md', 'README.md'] } }
|
||||||
|
|
||||||
def commit_files(commit)
|
def commit_files(commit)
|
||||||
commit.diff(commit.parent_ids.first).deltas.flat_map do |delta|
|
commit.diff_from_parent.deltas.flat_map do |delta|
|
||||||
[delta.old_file[:path], delta.new_file[:path]].uniq.compact
|
[delta.old_file[:path], delta.new_file[:path]].uniq.compact
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue