debian-mirror-gitlab/spec/lib/gitlab/git/conflict/parser_spec.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

248 lines
8.8 KiB
Ruby
Raw Permalink Normal View History

2020-01-01 13:55:28 +05:30
# frozen_string_literal: true
2022-10-11 01:57:18 +05:30
require 'fast_spec_helper'
2016-09-13 17:45:13 +05:30
2020-07-28 23:09:34 +05:30
RSpec.describe Gitlab::Git::Conflict::Parser do
2018-03-17 18:26:18 +05:30
describe '.parse' do
2016-09-13 17:45:13 +05:30
def parse_text(text)
2018-03-17 18:26:18 +05:30
described_class.parse(text, our_path: 'README.md', their_path: 'README.md')
2016-09-13 17:45:13 +05:30
end
context 'when the file has valid conflicts' do
let(:text) do
2020-03-13 15:44:24 +05:30
<<~CONFLICT
module Gitlab
module Regexp
extend self
2016-09-13 17:45:13 +05:30
2020-03-13 15:44:24 +05:30
def username_regexp
default_regexp
end
2016-09-13 17:45:13 +05:30
2020-03-13 15:44:24 +05:30
<<<<<<< files/ruby/regex.rb
def project_name_regexp
/\A[a-zA-Z0-9][a-zA-Z0-9_\-\. ]*\z/
end
2016-09-13 17:45:13 +05:30
2020-03-13 15:44:24 +05:30
def name_regexp
/\A[a-zA-Z0-9_\-\. ]*\z/
=======
def project_name_regex
%r{\A[a-zA-Z0-9][a-zA-Z0-9_\-\. ]*\z}
end
2016-09-13 17:45:13 +05:30
2020-03-13 15:44:24 +05:30
def name_regex
%r{\A[a-zA-Z0-9_\-\. ]*\z}
>>>>>>> files/ruby/regex.rb
end
2016-09-13 17:45:13 +05:30
2020-03-13 15:44:24 +05:30
def path_regexp
default_regexp
end
2016-09-13 17:45:13 +05:30
2020-03-13 15:44:24 +05:30
<<<<<<< files/ruby/regex.rb
def archive_formats_regexp
/(zip|tar|7z|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)/
=======
def archive_formats_regex
%r{(zip|tar|7z|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)}
>>>>>>> files/ruby/regex.rb
end
2016-09-13 17:45:13 +05:30
2020-03-13 15:44:24 +05:30
def git_reference_regexp
# Valid git ref regexp, see:
# https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
%r{
(?!
(?# doesn't begins with)
\/| (?# rule #6)
(?# doesn't contain)
.*(?:
[\/.]\.| (?# rule #1,3)
\/\/| (?# rule #6)
@\{| (?# rule #8)
\\ (?# rule #9)
)
)
[^\000-\040\177~^:?*\[]+ (?# rule #4-5)
(?# doesn't end with)
(?<!\.lock) (?# rule #1)
(?<![\/.]) (?# rule #6-7)
}x
end
2016-09-13 17:45:13 +05:30
2020-03-13 15:44:24 +05:30
protected
2016-09-13 17:45:13 +05:30
2020-03-13 15:44:24 +05:30
<<<<<<< files/ruby/regex.rb
def default_regexp
/\A[.?]?[a-zA-Z0-9][a-zA-Z0-9_\-\.]*(?<!\.git)\z/
=======
def default_regex
%r{\A[.?]?[a-zA-Z0-9][a-zA-Z0-9_\-\.]*(?<!\.git)\z}
>>>>>>> files/ruby/regex.rb
end
end
end
CONFLICT
2016-09-13 17:45:13 +05:30
end
2022-08-13 15:12:31 +05:30
shared_examples_for 'successful parsing' do
let(:lines) do
described_class.parse(content, our_path: 'files/ruby/regex.rb', their_path: 'files/ruby/regex.rb')
end
2020-10-24 23:57:45 +05:30
2022-08-13 15:12:31 +05:30
let(:old_line_numbers) do
lines.select { |line| line[:type] != 'new' }.map { |line| line[:line_old] }
end
2020-10-24 23:57:45 +05:30
2022-08-13 15:12:31 +05:30
let(:new_line_numbers) do
lines.select { |line| line[:type] != 'old' }.map { |line| line[:line_new] }
end
let(:line_indexes) { lines.map { |line| line[:line_obj_index] } }
2020-10-24 23:57:45 +05:30
2022-08-13 15:12:31 +05:30
it 'sets our lines as new lines' do
expect(lines[8..13]).to all(include(type: 'new'))
expect(lines[26..27]).to all(include(type: 'new'))
expect(lines[56..57]).to all(include(type: 'new'))
end
2016-09-13 17:45:13 +05:30
2022-08-13 15:12:31 +05:30
it 'sets their lines as old lines' do
expect(lines[14..19]).to all(include(type: 'old'))
expect(lines[28..29]).to all(include(type: 'old'))
expect(lines[58..59]).to all(include(type: 'old'))
end
it 'sets non-conflicted lines as both' do
expect(lines[0..7]).to all(include(type: nil))
expect(lines[20..25]).to all(include(type: nil))
expect(lines[30..55]).to all(include(type: nil))
expect(lines[60..62]).to all(include(type: nil))
end
it 'sets consecutive line numbers for line_obj_index, line_old, and line_new' do
expect(line_indexes).to eq(0.upto(62).to_a)
expect(old_line_numbers).to eq(1.upto(53).to_a)
expect(new_line_numbers).to eq(1.upto(53).to_a)
end
2016-09-13 17:45:13 +05:30
end
2022-08-13 15:12:31 +05:30
context 'content has LF endings' do
let(:content) { text }
it_behaves_like 'successful parsing'
2016-09-13 17:45:13 +05:30
end
2022-08-13 15:12:31 +05:30
context 'content has CRLF endings' do
let(:content) { text.gsub("\n", "\r\n") }
it_behaves_like 'successful parsing'
2016-09-13 17:45:13 +05:30
end
2022-08-13 15:12:31 +05:30
context 'content has mixed LF and CRLF endings' do
# Simulate mixed line endings by only changing some of the lines to CRLF
let(:content) do
text.each_line.map.with_index do |line, index|
index.odd? ? line.gsub("\n", "\r\n") : line
end.join
end
it_behaves_like 'successful parsing'
2016-09-13 17:45:13 +05:30
end
end
context 'when the file contents include conflict delimiters' do
2017-08-17 22:00:37 +05:30
context 'when there is a non-start delimiter first' do
it 'raises UnexpectedDelimiter when there is a middle delimiter first' do
2017-09-10 17:25:29 +05:30
expect { parse_text('=======') }
2018-03-17 18:26:18 +05:30
.to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
2017-08-17 22:00:37 +05:30
end
it 'raises UnexpectedDelimiter when there is an end delimiter first' do
2017-09-10 17:25:29 +05:30
expect { parse_text('>>>>>>> README.md') }
2018-03-17 18:26:18 +05:30
.to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
2017-08-17 22:00:37 +05:30
end
it 'does not raise when there is an end delimiter for a different path first' do
2017-09-10 17:25:29 +05:30
expect { parse_text('>>>>>>> some-other-path.md') }
.not_to raise_error
2017-08-17 22:00:37 +05:30
end
2016-09-13 17:45:13 +05:30
end
2017-08-17 22:00:37 +05:30
context 'when a start delimiter is followed by a non-middle delimiter' do
let(:start_text) { "<<<<<<< README.md\n" }
let(:end_text) { "\n=======\n>>>>>>> README.md" }
2016-09-13 17:45:13 +05:30
2017-08-17 22:00:37 +05:30
it 'raises UnexpectedDelimiter when it is followed by an end delimiter' do
2017-09-10 17:25:29 +05:30
expect { parse_text(start_text + '>>>>>>> README.md' + end_text) }
2018-03-17 18:26:18 +05:30
.to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
2017-08-17 22:00:37 +05:30
end
2016-09-13 17:45:13 +05:30
2017-08-17 22:00:37 +05:30
it 'raises UnexpectedDelimiter when it is followed by another start delimiter' do
2017-09-10 17:25:29 +05:30
expect { parse_text(start_text + start_text + end_text) }
2018-03-17 18:26:18 +05:30
.to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
2017-08-17 22:00:37 +05:30
end
2016-09-13 17:45:13 +05:30
2017-08-17 22:00:37 +05:30
it 'does not raise when it is followed by a start delimiter for a different path' do
2017-09-10 17:25:29 +05:30
expect { parse_text(start_text + '>>>>>>> some-other-path.md' + end_text) }
.not_to raise_error
2017-08-17 22:00:37 +05:30
end
2016-09-13 17:45:13 +05:30
end
2017-08-17 22:00:37 +05:30
context 'when a middle delimiter is followed by a non-end delimiter' do
let(:start_text) { "<<<<<<< README.md\n=======\n" }
let(:end_text) { "\n>>>>>>> README.md" }
2016-09-13 17:45:13 +05:30
2017-08-17 22:00:37 +05:30
it 'raises UnexpectedDelimiter when it is followed by another middle delimiter' do
2017-09-10 17:25:29 +05:30
expect { parse_text(start_text + '=======' + end_text) }
2018-03-17 18:26:18 +05:30
.to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
2017-08-17 22:00:37 +05:30
end
2016-09-13 17:45:13 +05:30
2017-08-17 22:00:37 +05:30
it 'raises UnexpectedDelimiter when it is followed by a start delimiter' do
2017-09-10 17:25:29 +05:30
expect { parse_text(start_text + start_text + end_text) }
2018-03-17 18:26:18 +05:30
.to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
2017-08-17 22:00:37 +05:30
end
2016-09-13 17:45:13 +05:30
2017-08-17 22:00:37 +05:30
it 'does not raise when it is followed by a start delimiter for another path' do
2017-09-10 17:25:29 +05:30
expect { parse_text(start_text + '<<<<<<< some-other-path.md' + end_text) }
.not_to raise_error
2017-08-17 22:00:37 +05:30
end
2016-09-13 17:45:13 +05:30
end
it 'raises MissingEndDelimiter when there is no end delimiter at the end' do
start_text = "<<<<<<< README.md\n=======\n"
2017-09-10 17:25:29 +05:30
expect { parse_text(start_text) }
2018-03-17 18:26:18 +05:30
.to raise_error(Gitlab::Git::Conflict::Parser::MissingEndDelimiter)
2016-09-13 17:45:13 +05:30
2017-09-10 17:25:29 +05:30
expect { parse_text(start_text + '>>>>>>> some-other-path.md') }
2018-03-17 18:26:18 +05:30
.to raise_error(Gitlab::Git::Conflict::Parser::MissingEndDelimiter)
2016-09-13 17:45:13 +05:30
end
end
context 'other file types' do
it 'raises UnmergeableFile when lines is blank, indicating a binary file' do
2017-09-10 17:25:29 +05:30
expect { parse_text('') }
2018-03-17 18:26:18 +05:30
.to raise_error(Gitlab::Git::Conflict::Parser::UnmergeableFile)
2016-09-13 17:45:13 +05:30
2017-09-10 17:25:29 +05:30
expect { parse_text(nil) }
2018-03-17 18:26:18 +05:30
.to raise_error(Gitlab::Git::Conflict::Parser::UnmergeableFile)
2016-09-13 17:45:13 +05:30
end
2016-09-29 09:46:39 +05:30
it 'raises UnmergeableFile when the file is over 200 KB' do
2017-09-10 17:25:29 +05:30
expect { parse_text('a' * 204801) }
2018-03-17 18:26:18 +05:30
.to raise_error(Gitlab::Git::Conflict::Parser::UnmergeableFile)
2016-09-13 17:45:13 +05:30
end
2017-08-17 22:00:37 +05:30
# All text from Rugged has an encoding of ASCII_8BIT, so force that in
# these strings.
context 'when the file contains UTF-8 characters' do
it 'does not raise' do
2020-01-01 13:55:28 +05:30
expect { parse_text((+"Espa\xC3\xB1a").force_encoding(Encoding::ASCII_8BIT)) }
2017-09-10 17:25:29 +05:30
.not_to raise_error
2017-08-17 22:00:37 +05:30
end
end
2016-09-13 17:45:13 +05:30
end
end
end