mirror of
https://github.com/abapGit/abapGit.git
synced 2025-04-30 20:03:20 +08:00
646 lines
22 KiB
ABAP
646 lines
22 KiB
ABAP
*&---------------------------------------------------------------------*
|
|
*& Include ZABAPGIT_PAGE_DIFF
|
|
*&---------------------------------------------------------------------*
|
|
|
|
CLASS lcl_gui_page_diff DEFINITION FINAL INHERITING FROM lcl_gui_page.
|
|
|
|
PUBLIC SECTION.
|
|
|
|
CONSTANTS:
|
|
BEGIN OF c_fstate,
|
|
local TYPE char1 VALUE 'L',
|
|
remote TYPE char1 VALUE 'R',
|
|
both TYPE char1 VALUE 'B',
|
|
END OF c_fstate.
|
|
|
|
TYPES: BEGIN OF ty_file_diff,
|
|
path TYPE string,
|
|
filename TYPE string,
|
|
lstate TYPE char1,
|
|
rstate TYPE char1,
|
|
fstate TYPE char1, " FILE state - Abstraction for shorter ifs
|
|
o_diff TYPE REF TO lcl_diff,
|
|
changed_by TYPE xubname,
|
|
type TYPE string,
|
|
END OF ty_file_diff,
|
|
tt_file_diff TYPE STANDARD TABLE OF ty_file_diff.
|
|
|
|
METHODS:
|
|
constructor
|
|
IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key
|
|
is_file TYPE lif_defs=>ty_file OPTIONAL
|
|
is_object TYPE lif_defs=>ty_item OPTIONAL
|
|
iv_supress_stage TYPE abap_bool DEFAULT abap_false
|
|
RAISING lcx_exception,
|
|
lif_gui_page~on_event REDEFINITION.
|
|
|
|
PROTECTED SECTION.
|
|
METHODS:
|
|
render_content REDEFINITION,
|
|
scripts REDEFINITION.
|
|
|
|
PRIVATE SECTION.
|
|
CONSTANTS: BEGIN OF c_actions,
|
|
toggle_unified TYPE string VALUE 'toggle_unified',
|
|
END OF c_actions.
|
|
|
|
DATA: mt_diff_files TYPE tt_file_diff,
|
|
mt_delayed_lines TYPE lcl_diff=>ty_diffs_tt,
|
|
mv_unified TYPE abap_bool VALUE abap_true,
|
|
mv_repo_key TYPE lcl_persistence_repo=>ty_repo-key,
|
|
mv_seed TYPE string. " Unique page id to bind JS sessionStorage
|
|
|
|
METHODS render_diff
|
|
IMPORTING is_diff TYPE ty_file_diff
|
|
RETURNING VALUE(ro_html) TYPE REF TO lcl_html.
|
|
METHODS render_diff_head
|
|
IMPORTING is_diff TYPE ty_file_diff
|
|
RETURNING VALUE(ro_html) TYPE REF TO lcl_html.
|
|
METHODS render_table_head
|
|
RETURNING VALUE(ro_html) TYPE REF TO lcl_html.
|
|
METHODS render_lines
|
|
IMPORTING is_diff TYPE ty_file_diff
|
|
RETURNING VALUE(ro_html) TYPE REF TO lcl_html.
|
|
METHODS render_beacon
|
|
IMPORTING is_diff_line TYPE lcl_diff=>ty_diff
|
|
is_diff TYPE ty_file_diff
|
|
RETURNING VALUE(ro_html) TYPE REF TO lcl_html.
|
|
METHODS render_line_split
|
|
IMPORTING is_diff_line TYPE lcl_diff=>ty_diff
|
|
iv_fstate TYPE char1
|
|
RETURNING VALUE(ro_html) TYPE REF TO lcl_html.
|
|
METHODS render_line_unified
|
|
IMPORTING is_diff_line TYPE lcl_diff=>ty_diff OPTIONAL
|
|
RETURNING VALUE(ro_html) TYPE REF TO lcl_html.
|
|
METHODS append_diff
|
|
IMPORTING it_remote TYPE lif_defs=>ty_files_tt
|
|
it_local TYPE lif_defs=>ty_files_item_tt
|
|
is_status TYPE lif_defs=>ty_result
|
|
RAISING lcx_exception.
|
|
METHODS build_menu
|
|
IMPORTING iv_supress_stage TYPE abap_bool
|
|
RETURNING VALUE(ro_menu) TYPE REF TO lcl_html_toolbar.
|
|
METHODS is_binary
|
|
IMPORTING iv_d1 TYPE xstring
|
|
iv_d2 TYPE xstring
|
|
RETURNING VALUE(rv_yes) TYPE abap_bool.
|
|
|
|
ENDCLASS. "lcl_gui_page_diff
|
|
|
|
CLASS lcl_gui_page_diff IMPLEMENTATION.
|
|
|
|
METHOD constructor.
|
|
|
|
DATA: lt_remote TYPE lif_defs=>ty_files_tt,
|
|
lt_local TYPE lif_defs=>ty_files_item_tt,
|
|
lt_status TYPE lif_defs=>ty_results_tt,
|
|
lo_repo TYPE REF TO lcl_repo_online,
|
|
lv_ts TYPE timestamp.
|
|
|
|
FIELD-SYMBOLS: <ls_status> LIKE LINE OF lt_status.
|
|
|
|
super->constructor( ).
|
|
ms_control-page_title = 'DIFF'.
|
|
mv_unified = lcl_app=>user( )->get_diff_unified( ).
|
|
mv_repo_key = iv_key.
|
|
|
|
GET TIME STAMP FIELD lv_ts.
|
|
mv_seed = |diff{ lv_ts }|. " Generate based on time
|
|
|
|
ASSERT is_file IS INITIAL OR is_object IS INITIAL. " just one passed
|
|
|
|
lo_repo ?= lcl_app=>repo_srv( )->get( iv_key ).
|
|
lt_remote = lo_repo->get_files_remote( ).
|
|
lt_local = lo_repo->get_files_local( ).
|
|
lt_status = lo_repo->status( ).
|
|
|
|
IF is_file IS NOT INITIAL. " Diff for one file
|
|
|
|
READ TABLE lt_status ASSIGNING <ls_status>
|
|
WITH KEY path = is_file-path filename = is_file-filename.
|
|
|
|
append_diff( it_remote = lt_remote
|
|
it_local = lt_local
|
|
is_status = <ls_status> ).
|
|
|
|
ELSEIF is_object IS NOT INITIAL. " Diff for whole object
|
|
|
|
LOOP AT lt_status ASSIGNING <ls_status>
|
|
WHERE obj_type = is_object-obj_type
|
|
AND obj_name = is_object-obj_name
|
|
AND match IS INITIAL.
|
|
append_diff( it_remote = lt_remote
|
|
it_local = lt_local
|
|
is_status = <ls_status> ).
|
|
ENDLOOP.
|
|
|
|
ELSE. " Diff for the whole repo
|
|
|
|
LOOP AT lt_status ASSIGNING <ls_status> WHERE match IS INITIAL.
|
|
append_diff( it_remote = lt_remote
|
|
it_local = lt_local
|
|
is_status = <ls_status> ).
|
|
ENDLOOP.
|
|
|
|
ENDIF.
|
|
|
|
IF lines( mt_diff_files ) = 0.
|
|
lcx_exception=>raise( 'PAGE_DIFF ERROR: No diff files found' ).
|
|
ENDIF.
|
|
|
|
ms_control-page_menu = build_menu( iv_supress_stage ).
|
|
|
|
ENDMETHOD.
|
|
|
|
METHOD append_diff.
|
|
|
|
DATA:
|
|
lv_offs TYPE i,
|
|
ls_r_dummy LIKE LINE OF it_remote ##NEEDED,
|
|
ls_l_dummy LIKE LINE OF it_local ##NEEDED.
|
|
|
|
|
|
FIELD-SYMBOLS: <ls_remote> LIKE LINE OF it_remote,
|
|
<ls_local> LIKE LINE OF it_local,
|
|
<ls_diff> LIKE LINE OF mt_diff_files.
|
|
|
|
READ TABLE it_remote ASSIGNING <ls_remote>
|
|
WITH KEY filename = is_status-filename
|
|
path = is_status-path.
|
|
IF sy-subrc <> 0.
|
|
ASSIGN ls_r_dummy TO <ls_remote>.
|
|
ENDIF.
|
|
|
|
READ TABLE it_local ASSIGNING <ls_local>
|
|
WITH KEY file-filename = is_status-filename
|
|
file-path = is_status-path.
|
|
IF sy-subrc <> 0.
|
|
ASSIGN ls_l_dummy TO <ls_local>.
|
|
ENDIF.
|
|
|
|
IF <ls_local> IS INITIAL AND <ls_remote> IS INITIAL.
|
|
lcx_exception=>raise( |DIFF: file not found { is_status-filename }| ).
|
|
ENDIF.
|
|
|
|
APPEND INITIAL LINE TO mt_diff_files ASSIGNING <ls_diff>.
|
|
<ls_diff>-path = is_status-path.
|
|
<ls_diff>-filename = is_status-filename.
|
|
<ls_diff>-lstate = is_status-lstate.
|
|
<ls_diff>-rstate = is_status-rstate.
|
|
|
|
IF <ls_diff>-lstate IS NOT INITIAL AND <ls_diff>-rstate IS NOT INITIAL.
|
|
<ls_diff>-fstate = c_fstate-both.
|
|
ELSEIF <ls_diff>-lstate IS NOT INITIAL.
|
|
<ls_diff>-fstate = c_fstate-local.
|
|
ELSE. "rstate IS NOT INITIAL, lstate = empty.
|
|
<ls_diff>-fstate = c_fstate-remote.
|
|
ENDIF.
|
|
|
|
" Changed by
|
|
IF <ls_local>-item-obj_type IS NOT INITIAL.
|
|
<ls_diff>-changed_by = to_lower( lcl_objects=>changed_by( <ls_local>-item ) ).
|
|
ENDIF.
|
|
|
|
" Extension
|
|
IF <ls_local>-file-filename IS NOT INITIAL.
|
|
<ls_diff>-type = reverse( <ls_local>-file-filename ).
|
|
ELSE.
|
|
<ls_diff>-type = reverse( <ls_remote>-filename ).
|
|
ENDIF.
|
|
|
|
FIND FIRST OCCURRENCE OF '.' IN <ls_diff>-type MATCH OFFSET lv_offs.
|
|
<ls_diff>-type = reverse( substring( val = <ls_diff>-type len = lv_offs ) ).
|
|
IF <ls_diff>-type <> 'xml' AND <ls_diff>-type <> 'abap'.
|
|
<ls_diff>-type = 'other'.
|
|
ENDIF.
|
|
|
|
IF <ls_diff>-type = 'other'
|
|
AND is_binary( iv_d1 = <ls_remote>-data iv_d2 = <ls_local>-file-data ) = abap_true.
|
|
<ls_diff>-type = 'binary'.
|
|
ENDIF.
|
|
|
|
" Diff data
|
|
IF <ls_diff>-type <> 'binary'.
|
|
IF <ls_diff>-fstate = c_fstate-remote. " Remote file leading changes
|
|
CREATE OBJECT <ls_diff>-o_diff
|
|
EXPORTING
|
|
iv_new = <ls_remote>-data
|
|
iv_old = <ls_local>-file-data.
|
|
ELSE. " Local leading changes or both were modified
|
|
CREATE OBJECT <ls_diff>-o_diff
|
|
EXPORTING
|
|
iv_new = <ls_local>-file-data
|
|
iv_old = <ls_remote>-data.
|
|
ENDIF.
|
|
ENDIF.
|
|
|
|
ENDMETHOD. "append_diff
|
|
|
|
METHOD is_binary.
|
|
|
|
DATA: lv_len TYPE i,
|
|
lv_idx TYPE i,
|
|
lv_x TYPE x.
|
|
|
|
FIELD-SYMBOLS <data> LIKE iv_d1.
|
|
|
|
IF iv_d1 IS NOT INITIAL. " One of them might be new and so empty
|
|
ASSIGN iv_d1 TO <data>.
|
|
ELSE.
|
|
ASSIGN iv_d2 TO <data>.
|
|
ENDIF.
|
|
|
|
lv_len = xstrlen( <data> ).
|
|
IF lv_len = 0.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
IF lv_len > 100.
|
|
lv_len = 100.
|
|
ENDIF.
|
|
|
|
" Simple char range test
|
|
" stackoverflow.com/questions/277521/how-to-identify-the-file-content-as-ascii-or-binary
|
|
DO lv_len TIMES. " I'm sure there is more efficient way ...
|
|
lv_idx = sy-index - 1.
|
|
lv_x = <data>+lv_idx(1).
|
|
|
|
IF NOT ( lv_x BETWEEN 9 AND 13 OR lv_x BETWEEN 32 AND 126 ).
|
|
rv_yes = abap_true.
|
|
EXIT.
|
|
ENDIF.
|
|
ENDDO.
|
|
|
|
ENDMETHOD. " is_binary.
|
|
|
|
METHOD build_menu.
|
|
|
|
DATA: lo_sub TYPE REF TO lcl_html_toolbar,
|
|
lt_types TYPE string_table,
|
|
lt_users TYPE string_table.
|
|
|
|
FIELD-SYMBOLS: <diff> LIKE LINE OF mt_diff_files,
|
|
<i> TYPE string.
|
|
|
|
" Get unique
|
|
LOOP AT mt_diff_files ASSIGNING <diff>.
|
|
APPEND <diff>-type TO lt_types.
|
|
APPEND <diff>-changed_by TO lt_users.
|
|
ENDLOOP.
|
|
|
|
SORT: lt_types, lt_users.
|
|
DELETE ADJACENT DUPLICATES FROM: lt_types, lt_users.
|
|
|
|
CREATE OBJECT ro_menu.
|
|
|
|
IF iv_supress_stage = abap_false.
|
|
ro_menu->add( iv_txt = 'Stage'
|
|
iv_act = |{ lif_defs=>gc_action-go_stage }?{ mv_repo_key }|
|
|
iv_id = 'stage-button'
|
|
iv_opt = lif_defs=>gc_html_opt-strong ).
|
|
ENDIF.
|
|
|
|
IF lines( lt_types ) > 1 OR lines( lt_users ) > 1.
|
|
CREATE OBJECT lo_sub EXPORTING iv_id = 'diff-filter'.
|
|
|
|
" File types
|
|
IF lines( lt_types ) > 1.
|
|
lo_sub->add( iv_txt = 'TYPE' iv_typ = lif_defs=>gc_action_type-separator ).
|
|
LOOP AT lt_types ASSIGNING <i>.
|
|
lo_sub->add( iv_txt = <i>
|
|
iv_typ = lif_defs=>gc_action_type-onclick
|
|
iv_aux = 'type'
|
|
iv_chk = abap_true ).
|
|
ENDLOOP.
|
|
ENDIF.
|
|
|
|
" Changed by
|
|
IF lines( lt_users ) > 1.
|
|
lo_sub->add( iv_txt = 'CHANGED BY' iv_typ = lif_defs=>gc_action_type-separator ).
|
|
LOOP AT lt_users ASSIGNING <i>.
|
|
lo_sub->add( iv_txt = <i>
|
|
iv_typ = lif_defs=>gc_action_type-onclick
|
|
iv_aux = 'changed-by'
|
|
iv_chk = abap_true ).
|
|
ENDLOOP.
|
|
ENDIF.
|
|
|
|
ro_menu->add( iv_txt = 'Filter'
|
|
io_sub = lo_sub ) ##NO_TEXT.
|
|
ENDIF.
|
|
|
|
ro_menu->add( iv_txt = 'Split/Unified view'
|
|
iv_act = c_actions-toggle_unified ) ##NO_TEXT.
|
|
|
|
ENDMETHOD. " build_menu.
|
|
|
|
METHOD lif_gui_page~on_event.
|
|
|
|
CASE iv_action.
|
|
WHEN c_actions-toggle_unified. " Toggle file diplay
|
|
mv_unified = lcl_app=>user( )->toggle_diff_unified( ).
|
|
ev_state = lif_defs=>gc_event_state-re_render.
|
|
ENDCASE.
|
|
|
|
ENDMETHOD. "lif_gui_page~on_event
|
|
|
|
METHOD render_content.
|
|
|
|
DATA ls_diff_file LIKE LINE OF mt_diff_files.
|
|
|
|
CREATE OBJECT ro_html.
|
|
|
|
ro_html->add( |<div id="diff-list" data-repo-key="{ mv_repo_key }">| ).
|
|
ro_html->add( lcl_gui_chunk_lib=>render_js_error_banner( ) ).
|
|
LOOP AT mt_diff_files INTO ls_diff_file.
|
|
lcl_progress=>show( iv_key = 'Diff'
|
|
iv_current = sy-tabix
|
|
iv_total = lines( mt_diff_files )
|
|
iv_text = |Render Diff - { ls_diff_file-filename }| ).
|
|
|
|
ro_html->add( render_diff( ls_diff_file ) ).
|
|
ENDLOOP.
|
|
ro_html->add( '</div>' ).
|
|
|
|
ENDMETHOD. "render_content
|
|
|
|
METHOD render_diff.
|
|
|
|
CREATE OBJECT ro_html.
|
|
|
|
ro_html->add( |<div class="diff" data-type="{ is_diff-type
|
|
}" data-changed-by="{ is_diff-changed_by
|
|
}" data-file="{ is_diff-path && is_diff-filename }">| ). "#EC NOTEXT
|
|
ro_html->add( render_diff_head( is_diff ) ).
|
|
|
|
" Content
|
|
IF is_diff-type <> 'binary'.
|
|
ro_html->add( '<div class="diff_content">' ). "#EC NOTEXT
|
|
ro_html->add( '<table class="diff_tab syntax-hl">' ). "#EC NOTEXT
|
|
ro_html->add( render_table_head( ) ).
|
|
ro_html->add( render_lines( is_diff ) ).
|
|
ro_html->add( '</table>' ). "#EC NOTEXT
|
|
ro_html->add( '</div>' ). "#EC NOTEXT
|
|
ELSE.
|
|
ro_html->add( '<div class="diff_content paddings center grey">' ). "#EC NOTEXT
|
|
ro_html->add( 'The content seems to be binary.' ). "#EC NOTEXT
|
|
ro_html->add( 'Cannot display as diff.' ). "#EC NOTEXT
|
|
ro_html->add( '</div>' ). "#EC NOTEXT
|
|
ENDIF.
|
|
|
|
ro_html->add( '</div>' ). "#EC NOTEXT
|
|
|
|
ENDMETHOD. " render_diff
|
|
|
|
METHOD render_diff_head.
|
|
|
|
DATA: ls_stats TYPE lcl_diff=>ty_count.
|
|
|
|
CREATE OBJECT ro_html.
|
|
|
|
ro_html->add( '<div class="diff_head">' ). "#EC NOTEXT
|
|
|
|
IF is_diff-type <> 'binary'.
|
|
ls_stats = is_diff-o_diff->stats( ).
|
|
IF is_diff-fstate = c_fstate-both. " Merge stats into 'update' if both were changed
|
|
ls_stats-update = ls_stats-update + ls_stats-insert + ls_stats-delete.
|
|
CLEAR: ls_stats-insert, ls_stats-delete.
|
|
ENDIF.
|
|
|
|
ro_html->add( |<span class="diff_banner diff_ins">+ { ls_stats-insert }</span>| ).
|
|
ro_html->add( |<span class="diff_banner diff_del">- { ls_stats-delete }</span>| ).
|
|
ro_html->add( |<span class="diff_banner diff_upd">~ { ls_stats-update }</span>| ).
|
|
ENDIF.
|
|
|
|
ro_html->add( |<span class="diff_name">{ is_diff-filename }</span>| ). "#EC NOTEXT
|
|
ro_html->add( lcl_gui_chunk_lib=>render_item_state(
|
|
iv1 = is_diff-lstate
|
|
iv2 = is_diff-rstate ) ).
|
|
|
|
IF is_diff-fstate = c_fstate-both AND mv_unified = abap_true.
|
|
ro_html->add( '<span class="attention pad-sides">Attention: Unified mode'
|
|
&& ' highlighting for MM assumes local file is newer ! </span>' ). "#EC NOTEXT
|
|
ENDIF.
|
|
|
|
ro_html->add( |<span class="diff_changed_by">last change by: <span class="user">{
|
|
is_diff-changed_by }</span></span>| ).
|
|
|
|
ro_html->add( '</div>' ). "#EC NOTEXT
|
|
|
|
ENDMETHOD.
|
|
|
|
METHOD render_table_head.
|
|
|
|
CREATE OBJECT ro_html.
|
|
|
|
IF mv_unified = abap_true.
|
|
ro_html->add( '<thead class="header">' ). "#EC NOTEXT
|
|
ro_html->add( '<tr>' ). "#EC NOTEXT
|
|
ro_html->add( '<th class="num">old</th>' ). "#EC NOTEXT
|
|
ro_html->add( '<th class="num">new</th>' ). "#EC NOTEXT
|
|
ro_html->add( '<th>code</th>' ). "#EC NOTEXT
|
|
ro_html->add( '</tr>' ). "#EC NOTEXT
|
|
ro_html->add( '</thead>' ). "#EC NOTEXT
|
|
ELSE.
|
|
ro_html->add( '<thead class="header">' ). "#EC NOTEXT
|
|
ro_html->add( '<tr>' ). "#EC NOTEXT
|
|
ro_html->add( '<th class="num"></th>' ). "#EC NOTEXT
|
|
ro_html->add( '<th>LOCAL</th>' ). "#EC NOTEXT
|
|
ro_html->add( '<th class="num"></th>' ). "#EC NOTEXT
|
|
ro_html->add( '<th>REMOTE</th>' ). "#EC NOTEXT
|
|
ro_html->add( '</tr>' ). "#EC NOTEXT
|
|
ro_html->add( '</thead>' ). "#EC NOTEXT
|
|
ENDIF.
|
|
|
|
ENDMETHOD. " render_table_head.
|
|
|
|
METHOD render_beacon.
|
|
|
|
DATA: lv_beacon TYPE string.
|
|
|
|
CREATE OBJECT ro_html.
|
|
|
|
IF is_diff_line-beacon > 0.
|
|
READ TABLE is_diff-o_diff->mt_beacons INTO lv_beacon INDEX is_diff_line-beacon.
|
|
ELSE.
|
|
lv_beacon = '---'.
|
|
ENDIF.
|
|
|
|
|
|
ro_html->add( '<thead class="nav_line">' ).
|
|
ro_html->add( '<tr>' ).
|
|
|
|
IF mv_unified = abap_true.
|
|
ro_html->add( '<th class="num"></th>' ).
|
|
ro_html->add( '<th class="num"></th>' ).
|
|
ro_html->add( |<th>@@ { is_diff_line-new_num } @@ { lv_beacon }</th>| ).
|
|
ELSE.
|
|
ro_html->add( '<th class="num"></th>' ).
|
|
ro_html->add( |<th colspan="3">@@ { is_diff_line-new_num } @@ { lv_beacon }</th>| ).
|
|
ENDIF.
|
|
|
|
ro_html->add( '</tr>' ).
|
|
ro_html->add( '</thead>' ).
|
|
|
|
ENDMETHOD. " render_beacon.
|
|
|
|
METHOD render_lines.
|
|
|
|
DATA: lo_highlighter TYPE REF TO lcl_syntax_highlighter,
|
|
lt_diffs TYPE lcl_diff=>ty_diffs_tt,
|
|
lv_insert_nav TYPE abap_bool.
|
|
|
|
FIELD-SYMBOLS <ls_diff> LIKE LINE OF lt_diffs.
|
|
|
|
lo_highlighter = lcl_syntax_highlighter=>create( is_diff-filename ).
|
|
CREATE OBJECT ro_html.
|
|
|
|
lt_diffs = is_diff-o_diff->get( ).
|
|
|
|
LOOP AT lt_diffs ASSIGNING <ls_diff>.
|
|
IF <ls_diff>-short = abap_false.
|
|
lv_insert_nav = abap_true.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
IF lv_insert_nav = abap_true. " Insert separator line with navigation
|
|
ro_html->add( render_beacon( is_diff_line = <ls_diff> is_diff = is_diff ) ).
|
|
lv_insert_nav = abap_false.
|
|
ENDIF.
|
|
|
|
IF lo_highlighter IS BOUND.
|
|
<ls_diff>-new = lo_highlighter->process_line( <ls_diff>-new ).
|
|
<ls_diff>-old = lo_highlighter->process_line( <ls_diff>-old ).
|
|
ELSE.
|
|
<ls_diff>-new = escape( val = <ls_diff>-new format = cl_abap_format=>e_html_attr ).
|
|
<ls_diff>-old = escape( val = <ls_diff>-old format = cl_abap_format=>e_html_attr ).
|
|
ENDIF.
|
|
|
|
CONDENSE <ls_diff>-new_num. "get rid of leading spaces
|
|
CONDENSE <ls_diff>-old_num.
|
|
|
|
IF mv_unified = abap_true.
|
|
ro_html->add( render_line_unified( is_diff_line = <ls_diff> ) ).
|
|
ELSE.
|
|
ro_html->add( render_line_split( is_diff_line = <ls_diff>
|
|
iv_fstate = is_diff-fstate ) ).
|
|
ENDIF.
|
|
|
|
ENDLOOP.
|
|
|
|
IF mv_unified = abap_true.
|
|
ro_html->add( render_line_unified( ) ). " Release delayed lines
|
|
ENDIF.
|
|
|
|
ENDMETHOD. "render_lines
|
|
|
|
METHOD render_line_split.
|
|
|
|
DATA: lv_new TYPE string,
|
|
lv_old TYPE string,
|
|
lv_mark TYPE string,
|
|
lv_bg TYPE string.
|
|
|
|
CREATE OBJECT ro_html.
|
|
|
|
" New line
|
|
lv_mark = ` `.
|
|
IF iv_fstate = c_fstate-both OR is_diff_line-result = lcl_diff=>c_diff-update.
|
|
lv_bg = ' diff_upd'.
|
|
lv_mark = `~`.
|
|
ELSEIF is_diff_line-result = lcl_diff=>c_diff-insert.
|
|
lv_bg = ' diff_ins'.
|
|
lv_mark = `+`.
|
|
ENDIF.
|
|
lv_new = |<td class="num" line-num="{ is_diff_line-new_num }"></td>|
|
|
&& |<td class="code{ lv_bg }">{ lv_mark }{ is_diff_line-new }</td>|.
|
|
|
|
" Old line
|
|
CLEAR lv_bg.
|
|
lv_mark = ` `.
|
|
IF iv_fstate = c_fstate-both OR is_diff_line-result = lcl_diff=>c_diff-update.
|
|
lv_bg = ' diff_upd'.
|
|
lv_mark = `~`.
|
|
ELSEIF is_diff_line-result = lcl_diff=>c_diff-delete.
|
|
lv_bg = ' diff_del'.
|
|
lv_mark = `-`.
|
|
ENDIF.
|
|
lv_old = |<td class="num" line-num="{ is_diff_line-old_num }"></td>|
|
|
&& |<td class="code{ lv_bg }">{ lv_mark }{ is_diff_line-old }</td>|.
|
|
|
|
" render line, inverse sides if remote is newer
|
|
ro_html->add( '<tr>' ). "#EC NOTEXT
|
|
IF iv_fstate = c_fstate-remote. " Remote file leading changes
|
|
ro_html->add( lv_old ). " local
|
|
ro_html->add( lv_new ). " remote
|
|
ELSE. " Local leading changes or both were modified
|
|
ro_html->add( lv_new ). " local
|
|
ro_html->add( lv_old ). " remote
|
|
ENDIF.
|
|
ro_html->add( '</tr>' ). "#EC NOTEXT
|
|
|
|
ENDMETHOD. "render_line_split
|
|
|
|
METHOD render_line_unified.
|
|
|
|
FIELD-SYMBOLS <diff_line> LIKE LINE OF mt_delayed_lines.
|
|
|
|
CREATE OBJECT ro_html.
|
|
|
|
" Release delayed subsequent update lines
|
|
IF is_diff_line-result <> lcl_diff=>c_diff-update.
|
|
LOOP AT mt_delayed_lines ASSIGNING <diff_line>.
|
|
ro_html->add( '<tr>' ). "#EC NOTEXT
|
|
ro_html->add( |<td class="num" line-num="{ <diff_line>-old_num }"></td>|
|
|
&& |<td class="num" line-num=""></td>|
|
|
&& |<td class="code diff_del">-{ <diff_line>-old }</td>| ).
|
|
ro_html->add( '</tr>' ). "#EC NOTEXT
|
|
ENDLOOP.
|
|
LOOP AT mt_delayed_lines ASSIGNING <diff_line>.
|
|
ro_html->add( '<tr>' ). "#EC NOTEXT
|
|
ro_html->add( |<td class="num" line-num=""></td>|
|
|
&& |<td class="num" line-num="{ <diff_line>-new_num }"></td>|
|
|
&& |<td class="code diff_ins">+{ <diff_line>-new }</td>| ).
|
|
ro_html->add( '</tr>' ). "#EC NOTEXT
|
|
ENDLOOP.
|
|
CLEAR mt_delayed_lines.
|
|
ENDIF.
|
|
|
|
ro_html->add( '<tr>' ). "#EC NOTEXT
|
|
CASE is_diff_line-result.
|
|
WHEN lcl_diff=>c_diff-update.
|
|
APPEND is_diff_line TO mt_delayed_lines. " Delay output of subsequent updates
|
|
WHEN lcl_diff=>c_diff-insert.
|
|
ro_html->add( |<td class="num" line-num=""></td>|
|
|
&& |<td class="num" line-num="{ is_diff_line-new_num }"></td>|
|
|
&& |<td class="code diff_ins">+{ is_diff_line-new }</td>| ).
|
|
WHEN lcl_diff=>c_diff-delete.
|
|
ro_html->add( |<td class="num" line-num="{ is_diff_line-old_num }"></td>|
|
|
&& |<td class="num" line-num=""></td>|
|
|
&& |<td class="code diff_del">-{ is_diff_line-old }</td>| ).
|
|
WHEN OTHERS. "none
|
|
ro_html->add( |<td class="num" line-num="{ is_diff_line-old_num }"></td>|
|
|
&& |<td class="num" line-num="{ is_diff_line-new_num }"></td>|
|
|
&& |<td class="code"> { is_diff_line-old }</td>| ).
|
|
ENDCASE.
|
|
ro_html->add( '</tr>' ). "#EC NOTEXT
|
|
|
|
ENDMETHOD. "render_line_unified
|
|
|
|
METHOD scripts.
|
|
|
|
CREATE OBJECT ro_html.
|
|
|
|
ro_html->add( 'var gHelper = new DiffHelper({' ).
|
|
ro_html->add( | seed: "{ mv_seed }",| ).
|
|
ro_html->add( | stageAction: "{ lif_defs=>gc_action-go_stage }",| ).
|
|
ro_html->add( ' ids: {' ).
|
|
ro_html->add( ' diffList: "diff-list",' ).
|
|
ro_html->add( ' filterMenu: "diff-filter",' ).
|
|
ro_html->add( ' stageButton: "stage-button"' ).
|
|
ro_html->add( ' }' ).
|
|
ro_html->add( '});' ).
|
|
|
|
ENDMETHOD. "scripts
|
|
ENDCLASS. "lcl_gui_page_diff
|