diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-22 11:31:16 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-22 11:31:16 +0000 |
commit | 905c1110b08f93a19661cf42a276c7ea90d0a0ff (patch) | |
tree | 756d138db422392c00471ab06acdff92c5a9b69c /lib/gitlab/ci/ansi2json/converter.rb | |
parent | 50d93f8d1686950fc58dda4823c4835fd0d8c14b (diff) | |
download | gitlab-ce-905c1110b08f93a19661cf42a276c7ea90d0a0ff.tar.gz |
Add latest changes from gitlab-org/gitlab@12-4-stable-ee
Diffstat (limited to 'lib/gitlab/ci/ansi2json/converter.rb')
-rw-r--r-- | lib/gitlab/ci/ansi2json/converter.rb | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/lib/gitlab/ci/ansi2json/converter.rb b/lib/gitlab/ci/ansi2json/converter.rb new file mode 100644 index 00000000000..8d25b66af9c --- /dev/null +++ b/lib/gitlab/ci/ansi2json/converter.rb @@ -0,0 +1,133 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Ansi2json + class Converter + def convert(stream, new_state) + @lines = [] + @state = State.new(new_state, stream.size) + + append = false + truncated = false + + cur_offset = stream.tell + if cur_offset > @state.offset + @state.offset = cur_offset + truncated = true + else + stream.seek(@state.offset) + append = @state.offset > 0 + end + + start_offset = @state.offset + + @state.set_current_line!(style: Style.new(@state.inherited_style)) + + stream.each_line do |line| + s = StringScanner.new(line) + convert_line(s) + end + + # This must be assigned before flushing the current line + # or the @current_line.offset will advance to the very end + # of the trace. Instead we want @last_line_offset to always + # point to the beginning of last line. + @state.set_last_line_offset + + flush_current_line + + # TODO: replace OpenStruct with a better type + # https://gitlab.com/gitlab-org/gitlab/issues/34305 + OpenStruct.new( + lines: @lines, + state: @state.encode, + append: append, + truncated: truncated, + offset: start_offset, + size: stream.tell - start_offset, + total: stream.size + ) + end + + private + + def convert_line(scanner) + until scanner.eos? + + if scanner.scan(Gitlab::Regex.build_trace_section_regex) + handle_section(scanner) + elsif scanner.scan(/\e([@-_])(.*?)([@-~])/) + handle_sequence(scanner) + elsif scanner.scan(/\e(([@-_])(.*?)?)?$/) + break + elsif scanner.scan(/</) + @state.current_line << '<' + elsif scanner.scan(/\r?\n/) + # we advance the offset of the next current line + # so it does not start from \n + flush_current_line(advance_offset: scanner.matched_size) + else + @state.current_line << scanner.scan(/./m) + end + + @state.offset += scanner.matched_size + end + end + + def handle_sequence(scanner) + indicator = scanner[1] + commands = scanner[2].split ';' + terminator = scanner[3] + + # We are only interested in color and text style changes - triggered by + # sequences starting with '\e[' and ending with 'm'. Any other control + # sequence gets stripped (including stuff like "delete last line") + return unless indicator == '[' && terminator == 'm' + + @state.update_style(commands) + end + + def handle_section(scanner) + action = scanner[1] + timestamp = scanner[2] + section = scanner[3] + + section_name = sanitize_section_name(section) + + if action == "start" + handle_section_start(section_name, timestamp) + elsif action == "end" + handle_section_end(section_name, timestamp) + end + end + + def handle_section_start(section, timestamp) + flush_current_line unless @state.current_line.empty? + @state.open_section(section, timestamp) + end + + def handle_section_end(section, timestamp) + return unless @state.section_open?(section) + + flush_current_line unless @state.current_line.empty? + @state.close_section(section, timestamp) + + # ensure that section end is detached from the last + # line in the section + flush_current_line + end + + def flush_current_line(advance_offset: 0) + @lines << @state.current_line.to_h + + @state.set_current_line!(advance_offset: advance_offset) + end + + def sanitize_section_name(section) + section.to_s.downcase.gsub(/[^a-z0-9]/, '-') + end + end + end + end +end |