gitlab-org--gitlab-foss/lib/gitlab/git/conflict/parser.rb
Alejandro Rodríguez faa9bd402d Create a Gitlab::Git submodule for conlict-related files
Rename classes to (hopefully) clearer names while we're doing that.
2017-10-12 22:03:15 -03:00

91 lines
2.6 KiB
Ruby

module Gitlab
module Git
module Conflict
class Parser
UnresolvableError = Class.new(StandardError)
UnmergeableFile = Class.new(UnresolvableError)
UnsupportedEncoding = Class.new(UnresolvableError)
# Recoverable errors - the conflict can be resolved in an editor, but not with
# sections.
ParserError = Class.new(StandardError)
UnexpectedDelimiter = Class.new(ParserError)
MissingEndDelimiter = Class.new(ParserError)
class << self
def parse(text, our_path:, their_path:, parent_file: nil)
validate_text!(text)
line_obj_index = 0
line_old = 1
line_new = 1
type = nil
lines = []
conflict_start = "<<<<<<< #{our_path}"
conflict_middle = '======='
conflict_end = ">>>>>>> #{their_path}"
text.each_line.map do |line|
full_line = line.delete("\n")
if full_line == conflict_start
validate_delimiter!(type.nil?)
type = 'new'
elsif full_line == conflict_middle
validate_delimiter!(type == 'new')
type = 'old'
elsif full_line == conflict_end
validate_delimiter!(type == 'old')
type = nil
elsif line[0] == '\\'
type = 'nonewline'
lines << {
full_line: full_line,
type: type,
line_obj_index: line_obj_index,
line_old: line_old,
line_new: line_new
}
else
lines << {
full_line: full_line,
type: type,
line_obj_index: line_obj_index,
line_old: line_old,
line_new: line_new
}
line_old += 1 if type != 'new'
line_new += 1 if type != 'old'
line_obj_index += 1
end
end
raise MissingEndDelimiter unless type.nil?
lines
end
private
def validate_text!(text)
raise UnmergeableFile if text.blank? # Typically a binary file
raise UnmergeableFile if text.length > 200.kilobytes
text.force_encoding('UTF-8')
raise UnsupportedEncoding unless text.valid_encoding?
end
def validate_delimiter!(condition)
raise UnexpectedDelimiter unless condition
end
end
end
end
end
end