gitlab-org--gitlab-foss/spec/lib/gitlab/git/commit_spec.rb
2017-09-25 11:34:10 +02:00

496 lines
14 KiB
Ruby

require "spec_helper"
describe Gitlab::Git::Commit, seed_helper: true do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:commit) { described_class.find(repository, SeedRepo::Commit::ID) }
let(:rugged_commit) do
repository.rugged.lookup(SeedRepo::Commit::ID)
end
describe "Commit info" do
before do
repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '').rugged
@committer = {
email: 'mike@smith.com',
name: "Mike Smith",
time: Time.now
}
@author = {
email: 'john@smith.com',
name: "John Smith",
time: Time.now
}
@parents = [repo.head.target]
@gitlab_parents = @parents.map { |c| described_class.decorate(repository, c) }
@tree = @parents.first.tree
sha = Rugged::Commit.create(
repo,
author: @author,
committer: @committer,
tree: @tree,
parents: @parents,
message: "Refactoring specs",
update_ref: "HEAD"
)
@raw_commit = repo.lookup(sha)
@commit = described_class.new(repository, @raw_commit)
end
it { expect(@commit.short_id).to eq(@raw_commit.oid[0..10]) }
it { expect(@commit.id).to eq(@raw_commit.oid) }
it { expect(@commit.sha).to eq(@raw_commit.oid) }
it { expect(@commit.safe_message).to eq(@raw_commit.message) }
it { expect(@commit.created_at).to eq(@raw_commit.author[:time]) }
it { expect(@commit.date).to eq(@raw_commit.committer[:time]) }
it { expect(@commit.author_email).to eq(@author[:email]) }
it { expect(@commit.author_name).to eq(@author[:name]) }
it { expect(@commit.committer_name).to eq(@committer[:name]) }
it { expect(@commit.committer_email).to eq(@committer[:email]) }
it { expect(@commit.different_committer?).to be_truthy }
it { expect(@commit.parents).to eq(@gitlab_parents) }
it { expect(@commit.parent_id).to eq(@parents.first.oid) }
it { expect(@commit.no_commit_message).to eq("--no commit message") }
it { expect(@commit.tree).to eq(@tree) }
after do
# Erase the new commit so other tests get the original repo
repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '').rugged
repo.references.update("refs/heads/master", SeedRepo::LastCommit::ID)
end
end
describe "Commit info from gitaly commit" do
let(:id) { 'f00' }
let(:parent_ids) { %w(b45 b46) }
let(:subject) { "My commit".force_encoding('ASCII-8BIT') }
let(:body) { subject + "My body".force_encoding('ASCII-8BIT') }
let(:committer) do
Gitaly::CommitAuthor.new(
name: generate(:name),
email: generate(:email),
date: Google::Protobuf::Timestamp.new(seconds: 123)
)
end
let(:author) do
Gitaly::CommitAuthor.new(
name: generate(:name),
email: generate(:email),
date: Google::Protobuf::Timestamp.new(seconds: 456)
)
end
let(:gitaly_commit) do
Gitaly::GitCommit.new(
id: id,
subject: subject,
body: body,
author: author,
committer: committer,
parent_ids: parent_ids
)
end
let(:commit) { described_class.new(repository, gitaly_commit) }
it { expect(commit.short_id).to eq(id[0..10]) }
it { expect(commit.id).to eq(id) }
it { expect(commit.sha).to eq(id) }
it { expect(commit.safe_message).to eq(body) }
it { expect(commit.created_at).to eq(Time.at(committer.date.seconds)) }
it { expect(commit.author_email).to eq(author.email) }
it { expect(commit.author_name).to eq(author.name) }
it { expect(commit.committer_name).to eq(committer.name) }
it { expect(commit.committer_email).to eq(committer.email) }
it { expect(commit.parent_ids).to eq(parent_ids) }
context 'no body' do
let(:body) { "".force_encoding('ASCII-8BIT') }
it { expect(commit.safe_message).to eq(subject) }
end
end
context 'Class methods' do
describe '.find' do
it "should return first head commit if without params" do
expect(described_class.last(repository).id).to eq(
repository.rugged.head.target.oid
)
end
it "should return valid commit" do
expect(described_class.find(repository, SeedRepo::Commit::ID)).to be_valid_commit
end
it "should return valid commit for tag" do
expect(described_class.find(repository, 'v1.0.0').id).to eq('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9')
end
it "should return nil for non-commit ids" do
blob = Gitlab::Git::Blob.find(repository, SeedRepo::Commit::ID, "files/ruby/popen.rb")
expect(described_class.find(repository, blob.id)).to be_nil
end
it "should return nil for parent of non-commit object" do
blob = Gitlab::Git::Blob.find(repository, SeedRepo::Commit::ID, "files/ruby/popen.rb")
expect(described_class.find(repository, "#{blob.id}^")).to be_nil
end
it "should return nil for nonexisting ids" do
expect(described_class.find(repository, "+123_4532530XYZ")).to be_nil
end
context 'with broken repo' do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_BROKEN_REPO_PATH, '') }
it 'returns nil' do
expect(described_class.find(repository, SeedRepo::Commit::ID)).to be_nil
end
end
end
describe '.last_for_path' do
context 'no path' do
subject { described_class.last_for_path(repository, 'master') }
describe '#id' do
subject { super().id }
it { is_expected.to eq(SeedRepo::LastCommit::ID) }
end
end
context 'path' do
subject { described_class.last_for_path(repository, 'master', 'files/ruby') }
describe '#id' do
subject { super().id }
it { is_expected.to eq(SeedRepo::Commit::ID) }
end
end
context 'ref + path' do
subject { described_class.last_for_path(repository, SeedRepo::Commit::ID, 'encoding') }
describe '#id' do
subject { super().id }
it { is_expected.to eq(SeedRepo::BigCommit::ID) }
end
end
end
shared_examples '.where' do
context 'path is empty string' do
subject do
commits = described_class.where(
repo: repository,
ref: 'master',
path: '',
limit: 10
)
commits.map { |c| c.id }
end
it 'has 10 elements' do
expect(subject.size).to eq(10)
end
it { is_expected.to include(SeedRepo::EmptyCommit::ID) }
end
context 'path is nil' do
subject do
commits = described_class.where(
repo: repository,
ref: 'master',
path: nil,
limit: 10
)
commits.map { |c| c.id }
end
it 'has 10 elements' do
expect(subject.size).to eq(10)
end
it { is_expected.to include(SeedRepo::EmptyCommit::ID) }
end
context 'ref is branch name' do
subject do
commits = described_class.where(
repo: repository,
ref: 'master',
path: 'files',
limit: 3,
offset: 1
)
commits.map { |c| c.id }
end
it 'has 3 elements' do
expect(subject.size).to eq(3)
end
it { is_expected.to include("d14d6c0abdd253381df51a723d58691b2ee1ab08") }
it { is_expected.not_to include("eb49186cfa5c4338011f5f590fac11bd66c5c631") }
end
context 'ref is commit id' do
subject do
commits = described_class.where(
repo: repository,
ref: "874797c3a73b60d2187ed6e2fcabd289ff75171e",
path: 'files',
limit: 3,
offset: 1
)
commits.map { |c| c.id }
end
it 'has 3 elements' do
expect(subject.size).to eq(3)
end
it { is_expected.to include("2f63565e7aac07bcdadb654e253078b727143ec4") }
it { is_expected.not_to include(SeedRepo::Commit::ID) }
end
context 'ref is tag' do
subject do
commits = described_class.where(
repo: repository,
ref: 'v1.0.0',
path: 'files',
limit: 3,
offset: 1
)
commits.map { |c| c.id }
end
it 'has 3 elements' do
expect(subject.size).to eq(3)
end
it { is_expected.to include("874797c3a73b60d2187ed6e2fcabd289ff75171e") }
it { is_expected.not_to include(SeedRepo::Commit::ID) }
end
end
describe '.where with gitaly' do
it_should_behave_like '.where'
end
describe '.where without gitaly', skip_gitaly_mock: true do
it_should_behave_like '.where'
end
describe '.between' do
subject do
commits = described_class.between(repository, SeedRepo::Commit::PARENT_ID, SeedRepo::Commit::ID)
commits.map { |c| c.id }
end
it 'has 1 element' do
expect(subject.size).to eq(1)
end
it { is_expected.to include(SeedRepo::Commit::ID) }
it { is_expected.not_to include(SeedRepo::FirstCommit::ID) }
end
describe '.find_all' do
shared_examples 'finding all commits' do
it 'should return a return a collection of commits' do
commits = described_class.find_all(repository)
expect(commits).to all( be_a_kind_of(described_class) )
end
context 'max_count' do
subject do
commits = described_class.find_all(
repository,
max_count: 50
)
commits.map(&:id)
end
it 'has 34 elements' do
expect(subject.size).to eq(34)
end
it 'includes the expected commits' do
expect(subject).to include(
SeedRepo::Commit::ID,
SeedRepo::Commit::PARENT_ID,
SeedRepo::FirstCommit::ID
)
end
end
context 'ref + max_count + skip' do
subject do
commits = described_class.find_all(
repository,
ref: 'master',
max_count: 50,
skip: 1
)
commits.map(&:id)
end
it 'has 24 elements' do
expect(subject.size).to eq(24)
end
it 'includes the expected commits' do
expect(subject).to include(SeedRepo::Commit::ID, SeedRepo::FirstCommit::ID)
expect(subject).not_to include(SeedRepo::LastCommit::ID)
end
end
end
context 'when Gitaly find_all_commits feature is enabled' do
it_behaves_like 'finding all commits'
end
context 'when Gitaly find_all_commits feature is disabled', skip_gitaly_mock: true do
it_behaves_like 'finding all commits'
context 'while applying a sort order based on the `order` option' do
it "allows ordering topologically (no parents shown before their children)" do
expect_any_instance_of(Rugged::Walker).to receive(:sorting).with(Rugged::SORT_TOPO)
described_class.find_all(repository, order: :topo)
end
it "allows ordering by date" do
expect_any_instance_of(Rugged::Walker).to receive(:sorting).with(Rugged::SORT_DATE | Rugged::SORT_TOPO)
described_class.find_all(repository, order: :date)
end
it "applies no sorting by default" do
expect_any_instance_of(Rugged::Walker).to receive(:sorting).with(Rugged::SORT_NONE)
described_class.find_all(repository)
end
end
end
end
end
describe '#init_from_rugged' do
let(:gitlab_commit) { described_class.new(repository, rugged_commit) }
subject { gitlab_commit }
describe '#id' do
subject { super().id }
it { is_expected.to eq(SeedRepo::Commit::ID) }
end
end
describe '#init_from_hash' do
let(:commit) { described_class.new(repository, sample_commit_hash) }
subject { commit }
describe '#id' do
subject { super().id }
it { is_expected.to eq(sample_commit_hash[:id])}
end
describe '#message' do
subject { super().message }
it { is_expected.to eq(sample_commit_hash[:message])}
end
end
shared_examples '#stats' do
subject { commit.stats }
describe '#additions' do
subject { super().additions }
it { is_expected.to eq(11) }
end
describe '#deletions' do
subject { super().deletions }
it { is_expected.to eq(6) }
end
end
describe '#stats with gitaly on' do
it_should_behave_like '#stats'
end
describe '#stats with gitaly disabled', skip_gitaly_mock: true do
it_should_behave_like '#stats'
end
describe '#to_diff' do
subject { commit.to_diff }
it { is_expected.not_to include "From #{SeedRepo::Commit::ID}" }
it { is_expected.to include 'diff --git a/files/ruby/popen.rb b/files/ruby/popen.rb'}
end
describe '#has_zero_stats?' do
it { expect(commit.has_zero_stats?).to eq(false) }
end
describe '#to_patch' do
subject { commit.to_patch }
it { is_expected.to include "From #{SeedRepo::Commit::ID}" }
it { is_expected.to include 'diff --git a/files/ruby/popen.rb b/files/ruby/popen.rb'}
end
describe '#to_hash' do
let(:hash) { commit.to_hash }
subject { hash }
it { is_expected.to be_kind_of Hash }
describe '#keys' do
subject { super().keys.sort }
it { is_expected.to match(sample_commit_hash.keys.sort) }
end
end
describe '#diffs' do
subject { commit.diffs }
it { is_expected.to be_kind_of Gitlab::Git::DiffCollection }
it { expect(subject.count).to eq(2) }
it { expect(subject.first).to be_kind_of Gitlab::Git::Diff }
end
describe '#ref_names' do
let(:commit) { described_class.find(repository, 'master') }
subject { commit.ref_names(repository) }
it 'has 1 element' do
expect(subject.size).to eq(1)
end
it { is_expected.to include("master") }
it { is_expected.not_to include("feature") }
end
def sample_commit_hash
{
author_email: "dmitriy.zaporozhets@gmail.com",
author_name: "Dmitriy Zaporozhets",
authored_date: "2012-02-27 20:51:12 +0200",
committed_date: "2012-02-27 20:51:12 +0200",
committer_email: "dmitriy.zaporozhets@gmail.com",
committer_name: "Dmitriy Zaporozhets",
id: SeedRepo::Commit::ID,
message: "tree css fixes",
parent_ids: ["874797c3a73b60d2187ed6e2fcabd289ff75171e"]
}
end
end