9a73b634ab
This adds an ID-less table containing one row per file, per merge request diff. It has a column for each attribute on Gitlab::Git::Diff that is serialised currently, with the advantage that we can easily query the attributes of this new table. It does not migrate existing data, so we have fallback code when the legacy st_diffs column is present instead. For a merge request diff to be valid, it should have at most one of: * Rows in this new table, with the correct merge_request_diff_id. * A non-NULL st_diffs column. It may have neither, if the diff is empty.
158 lines
4.6 KiB
Ruby
158 lines
4.6 KiB
Ruby
require 'spec_helper'
|
|
|
|
describe MergeRequestDiff, models: true do
|
|
describe 'create new record' do
|
|
subject { create(:merge_request).merge_request_diff }
|
|
|
|
it { expect(subject).to be_valid }
|
|
it { expect(subject).to be_persisted }
|
|
it { expect(subject.commits.count).to eq(29) }
|
|
it { expect(subject.diffs.count).to eq(20) }
|
|
it { expect(subject.head_commit_sha).to eq('b83d6e391c22777fca1ed3012fce84f633d7fed0') }
|
|
it { expect(subject.base_commit_sha).to eq('ae73cb07c9eeaf35924a10f713b364d32b2dd34f') }
|
|
it { expect(subject.start_commit_sha).to eq('0b4bc9a49b562e85de7cc9e834518ea6828729b9') }
|
|
end
|
|
|
|
describe '#latest' do
|
|
let!(:mr) { create(:merge_request, :with_diffs) }
|
|
let!(:first_diff) { mr.merge_request_diff }
|
|
let!(:last_diff) { mr.create_merge_request_diff }
|
|
|
|
it { expect(last_diff.latest?).to be_truthy }
|
|
it { expect(first_diff.latest?).to be_falsey }
|
|
end
|
|
|
|
describe '#diffs' do
|
|
let(:mr) { create(:merge_request, :with_diffs) }
|
|
let(:mr_diff) { mr.merge_request_diff }
|
|
|
|
context 'when the :ignore_whitespace_change option is set' do
|
|
it 'creates a new compare object instead of loading from the DB' do
|
|
expect(mr_diff).not_to receive(:load_diffs)
|
|
expect(Gitlab::Git::Compare).to receive(:new).and_call_original
|
|
|
|
mr_diff.raw_diffs(ignore_whitespace_change: true)
|
|
end
|
|
end
|
|
|
|
context 'when the raw diffs are empty' do
|
|
before do
|
|
MergeRequestDiffFile.delete_all(merge_request_diff_id: mr_diff.id)
|
|
end
|
|
|
|
it 'returns an empty DiffCollection' do
|
|
expect(mr_diff.raw_diffs).to be_a(Gitlab::Git::DiffCollection)
|
|
expect(mr_diff.raw_diffs).to be_empty
|
|
end
|
|
end
|
|
|
|
context 'when the raw diffs have invalid content' do
|
|
before do
|
|
MergeRequestDiffFile.delete_all(merge_request_diff_id: mr_diff.id)
|
|
mr_diff.update_attributes(st_diffs: ["--broken-diff"])
|
|
end
|
|
|
|
it 'returns an empty DiffCollection' do
|
|
expect(mr_diff.raw_diffs.to_a).to be_empty
|
|
expect(mr_diff.raw_diffs).to be_a(Gitlab::Git::DiffCollection)
|
|
expect(mr_diff.raw_diffs).to be_empty
|
|
end
|
|
end
|
|
|
|
context 'when the raw diffs exist' do
|
|
it 'returns the diffs' do
|
|
expect(mr_diff.raw_diffs).to be_a(Gitlab::Git::DiffCollection)
|
|
expect(mr_diff.raw_diffs).not_to be_empty
|
|
end
|
|
|
|
context 'when the :paths option is set' do
|
|
let(:diffs) { mr_diff.raw_diffs(paths: ['files/ruby/popen.rb', 'files/ruby/popen.rb']) }
|
|
|
|
it 'only returns diffs that match the (old path, new path) given' do
|
|
expect(diffs.map(&:new_path)).to contain_exactly('files/ruby/popen.rb')
|
|
end
|
|
|
|
it 'uses the diffs from the DB' do
|
|
expect(mr_diff).to receive(:load_diffs)
|
|
|
|
diffs
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe '#save_diffs' do
|
|
it 'saves collected state' do
|
|
mr_diff = create(:merge_request).merge_request_diff
|
|
|
|
expect(mr_diff.collected?).to be_truthy
|
|
end
|
|
|
|
it 'saves overflow state' do
|
|
allow(Commit).to receive(:max_diff_options)
|
|
.and_return(max_lines: 0, max_files: 0)
|
|
|
|
mr_diff = create(:merge_request).merge_request_diff
|
|
|
|
expect(mr_diff.overflow?).to be_truthy
|
|
end
|
|
|
|
it 'saves empty state' do
|
|
allow_any_instance_of(MergeRequestDiff).to receive(:commits)
|
|
.and_return([])
|
|
|
|
mr_diff = create(:merge_request).merge_request_diff
|
|
|
|
expect(mr_diff.empty?).to be_truthy
|
|
end
|
|
end
|
|
|
|
describe '#commits_sha' do
|
|
it 'returns all commits SHA using serialized commits' do
|
|
subject.st_commits = [
|
|
{ id: 'sha1' },
|
|
{ id: 'sha2' }
|
|
]
|
|
|
|
expect(subject.commits_sha).to eq(%w(sha1 sha2))
|
|
end
|
|
end
|
|
|
|
describe '#compare_with' do
|
|
subject { create(:merge_request, source_branch: 'fix').merge_request_diff }
|
|
|
|
it 'delegates compare to the service' do
|
|
expect(CompareService).to receive(:new).and_call_original
|
|
|
|
subject.compare_with(nil)
|
|
end
|
|
|
|
it 'uses git diff A..B approach by default' do
|
|
diffs = subject.compare_with('0b4bc9a49b562e85de7cc9e834518ea6828729b9').diffs
|
|
|
|
expect(diffs.size).to eq(3)
|
|
end
|
|
end
|
|
|
|
describe '#commits_count' do
|
|
it 'returns number of commits using serialized commits' do
|
|
subject.st_commits = [
|
|
{ id: 'sha1' },
|
|
{ id: 'sha2' }
|
|
]
|
|
|
|
expect(subject.commits_count).to eq 2
|
|
end
|
|
end
|
|
|
|
describe '#utf8_st_diffs' do
|
|
it 'does not raise error when a hash value is in binary' do
|
|
subject.st_diffs = [
|
|
{ diff: "\0" },
|
|
{ diff: "\x05\x00\x68\x65\x6c\x6c\x6f" }
|
|
]
|
|
|
|
expect { subject.utf8_st_diffs }.not_to raise_error
|
|
end
|
|
end
|
|
end
|